The MACRO and LOOP Processor

Command List Preprocessing

The command list preprocessing programs are used by the system on both the IBM and the VMS/Ultrix versions of MDPP. Their use is essentially the same, with minor exceptions in the cases of one or two extensions available on the DEC systems which are not available in the IBM. The combination of programs constitute an edit of the input command list.

There are two data preprocessing programs: the first is the so-called MACRO processor which processes the equivalent of `subroutine calls' for the preprocessor. The second is the LOOP processor, which interprets the arithmetic expressions and handles looping through parts of the input from the MACRO processor. Although the conventions of the two programs are similar, there are differences, and the user should be careful to avoid confusion between them. On the IBM the two programs are separate and are run by separate JCL commands. On the VAX the two programs have been combined into a single task which runs the two successively.


The MACRO Processor

The preprocessor to the micrograph processing program is designed to allow MACRO definitions which can either be in a MACRO library or declared as instream MACRO's. Libraries are very easy to create; the text editors can be used to create them. These will be dealt with in more detail after the use of instream MACRO's has been discussed.

The main advantage to using MACROs is their convenience. Once a sequence of commands has been shown to be correct, one only need write these as a MACRO once; these lines can then be used by calling the MACRO by name. These macros make the coding of input commands to the micrograph processor a much simpler task.

The versatility in using MACROs arises from their variable symbol capabilities. These symbols are dummy symbols that appear in the lines of text within the MACRO, and are replaced by their corresponding values at the time of the MACRO call. The process of replacing the variable symbols is referred to as expanding a MACRO, and the result of the replacement is a MACRO expansion. Any replacements for an expansion apply only to that expansion; any additional calls have different values for the variable symbols.

All variable symbols begin with the ampersand character, `&', followed by a two digit number from one to ninety-nine. The number refers to the position on the call line of the value used to replace this symbol. A lone ampersand will designate the first value to be used as a replacement, as if it were &1 or &01. For example, &02, &03, &45, &12, and & are all legitimate variable symbols.

In addition to specifing the value that is to be used to replace the variable symbol, these symbols must indicate where the replacement is to go. That is, column alignment must be specified, since much of these symbols are used to pass values to a FORTRAN program using formatted input operations. It is essential that the input line be prepared with the column specifications of the format statement in mind. To accomplish this, the variable symbols also define the fields that are to be used to maintain the needed column alignment. These fields are right-justified; blanks are inserted as necessary on the left, and any excess characters will be truncated from the left.

Each field consists of the variable symbol and all blanks preceeding this symbol. The right-most character of the symbol will be the right-most column used in the expansion. For &04, &14, or &2, this will be the last digit. In the case of the lone ampersand, this character itself will mark the right-most column of its field. There is one exception to this rule that only applies when using nested CALL commands, which will be clarified in the discussion of the CALL command.

An example of a legitimate line of text for a MACRO would be something like:

123456789o123456789o123456789o123456789o123456789o

SV &07 &2 &12 &

The numbers above the line are column numbers. Notice that the variable symbols can be used in any order, and that for the numbers less than ten, either one or two digits may be used to specify that symbol. In any case, the field will end (right-most position) with the last digit used. For this example, four variable symbols defining four fields are used. These fields go from columns 3-10, 11-20, 21-33, and 34-43.

Commands Accepted By MACROS

There are 6 commands accepted by the MACRO processor which guide its functioning. These are MACRO, CALL, LIST, MEND, CMNT, and DFLT. Each command consists of the command starting in column 1 of the line. The program ex

amines the first four columns of each line for the presence of any commands. So only the first four letters of the commands are necessary for the program to recognize them (MACR, CALL, LIST, MEND, CMNT, and DFLT). In fact, any line beginning with any of these four commands in the first four columns will be taken as a command. If a line begins with the word LISTLESS, that line will be taken to be the LIST command. This may create some problems. If a line does not contain any commands, it is written out unchanged. There is one exception to this, the exclamation point. This is described below in more detail in the discussion of the CMNT command.

