            USER'S GUIDE TO THE SUNGRAPH FORMAT DISK I/O ROUTINES

                                  JULY 1988



                              TABLE OF CONTENTS

1.0  INTRODUCTION

2.0  GENERAL INFORMATION
     2.1 Supported Data Types
     2.2 The Concept of Data Blocks
     2.3 Files Associated with Disk I/O
     2.4 Calling the Disk I/O Routines from C
     2.5 Calling the Disk I/O Routines from FORTRAN
     2.6 Error Reporting

3.0  USING THE DISK WRITE ROUTINES
     3.1 Description of the Disk Write Routines
          3.1.1 Open File Routine
          3.1.2 Define Variable Routine
          3.1.3 Save Variable Routine
          3.1.4 End Block Routine
          3.1.5 Close File Routine
          3.1.6 Disk Write Error Routines

4.0  USING THE DISK READ ROUTINES
     4.1 Description of the Disk Read Routines
          4.1.1 Open Variable Channel Routine
          4.1.2 Open Block Channel Routine
          4.1.3 Read Format Routine
          4.1.4 File Length Routine
          4.1.5 Goto Sample Routine
          4.1.6 Read Variable Routine
          4.1.7 Goto Block Routine
          4.1.8 Read Block Routine
          4.1.9 Close Channel Routine
          4.1.10 Disk Read Error Routines


1.0  INTRODUCTION

     A set of routines to transfer data between programs and disk was
developed as part of the SUNGRAPH project.  The primary use of these routines
is to transfer data from a program to SUNGRAPH.  In this case, the user's
program uses only the disk write routines.  Another use for these routines is
to pass data between user's programs in situations where disk storage is
needed, but display with SUNGRAPH is not necessary.  In this case, the user
will need to use the disk read routines as well.  This document describes
each disk I/O routine and how to use them.  It does not describe the actual
format of the disk files which the routines use.


2.0  GENERAL INFORMATION

     The disk I/O routines are written in C and are available on the Alliant
and the Suns.  Calling them from C programs is just like calling any C
function.  Porting the routines to other machines should be straightforward.
A FORTRAN interface to the I/O routines is provided for the Alliant and Sun
machines.  These interfaces are machine dependent and therefore don't port
easily to other machines.

2.1  Supported Data Types

     The disk I/O routines enable users to write and read variables of several
data types.  The current version supports two and four byte integers and four
byte floating point variables.  Other data types can be added quite easily as
the need arises. 

2.2  The Concept of Data Blocks

     A data file can contain the values of one or more variables.  The files
and the routines which read and write them are organized around the concept of
data blocks.  A data block is the elementary unit of a data file and consists
of one or more values of each variable stored in the file.  When a new file is
created, the user decides how many variables the file will have and how many
values of each variable will be saved per data block.  A data file consists of
an arbitrary number of concatenated data blocks.

2.3  Files Associated With Disk I/O

     Data files created by the disk write routines have the extension
.sg_data.  These files consist entirely of data saved by the user; there is NO
header or record information.  Associated with each data file is a format file
having the extension .sg_format.  The format file (which has the function of a
small header) has information about the data file.  The format file contains
the following: 

     a) a number indicating data file type
     b) the number of variables in the data file
     c) for each variable in the file:
          1) data type
          2) number of values per block
          3) name

The description for the read_format routine contains additional information
about the format file.

     Any file written with the disk write routines can be read with the disk
read routines.  One other type of file can be read.  This data file must have
the extension .spd (SPeech Data).  These files usually originate by A/D
conversion of a signal of interest, such as speech.  To be an spd file, the
following must hold: 

     a) the data consists entirely of 16 bit integers stored in the binary
format of the Alliant or Sun (or machine with equivalent representation).  In
FORTRAN, this is an integer*2.  In C, it is a short int.
     b) the sample values are from a single data source.  i.e. the file has
values of a single variable; it is not multiplexed. 

2.4  Calling the Disk I/O Routines from C

     All object code that you need to link to is contained in one archive
