home *** CD-ROM | disk | FTP | other *** search
- .pa
- FILE HANDLING ROUTINES
-
- FORTRAN is rather ill suited to file I/O. It is painfully slow compared to the
- actual speed of memory-to-disk transfers. I have developed this set of
- procedures to allow fast file access from FORTRAN. On the HP-1000F and HP-A900
- these routines provide a speed increase factor of about 20. On the PC the
- speed increase is more like 30 for FORTRAN/V3.31 and 3 for FORTRAN/V4 It
- may seem a little circuitous at first to always read and write character
- strings instead of numbers and to call some subroutine rather than simply
- using "WRITE" and "READ" statements; but once you get used to it, it isn't so
- bad; and the speed is worth a little extra trouble.
-
- As far as numbers go, you can use DEC0DE to decode them from the character
- strings and "WRITE(CBUF,1000)" to encode them.
-
- I have allowed for only four sequential access files and one random access
- file. It's not obvious in FORTRAN, but you can't just open an unlimited number
- of files. If you need more you can always access the binary file procedures
- directly (e.g. BOPEN). You can open as many files with BOPEN as there are
- FILES=?? allocated in your CONFIG.SYS file.
-
- A word of warning about reading files created by word processors and the
- like... these procedures ignore control characters on either read or write and
- chop-off trailing blanks on write. Also, files must end with the standard EOF
- character (zero record length for HPs or ctrl-Z for PCs). This is done for you
- automatically by the end-file functions and most editors (at least WED and
- IBM's Professional Editor). If you create a file using FORTRAN on the PC
- WITHOUT these procedures and then attempt to read it WITH these procedures you
- will get trash at the end unless you put a CHAR(26) on the last line (A1
- format) before you close the file.
-
- Another word of caution. Do not mix Microsoft's FORTRAN file I/O and these
- routines. The only thing that I know it messes up is the directory search
- functions (DIRSET and DIRNXT); however, one can't be sure. You see there is
- this special area at the top of your program called a program segment prefix
- (PSP) which contains an important data transfer area (DTA). FORTRAN moves this
- area off into the twilight zone; whereas, these routines leave it alone. They
- just aren't compatible.
- .pa
- QUICK LIST OF FILE HANDLING SUBROUTINES
-
- BCLOSE... binary file close
- BCREAT... binary file open (status='unknown')
- BMFP..... move binary file pointer
- BOPEN.... binary file open (status='old')
- BPURGE... binary file purge/delete
- BREAD.... binary file read
- BWRITE... binary file write
- DIRNXT... get next entry in directory
- DIRSET... set up for directory search
- ECLOS.... close random access file
- EOPEN.... open random access file
- EREAD.... read random access file
- EWRIT.... write random access file
- FBKSP1... backspace first sequential access file
- FCLOS1... close first sequential access file
- FENDF1... end (affix EOF marker to) first sequential access file
- FEXIST... logical check for file exist
- FOPEN1... open first sequential access file
- FREAD1... read first sequential access file
- FRWND1... rewind first sequential access file
- FWRIT1... write first sequential access file
- GETPSP... get the program segment prefix (PC only - on HP use GETST)
- RRPAR.... get file name from runtime string
-
- also available are:
-
- FWRIT2, FBKSP2, FCLOS2, FENDF2, FOPEN2, FREAD2, and FRWND2.
- FWRIT3, FBKSP3, FCLOS3, FENDF3, FOPEN3, FREAD3, and FRWND3.
- FWRIT4, FBKSP4, FCLOS4, FENDF4, FOPEN4, FREAD4, and FRWND4.
-
- A note about binary file routines:
-
- These are not available on the HP. They are absolute file I/O. There
- is no consideration of record separators, line-feeds, carriage
- return, or end of file markers. This applies to reading and writing.
- .pa
- NAME: BCLOSE
- PURPOSE: close a binary file
- TYPE: subroutine (far external)
- SYNTAX: CALL BCLOSE(IHAND)
- INPUT: IHAND (INTEGER*2) file handle (see BOPEN)
- OUTPUT: none
-
-
- NAME: BCREAT
- PURPOSE: open a binary file and create if not already exist
- TYPE: subroutine (far external)
- SYNTAX: CALL BCREAT(NAME,ICODE,IHAND,IERR)
- INPUT: NAME (CHARACTER*(*)) ASCIIZ string (the last character MUST be a
- CHAR(0)! or else disaster may result)
- ICODE (INTEGER*2) open code (see BOPEN)
- OUTPUT: IHAND (INTEGER*2) file handle (see BOPEN)
- IERR (INTEGER*2) error indicator (see BOPEN)
-
-
- NAME: BMFP
- PURPOSE: move binary file pointer
- TYPE: subroutine (far external)
- SYNTAX: CALL BMFP(IHAND,NBYTES,IERR)
- INPUT: IHAND (INTEGER*2) file handle (see BOPEN)
- NBYTES (INTEGER*4 note unsigned long integer!) number of bytes from
- the beginning of the file where you want the pointer to be
- positioned (e.g. NBYTES=INT4(0) is a rewind)
- OUTPUT: IERR (INTEGER*2) error indicator (IERR=1 indicated invalid handle)
-
-
- NAME: BOPEN
- PURPOSE: open an existing binary file
- TYPE: subroutine (far external)
- SYNTAX: CALL BOPEN(NAME,ICODE,IHAND,IERR)
- INPUT: NAME (CHARACTER*(*)) ASCIIZ string (the last character MUST be a
- CHAR(0)! or else disaster may result)
- ICODE (INTEGER*2) open code (see chart below)
- bit 7 6 5 4 3 2 1 0
- . . . . . . . 1 read only
- . . . . . . 1 . hidden
- . . . . . 1 . . system
- . . . . 1 . . . volume label
- . . . 1 . . . . subdirectory
- . . 1 . . . . . archive
- . 1 . . . . . . unused
- 1 . . . . . . . unused
- OUTPUT: IHAND (INTEGER*2) file handle (you must keep track of this and use
- it every time you refer to the file)
- IERR (INTEGER*2) error indicator
- IERR= 2 file not found or invalid file name
- IERR= 3 path not found or invalid path name
- IERR= 4 no handles available (too many files already open)
- IERR= 5 access denied (protected file)
- IERR=12 invalid access code
-
-
- NAME: BPURGE
- PURPOSE: purge/delete an existing file
- TYPE: subroutine (far external)
- SYNTAX: CALL BPURGE(NAME)
- INPUT: NAME (CHARACTER*(*)) ASCIIZ string (the last character MUST be a
- CHAR(0)! or else disaster may result)
- OUTPUT: none
-
-
- NAME: BREAD
- PURPOSE: read from a binary file (what's in there is what you get-literally!)
- TYPE: subroutine (far external)
- SYNTAX: CALL BREAD(IHAND,LREC,CBUF,LBUF,IERR)
- INPUT: IHAND (INTEGER*2) file handle (see BOPEN)
- LREC (INTEGER*2) size of buffer to be read in bytes (unsigned
- integer - can go up to 65535)
- OUTPUT: CBUF (CHARACTER*(*)) buffer
- LBUF (INTEGER*2) actual number of bytes read (you must check for
- end of file, LBUF can be zero)
- IERR (INTEGER*2) error indicator
- IERR=5 access denied (protected file)
- IERR=6 invalid handle
-
-
- NAME: BWRITE
- PURPOSE: write to a binary file (what you put in there is what will be in
- there, literally!)
- TYPE: subroutine (far external)
- SYNTAX: CALL BWRITE(IHAND,LREC,CBUF,IERR)
- INPUT: IHAND (INTEGER*2) file handle (see BOPEN)
- LREC (INTEGER*2) size of buffer to be written in bytes (unsigned
- integer - can go up to 65535)
- CBUF (CHARACTER*(*)) buffer
- OUTPUT: IERR (INTEGER*2) error indicator
- IERR=5 access denied (protected file)
- IERR=6 invalid handle
- IERR=7 write error or insufficient space
-
-
- NAME: DIRNXT
- PURPOSE: get next entry in directory (see DIRSET)
- TYPE: subroutine (far external)
- SYNTAX: CALL DIRNXT(NAME)
- INPUT: none
- OUTPUT: NAME (CHARACTER*12) next matching name (blank indicates no more
- matches)
-
-
- NAME: DIRSET
- PURPOSE: set up for directory search
- TYPE: subroutine (far external)
- SYNTAX: CALL DIRNXT(NAME)
- INPUT: NAME (CHARACTER*12) file mask (e.g. '*.*') DO NOT use a constant
- character string as it will be written over on return.
- OUTPUT: NAME (CHARACTER*12) first matching name (blank indicates no matches)
- NOTE: You must call this before DIRNXT. See example program at the end
- of this section.
-
-
- NAME: ECLOS
- PURPOSE: close random access file
- TYPE: subroutine (far external)
- SYNTAX: CALL ECLOS
- INPUT: none
- OUTPUT: none
-
-
- NAME: EOPEN
- PURPOSE: open random access file
- TYPE: subroutine (far external)
- SYNTAX: CALL EOPEN(NAME,NEW,LREC,IERR)
- INPUT: NAME (CHARACTER*? up to 64 including drive and path)
- NEW (INTEGER*2) NEW<0 means 'old', NEW=0 means 'unknown'
- NEW>0 means 'new' (note that Microsoft hasn't yet learned what
- 'new', 'old', and 'unknown' mean. 'New' means make one and if
- it already exists return an error. 'Old' means open it and if
- it doesn't already exist return an error. 'Unknown' means open
- it and create it if necessary.)
- LREC (INTEGER*2) record length in bytes
- OUTPUT: IERR (INTEGER*2) error indicator (IER=0 is normal)
-
-
- NAME: EREAD
- PURPOSE: read random access file
- TYPE: subroutine (far external)
- SYNTAX: CALL EREAD(CBUF,NREC,IERR)
- INPUT: NREC (INTEGER*2) desired record number
- OUTPUT: CBUF (CHARACTER*LREC see EOPEN) buffer
- IERR (INTEGER*2) error indicator (IER=0 is normal)
-
-
- NAME: EWRIT
- PURPOSE: write random access file
- TYPE: subroutine (far external)
- SYNTAX: CALL EWRIT(CBUF,NREC,IERR)
- INPUT: CBUF (CHARACTER*LREC see EOPEN) buffer
- NREC (INTEGER*2) desired record number
- OUTPUT: IERR (INTEGER*2) error indicator (IER=0 is normal)
-
-
- NAME: FBKSP1
- PURPOSE: backspace first sequential access file
- TYPE: subroutine (far external)
- SYNTAX: CALL FBKSP1(NREC)
- INPUT: NREC (INTEGER*2) number of records to backspace (if NREC is
- larger than the number of records read so far this will be
- the same as a rewind)
- OUTPUT: none
-
-
- NAME: FCLOS1
- PURPOSE: close first sequential access file
- TYPE: subroutine (far external)
- SYNTAX: CALL FCLOS1
- INPUT: none
- OUTPUT: none
-
-
- NAME: FENDF1
- PURPOSE: end (affix EOF marker to) first sequential access file
- TYPE: subroutine (far external)
- SYNTAX: CALL FENFD1
- INPUT: none
- OUTPUT: none
-
-
- NAME: FEXIST
- PURPOSE: logical test for file exist
- TYPE: LOGICAL*2 function (far external)
- SYNTAX: IF(.NOT.FEXIST('THISFILE.EXT')) GO TO 100
- INPUT: CHARACTER*(*) file name
- OUTPUT: none
-
-
- NAME: FOPEN1
- PURPOSE: open first sequential access file
- TYPE: subroutine (far external)
- SYNTAX: CALL FOPEN1(NAME,NEW,IERR)
- INPUT: NAME (CHARACTER*? up to 64 including drive and path)
- NEW (INTEGER*2) NEW<0 means 'old', NEW=0 means 'unknown'
- NEW>0 means 'new' (note that Microsoft hasn't yet learned what
- 'new', 'old', and 'unknown' mean. 'New' means make one and if
- it already exists return an error. 'Old' means open it and if
- it doesn't already exist return an error. 'Unknown' means open
- it and create it if necessary.)
- OUTPUT: IERR (INTEGER*2) error indicator (IER=0 is normal)
- NOTE: See example program at the end of this section.
-
-
- NAME: FREAD1
- PURPOSE: read first sequential access file
- TYPE: subroutine (far external)
- SYNTAX: CALL FREAD1(CBUF,NBUF,LREC,IERR,IEND)
- INPUT: NBUF (INTEGER*2) number of bytes in CBUF
- OUTPUT: CBUF (CHARACTER*?) buffer
- LREC (INTEGER*2) nominal record length
- IERR (INTEGER*2) error indicator (IERR=0 is normal)
- IEND (INTEGER*2) EOF indicator (IEND=0 is normal)
-
-
- NAME: FWRIT1
- PURPOSE: write first sequential access file
- TYPE: subroutine (far external)
- SYNTAX: CALL FWRIT1(CBUF,NBUF,IERR)
- INPUT: CBUF (CHARACTER*?) buffer
- NBUF (INTEGER*2) number of bytes in CBUF
- OUTPUT: IERR (INTEGER*2) error indicator (IERR=0 is normal)
-
-
- NAME: FRWND1
- PURPOSE: rewind first sequential access file
- TYPE: subroutine (far external)
- SYNTAX: CALL FRWND1
- INPUT: none
- OUTPUT: none
-
-
- NAME: GETPSP
- PURPOSE: get the program segment prefix (PC only - on HP use GETST)
- TYPE: subroutine (far external)
- SYNTAX: CALL GETPSP(PSP)
- INPUT: none
- OUTPUT: PSP (CHARACTER*1 PSP(128))
- NOTE: This seems like a logical thing to want; but to actually find
- the PSP after DOS gets through with it on the PC is no easy
- task when working from inside an EXE file.
-
-
- NAME: RRPAR
- PURPOSE: get file name from runtime string
- TYPE: subroutine (far external)
- SYNTAX: CALL RRPAR(N,NAME)
- INPUT: N (INTEGER*2) number of entry see example below
- OUTPUT: NAME (CHARACTER*12)
- NOTE: the purpose of this is to fetch and parse the string that you
- type in after the name of your program as below
-
- MYPROG this.dat that.for other.bin wednesday
-
- fetch the names with the following
-
- CHARACTER NAME1*12,NAME2*12,NAME3*12,COMMENT*12
- CALL RRPAR(1,NAME1)
- CALL RRPAR(2,NAME2)
- CALL RRPAR(3,NAME3)
- CALL RRPAR(4,COMMENT)
-
- you will get the following
-
- NAME1='this.dat'
- NAME2='that.for'
- NAME3='other.bin'
- COMMENT='wednesday'
- .ad LIBRY5A.DOC