MACRO This command is followed by at least one space, and then the name of the MACRO. The name may be any eight alpha-numeric characters or any special characters (*,-,+,#, etc.). Of course, the name may be less than 8 characters. This name is used by the program to be able to reference this MACRO by use of the CALL command. See below.

MEND This is the trailer statement for the MACROs. All MACROs must end with this statement.

LIST This is used to get a listing of the output of the preprocessor. It must be the first line in the command list if it is going to be used. Otherwise, the list command will be ignored and no listing will be produced. No parameters are necessary.

DFLT Normally, the replacements for the variable symbols are specified in the call command (see below). Any such symbol replacements not so specified will be replaced by blanks. It is possible to change the default value for any symbol by using the DFLT command. This is done by following the word DFLT by values for the variable symbols, separated by commas. Consecutive commas will skip those elements (their default will remain as the blank.) and only give defaults for the proper elements. For example:

DFLT REP1,REP2,,REP4,,,REP7

Any symbol for &3, or &8, &9 etc., will be replaced by blanks, if not given a value by the CALL statement.

CALL This is the command to call a MACRO. The name of the MACRO is separated from the word CALL by at least one space. Following the name of the MACRO, there must be at least one blank and then the list of the replacements for the variable symbols. Commas are used to separate these replacements, and consecutive commas are allowed. As was said above, any variable symbol not assigned a value by either a DFLT line or here in the CALL command is replaced by blanks. For example:

CALL MAC-1A 1.2,3.5,,LIST OUT,5

This example demonstrates that any character can be used to name a MACRO, and that the list of replacements follows the name, separated by at least one space.

The very nice feature of the CALL command is that nested calls are allowed. A MACRO may call another MACRO except itself (no recursion allowed). The limit of the nesting abilities is approximately 100 levels, depending on how many variable symbol replacements are used for each MACRO. It is not likely that this limit will be exceeded.

Note that the call statement itself may have variable symbols, if it appears in a MACRO definition. The substitutions of the variable symbols in the CALL command do not follow the field definition as given above. That is, the rule that fields are defined by the appearance of the blanks and ampersand and digits is ignored here. The replacing process will occupy as many columns as is necessary to use the entire replacement. No truncation will occur.

Eg.: CALL MAC-2C 1.3,&5,&7,&12,&2

does not define fields of 2 or 3 characters, as would have been thecase elsewhere.

The limit of the length of any line is 80 characters, which may lead to a problem. Since it is likely that a replacement will be longer than the variable symbol specifing it, it is easy to exceed this 80 character limit. No continuation lines are allowed, so the replacement line will have to be shortened if this happens. The program will flag this as an error.

CMNT Comment lines are allowed. Any line beginning with the command CMT is taken as a comment and not processed any further. In addition, comments are allowed on any other line by delimiting the significant text on the line with an exclamation point, !, and then anything that follows is treated as a comment and ignored.

Error Messages

1. WARNING--MACRO NAME FOR MACRO name WAS ORIGINALLY

LONGER THAN 8 CHARACTERS. NAME TRUNCATED TO 8.

This message is an indication that the name of a MACRO has been truncated to eight characters. This may or may not cause a problem. If so, shorten the name to the eight character limit.

2. WARNING--THE MACRO name MACRO IS MULTIPLY DEFINED. FIRST DEFINITION USED. Only one MACRO with any given name is allowed. If duplicate MACROs are defined in the same command list, only the first one will be used to expand CALL's. Rename MACROs as necessary.

3. WARNING--CATLOG EXHAUSTED. ATTEMPT TO DEFINE MORE THAN 100 MACROS. EXTRA MACRO IGNORED. If this is the case, check to see that each MACRO defined is really used. If so, try combining MACROs. If this is not possible, you're out of luck.

4. WARNING--DFLT LINE FOR THE MACRO name MACRO NOT IMMEDIATELY AFTER MACRO DEFINITION STATEMENT. LINE IGNORED. The default line must immediately follow the MACRO command. If not, this message will be issued, and the default values on the line are ignored. All defaults resume to blanks. Rearrange the commands so that this condition is satisfied.

5. WARNING--NO MEND STATEMENT FOR THE MACRO name MACRO. MEND GENERATED. An mend statement will be generated if it is not used, but the recovery process used by this program is inefficient. Try not to rely on it because it will slow down the execution of the program and increase the number of EXCP's used.

6. UNEXPECTED COMMAND ON LINE. LINE IGNORED. This message will be followed by the offending line. It occurs if MEND or DFLT appears outside of a MACRO definition, or if LIST appears as any other statement but the first one.

7. WARNING--TOO MANY NESTED MACROS. MACRO name MACRO IGNORED. Attempt to nest MACROs beyond the limit of 100. Redesign your MACRO structures so as not to exceed the limit.

8. MACRO name MACRO IS UNDEFINED. PROCESSING CONTINUES. The MACRO name appearing in a CALL statement was not found. Expansion not done. Check spelling.

9. CALL MACRO name LINE TOO LONG AFTER REPLACING `&' VARIABLES. LINE TRUNCATED AND PROCESSING CONTINUES. The line limit of 80 characters was exceeded. See above discussion of the CALL command.

Running The Program

The program is run either by including the correct JCL to read the input file and generate the expanded output file for the MDPP (on the IBM), or by requesting that the preprocessing task MCW process the input by an appropriate answer during MDPP startup (on the DEC machines).

Use Of Macro Library Facility

The use of the library facility eliminates the need of entering each MACRO to be used in the input file to the MACRO processor each time it is used. Commonly used macros can be stored in a library, and called as needed. Since the instream MACROs are searched before the library, any library MACRO may be overridden in this manner. But be careful, any other MACRO that calls this MACRO in a nested fashion will now try to expand the new MACRO, instead of the one originally intended. This may lead to errors.

The library file is a file of the macros as they would appear as if they were instream macros. These are typed into a file by one of the text editors like EDT or K52. The file name used to hold this library must be USERLIB.MCW. If the macro processor cannot find a called macro in the input file, it will open the file USERLIB.MCW, located on SY:, and search this file sequentially. It will look for a MACR command with the name of the macro for which it is looking.

If the macro name is not found in USERLIB.MCW, a second library file is opened and sequentially searched. This file is a system libary file, and is in a specific location in a specific user identification code (UIC). The used is: MDPLIB:SYSLIB.MCW. If the macro is not found here, either, then a macro-not-found error message is issued to the terminal. SYSLIB.MCW is also created by a text editor like EDT.

Considerations for the IBM. The IBM is probably not what you need to read about now, since you are running on a DEC machine!! If you need IBM documentation, please read the text version of this file where it has been preserved (for posterity).


The LOOP Processor

The loop processor allows the user to include loops in the input command string, and to process arithmetic expressions. The program is controlled by a set of nine four-letter commands, and the arithmetic line definition character. These are:

LOOP start loop over following code
LEND end loop
RSET direct exit from loop
LOCL generate a local output file (Not on the IBM)
INPT input a line from an external file
GOTO jump to flaged line
FLAG object of a `GOTO'
LLST list the following lines to the output list
NLST stop listing at this point
STOP stop processing here.
TERM terminate processing: last command of the list
= denotes an arithmetic line

Arithmetic Lines and Their Use

In order to make use of looping, you need to be able to do some simple arithmetic. This is done in `arithmetic lines' which are marked for the program by an `=' sign in column one. Arithmetic is performed on constants and variables according to the following rules.

Variables, Constants and Operations.

There are two types of variables called `registers' and `loop parameters'. Currently in the program there are 99 registers and 20 loop parameters. Registers are denoted by symbols like `Xnn' or `Xn', or additionaly `Inn' or `In' (eg. X23, X4, I78, I2). The `I' notation allows a register to be referenced by index; that is to say for example, that the register referenced by `I23' will be the one whose value is stored in register 23. If X23=17 then setting `I23=', or using `I23' in an arithmetic expression will cause `X17' to be updated or used. Putting it another way, register values may be accessed as an array, although you have to use care in doing so. Loop paramters are denoted by symbols like `Lnn' or `Ln' or `Cnn' or `Cn' (eg. L11, L8, C17, C1). The difference between the `L' and the `C' notation will be described below.

Constants are written generally following FORTRAN conventions. Therefore, valid notations are 6, 6., 6.0, 6E0, or .123, 123E-3, 12.3E-2: the first group are all equivalent representations of the number `6', the last group are all equal to `0.123'. If the number is negative, put a minus sign in front of it.

Operations are denoted by single letter symbols such as `+', `-' `*' and `/'; which have the conventional meanings. For a complete list of the active symbols consult the table at the end of the section.

Syntax

As was said above, each arithmetic line must have an `=' in column 1. Then a register designation follows ('X' or `I' notation allowed), another =, and then an arithmetic expression. This expression is not written in algebraic notation, but in reverse Polish notation, RPN, as used by the Hewlett-Packard line of calculators.

