home *** CD-ROM | disk | FTP | other *** search
-
- **************************************************************
- * Fast Fortran 77 Callable Binary File Handling Routines *
- * *
- * for RISC OS and RISC iX *
- **************************************************************
- * Version 1.0 copyright Interactive Software Services 1992 *
- **************************************************************
-
- 1. Introduction
- ------------
-
- This file documents a set of Fortran callable binary file handling routines
- for users of Acorn's RISC OS and RISC iX operating systems on ARM-based
- computers. The routines are significantly faster than conventional Fortran
- i/o (roughly 15 times faster under RISC OS and about 4 times faster under
- Unix). The RISC iX version is also compatible with f77 on Sun workstations.
-
- The file handling subroutines described here are based on code written
- originally as internal routines for INTERACTER, a portable Fortran 77
- user-interface and graphics library from Interactive Software Services Ltd.,
- which runs on RISC OS, Unix, DOS, VMS and PRIMOS. These binary file handling
- routines are being placed in the public domain to help encourage the use of
- Fortran on Acorn hardware. But first, some boring but important legalities.
-
- THE CODE WHICH IS DESCRIBED IN THIS FILE IS HEREBY PLACED IN THE
- PUBLIC DOMAIN SUBJECT TO THE FOLLOWING TERMS AND CONDITIONS :
-
- (1) IN NO CIRCUMSTANCES WILL INTERACTIVE SOFTWARE SERVICES LTD. BE
- LIABLE FOR ANY DAMAGE OR LOSS OF PROFITS OR FOR ANY INDIRECT
- OR CONSEQUENTIAL LOSS ARISING FROM THE USE OF THIS CODE
- (2) DOCUMENTATION FOR ANY PROGRAM WHICH INCORPORATES THESE ROUTINES
- SHOULD INCLUDE DUE ACKNOWLEDGEMENT TO INTERACTIVE SOFTWARE SERVICES
- LTD. AS THE ORIGINAL AUTHORS OF THE CODE CONTAINED HEREIN
- (3) THIS DOCUMENTATION FILE AND THE ASSOCIATED SOURCE CODE MAY BE
- FREELY REDISTRIBUTED ON A NON-PROFIT MAKING BASIS I.E. ONLY
- REASONABLE MEDIA AND HANDLING CHARGES MAY BE MADE
- (4) ONLY UNALTERED VERSIONS OF THIS SOURCE CODE AND THE ASSOCIATED
- DOCUMENTATION FILE MAY BE REDISTRIBUTED
-
- 2. Files
- -----
- Two source files are provided containing the binary file handling
- routines, one for RISC OS and the other for Unix (RISC iX). Where the
- code is distributed on a RISC OS disk the following files are supplied
-
- asm.binaryio : ARM assembler source for RISC OS version
- of binary file handling routines
-
- c.binaryio : C source for RISC iX version
- (can also be used on Sun workstations)
-
- doc.binaryio : This file !
-
- aof.binaryio : Object code for RISC OS version
-
- (On the PD_F77 disc, only the last two are usually supplied, in
- Library.Docs.Binaryio and an alf formatted version of the aof in
- Library.lib.Binaryio)
-
- 3. Overview
- --------
- The binary file handling routines allow both character and numeric data
- to be randomly written to and read from binary data files. No structure
- is imposed on files accessed by these routines, giving the programmer
- complete byte-level file access. The routines bypass the standard Fortran
- i/o system completely giving very significant i/o performance improvements
- especially under RISC OS. Tests have shown a 15-fold speed increase over
- standard Fortran i/o under RISC OS. The improvements of 4 to 5 times under
- RISC iX seem modest in comparison but are still very significant. The exact
- speed improvements which you can expect to achieve in any particular
- application depend to some extent on what type of Fortran i/o they are used
- to replace.
-
- Seven routines are provided to perform open, close, read, write and seek
- operations :
-
- BFOPEN : Opens a file for fast binary i/o
- BFCLOSE : Closes a file opened by BFOPEN
- BFREAD : Reads non-CHARACTER data from a file
- BFREADC : Reads CHARACTER data from a file
- BFWRITE : Writes non-CHARACTER data to a file
- BFWRITEC : Writes CHARACTER data to a file
- BFSEEK : Moves the file pointer
-
- The i/o model adopted is similar to that used by Unix and MeSs DOS.
- BFOPEN is called to open a file in read, write or read/write mode and
- obtain a file handle. BFWRITE/BFWRITEC and/or BFREAD/BFREADC can then
- be used to write/read data to/from the file at the current file pointer
- position. The position of the file pointer can be updated using BFSEEK,
- allowing completely random access to any byte address in a file.
-
- Separate versions of the write routines and the read routines are provided
- for CHARACTER and non-CHARACTER data due to the differences in the argument
- passing mechanism for these data types. Use BFREADC/BFWRITEC to read/write
- CHARACTER data of any sort and BFREAD/BFWRITE to read/write all other data
- types (i.e. INTEGER, LOGICAL, REAL, DOUBLE PRECISION, etc.)
-
- 4. Error Handling
- --------------
- To simplify portability, error handling is implemented via an IERROR
- parameter which is always the last argument to each of the seven binary
- file handling routines. In all cases, a zero return code means there was
- no error. A non-zero error return specifies a system dependent error code.
- Different codes are returned under RISC OS and RISC iX.
-
- 5. Subroutine Descriptions
- -----------------------
- In the following documentation each subroutine argument is preceded by an
- (I) or (O) to signify whether it is an Input or Output argument.
-
- ----------------------------------------------------------------------------
- SUBROUTINE BFOPEN(FILNAM,MODE,IHANDL,IERROR)
-
- Open a file for fast binary i/o
-
- (I) FILNAM = Filename (must be null terminated)
- (I) MODE = Mode to open file in
- 0 = read / 1 = write / 2 = read/write
- (O) IHANDL = File handle
- (O) IERROR = Error flag (non-zero if an error occurred)
-
- CHARACTER*(*) FILNAM
- INTEGER MODE,IHANDL,IERROR
-
- BFOPEN opens a file for binary i/o and returns a file handle (channel
- number). This handle will be used in all subsequent file accesses via
- the other 'BF' routines until BFCLOSE is called. Several files can be
- open simultaneously, in which case the operating system will return
- different handles for each opened file. Do not confuse IHANDL with a
- Fortran Logical File Number. Whilst IHANDL serves a similar purpose
- to a LFN, its value is allocated by the operating system, not the
- user program and it cannot be used in Fortran i/o (read/write/etc.)
- statements.
-
- The filename FILNAM must be null-terminated under both RISC OS and RISC iX.
- i.e. a CHAR(0) must be concatenated onto the end of the filename passed
- to BFOPEN.
-
- The MODE argument controls how the file will be opened. Values of 0 or 2
- leave the current file contents intact. A value of 1 (write mode) creates
- an empty file if it did not already exist or sets the file length to zero
- otherwise. It is an error to open a non-existent file for read access.
-
- The file handle IHANDL should be preserved since this is the only means
- of identifying the file to be accessed in subsequent read/write/seek
- operations
-
- e.g. PARAMETER (IR = 0, IW = 1 , IRW = 2)
- CALL BFOPEN('datafile'//CHAR(0),IW,IHANDL,IERROR)
- IF (IERROR.NE.0) THEN
- WRITE(*,*)'Failed to open datafile'
- STOP
- ENDIF
- CALL BFWRITE(IHANDL,IVALUE,4,NWRITN,IERROR)
-
- ----------------------------------------------------------------------------
- SUBROUTINE BFCLOSE(IHANDL,IERROR)
-
- close a binary file
-
- (I) IHANDL = File handle (obtained by previous call to BFOPEN)
- (O) IERROR = Error flag (non-zero if an error occurred)
-
- INTEGER IHANDL,IERROR
-
- Call BFCLOSE when you have finished processing a file.
-
- e.g. PARAMETER (IR = 0, IW = 1 , IRW = 2)
- CALL BFOPEN('datafile'//CHAR(0),IW,IHANDL,IERROR)
- :
- CALL BFCLOSE(IHANDL,IERROR)
- IF (IERROR.NE.0) WRITE(*,*)'Failed to close datafile'
-
- ----------------------------------------------------------------------------
- SUBROUTINE BFWRITEC(IHANDL,BUFFER,NBYTES,NWRITN,IERROR)
-
- Write a specified number of bytes from a CHARACTER
- buffer to a binary file
-
- (I) IHANDL = File handle
- (I) BUFFER = Character buffer holding data to write
- (I) NBYTES = Number of bytes to write
- (O) NWRITN = Number of bytes actually written
- (O) IERROR = Error flag (non-zero if an error occurred)
-
- INTEGER IHANDL,NBYTES,NWRITN
- CHARACTER*(*) BUFFER
-
- BFWRITEC writes the specified number of bytes from a data buffer which has
- been declared to be of type CHARACTER in the calling program. It does not
- matter whether the data buffer is an array, variable or literal string,
- so long as it is of type CHARACTER. NBYTES will then be written from that
- address regardless of the declared size of BUFFER in the calling program.
-
- Two pieces of information are returned : NWRITN is the number of bytes
- actually written (usually the same as NBYTES) and IERROR is the error flag.
- IERROR can be set for various reasons (e.g. bad file handle, disk full, etc)
-
- BFWRITEC writes data at the current file pointer position, which is
- set initially by BFOPEN to zero (the start of the file). On successful
- completion the file pointer is updated by NBYTES bytes, so that a
- subsequent call to BFWRITEC/BFWRITE will write to the position immediately
- following the last data to be written.
-
- e.g. PARAMETER (IR = 0, IW = 1 , IRW = 2)
- CHARACTER*1 BUFF1(100)
- CHARACTER*20 BUFF2
- CALL BFOPEN('datafile'//CHAR(0),IW,IHANDL,IERROR)
- CALL BFWRITEC(IHANDL,BUFF1,100,NWRITN,IERROR)
- CALL BFWRITEC(IHANDL,BUFF2,LEN(BUFF2),NWRITN,IERROR)
- CALL BFWRITEC(IHANDL,'I hate C',8,NWRITN,IERROR)
-
- ----------------------------------------------------------------------------
- SUBROUTINE BFWRITE(IHANDL,BUFFER,NBYTES,NWRITN,IERROR)
-
- Write a specified number of bytes from a non-CHARACTER
- buffer to a binary file
-
- (I) IHANDL = File handle
- (I) BUFFER = Non-character buffer holding data to write
- (I) NBYTES = Number of bytes to write
- (O) NWRITN = Number of bytes actually written
- (O) IERROR = Error flag (non-zero if an error occurred)
-
- INTEGER IHANDL,NBYTES,NWRITN,IERROR
- INTEGER/REAL/etc. BUFFER
-
- BFWRITE is exactly equivalent to BFWRITEC except that it should be used
- to write non-CHARACTER data, e.g. INTEGER, REAL, LOGICAL, etc. BFWRITE
- does not know or care what type of data is being written (so long as it
- is not CHARACTER) since BUFFER simply specifies an address of an area
- of memory to be written to disk. Thus a mixture of data (such as the
- data in a COMMON block) can easily be written in a single call simply
- by specifying the variable which lies at the start of the memory area
- to be written. Remember though, that NBYTES specifies the number of BYTES
- of data to be written so you must be careful to calculate the total buffer
- size accordingly
-
- e.g. COMMON/MIX/ IVALUE,RVALUE,LVALUE,DVALUE
- INTEGER IVALUE
- REAL RVALUE
- LOGICAL LVALUE
- DOUBLE PRECISION DVALUE
- PARAMETER (IR = 0, IW = 1 , IRW = 2)
- CALL BFOPEN('datafile'//CHAR(0),IW,IHANDL,IERROR)
- C NBYTES = sizeof(INTEGER) + sizeof(REAL)
- C + sizeof(LOGICAL) + sizeof(DOUBLE PRECISION)
- NBYTES = 4 + 4 + 4 + 8
- CALL BFWRITE(IHANDL,IVALUE,NBYTES,NWRITN,IERROR)
-
- ----------------------------------------------------------------------------
- SUBROUTINE BFREADC(IHANDL,BUFFER,NBYTES,NREAD,IERROR)
-
- Read a specified number of bytes from a binary file
- into a CHARACTER buffer
-
- (I) IHANDL = File handle
- (I) BUFFER = Character buffer to receive data
- (I) NBYTES = Number of bytes to read
- (O) NREAD = Number of bytes actually read
- (O) IERROR = Error flag (non-zero if an error occurred)
-
- INTEGER IHANDL,NBYTES,NREAD,IERROR
- CHARACTER*(*) BUFFER
-
- BFREADC writes the specified number of bytes from a file into a data buffer
- which has been declared to be of type CHARACTER in the calling program.
- It does not matter whether the data buffer is an array or a variable (but
- not a literal string) so long as it is of type CHARACTER. Up to NBYTES will
- then be read from the file to that address regardless of the declared size
- of BUFFER in the calling program.
-
- Two pieces of information are returned : NREAD is the number of bytes
- actually read. This need not necessarily be the same as NBYTES since there
- may not be that many ytes left in the file. Asusual, IERROR is the error
- flag which is most likely to be set if a bad file handle is specified,
-
- BFREADC reads data from the current file pointer position, which is
- set initially by BFOPEN to zero (the start of the file) and can be updated
- by calling BFSEEK. On successful completion the file pointer is updated by
- NREAD bytes, so that a subsequent call to BFREADC/BFREAD will read from the
- position immediately following the last data to be read.
-
- e.g. PARAMETER (IR = 0, IW = 1 , IRW = 2)
- CHARACTER*1 BUFF1(100)
- CHARACTER*20 BUFF2
- CALL BFOPEN('datafile'//CHAR(0),IR,IHANDL,IERROR)
- CALL BFREADC(IHANDL,BUFF1,100,NREAD,IERROR)
- IF (NREAD.EQ.100)
- 1 CALL BFREADC(IHANDL,BUFF2,LEN(BUFF2),NREAD,IERROR)
-
- ----------------------------------------------------------------------------
- SUBROUTINE BFREAD(IHANDL,BUFFER,NBYTES,NREAD,IERROR)
-
- Read a specified number of bytes from a binary file
- into a non-CHARACTER buffer
-
- (I) IHANDL = File handle
- (I) BUFFER = Non-character buffer to receive data
- (I) NBYTES = Number of bytes to read
- (O) NREAD = Number of bytes actually read
- (O) IERROR = Error flag (non-zero if an error occurred)
-
- INTEGER IHANDL,NBYTES,NREAD,IERROR
- INTEGER/REAL/etc. BUFFER
-
- BFREAD is exactly equivalent to BFREADC except that it should be used
- to read data into non-CHARACTER variables, e.g. INTEGER, REAL, LOGICAL, etc.
- BFREAD does not know or care what type of data is being written (so long as
- it is not being read into a CHARACTER variable) since BUFFER simply
- specifies an address of an area of memory to which disk data is to be read.
- Thus a mixture of data (such as the data in a COMMON block) can easily be
- restored in a single call simply by specifying the variable which lies at
- the start of the memory area to be updated. Remember though, that NBYTES
- specifies the number of BYTES of data to be read so you must be careful to
- calculate the total buffer size accordingly
-
- e.g. COMMON/MIX/ IVALUE,RVALUE,LVALUE,DVALUE
- INTEGER IVALUE
- REAL RVALUE
- LOGICAL LVALUE
- DOUBLE PRECISION DVALUE
- PARAMETER (IR = 0, IW = 1 , IRW = 2)
- CALL BFOPEN('datafile'//CHAR(0),IR,IHANDL,IERROR)
- C NBYTES = sizeof(INTEGER) + sizeof(REAL)
- C + sizeof(LOGICAL) + sizeof(DOUBLE PRECISION)
- NBYTES = 4 + 4 + 4 + 8
- CALL BFREAD(IHANDL,IVALUE,NBYTES,NREAD,IERROR)
-
- ----------------------------------------------------------------------------
- SUBROUTINE BFSEEK(IHANDL,IFPOS,IERROR)
-
- Move binary file pointer
-
- (I) IHANDL = File handle (obtained by previous call to BFOPEN)
- (I) IFPOS = File pointer position (0 = start of file)
- (O) IERROR = Error flag (non-zero if an error occurred)
-
- INTEGER IHANDL,IFPOS,IERROR
-
- BFSEEK moves the file pointer within the file specified by BFSEEK. To rewind
- a file to the beginning specify an IFPOS value of zero. To move the file
- pointer to the end of the file, specify a huge IFPOS value larger than the
- file can possibly be. (n.b. this behaviour is different from the default
- RISC OS file handling routines which would attempt to extend a file to the
- new length if a file pointer is specified beyond the current extent).
-
- As usual IERROR flags errors. The most likely error is that IHANDL is
- invalid.
-
- e.g. PARAMETER (IR = 0, IW = 1 , IRW = 2)
- CHARACTER*10 START
- CALL BFOPEN('datafile'//CHAR(0),IRW,IHANDL,IERROR)
- IHUGE = 9999999
- CALL BFSEEK(IHANDL,IHUGE,IERROR)
- CALL BFWRITEC(IHANDL,'End of file',11,NWRITN,IERROR)
- CALL BFSEEK(IHANDL,0,IERROR)
- C Read first 10 bytes from start of file
- CALL BFREADC(IHANDL,START,10,NREAD,IERROR)
-
- ----------------------------------------------------------------------------
-
- 6. Feedback
- --------
- Any comments or bug reports to Lawson Wakefield of I.S.S. Ltd. on :
-
- Tel. (+44) 0785 715588
- Fax (+44) 0785 714913
-