file.  "disk_io.h" is a header file which contains definitions of some
parameters in the read and write routines.  You may want to use some of these
definitions in your program, but this is not necessary.  The files are located
as follows: 

          diskio/disk_io.h
          diskio/disk_io.a


2.5  Calling the Disk I/O Routines from FORTRAN

     Most of the disk I/O routines can be called from FORTRAN; exceptions
are noted in the routine descriptions.  When calling these routines from
Alliant FORTRAN, string arguments passed to the I/O routines are required to
be terminated with a null.  Put the null right after the last valid character. 

     All object code that you need to link to is contained in one archive
file.  The location of the object files is as follows: 

          diskio/disk_io.a

     The "released" directory also contains source code for all object files
in the archive file. 

2.6  Error Reporting

     The disk I/O routines check for all but the most unlikely error
conditions.  There are two error reporting methods which the user can select
from.  The default method is that when an error is detected, an error message
is printed.  Program execution is then halted.  The default method is called
auto error reporting.  The other error reporting method is for the disk I/O
routine to return a negative number.  (Disk I/O routines return zero or a
positive number when successful.)  The user checks the return value and takes
appropriate action.  All return values are type int (integer*4 in FORTRAN).  A
routine to turn an error number into an error message is provided.  The
following routine allows the user to change the error handling method. 

     disk_io_erh(flag)   flag is an int (integer*4 in FORTRAN)

When 'flag' is zero, auto error reporting is disabled
When 'flag' is not zero, auto error reporting is enabled.

     The error handling method can be changed as often as you want, thus
allowing some error conditions to be handled automatically and others to be
handled by the user.


3.0  USING THE DISK WRITE ROUTINES

     There are five routines in the disk write collection:
     1) open_file - opens a file for writing;
     2) def_variable - defines attributes of a variable to be saved;
     3) save_variable - saves the values of a variable;
     4) end_block - declares that all values of the variables have been saved
                    for this block;
     5) close_file - ends the use of a file

     For each file that you want to save variables in, you use a process
similar to the following.  First, open the file with open_file.  Then, for
each variable, declare its name, data type, number of values saved per block,
and default value with the def_variable routine.  These two routines set up
the file so that data can be saved and don't get called again for this file.
Next, save the values of variables with save_variable.  When all values
of a block of file variables have been saved, call end_block.  Repeat the
process of saving variables and ending a block for as much data as you want to
save.  After saving the last block, close the file with close_file. 

     If you use the auto error reporting method, a disk I/O error halts
execution and causes an error message to be printed.  If you don't use this
method, a disk I/O routine indicates an error via a negative return value.
This condition should be tested after using any of these routines and
appropriate action taken if an error occurs.  The disk write error routines
are provided to turn the return value into an error message.


3.1  Description of the Disk Write Routines

3.1.1  Open File Routine:

     file_id = open_file ( filename, open_type )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       filename  |  char *  |  character*80  (or shorter)
      open_type  |   int    |  integer*4

     This routine opens the file "filename" so that data may be written to it.
The parameter "open_type" specifies the following:
     1 - Open the file unconditionally.  Discard any prior data in the file.
     2 - Append to an existing file.
     3 - Open a new file.  If the file already exists, don't open it.
         (An error message will indicate that the file already exists.)

     The data will be written to a file named "filename.sg_data" and
information about this file's format will be written to "filename.sg_format".
Since the variable definition process determines part of the file format
information, the format file is not written until this process terminates
(with the first call to end_block, described below).  When appending to an
existing file, the current format must match that of the appended file.  This
is checked in the first call to end_block. 

Returned value:

     If there are no errors, the returned value is a file id which is used to
identify this open file when using several other of the disk write routines.
A valid file id is >= 0.  If an error occurs, the returned value is < 0.

The following errors are detected:

     - file "filename" is already open
     - filename is too long
     - the number of files currently open is the maximum
     - could not create a format file
     - could not create a data file
     - could not open filename.sg_format for reading
     - could not open filename.sg_data for writing
     - file "filename" exists and open_type prohibits overwriting
     - invalid open_type