The syntax of the arithmetic expressions requires that each component of an expression be separated by commas, including constants, registers, and operators. It is permissible to have more than one calculation on a single input line. To do this, merely separate the calculations by a comma colon comma (,:,), and write the next calculation. This may be repeated until the input line is filled (up to 80 columns long).

Reverse Polish Notation was developed by the polish mathematician Jan Lukasiewicz. It does not use parentheses to indicate the order of operations. Instead, a concept called a stack is used. Also, the notation is called reverse because the operators (+,-,*,/,etc.) follow the operands (numbers or registers), not precede them as our algebraic system requires. For example, to subtract X from Y, algebraic notation would write this as Y-X. RPN would write this as Y,X,-. The rules for all the arithmetic operators are:

algebraicRPN
Y + XY,X,+
Y - XY,X,-
Y + XY,X,+
Y / XY,X,/
Notice that the operands (registers in this case) are in the same order in both notations; only the operators are in the reverse order. The stack refers to a series of sequentially "stacked" registers. Each number, no matter how many digits (in the range 0.5397605E-30 <= !x! <= 0.7237005E+30) will occupy one register. Numbers can only enter or leave from the bottom of the stack. When a number enters the bottom, each element already there rises to the next higher register, and vice-versa when a number is removed from the stack. Pushing a number onto the stack refers to entering a number, while pulling a number does the reverse.

