[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference noted::hackers_v1

Title:-={ H A C K E R S }=-
Notice:Write locked - see NOTED::HACKERS
Moderator:DIEHRD::MORRIS
Created:Thu Feb 20 1986
Last Modified:Mon Aug 03 1992
Last Successful Update:Fri Jun 06 1997
Number of topics:680
Total number of notes:5456

447.0. "IOSTAT=43 Fortran error." by PHENIX::SMITH (William P.N. (WOOKIE::) Smith) Wed Apr 15 1987 17:24

    Anyone have any idea why Fortran (or maybe RMS) is blowing up on
    me?  I'm opening a file, reading out the first 2 lines, which are
    comments, and asking if this is the desired file.  If it isn't,
    I can open another file just fine (after closing the first one),
    and repeat the procedure.  If it is the right file, I read out the
    rest of the data [plot it using RGL but that's not important, if
    I cut out the RGL it still doesn't work] and ask for another file.
     It's this second file that will not open.  I get an IOSTAT=43 and
    a branch to my error routine.  43 is supposedly FILNAMSPE, "File
    name specification error" (A file-name specification given to OPEN
    [...] was not acceptable to RMS.  I print out the file name, and
    it looks OK, but the file won't open.  I've tried different unit
    numbers, rewinding the file before closing it, and a bunch of oher
    things, but I still get the same error.  Does this sound like something
    soneone has seen before?  Mail me if you want to see the code at
    WOOKIE::SMITH.  Many thanks in advance!
    
    Willie
    
T.RTitleUserPersonal
Name
DateLines
447.1BMT::KOZAKIEWICZThu Apr 16 1987 01:0739
    I am not sure if this applies to you, since I cannot tell from your
    note, but an absolute sure fire way to get the error you describe
    is if the character after the last valid character in the filename
    string is not = 0 (NUL) or 32 (SPACE).  This can easily happen if
    you are reading the file specification into a BYTE array, or you
    are using a CHARACTER variable for other things and are not careful
    to blank it before you use it for a filename. Your code should look
    like this:
    
    	BYTE		FNAME(40)
    		.
    		.
    	READ (UNIT, '(Q,40A1)') LEN, FNAME	!Get filename and length
    	FNAME(LEN+1) = 0
    
    	OPEN (UNIT=ZZ, NAME=FNAME, ....)
    
    	If you are using a CHARACTER variable, the following will get
    you into trouble:
    
    	CHARACTER*80	BUF
    		.
    		.
    	READ (UNIT, '(A80)') BUF	!Read some junk into BUF (I
    					! assume it has control characters
    					! in it)
    
    	 other processing occurs
    
        READ (UNIT, '(A15)') BUF(1:15)	!Assume fixed length filename?
    	OPEN (UNIT, NAME=BUF...)	!BUF(16:16) may contain junk
    					! from before...
    
    	The proper way to do this is:
    
    	BUF = ' '
    	READ (UNIT, '(A80)') BUF
    	OPEN (UNIT, NAME=BUF...)
    
447.2I hacked around it...PHENIX::SMITHWilliam P.N. (WOOKIE::) SmithThu Apr 16 1987 16:5918
    Well, I can read the first couple of lines out of one file, read
    the first couple of lines out of a different file, [and on and on
    all day if I like], but as soon as I decide I like a file and read
    all the data out of it, I can't even open the same file again! 
    I have been clearing the string to spaces before requesting another
    file name, but that doesn't seem to make much difference.
    	I did, however, find a work around. If I clear out the comment
    lines that I read from the file before I close it and then go back
    and open another file, it works just fine.  [Well, this is the hackers
    notes files... :} ]  Don't ask me why RMS cares what I do with other
    variables, but whatever makes it happy!  I've commented it so that
    no-one will try to 'enhance' the code by removing that extra little
    addition....
    
    FORTRAN: GOD is real, unless declared integer....
    
    Willie
    
447.3BISTRO::HEINIf We don't Have it,You don't Need it!Tue Apr 21 1987 07:2420
    William,
    
    	I expect that the reply in .1 really explains the problem.
    	Somehow there is garbage in the file name string. As you 
    	found the clearing this 'comment line' appears to fix the
    	problem the conclusion must be that there is somehow an
    	overlap of the variable and the one used for the filename.
    	
    	To verify I would change to OPEN statement to use a USEROPEN
    	of the simplest sort and set a breakpoint there. When the
    	useropen is called after displaying an entire file and trying
    	to open a second file, then look in the FAB filename fields:
    	@4(AP)   --> Fab 
    	Fab + 2C --> File name address
    	Fab + 34 --> File name size (byte)
    	Fab + 30 --> Default name addres
    	Fab + 35 --> Default name size (byte)
    
    	Have fun,
    		Hein.
447.4reminiscing ...ANGORA::ZARLENGASpock, where's my mint julep?Thu Apr 23 1987 22:5814
    	1 more idea - check the filename CLOSELY.  I found an obscure
    error in a program on a VT220 while my VT125 was being serviced.
    The filename string's 1st character had bit 7 set ... it was a
    "multinational" character ... my VT125 displayed it the same
    whether bit 7 was 0 or 1 ... the VT220 displayed a strange looking
    creature.
    	I though I had all bases covered ... I was writing the filename
    to the terminal ... but as characters, when I went to write the
    individual cells as octal numbers the error showed up on my VT125
    too.  That was the toughest one I've ever found (and it was my
    code too!)
    	It might be similar to your problem.
    
    -mike