3.1.2  Define Variable Routine:
     
     var_id = def_variable ( file_id, name, type, number, def_val )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       file_id   |   int    |   integer*4
         name    |  char *  |  character*16  (or shorter)
         type    |   int    |   integer*4
        number   |   int    |   integer*4
       def_val   | "type" * |     "type"     (see description below)

     This routine defines parameters of a variable to be saved.  The
parameters are the variable's name, data type, number per block, and default
value.  Variables in a particular file may be defined until the first call to
end_block for that file; i.e. calling end_block ends the variable definition
process for a file.  The string used as the variable's name does not have to
be the name the calling program uses to reference the variable's values.  It
can be some other string of the programmer's choosing.  This name is used to
select the variable for reading by the disk read routines.  It is also used to
select and label variables in SUNGRAPH.  This routine does NOT check for
duplication of variable names, so be sure that each file variable has a unique
name.  The default value is written if the user has saved fewer than "number"
values per block when end_block is called.  In FORTRAN, the default value's
type must be the saved variable's type.  (e.g.  If type=3, the default value
must be a real*4.)  In C, the default value is a POINTER to a value of the
type specified in the argument list.  (e.g.  If type=3, the default value must
be a pointer to a float.)  The argument "type" refers to data types according
to the following table: 

    TYPE  #  |  C TYPE  |  # of BYTES  |  FORTRAN TYPE
    --------------------------------------------------
       1     |  short	|      2       |  integer*2
       2     |   int	|      4       |  integer*4
       3     |  float	|      4       |    real*4

Returned value:

     When no error occurs, the returned value is a variable id which is used
to identify this variable when saving its values with the save variable
routine.  A valid variable id is >= 0.  If an error occurs, the returned value
is < 0. 

The following errors are detected:

     - 'file_id' is out of range
     - 'file_id' corresponds to an unopened file
     - the file variables have already been defined
     - invalid data type specified
     - invalid number of values specified
     - the maximum number of variables have already been defined
     - variable name is too long
     - could not get a buffer for saved values


3.1.3  Save Variable Routine:

     status = save_variable ( var_id, values, num )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
        var_id   |   int    |   integer*4
        values   |  varies  |     varies
                 | (array)  |    (array)
         num     |   int    |   integer*4

     This routine saves values of a variable that has been defined.  "values"
is the array of which "num" values will be saved.  The data type of the values
array must match that declared when the variable was defined.  The routine
does NOT test for such a match.  The number of values saved per call can be
from 1 to the number per block specified when the variable was defined with
def_variable.  The total number of values saved per variable cannot exceed the
number per block specified when the variable was defined.  Note to C users:
When saving a single value, be sure that "values" is a POINTER to that value. 

Returned value:

     The returned value indicates the error status of the routine.  If no
error occurs, the returned value is 0.  If an error occurs, the value is < 0. 

The following errors are detected:

     - 'num' < 1
     - 'var_id' is out of range
     - 'var_id' corresponds to an undefined variable
     - all values of this variable have been saved in the current block
     - saved less than the specified number of values because the current
       block became full


3.1.4  End Block Routine:

     status = end_block ( file_id )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       file_id   |   int    |   integer*4

     This routine terminates the saving of variables for a block.  This is the
routine which writes the block values to the data file.  The first call to
this routine terminates the variable definition process, i.e. def_variable can
no longer be called for this file_id.  When a file is open for appending, the
first call to this routine checks to see that the variable definition of the
appended file matches the current definition.  An error is returned if not.

Returned value:

     The returned value indicates the error status of the routine.  If no
error occurs, the returned value is 0.  If an error occurs, the value is < 0. 

The following errors are detected:

     - 'file_id' is out of range
     - 'file_id' corresponds to an unopened file
     - current variable definition differs from that of appended file
     - error when writing format file
     - error when writing data buffer to disk
     - no variables have been defined


