home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
fortran
/
library
/
library
/
libry5.doc
< prev
next >
Wrap
Text File
|
1989-11-10
|
14KB
|
349 lines
.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