447.5got it!PHENIX::SMITHWilliam P.N. (WOOKIE::) SmithThu Apr 23 1987 23:3015
    Thanks guys, I found it, I had set the filename to all spaces before
    I got the new name from the terminal, but I had not stuck in a zero
    byte for a terminator.  Works just fine now.
    
    		READ	(*,1000) NUMCHAR, INFILE
    1000	FORMAT	(Q,50A1)
    
    		IF	(NUMCHAR.LT.50) INFILE(NUMCHAR+1) = 0
        
    I also made the file name up to 50 chars long, so I can use the
    new VMS sytle of very_long_file_names_so_they_wont_conflict.and_
    I_dont_accidently_delete_them.
    
    Willie
    
447.6Fortran speed?COBRA::SMITHWilliam P.N. (WOOKIE::) SmithMon Apr 27 1987 17:0526
    OK, since it's part of the same project, I'll continue on instead
    of starting a new topic.  I've written a quick and dirty Fortran
    program to read lines out of a text file and proccess tham as follows:
    
    	If the line you read is the same as the last line, throw it
    away and go back for another one.
    
    	If the line is different and there is a " in it (it contains
    text) write it to the output file.
    
    	If the line is different and does not contain a " (no text),
    squeeze all spaces out of it and write the result to the output
    file.
    
    This has the effect of making the file up to 73 percent smaller,
    and works really well except for one minor detail.  It takes just
    short of forever.  On a microvax I it took around 14 minutes of
    real time, almost 14 minutes of CPU time, and under 100 page faults
    to squish a 507 block file down to 160 blocks.  I figgered there
    was something wrong, so I tried it on a machovax and it still took
    7 minutes, mostly CPU time.  Is this reasonable?  The source is
    only 4 blocks with comments....
    
    Willie
    
    14 minutes of CPU time
447.7ALBANY::KOZAKIEWICZYou can call me Al...Mon Apr 27 1987 19:3218
I see two possibilities.  The first (and least likely) is that your files
are assumed to be shared, and thus RMS is performing 1 disk I/O (with the
attendant record blocking/unblocking) per record operation.  This can be
solved by either ensuring that there is no implied file sharing going on,
or by using the deferred write option (I have sample FORTRAN programs which
enable this option, if you need to see them),i.e. set the FAB$V_DFW bit.