3.1.5  Close File Routine:

     status = close_file ( file_id )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       file_id   |   int    |   integer*4

     This routine closes the file associated with "file_id".  In the event
that more files need to be written than can be opened simultaneously, this
routine provides a way to close a file so that another can be opened. 

Returned value:

     The returned value indicates the error status of the routine.  If no
error occurs, the returned value is 0.  If an error occurs, the value is < 0. 

The following errors are detected:

     - 'file_id' is out of range
     - 'file_id' corresponds to an unopened file


3.1.6  Disk Write Error Routines:

     print_disk_write_error ( err_num )            (Callable from FORTRAN)
     error_string = disk_write_error ( err_num )   (No FORTRAN interface yet)

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       err_num   |   int    |   integer*4

     The disk write routines return a value which, when less than zero,
corresponds to an error number.  The disk write error routines provide a way
to turn the error number into an appropriate error message.  The
disk_write_error routine returns brief error message corresponding to
"err_num".  The "print_disk_write_error" routine prints a more elaborate error
message.  These routines return "No error" for arguments zero or greater and
"Bad value for error number" if "err_num" is not a value from one of the write
routines. 


4.0  USING THE DISK READ ROUTINES

     The disk read routines are structured to provide "channels" through which
the file variables flow.  There are two types of channels - variable channels
and block channels.  A variable channel provides access to just one of the
variables in a file, independent of how many variables the file may contain. 
A block channel provides access to all of the variables in a file.  The values
of a variable are read on a variable channel via the read_variable routine.
This routine can return any number of the variable's values in a single call.
Values are read on a block channel via the read_block routine.  This routine
returns one block of values per call.  The reading is done sequentially on
each channel type.  Two routines are provided to modify the point from which
data is read - the goto_sample routine and the goto_block routine.  There is
also a routine to read the file format and one to close channels.

The disk read routines consist of the following:
     1) read_format - reads and returns information about the data file
             format.
     2) open_var_channel - opens a channel to access one variable in a data
             file.
     3) read_variable - reads and returns values of a variable.
     4) goto_sample - re-positions the reading process so that read_variable
             will read from a different sample in the file.
     5) open_block_channel - opens a channel to access all variables in a data
             file.
     6) read_block - reads and returns the values of one block of data.
     7) goto_block - re-positions the reading process so that read_variable
             and read_block will read from a different place in the file.
     8) file_length - return the length of an open file.
     9) close_channel - close an open channel.

     To set-up a variable channel do the following.  First, call
open_var_channel to open a channel and get a channel id.  Then use
read_variable to read values and if necessary, use goto_sample or goto_block
to read non-sequentially.  Call close_channel when you no longer want to read
values of the variable on that channel.  To use a block channel, do the
following.  First, call open_block_channel to open a channel and get a channel
id.  Then use read_block to read one block's worth of values.  Use goto_block
if you need to read other than sequentially.  The read_format routine is
provided to read format information in situations when the file format is not
known at the time your program is being written. 

     If you use the auto error reporting method, a disk I/O error halts
execution and causes an error message to be printed.  If you don't use this
method, a disk I/O routine indicates an error via a negative return value.
This condition should be tested after using any of these routines and
appropriate action taken if an error occurs.  The disk read error routines
are provided to turn the return value into an error message.


4.1  Description of the Disk Read Routines

4.1.1  Open Variable Channel Routine:

     chan_id = open_var_channel ( filename, var_name )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       filename  |  char *  |  character*80  (or shorter)
       var_name  |  char *  |  character*16  (or shorter)

     This routine is called to establish a new channel to access the values of
one of the variables in a data file.  "filename" is the name of the file and
"var_name" is the name of the variable whose values are to be read.  The
variable's values are accessed with the read_variable routine.  This function
returns a channel id which is used to identify the opened channel when calling
other disk read routines.  "filename" can have an extension, but it is not
mandatory.   

If "filename" has an extension:
     a) The extension is tested for validity.  (e.g. Is it .sg_data or one of
        the other types that can be read by these routines?)  Valid extensions
        are: .sg_data  .spd
     b) If the extension is valid, open_var_channel tries to open "filename".
        If the extension is not valid, an error is returned.