The stack used by this program has 20 registers, allowing 19 levels of nested (parenthesized) operations, which is far beyond any reasonable needs. The bottom-most, or the point of entry or exit from the stack, is called the X register, the one above is the Y register, above that is Z, and the 17 above that are collectively referred to as T (for Top). This can be diagrammed like so:

+--------+

T !________!

! !
Z !________!

! !
Y !________!

! !
X !________!

All of the arithmetic operators require both numbers be in the stack before any computations are done. For example, suppose we wanted to add 34 and 21. This would be entered as 34,21,+. The contents of the stack would be as such. The first number, 34, would enter the X register, then the next number would enter the X register, forcing the number previously there up to the Y register, like so:

+--------+

T !________!

Z ! !
!________!

Y ! 34 !

!________!

X ! 21 !

!________!

Then the addition operation is performed, and the result replaces the addend in the X register. The other addend in the Y register is pulled off the stack, and the contents of all of the registers above X roll down one. The stack after the addition would look like this:

+--------+

T !________!

Z ! !
!________!

Y ! !
!________!

X ! 55 !

!________!

Chain Arithmetic

To perform chain arithmetic, one must remember that these operators still require that both numbers already be on the stack in the X and Y registers. Consider this example: 3/4 - 5*2 + 6*(7 + 8). This would be evaluated in RPN thusly: 3,4,/,5,2,*,-,6,7,8,+,*,+.

+--------+ +--------+ +--------+ +--------+ +--------+

T !________! !________! !________! !________! !________!

! ! ! ! ! ! ! ! ! .75 !

Z !________! !________! !________! !________! !________!

! ! ! 3 ! ! ! ! .75 ! ! 5 !

Y !________! !________! !________! !________! !________!

! 3 ! ! 4 ! ! .75 ! ! 5 ! ! 2 !

X !________! !________! !________! !________! !________!

3 4 / 5 2


+--------+ +--------+ +--------+ +--------+ +--------+

T !________! !________! !________! !________! !________!

! ! ! ! ! ! ! -9.25 ! ! 6 !

Z !________! !________! !________! !________! !________!

! .75 ! ! ! ! -9.25 ! ! 6 ! ! 7 !

Y !________! !________! !________! !________! !________!

! 10 ! ! -9.25 ! ! 6 ! ! 7 ! ! 8 !

X !________! !________! !________! !________! !________!

* - 6 7 8


+--------+ +--------+ +--------+

T !________! !________! !________!

! -9.25 ! ! ! ! !

Z !________! !________! !________!

! 6 ! ! -9.25 ! ! !
Y !________! !________! !________!

! 15 ! ! 90 ! ! 80.75 !

X !________! !________! !________!

+ * +

Note: The T register collectively refers to the top 17 registers, not a single register. Further examples of allowable expressions are:

= X1=X2,L1,+
= X3=X4, :, X5=2.,X6,-
= X5=4.,X1,C1,-,/

These should be interpreted as follows:

X1=X2+L1
X3=X4 X5=2.-X6
X5=4./(X1-C1)

Impermissible expressions would be:

= L2=X1,X2,X3,+,+
= 12.3=X2 = C2=3
= X23=23,+,6