The other (most likely) possibility is the amount of time consumed comparing
the character strings.  Are you using CHARACTER variables or BYTE arrays?
If you are using BYTE arrays and comparing each character in a DO loop, 
processing will be slow.  Direct comparisons via CHARACTER variables *MAY*
be faster (I do not know how FORTRAN handles them - get a machine code listing
and see...).  One algorithm change you might make would be to
compare the length of the strings first (assuming these are variable length
records...).  Only compare the strings if the length is the same (If the length
is different, so are the strings).  Also, combine several of the operations 
into one loop.  That way you could compare and check for '"' at the same time.

447.8I'll see what happens.COBRA::SMITHWilliam P.N. (WOOKIE::) SmithMon Apr 27 1987 20:398
    I'm using byte arrays, I'll give CHARACTER arrays a shot.  I'm already
    comparing string length, but I'm not doing the _look_for_"_while_
    _squishing_string_, which should speed things up a bit (and save
    me another few bytes), I'll let you know what happens.  Never heard
    of deferred write, I'd appreciate your samples...  Thanks,
    
    Willie
    
447.9CAFEIN::PFAUNow where did I leave my marbles?Mon Apr 27 1987 21:026
    I believe (my FORTRAN is a bit rusty) that VAX-FORTRAN has an INDEX
    function which will return the offset into a string at which a
    particular character or substring appears.  You might want to use
    this to locate the quote character.
    
    tom_p
447.10Check BAS$EDIT functionality.BISTRO::HEINIf We don't Have it,You don't Need it!Tue Apr 28 1987 08:001
    
447.11use PCA firstDYO780::DYSERTBarry DysertTue Apr 28 1987 12:558
    It's true that there is an INDEX function that allows you to find
    a character within a given string.  What I would suggest you do
    first, though, is load your program with PCA.  PCA is a wonderful
    product that allows you to find where your program is spending most
    of its time.  After all, you may be grinding to optimize what you
    think is the "bad" code only to realize a few percent performance
    improvement.  PCA will show you for sure what part of your program
    is responsible for the excessive CPU time.
447.12Now if it had been Z-80 assembly...COBRA::SMITHWilliam P.N. (WOOKIE::) SmithTue Apr 28 1987 17:069
    Well, I asked a Real Programmer for hints and he ended up rewriting
    the code and now it runs in 2 minutes...  The most significant speed
    increases were opening the files (...,blocksize=20480,...), using
    character arrays instead of bytes, and combining short output lines
    into longer ones.  The logic is pretty much the same as my original
    program, but the coding is _very_ different....
    
    Willie
    
447.13ALBANY::KOZAKIEWICZYou can call me Al...Tue Apr 28 1987 17:1940
I checked out what kind of code the FORTRAN compiler generates for the
following two character compare sequences:

	CHARACTER*99	A,B
	IF (A .NE. B) GOTO 999

		and

	BYTE		A(99),B(99)
	DO I = 1, 99
	 IF (A(I) .NE. B(I)) GOTO 999
	ENDDO

In the first example the compiler yields something like:

	MOVAL	A, reg a	;Move the addresses of the strings to
	MOVAL	B, reg b	;  registers

	CMPC3	99, A, B	;Compare...
	BNE	#.999		;NE

By the way, the CMPC instruction is not defined for the uVAX architecture.
The second example gets you something like this:

	MOVAL	A, reg a
	MOVAL	B, reg b
	MOVL	#-99, R0	;Loop counter
10$:	CMPB	(Ra)+, (Rb)+	;Compare this byte
	BNE	#.999		; NE
	AOBLEQ	R0, 10$		;Loop

As you can see, the second example replaces one instruction (CMPC3) with
three (CMPB, BNE, AOBLEQ) which must be executed once for each equal character.
Of course, the character compare instruction will vary in execution time
depending upon the length of the longest string, by I will lay money that
it executes faster than the DO loop.

And by the way, the performance coverage analyzer (PCA) might help, but it
is really going after a fly with a cannon.  The use of such tools is not
a panacea for poor design.