Inpak 90 is a Fortran (77/90) collection of routines/functions for accessing Resource Files in ASCII format. The package is optimized for minimizing formatted I/O, performing all of its string operations in memory using Fortran intrinsic functions.
A Resource File is a text file consisting of variable length lines (records), each possibly starting with a label (or key), followed by some data. A simple resource file looks like this:
# Lines starting with # are comments which are # ignored during processing. my_file_names: jan87.dat jan88.dat jan89.dat radius_of_the_earth: 6.37E6 # these are comments too constants: 3.1415 25 my_favourite_colors: green blue 022 # text & number are OK
In this example, my_file_names: and constants: are labels, while jan87.dat, jan88.dat and jan89.dat are data associated with label my_file_names:. Resource files can also contain simple tables of the form,
my_table_name:: 1000 3000 263.0 925 3000 263.0 850 3000 263.0 700 3000 269.0 500 3000 287.0 400 3000 295.8 300 3000 295.8 ::
Resource files are random access, the particular order of the records are not important (except between ::s in a table definition).
The first step is to load the ASCII resource (rc) file into memory1:
call i90_LoadF ( 'my_file.rc', iret )
The next step is to select the label (record) of interest, say
call i90_label ( 'constants:', iret )
The 2 constants above can be retrieved with the following code fragment:
real r integer i call i90_label ( 'constants:', iret ) r = i90_gfloat(iret) ! results in r = 3.1415 i = i90_gint(iret) ! results in i = 25
The file names above can be retrieved with the following code fragment:
character*20 fn1, fn2, fn3 integer iret call i90_label ( 'my_file_names:', iret ) call i90_Gtoken ( fn1, iret ) ! ==> fn1 = 'jan87.dat' call i90_Gtoken ( fn2, iret ) ! ==> fn1 = 'jan88.dat' call i90_Gtoken ( fn3, iret ) ! ==> fn1 = 'jan89.dat'
To access the table above, the user first must use i90_label() to locate the beginning of the table, e.g.,
call i90_label ( 'my_table_name::', iret )
Subsequently, i90_gline() can be used to gain access to each row of the table. Here is a code fragment to read the above table (7 rows, 3 columns):
real table(7,3) character*20 word integer iret call i90_label ( 'my_table_name::', iret ) do i = 1, 7 call i90_gline ( iret ) do j = 1, 3 table(i,j) = i90_gfloat ( iret ) end do end do
Get the idea?
------------------------------------------------------------------ Routine/Function Description ------------------------------------------------------------------ I90_LoadF ( filen, iret ) loads resource file into memory I90_Label ( label, iret ) selects a label (key) I90_GLine ( iret ) selects next line (for tables) I90_Gtoken ( word, iret ) get next token I90_Gfloat ( iret ) returns next float number (function) I90_GInt ( iret ) returns next integer number (function) i90_AtoF ( string, iret ) ASCII to float (function) i90_AtoI ( string, iret ) ASCII to integer (function) I90_Len ( string ) string length without trailing blanks LabLin ( label ) similar to i90_label (no iret) FltGet ( default ) returns next float number (function) IntGet ( default ) returns next integer number (function) ChrGet ( default ) returns next character (function) TokGet ( string, default ) get next token ------------------------------------------------------------------
Common Arguments:
character*(*) filen file name integer iret error return code (0 is OK) character*(*) label label (key) to locate record character*(*) word blank delimited string character*(*) string a sequence of characters
See the Prologues in the next section for additional details.
This software is available at
ftp://niteroi.gsfc.nasa.gov/pub/packages/i90/There you will find the following files:
i90.f Fortran 77/90 source code i90.h Include file needed by i90.f ti90.f Test code i90.ps Postscript documentationAn on-line version of this document is available at
ftp://niteroi.gsfc.nasa.gov/www/packages/i90/i90.html
INTERFACE:
subroutine I90_allLoadF(fname,root,comm,istat) use m_mpif90, only : MP_perr use m_mpif90, only : MP_comm_rank use m_mpif90, only : MP_CHARACTER use m_mpif90, only : MP_INTEGER use m_die, only : perr implicit none character(len=*),intent(in) :: fname integer,intent(in) :: root integer,intent(in) :: comm integer,intent(out) :: istatREVISION HISTORY:
28Jul98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
INTERFACE:
subroutine push_(ier) use m_die, only : perr use m_mall,only : mall_mci,mall_ci,mall_ison implicit none integer,intent(out) :: ierREVISION HISTORY:
05Aug98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
INTERFACE:
subroutine pop_(ier) use m_die, only : perr use m_mall,only : mall_mco,mall_co,mall_ison implicit none integer,intent(out) :: ierREVISION HISTORY:
05Aug98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
INTERFACE:
subroutine i90_fullRelease(ier) use m_die,only : perr implicit none integer,intent(out) :: ierREVISION HISTORY:
05Aug98 - Jing Guo <guo@thunder> - initial prototype/prolog/code
Reads resource file, strips out comments, translate TABs into blanks, and loads the modified file contents into memory. Must be called only once for each resource file.
CALLING SEQUENCE:
call i90_LoadF ( filen, iret )INPUT PARAMETERS:
character*(*) filen ! file nameOUTPUT PARAMETERS:
integer iret ! Return code: ! 0 no error ! -98 coult not get unit number ! (strange!) ! -98 talk to a wizzard ! -99 out of memory: increase ! NBUF_MAX in 'i90.h' ! other iostat from open statement.BUGS:
It does not perform dynamic allocation, mostly to keep vanilla f77 compatibility. Overall amount of static memory is small (~100K for default NBUF_MAX = 400*256).SEE ALSO:
i90_label() selects a label (key)FILES USED:
File name supplied on input. The file is opened, read and then closed.REVISION HISTORY:
19Jun96 da Silva Original code.
Once the buffer has been loaded with i90_loadf(), this routine selects a given ``line'' (record/table) associated with ``label''. Think of ``label'' as a resource name or data base ``key''.
CALLING SEQUENCE:
call i90_Label ( label, iret )INPUT PARAMETERS:
character(len=*),intent(in) :: label ! input labelOUTPUT PARAMETERS:
integer iret ! Return code: ! 0 no error ! -1 buffer not loaded ! -2 could not find labelSEE ALSO:
i90_loadf() load file into buffer i90_gtoken() get next token i90_gline() get next line (for tables) atof() convert word (string) to float atoi() convert word (string) to integerREVISION HISTORY:
19Jun96 da Silva Original code. 19Jan01 Jay Larson <[email protected]> - introduced CHARACTER variable EOL_label, which is used to circumvent pgf90 problems with passing concatenated characters as an argument to a function.
Selects next line, irrespective of of label. If the next line starts with :: (end of table mark), then it lets the user know. This sequential access of the buffer is useful to assess tables, a concept introduced in Inpak 77 by Jing Guo. A table is a construct like this:
my_table_name:: 1000 3000 263.0 925 3000 263.0 850 3000 263.0 700 3000 269.0 500 3000 287.0 400 3000 295.8 300 3000 295.8 ::
To access this table, the user first must use i90_label() to locate the beginning of the table, e.g.,
call i90_label ( 'my_table_name::', iret )
Subsequently, i90_gline() can be used to gain acess to each row of the table. Here is a code fragment to read the above table (7 rows, 3 columns):
real table(7,3) character*20 word integer iret call i90_label ( 'my_table_name::', iret ) do i = 1, 7 call i90_gline ( iret ) do j = 1, 3 table(i,j) = fltget ( 0. ) end do end do
For simplicity we have assumed that the dimensions of table were known. It is relatively simple to infer the table dimensions by manipulating ``iret''.
CALLING SEQUENCE:
call i90_gline ( iret )INPUT PARAMETERS:
None.OUTPUT PARAMETERS:
integer iret ! Return code: ! 0 no error ! -1 end of buffer reached ! +1 end of table reachedSEE ALSO:
i90_label() selects a line (record/table)REVISION HISTORY:
10feb95 Guo Wrote rdnext(), Inpak 77 extension. 19Jun96 da Silva Original code with functionality of rdnext()
Get next token from current line. The current line is defined by a call to i90_label(). Tokens are sequences of characters (including blanks) which may be enclosed by single or double quotes. If no quotes are present, the token from the current position to the next blank of TAB is returned.
Examples of valid token:
single_token "second token on line" "this is a token" 'Another example of a token' 'this is how you get a " inside a token' "this is how you get a ' inside a token" This is valid too # the line ends before the #The last line has 4 valid tokens: This, is, valid and too.
Invalid string constructs:
cannot handle mixed quotes (i.e. single/double) 'escaping like this \' is not implemented' 'this # will not work because of the #'The # character is reserved for comments and cannot be included inside quotation marks.
CALLING SEQUENCE:
call i90_GToken ( token, iret )INPUT PARAMETERS:
None.OUTPUT PARAMETERS:
character*(*) token ! Next token from current line integer iret ! Return code: ! 0 no error ! -1 either nothing left ! on line or mismatched ! quotation marks.BUGS:
Standard Unix escaping is not implemented at the moment.SEE ALSO:
i90_label() selects a line (record/table) i90_gline() get next line (for tables) atof() convert word (string) to float atoi() convert word (string) to integerREVISION HISTORY:
19Jun96 da Silva Original code.
Returns next float (real number) from the current line. If an error occurs a zero value is returned.
CALLING SEQUENCE:
real rnumber rnumber = i90_gfloat ( default )OUTPUT PARAMETERS:
integer,intent(out) :: iret ! Return code: ! 0 no error ! -1 either nothing left ! on line or mismatched ! quotation marks. ! -2 parsing errorREVISION HISTORY:
19Jun96 da Silva Original code.
Returns next integer number from the current line. If an error occurs a zero value is returned.
CALLING SEQUENCE:
integer number number = i90_gint ( default )OUTPUT PARAMETERS:
integer iret ! Return code: ! 0 no error ! -1 either nothing left ! on line or mismatched ! quotation marks. ! -2 parsing errorREVISION HISTORY:
19Jun96 da Silva Original code. 24may00 da Silva delcared x as real*8 in case this module is compiled with real*4
Converts string to real number. Same as obsolete str2rn().
CALLING SEQUENCE:
real rnumber rnumber = i90_atof ( string, iret )INPUT PARAMETERS:
character(len=*),intent(in) :: string ! a stringOUTPUT PARAMETERS:
integer,intent(out) :: iret ! Return code: ! 0 no error ! -1 could not convert, probably ! string is not a numberREVISION HISTORY:
19Jun96 da Silva Original code.
Converts string to integer number.
CALLING SEQUENCE:
integer number number = i90_atoi ( string, iret )INPUT PARAMETERS:
character*(*) string ! a stringOUTPUT PARAMETERS:
integer iret ! Return code: ! 0 no error ! -1 could not convert, probably ! string is not a numberREVISION HISTORY:
19Jun96 da Silva Original code.
Returns the length of a string excluding trailing blanks. It follows that
i90_len(string) .le. len(string),where len is the intrinsic string length function. Example:
ls = len('abc ') ! results in ls = 5 ls = i90_len ('abc ') ! results in ls = 3
CALLING SEQUENCE:
integer ls ls = i90_len ( string )INPUT PARAMETERS:
character*(*) string ! a stringOUTPUT PARAMETERS:
The length of the string, excluding trailing blanks.REVISION HISTORY:
01Apr94 Guo Original code (a.k.a. luavail()) 19Jun96 da Silva Minor modification + prologue.
Look for an available (not opened) Fortran logical unit for i/o.
CALLING SEQUENCE:
integer lu lu = i90_lua()INPUT PARAMETERS:
None.OUTPUT PARAMETERS:
The desired unit number if positive, -1 if unsucessful.REVISION HISTORY:
01Apr94 Guo Original code (a.k.a. luavail()) 19Jun96 da Silva Minor modification + prologue.
Pads from the right with the comment character (#). It also replaces TABs with blanks for convenience. This is a low level i90 routine.
CALLING SEQUENCE:
call i90_pad ( string )INPUT PARAMETERS:
character*256 string ! input stringOUTPUT PARAMETERS:
character*256 stringBUGS:
It alters TABs even inside strings.REVISION HISTORY:
19Jun96 da Silva Original code.
Removes blanks and TABS from begenning of string. This is a low level i90 routine.
CALLING SEQUENCE:
call i90_Trim ( string )INPUT PARAMETERS:
character*256 string ! the input stringOUTPUT PARAMETERS:
character*256 string ! the modified stringREVISION HISTORY:
19Jun96 da Silva Original code.
Selects a given ``line'' (record/table) associated with ``label''. Similar to i90_label(), but prints a message to stdout if it cannot locate the label. Kept for Inpak 77 upward compatibility.
CALLING SEQUENCE:
call lablin ( label )INPUT PARAMETERS:
character(len=*),intent(in) :: label ! string with label nameOUTPUT PARAMETERS:
None.REVISION HISTORY:
19Jun96 da Silva Original code.
Returns next float (real number, single precision) from the current line, or a default value if it fails to obtain the desired number. Kept for Inpak 77 upward compatibility.
CALLING SEQUENCE:
real rnumber, default rnumber = fltgetsp ( default )INPUT PARAMETERS:
real(SP), intent(IN) :: default ! default value.REVISION HISTORY:
19Jun96 da Silva Original code. 12Oct99 Guo/Larson - Built from original FltGet() function.
Returns next float (real number) from the current line, or a default value (double precision) if it fails to obtain the desired number. Kept for Inpak 77 upward compatibility.
CALLING SEQUENCE:
real(DP) :: default real :: rnumber rnumber = FltGetdp(default)INPUT PARAMETERS:
real(DP), intent(IN) :: default ! default value.REVISION HISTORY:
19Jun96 da Silva Original code. 12Oct99 Guo/Larson - Built from original FltGet() function.
Returns next integer number from the current line, or a default value if it fails to obtain the desired number. Kept for Inpak 77 upward compatibility.
CALLING SEQUENCE:
integer number, default number = intget ( default )INPUT PARAMETERS:
integer default ! default value.REVISION HISTORY:
19Jun96 da Silva Original code.
Returns next non-blank character from the current line, or a default character if it fails for whatever reason. Kept for Inpak 77 upward compatibility.
CALLING SEQUENCE:
character*1 ch, default ch = chrget ( default )INPUT PARAMETERS:
character*1 default ! default value.REVISION HISTORY:
19Jun96 da Silva Original code.
Returns next token from the current line, or a default word if it fails for whatever reason.
CALLING SEQUENCE:
call TokGet ( token, default )INPUT PARAMETERS:
character*(*) default ! default tokenOUTPUT PARAMETERS:
character*(*) token ! desired tokenREVISION HISTORY:
19Jun96 da Silva Original code.