These break the rules as follows:

- Loop variable on LHS of equal sign not allowed, only registers are allowed here.
- Constant on LHS of equal sign.
- Loop variable on LHS of equal sign.
- Incorrect ordering of symbols, X23 would have the value 6 after this.

There are several operators that only operate on the X register. These are the operations like log or sine which do not alter the contents of the Y register or the rest of the stack. Whatever number is in the X register serves as the argument for these functions, and the result replaces the argument in the X register. These operators must also follow the operands, like:

= X1=34,L,:, X2 = 3,4,/,7,8,*,+,C

The `catch' to using RPN is that most errors are not trapped, and the user may get odd results without really understanding what went wrong. So watch it! If you have doubts as to what is happening use the `LLST' command to see what you actually did.

The LOCL Command

This command is available on the PDP only. What it does is to create a file called `MACLOP.OUT' which contains the expanded command list from the processor, and terminates MDPP, which calls the processor, without executing the expanded command list. The same effect is obtined on the IBM by simply terminating the JCL commands after the processing steps, and creating a perminant file, which is trivial.

The restriction on the use of `LOCL' is that it must be the first command recognised by the LOOP processor; which means that the only command which may proceed it in the input command list is the command `LIST', which is processed by the MACRO part of the program. LOCL is very helpful in getting a command list debugged, since it does not send the machine off for 2 hours running a list which contains an easily spotted error.

The LLST and NLST Commands

The LLST command switches on listing of the processed output to the list file in addition to the command file to be used by the MDPP. Listing begins at the line after the LLST command and is terminated by the command NLST Its value is mainly in debugging the loop processor commands. Remember that if you put them in a loop they will generate large amounts of output.

The LOOP, LEND and RSET Commands

A loop is defined by a LOOP command: all the material between it and the LEND with which it is paired will be executed cyclically for the appropriate number of times.

The command is written in the form `LOOP nn' begining in column one. `nn' is the largest value that the loop variable reaches at the end of the loop: the loop variable runs from zero to `nn' (note the difference between this and FORTRAN).

The loop parameter which is varied is defined by the level of the loop. In a case where there are three nested loops the outer loop will have variable `L1', the next `L2', and the inner loop will have the variable `L3'. The user is not free to choose the name of the loop variable; this may seem a little irritating at first, but is easy to get used to. An example follows:

LOOP 6 (L1)
blah blah

LOOP 2 (L2)
blogs blogs

LEND

LOOP 3 (L2)

LOOP 5 (L3)
ying tong iddle i fo

LEND

LEND

LEND

There are four loops defined here, one outer one whose loop variable is `L1', an inner, loop variable `L2'; the loop following it is at the same depth and so has the same loop variable `L2', but it contains yet another loop which is the third in a nest and therefore has a loop variable of `L3'.

This example also illustrates the use of the `LEND' command. An LEND terminates the loop at the greatest depth, subsequent LENDs terminates loops at successivly higher levels; extra LENDs are ignored. The difference with FORTRAN is that a loop does not have its own specified end point, and therefore checking of correct nesting is not done: this is all up to you, the lucky user.

This notation poses a problem in that you are not able to jump out of a loop. This problem is overcome with the RSET command. RSET terminates the current loop irrespective of whether the full number of cycles have been executed or not. If you wish to jump out of the loop you must include the RSET command to close the loop. An example follows:

LOOP 123
program
GOTO I89=0,0,22
LEND
GOTO 33
FLAG 22
RSET
FLAG 33
more program

This convention is fine for a simple program but if MACROs are used there may be problems, since you do not know necessarily what the loop variable will be for a loop within a MACRO. This is overcome by the `C' notation for loop variables. In this convention `C1' is the loop variable of the current deepest loop; `C2' is the variable of the loop at the next higher level, and so on. Since MACROs are not expected to have many loops in them, this convention is not difficult to use; you just have to realise that the names of loop variables will change as the depth of looping changes. If a `C' loop variable is out of range in the negative sense it is set to zero, positive out of range loop variables cause an error.

Since loops rarely get more than a few deep it is unlikely that a typical user will need more than the limit of a nest of 20 deep.

The GOTO and FLAG Commands

The GOTO and FLAG commands are provided to allow the user to execute jumps to various parts of the input text. The GOTO command can be written in two ways: (a) The direct jump, which is written as `GOTO nn', and (b) The conditional jump written as `GOTO Xnn=aa,bb,cc'.