If "filename" does not have an extension:
     a) Each valid extension is concatenated in turn with a copy of filename
        and the resulting filename is tested for existence.  The order is:
        .sg_data, .spd.
     b) If this file exists, open_var_channel tries to open it.
        If none of these files exist, an error is returned.

     If the file to be opened is a .sg_data file, the format information must
reside in a corresponding .sg_format file.  There is no format file associated
with .spd files.

Returned value:

     If there are no errors, the returned value is a channel id which is used
to identify the open channel when using other disk read routines.  A valid
channel id is >= 0.  If an error occurs, the returned value is < 0. 

The following errors are detected:

     - filename is too long
     - all channels are open
     - there is a format file problem
       (use read_format to determine the problem)
     - the specified variable was not found
     - invalid extension in filename
     - no data file found
     - the data file could not be opened


4.1.2  Open Block Channel Routine:

     chan_id = open_block_channel ( filename )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       filename  |  char *  |  character*80  (or shorter)

     This routine is called to establish a new channel to access the values of
all of the variables in a data file.  The values of the data file variables
are accessed with the read_block routine.  This function returns a channel id
which is used to identify the opened channel when calling other disk read
routines.  The same rules concerning filename extensions described in
open_var_channel apply to open_block_channel.

Returned value:

     If there are no errors, the returned value is a channel id which is used
to identify the open channel when using other disk read routines.  A valid
channel id is >= 0.  If an error occurs, the returned value is < 0. 

The following errors are detected:

     - filename is too long
     - all channels are open
     - there is a format file problem
       (use read_format to determine the problem)
     - invalid extension in filename
     - no data file found
     - the data file could not be opened


4.1.3  Read Format Routine:

     status = read_format ( filename, format, vnames )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       filename  |  char *  |  character*80  (or shorter)
        format   |   int    |   integer*4
                 | (array)  |    (array)
        vnames   | char **  |  character*16  (see description)
                 |          |    (array)

     This routine reads the format file associated with file "filename" and
returns this information.  As with the filename argument in the open channel
routines, read_format accepts filenames with or without extensions.  It uses
the same process that the open channel routines use to determine for what data
file the format information is sought.  Hence, for a given filename,
read_format always gets the format which corresponds to the data file opened
by an open channel routine.  (However, read_format accepts filenames that end
with .sg_format.  Such a filename would cause an error if given to an open
channel routine.)  When calling from FORTRAN, vnames should be declared:

     character*16 vnames(n)

n should be equal to or greater than the number of variables in the file.  A
safe choice for n is the maximum number of variables permitted in a file
(currently 36).

The format array contains the following information:

     format[0]   -   file type indicator
                     current meaning (could be expanded later):
                     1 if .sg_data file allows sample & block positioning;
                     0 if this is NOT allowed
     format[1]   -   number of variables/block in .sg_data file
     format[2*n]  -  data type of variable n in .sg_data file
                     1 - short; 2 - int; 3 - float
                     (integer*2; integer*4; real*4 in FORTRAN)
     format[2*n+1] - number of values/block of variable n in .sg_data file

"vnames" is an array of pointers to the names of variables saved in the data
file.  Thus, vnames[0] points to the name of the first variable, vnames[1]
points to the name of the second variable, etc.  In FORTRAN, vnames is an
array of character strings.  vnames(1) has the name of the first variable,
vnames(2) has the name of the second variable, etc.

     The format information comes from a .sg_format file when the data file is
a .sg_data file.  Other data file types have fixed formats which return a set
of parameters stored in this routine.  Listed below are the format parameters
for each of these other data file types.

Format parameters for .spd data files:
     format[0] = 1
     format[1] = 1
     format[2] = 1
     format[3] = 512
     vnames[0] = "speech_data"

(No other data file types are currently defined.)

Returned value:

     The returned value indicates the error status of the routine.  If no
