Line Input Processing : readline: and dcodefld:
Application of the readline: macro causes the following processes to take
place. The nucleus reads a line of characters into the character array CHRIP.
These are copied into another buffer CHRIN and converted to upper-case
characters. The leading characters are checked for a recognisable line
identification code (either as a system command or according to the table of
line ID'd supplied as an argument of readline:).
The macro dcodefld: scans the contents of CHRIN and converts non-blank strings
into numeric and coded-alphabetic data which is stored in the real array BUFIN.
The contents of BUFIN are referred to as field data, because each string of
characters on an input line, separated by one or more blanks, is identified by
a separate field number.
These processes illustrate the relative sophistication of apparently simple
macro tools. In this part of the manual, and those that follow, the general
application procedures of the most commonly used macros will be given. Note
that the precise definitions of all system macros is given lateras System Macro
Definitions. For more detailed information on macro applications and working
examples refer to the source files of representative programs such as FC.
To read a line from the standard line input device ioinp: one uses the
instruction
readline:(list,length)
where list is a character table containing line identification codes of lines
which are expected, and length is the length of the character table. Most lines
in the Xtal system are read in this way. In other words, readline: tells the
nucleus routine AA01 which lines it expects to be read at that time. If a line
is encountered with an ID code that is not on the list, the routine AA01 will
usually exit with an error message.
There are exceptions to this process. One of these is that the input line can
be a system control line (i.e. title, remark, copybdf, reset, master, setid,
field, order or finish). The function of these lines has been detailed in the
Primer Section of this manual. The other exception is when the length variable
is set negative. This prevents AA01 from exiting if an input line is not
recognised and enables the calling subroutine to take corrective action.
When the input line does have an ID code matching that in list, an integer is
assigned to the system variable LINID corresponding to the order of the codes
in the list. The calling subroutine uses LINID to apply the data that has been
placed in the character and field buffers CHRIP, CHRIN and BUFIN.
Decoding the character buffer
The character data in CHRIP and CHRIN is converted into field information
which is stored in the floating-point buffer BUFIN. Apart from the line ID
code, all data entered on Xtal lines is usually considered as free format. For
a detailed description of the rules governing free and fixed formats read the
Primer Section of this manual. Each character string separated by one or more
blanks is treated as a separate data field. The ID code is treated as field
zero. The following character strings (scanning left to right) are assigned
field numbers sequentially (except when special field controls such as *n and
$n, or the system control lines field and order, are in force). The contents of
each string in CHRIN is decoded into either a floating-point number or a signal
which specifies the position of an alphanumeric string in CHRIP and CHRIN.
These values are stored in BUFIN.
A floating-point number is distinguished from a character string as described
in the Primer. Both integer and real numbers entered on an input line are
stored in BUFIN as real numbers. Unused or blank fields are stored in BUFIN as
the value of the macro voidflg: (which is defined as -4.E+20). The signal
stored in BUFIN to identify character strings is a floating-point number of the
form -NNMM.E+21. The mantissa NNMM represents packed integers NN and MM which
indicate the position of the first and the last+1 characters, respectively, of
the string.
Note that each of the field data types: real number, voidflg: and string
signal, are floating-point numbers. This is essential for storage in BUFIN and
for later testing and data transfer. More importantly, however, the
floating-point value of voidflg: defines the largest negative number permitted
for input into an Xtal program. Negative numbers that are larger than voidflg:
are interpreted when testing the values of BUFIN as string signals. In other
words, if the value of BUFIN(I) is greater than voidflg: it is considered to be
numerical; if it is less than voidflg: it is considered to a character string
signal. As illustrated in the example below, the values of NN and MM are
readily extracted from the string signal using the macro stringlim:. NN and MM
may then be used to transfer or test the character string as stored in the
array CHRIN.
Each Xtal file is assigned a device number. These numbers are specified
initially using the macros unitinp:, unitpch:, and so on. The device numbers of
all files are stored in the system common array IOUNIT. Details on which file
is assigned to which IOUNIT element are given in the XMACRO file. It is
possible to change the device numbers of the line files internally within a
program. Except for ioinp:, this must be done with extreme care as it can also
effect subsequent calculations.
The macro readline: always causes a line to be read from the device designated
by ioinp:. In some calculations, however, it is necessary to input line data
from more than one device (e.g. the program ADDREF). In such cases, the
programmer may use the macro linestream: to insert a line file temporarily into
the standard input stream. linestream: stores the current value of ioinp: in
the system variable IOIN2 and changes the value of ioinp: to the device number
of new line input file. Readline: will automatically interchange the device
numbers stored in ioinp: and IOIN2 when it detects an end-of-file. The
advantage of this single entry approach to line input is obvious; there is only
one line input stream and the line input screening process is simplified.
In some special situations line data may be input from non-standard devices.
For example, the nucleus error routine AA06 reads the error message file (see
the macro errfile:), and the program CIFIO reads line data from a file with
filename extension cif. In these cases, however, the input files do not contain
the usual Xtal line identifiers and therefore do not require the facilities
provided by readline:.
Here is an example showing a typical sequence of instructions used to read
lines. The basic structure is in three parts:
-
Define the line identifiers using a chardata: statement. This list is
composed of line codes (maximum length of 6 characters) separated by a blank.
The first and last character of the list must be a blank.
-
Read the line with a readline:
-
Use the LINID number to process the contents of the CHRIN and BUFIN
buffers.
chardata:(T5, HKLIN FILIN STORE END )#
chardata:(T6,HKL ISG BDF )#
datastuff:#
..........
REPEAT# Loop over input lines
$(# >>>>>>>>>>>>>>>>>>>>>>>>>> 2
readline:(T5,NT5)# Read a line from ioinp:
IF(LINID==4) BREAK# Exit reading loop on END
.........
IF(LINID==3)# **** process STORE line ****
DO I=1,10# Loop over input fields
$(# >>>>>>>>>>>>>>>>>>>>>>>>>> 7
ifvo:(BUFIN(I)) NEXT# Skip void fields
IF(BUFIN(I)<voidflg:)# Test for string signal
$(# >>>>>>>>>>>>>>>>>>>>>>>>>> 8
stringlim:(I,J,K)# Get string limits in CHRIN
compchar:(CHRIN,J,T6,1,3,4,NT6,K)# Look for a match
..........
$)# <<<<<<<<<<<<<<<<<<<<<<<<<< 8
ELSE QX(MARK4+3)=BUFIN(I)# Store numerical value
$)# <<<<<<<<<<<<<<<<<<<<<<<<<< 7
..........
$)# <<<<<<<<<<<<<<<<<<<<<<<<<< 2
There are several aspects of this example which need clarification;
particularly the use of macros such as ifvo:, stringlim: and compchar:. The
reader will need to refer to the definitions of these macros given later in
this section. The purpose here is simply to show the usual procedure for
reading a series of input lines. Every program uses this mechanism. As a
further example refer to the program FC.