The symbols `nn', `aa', etc. can be of two different types, either numbers like `23' or `6' or alphanumeric symbols like `W2' or `*'. Number-type symbols are called random labels and allow the program to jump to any other part of itself. Of course, a random label can only be used once in a program. The alphanumeric symbols are called downstream labels and they are searched for only downstream from the GOTO which references them. Downstream labels can be reused through the program without limit. There is a limit of 99 random labels from 1 to 99. Downstream labels can be constructed from any combination of characters, excluding those begining with a number or containing a comma or equals sign.

The direct jump (eg GOTO nn) causes a direct jump to the line labeled `FLAG nn'. Only random flags may be located upstream of the GOTO command.

In the conditional jump, `Xnn' is a register name, and `aa', `bb' and `cc' are labels which define FLAG lines. The jump will be to `FLAG aa' if Xnn<0, to `FLAG bb' if Xnn=0 and to `FLAG cc' if Xnn>0. The index register notation (eg `I78') may also be used in the GOTO. Random and downstream labels may be mixed in a GOTO command.

The GOTO and FLAG commands do not cause errors in the execution of

the loop processor: lines which are incorrect are ignored. This is a facility which allows jumps to be made conditional on the provision of an appropriate flag number in a MACRO for example. Therefore syntactically correct lines include `GOTO', `GOTO X8=0,0,12' and `GOTO X12=13,0,5'. In the first case the command will be ignored, in the second and third the conditions where a flag definition number is omitted will cause the program to continue on the next line. A line with just `FLAG' on it will be ignored in all cases.

The INPT Command

The INPT command is used to read a line from any one of 5 external files which the user may open. To use this feature the user puts in a line into a command list `INPT n "string"', where n is a stream number. If stream `n' is not yet open the loop processor requests the user, at the terminal, to provide the name of the file to be opened. Once it has this information the file is opened and a line is read from it. If a string has been included between `"' marks this string is concatenated onto the line read from the input stream. The most obvious use for this is to add strings like `_BI' to file names which are being input from a list for processing. The final input line, after modification, is then processed by the loop processor, and if it is a data line, is transfered to the output. If `n' is zero or blank, `n=1' is assumed.

The INPT command is useful to put into a loop so that variable information can be read in efficiently. For example, if you wish to process a number of particles so as to find their centers you will need to be ablr to enter both the names of the files to be processed, and a first guess at their centers. This information cannot be entered into the loop directly, however, it can be entered into a separate file in a simple manner, and can be picked up by the INPT command as it goes round in the loop.

The TERM Command

The TERM command is the last command in the command list given to the loop processor. It is not an optional extra! so do not omit it. If the command is omitted then the program will end in error and errors may result in the processing of `GOTO' commands.

Replacement of Symbols in The Text

The LOOP processor is useless without a means to get the numbers it calculates into the text being prepared for the MDPP. The loop processor therefore contains an editor which searches the input lines for replacement symbols which indicate which register values are to be written into the text. The format of the output into the line is indicated by the user by the replacement symbol he uses: if `$23' is used the contents of register 23 is to be written out in integer format, if `%45' is written register 45 is output in floating point format, and if `@7' is used register 7 is written out in exponential format.

The field into which the number is written in the text is defined by the number of blanks to the left of the symbol plus the length of the symbol itself: this is the same convention as is used by the MACRO processor with its replacement symbols of the form `&7', for example. Since all arithmetic is done in floating point numbers inside the computer all numbers have a precision limited to 7 figures, and the output of data respects this limit. If the field is too small to accomodate the number, it is trimmed from the left, in the case of integers; from both ends for floating point numbers, and from the right if exponential format is used. There are limits on the field sizes; only integers can be output into a field smaller than 3 characters, and only floating point or integers can be written into a field smaller than 7 characters. If these rules are broken the program uses the appropriate format, which may not be quite as you would like it.

In order to restrict the field sizes the `backslash' character is used as a field delimiting character. It is replaced by a blank in the output, but is recognised as `non-blank' when fields are scanned. It should be used to stop numbers spilling over to the left, which may be necessary since the minus sign of a negative number is always written into the left-most location of the output field. As an example, let X9=17.1 and X82=-56. If the text contains the lines:

FIXED= $9 FLOAT= %9 EXP= @9
FIXED= $82 FLOAT= %82 EXP= @82