error occurs, the returned value is 0.  If an error occurs, the value is < 0.

The following errors are detected:

     - filename is too long
     - invalid extension in filename
     - no data file found, so can't determine format
     - the format file could not be opened
     - the format file is not complete
     - invalid value read for file type
     - invalid value read for variables/block
     - invalid value read for data type
     - invalid value read for values/block


4.1.4  File Length Routine:

     status = file_length ( chan_id, bytes, samples, blocks )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       chan_id   |   int    |   integer*4
        bytes    |  int *   |   integer*4
       samples   |  int *   |   integer*4
        blocks   |  int *   |   integer*4

     This routine returns the length of the file connected to "chan_id" in
terms of bytes, samples and blocks.  I don't know what it should do with 
real-time data files (sockets) yet.

Returned value:

     The returned value indicates the error status of the routine.  If no
error occurs, the returned value is 0.  If an error occurs, the value is < 0.

The following errors are detected:

     - channel number is outside valid range
     - specified channel is not open


4.1.5  Goto Sample Routine:

     position = goto_sample ( chan_id, sample_num, how )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       chan_id   |   int    |   integer*4
      sample_num |   int    |   integer*4
         how     |   int    |   integer*4

     This routine changes the sample number that the next call to
read_variable on "chan_id" reads from.  When "how" is 0, "sample_num" is
measured from the beginning of the file (i.e. absolute positioning).  When
"how" is not 0, "sample_num" is measured from the current file position (i.e.
relative positioning).  The first sample in the file is called sample 1.  This
routine can be called only if the specified channel is a "variable channel",
that is one opened via open_var_channel.  This routine does not return an
error if the sample to be read is beyond the end of file; this condition is
reported when reading.

Returned value:

     If there are no errors, the returned value indicates the current file
position (the sample number of the next sample to be read by read_variable). A
valid sample number is 1 or greater.  If an error occurs, the returned value
is < 0. 

The following errors are detected:

     - channel number is outside valid range
     - specified channel is not open
     - this routine is for use only with variable channel types
     - the file connected to this channel prohibits positioning
     - effective sample_num is < 1


4.1.6  Read Variable Routine:

     position = read_variable ( chan_id, values, num, num_read )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       chan_id   |   int    |   integer*4
        values   |  varies  |     varies
                 | (array)  |    (array)
         num     |   int    |   integer*4
       num_read  |  int *   |   integer*4

     This routine returns the next "num" values of the variable connected to
channel number "chan_id".  "values" is an array where the returned values are
placed.  In the calling routine, this array type should match that of the
variable being returned.  The size of "n" is limited only by the array size in
the calling routine.  The actual number of values read is returned in
"num_read".  "num_read" will equal "num" unless an error (specified below)
occurs; in this case, it may be zero to num-1.  This routine can be called
only if the specified channel is a "variable channel", that is one opened via
open_var_channel.

Returned value:

     If there are no errors, the returned value indicates the current file
position (the sample number of the next sample to be read by read_variable). A
valid sample number is 1 or greater.  If an error occurs, the returned value
is < 0. 

The following errors are detected:

     - error during the file read operation
     - EOF encountered on the data file
     - channel number is outside valid range
     - specified channel is not open
     - this routine is for use only with variable channel types


4.1.7  Goto Block Routine:

     position = goto_block ( chan_id, block_num, how )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       chan_id   |   int    |   integer*4
      block_num  |   int    |   integer*4
         how     |   int    |   integer*4

     This routine changes the place from which data is read in the file
connected to "chan_id".  When "how" is 0, "block_num" is measured from the
beginning of the file (i.e. absolute positioning).  When "how" is not 0,
"block_num" is measured from the current file position (i.e. relative
positioning).  It can be used on block channels and on variable channels.  The
first block in a file is called block 1.  This routine does not return an
error if positioned beyond the end of file; this condition is reported when
reading.

     On block channels, the repositioning is as follows:

     If absolute positioning, the block number read by the next read_block is
"block_num". 
     If relative positioning, the block number read by the next read_block is
