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.

Reading a line

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.

Line Input Devices

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:.

Line Input Example

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.