These would be replaced by:

FIXED= 17 FLOAT= 17.1 EXP= .171000E 02
FIXED=- 56 FLOAT=- 56. EXP=-.560000E 02

It is also important to know that a crude rounding algorithm is applied to output in integer and exponential formats. This will cause a register with a value of 14.6 to be output in integer format ('$') as 15; ie it will have been rounded up. If this is not what you want use the `F' operation in the arithmetic lines to fix the number before attempting to output it.

The final word is that `$', `%' and `@' are forbidden characters in the command list since they will always be replaced by the program. A single `$' is taken as `$1', so you can avoid register 1 if you want to replace single characters in the output (like the single & in the MACRO processor). Only use the replacement symbols where you want to do replacements, and nowhere else.

Final Programing Hints

The MACRO processor allows nested calls to other MACROs. This is all well and good but it poses problems to the LOOP processor since there are only 99 registers, and no limitations on which of them are used. A hint is to avoid the low numbered registers when registers are used in MACROs. If you use a MACRO to call another MACRO you will have to check that you are not reusing registers that are used in the calling MACRO and which are needed unaltered after the call; this applies to MACROs and the calling program as well of course.

There is a problem with executing GOTOs in a MACRO. Obviously, since there are only a limited number of random labels there is a limit on the flexibility available. A more fundamental problem is that random labels may not be reused. The only really practical option is, therefore, to use downstream labels everywhere. This will be fine in most cases, however if you need to execute a jump upstream of the GOTO you will not be able to do it directly. This can be overcome by using a dummy loop to carry you back to the top of the place you want to go and to repeat the GOTO there. Don't forget to use the RSET command before returning to the main program.

To be frank I doubt that there will be any real problem involved. We have run the MDPP for 8 years so far without ever needing either LOOPs or MACRO and we can continue to do so without problem. However, both procedures offer new ways to avoid errors by getting the calculations done automatically in procedures saved in library, and this makes the initial writing of command list for the MDPP an easier job.

Permissible Operations for the Loop Processor

The LOOP processor recognises a series of commands which the user is

able to utilise for processing arithmetic lines. As mentioned above arithmetic is performed in RPN and utilises a stack of numbers. Each number or register entered in the command string is `pushed' into the bottom of the stack at position 1, and all other stack members are pushed up into higher positions. The line which follows:

= X10=1.,2.,3.

will cause the number `3' to be in location 1, `2' to be in location 2 and `1' to be in location 3 in the stack. Operations always affect locations 1 & 2. If we complete the line

= X10=1.,2.,3.,-,+

then this will correspond to the equation `X10=(2.-3.)+1.' and X10 would have the value 0..


Table of RPN Operations

In the table which follows `X' always refers to the number in the bottom of the stack (position 1), and `Y' refers to the number in the next-to-bottom position (position 2). To repeat what has been already said above, the last number to be pushed into the stack is at the bottom. If the operation is of the general form `Y,X,op' then the result of this operation is placed into X, and, in addition, the stack is `pulled' (compressed) to overwrite the original value of Y with the stack member above it, and all other members are copied down. If the operation is of the type X,op, then the new value is put into X and the stack is not altered. At the end of the command string, the value in the bottom of the stack is copied into the register specified at the begining of the command line. If the stack is not emptied (ie you have screwed up), the other values are ignored; no warning is given of such an error. OK enough talk, here is the table.

OperationFunction Expression
Algebraic ExpressionRPNPull
+addX=Y+XX,Y,+Y
-subtractX=Y-XY,X,-Y
*multiplyX=Y*XY,X,*Y
/divideX=Y/XY,X,/Y
PpermuteswapX&Ynone
EpowerX=Y**XY,X,EY
>maxX=ma<(Y,X)Y,X,>Y
<minX=min(Y,X)Y,X,<Y
Gtransfer of signX=!Y!*sign(X)Y,X,G Y
Mmod Xmod XX,Mnone
DduplicateX=X,Y=XX,D push
RarctanX=atn(Y/X)Y,X,RY
FfixX=fix(!X!)X,Fnone
Llog base eX=ln(X)X,L none
SsineX=sin(X)X,Snone
CcosineX=cos(X)X,Cnone
XexpX=exp(X)x,Xnone
AabsX=abs(X)X,Anone
Yrandom numberX=ranY push
QifX=X,Y,T1X,Y,T1,Z,Q X,Y,T1,Z