changed by "block_num" blocks. 

     On variable channels, the repositioning is as follows:

     If absolute positioning, the first sample read by the next read_variable
is sample number: 
1 + (block_num - 1) * (# of values of variable per block)
     If relative positioning, the first sample read by the next read_variable
is changed by "block_num" blocks. 

Returned value:

     If there are no errors, the returned value indicates the current file
position.  On variable channels, the returned value is the sample number of
the next sample to be read by read_variable.  On block channels, the returned
value is the block number of the next block to be read by read_block. A valid
sample number or block number is 1 or greater.  If an error occurs, the
returned value is < 0.

The following errors are detected:

     - channel number is outside valid range
     - specified channel is not open
     - the file connected to this channel prohibits positioning
     - effective block_num < 1


4.1.8  Read Block Routine:

     position = read_block ( chan_id, val_pntr )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       chan_id   |   int    |   integer*4
       val_pntr  | pointer  |   integer*4    (see below)
                 |  array   |     array

     This routine returns one block of values from the file connected to
channel "chan_id".  "val_pntr" is an array of pointers having one element for
each block variable.  The calling routine sets each pointer in the array to
specify where the values for each block variable are to go.  Thus, val_pntr[0]
is the address where the first value of the first block variable will be
stored; val_pntr[1] is the address where the first value of the second block
variable will be stored; etc.  Subsequent values of the variables are stored
in sequential locations following the address of the first value.

     For FORTRAN (ugh) users, here's what you do with val_pntr.  This array is
set up to contain for each block variable, the ADDRESS of where you want the
first value of each variable to be placed.  A routine for getting the address
of a variable is included in the disk I/O package.  To illustrate the process,
suppose you have two variables in a block and you want to store them in x and
y.  The following code fragment shows what you do: 

     INTEGER*4 GET_ADDRESS  ! get_address returns an address of type integer*4
     REAL*4 X(13)           ! there are 13 values of X per block
     INTEGER*4 Y(8)         ! there are 8 values of Y per block
     VAL_PNTR(2)            ! there are 2 variables per block

     VAL_PNTR(1) = GET_ADDRESS( X(1) )
     VAL_PNTR(2) = GET_ADDRESS( Y(1) )

     STATUS = READ_BLOCK(CHAN_ID, VAL_PNTR)

     If the X and Y arrays are stored at fixed memory addresses, the val_pntr 
array can be set just once, rather than before each use of read_block.  If the
arrays move, val_pntr must be recalculated.

Returned value:

     If there are no errors, the returned value indicates the current file
position (the block number of the next block to be read by read_block).  A
valid block number is 1 or greater.  If an error occurs, the returned value is
< 0. 

The following errors are detected:

     - channel number is outside valid range
     - specified channel is not open
     - this routine is for use only with block channel types
     - error during the file read operation
     - EOF encountered on the data file


4.1.9  Close Channel Routine:

     status = close_channel ( chan_id )

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       chan_id   |   int    |   integer*4

     This routine closes the specified channel.  Doing so makes the channel id
available for re-assignment.

Returned value:

     The returned value indicates the error status of the routine.  If no
error occurs, the returned value is 0.  If an error occurs, the value is < 0. 

The following errors are detected:

     - channel number is outside valid range
     - specified channel is not open


4.1.10  Disk Read Error Routines:

     print_disk_read_error ( err_num )            (Callable from FORTRAN)
     error_string = disk_read_error ( err_num )   (No FORTRAN interface yet)

       argument  |  C type  |  FORTRAN type
     ------------+----------+----------------
       err_num   |   int    |   integer *4

     The disk read routines return a value which, when less than zero,
corresponds to an error number.  The disk read error routines provide a way to
turn the error number into an appropriate error message.  The disk_read_error
routine returns a brief error message corresponding to "err_num".  The
"print_disk_read_error" routine prints a more elaborate error message.  These
routines return "No error" for arguments zero or greater and "Bad value for
error number" if "err_num" is not a value from one of the read routines.
