\input cwebmac
% This file is part of the MMIXware package (c) Donald E Knuth 1999
% This material goes at the beginning of all Stanford GraphBase CWEB files

\def\topofcontents{
  \leftline{\sc\today\ at \hours}\bigskip\bigskip
  \centerline{\titlefont\title}}

\font\ninett=cmtt9
\def\botofcontents{\vskip 0pt plus 1filll
    \ninerm\baselineskip10pt
    \noindent\copyright\ 1993 Stanford University
    \bigskip\noindent
    This file may be freely copied and distributed, provided that
    no changes whatsoever are made. All users are asked to help keep
    the Stanford GraphBase files consistent and ``uncorrupted,''
    identical everywhere in the world. Changes are permissible only
    if the modified file is given a new name, different from the names of
    existing files in the Stanford GraphBase, and only if the modified file is
    clearly identified as not being part of that GraphBase.
    (The {\ninett CWEB} system has a ``change file'' facility by
    which users can easily make minor alterations without modifying
    the master source files in any way. Everybody is supposed to use
    change files instead of changing the files.)
    The author has tried his best to produce correct and useful programs,
    in order to help promote computer science research,
    but no warranty of any kind should be assumed.
    \smallskip\noindent
    Preliminary work on the Stanford GraphBase project
    was supported in part by National Science
    Foundation grant CCR-86-10181.}

\def\prerequisite#1{\def\startsection{\noindent
    Important: Before reading {\sc\title},
    please read or at least skim the program for {\sc#1}.\bigskip
    \let\startsection=\stsec\stsec}}
\def\prerequisites#1#2{\def\startsection{\noindent
    Important: Before reading {\sc\title}, please read
    or at least skim the programs for {\sc#1} and {\sc#2}.\bigskip
    \let\startsection=\stsec\stsec}}

\def\title{ERISCAL}

\def\ERISC{\.{ELTE RISC}}
\def\MMIX{\.{MMIX}}
\def\ERISCAL{\.{ERISCAL}}
\def\MMIXAL{\.{MMIXAL}}
\def\Hex#1{\hbox{$^{\scriptscriptstyle\#}$\tt#1}} % experimental hex constant
\def\<#1>{\hbox{$\langle\,$#1$\,\rangle$}}\let\is=\longrightarrow
\def\bull{\smallbreak\textindent{$\bullet$}}




\ifx\exotic+
 \font\heb=heb8 at 10pt
 \font\rus=lhwnr8
 \input unicode
 \unicodeptsize=8pt
\fi


\N{1}{1}Definition of ERISCAL. This program takes input written in \ERISCAL,
the \ERISC\ assembly language, and translates it
into binary files that can be loaded and executed
on \ERISC\ simulators or hardwares. \ERISCAL\ is much simpler
than the ``industrial
strength'' assembly languages that computer manufacturers usually provide,
because it is primarily intended for the simple demonstration programs.
Yet it tries to have enough
features to serve also as the back end of compilers for \CEE/ and other
high-level languages.

Instructions for using the program appear at the end of this document.
First we will discuss the input and output languages in detail; then we'll
consider the translation process, step by step; then we'll put everything
together.

\fi

\M{2}A program in \ERISCAL\ consists of a series of {\it lines}, each of which
usually contains a single instruction. However, lines with no instructions are
possible, and so are lines with two or more instructions.

Each instruction has
three parts called its label field, opcode field, and operand field; these
fields are separated from each other by one or more spaces.
The label field, which is often empty, consists of all characters up to the
first blank space. The opcode field, which is never empty, runs from the first
nonblank after the label to the next blank space. The operand field, which
again might be empty, runs from the next nonblank character (if any) to the
first blank or semicolon that isn't part of a string or character constant.
If the operand field is followed by a semicolon, possibly with intervening
blanks, a new instruction begins immediately after the semicolon; otherwise
the rest of the line is ignored. The end of a line is treated as a blank space
for the purposes of these rules, with the additional proviso that
string or character constants are not allowed to extend from one line to
another.

The label field must begin with a letter or a digit; otherwise the entire
line is treated as a comment. Popular ways to introduce comments,
either at the beginning of a line or after the operand field, are to
precede them by the character \.\% as in \TeX, or by \.{//} as in \CPLUSPLUS/;
\ERISCAL\ is not very particular. However, Lisp-style comments introduced
by single semicolons will fail if they follow an instruction, because
they will be assumed to introduce another instruction.

\fi

\M{3}\ERISCAL\ has no built-in macro capability, nor does it know how to
include header files and such things. But users can run their files
through a standard \CEE/ preprocessor to obtain \ERISCAL\ programs in which
macros and such things have been expanded. (Caution: The preprocessor also
removes \CEE/-style comments, unless it is told not to do so.)
Literate programming tools could also be used for preprocessing.

If a line begins with the special form `\.\# \<integer> \<string>',
this program interprets it as a {\it line directive\/} emitted by a
preprocessor. For example,
$$\leftline{\indent\.{\# 13 "foo.mms"}}$$
means that the following line was line 13 in the user's source file
\.{foo.mms}. Line directives allow us to correlate errors with the
user's original file; we also pass them to the output, for use by
simulators and debuggers.

\fi

\M{4}\ERISCAL\ deals primarily with {\it symbols\/} and {\it constants}, which
it
interprets and combines to form machine language instructions and data.
Constants are simplest, so we will discuss them first.

A {\it decimal constant\/} is a sequence of digits, representing a number in
radix~10. A~{\it hexadecimal constant\/} is a sequence of hexadecimal digits,
preceded by~\.\#, representing a number in radix~16:
$$\vbox{\halign{$#$\hfil\cr
\<digit>\is\.0\mid\.1\mid\.2\mid\.3\mid\.4\mid
\.5\mid\.6\mid\.7\mid\.8\mid\.9\cr
\<hex digit>\is\<digit>\mid\.A\mid\.B\mid\.C\mid\.D\mid\.E\mid\.F\mid
\.a\mid\.b\mid\.c\mid\.d\mid\.e\mid\.f\cr
\<decimal constant>\is\<digit>\mid\<decimal constant>\<digit>\cr
\<hex constant>\is\.\#\<hex digit>\mid\<hex constant>\<hex digit>\cr
}}$$
Constants whose value is $2^{32}$ or more are reduced modulo $2^{32}$.

\fi

\M{5}A {\it character constant\/} is a single character enclosed in
single quote marks; it denotes the {\mc ASCII} or Unicode number
corresponding to that character. For example, \.{'a'}
represents the constant \.{\#61}, also known as~\.{97}. The quoted character
can be
anything except the character that the \CEE/ library calls \.{\\n} or {\it
newline}; that character should be represented as \.{\#a}.
$$\vbox{\halign{$#$\hfil\cr
\<character constant>\is\.'\<single byte character except newline>\.'\cr
\<constant>\is\<decimal constant>\mid\<hex constant>\mid\<character constant>
\cr}}$$
Notice that \.{'''} represents a single quote, the code \.{\#27}; and
\.{'\\'} represents a backslash, the code \.{\#5c}. \ERISCAL~characters are
never ``quoted'' by backslashes as in the \CEE/~language.

In the present implementation
a character constant will always be at most 255, since wyde character
input is not supported.
\ifx\exotic+ But if the input were in Unicode one could write,
say, \.'{\heb\char"40}\.' or \.'{\rus ZH}\.' for \.{\#05d0} or
\.{\#0416}. \fi
The present program
does not support Unicode directly because basic software for inputting and
outputting 16-bit characters was still in a primitive state at the time of
writing. But the data structures below are designed so that a change to
Unicode will not be difficult when the time is ripe.

\fi

\M{6}A {\it string constant\/} like \.{"Hello"} is an abbreviation for
a sequence of one or more character constants separated by commas:
\.{'H','e','l','l','o'}.
Any character except newline or the double quote mark~\."
can appear between the double quotes of a string constant.
\ifx\exotic+ Similarly,
\."\Uni1.08:24:24:-1:20% Unicode char "9ad8
<002000001800000806ffffff00000002004003ffe00300e00300c00300c003ffc0%
0300c02000043ffffe30000e31008c31ffcc3181cc31818c31818c31ff8c31818c3%
0007c300018>%
\thinspace\Uni1.08:24:24:-1:20% Unicode char "5fb7
<1c038018030018030631ffff30060067860446fffe86ccce0ccccc0ccccc18cccc%
18fffc38c00c38001878fffc58040098030818398618b18318b00b19b0081b300c1%
b3ffc181ff8>%
\thinspace\Uni1.08:24:24:-1:20% Unicode char "7eb3
<0601c00e01800c018018018018218231bfff61b187433186ff3186c631860c3186%
18334630332663b6367e341660380600300600300603b0061e3006f03006c030060%
0303e00300c>%
\kern.1em\." is an abbreviation for
\.'\Uni1.08:24:24:-1:20% Unicode char "9ad8
<002000001800000806ffffff00000002004003ffe00300e00300c00300c003ffc0%
0300c02000043ffffe30000e31008c31ffcc3181cc31818c31818c31ff8c31818c3%
0007c300018>%
\.{','}\Uni1.08:24:24:-1:20% Unicode char "5fb7
<1c038018030018030631ffff30060067860446fffe86ccce0ccccc0ccccc18cccc%
18fffc38c00c38001878fffc58040098030818398618b18318b00b19b0081b300c1%
b3ffc181ff8>%
\.{','}\Uni1.08:24:24:-1:20% Unicode char "7eb3
<0601c00e01800c018018018018218231bfff61b187433186ff3186c631860c3186%
18334630332663b6367e341660380600300600300603b0061e3006f03006c030060%
0303e00300c>%
\.' (namely \.{\#9ad8,\#5fb7,\#7eb3}) when Unicode is supported.
\fi

\fi

\M{7}A {\it symbol\/} in \ERISCAL\ is any sequence of letters and digits,
beginning with a letter. A~colon~`\.:' or underscore symbol `\.\_'
is regarded as a letter, for purposes of this definition.
All extended-ASCII characters like `{\tt \'e}',
whose 8-bit code exceeds 126, are also treated as letters.
$$\vbox{\halign{$#$\hfil\cr
\<letter>\is\.A\mid\.B\mid\cdots\mid\.Z\mid\.a\mid\.b\mid\cdots\mid\.z\mid
\.:\mid\.\_\mid\<{character with code value $>126$}>\cr
\<symbol>\is\<letter>\mid\<symbol>\<letter>\mid\<symbol>\<digit>\cr
}}$$

In future implementations, when \ERISCAL\ is used with Unicode,
all wyde characters whose 16-bit code exceeds 126 will be regarded
as letters; thus \ERISCAL\ symbols will be able to involve Greek letters or
Chinese characters or thousands of other glyphs.
\fi

\M{8}A symbol is said to
be {\it fully qualified\/} if it begins with a colon. Every symbol
that is not fully qualified is an abbreviation for the fully qualified
symbol obtained by placing the {\it current prefix\/} in front of it;
the current prefix is always fully qualified. At the beginning of an
\ERISCAL\ program the current prefix is simply the single character~`\.:',
but the user can change it with the \.{PREFIX} command. For example,
$$\vbox{\halign{&\quad\tt#\hfil\cr
ADD&x,y&\% means ADD :x,:y\cr
PREFIX&Foo:&\% current prefix is :Foo:\cr
ADD&x,y&\% means ADD :Foo:x,:Foo:y\cr
PREFIX&Bar:&\% current prefix is :Foo:Bar:\cr
ADD&:x,y&\% means ADD :x,:Foo:Bar:y\cr
PREFIX&:&\% current prefix reverts to :\cr
ADD&x,Foo:Bar:y&\% means ADD :x,:Foo:Bar:y\cr
}}$$
This mechanism allows large programs to avoid conflicts between symbol names,
when parts of the program are independent and/or written by different users.
The current prefix conventionally ends with a colon, but this convention
need not be obeyed.

\fi

\M{9}A {\it local symbol\/} is a decimal digit followed by one of the
letters \.B, \.F, or~\.H, meaning ``backward,'' ``forward,'' or ``here'':
$$\vbox{\halign{$#$\hfill\cr
\<local operand>\is\<digit>\,\.B\mid\<digit>\,\.F\cr
\<local label>\is\<digit>\,\.H\cr
}}$$
The \.B and \.F forms are permitted only in the operand field of \ERISCAL\
instructions; the \.H form is permitted only in the label field. A local
operand such as~\.{2B} stands for the last local label~\.{2H}
in instructions before the current one, or 0 if \.{2H} has not yet appeared
as a label. A~local operand such as~\.{2F} stands
for the first \.{2H} in instructions after the current one. Thus, in a
sequence such as
$$\vbox{\halign{\tt#\cr 2H JMP 2F\cr 2H JMP 2B\cr}}$$
the first instruction jumps to the second and the second jumps to the first.

Local symbols are useful for references to nearby points of a program, in
cases where no meaningful name is appropriate. They can also be useful
in special situations where a redefinable symbol is needed; for example,
an instruction like
$$\.{9H IS 9B+1}$$
will maintain a running counter.

\fi

\M{10}Each symbol receives a value called its {\it equivalent\/} when it
appears in the label field of an instruction; it is said to be {\it defined\/}
after its equivalent has been established. A few symbols, like \.{Fopen},
are predefined because they refer to fixed constants
associated with the \ERISC\ hardware or its rudimentary operating system;
otherwise every symbol should be
defined exactly once. The two appearances of `\.{2H}' in the example
above do not violate this rule, because the second `\.{2H}' is not the
same symbol as the first.

A predefined symbol can be redefined (given a new equivalent). After it
has been redefined it acts like an ordinary symbol and cannot be
redefined again. A complete list of the predefined symbols appears
in the program below.

Equivalents are either {\it pure\/} or {\it register numbers}. A pure
equivalent is an unsigned wyde, but a register number
equivalent is a nybble value, between 0 and~15.
A dollar sign is used to change a pure number into a register number;
for example, `\.{\$15}' means register number~15.

\fi

\M{11}Constants and symbols are combined into {\it expressions\/} in a simple
way:
$$\vbox{\halign{$#$\hfil\cr
\<primary expression>\is\<constant>\mid\<symbol>\mid\<local operand>\mid
\.{@}\mid\cr
\hskip12pc\.(\<expression>\.)\mid\<unary operator>\<primary expression>\cr
\<term>\is\<primary expression>\mid
\<term>\<strong operator>\<primary expression>\cr
\<expression>\is\<term>\mid\<expression>\<weak operator>\<term>\cr
\<unary operator>\is\.*\mid\.+\mid\.-\mid\.\~\mid\.\$\mid\.\&\cr
\<strong operator>\is\.*\mid\./\mid\.{//}\mid\.\%\mid\.{<<}\mid\.{>>}
\mid\.\&\cr
\<weak operator>\is\.+\mid\.-\mid\.{\char'174}\mid\.\^\cr
}}$$
Each expression has a value that is either pure, a register number
or an indirect version of these.
The character \.{@} stands for the current location, which is always pure.
The unary operators
\.*,\.+, \.-, \.\~, \.\$, and \.\& mean, respectively, ``indirectize'',
``relativize,''
``subtract from zero,'' ``complement the bits,'' ``change from pure value
to register number,'' and ``take the serial number.'' Only the first of these,
\.*, can be applied to a register number. The last unary operator, \.\&,
applies only to symbols, and it is of interest primarily to system programmers;
it converts a symbol to the unique positive integer that is used to identify
it in the binary file output by \ERISCAL.  The unusual operator \.+ make a
relative value from a value subtracting the current location from it.
A relative value is useful if we want to add it to the current location;
it is mainly used in the \.{SRC} field of instructions.  Another unusual
operator \.* symple gives the information of the compiler that the value of
this field will be used indirectly, i.e, addressing mode is 3. It main use
is in instruction as \.{SETL} \$4,*\$5 setting \$4 from address contained
in \$5, but it is also used as for example \.{SETL} \$4,*xxxx meaning that
\$4 set from the \$0 relative data \.{xxxx} contained in wyde after the
instruction.

Binary operators come in two flavors, strong and weak. The strong ones
are essentially concerned with multiplication or division: \.{x*y},
\.{x/y}, \.{x//y}, \.{x\%y}, \.{x<<y}, \.{x>>y}, and \.{x\&y}
stand respectively for
$(x\times y)\bmod2^{64}$ (multiplication), $\lfloor x/y\rfloor$ (division),
$\lfloor2^{64}x/y\rfloor$ (fractional division), $x\bmod y$ (remainder),
$(x\times2^y)\bmod2^{64}$ (left~shift), $\lfloor x/2^y\rfloor$
(right shift), and $x\mathbin{\char`\&}y$ (bitwise and) on unsigned wydes.
Division is legal only if $y>0$; fractional division is
legal only if $x<y$. None of the strong binary operations can be
applied to register numbers.

The weak binary operations \.{x+y}, \.{x-y}, \.{x\char'174 y}, and
\.{x\^y} stand respectively for $(x+y)\bmod2^{64}$ (addition),
$(x-y)\bmod2^{64}$ (subtraction), $x\mathbin{\mkern1mu\vert\mkern1mu}y$
(bitwise or), and $x\oplus y$ (bitwise exclusive-or) on
unsigned wydes. These operations can be applied to register
numbers only in four contexts: $\<register>+\<pure>$, $\<pure>+\<register>$,
$\<register>-\<pure>$
and $\<register>-\<register>$. For example, if \.{x} denotes \.{\$1} and
\.{y} denotes \.{\$10}, then \.{x+3} and \.{3+x} denote \.{\$4}, and
\.{y-x} denotes the pure value \.{9}.

Register numbers within expressions are allowed to be
arbitrary wydes, but a register number assigned as the
equivalent of a symbol should not exceed 15.

(Incidentally, one might ask why the designer of \ERISCAL\ did not simply
adopt the existing rules of \CEE/ for expressions. The primary reason is that
the designers of \CEE/ chose to give \.{<<}, \.{>>}, and \.\& a lower
precedence than~\.+; but in \ERISCAL\ we want to be able to write things
like \.{o<<24+x<<16+y<<8+z} or \.{@+yz<<2} or \.{@+(\#100-@)\&\#ff}.
Since the conventions of \CEE/ were inappropriate, it was better
to make a clean break, not pretending to have a close relationship
with that language. The new rules are quite easily memorized,
because \ERISCAL\ has just two levels of precedence, and the strong binary
operations are all essentially multiplicative by nature
while the weak binary operations are essentially additive.)

\fi

\M{12}A symbol is called a {\it future reference\/} until it has been defined.
\ERISCAL\ restricts the use of future references, so that programs can
be assembled quickly in one pass over the input; therefore all
expressions can be evaluated when the \ERISCAL\ processor first sees them.

The restrictions are easily stated: Future references
cannot be used in expressions together with unary or binary operators (except
the unary~\.+, which does nothing); moreover, future references
can appear as operands only in instructions that have relative
addresses (namely branches, probable branches, \.{JMP}, \.{PUSHJ},
\.{GETA}) or in wyde constants (the pseudo-operation \.{OCTA}).
Thus, for example, one can say \.{JMP}~\.{1F} or \.{JMP}~\.{1B-4}, but not
\.{JMP}~\.{1F-4}.

\fi

\M{13}We noted earlier that each \ERISCAL\ instruction contains
a label field, an opcode field, and an operand field. The label field is
either empty or a symbol or local label; when it is nonempty, the
symbol or local label receives an equivalent. The operand field is
either empty or a sequence of expressions separated by commas; when
it is empty, it is equivalent to the simple operand field~`\.0'.
$$\vbox{\halign{$#$\hfil\cr
\<instruction>\is\<label>\<opcode>\<operand list>\cr
\<label>\is\<empty>\mid\<symbol>\mid\<local label>\cr
\<operand list>\is\<empty>\mid\<expression list>\cr
\<expression list>\is\<expression>\mid\<expression list>\.,\<expression>\cr
}}$$

The opcode field contains either a symbolic \ERISC\ operation name (like
\.{ADD}), or an {\it alias operation}, or a {\it pseudo-operation}.
Alias operations are alternate names for \ERISC\ operations whose standard
names are inappropriate in certain contexts.
Pseudo-operations do not correspond
directly to \ERISC\ commands, but they govern the assembly process in
important ways.

There are ?????? alias operations:

\smallskip
$$\vbox{\halign{$#$\hfil\cr
\<opcode>\is\<symbolic \ERISC\ operation>\mid\<alias operation>\cr
\hskip12pc\mid\<pseudo-operation>\cr
\<symbolic \ERISC\ operation>\is\.{LZ}\mid\cdots\mid\.{JMP}\cr
\<alias operation>\is\.{XXX}\mid\cdots\mid\.{ZZZ}\cr
\<pseudo-operation>\is\.{IS}\mid\.{LOC}\mid\.{PREFIX}\mid\.{DATA}\mid
\.{CODE}\mid\.{BSPEC}\mid\.{ESPEC}\mid\.{WYDE}\cr
}}$$

\fi

\M{14}\ERISC\ operations like \.{ADD} require exactly two expressions as
operands.

\fi

\M{15}In all cases when the opcode corresponds to an \ERISC\ operation,
the \ERISCAL\ instruction tells the assembler to carry out three steps:
(1)~Define the equivalent of the label field to be the
current location, if the label is nonempty;
(2)~Evaluate the operands and assemble the specified \ERISC\ instruction into
the current location;
(3)~Increase the current location by~1.

\fi

\M{16}Now let's consider the pseudo-operations, starting with the simplest
cases.

\bull\<label> \.{IS} \<expression>
defines the value of the label to be the value of the expression,
which must not be a future reference. The expression may be
either pure or a register number.

\bull\<label> \.{LOC} \<expression>
first defines the label to be the value of the current location, if the label
is nonempty. Then the current location is changed to the value of the
expression, which must be pure.

\smallskip For example, `\.{LOC} \.{\#1000}' will start assembling subsequent
instructions or data in location whose hexa\-decimal value is \Hex{1000}.
`\.X~\.{LOC}~\.{@+500}' defines \.X to be the address of the first
of 500 bytes in memory; assembly will continue at location $\.X+500$.
The operation of aligning the current location to a multiple of~256,
if it is not already aligned in that way, can be expressed as
`\.{LOC}~\.{@+(256-@)\&255}'.

A less trivial example arises if we want to emit instructions and data into
two separate areas of memory, but we want to intermix them in the
\ERISCAL\ source file. We could start by defining \.{8H} and \.{9H}
to be the starting addresses of the instruction and data segments,
respectively. Then, a sequence of instructions could be enclosed
in `\.{LOC}~\.{8B}; \dots; \.{8H}~\.{IS}~\.{@}'; a sequence of
data could be enclosed in `\.{LOC}~\.{9B}; \dots; \.{9H}~\.{IS}~\.{@}'.
Any number of such sequences could then be combined.
Instead of the two pseudo-instructions `\.{8H}~\.{IS}~\.{@;} \.{LOC}~\.{9B}'
one could in fact write simply `\.{8H}~\.{LOC}~\.{9B}' when
switching from instructions to data.

\bull \.{PREFIX} \<symbol>
redefines the current prefix to be the given symbol (fully qualified).
The label field should be blank.

\fi

\M{17}The next pseudo-operations assemble wydes of data.

\bull \<label> \.{WYDE} \<expression list>
defines the label to be the current location, if the label field is nonempty;
then it assembles one wyde for each expression in the expression list, and
advances the current location by the number of wydes. The expressions
should all be pure numbers that fit in one wyde.

String constants are often used in such expression lists.
For example, if the current location is \Hex{1000}, the instruction
\.{WYDE}~\.{"Hello",0} assembles six wydes containing the constants
\.{'H'}, \.{'e'}, \.{'l'}, \.{'l'}, \.{'o'}, and~\.0 into locations
\Hex{1000}, \dots,~\Hex{1005}, and advances the current location
to \Hex{1006}.

\fi

\M{18}Global registers are important by starting in \ERISC\ programs.
We give starting values to these registers.

\bull \<label> \.{GREG} \<expression>
allocates a new global register, and assigns its number as the
equivalent of the label.
At the beginning of assembly, the current global threshold~G is~\$0.
Each distinct \.{GREG} instruction increases~G by~1.

The value of the expression will be loaded into the global register at
the beginning of the program, except if the ABI of the given operating
system and/or source language does not dictate otherwise.  Register \$0
is always has a defined starting value, the value of the label
\.{:Main}.

When \ERISCAL\ programs use subroutines with a memory stack in
addition to the built-in register stack, they usually begin with the
instructions `\.{sp}~\.{GREG}~\.{0;fp}~\.{GREG}~\.0'; these
instructions allocate a {\it stack pointer\/} \.{sp=\$1} and a {\it
frame pointer\/} \.{fp=\$2}. Usually with `\.{lp}~\.{GREG}\.{0;}' we
also give a name to a {\it link pointer\/} \.{lp=\$3} for return addresses.
However, subroutine libraries are free to implement any conventions
for registers and stacks that they like.

\fi

\M{19}If our program will run on an \ERISC\ processor embedded in hardware
supporting Harvard architecture instead of von Neumann architecture,
we need two more pseudo-instructions.  (In this case we have to use
the \.{-h} compiler option.)

\bull \.{CODE}
ends generating data going to the data
segment and begins generate code going to the code
segment; it has no effect if \.{-h} option is not given.

\bull \.{DATA}
ends generating code going to the code
segment and begins generate data going to the data
segment; it has no effect if \.{-h} option is not given.

Remark that by \.{-h} option there is the possibility also to generate
code into the data segment, but cannot execute there (only
read/write), and there is the possibility to generate data to the code
segment but cannot read/write there, only execute.  Nevertheless,
there is one possibility to write the content of a register \.{\$s}
into the code segment by a `\ \.{PUSH}~\.{\$0,\$s}' instruction and
leter execute it; we does not suggest this trick to use in user
programs, because some operating systems does not save the content of
the code segment by pageing.

\fi

\M{20}Finally, there are two pseudo-instructions to pass information
and hints to the loading routine and/or to debuggers that will be
using the assembled program.

\bull \.{BSPEC} \<expression>
begins ``special mode''; the \<expression> should have a value that
fits in two bytes, and the label field should be blank.

\bull \.{ESPEC}
ends ``special mode''; the operand field is ignored, and the label
field should be blank.

\smallskip\noindent

All material assembled between \.{BSPEC} and \.{ESPEC} is passed
directly to the output, but not loaded as part of the assembled
program.  Ordinary \ERISC\ instructions cannot appear in special mode;
only the pseudo-operations \.{IS}, \.{PREFIX}, \.{WYDE} are
allowed.  The operand of \.{BSPEC} should have a value that fits in a
wyde; this value identifies the kind of data that follows. (For
example, \.{BSPEC}~\.0 might introduce information about subroutine
calling conventions at the current location, and \.{BSPEC}~\.1 might
introduce line numbers from a high-level-language program that was
compiled into the code at the current place.  System routines often
need to pass such information through an assembler to the operating
system, hence \ERISCAL\ provides a general-purpose conduit.)

\fi

\M{21}A program should begin at the special symbolic location \.{Main}
(more precisely, at the address corresponding to
the fully qualified symbol \.{:Main}).
This symbol always has serial number~1, and it must always be defined.

Locations should not receive assembled data more than once.
(More precisely, the loader will load the bitwise~xor of all the
data assembled for each wyde position; but the general rule ``do not load
two things into the same wyde'' is safest.)
All locations that do not receive assembled data are initially zero,
except that the the operating system may put command-line data and
debugger data into data segment above the stack.
(The rudimentary \ERISC\ operating system starts a program
with the number of command-line arguments in and a pointer to
the beginning of an array of argument pointers in stack pointed by \$2.)

\fi

\N{1}{22}Binary ERO output. When the \ERISCAL\ processor assembles a file
called \.{foo.ers}, it produces a binary output file called \.{foo.ero}.
(The suffix \.{ers} stands for ``\ERISC\ symbolic,'' and \.{ero} stands
for ``\ERISC\ object.'') Such \.{ero} files have a simple structure
consisting of a sequence of wydes. Some of the wydes are
instructions to a loading routine; others are data to be loaded.

Loader instructions are distinguished from wydes of data by their
first three (most significant) nybble, which has the special escape-code value
\Hex{0e5}, called \PB{\\{ero}} in the program below. This code value
corresponds
to \ERISC's insruction \.{RESUME}, which is unlikely to occur in wydes of
data. The last nybble of a loader instruction is the loader opcode,
called the {\it lopcode}.

\Y\B\4\D$\\{ero}$ \5
\T{\^0e5}\par
\fi

\M{23}When a wyde of the \.{ero} file does not begin with the escape code,
it is loaded into the current location~$\lambda$, and $\lambda$ is
increased by one.  More exacly, there may be two current locations,
one for code segment, and one for data segment and we may change
between them.  Both start with zero.  The current line number is also
increased by~1, if it is nonzero.

When a wyde does begin with the escape code, its last nybble
is the lopcode defining a loader instruction. There are thirteen lopcodes:

\bull \PB{\\{lop\_quote}}: $\Hex{0}$. Treat the next wyde as
an ordinary wyde, even if it begins with the escape code.

\bull \PB{\\{lop\_seg}}: $\Hex{1}$. Change between data and code segment.

\bull \PB{\\{lop\_skip}}: $\Hex{2}$. Increase the current location by
the next wyde.

\bull \PB{\\{lop\_fixw}}: $\Hex{3}$. Load (by \.{XOR}) the value of the
current location into wyde P, where P~is the 16-bit address defined by
the next wyde.  (The wyde at~P was previously assembled as zero
because of a future reference.)

\bull \PB{\\{lop\_fixr}}: $\Hex{4}$. Load (by \.{XOR}) the next wyde called
$\delta$ into the \.{SRC} field of the wyde in location~P, where P~is
the address that precedes the current location by $\delta$. (This
nybble was previously loaded by an \ERISC\ instruction with a relative
address. Its \.{SRC} field was previously assembled as zero because of
a future reference.)

\bull \PB{\\{lop\_fixwx}}: $\Hex{5}$.  Proceed as in \PB{\\{lop\_fixw}}, but
load the
current location to the other segment.

\bull \PB{\\{lop\_fixrx}}: $\Hex{6}$.  Proceed as in \PB{\\{lop\_fixr}}, but
load the
current location to the other segment.

\bull \PB{\\{lop\_file}}: $\Hex{9}$. Set the current file number to the upper
half of the next wyde and the current line number to~zero.  The lower
half of the next wyde gives the length of the filename. The following
wydes are the characters of the file name.  If this file number has
occurred previously, the file name has length zero.

\bull \PB{\\{lop\_line}}: $\Hex{a}$. Set the current line number to the next
wyde. If the line number is nonzero, the current file and current line
should correspond to the source location that generated the next data
to be loaded, for use in diagnostic messages. (The \ERISCAL\ program
gives precise line numbers to the sources of wydes in code segment,
which tend to be instructions, but not to the sources of wydes
assembled in data segments.)

\bull \PB{\\{lop\_spec}}: $\Hex{b}$. Begin special data of type given by the
next wyde. The subsequent wydes, continuing until the next
loader operation other than \PB{\\{lop\_quote}}, comprise the special data. A
\PB{\\{lop\_quote}} instruction allows wydes of special data to begin with the
escape code.

\bull \PB{\\{lop\_pre}}: $\Hex{c}$. A~\PB{\\{lop\_pre}} instruction, which
defines the
``preamble,'' must be the first wyde of every \.{ero} file. The
higher byte of the next wyde specifies the version number of \.{ero}
format, currently~1; other version numbers may be defined later, but
version~1 should always be supported as described in the present
document.  The lower byte of the next wyde specifies how many wydes
following a \PB{\\{lop\_pre}} command provide additional information that
might be of interest to system routines. If it is nonzero, the first
two wydes of additional information in big endian order records the
time that this \.{ero} file was created, measured in seconds since
00:00:00 Greenwich Mean Time on 1~Jan~1970.

\bull \PB{\\{lop\_post}}: $\Hex{d}$.  This instruction begins the {\it
postamble}, which follows all instructions and data to be loaded. It
causes \$0, $\rm1$, \dots,~\$15 initially set to the values of the
next 16 wydes.

\bull \PB{\\{lop\_stab}}: $\Hex{e}$. This instruction must appear immediately
after the wydes following~\PB{\\{lop\_post}}. It is followed by the symbol
table, which lists the equivalents of all user-defined symbols in a
compact form that will be described later.

\bull \PB{\\{lop\_end}}: $\Hex{f}$. This instruction must be the very last two
wydes of each \.{ero} file. The next wyde gives exactly, how many
wydes must appear between it and the \PB{\\{lop\_stab}} command.  (Therefore a
program can easily find the symbol table without reading forward
through the entire \.{ero} file.)

\smallskip
A separate routine called \.{EROtype} is available to translate
binary \.{ero} files into human-readable form.

\Y\B\4\D$\\{lop\_quote}$ \5
\T{\^0}\C{ the quotation lopcode }\par
\B\4\D$\\{lop\_seg}$ \5
\T{\^1}\C{ the segment change lopcode }\par
\B\4\D$\\{lop\_skip}$ \5
\T{\^2}\C{ the skip lopcode }\par
\B\4\D$\\{lop\_fixw}$ \5
\T{\^3}\C{ the wyde-fix lopcode }\par
\B\4\D$\\{lop\_fixr}$ \5
\T{\^4}\C{ the relative-fix lopcode }\par
\B\4\D$\\{lop\_fixwx}$ \5
\T{\^5}\C{ extended relative-fix lopcode }\par
\B\4\D$\\{lop\_fixrx}$ \5
\T{\^6}\C{ extended relative-fix lopcode }\par
\B\4\D$\\{lop\_file}$ \5
\T{\^9}\C{ the file name lopcode }\par
\B\4\D$\\{lop\_line}$ \5
\T{\^a}\C{ the file position lopcode }\par
\B\4\D$\\{lop\_spec}$ \5
\T{\^b}\C{ the special hook lopcode }\par
\B\4\D$\\{lop\_pre}$ \5
\T{\^c}\C{ the preamble lopcode }\par
\B\4\D$\\{lop\_post}$ \5
\T{\^d}\C{ the postamble lopcode }\par
\B\4\D$\\{lop\_stab}$ \5
\T{\^e}\C{ the symbol table lopcode }\par
\B\4\D$\\{lop\_end}$ \5
\T{\^f}\C{ the end-it-all lopcode }\par
\fi

\M{24}Many readers will have noticed that \ERISCAL\ has no facilities for
relocatable output, nor does \.{ero} format support such features. Knuth's
first drafts of \.{MMIXAL} and \.{mmo} did allow relocatable objects,
with external linkages, but the rules were substantially more complicated and
therefore inconsistent with the goals of {\sl The Art of Computer Programming}.
His \.{MMIXAL} design might actually prove to be superior to the current
practice, now that computer memory is significantly cheaper than it
used to be, because one-pass assembly and loading are extremely fast when
relocatability and external linkages are disallowed. Different program modules
can be assembled together about as fast as they could be linked together under
a relocatable scheme, and they can communicate with each other in much more
flexible ways. Debugging tools are enhanced when open-source libraries are
combined with user programs, and such libraries will certainly improve in
quality when their source form is accessible to a larger community of users.

\fi

\N{1}{25}Basic data types.
This program for the 16-bit ELTE RISC architecture is based on 32-bit
integer arithmetic, because it is essencial to be possible to rewrite
to the \.{scc} compiler running on \ERISC.  The definition of type
\&{wyde} should be changed.

\Y\B\4\X25:Type definitions\X${}\E{}$\6
\&{typedef} \&{unsigned} \&{int} \&{wyde};\C{ assumes that an int is at least
16 bits wide }\6
\&{typedef} \&{unsigned} \&{int} \&{tetra};\C{ assumes that an int is at
exactly 32 bits wide }\6
\&{typedef} \&{enum} ${}\{{}$\1\6
${}\\{false},\39\\{true}{}$\2\6
${}\}{}$\5
\&{bool};\par
\As31, 56, 60, 64, 68\ETs81.
\U137.\fi

\M{26}\B\X26:Global variables\X${}\E{}$\6
\&{wyde} \\{zero\_wyde};\C{ \PB{$\\{zero\_wyde}\K\T{0}$} }\6
\&{wyde} \\{neg\_one}${}\K{-}\T{1}{}$;\C{ \PB{$\\{neg\_one}\K{-}\T{1}$} }\6
\&{wyde} \\{aux};\C{ auxiliary output of a subroutine }\6
\&{bool} \\{overflow};\C{ set by certain subroutines for signed arithmetic }\par
\As34, 37, 38, 44, 47, 48, 53, 58, 62, 65, 69, 75, 82, 89, 104, 116, 134, 140%
\ETs144.
\U137.\fi

\M{27}Left and right shifts are not difficult.

\Y\B\4\X27:Subroutines\X${}\E{}$\6
\&{wyde} \\{shift\_left}\,\,${}\.{ARGS}((\&{wyde},\39\&{int})){}$;\5
\hbox{}\6{}\&{wyde} ${}\\{shift\_left}(\|y,\39\|s{}$)\C{ shift left by $s$
bits, where $0\le s\le16$ }\1\1\6
\&{wyde} \|y;\6
\&{int} \|s;\2\2\6
${}\{{}$\1\6
\&{while} ${}(\|s\G\T{8}){}$\1\5
${}\|y\MRL{{\LL}{\K}}\T{8},\39\|s\MRL{-{\K}}\T{8};{}$\2\6
${}\|y\MRL{{\LL}{\K}}\|s;{}$\6
\&{return} \|y${}\AND\T{\^ffff};{}$\6
\4${}\}{}$\2\7
\&{wyde} \\{shift\_right}\,\,${}\.{ARGS}((\&{wyde},\39\&{int},\39\&{int})){}$;\5
\hbox{}\6{}\&{wyde} ${}\\{shift\_right}(\|y,\39\|s,\39\|u{}$)\C{ shift right,
arithmetically if $u=0$ }\1\1\6
\&{wyde} \|y;\6
\&{int} \|s${},{}$ \|u;\2\2\6
${}\{{}$\1\6
\&{while} ${}(\|s\G\T{8}){}$\1\5
${}\|y\K(\|y\GG\T{8})+(\|u\?\T{0}:{-}((\|y\GG\T{7})\AND\T{\^ff})),\39\|s\MRL{-{%
\K}}\T{8};{}$\2\6
\&{if} (\|s)\1\5
${}\|y\K(\|y\GG\|s)+(\|u\?\T{0}:({-}(\|y\GG\T{7}))\LL(\T{8}-\|s));{}$\2\6
\&{return} \|y;\6
\4${}\}{}$\2\par
\As28, 29, 42, 43, 45, 46, 49, 50, 51, 52, 54, 57, 59, 61, 73\ETs74.
\U137.\fi

\N{1}{28}Multiplication. We need to multiply two unsigned 16-bit integers,
obtaining
an unsigned 32-bit product. It is easy to do this on a 16-bit machine
by using Algorithm 4.3.1M of {\sl Seminumerical Algorithms}, with $b=2^8$.

The following subroutine returns the lower half of the product, and
puts the upper half into a global tetrabyte called \PB{\\{aux}}.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{wyde} \\{wmult}\,\,${}\.{ARGS}((\&{wyde},\39\&{wyde})){}$;\5
\hbox{}\6{}\&{wyde} ${}\\{wmult}(\|y,\39\|z){}$\1\1\6
\&{wyde} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{wyde} \|u${},{}$ \|v${},{}$ \|t;\6
\&{wyde} \\{acc};\7
${}\|u\K\|y\AND\T{\^ff};{}$\6
${}\|v\K\|z\AND\T{\^ff};{}$\6
${}\|t\K\|u*\|v;{}$\6
${}\\{acc}\K\|t\AND\T{\^ff};{}$\6
${}\|t\MRL{{\GG}{\K}}\T{8}{}$;\C{ low times low }\6
${}\|y\MRL{{\GG}{\K}}\T{8};{}$\6
${}\|y\MRL{\AND{\K}}\T{\^ff};{}$\6
${}\|v\MRL{*{\K}}\|y;{}$\6
${}\|v\MRL{+{\K}}\|t;{}$\6
${}\|t\K\|v\AND\T{\^ff};{}$\6
${}\|v\MRL{{\GG}{\K}}\T{8}{}$;\C{ high times low }\6
${}\|z\MRL{{\GG}{\K}}\T{8};{}$\6
${}\|z\MRL{\AND{\K}}\T{\^ff};{}$\6
${}\|u\MRL{*{\K}}\|z;{}$\6
${}\|u\MRL{+{\K}}\|t;{}$\6
${}\|t\K\|u\AND\T{\^ff};{}$\6
${}\|u\MRL{{\GG}{\K}}\T{8}{}$;\C{ low times high }\6
${}\\{aux}\K\|y*\|z;{}$\6
${}\\{aux}\MRL{+{\K}}\|u;{}$\6
${}\\{acc}\MRL{+{\K}}\|t{}$;\C{ high times high }\6
\&{return} \\{acc};\6
\4${}\}{}$\2\par
\fi

\M{29}Division inputs the high half of a dividend in the global
variable~\PB{\\{aux}} and returns the remainder in~\PB{\\{aux}}. Long division
of an
unsigned 32-bit integer by an unsigned 16-bit integer is, of course,
one of the most challenging routines needed for \ERISC\ arithmetic. The
following program, based on Algorithm 4.3.1D of {\sl Seminumerical
Algorithms}, computes wydes $q$ and $r$ such that
$(2^{16}x+y)=qz+r$ and $0\le r<z$, given wydes $x$, $y$, and~$z$,
assuming that $x<z$.  (If $x\ge z$, it simply sets $q=x$ and $r=y$.)
The quotient~$q$ is returned by the subroutine; the remainder~$r$ is
stored in \PB{\\{aux}}.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{wyde} \\{wdiv}\,\,${}\.{ARGS}((\&{wyde},\39\&{wyde},\39\&{wyde})){}$;\5
\hbox{}\6{}\&{wyde} ${}\\{wdiv}(\|x,\39\|y,\39\|z){}$\1\1\6
\&{wyde} \|x${},{}$ \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
\&{int} \|j${},{}$ \|n;\6
\&{wyde} \\{zl}${},{}$ \\{zh}${},{}$ \|c${},{}$ \|q${},{}$ \|m${},{}$ \|t;\7
${}\|x\MRL{\AND{\K}}\T{\^ffff}{}$;\5
${}\|y\MRL{\AND{\K}}\T{\^ffff}{}$;\5
${}\|z\MRL{\AND{\K}}\T{\^ffff};{}$\6
\&{if} ${}(\|x\G\|z{}$)\5
${}\{{}$\5
\1${}\\{aux}\K\|y\AND\T{\^ffff}{}$;\5
\&{return} \|x${}\AND\T{\^ffff}{}$;\5
${}\}{}$\2\6
${}\|n\K\T{0};{}$\6
\&{while} ${}(\R(\|z\AND(\T{1}\LL\T{15}))){}$\5
${}\{{}$\1\6
${}\|z\MRL{{\LL}{\K}}\T{1};{}$\6
${}\|c\K\|y\GG\T{15};{}$\6
${}\|x\MRL{{\LL}{\K}}\T{1};{}$\6
${}\|x\MRL{+{\K}}\|c;{}$\6
${}\|y\MRL{{\LL}{\K}}\T{1};{}$\6
${}\PP\|n;{}$\6
\4${}\}{}$\2\6
${}\\{zl}\K\|z\AND\T{\^ff};{}$\6
${}\|z\MRL{-{\K}}\\{zl};{}$\6
${}\\{zh}\K\|z\GG\T{8};{}$\6
${}\\{aux}\K\T{0};{}$\6
\&{for} ${}(\|j\K\T{1};{}$ ${}\|j\G\T{0};{}$ ${}\|j\MM){}$\5
${}\{{}$\1\6
\&{if} ${}(\|x\G\|z){}$\1\5
${}\|q\K\T{\^ff};{}$\2\6
\&{else}\1\5
${}\|q\K\|x/\\{zh}{}$;\C{approx q-digit }\2\6
${}\|m\K\\{zl}*\|q;{}$\6
${}\|t\K(\|m\AND\T{\^ff})\LL\T{8};{}$\6
${}\|m\GG\T{8}{}$;\C{ q times low part }\6
${}\|c\K\T{0};{}$\6
${}\|t\K\|y-\|t;{}$\6
\&{if} ${}(\|t>\|y){}$\1\5
${}\PP\|c;{}$\2\6
${}\|y\K\|t{}$;\C{ multiple back }\6
${}\|t\K\|x-\|c;{}$\6
${}\|c\K\T{0};{}$\6
\&{if} ${}(\|t>\|x){}$\1\5
${}\PP\|c;{}$\2\6
${}\|x\K\|t-\|m;{}$\6
\&{if} ${}(\|x>\|t){}$\1\5
${}\PP\|c;{}$\2\6
${}\|t\K\|x;{}$\6
${}\|x\K\|t-\\{zh}*\|q;{}$\6
\&{if} ${}(\|x>\|t){}$\1\5
${}\PP\|c;{}$\2\6
\&{while} (\|c)\5
${}\{{}$\C{ add back while carry }\1\6
${}\MM\|q;{}$\6
${}\|t\K\T{0};{}$\6
${}\|y\MRL{+{\K}}(\\{zl}\LL\T{8});{}$\6
\&{if} ${}(\|y<(\\{zl}\LL\T{8})){}$\1\5
${}\PP\|t;{}$\2\6
${}\|x\MRL{+{\K}}\|t;{}$\6
\&{if} ${}(\|x<\|t){}$\1\5
${}\MM\|c;{}$\2\6
${}\|x\MRL{+{\K}}\\{zh};{}$\6
\&{if} ${}(\|x<\\{zh}){}$\1\5
${}\MM\|c;{}$\2\6
\4${}\}{}$\2\6
${}\\{aux}\MRL{{\LL}{\K}}\T{8};{}$\6
${}\\{aux}\MRL{+{\K}}\|q;{}$\6
${}\|x\MRL{{\LL}{\K}}\T{8};{}$\6
${}\|x\MRL{+{\K}}\|y\GG\T{8};{}$\6
${}\|y\MRL{{\LL}{\K}}\T{8};{}$\6
\4${}\}{}$\2\6
${}\|x\MRL{{\GG}{\K}}\|n;{}$\6
\&{return} \|x;\6
\4${}\}{}$\2\par
\fi

\M{30}Here's a rudimentary check to see if arithmetic is in trouble.

\fi

\M{31}Future versions of this program will work with symbols formed from
Unicode
characters, but the present code limits itself to an 8-bit subset.
The type \&{Char} is defined here in order to ease the later transition:
At present, \&{Char} is the same as \&{char}, but
\&{Char} can be changed to a 16-bit type in the Unicode version.

Other changes will also be necessary when the transition to Unicode is made;
for example, some calls of \PB{\\{fprintf}} will become calls of \PB{%
\\{fwprintf}},
and some occurrences of \.{\%s} will become \.{\%ls} in print formats.
The switchable type name \&{Char} provides at least a first step
towards a brighter future with Unicode.

\Y\B\4\X25:Type definitions\X${}\mathrel+\E{}$\6
\&{typedef} \&{char} \&{Char};\C{ bytes that will become wydes some day }\par
\fi

\M{32}While we're talking about classic systems versus future systems, we
might as well define the \PB{\.{ARGS}} macro, which makes function prototypes
available on {\mc ANSI \CEE/} systems without making them
uncompilable on older systems. Each subroutine below is declared first
with a prototype, then with an old-style definition.

\Y\B\4\X32:Preprocessor definitions\X${}\E{}$\6
\8\#\&{ifdef} \.{\_\_STDC\_\_}\6
\8\#\&{define} \.{ARGS}(\\{list}) \5\\{list}\6
\8\#\&{else}\6
\8\#\&{define} \.{ARGS}(\\{list}) \5(\,)\6
\8\#\&{endif}\par
\A40.
\U137.\fi

\N{1}{33}Basic input and output. Input goes into a buffer that is normally
limited to 72 characters. This limit can be raised, by using the
\.{-b} option when invoking the assembler; but short buffers will keep
listings from becoming unwieldy, because a symbolic listing adds 19
characters per~line.

\Y\B\4\X33:Initialize everything\X${}\E{}$\6
\&{if} ${}(\\{buf\_size}<\T{72}){}$\1\5
${}\\{buf\_size}\K\T{72};{}$\2\6
${}\\{buffer}\K{}$(\&{Char} ${}{*}){}$ \\{calloc}${}(\\{buf\_size}+\T{1},\39%
\&{sizeof}(\&{Char}));{}$\6
${}\\{lab\_field}\K{}$(\&{Char} ${}{*}){}$ \\{calloc}${}(\\{buf\_size}+\T{1},%
\39\&{sizeof}(\&{Char}));{}$\6
${}\\{op\_field}\K{}$(\&{Char} ${}{*}){}$ \\{calloc}${}(\\{buf\_size},\39%
\&{sizeof}(\&{Char}));{}$\6
${}\\{operand\_list}\K{}$(\&{Char} ${}{*}){}$ \\{calloc}${}(\\{buf\_size},\39%
\&{sizeof}(\&{Char}));{}$\6
${}\\{err\_buf}\K{}$(\&{Char} ${}{*}){}$ \\{calloc}${}(\\{buf\_size}+\T{60},\39%
\&{sizeof}(\&{Char}));{}$\6
\&{if} ${}(\R\\{buffer}\V\R\\{lab\_field}\V\R\\{op\_field}\V\R\\{operand\_list}%
\V\R\\{err\_buf}){}$\1\5
\\{panic}(\.{"No\ room\ for\ the\ buf}\)\.{fers"});\2\par
\As63, 71, 83, 90\ETs141.
\U137.\fi

\M{34}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{Char} ${}{*}\\{buffer}{}$;\C{ raw input of the current line }\6
\&{Char} ${}{*}\\{buf\_ptr}{}$;\C{ current position within \PB{\\{buffer}} }\6
\&{Char} ${}{*}\\{lab\_field}{}$;\C{ copy of the label field of the current
instruction }\6
\&{Char} ${}{*}\\{op\_field}{}$;\C{ copy of the opcode field of the current
instruction }\6
\&{Char} ${}{*}\\{operand\_list}{}$;\C{ copy of the operand field of the
current instruction }\6
\&{Char} ${}{*}\\{err\_buf}{}$;\C{ place where dynamic error messages are
sprinted }\par
\fi

\M{35}\B\X35:Get the next line of input text, or \PB{\&{break}} if the input
has ended\X${}\E{}$\6
\&{if} ${}(\R\\{fgets}(\\{buffer},\39\\{buf\_size}+\T{1},\39\\{src\_file})){}$%
\1\5
\&{break};\2\6
${}\PP\\{line\_no};{}$\6
${}\\{line\_listed}\K\\{false};{}$\6
${}\|j\K\\{strlen}(\\{buffer});{}$\6
\&{if} ${}(\\{buffer}[\|j-\T{1}]\E\.{'\\n'}){}$\1\5
${}\\{buffer}[\|j-\T{1}]\K\.{'\\0'}{}$;\C{ remove the newline }\2\6
\&{else} \&{if} ${}((\|j\K\\{fgetc}(\\{src\_file}))\I\.{EOF}){}$\1\5
\X36:Flush the excess part of an overlong line\X;\2\6
\&{if} ${}(\\{buffer}[\T{0}]\E\.{'\#'}){}$\1\5
\X39:Check for a line directive\X;\2\6
${}\\{buf\_ptr}\K\\{buffer}{}$;\par
\U137.\fi

\M{36}\B\X36:Flush the excess part of an overlong line\X${}\E{}$\6
${}\{{}$\1\6
\&{while} ${}(\|j\I\.{'\\n'}\W\|j\I\.{EOF}){}$\1\5
${}\|j\K\\{fgetc}(\\{src\_file});{}$\2\6
\&{if} ${}(\R\\{long\_warning\_given}){}$\5
${}\{{}$\1\6
${}\\{long\_warning\_given}\K\\{true};{}$\6
\\{err}(\.{"*trailing\ character}\)\.{s\ of\ long\ input\ line}\)\.{\ have\
been\ dropped"});\6
${}\\{fprintf}(\\{stderr},\39\.{"(say\ `-b\ <number>'\ }\)\.{to\ increase\ the\
leng}\)\.{th\ of\ my\ input\ buffe}\)\.{r)\\n"});{}$\6
\4${}\}{}$\5
\2\&{else}\1\5
\\{err}(\.{"*trailing\ character}\)\.{s\ dropped"});\2\6
\4${}\}{}$\2\par
\U35.\fi

\M{37}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{cur\_file};\C{ index of the current file in \PB{\\{filename}} }\6
\&{int} \\{line\_no};\C{ current position in the file }\6
\&{bool} \\{line\_listed};\C{ have we listed the buffer contents? }\6
\&{bool} \\{long\_warning\_given};\C{ have we given the hint about \.{-b}? }\par
\fi

\M{38}We keep track of source file name and line number at all times, for
error reporting and for synchronization data in the object file.
Up to 256 different source file names can be remembered.

\Y\B\4\X26:Global variables\X${}\mathrel+\E{}$\6
\&{Char} ${}{*}\\{filename}[\T{257}]{}$;\C{ source file names, including those
in line directives }\6
\&{int} \\{filename\_count};\C{ how many \PB{\\{filename}} entries have we
filled? }\par
\fi

\M{39}If the current line is a line directive, it will also be treated
as a comment by the assembler.

\Y\B\4\X39:Check for a line directive\X${}\E{}$\6
${}\{{}$\1\6
\&{for} ${}(\|p\K\\{buffer}+\T{1};{}$ ${}\\{isspace}({*}\|p);{}$ ${}\|p\PP){}$%
\1\5
;\2\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\\{isdigit}({*}\|p);{}$ ${}\|p\PP){}$\1\5
${}\|j\K\T{10}*\|j+{*}\|p-\.{'0'};{}$\2\6
\&{for} ( ; ${}\\{isspace}({*}\|p);{}$ ${}\|p\PP){}$\1\5
;\2\6
\&{if} ${}({*}\|p\E\.{'\\"'}){}$\5
${}\{{}$\1\6
\&{if} ${}(\R\\{filename}[\\{filename\_count}]){}$\5
${}\{{}$\1\6
${}\\{filename}[\\{filename\_count}]\K{}$(\&{Char} ${}{*}){}$ \\{calloc}${}(%
\.{FILENAME\_MAX}+\T{1},\39\&{sizeof}(\&{Char}));{}$\6
\&{if} ${}(\R\\{filename}[\\{filename\_count}]){}$\1\5
\\{panic}(\.{"Capacity\ exceeded:\ }\)\.{Out\ of\ filename\ memo}\)\.{ry"});\2\6
\4${}\}{}$\2\6
\&{for} ${}(\|p\PP,\39\|k\K\T{0};{}$ ${}{*}\|p\W{*}\|p\I\.{'\\"'}\W\|k<%
\.{FILENAME\_MAX};{}$ ${}\|p\PP,\39\|k\PP){}$\1\5
${}\\{filename}[\\{filename\_count}][\|k]\K{*}\|p;{}$\2\6
\&{if} ${}(\|k\E\.{FILENAME\_MAX}){}$\1\5
\\{panic}(\.{"Capacity\ exceeded:\ }\)\.{File\ name\ too\ long"});\2\6
\&{if} ${}({*}\|p\E\.{'\\"'}\W{*}(\|p-\T{1})\I\.{'\\"'}){}$\5
${}\{{}$\C{ yes, it's a line directive }\1\6
${}\\{filename}[\\{filename\_count}][\|k]\K\.{'\\0'};{}$\6
\&{for} ${}(\|k\K\T{0};{}$ ${}\\{strcmp}(\\{filename}[\|k],\39\\{filename}[%
\\{filename\_count}])\I\T{0};{}$ ${}\|k\PP){}$\1\5
;\2\6
\&{if} ${}(\|k\E\\{filename\_count}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{filename\_count}\E\T{256}){}$\1\5
\\{panic}(\.{"Capacity\ exceeded:\ }\)\.{More\ than\ 256\ file\ n}\)\.{ames"});%
\2\6
${}\\{filename\_count}\PP;{}$\6
\4${}\}{}$\2\6
${}\\{cur\_file}\K\|k;{}$\6
${}\\{line\_no}\K\|j-\T{1};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\U35.\fi

\M{40}Archaic versions of the \CEE/ library do not define \PB{\.{FILENAME%
\_MAX}}.

\Y\B\4\X32:Preprocessor definitions\X${}\mathrel+\E{}$\6
\8\#\&{ifndef} \.{FILENAME\_MAX}\6
\8\#\&{define} \.{FILENAME\_MAX} \5\T{256}\6
\8\#\&{endif}\par
\fi

\M{41}\B\X41:Local variables\X${}\E{}$\6
\&{register} \&{Char} ${}{*}\|p,{}$ ${}{*}\|q{}$;\C{ the place where we're
currently scanning }\par
\A67.
\U137.\fi

\M{42}The next several subroutines are useful for preparing a listing of
the assembled results. In such a listing, which the user can request
with a command-line option, we fill the leftmost 19 columns with
a representation of the output that has been assembled from the
input in the buffer. Sometimes the assembled output requires
more than one line, because we have room to output only a tetrabyte per line.

The \PB{\\{flush\_listing\_line}} subroutine is called when we have finished
generating one line's worth of assembled material. Its parameter is
a string to be printed between the assembled material and the
buffer contents, if the input line hasn't yet been echoed. The length
of this string should be 19 minus the number of characters already printed
on the current line of the listing.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{flush\_listing\_line}\,\,\.{ARGS}((\&{char} ${}{*})){}$;\5
\hbox{}\6{}\&{void} \\{flush\_listing\_line}(\|s)\1\1\6
\&{char} ${}{*}\|s;\2\2{}$\6
${}\{{}$\1\6
\&{if} (\\{line\_listed})\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"\\n"});{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{fprintf}(\\{listing\_file},\39\.{"\%s\%s\\n"},\39\|s,\39\\{buffer});{}$\6
${}\\{line\_listed}\K\\{true};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{43}Only the two least significant hex digits of a location are shown on
the listing, unless the other digits have changed. The following subroutine
prints an extra line when a change needs to be shown.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{update\_listing\_loc}\,\,\.{ARGS}((\&{void}));\5
\hbox{}\6{}\&{void} \\{update\_listing\_loc}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{if} ${}(\\{cur\_seg}\I\\{listing\_seg}\V((\\{cur\_loc}\XOR\\{listing\_loc})%
\AND\T{\^ff00})){}$\5
${}\{{}$\1\6
${}\\{fprintf}(\\{listing\_file},\39\.{"\%01x\%04x:"},\39\\{cur\_seg},\39\\{cur%
\_loc});{}$\6
\\{flush\_listing\_line}(\.{"\ \ "});\6
\4${}\}{}$\2\6
${}\\{listing\_seg}\K\\{cur\_seg}{}$;\5
${}\\{listing\_loc}\K\\{cur\_loc};{}$\6
\4${}\}{}$\2\par
\fi

\M{44}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{wyde} \\{cur\_loc};\C{ current location of assembled output }\6
\&{wyde} \\{cur\_seg}${}\K\T{0}{}$;\C{ current segment of assembled output }\6
\&{wyde} \\{cur\_code\_loc};\C{ current location of assembled output }\6
\&{wyde} \\{cur\_data\_loc};\C{ current location of assembled output }\6
\&{wyde} \\{listing\_loc};\C{ current location on the listing }\6
\&{wyde} \\{listing\_seg};\C{ current segment on the listing }\6
\&{unsigned} \&{char} \\{hold\_buf}[\T{4}];\C{ assembled nybbles }\6
\&{unsigned} \&{char} \\{held\_bits};\C{ which nybbles of \PB{\\{hold\_buf}}
are active? }\6
\&{unsigned} \&{char} \\{listing\_bits};\C{ which of them haven't been listed
yet? }\6
\&{bool} \\{spec\_mode};\C{ are we between \PB{\.{BSPEC}} and \PB{\.{ESPEC}}? }%
\6
\&{wyde} \\{spec\_mode\_loc};\C{ number of wydes in the current special output
}\par
\fi

\M{45}When nybbles are assembled, they are placed into the \PB{\\{hold\_buf}}.
Furthermore, \PB{\\{listing\_bits}}
is increased by \PB{$\T{\^10}\LL\|j$} if that nybble is a future reference to
be
resolved later.

The nybbles are held until we need to output them.
The \PB{\\{listing\_clear}} routine lists any that have been held
but not yet shown. It should be called only when \PB{$\\{listing\_bits}\I%
\T{0}$}.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{listing\_clear}\,\,\.{ARGS}((\&{void}));\5
\hbox{}\6{}\&{void} \\{listing\_clear}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{register} \&{int} \|j;\7
\&{if} (\\{spec\_mode})\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"\ \ \ \ \ \ \ \ \ "});{}$\2\6
\&{else}\5
${}\{{}$\1\6
\\{update\_listing\_loc}(\,);\6
${}\\{fprintf}(\\{listing\_file},\39\.{"\%02x:\ "},\39\\{listing\_loc});{}$\6
\4${}\}{}$\2\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\T{4};{}$ ${}\|j\PP){}$\1\6
\&{if} ${}(\\{listing\_bits}\AND(\T{\^10}\LL\|j)){}$\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"x"});{}$\2\6
\&{else}\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"\%01x"},\39(\|j\AND\T{1})\?\\{hold%
\_buf}[\|j\GG\T{1}]\GG\T{4}:\\{hold\_buf}[\|j\GG\T{1}]\AND\T{\^f});{}$\2\2\6
\\{flush\_listing\_line}(\.{"\ \ "});\6
${}\\{listing\_bits}\K\T{0};{}$\6
\4${}\}{}$\2\par
\fi

\M{46}Error messages are written to \PB{\\{stderr}}. If the message begins with
`\.*' it is merely a warning; if it begins with `\.!' it is fatal;
otherwise the error is probably serious enough to make manual correction
necessary, yet it is not tragic. Errors and warnings appear
also on the optional listing file.

\Y\B\4\D$\\{err}(\|m)$ \6
${}\{{}$\5
\1\\{report\_error}(\|m);\5
\&{if} ${}(\|m[\T{0}]\I\.{'*'}){}$\1\5
\&{goto} \\{bypass};\5
\2${}\}{}$\2\par
\B\4\D$\\{derr}(\|m,\|p)$ \6
${}\{{}$\5
\1${}\\{sprintf}(\\{err\_buf},\39\|m,\39\|p);{}$\6
\\{report\_error}(\\{err\_buf});\5
\&{if} ${}(\\{err\_buf}[\T{0}]\I\.{'*'}){}$\1\5
\&{goto} \\{bypass};\5
\2${}\}{}$\2\par
\B\4\D$\\{dderr}(\|m,\|p,\|q)$ \6
${}\{{}$\5
\1${}\\{sprintf}(\\{err\_buf},\39\|m,\39\|p,\39\|q);{}$\6
\\{report\_error}(\\{err\_buf});\5
\&{if} ${}(\\{err\_buf}[\T{0}]\I\.{'*'}){}$\1\5
\&{goto} \\{bypass};\5
\2${}\}{}$\2\par
\B\4\D$\\{panic}(\|m)$ \6
${}\{{}$\5
\1${}\\{sprintf}(\\{err\_buf},\39\.{"!\%s"},\39\|m){}$;\5
\\{report\_error}(\\{err\_buf});\5
${}\}{}$\2\par
\B\4\D$\\{dpanic}(\|m,\|p)$ \6
${}\{{}$\5
\1${}\\{err\_buf}[\T{0}]\K\.{'!'}{}$;\5
${}\\{sprintf}(\\{err\_buf}+\T{1},\39\|m,\39\|p){}$;\5
\\{report\_error}(\\{err\_buf});\5
${}\}{}$\2\par
\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{report\_error}\,\,\.{ARGS}((\&{char} ${}{*})){}$;\5
\hbox{}\6{}\&{void} \\{report\_error}(\\{message})\1\1\6
\&{char} ${}{*}\\{message};\2\2{}$\6
${}\{{}$\1\6
\&{if} ${}(\R\\{filename}[\\{cur\_file}]){}$\1\5
${}\\{filename}[\\{cur\_file}]\K\.{"(nofile)"};{}$\2\6
\&{if} ${}(\\{message}[\T{0}]\E\.{'*'}){}$\1\5
${}\\{fprintf}(\\{stderr},\39\.{"\\"\%s\\",\ line\ \%d\ war}\)\.{ning:\ \%s%
\\n"},\39\\{filename}[\\{cur\_file}],\39\\{line\_no},\39\\{message}+\T{1});{}$%
\2\6
\&{else} \&{if} ${}(\\{message}[\T{0}]\E\.{'!'}){}$\1\5
${}\\{fprintf}(\\{stderr},\39\.{"\\"\%s\\",\ line\ \%d\ fat}\)\.{al\ error:\ %
\%s\\n"},\39\\{filename}[\\{cur\_file}],\39\\{line\_no},\39\\{message}+%
\T{1});{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{fprintf}(\\{stderr},\39\.{"\\"\%s\\",\ line\ \%d:\ \%s}\)\.{!\\n"},\39%
\\{filename}[\\{cur\_file}],\39\\{line\_no},\39\\{message});{}$\6
${}\\{err\_count}\PP;{}$\6
\4${}\}{}$\2\6
\&{if} (\\{listing\_file})\5
${}\{{}$\1\6
\&{if} ${}(\R\\{line\_listed}){}$\1\5
\\{flush\_listing\_line}(\.{"******************\ }\)\.{"});\2\6
\&{if} ${}(\\{message}[\T{0}]\E\.{'*'}){}$\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"************\ warnin}\)\.{g:\ \%s\\n"},%
\39\\{message}+\T{1});{}$\2\6
\&{else} \&{if} ${}(\\{message}[\T{0}]\E\.{'!'}){}$\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"********\ fatal\ erro}\)\.{r:\ \%s!%
\\n"},\39\\{message}+\T{1});{}$\2\6
\&{else}\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"**********\ error:\ \%}\)\.{s!\\n"},\39%
\\{message});{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\\{message}[\T{0}]\E\.{'!'}){}$\1\5
${}\\{exit}({-}\T{2});{}$\2\6
\4${}\}{}$\2\par
\fi

\M{47}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{err\_count};\C{ this many errors were found }\par
\fi

\M{48}Output to the binary \PB{\\{obj\_file}} occurs four nybbles at a time.
The
nybbles are assembled in small buffers, not output as single wyde,
because we want the output to be big-endian even when the assembler
is running on a little-endian machine.

\Y\B\4\D$\\{ero\_write}(\\{buf})$ \5
\&{if} ${}(\\{fwrite}(\\{buf},\39\T{1},\39\T{2},\39\\{obj\_file})\I\T{2})$ $%
\\{dpanic}(\.{"Can't\ write\ on\ \%s"},\39\\{obj\_file\_name}{}$)\par
\Y\B\4\X26:Global variables\X${}\mathrel+\E{}$\6
\&{unsigned} \&{char} \\{lop\_quote\_command}[\T{2}]${}\K\{(\\{ero}\GG\T{4})%
\AND\T{\^ff},\39(\\{ero}\LL\T{4})\AND\T{\^f0}+\\{lop\_quote}\};{}$\6
\&{unsigned} \&{char} \\{ero\_buf}[\T{2}];\6
\&{int} \\{ero\_ptr};\par
\fi

\M{49}\B\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{ero\_clear}\,\,\.{ARGS}((\&{void}));\6
\&{void} \\{ero\_out}\,\,\.{ARGS}((\&{void}));\6
\&{void} \\{ero\_wyde}\,\,\.{ARGS}((\&{wyde}));\6
\&{void} \\{ero\_lop}\,\,${}\.{ARGS}((\&{char},\39{}$\&{unsigned} \&{char}${},%
\39{}$\&{unsigned} \&{char}));\6
\&{void} \\{ero\_lopp}\,\,${}\.{ARGS}((\&{char},\39\&{wyde}));{}$\7
\&{void} \\{ero\_clear}(\,)\C{ clears \PB{\\{hold\_buf}}, when \PB{$\\{held%
\_bits}\I\T{0}$} }\6
${}\{{}$\1\6
\&{if} ${}(\\{hold\_buf}[\T{0}]\E\\{ero}\GG\T{4}\W\\{hold\_buf}[\T{1}]\GG\T{4}%
\E\\{ero}\AND\T{\^f}){}$\1\5
\\{ero\_write}(\\{lop\_quote\_command});\2\6
\\{ero\_write}(\\{hold\_buf});\6
\&{if} ${}(\\{listing\_file}\W\\{listing\_bits}){}$\1\5
\\{listing\_clear}(\,);\2\6
${}\\{held\_bits}\K\T{0};{}$\6
${}\\{hold\_buf}[\T{0}]\K\\{hold\_buf}[\T{1}]\K\T{0};{}$\6
${}\PP\\{ero\_cur\_loc};{}$\6
\&{if} (\\{ero\_line\_no})\1\5
${}\PP\\{ero\_line\_no};{}$\2\6
\4${}\}{}$\2\7
\&{void} \\{ero\_out}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{if} (\\{held\_bits})\1\5
\\{ero\_clear}(\,);\2\6
\\{ero\_write}(\\{ero\_buf});\6
\4${}\}{}$\2\7
\&{void} \\{ero\_wyde}(\|t)\C{ output a wyde }\1\1\6
\&{wyde} \|t;\2\2\6
${}\{{}$\1\6
${}\\{ero\_buf}[\T{0}]\K(\|t\GG\T{8})\AND\T{\^ff}{}$;\5
${}\\{ero\_buf}[\T{1}]\K\|t\AND\T{\^ff};{}$\6
\\{ero\_out}(\,);\6
\4${}\}{}$\2\7
\&{void} \\{ero\_trie\_wyde}(\|t)\C{ output a trie wyde }\1\1\6
\&{wyde} \|t;\2\2\6
${}\{{}$\1\6
${}\\{ero\_buf}[\T{0}]\K(\|t\GG\T{8})\AND\T{\^ff}{}$;\5
${}\\{ero\_buf}[\T{1}]\K\|t\AND\T{\^ff};{}$\6
\\{ero\_out}(\,);\6
${}\PP\\{ero\_ptr};{}$\6
\4${}\}{}$\2\7
\&{void} ${}\\{ero\_lop}(\|x,\39\|y,\39\|z{}$)\C{ output a loader operation }\1%
\1\6
\&{char} \|x;\6
\&{unsigned} \&{char} \|y${},{}$ \|z;\2\2\6
${}\{{}$\1\6
${}\\{ero\_buf}[\T{0}]\K(\\{ero}\GG\T{4})\AND\T{\^ff}{}$;\5
${}\\{ero\_buf}[\T{1}]\K((\\{ero}\LL\T{4})\AND\T{\^f0})+(\|x\AND\T{\^f});{}$\6
\\{ero\_out}(\,);\6
${}\\{ero\_buf}[\T{0}]\K\|y\AND\T{\^ff}{}$;\5
${}\\{ero\_buf}[\T{1}]\K\|z\AND\T{\^ff};{}$\6
\\{ero\_out}(\,);\6
\4${}\}{}$\2\7
\&{void} ${}\\{ero\_lopp}(\|x,\39\\{yz}{}$)\C{ output a loader operation with
wyde operand }\1\1\6
\&{char} \|x;\6
\&{wyde} \\{yz};\2\2\6
${}\{{}$\1\6
${}\\{ero\_buf}[\T{0}]\K(\\{ero}\GG\T{4})\AND\T{\^ff}{}$;\5
${}\\{ero\_buf}[\T{1}]\K((\\{ero}\LL\T{4})\AND\T{\^f0})+(\|x\AND\T{\^f});{}$\6
\\{ero\_out}(\,);\6
${}\\{ero\_buf}[\T{0}]\K(\\{yz}\GG\T{8})\AND\T{\^ff}{}$;\5
${}\\{ero\_buf}[\T{1}]\K\\{yz}\AND\T{\^ff};{}$\6
\\{ero\_out}(\,);\6
\4${}\}{}$\2\par
\fi

\M{50}The \PB{\\{ero\_seg}} subroutine makes the current segment in the object
file
equal to \PB{\\{cur\_seg}}.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{ero\_seg}\,\,\.{ARGS}((\&{void}));\5
\hbox{}\6{}\&{void} \\{ero\_seg}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{if} (\\{held\_bits})\1\5
\\{ero\_clear}(\,);\2\6
\&{if} ${}(\\{ero\_cur\_seg}\I\\{cur\_seg}){}$\1\5
${}\\{ero\_wyde}((\\{ero}\LL\T{4})+\\{lop\_seg});{}$\2\6
${}\\{ero\_cur\_seg}\K\\{cur\_seg};{}$\6
\4${}\}{}$\2\par
\fi

\M{51}The \PB{\\{ero\_loc}} subroutine makes the current location in the object
file
equal to \PB{\\{cur\_loc}}.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{ero\_loc}\,\,\.{ARGS}((\&{void}));\5
\hbox{}\6{}\&{void} \\{ero\_loc}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{wyde} \|w;\7
\\{ero\_seg}(\,);\6
${}\|w\K(\\{cur\_loc}-\\{ero\_cur\_loc})\AND\T{\^ffff};{}$\6
\&{if} (\|w)\1\5
${}\\{ero\_lopp}(\\{lop\_skip},\39\|w);{}$\2\6
${}\\{ero\_cur\_loc}\K\\{cur\_loc};{}$\6
\4${}\}{}$\2\par
\fi

\M{52}Similarly, the \PB{\\{ero\_sync}} subroutine makes sure that the current
file and
line number in the output file agree with \PB{\\{cur\_file}} and \PB{\\{line%
\_no}}.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{ero\_sync}\,\,\.{ARGS}((\&{void}));\5
\hbox{}\6{}\&{void} \\{ero\_sync}(\,)\1\1\2\2\6
${}\{{}$\1\6
\&{register} \&{int} \|j;\6
\&{register} \&{unsigned} \&{char} ${}{*}\|p;{}$\7
\&{if} ${}(\\{cur\_file}\I\\{ero\_cur\_file}){}$\5
${}\{{}$\1\6
\&{if} (\\{filename\_passed}[\\{cur\_file}])\1\5
${}\\{ero\_lop}(\\{lop\_file},\39\\{cur\_file},\39\T{0});{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{ero\_lop}(\\{lop\_file},\39\\{cur\_file},\39\\{strlen}(\\{filename}[%
\\{cur\_file}]));{}$\6
\&{for} ${}(\|p\K\\{filename}[\\{cur\_file}];{}$ ${}{*}\|p;{}$ ${}\|p\PP){}$\5
${}\{{}$\1\6
${}\\{ero\_buf}[\T{0}]\K({*}\|p\GG\T{8})\AND\T{\^ff};{}$\6
${}\\{ero\_buf}[\T{1}]\K{*}\|p\AND\T{\^ff};{}$\6
\\{ero\_out}(\,);\6
\4${}\}{}$\2\6
${}\\{filename\_passed}[\\{cur\_file}]\K\T{1};{}$\6
\4${}\}{}$\2\6
${}\\{ero\_cur\_file}\K\\{cur\_file};{}$\6
${}\\{ero\_line\_no}\K\T{0};{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\\{line\_no}\I\\{ero\_line\_no}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{line\_no}\G\T{\^10000}){}$\1\5
\\{panic}(\.{"I\ can't\ deal\ with\ l}\)\.{ine\ numbers\ exceedin}\)\.{g\
65535"});\2\6
${}\\{ero\_lopp}(\\{lop\_line},\39\\{line\_no});{}$\6
${}\\{ero\_line\_no}\K\\{line\_no};{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{53}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{wyde} \\{ero\_cur\_loc};\C{ current location in the object file }\6
\&{wyde} \\{ero\_cur\_seg};\C{ current segment in the object file }\6
\&{int} \\{ero\_line\_no};\C{ current line number in the \.{ero} output so far
}\6
\&{int} \\{ero\_cur\_file};\C{ index of the current file in the \.{ero} output
so far }\6
\&{char} \\{filename\_passed}[\T{256}];\C{ has a filename been recorded in the
output? }\par
\fi

\M{54}Here is a basic subroutine that assembles a wyde starting at \PB{\\{cur%
\_loc}}.
The \PB{\\{x\_bits}} parameter tells which wydes, if any, are part of
a future reference.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{assemble}\,\,${}\.{ARGS}((\&{wyde},\39{}$\&{unsigned} \&{char}));\5
\hbox{}\6{}\&{void} ${}\\{assemble}(\\{dat},\39\\{x\_bits}){}$\1\1\6
\&{wyde} \\{dat};\6
\&{unsigned} \&{char} \\{x\_bits};\C{ These nybbles will be listed as x }\2\2\6
${}\{{}$\1\6
\&{register} \&{int} \|j${},{}$ \|l;\7
\&{if} (\\{spec\_mode})\1\5
${}\|l\K\\{spec\_mode\_loc};{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\|l\K\\{cur\_loc};{}$\6
\X55:Make sure \PB{\\{cur\_loc}} and \PB{\\{ero\_cur\_loc}} refer to the same
wyde\X;\6
\4${}\}{}$\2\6
${}\\{hold\_buf}[\T{0}]\K(\\{dat}\GG\T{8})\AND\T{\^ff};{}$\6
${}\\{hold\_buf}[\T{1}]\K\\{dat}\AND\T{\^ff};{}$\6
${}\\{listing\_bits}\MRL{{\OR}{\K}}\\{x\_bits}+\T{\^f};{}$\6
${}\\{held\_bits}\K\T{\^f};{}$\6
\&{if} (\\{listing\_file})\1\5
\\{listing\_clear}(\,);\2\6
\\{ero\_clear}(\,);\6
\&{if} (\\{spec\_mode})\1\5
${}\PP\\{spec\_mode\_loc};{}$\2\6
\&{else}\1\5
${}\PP\\{cur\_loc};{}$\2\6
\4${}\}{}$\2\par
\fi

\M{55}\B\X55:Make sure \PB{\\{cur\_loc}} and \PB{\\{ero\_cur\_loc}} refer to
the same wyde\X${}\E{}$\6
\&{if} ${}(\\{cur\_seg}\I\\{ero\_cur\_seg}){}$\1\5
\\{ero\_seg}(\,);\2\6
\&{if} ${}((\\{cur\_loc}\XOR\\{ero\_cur\_loc})\AND\T{\^ffff}){}$\1\5
\\{ero\_loc}(\,);\2\par
\Us54\ET111.\fi

\N{1}{56}The symbol table. Symbols are stored and retrieved by means of
a {\it ternary search trie}, following ideas of Bentley and
Sedgewick. (See {\sl ACM--SIAM Symp.\ on Discrete Algorithms\/ \bf8} (1997),
360--369; R.~Sedgewick, {\sl Algorithms in C\/} (Reading, Mass.:\
Addison--Wesley, 1998), \S15.4.) Each trie node stores a character,
and there are branches to subtries for the cases where a given character
is less than, equal to, or greater than the character in the trie.
There also is a pointer to a symbol table entry if a symbol ends at
the current node.

\Y\B\4\X25:Type definitions\X${}\mathrel+\E{}$\6
\&{typedef} \&{struct} \&{ternary\_trie\_struct} ${}\{{}$\1\6
\&{unsigned} \&{short} \\{ch};\C{ the (possibly wyde) character stored here }\6
\&{struct} \&{ternary\_trie\_struct} ${}{*}\\{left},{}$ ${}{*}\\{mid},{}$
${}{*}\\{right}{}$;\C{ downward
 in the ternary trie }\6
\&{struct} \&{sym\_tab\_struct} ${}{*}\\{sym}{}$;\C{ equivalents of symbols }\2%
\6
${}\}{}$ \&{trie\_node};\par
\fi

\M{57}We allocate trie nodes in chunks of 1000 at a time.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{trie\_node} ${}{*}\\{new\_trie\_node}\,\,\.{ARGS}((\&{void})){}$;\5
\hbox{}\6{}\&{trie\_node} ${}{*}\\{new\_trie\_node}(\,){}$\1\1\2\2\6
${}\{{}$\1\6
\&{register} \&{trie\_node} ${}{*}\|t\K\\{next\_trie\_node};{}$\7
\&{if} ${}(\|t\E\\{last\_trie\_node}){}$\5
${}\{{}$\1\6
${}\|t\K{}$(\&{trie\_node} ${}{*}){}$ \\{calloc}${}(\T{1000},\39\&{sizeof}(%
\&{trie\_node}));{}$\6
\&{if} ${}(\R\|t){}$\1\5
\\{panic}(\.{"Capacity\ exceeded:\ }\)\.{Out\ of\ trie\ memory"});\2\6
${}\\{last\_trie\_node}\K\|t+\T{1000};{}$\6
\4${}\}{}$\2\6
${}\\{next\_trie\_node}\K\|t+\T{1};{}$\6
\&{return} \|t;\6
\4${}\}{}$\2\par
\fi

\M{58}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{trie\_node} ${}{*}\\{trie\_root}{}$;\C{ root of the trie }\6
\&{trie\_node} ${}{*}\\{op\_root}{}$;\C{ root of subtrie for opcodes }\6
\&{trie\_node} ${}{*}\\{next\_trie\_node},{}$ ${}{*}\\{last\_trie\_node}{}$;\C{
allocation control }\6
\&{trie\_node} ${}{*}\\{cur\_prefix}{}$;\C{ root of subtrie for unqualified
symbols }\par
\fi

\M{59}The \PB{\\{trie\_search}} subroutine starts at a given node of the trie
and finds
a given string in its middle subtrie, inserting new nodes if necessary.
The string ends with the first nonletter or nondigit; the location
of the terminating character is stored in global variable~\PB{\\{terminator}}.

\Y\B\4\D$\\{isletter}(\|c)$ \5
$(\\{isalpha}(\|c)\V\|c\E\.{'\_'}\V\|c\E\.{':'}\V{}$(\&{unsigned} \&{int})(%
\|c)${}>\T{126}{}$)\par
\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{trie\_node} ${}{*}\\{trie\_search}\,\,{}$\.{ARGS}((\&{trie\_node} ${}{*},%
\39{}$\&{Char} ${}{*}));{}$\6
\&{Char} ${}{*}\\{terminator}{}$;\C{ where the search ended }\7
\&{trie\_node} ${}{*}\\{trie\_search}(\|t,\39\|s){}$\1\1\6
\&{trie\_node} ${}{*}\|t;{}$\6
\&{Char} ${}{*}\|s;\2\2{}$\6
${}\{{}$\1\6
\&{register} \&{trie\_node} ${}{*}\\{tt}\K\|t;{}$\6
\&{register} \&{Char} ${}{*}\|p\K\|s;{}$\7
\&{while} (\T{1})\5
${}\{{}$\1\6
\&{if} ${}(\R\\{isletter}({*}\|p)\W\R\\{isdigit}({*}\|p)){}$\5
${}\{{}$\1\6
${}\\{terminator}\K\|p{}$;\5
\&{return} \\{tt};\6
\4${}\}{}$\2\6
\&{if} ${}(\\{tt}\MG\\{mid}){}$\5
${}\{{}$\1\6
${}\\{tt}\K\\{tt}\MG\\{mid};{}$\6
\&{while} ${}({*}\|p\I\\{tt}\MG\\{ch}){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\|p<\\{tt}\MG\\{ch}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{tt}\MG\\{left}){}$\1\5
${}\\{tt}\K\\{tt}\MG\\{left};{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{tt}\MG\\{left}\K\\{new\_trie\_node}(\,){}$;\5
${}\\{tt}\K\\{tt}\MG\\{left}{}$;\5
\&{goto} \\{store\_new\_char};\6
\4${}\}{}$\2\6
\4${}\}{}$\5
\2\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\\{tt}\MG\\{right}){}$\1\5
${}\\{tt}\K\\{tt}\MG\\{right};{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\\{tt}\MG\\{right}\K\\{new\_trie\_node}(\,){}$;\5
${}\\{tt}\K\\{tt}\MG\\{right}{}$;\5
\&{goto} \\{store\_new\_char};\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
${}\|p\PP;{}$\6
\4${}\}{}$\5
\2\&{else}\5
${}\{{}$\1\6
${}\\{tt}\MG\\{mid}\K\\{new\_trie\_node}(\,){}$;\5
${}\\{tt}\K\\{tt}\MG\\{mid};{}$\6
\4\\{store\_new\_char}:\5
${}\\{tt}\MG\\{ch}\K{*}\|p\PP;{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\par
\fi

\M{60}Symbol table nodes hold the serial numbers and
equivalents of defined symbols. They also
hold ``fixup information'' for undefined symbols; this will allow the
loader to correct any previously assembled instructions that refer to such
symbols when they are eventually defined.

In the symbol table node for a defined symbol, the \PB{\\{link}} field
has one of the special codes \PB{\.{DEFINED}} or \PB{\.{REGISTER}} or \PB{%
\.{PREDEFINED}}, and the
\PB{\\{equiv}} field holds the defined value. The \PB{\\{serial}} number
is a unique identifier for all user-defined symbols.

In the symbol table node for an undefined symbol, the \PB{\\{equiv}} field
is ignored. The \PB{\\{link}} field
points to the first node of fixup information; that node is, in turn,
a symbol table node that might link to other fixups. The \PB{\\{serial}} number
in a fixup node is either 0 or 1 or 2, meaning respectively ``fixup the
wyde pointed to by \PB{\\{equiv}}'' or ``fixup the relative address in the YZ
field of the instruction pointed to by \PB{\\{equiv}}'' or ``fixup the relative
address in the XYZ field of the instruction pointed to by \PB{\\{equiv}}.''

\Y\B\4\D$\.{DEFINED}$ \5
(\&{sym\_node} ${}{*}){}$ \T{1}\C{ code value for wyde equivalents }\par
\B\4\D$\.{REGISTER}$ \5
(\&{sym\_node} ${}{*}){}$ \T{2}\C{ code value for register-number equivalents }%
\par
\B\4\D$\.{PREDEFINED}$ \5
(\&{sym\_node} ${}{*}){}$ \T{3}\C{ code value for not-yet-used equivalents }\par
\B\4\D$\\{seg\_bit}$ \5
\T{1}\C{ \PB{\\{serial}} code bit for data segment }\par
\B\4\D$\\{nyb\_bit}$ \5
\T{2}\C{ \PB{\\{serial}} code bit for signed nybble fixup }\par
\B\4\D$\\{rel\_bit}$ \5
\T{4}\C{ \PB{\\{serial}} code bit for relative fixup }\par
\Y\B\4\X25:Type definitions\X${}\mathrel+\E{}$\6
\&{typedef} \&{struct} \&{sym\_tab\_struct} ${}\{{}$\1\6
\&{int} \\{serial};\C{ serial number of symbol; type number for fixups }\6
\&{struct} \&{sym\_tab\_struct} ${}{*}\\{link}{}$;\C{ \PB{\.{DEFINED}} status
or link to fixup }\6
\&{wyde} \\{equiv};\C{ the equivalent value }\6
\&{wyde} \\{seg};\C{ the segment: 0 for code, 1 for data, if it is }\2\6
${}\}{}$ \&{sym\_node};\par
\fi

\M{61}The allocation of new symbol table nodes proceeds in chunks, like the
allocation of trie nodes. But in this case we also have the possibility
of reusing old fixup nodes that are no longer needed.

\Y\B\4\D$\\{recycle\_fixup}(\\{pp})$ \5
$\\{pp}\MG\\{link}\K\\{sym\_avail},\39\\{sym\_avail}\K{}$\\{pp}\par
\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{sym\_node} ${}{*}\\{new\_sym\_node}\,\,\.{ARGS}((\&{bool})){}$;\5
\hbox{}\6{}\&{sym\_node} ${}{*}\\{new\_sym\_node}(\\{serialize}){}$\1\1\6
\&{bool} \\{serialize};\C{ should the new node receive a unique serial number?
}\2\2\6
${}\{{}$\1\6
\&{register} \&{sym\_node} ${}{*}\|p\K\\{sym\_avail};{}$\7
\&{if} (\|p)\5
${}\{{}$\1\6
${}\\{sym\_avail}\K\|p\MG\\{link}{}$;\5
${}\|p\MG\\{link}\K\NULL{}$;\5
${}\|p\MG\\{serial}\K\T{0}{}$;\5
${}\|p\MG\\{equiv}\K\\{zero\_wyde}{}$;\5
${}\|p\MG\\{seg}\K\\{zero\_wyde};{}$\6
\4${}\}{}$\5
\2\&{else}\5
${}\{{}$\1\6
${}\|p\K\\{next\_sym\_node};{}$\6
\&{if} ${}(\|p\E\\{last\_sym\_node}){}$\5
${}\{{}$\1\6
${}\|p\K{}$(\&{sym\_node} ${}{*}){}$ \\{calloc}${}(\T{1000},\39\&{sizeof}(%
\&{sym\_node}));{}$\6
\&{if} ${}(\R\|p){}$\1\5
\\{panic}(\.{"Capacity\ exceeded:\ }\)\.{Out\ of\ symbol\ memory}\)\.{"});\2\6
${}\\{last\_sym\_node}\K\|p+\T{1000};{}$\6
\4${}\}{}$\2\6
${}\\{next\_sym\_node}\K\|p+\T{1};{}$\6
\4${}\}{}$\2\6
\&{if} (\\{serialize})\1\5
${}\|p\MG\\{serial}\K\PP\\{serial\_number};{}$\2\6
\&{return} \|p;\6
\4${}\}{}$\2\par
\fi

\M{62}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{serial\_number};\6
\&{sym\_node} ${}{*}\\{sym\_root}{}$;\C{ root of the sym }\6
\&{sym\_node} ${}{*}\\{next\_sym\_node},{}$ ${}{*}\\{last\_sym\_node}{}$;\C{
allocation control }\6
\&{sym\_node} ${}{*}\\{sym\_avail}{}$;\C{ stack of recycled symbol table nodes
}\par
\fi

\M{63}We initialize the trie by inserting all the predefined symbols.
Opcodes are given the prefix \.{\^}, to distinguish them from
ordinary symbols; this character nicely divides uppercase letters from
lowercase letters.

\Y\B\4\X33:Initialize everything\X${}\mathrel+\E{}$\6
$\\{trie\_root}\K\\{new\_trie\_node}(\,);{}$\6
${}\\{cur\_prefix}\K\\{trie\_root};{}$\6
${}\\{op\_root}\K\\{new\_trie\_node}(\,);{}$\6
${}\\{trie\_root}\MG\\{mid}\K\\{op\_root};{}$\6
${}\\{trie\_root}\MG\\{ch}\K\.{':'};{}$\6
${}\\{op\_root}\MG\\{ch}\K\.{'\^'};{}$\6
\X66:Put the \ERISC\ opcodes and \ERISCAL\ pseudo-ops into the trie\X;\6
\X70:Put other predefined symbols into the trie\X;\par
\fi

\M{64}Most of the assembly work can be table driven, based on bits that
are stored as the ``equivalents'' of opcode symbols like \.{\^ADD}.

\Y\B\4\D$\\{arg\_num\_bits}$ \5
\T{\^3}\C{ number of arguments: 0,1,2,>=3? }\par
\B\4\D$\\{immed\_bit}$ \5
\T{\^4}\C{ immediate addressing is allowed? }\par
\B\4\D$\\{dest\_bit}$ \5
\T{\^8}\C{ destination modified  addressing is allowed? }\par
\B\4\D$\\{reg\_bit}$ \5
\T{\^10}\C{ register addressing is allowed? }\par
\B\4\D$\\{indir\_bit}$ \5
\T{\^20}\C{ indirect addressings  is allowed? }\par
\B\4\D$\\{no\_label\_bit}$ \5
\T{\^40}\C{ should the label be blank? }\par
\B\4\D$\\{spec\_bit}$ \5
\T{\^80}\C{ is this opcode allowed in \.{SPEC} mode? }\par
\Y\B\4\X25:Type definitions\X${}\mathrel+\E{}$\6
\&{typedef} \&{struct} ${}\{{}$\1\6
\&{Char} ${}{*}\\{name}{}$;\C{ symbolic opcode }\6
\&{int} \\{bits};\C{ treatment of operands }\2\6
${}\}{}$ \&{op\_spec};\7
\&{typedef} \&{enum} ${}\{{}$\1\6
${}\.{IS}\K\T{\^01},\39\.{LOC},\39\.{PREFIX},\39\.{BSPEC}\K\T{\^11},\39%
\.{ESPEC},\39\.{WYDE},\39\.{GREG}\K\T{\^21},\39\.{CODE},\39\.{DATA}{}$\2\6
${}\}{}$\5
\&{pseudo\_op};\par
\fi

\M{65}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{op\_spec} \\{op\_init\_table}[\,]${}\K\{{}$\6
${}\{\.{"LZ"},\39\T{\^003e}\},\39\{\.{"TRAP"},\39\T{\^e506}\},\39\{%
\.{"RESUME"},\39\T{\^e512}\},\39\{\.{"JMP"},\39\T{\^f43e}\},\39\{\.{"IS"},\39(%
\.{IS}\LL\T{8})+\T{\^81}\},\39\{\.{"LOC"},\39(\.{LOC}\LL\T{8})+\T{\^01}\},\39\{%
\.{"PREFIX"},\39(\.{PREFIX}\LL\T{8})+\T{\^c1}\},\39\{\.{"WYDE"},\39(\.{WYDE}\LL%
\T{8})+\T{\^83}\},{}$\6
${}\{\.{"GREG"},\39(\.{GREG}\LL\T{8})+\T{\^81}\},\39\{\.{"CODE"},\39(\.{CODE}%
\LL\T{8})+\T{\^00}\},\39\{\.{"DATA"},\39(\.{DATA}\LL\T{8})+\T{\^00}\},\39\{%
\.{"BSPEC"},\39(\.{BSPEC}\LL\T{8})+\T{\^41}\},\39\{\.{"ESPEC"},\39(\.{ESPEC}\LL%
\T{8})+\T{\^c0}\}\}{}$;\6
\&{int} \\{op\_init\_size};\C{ the number of items in \PB{\\{op\_init\_table}}
}\par
\fi

\M{66}\B\X66:Put the \ERISC\ opcodes and \ERISCAL\ pseudo-ops into the trie%
\X${}\E{}$\6
$\\{op\_init\_size}\K{}$(\&{sizeof} \\{op\_init\_table})${}/\&{sizeof}(\&{op%
\_spec});{}$\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\\{op\_init\_size};{}$ ${}\|j\PP){}$\5
${}\{{}$\1\6
${}\\{tt}\K\\{trie\_search}(\\{op\_root},\39\\{op\_init\_table}[\|j].%
\\{name});{}$\6
${}\\{pp}\K\\{tt}\MG\\{sym}\K\\{new\_sym\_node}(\\{false});{}$\6
${}\\{pp}\MG\\{link}\K\.{PREDEFINED};{}$\6
${}\\{pp}\MG\\{equiv}\K\\{op\_init\_table}[\|j].\\{bits};{}$\6
${}\\{pp}\MG\\{seg}\K\T{0};{}$\6
\4${}\}{}$\2\par
\U63.\fi

\M{67}\B\X41:Local variables\X${}\mathrel+\E{}$\6
\&{register} \&{trie\_node} ${}{*}\\{tt};{}$\6
\&{register} \&{sym\_node} ${}{*}\\{pp},{}$ ${}{*}\\{qq}{}$;\par
\fi

\M{68}\B\X25:Type definitions\X${}\mathrel+\E{}$\6
\&{typedef} \&{struct} ${}\{{}$\1\6
\&{Char} ${}{*}\\{name};{}$\6
\&{wyde} \|h${},{}$ \|l;\2\6
${}\}{}$\5
\&{predef\_spec};\par
\fi

\M{69}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{predef\_spec} \\{predefs}[\,]${}\K\{\{\.{"Inf"},\39\T{1},\39\T{\^ff00}\},{}$%
\6
${}\{\.{"StdIn"},\39\T{0},\39\T{0}\},\39\{\.{"StdOut"},\39\T{0},\39\T{1}\},\39%
\{\.{"StdErr"},\39\T{0},\39\T{2}\},{}$\6
${}\{\.{"TextRead"},\39\T{0},\39\T{0}\},\39\{\.{"TextWrite"},\39\T{0},\39\T{1}%
\},\39\{\.{"BinaryRead"},\39\T{0},\39\T{2}\},\39\{\.{"BinaryWrite"},\39\T{0},%
\39\T{3}\},\39\{\.{"BinaryReadWrite"},\39\T{0},\39\T{4}\},{}$\6
${}\{\.{"Halt"},\39\T{0},\39\T{0}\},\39\{\.{"Fopen"},\39\T{0},\39\T{1}\},\39\{%
\.{"Fclose"},\39\T{0},\39\T{2}\},\39\{\.{"Fread"},\39\T{0},\39\T{3}\},\39\{%
\.{"Fgets"},\39\T{0},\39\T{4}\},\39\{\.{"Fgetws"},\39\T{0},\39\T{5}\},\39\{%
\.{"Fwrite"},\39\T{0},\39\T{6}\},\39\{\.{"Fputs"},\39\T{0},\39\T{7}\},\39\{%
\.{"Fputws"},\39\T{0},\39\T{8}\},\39\{\.{"Fseek"},\39\T{0},\39\T{9}\},\39\{%
\.{"Ftell"},\39\T{0},\39\T{10}\}\};{}$\6
\&{int} \\{predef\_size};\par
\fi

\M{70}\B\X70:Put other predefined symbols into the trie\X${}\E{}$\6
$\\{predef\_size}\K{}$(\&{sizeof} \\{predefs})${}/\&{sizeof}(\&{predef%
\_spec});{}$\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\\{predef\_size};{}$ ${}\|j\PP){}$\5
${}\{{}$\1\6
${}\\{tt}\K\\{trie\_search}(\\{trie\_root},\39\\{predefs}[\|j].\\{name});{}$\6
${}\\{pp}\K\\{tt}\MG\\{sym}\K\\{new\_sym\_node}(\\{false});{}$\6
${}\\{pp}\MG\\{link}\K\.{PREDEFINED};{}$\6
${}\\{pp}\MG\\{seg}\K\\{harvard}\AND\\{predefs}[\|j].\|h,\39\\{pp}\MG\\{equiv}%
\K\\{predefs}[\|j].\|l;{}$\6
\4${}\}{}$\2\par
\U63.\fi

\M{71}We place \.{Main} into the trie at the beginning of assembly,
so that it will show up as an undefined symbol if the user
specifies no starting point.

\Y\B\4\X33:Initialize everything\X${}\mathrel+\E{}$\6
$\\{trie\_search}(\\{trie\_root},\39\.{"Main"})\MG\\{sym}\K\\{new\_sym\_node}(%
\\{true}){}$;\par
\fi

\M{72}At the end of assembly we traverse the entire symbol table, visiting each
symbol in lexicographic order and transmitting the trie structure to the
output file. We detect any undefined future references at this time.

The order of traversal has a simple recursive pattern: To traverse the subtrie
rooted at~\PB{\|t}, we
$$\vbox{\halign{#\hfil\cr
traverse \PB{$\|t\MG\\{left}$}, if the left subtrie is nonempty;\cr
visit \PB{$\|t\MG\\{sym}$}, if this symbol table entry is present;\cr
traverse \PB{$\|t\MG\\{mid}$}, if the middle subtrie is nonempty;\cr
traverse \PB{$\|t\MG\\{right}$}, if the right subtrie is nonempty.\cr
}}$$
This pattern leads to a compact representation in the \.{ero} file, usually
requiring fewer than two wydes per trie node plus the wydes needed to encode
the equivalents and serial numbers. Each node of the trie is encoded as a
``master wyde'' followed by the encodings of the left subtrie,
character, equivalent, middle subtrie, and right subtrie.  If possible,
we put the character \PB{\\{ch}} and part or all of the equivalent into the
master wyde. The master wyde is the sum of
$$
\vbox{\halign{#\hfil\cr
\Hex{8000}, if the left subtrie is nonempty;\cr
\Hex{4000}, if the middle subtrie is nonempty;\cr
\Hex{2000}, if the right subtrie is nonempty;\cr
\qquad and one of the following values:\cr
\Hex{0xyz}, if the symbol's equivalent is \$0 plus \PB{\|x}\cr
\qquad and the character code is \PB{\\{yz}};\cr
\Hex{1xyz}, if \PB{$\\{xyz}\K(\|s\LL\T{10})+\\{ch}$}, where \PB{\|s}is the
symbol's segment and the\cr
\qquad character code at most 10 bits (so most significant bit of \PB{\|x} is
0);\cr
\Hex{1xyz}, if the symbol is nondefined and \PB{$\\{xyz}\K(\T{1}\LL\T{11})+%
\\{ch}$}, where the\cr
\qquad character code at most 10 bits (so most significant bits of \PB{\|x} are
10);\cr
\Hex{1c0z}, if the symbol's equivalent is \$0 plus \PB{\|z}, and \PB{\\{ch}} is
in a\cr
\qquad separate wyde (so most significant bits of the second wyde are 110);\cr
\Hex{1e0z}, if the symbol's segment is \PB{\|z}, and \PB{\\{ch}} is in separate
wyde;\cr
\qquad (so bits of the second wyde are 1110);\cr
\Hex{1f0z}, if the symbol is nondefined, and \PB{\\{ch}} is in separate wyde;%
\cr
\qquad (so bits of the second wyde are 1111);\cr}}
$$
the character is omitted if the middle subtrie and the equivalent are
both empty.  Symbol equivalents are followed by the serial number,
represented as a wyde.

\fi

\M{73}First we prune the trie by removing all predefined symbols that the
user did not redefine.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{trie\_node} ${}{*}\\{prune}\,\,{}$\.{ARGS}((\&{trie\_node} ${}{*})){}$;\5
\hbox{}\6{}\&{trie\_node} ${}{*}\\{prune}(\|t){}$\1\1\6
\&{trie\_node} ${}{*}\|t;\2\2{}$\6
${}\{{}$\1\6
\&{register} \&{int} \\{useful}${}\K\T{0};{}$\7
\&{if} ${}(\|t\MG\\{sym}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|t\MG\\{sym}\MG\\{serial}){}$\1\5
${}\\{useful}\K\T{1};{}$\2\6
\&{else}\1\5
${}\|t\MG\\{sym}\K\NULL;{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\|t\MG\\{left}){}$\5
${}\{{}$\1\6
${}\|t\MG\\{left}\K\\{prune}(\|t\MG\\{left});{}$\6
\&{if} ${}(\|t\MG\\{left}){}$\1\5
${}\\{useful}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\|t\MG\\{mid}){}$\5
${}\{{}$\1\6
${}\|t\MG\\{mid}\K\\{prune}(\|t\MG\\{mid});{}$\6
\&{if} ${}(\|t\MG\\{mid}){}$\1\5
${}\\{useful}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
\&{if} ${}(\|t\MG\\{right}){}$\5
${}\{{}$\1\6
${}\|t\MG\\{right}\K\\{prune}(\|t\MG\\{right});{}$\6
\&{if} ${}(\|t\MG\\{right}){}$\1\5
${}\\{useful}\K\T{1};{}$\2\6
\4${}\}{}$\2\6
\&{if} (\\{useful})\1\5
\&{return} \|t;\2\6
\&{else}\1\5
\&{return} ${}\NULL;{}$\2\6
\4${}\}{}$\2\par
\fi

\M{74}Then we output the trie by following the recursive traversal pattern.

\Y\B\4\X27:Subroutines\X${}\mathrel+\E{}$\6
\&{void} \\{out\_stab}\,\,\.{ARGS}((\&{trie\_node} ${}{*})){}$;\5
\hbox{}\6{}\&{void} \\{out\_stab}(\|t)\1\1\6
\&{trie\_node} ${}{*}\|t;\2\2{}$\6
${}\{{}$\1\6
\&{register} \&{int} \|m${}\K\T{0}{}$;\C{ master wyde }\6
\&{register} \&{int} \|s${}\K\T{1}{}$;\C{ defined serial? }\6
\&{register} \&{int} \|c${}\K\T{1}{}$;\C{ out character in separate wyde? }\6
\&{register} \&{sym\_node} ${}{*}\\{pp};{}$\7
\&{if} ${}(\|t\MG\\{ch}>\T{\^3ff}){}$\1\5
${}\|m\MRL{+{\K}}\T{\^1f00};{}$\2\6
\&{else}\1\5
${}\|m\MRL{+{\K}}\|t\MG\\{ch},\39\|c\K\T{0};{}$\2\6
\&{if} ${}(\|t\MG\\{left}){}$\1\5
${}\|m\MRL{+{\K}}\T{\^8000};{}$\2\6
\&{if} ${}(\|t\MG\\{mid}){}$\1\5
${}\|m\MRL{+{\K}}\T{\^4000};{}$\2\6
\&{if} ${}(\|t\MG\\{right}){}$\1\5
${}\|m\MRL{+{\K}}\T{\^2000};{}$\2\6
\&{if} ${}(\|t\MG\\{sym}){}$\5
${}\{{}$\1\6
\&{if} ${}(\|t\MG\\{sym}\MG\\{link}\E\.{REGISTER}){}$\1\6
\&{if} ${}(\|t\MG\\{ch}<\T{\^ff}){}$\1\5
${}\|m\MRL{+{\K}}\T{\^1000}+\|t\MG\\{ch}+(((\|t\MG\\{sym}\MG\\{equiv})\AND\T{%
\^f})\LL\T{7}),\39\|c\K\T{0};{}$\2\6
\&{else}\1\5
${}\|m\MRL{+{\K}}\T{\^1c00}+((\|t\MG\\{sym}\MG\\{equiv})\AND\T{\^f});{}$\2\2\6
\&{else} \&{if} ${}(\|t\MG\\{sym}\MG\\{link}\E\.{DEFINED}){}$\1\6
\&{if} ${}(\|t\MG\\{ch}<\T{\^3ff}){}$\1\5
${}\|m\MRL{+{\K}}\T{\^1800}+(\|t\MG\\{sym}\MG\\{seg}\LL\T{10})+\|t\MG\\{ch},\39%
\|c\K\T{0};{}$\2\6
\&{else}\1\5
${}\|m\MRL{+{\K}}\T{\^1e00}+\|t\MG\\{sym}\MG\\{seg};{}$\2\2\6
\&{else} \&{if} ${}(\|t\MG\\{sym}\MG\\{link}\V\|t\MG\\{sym}\MG\\{serial}\E%
\T{1}){}$\1\5
\X78:Report an undefined symbol\X\2\6
\&{else}\1\5
${}\|s\K\T{0};{}$\2\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\|s\K\T{0};{}$\2\6
\\{ero\_trie\_wyde}(\|m);\6
\&{if} ${}(\|t\MG\\{left}){}$\1\5
${}\\{out\_stab}(\|t\MG\\{left});{}$\2\6
\&{if} ${}(\|m\AND\T{\^4000}\V\|c\V\|s){}$\1\5
\X76:Visit \PB{\|t} and traverse \PB{$\|t\MG\\{mid}$}\X;\2\6
\&{if} ${}(\|t\MG\\{right}){}$\1\5
${}\\{out\_stab}(\|t\MG\\{right});{}$\2\6
\4${}\}{}$\2\par
\fi

\M{75}We make room for symbols up to 999 bytes long. Strictly speaking,
the program should check if this limit is exceeded; but really!

\Y\B\4\X26:Global variables\X${}\mathrel+\E{}$\6
\&{Char} \\{sym\_buf}[\T{1000}];\6
\&{Char} ${}{*}\\{sym\_ptr}{}$;\par
\fi

\M{76}A global variable called \PB{\\{sym\_buf}} holds all characters on middle
branches to
the current trie node; \PB{\\{sym\_ptr}} is the first currently unused
character in \PB{\\{sym\_buf}}.

\Y\B\4\X76:Visit \PB{\|t} and traverse \PB{$\|t\MG\\{mid}$}\X${}\E{}$\6
${}\{{}$\1\6
\&{if} (\|c)\1\5
${}\\{ero\_trie\_wyde}(\|t\MG\\{ch});{}$\2\6
${}{*}\\{sym\_ptr}\PP\K(\|t\MG\\{ch}>\T{\^ff}\?\.{'?'}:\|t\MG\\{ch}){}$;\C{
Unicode? not yet }\6
\&{if} ${}(\|s\W\|t\MG\\{sym}\MG\\{link}){}$\5
${}\{{}$\1\6
\&{if} (\\{listing\_file})\1\5
\X77:Print symbol \PB{\\{sym\_buf}} and its equivalent\X;\2\6
${}\\{ero\_trie\_wyde}(\|t\MG\\{sym}\MG\\{serial});{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\|t\MG\\{mid}){}$\1\5
${}\\{out\_stab}(\|t\MG\\{mid});{}$\2\6
${}\\{sym\_ptr}\MM;{}$\6
\4${}\}{}$\2\par
\U74.\fi

\M{77}The initial `\.:' of each fully qualified symbol is omitted here, since
most
users of \ERISCAL\ will probably not need the \.{PREFIX} feature. One
consequence of this omission is that the one-character symbol~`\.:'
itself, which is allowed by the rules of \ERISCAL, is printed as the null
string.

\Y\B\4\X77:Print symbol \PB{\\{sym\_buf}} and its equivalent\X${}\E{}$\6
${}\{{}$\1\6
${}{*}\\{sym\_ptr}\K\.{'\\0'};{}$\6
${}\\{fprintf}(\\{listing\_file},\39\.{"\ \%s\ =\ "},\39\\{sym\_buf}+\T{1});{}$%
\6
${}\\{pp}\K\|t\MG\\{sym};{}$\6
\&{if} ${}(\\{pp}\MG\\{link}\E\.{DEFINED}){}$\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"\#\%01x\%04x"},\39\\{pp}\MG\\{seg},\39%
\\{pp}\MG\\{equiv});{}$\2\6
\&{else} \&{if} ${}(\\{pp}\MG\\{link}\E\.{REGISTER}){}$\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"\$\%02d"},\39\\{pp}\MG\\{equiv});{}$\2\6
\&{else}\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"?"});{}$\2\6
${}\\{fprintf}(\\{listing\_file},\39\.{"\ (\%d)\\n"},\39\\{pp}\MG%
\\{serial});{}$\6
\4${}\}{}$\2\par
\U76.\fi

\M{78}\B\X78:Report an undefined symbol\X${}\E{}$\6
${}\{{}$\1\6
${}{*}\\{sym\_ptr}\K(\|t\MG\\{ch}>\T{\^ff}\?\.{'?'}:\|t\MG\\{ch}){}$;\C{
Unicode? not yet }\6
${}{*}(\\{sym\_ptr}+\T{1})\K\.{'\\0'};{}$\6
${}\\{fprintf}(\\{stderr},\39\.{"undefined\ symbol:\ \%}\)\.{s\\n"},\39\\{sym%
\_buf}+\T{1});{}$\6
${}\\{err\_count}\PP,\39\|s\K\T{0};{}$\6
\&{if} ${}(\|t\MG\\{ch}<\T{\^3ff}){}$\1\5
${}\|m\MRL{+{\K}}\T{\^1800}+\|t\MG\\{ch},\39\|c\K\T{1};{}$\2\6
\&{else}\1\5
${}\|m\MRL{+{\K}}\T{\^1fff};{}$\2\6
\4${}\}{}$\2\par
\U74.\fi

\M{79}\B\X79:Check and output the trie\X${}\E{}$\6
$\\{op\_root}\MG\\{mid}\K\NULL{}$;\C{ annihilate all the opcodes }\6
\\{prune}(\\{trie\_root});\6
${}\\{sym\_ptr}\K\\{sym\_buf};{}$\6
\&{if} (\\{listing\_file})\1\5
${}\\{fprintf}(\\{listing\_file},\39\.{"\\nSymbol\ table:\\n"});{}$\2\6
${}\\{ero\_wyde}((\\{ero}\LL\T{4})+\\{lop\_stab});{}$\6
\\{out\_stab}(\\{trie\_root});\6
${}\\{ero\_lopp}(\\{lop\_end},\39\\{ero\_ptr}){}$;\par
\U143.\fi

\N{1}{80}Expressions. The most intricate part of the assembly process is
the task of scanning and evaluating expressions in the operand field.
Fortunately, \ERISCAL's expressions have a simple structure that can
be handled easily with a stack-based approach.

Two stacks hold pending data as the operand field is scanned and evaluated.
The \PB{\\{op\_stack}} contains operators that have not yet been performed; the
\PB{\\{val\_stack}} contains values that have not yet been used. After an
entire
operand list has been scanned, the \PB{\\{op\_stack}} will be empty and the
\PB{\\{val\_stack}} will hold the operand values needed to assemble the current
instruction.

\fi

\M{81}Entries on \PB{\\{op\_stack}} have one of the constant values defined
here, and they
have one of the precedence levels defined here.

Entries on \PB{\\{val\_stack}} have \PB{\\{equiv}}, \PB{\\{link}}, and \PB{%
\\{status}} fields; the \PB{\\{link}}
points to a trie node if the expression is a symbol that has not yet
been subjected to any operations.

\Y\B\4\X25:Type definitions\X${}\mathrel+\E{}$\6
\&{typedef} \&{enum} ${}\{{}$\1\6
${}\\{indirectize},\39\\{relativize},\39\\{negate},\39\\{serialize},\39%
\\{complement},\39\\{registerize},\3{-1}\39\\{plus},\39\\{minus},\39\\{times},%
\39\\{over},\39\\{frac},\39\\{mod},\39\\{shl},\39\\{shr},\39\\{and},\39\\{or},%
\39\\{xor},\3{-1}\39\\{outer\_lp},\39\\{outer\_rp},\39\\{inner\_lp},\39\\{inner%
\_rp}{}$\2\6
${}\}{}$ \&{stack\_op};\6
\&{typedef} \&{enum} ${}\{{}$\1\6
${}\\{zero},\39\\{weak},\39\\{strong},\39\\{unary}{}$\2\6
${}\}{}$ \&{prec};\6
\&{typedef} \&{enum} ${}\{{}$\1\6
${}\\{pure},\39\\{reg\_val},\39\\{undefined},\39\\{rel\_undefined},\3{-1}\39%
\\{ind\_pure},\39\\{ind\_reg\_val},\39\\{ind\_undefined},\39\\{ind\_rel%
\_undefined}{}$\2\6
${}\}{}$ \&{stat};\6
\&{typedef} \&{struct} ${}\{{}$\1\6
\&{wyde} \\{equiv};\C{ current value }\6
\&{trie\_node} ${}{*}\\{link}{}$;\C{ trie reference for symbol }\6
\&{stat} \\{status};\C{ \PB{\\{pure}}, \PB{\\{reg\_val}}, \PB{\\{undefined}},
... }\2\6
${}\}{}$ \&{val\_node};\par
\fi

\M{82}\B\D$\\{top\_op}$ \5
$\\{op\_stack}[\\{op\_ptr}-\T{1}{}$]\C{ top entry on the operator stack }\par
\B\4\D$\\{top\_val}$ \5
$\\{val\_stack}[\\{val\_ptr}-\T{1}{}$]\C{ top entry on the value stack }\par
\B\4\D$\\{next\_val}$ \5
$\\{val\_stack}[\\{val\_ptr}-\T{2}{}$]\C{ next-to-top entry of the value stack
}\par
\Y\B\4\X26:Global variables\X${}\mathrel+\E{}$\6
\&{stack\_op} ${}{*}\\{op\_stack}{}$;\C{ stack for pending operators }\6
\&{int} \\{op\_ptr};\C{ number of items on \PB{\\{op\_stack}} }\6
\&{val\_node} ${}{*}\\{val\_stack}{}$;\C{ stack for pending operands }\6
\&{int} \\{val\_ptr};\C{ number of items on \PB{\\{val\_stack}} }\6
\&{prec} \\{precedence}[\,]${}\K\{\\{unary},\39\\{unary},\39\\{unary},\39%
\\{unary},\39\\{unary},\39\\{unary},\3{-1}\39\\{weak},\39\\{weak},\39%
\\{strong},\39\\{strong},\39\\{strong},\39\\{strong},\39\\{strong},\39%
\\{strong},\39\\{strong},\39\\{weak},\39\\{weak},\3{-1}\39\\{zero},\39\\{zero},%
\39\\{zero},\39\\{zero}\}{}$;\C{ precedences of the respective \PB{\&{stack%
\_op}} values }\6
\&{stack\_op} \\{rt\_op};\C{ newly scanned operator }\6
\&{wyde} \\{acc};\C{ temporary accumulator }\par
\fi

\M{83}\B\X33:Initialize everything\X${}\mathrel+\E{}$\6
$\\{op\_stack}\K{}$(\&{stack\_op} ${}{*}){}$ \\{calloc}${}(\\{buf\_size},\39%
\&{sizeof}(\&{stack\_op}));{}$\6
${}\\{val\_stack}\K{}$(\&{val\_node} ${}{*}){}$ \\{calloc}${}(\\{buf\_size},\39%
\&{sizeof}(\&{val\_node}));{}$\6
\&{if} ${}(\R\\{op\_stack}\V\R\\{val\_stack}){}$\1\5
\\{panic}(\.{"No\ room\ for\ the\ sta}\)\.{cks"});\2\par
\fi

\M{84}The operand field of an instruction will have been copied into a separate
\&{Char} array called \PB{\\{operand\_list}} when we reach this part of the
program.

\Y\B\4\X84:Scan the operand field\X${}\E{}$\6
$\|p\K\\{operand\_list};{}$\6
${}\\{val\_ptr}\K\T{0}{}$;\C{ \PB{\\{val\_stack}} is empty }\6
${}\\{op\_stack}[\T{0}]\K\\{outer\_lp},\39\\{op\_ptr}\K\T{1}{}$;\C{ \PB{\\{op%
\_stack}} contains an ``outer left parenthesis'' }\6
\&{while} (\T{1})\5
${}\{{}$\1\6
\X85:Scan opening tokens until putting something on \PB{\\{val\_stack}}\X;\6
\4\\{scan\_close}:\5
\X96:Scan a binary operator or closing token, \PB{\\{rt\_op}}\X;\6
\&{while} ${}(\\{precedence}[\\{top\_op}]\G\\{precedence}[\\{rt\_op}]){}$\1\5
\X97:Perform the top operation on \PB{\\{op\_stack}}\X;\2\6
\4\\{hold\_op}:\5
${}\\{op\_stack}[\\{op\_ptr}\PP]\K\\{rt\_op};{}$\6
\4${}\}{}$\2\6
\4\\{operands\_done}:\par
\U101.\fi

\M{85}A comment that follows an empty operand list needs to be detected here.

\Y\B\4\X85:Scan opening tokens until putting something on \PB{\\{val\_stack}}%
\X${}\E{}$\6
\4\\{scan\_open}:\5
\&{if} ${}(\\{isletter}({*}\|p)){}$\1\5
\X86:Scan a symbol\X\2\6
\&{else} \&{if} ${}(\\{isdigit}({*}\|p)){}$\5
${}\{{}$\1\6
\&{if} ${}({*}(\|p+\T{1})\E\.{'F'}){}$\1\5
\X87:Scan a forward local\X\2\6
\&{else} \&{if} ${}({*}(\|p+\T{1})\E\.{'B'}){}$\1\5
\X88:Scan a backward local\X\2\6
\&{else}\1\5
\X93:Scan a decimal constant\X;\2\6
\4${}\}{}$\5
\2\&{else}\5
\1\&{switch} ${}({*}\|p\PP){}$\5
${}\{{}$\1\6
\4\&{case} \.{'\#'}:\5
\X94:Scan a hexadecimal constant\X;\5
\&{break};\6
\4\&{case} \.{'\\''}:\5
\X91:Scan a character constant\X;\5
\&{break};\6
\4\&{case} \.{'\\"'}:\5
\X92:Scan a string constant\X;\5
\&{break};\6
\4\&{case} \.{'@'}:\5
\X95:Scan the current location\X;\5
\&{break};\6
\4\&{case} \.{'*'}:\5
${}\\{op\_stack}[\\{op\_ptr}\PP]\K\\{indirectize}{}$;\5
\&{goto} \\{scan\_open};\6
\4\&{case} \.{'+'}:\5
${}\\{op\_stack}[\\{op\_ptr}\PP]\K\\{relativize}{}$;\5
\&{goto} \\{scan\_open};\6
\4\&{case} \.{'-'}:\5
${}\\{op\_stack}[\\{op\_ptr}\PP]\K\\{negate}{}$;\5
\&{goto} \\{scan\_open};\6
\4\&{case} \.{'\&'}:\5
${}\\{op\_stack}[\\{op\_ptr}\PP]\K\\{serialize}{}$;\5
\&{goto} \\{scan\_open};\6
\4\&{case} \.{'\~'}:\5
${}\\{op\_stack}[\\{op\_ptr}\PP]\K\\{complement}{}$;\5
\&{goto} \\{scan\_open};\6
\4\&{case} \.{'\$'}:\5
${}\\{op\_stack}[\\{op\_ptr}\PP]\K\\{registerize}{}$;\5
\&{goto} \\{scan\_open};\6
\4\&{case} \.{'('}:\5
${}\\{op\_stack}[\\{op\_ptr}\PP]\K\\{inner\_lp}{}$;\5
\&{goto} \\{scan\_open};\6
\4\&{default}:\6
\&{if} ${}(\|p\E\\{operand\_list}+\T{1}){}$\5
${}\{{}$\C{ treat operand list as empty }\1\6
${}\\{operand\_list}[\T{0}]\K\.{'0'},\39\\{operand\_list}[\T{1}]\K\.{'\\0'},\39%
\|p\K\\{operand\_list};{}$\6
\&{goto} \\{scan\_open};\6
\4${}\}{}$\2\6
\&{if} ${}({*}(\|p-\T{1})){}$\1\5
${}\\{derr}(\.{"syntax\ error\ at\ cha}\)\.{racter\ `\%c'"},\39{*}(\|p-\T{1}))%
\\{derr}(\.{"syntax\ error\ after\ }\)\.{character\ `\%c'"},\39{*}(\|p-%
\T{2})){}$\2\6
\4${}\}{}$\2\2\par
\U84.\fi

\M{86}\B\X86:Scan a symbol\X${}\E{}$\6
${}\{{}$\1\6
\&{if} ${}({*}\|p\E\.{':'}){}$\1\5
${}\\{tt}\K\\{trie\_search}(\\{trie\_root},\39\|p+\T{1});{}$\2\6
\&{else}\1\5
${}\\{tt}\K\\{trie\_search}(\\{cur\_prefix},\39\|p);{}$\2\6
${}\|p\K\\{terminator};{}$\6
\4\\{symbol\_found}:\5
${}\\{val\_ptr}\PP;{}$\6
${}\\{pp}\K\\{tt}\MG\\{sym};{}$\6
\&{if} ${}(\R\\{pp}){}$\1\5
${}\\{pp}\K\\{tt}\MG\\{sym}\K\\{new\_sym\_node}(\\{true});{}$\2\6
${}\\{top\_val}.\\{link}\K\\{tt},\39\\{top\_val}.\\{equiv}\K\\{pp}\MG%
\\{equiv};{}$\6
\&{if} ${}(\\{pp}\MG\\{link}\E\.{PREDEFINED}){}$\1\5
${}\\{pp}\MG\\{link}\K\.{DEFINED};{}$\2\6
${}\\{top\_val}.\\{status}\K(\\{pp}\MG\\{link}\E\.{DEFINED}\?\\{pure}:\\{pp}\MG%
\\{link}\E\.{REGISTER}\?\\{reg\_val}:\\{undefined});{}$\6
\4${}\}{}$\2\par
\U85.\fi

\M{87}\B\X87:Scan a forward local\X${}\E{}$\6
${}\{{}$\1\6
${}\\{tt}\K{\AND}\\{forward\_local\_host}[{*}\|p-\.{'0'}]{}$;\5
${}\|p\MRL{+{\K}}\T{2}{}$;\5
\&{goto} \\{symbol\_found};\6
\4${}\}{}$\2\par
\U85.\fi

\M{88}\B\X88:Scan a backward local\X${}\E{}$\6
${}\{{}$\1\6
${}\\{tt}\K{\AND}\\{backward\_local\_host}[{*}\|p-\.{'0'}]{}$;\5
${}\|p\MRL{+{\K}}\T{2}{}$;\5
\&{goto} \\{symbol\_found};\6
\4${}\}{}$\2\par
\U85.\fi

\M{89}Statically allocated variables \PB{\\{forward\_local\_host}[\|j]} and
\PB{\\{backward\_local\_host}[\|j]} masquerade as nodes of the trie.

\Y\B\4\X26:Global variables\X${}\mathrel+\E{}$\6
\&{trie\_node} \\{forward\_local\_host}[\T{10}]${},{}$ \\{backward\_local%
\_host}[\T{10}];\6
\&{sym\_node} \\{forward\_local}[\T{10}]${},{}$ \\{backward\_local}[\T{10}];\par
\fi

\M{90}Initially \.{0H}, \.{1H}, \dots, \.{9H} are defined to be zero.

\Y\B\4\X33:Initialize everything\X${}\mathrel+\E{}$\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\T{10};{}$ ${}\|j\PP){}$\5
${}\{{}$\1\6
${}\\{forward\_local\_host}[\|j].\\{sym}\K{\AND}\\{forward\_local}[\|j];{}$\6
${}\\{backward\_local\_host}[\|j].\\{sym}\K{\AND}\\{backward\_local}[\|j];{}$\6
${}\\{backward\_local}[\|j].\\{link}\K\.{DEFINED};{}$\6
\4${}\}{}$\2\par
\fi

\M{91}We have already checked to make sure that the character constant is
legal.

\Y\B\4\X91:Scan a character constant\X${}\E{}$\6
$\\{acc}\K{*}\|p;{}$\6
${}\|p\MRL{+{\K}}\T{2};{}$\6
\&{goto} \\{constant\_found};\par
\U85.\fi

\M{92}\B\X92:Scan a string constant\X${}\E{}$\6
$\\{acc}\K{*}\|p;{}$\6
\&{if} ${}({*}\|p\E\.{'\\"'}){}$\5
${}\{{}$\1\6
${}\|p\PP;{}$\6
${}\\{acc}\K\T{0};{}$\6
\\{err}(\.{"*null\ string\ is\ tre}\)\.{ated\ as\ zero"})\6
\4${}\}{}$\5
\2\&{else} \&{if} ${}({*}(\|p+\T{1})\E\.{'\\"'}){}$\1\5
${}\|p\MRL{+{\K}}\T{2};{}$\2\6
\&{else}\1\5
${}{*}\|p\K\.{'\\"'},\39{*}\MM\|p\K\.{','};{}$\2\6
\&{goto} \\{constant\_found};\par
\U85.\fi

\M{93}\B\X93:Scan a decimal constant\X${}\E{}$\6
$\\{acc}\K{*}\|p-\.{'0'};{}$\6
\&{for} ${}(\|p\PP;{}$ ${}\\{isdigit}({*}\|p);{}$ ${}\|p\PP){}$\5
${}\{{}$\1\6
${}\\{acc}\MRL{+{\K}}(\\{acc}\LL\T{2});{}$\6
${}\\{acc}\K(\\{acc}\LL\T{1})+({*}\|p-\.{'0'});{}$\6
\4${}\}{}$\2\6
\4\\{constant\_found}:\5
${}\\{val\_ptr}\PP;{}$\6
${}\\{top\_val}.\\{link}\K\NULL;{}$\6
${}\\{top\_val}.\\{equiv}\K\\{acc};{}$\6
${}\\{top\_val}.\\{status}\K\\{pure}{}$;\par
\U85.\fi

\M{94}\B\X94:Scan a hexadecimal constant\X${}\E{}$\6
\&{if} ${}(\R\\{isxdigit}({*}\|p)){}$\1\5
\\{err}(\.{"illegal\ hexadecimal}\)\.{\ constant"});\2\6
${}\\{acc}\K\T{0};{}$\6
\&{for} ( ; ${}\\{isxdigit}({*}\|p);{}$ ${}\|p\PP){}$\5
${}\{{}$\1\6
${}\\{acc}\K(\\{acc}\LL\T{4})+({*}\|p-\.{'0'});{}$\6
\&{if} ${}({*}\|p\G\.{'a'}){}$\1\5
${}\\{acc}\MRL{+{\K}}\.{'0'}-\.{'a'}+\T{10};{}$\2\6
\&{else} \&{if} ${}({*}\|p\G\.{'A'}){}$\1\5
${}\\{acc}\MRL{+{\K}}\.{'0'}-\.{'A'}+\T{10};{}$\2\6
\4${}\}{}$\2\6
\&{goto} \\{constant\_found};\par
\U85.\fi

\M{95}\B\X95:Scan the current location\X${}\E{}$\6
$\\{acc}\K\\{cur\_loc};{}$\6
\&{goto} \\{constant\_found};\par
\U85.\fi

\M{96}\B\X96:Scan a binary operator or closing token, \PB{\\{rt\_op}}\X${}\E{}$%
\6
\&{switch} ${}({*}\|p\PP){}$\5
${}\{{}$\1\6
\4\&{case} \.{'+'}:\5
${}\\{rt\_op}\K\\{plus}{}$;\5
\&{break};\6
\4\&{case} \.{'-'}:\5
${}\\{rt\_op}\K\\{minus}{}$;\5
\&{break};\6
\4\&{case} \.{'*'}:\5
${}\\{rt\_op}\K\\{times}{}$;\5
\&{break};\6
\4\&{case} \.{'/'}:\5
\&{if} ${}({*}\|p\I\.{'/'}){}$\1\5
${}\\{rt\_op}\K\\{over};{}$\2\6
\&{else}\1\5
${}\|p\PP,\39\\{rt\_op}\K\\{frac}{}$;\5
\2\&{break};\6
\4\&{case} \.{'\%'}:\5
${}\\{rt\_op}\K\\{mod}{}$;\5
\&{break};\6
\4\&{case} \.{'<'}:\5
${}\\{rt\_op}\K\\{shl}{}$;\5
\&{goto} \\{sh\_check};\6
\4\&{case} \.{'>'}:\5
${}\\{rt\_op}\K\\{shr};{}$\6
\4\\{sh\_check}:\5
${}\|p\PP{}$;\5
\&{if} ${}({*}(\|p-\T{1})\E{*}(\|p-\T{2})){}$\1\5
\&{break};\2\6
${}\\{derr}(\.{"syntax\ error\ at\ `\%c}\)\.{'"},\39{*}(\|p-\T{2}));{}$\6
\4\&{case} \.{'\&'}:\5
${}\\{rt\_op}\K\\{and}{}$;\5
\&{break};\6
\4\&{case} \.{'|'}:\5
${}\\{rt\_op}\K\\{or}{}$;\5
\&{break};\6
\4\&{case} \.{'\^'}:\5
${}\\{rt\_op}\K\\{xor}{}$;\5
\&{break};\6
\4\&{case} \.{')'}:\5
${}\\{rt\_op}\K\\{inner\_rp}{}$;\5
\&{break};\6
\4\&{case} \.{'\\0'}:\5
\&{case} \.{','}:\5
${}\\{rt\_op}\K\\{outer\_rp}{}$;\5
\&{break};\6
\4\&{default}:\5
${}\\{derr}(\.{"syntax\ error\ at\ `\%c}\)\.{'"},\39{*}(\|p-\T{1}));{}$\6
\4${}\}{}$\2\par
\U84.\fi

\M{97}\B\X97:Perform the top operation on \PB{\\{op\_stack}}\X${}\E{}$\6
\&{switch} ${}(\\{op\_stack}[\MM\\{op\_ptr}]){}$\5
${}\{{}$\1\6
\4\&{case} \\{inner\_lp}:\5
\&{if} ${}(\\{rt\_op}\E\\{inner\_rp}){}$\1\5
\&{goto} \\{scan\_close};\2\6
\\{err}(\.{"*missing\ right\ pare}\)\.{nthesis"});\5
\&{break};\6
\4\&{case} \\{outer\_lp}:\5
\&{if} ${}(\\{rt\_op}\E\\{outer\_rp}){}$\5
${}\{{}$\1\6
\&{if} ${}((\\{top\_val}.\\{status}\E\\{reg\_val}\V\\{top\_val}.\\{status}\E%
\\{ind\_reg\_val})\W\3{-1}\\{top\_val}.\\{equiv}>\T{\^f}){}$\5
${}\{{}$\1\6
\\{err}(\.{"*register\ number\ to}\)\.{o\ large,\ will\ be\ red}\)\.{uced\ mod\
16"});\6
${}\\{top\_val}.\\{equiv}\MRL{\AND{\K}}\T{\^f};{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\R{*}(\|p-\T{1})){}$\1\5
\&{goto} \\{operands\_done};\2\6
\&{else}\1\5
${}\\{rt\_op}\K\\{outer\_lp}{}$;\5
\2\&{goto} \\{hold\_op};\C{ comma }\6
\4${}\}{}$\5
\2\&{else}\5
${}\{{}$\1\6
${}\\{op\_ptr}\PP;{}$\6
\\{err}(\.{"*missing\ left\ paren}\)\.{thesis"});\6
\&{goto} \\{scan\_close};\6
\4${}\}{}$\2\6
\hbox{\4}\X99:Cases for unary operators\X\6
\hbox{\4}\X98:Cases for binary operators\X\6
\4${}\}{}$\2\par
\U84.\fi

\M{98}Now we come to the part where equivalents are changed by unary
or binary operators found in the expression being scanned.

The most typical operator, and in some ways the fussiest one
to deal with, is binary addition. Once we've written the code for
this case, the other cases almost take care of themselves.

\Y\B\4\X98:Cases for binary operators\X${}\E{}$\6
\4\&{case} \\{plus}:\5
\&{if} ${}(\\{top\_val}.\\{status}\G\\{ind\_pure}){}$\1\5
\\{err}(\.{"cannot\ add\ an\ indir}\)\.{ect\ quantity"});\2\6
\&{if} ${}(\\{next\_val}.\\{status}\G\\{ind\_pure}){}$\1\5
\\{err}(\.{"cannot\ add\ to\ an\ in}\)\.{direct\ quantity"});\2\6
\&{if} ${}(\\{top\_val}.\\{status}\G\\{undefined}){}$\1\5
\\{err}(\.{"cannot\ add\ an\ undef}\)\.{ined\ quantity"});\2\6
\&{if} ${}(\\{next\_val}.\\{status}\G\\{undefined}){}$\1\5
\\{err}(\.{"cannot\ add\ to\ an\ un}\)\.{defined\ quantity"});\2\6
\&{if} ${}(\\{top\_val}.\\{status}\E\\{reg\_val}\W\\{next\_val}.\\{status}\E%
\\{reg\_val}){}$\1\5
\\{err}(\.{"cannot\ add\ two\ regi}\)\.{ster\ numbers"});\2\6
${}\\{next\_val}.\\{equiv}\MRL{+{\K}}\\{top\_val}.\\{equiv};{}$\6
\4\\{fin\_bin}:\5
${}\\{next\_val}.\\{status}\K(\\{top\_val}.\\{status}\E\\{next\_val}.\\{status}%
\?\\{pure}:\\{reg\_val});{}$\6
${}\\{val\_ptr}\MM;{}$\6
\4\\{delink}:\5
${}\\{top\_val}.\\{link}\K\NULL{}$;\5
\&{break};\par
\A100.
\U97.\fi

\M{99}\B\D$\\{unary\_check}(\\{verb})$ \5
\&{if} ${}(\\{top\_val}.\\{status}\I\\{pure})$ $\\{derr}(\.{"can\ \%s\ pure\
values\ }\)\.{only"},\39\\{verb}{}$)\par
\Y\B\4\X99:Cases for unary operators\X${}\E{}$\6
\4\&{case} \\{indirectize}:\5
\&{if} ${}(\\{top\_val}.\\{status}<\\{ind\_pure}){}$\1\5
${}\\{top\_val}.\\{status}\MRL{+{\K}}\\{ind\_pure}-\\{pure}{}$;\5
\2\&{goto} \\{delink};\6
\4\&{case} \\{relativize}:\5
\&{if} ${}(\R(\\{top\_val}.\\{status}\E\\{pure}\V\\{top\_val}.\\{status}\E%
\\{undefined})){}$\1\5
\\{err}(\.{"can\ relativise\ only}\)\.{\ pure\ values\ and\ for}\)\.{ward\
references"});\2\6
\&{if} ${}(\\{top\_val}.\\{status}\E\\{pure}){}$\1\5
${}\\{top\_val}.\\{equiv}\MRL{-{\K}}\\{cur\_loc};{}$\2\6
\&{else}\1\5
${}\\{top\_val}.\\{status}\K\\{rel\_undefined}{}$;\5
\2\&{goto} \\{delink};\6
\4\&{case} \\{negate}:\5
\\{unary\_check}(\.{"negate"});\6
${}\\{top\_val}.\\{equiv}\K\\{zero\_wyde}-\\{top\_val}.\\{equiv}{}$;\5
\&{goto} \\{delink};\6
\4\&{case} \\{complement}:\5
\\{unary\_check}(\.{"complement"});\6
${}\\{top\_val}.\\{equiv}\K\CM\\{top\_val}.\\{equiv};{}$\6
\&{goto} \\{delink};\6
\4\&{case} \\{registerize}:\5
\\{unary\_check}(\.{"registerize"});\6
${}\\{top\_val}.\\{status}\K\\{reg\_val}{}$;\5
\&{goto} \\{delink};\6
\4\&{case} \\{serialize}:\5
\&{if} ${}(\R\\{top\_val}.\\{link}){}$\1\5
\\{err}(\.{"can\ take\ serial\ num}\)\.{ber\ of\ symbol\ only"});\2\6
${}\\{top\_val}.\\{equiv}\K\\{top\_val}.\\{link}\MG\\{sym}\MG\\{serial};{}$\6
${}\\{top\_val}.\\{status}\K\\{pure}{}$;\5
\&{goto} \\{delink};\par
\U97.\fi

\M{100}\B\D$\\{binary\_check}(\\{verb})$ \5
\&{if} ${}(\\{top\_val}.\\{status}\I\\{pure}\V\\{next\_val}.\\{status}\I%
\\{pure})$ $\\{derr}(\.{"can\ \%s\ pure\ values\ }\)\.{only"},\39\\{verb}{}$)%
\par
\Y\B\4\X98:Cases for binary operators\X${}\mathrel+\E{}$\6
\4\&{case} \\{minus}:\5
\&{if} ${}(\\{top\_val}.\\{status}\G\\{ind\_pure}){}$\1\5
\\{err}(\.{"cannot\ subtract\ an\ }\)\.{indirect\ quantity"});\2\6
\&{if} ${}(\\{top\_val}.\\{status}\G\\{undefined}){}$\1\5
\\{err}(\.{"cannot\ subtract\ an\ }\)\.{undefined\ quantity"});\2\6
\&{if} ${}(\\{next\_val}.\\{status}\G\\{ind\_pure}){}$\1\5
\\{err}(\.{"cannot\ subtract\ fro}\)\.{m\ an\ indirect\ quanti}\)\.{ty"});\2\6
\&{if} ${}(\\{next\_val}.\\{status}\G\\{undefined}){}$\1\5
\\{err}(\.{"cannot\ subtract\ fro}\)\.{m\ an\ undefined\ quant}\)\.{ity"});\2\6
\&{if} ${}(\\{top\_val}.\\{status}\E\\{reg\_val}\W\\{next\_val}.\\{status}\I%
\\{reg\_val}){}$\1\5
\\{err}(\.{"cannot\ subtract\ reg}\)\.{ister\ number\ from\ pu}\)\.{re\
value"});\2\6
${}\\{next\_val}.\\{equiv}\MRL{-{\K}}\\{top\_val}.\\{equiv}{}$;\5
\&{goto} \\{fin\_bin};\6
\4\&{case} \\{times}:\5
\\{binary\_check}(\.{"multiply"});\6
${}\\{next\_val}.\\{equiv}\K\\{wmult}(\\{next\_val}.\\{equiv},\39\\{top\_val}.%
\\{equiv}){}$;\5
\&{goto} \\{fin\_bin};\6
\4\&{case} \\{over}:\5
\&{case} \\{mod}:\5
\\{binary\_check}(\.{"divide"});\6
\&{if} ${}(\\{top\_val}.\\{equiv}\E\T{0}){}$\1\5
\\{err}(\.{"*division\ by\ zero"});\2\6
${}\\{next\_val}.\\{equiv}\K\\{wdiv}(\\{zero\_wyde},\39\\{next\_val}.\\{equiv},%
\39\\{top\_val}.\\{equiv});{}$\6
\&{if} ${}(\\{op\_stack}[\\{op\_ptr}]\E\\{mod}){}$\1\5
${}\\{next\_val}.\\{equiv}\K\\{aux};{}$\2\6
\&{goto} \\{fin\_bin};\6
\4\&{case} \\{frac}:\5
\\{binary\_check}(\.{"compute\ a\ ratio\ of"});\6
\&{if} ${}(\\{next\_val}.\\{equiv}\G\\{top\_val}.\\{equiv}){}$\1\5
\\{err}(\.{"*illegal\ fraction"});\2\6
${}\\{next\_val}.\\{equiv}\K\\{wdiv}(\\{next\_val}.\\{equiv},\39\\{zero\_wyde},%
\39\\{top\_val}.\\{equiv}){}$;\5
\&{goto} \\{fin\_bin};\6
\4\&{case} \\{shl}:\5
\&{case} \\{shr}:\5
\\{binary\_check}(\.{"compute\ a\ bitwise\ s}\)\.{hift\ of"});\6
\&{if} ${}(\\{top\_val}.\\{equiv}>\T{15}){}$\1\5
${}\\{next\_val}.\\{equiv}\K\\{zero\_wyde};{}$\2\6
\&{else} \&{if} ${}(\\{op\_stack}[\\{op\_ptr}]\E\\{shl}){}$\1\5
${}\\{next\_val}.\\{equiv}\MRL{{\LL}{\K}}\\{top\_val}.\\{equiv};{}$\2\6
\&{else}\1\5
${}\\{next\_val}.\\{equiv}\MRL{{\GG}{\K}}\\{top\_val}.\\{equiv};{}$\2\6
\&{goto} \\{fin\_bin};\6
\4\&{case} \\{and}:\5
\\{binary\_check}(\.{"compute\ bitwise\ and}\)\.{\ of"});\6
${}\\{next\_val}.\\{equiv}\MRL{\AND{\K}}\\{top\_val}.\\{equiv};{}$\6
\&{goto} \\{fin\_bin};\6
\4\&{case} \\{or}:\5
\\{binary\_check}(\.{"compute\ bitwise\ or\ }\)\.{of"});\6
${}\\{next\_val}.\\{equiv}\MRL{{\OR}{\K}}\\{top\_val}.\\{equiv};{}$\6
\&{goto} \\{fin\_bin};\6
\4\&{case} \\{xor}:\5
\\{binary\_check}(\.{"compute\ bitwise\ xor}\)\.{\ of"});\6
${}\\{next\_val}.\\{equiv}\MRL{{\XOR}{\K}}\\{top\_val}.\\{equiv};{}$\6
\&{goto} \\{fin\_bin};\par
\fi

\N{1}{101}Assembling an instruction.
Now let's move up from the expression level to the instruction level. We get to
this part of the program at the beginning of a line, or after a
semicolon at the end of an instruction earlier on the current line.
Our current position in the buffer is the value of \PB{\\{buf\_ptr}}.

\Y\B\4\X101:Process the next \ERISCAL\ instruction or comment\X${}\E{}$\6
$\|p\K\\{buf\_ptr}{}$;\5
${}\\{buf\_ptr}\K\.{""};{}$\6
\X102:Scan the label field; \PB{\&{goto} \\{bypass}} if there is none\X;\6
\X103:Scan the opcode field; \PB{\&{goto} \\{bypass}} if there is none\X;\6
\X105:Copy the operand field\X;\6
${}\\{buf\_ptr}\K\|p;{}$\6
\&{if} ${}(\\{spec\_mode}\W\R(\\{op\_bits}\AND\\{spec\_bit})){}$\1\5
${}\\{derr}(\.{"cannot\ use\ `\%s'\ in\ }\)\.{special\ mode"},\39\\{op%
\_field});{}$\2\6
\&{if} ${}((\\{op\_bits}\AND\\{no\_label\_bit})\W\\{lab\_field}[\T{0}]){}$\5
${}\{{}$\1\6
${}\\{derr}(\.{"*label\ field\ of\ `\%s}\)\.{'\ instruction\ is\ ign}\)%
\.{ored"},\39\\{op\_field});{}$\6
${}\\{lab\_field}[\T{0}]\K\.{'\\0'};{}$\6
\4${}\}{}$\2\6
\X84:Scan the operand field\X;\6
\&{if} ${}(\\{opcode}\E\.{GREG}){}$\1\5
\X106:Allocate a global register\X;\2\6
\&{if} (\\{lab\_field}[\T{0}])\1\5
\X107:Define the label\X;\2\6
\X113:Do the operation\X;\6
\4\\{bypass}:\par
\U137.\fi

\M{102}\B\X102:Scan the label field; \PB{\&{goto} \\{bypass}} if there is none%
\X${}\E{}$\6
\&{if} ${}(\R{*}\|p){}$\1\5
\&{goto} \\{bypass};\2\6
${}\|q\K\\{lab\_field};{}$\6
\&{if} ${}(\R\\{isspace}({*}\|p)){}$\5
${}\{{}$\1\6
\&{if} ${}(\R\\{isdigit}({*}\|p)\W\R\\{isletter}({*}\|p)){}$\1\5
\&{goto} \\{bypass};\C{ comment }\2\6
\&{for} ${}({*}\|q\PP\K{*}\|p\PP;{}$ ${}\\{isdigit}({*}\|p)\V\\{isletter}({*}%
\|p);{}$ ${}\|p\PP,\39\|q\PP){}$\1\5
${}{*}\|q\K{*}\|p;{}$\2\6
\&{if} ${}({*}\|p\W\R\\{isspace}({*}\|p)){}$\1\5
${}\\{derr}(\.{"label\ syntax\ error\ }\)\.{at\ `\%c'"},\39{*}\|p);{}$\2\6
\4${}\}{}$\2\6
${}{*}\|q\K\.{'\\0'};{}$\6
\&{if} ${}(\\{isdigit}(\\{lab\_field}[\T{0}])\W(\\{lab\_field}[\T{1}]\I\.{'H'}%
\V\\{lab\_field}[\T{2}])){}$\1\5
${}\\{derr}(\.{"improper\ local\ labe}\)\.{l\ `\%s'"},\39\\{lab\_field});{}$\2\6
\&{for} ${}(\|p\PP;{}$ ${}\\{isspace}({*}\|p);{}$ ${}\|p\PP){}$\1\5
;\2\par
\U101.\fi

\M{103}We copy the opcode field to a special buffer because we might
want to refer to the symbolic opcode in error messages.

\Y\B\4\X103:Scan the opcode field; \PB{\&{goto} \\{bypass}} if there is none%
\X${}\E{}$\6
$\|q\K\\{op\_field}{}$;\5
\&{while} ${}(\\{isletter}({*}\|p)\V\\{isdigit}({*}\|p)){}$\1\5
${}{*}\|q\PP\K{*}\|p\PP;{}$\2\6
${}{*}\|q\K\.{'\\0'};{}$\6
\&{if} ${}(\R\\{isspace}({*}\|p)\W{*}\|p\W\\{op\_field}[\T{0}]){}$\1\5
${}\\{derr}(\.{"opcode\ syntax\ error}\)\.{\ at\ `\%c'"},\39{*}\|p);{}$\2\6
${}\\{pp}\K\\{trie\_search}(\\{op\_root},\39\\{op\_field})\MG\\{sym};{}$\6
\&{if} ${}(\R\\{pp}){}$\5
${}\{{}$\1\6
\&{if} (\\{op\_field}[\T{0}])\1\5
${}\\{derr}(\.{"unknown\ operation\ c}\)\.{ode\ `\%s'"},\39\\{op\_field});{}$\2%
\6
\&{if} (\\{lab\_field}[\T{0}])\1\5
${}\\{derr}(\.{"*no\ opcode;\ label\ `}\)\.{\%s'\ will\ be\ ignored"},\39\\{lab%
\_field});{}$\2\6
\&{goto} \\{bypass};\6
\4${}\}{}$\2\6
${}\\{opcode}\K(\\{pp}\MG\\{equiv}\GG\T{8})\AND\T{\^ff},\39\\{op\_bits}\K\\{pp}%
\MG\\{equiv}\AND\T{\^ff};{}$\6
\&{while} ${}(\\{isspace}({*}\|p)){}$\1\5
${}\|p\PP{}$;\2\par
\U101.\fi

\M{104}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{wyde} \\{opcode};\C{ numeric code for \ERISC\ operation or \ERISCAL\
pseudo-op }\6
\&{wyde} \\{op\_bits};\C{ flags describing an operator's special
characteristics }\6
\&{wyde} \\{arg\_num};\C{ number of arguments: 0,1,2,>=3 }\par
\fi

\M{105}We copy the operand field to a special buffer so that we can
change string constants while scanning them later.

\Y\B\4\X105:Copy the operand field\X${}\E{}$\6
$\|q\K\\{operand\_list};{}$\6
\&{while} ${}({*}\|p){}$\5
${}\{{}$\1\6
\&{if} ${}({*}\|p\E\.{';'}){}$\1\5
\&{break};\2\6
\&{if} ${}({*}\|p\E\.{'\\''}){}$\5
${}\{{}$\1\6
${}{*}\|q\PP\K{*}\|p\PP;{}$\6
\&{if} ${}(\R{*}\|p){}$\1\5
\\{err}(\.{"incomplete\ characte}\)\.{r\ constant"});\2\6
${}{*}\|q\PP\K{*}\|p\PP;{}$\6
\&{if} ${}({*}\|p\I\.{'\\''}){}$\1\5
\\{err}(\.{"illegal\ character\ c}\)\.{onstant"});\2\6
\4${}\}{}$\5
\2\&{else} \&{if} ${}({*}\|p\E\.{'\\"'}){}$\5
${}\{{}$\1\6
\&{for} ${}({*}\|q\PP\K{*}\|p\PP;{}$ ${}{*}\|p\W{*}\|p\I\.{'\\"'};{}$ ${}\|p%
\PP,\39\|q\PP){}$\1\5
${}{*}\|q\K{*}\|p;{}$\2\6
\&{if} ${}(\R{*}\|p){}$\1\5
\\{err}(\.{"incomplete\ string\ c}\)\.{onstant"});\2\6
\4${}\}{}$\2\6
${}{*}\|q\PP\K{*}\|p\PP;{}$\6
\&{if} ${}(\\{isspace}({*}\|p)){}$\1\5
\&{break};\2\6
\4${}\}{}$\2\6
\&{while} ${}(\\{isspace}({*}\|p)){}$\1\5
${}\|p\PP;{}$\2\6
\&{if} ${}({*}\|p\E\.{';'}){}$\1\5
${}\|p\PP;{}$\2\6
\&{else}\1\5
${}\|p\K\.{""}{}$;\C{ if not followed by semicolon, rest of the line is a
comment }\2\6
\&{if} ${}(\|q\E\\{operand\_list}){}$\1\5
${}{*}\|q\PP\K\.{'0'}{}$;\C{ change empty operand field to `\.0' }\2\6
${}{*}\|q\K\.{'\\0'}{}$;\par
\U101.\fi

\M{106}\B\X106:Allocate a global register\X${}\E{}$\6
$\{$ \&{if} ${}(\\{greg}\E\T{15})$ \\{err}(\.{"too\ many\ global\ reg}\)%
\.{isters"}) \6
\&{else}\5
${}\{{}$\1\6
${}\PP\\{greg};{}$\6
${}\\{greg\_val}[\\{greg}]\K\\{val\_stack}[\T{0}].\\{equiv};{}$\6
\4${}\}{}$\2\6
$\}{}$\par
\U101.\fi

\M{107}If the label is, say \.{2H}, we will already have used the old
value of \.{2B} when evaluating the operands. Furthermore, an
operand of \.{2F} will have been treated as undefined, which it
still is.

Symbols can be defined more than once, but only if each definition
gives them the same equivalent value.

A warning message is given when a predefined symbol is being redefined,
if its predefined value has already been used.

\Y\B\4\X107:Define the label\X${}\E{}$\6
${}\{{}$\1\6
\&{sym\_node} ${}{*}\\{new\_link}\K\.{DEFINED};{}$\7
${}\\{acc}\K\\{cur\_loc};{}$\6
\&{if} ${}(\\{opcode}\E\.{IS}){}$\5
${}\{{}$\1\6
${}\\{cur\_loc}\K\\{val\_stack}[\T{0}].\\{equiv};{}$\6
\&{if} ${}(\\{val\_stack}[\T{0}].\\{status}\E\\{reg\_val}){}$\1\5
${}\\{new\_link}\K\.{REGISTER};{}$\2\6
\4${}\}{}$\5
\2\&{else} \&{if} ${}(\\{opcode}\E\.{GREG}){}$\1\5
${}\\{cur\_loc}\K\\{greg},\39\\{new\_link}\K\.{REGISTER};{}$\2\6
\X109:Find the symbol table node, \PB{\\{pp}}\X;\6
\&{if} ${}(\\{pp}\MG\\{link}\E\.{DEFINED}\V\\{pp}\MG\\{link}\E\.{REGISTER}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{pp}\MG\\{seg}\I\\{cur\_seg}\V\\{pp}\MG\\{equiv}\I\\{cur\_loc}\V%
\\{pp}\MG\\{link}\I\\{new\_link}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{pp}\MG\\{serial}){}$\1\5
${}\\{derr}(\.{"symbol\ `\%s'\ is\ alre}\)\.{ady\ defined"},\39\\{lab%
\_field});{}$\2\6
${}\\{pp}\MG\\{serial}\K\PP\\{serial\_number};{}$\6
${}\\{derr}(\.{"*redefinition\ of\ pr}\)\.{edefined\ symbol\ `\%s'}\)\.{"},\39%
\\{lab\_field});{}$\6
\4${}\}{}$\2\6
\4${}\}{}$\5
\2\&{else} \&{if} ${}(\\{pp}\MG\\{link}\E\.{PREDEFINED}){}$\1\5
${}\\{pp}\MG\\{serial}\K\PP\\{serial\_number};{}$\2\6
\&{else} \&{if} ${}(\\{pp}\MG\\{link}){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{new\_link}\E\.{REGISTER}){}$\1\5
\\{err}(\.{"future\ reference\ ca}\)\.{nnot\ be\ to\ a\ registe}\)\.{r"});\2\6
\&{do}\5
\X110:Fix prior references to this label\X\5
\5
\&{while} ${}(\\{pp}\MG\\{link});{}$\6
\4${}\}{}$\2\6
\&{if} (\\{isdigit}(\\{lab\_field}[\T{0}]))\1\5
${}\\{pp}\K{\AND}\\{backward\_local}[\\{lab\_field}[\T{0}]-\.{'0'}];{}$\2\6
${}\\{pp}\MG\\{equiv}\K\\{cur\_loc}{}$;\5
${}\\{pp}\MG\\{seg}\K\\{cur\_seg}{}$;\5
${}\\{pp}\MG\\{link}\K\\{new\_link};{}$\6
\X108:Fix references that might be in the \PB{\\{val\_stack}}\X;\6
\&{if} ${}(\\{listing\_file}\W(\\{opcode}\E\.{IS}\V\\{opcode}\E\.{LOC})){}$\1\5
\X112:Make special listing to show the label equivalent\X;\2\6
${}\\{cur\_loc}\K\\{acc};{}$\6
\4${}\}{}$\2\par
\U101.\fi

\M{108}\B\X108:Fix references that might be in the \PB{\\{val\_stack}}\X${}%
\E{}$\6
\&{if} ${}(\R\\{isdigit}(\\{lab\_field}[\T{0}])){}$\1\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\\{val\_ptr};{}$ ${}\|j\PP){}$\1\6
\&{if} ${}(\\{val\_stack}[\|j].\\{status}\E\\{undefined}\W\\{val\_stack}[\|j].%
\\{link}\MG\\{sym}\E\\{pp}){}$\5
${}\{{}$\1\6
${}\\{val\_stack}[\|j].\\{status}\K(\\{new\_link}\E\.{REGISTER}\?\\{reg\_val}:%
\\{pure});{}$\6
${}\\{val\_stack}[\|j].\\{equiv}\K\\{cur\_loc};{}$\6
\4${}\}{}$\2\2\2\par
\U107.\fi

\M{109}\B\X109:Find the symbol table node, \PB{\\{pp}}\X${}\E{}$\6
\&{if} (\\{isdigit}(\\{lab\_field}[\T{0}]))\1\5
${}\\{pp}\K{\AND}\\{forward\_local}[\\{lab\_field}[\T{0}]-\.{'0'}];{}$\2\6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\\{lab\_field}[\T{0}]\E\.{':'}){}$\1\5
${}\\{tt}\K\\{trie\_search}(\\{trie\_root},\39\\{lab\_field}+\T{1});{}$\2\6
\&{else}\1\5
${}\\{tt}\K\\{trie\_search}(\\{cur\_prefix},\39\\{lab\_field});{}$\2\6
${}\\{pp}\K\\{tt}\MG\\{sym};{}$\6
\&{if} ${}(\R\\{pp}){}$\1\5
${}\\{pp}\K\\{tt}\MG\\{sym}\K\\{new\_sym\_node}(\\{true});{}$\2\6
\4${}\}{}$\2\par
\U107.\fi

\M{110}\B\X110:Fix prior references to this label\X${}\E{}$\6
${}\{{}$\1\6
${}\\{qq}\K\\{pp}\MG\\{link};{}$\6
${}\\{pp}\MG\\{link}\K\\{qq}\MG\\{link};{}$\6
\X111:Fix a future reference\X\6
\\{recycle\_fixup}(\\{qq});\6
\4${}\}{}$\2\par
\U107.\fi

\M{111}\B\X111:Fix a future reference\X${}\E{}$\6
$\{$ \&{wyde} \|w;\6
\&{int} \|s;\7
${}\|s\K\\{qq}\MG\\{serial};$ \&{if} ${}(\|s\AND\\{seg\_bit}\I\\{cur\_seg}{}$)%
\C{ different segment }\6
$\\{dderr}(\.{"location\ \#\%01x\%04x\ }\)\.{is\ in\ a\ different\ se}\)%
\.{gment"},\39\\{qq}\MG\\{seg},\39\\{qq}\MG\\{equiv})$ \6
\&{else}\5
${}\{{}$\1\6
\X55:Make sure \PB{\\{cur\_loc}} and \PB{\\{ero\_cur\_loc}} refer to the same
wyde\X\6
\&{if} ${}(\|s\AND\\{rel\_bit}){}$\5
${}\{{}$\1\6
${}\|k\K\T{0};{}$\6
${}\|w\K\\{cur\_loc}-\\{qq}\MG\\{equiv};{}$\6
\&{if} ${}(\|s\AND\\{nyb\_bit}){}$\5
${}\{{}$\1\6
\&{if} ${}(\R(\|w\AND\T{\^8000})){}$\1\6
\&{if} ${}(\|w<\T{\^8}){}$\1\5
${}\\{ero\_lopp}(\\{lop\_fixr},\39\|w);{}$\2\6
\&{else}\1\5
${}\|k\K\T{1};{}$\2\2\6
\&{else} \&{if} ${}(\|w\G\T{\^fff8}){}$\1\5
${}\\{ero\_lopp}(\\{lop\_fixr},\39\|w\AND\T{\^f});{}$\2\6
\&{else}\1\5
${}\|k\K\T{1};{}$\2\6
\4${}\}{}$\5
\2\&{else}\1\5
${}\\{ero\_lopp}(\\{lop\_fixr},\39\|w);{}$\2\6
\&{if} (\|k)\1\5
${}\\{dderr}(\.{"relative\ address\ in}\)\.{\ location\ \#\%01x\%04x\ }\)\.{is\
too\ far\ away"},\39\\{qq}\MG\\{seg},\39\\{qq}\MG\\{equiv});{}$\2\6
\4${}\}{}$\2\6
\&{else}\5
${}\{{}$\1\6
${}\|k\K\T{0};{}$\6
${}\|w\K\\{qq}\MG\\{equiv};{}$\6
\&{if} ${}(\|s\AND\\{nyb\_bit}){}$\5
${}\{{}$\1\6
\&{if} ${}(\R(\|w\AND\T{\^8000})){}$\1\6
\&{if} ${}(\|w<\T{\^8}){}$\1\5
${}\\{ero\_lopp}(\\{lop\_fixw},\39\|w);{}$\2\6
\&{else}\1\5
${}\|k\K\T{1};{}$\2\2\6
\&{else} \&{if} ${}(\|w\G\T{\^fff8}){}$\1\5
${}\\{ero\_lopp}(\\{lop\_fixw},\39\|w\AND\T{\^f});{}$\2\6
\&{else}\1\5
${}\|k\K\T{1};{}$\2\6
\4${}\}{}$\5
\2\&{else}\1\5
${}\\{ero\_lopp}(\\{lop\_fixr},\39\|w);{}$\2\6
\&{if} (\|k)\1\5
${}\\{dderr}(\.{"defined\ nybble\ in\ l}\)\.{ocation\ \#\%01x\%04x\ is}\)\.{\
too\ large"},\39\\{qq}\MG\\{seg},\39\\{qq}\MG\\{equiv});{}$\2\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
$\}{}$\par
\U110.\fi

\M{112}\B\X112:Make special listing to show the label equivalent\X${}\E{}$\6
\&{if} ${}(\\{new\_link}\E\.{DEFINED}){}$\5
${}\{{}$\1\6
${}\\{fprintf}(\\{listing\_file},\39\.{"(\%04x)"},\39\\{cur\_loc});{}$\6
\\{flush\_listing\_line}(\.{"\ "});\6
\4${}\}{}$\5
\2\&{else}\5
${}\{{}$\1\6
${}\\{fprintf}(\\{listing\_file},\39\.{"(\$\%02d)"},\39\\{cur\_loc}\AND\T{%
\^f});{}$\6
\\{flush\_listing\_line}(\.{"\ \ \ \ \ \ "});\6
\4${}\}{}$\2\par
\U107.\fi

\M{113}\B\X113:Do the operation\X${}\E{}$\6
$\\{future\_bits}\K\T{0};{}$\6
${}\\{arg\_num}\K\\{op\_bits}\AND\\{arg\_num\_bits};{}$\6
\&{if} ${}(\\{arg\_num}\E\T{3}){}$\1\5
\X114:Do a many-operand operation\X\2\6
\&{else}\5
\1\&{switch} (\\{arg\_num})\5
${}\{{}$\1\6
\4\&{case} \T{0}:\5
\&{if} ${}(\\{val\_ptr}>\T{1}){}$\1\5
${}\\{derr}(\.{"opcode\ `\%s'\ needs\ n}\)\.{o\ operand"},\39\\{op\_field});{}$%
\2\6
\X133:Do a one-operand operation\X;\6
\&{break};\6
\4\&{case} \T{1}:\5
\&{if} ${}(\\{val\_ptr}>\T{1}){}$\1\5
${}\\{derr}(\.{"opcode\ `\%s'\ needs\ o}\)\.{ne\ operand"},\39\\{op%
\_field});{}$\2\6
\X133:Do a one-operand operation\X;\6
\&{break};\6
\4\&{case} \T{2}:\5
\&{if} ${}(\\{val\_ptr}\I\T{2}){}$\1\5
${}\\{derr}(\.{"opcode\ `\%s'\ must\ ha}\)\.{ve\ two\ operands"},\39\\{op%
\_field}){}$\2\6
\X117:Do a two-operand operation\X;\6
\&{break};\6
\4\&{default}:\5
${}\\{derr}(\.{"too\ many\ operands\ f}\)\.{or\ opcode\ `\%s'"},\39\\{op%
\_field});{}$\6
\4${}\}{}$\2\2\par
\U101.\fi

\M{114}The many-operand operator is \PB{\.{WYDE}}.

\Y\B\4\X114:Do a many-operand operation\X${}\E{}$\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\\{val\_ptr};{}$ ${}\|j\PP){}$\5
${}\{{}$\1\6
\X115:Deal with cases where \PB{\\{val\_stack}[\|j]} is impure\X;\6
\&{if} ${}(\\{val\_stack}[\|j].\\{status}\E\\{undefined}\V\\{val\_stack}[\|j].%
\\{status}\E\\{rel\_undefined}){}$\1\5
${}\\{assemble}(\T{0},\39\T{\^f0});{}$\2\6
\&{else}\1\5
${}\\{assemble}(\\{val\_stack}[\|j].\\{equiv},\39\T{0});{}$\2\6
\4${}\}{}$\2\par
\U113.\fi

\M{115}\B\X115:Deal with cases where \PB{\\{val\_stack}[\|j]} is impure\X${}%
\E{}$\6
\&{if} ${}(\\{val\_stack}[\|j].\\{status}\G\\{ind\_pure}){}$\5
${}\{{}$\1\6
\\{err}(\.{"*indirect\ number\ us}\)\.{ed\ as\ a\ constant"})\6
${}\\{val\_stack}[\|j].\\{status}\MRL{-{\K}}\\{ind\_pure};{}$\6
\4${}\}{}$\2\6
\&{if} ${}(\\{val\_stack}[\|j].\\{status}\E\\{reg\_val}){}$\1\5
\\{err}(\.{"*register\ number\ us}\)\.{ed\ as\ a\ constant"})\2\6
\&{else} \&{if} ${}(\\{val\_stack}[\|j].\\{status}\E\\{undefined}){}$\5
${}\{{}$\1\6
${}\\{pp}\K\\{val\_stack}[\|j].\\{link}\MG\\{sym};{}$\6
${}\\{qq}\K\\{new\_sym\_node}(\\{false});{}$\6
${}\\{qq}\MG\\{link}\K\\{pp}\MG\\{link};{}$\6
${}\\{pp}\MG\\{link}\K\\{qq};{}$\6
${}\\{qq}\MG\\{serial}\K\\{cur\_seg};{}$\6
${}\\{qq}\MG\\{equiv}\K\\{cur\_loc};{}$\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\\{val\_stack}[\|j].\\{status}\E\\{rel\_undefined}){}$\5
${}\{{}$\1\6
${}\\{pp}\K\\{val\_stack}[\|j].\\{link}\MG\\{sym};{}$\6
${}\\{qq}\K\\{new\_sym\_node}(\\{false});{}$\6
${}\\{qq}\MG\\{link}\K\\{pp}\MG\\{link};{}$\6
${}\\{pp}\MG\\{link}\K\\{qq};{}$\6
${}\\{qq}\MG\\{serial}\K\\{cur\_seg}+\\{rel\_bit};{}$\6
${}\\{qq}\MG\\{equiv}\K\\{cur\_loc};{}$\6
\4${}\}{}$\2\par
\U114.\fi

\M{116}Individual fields of an instruction are placed into
global variables \PB{\|x}, \PB{\|y}, \PB{\|z}.

\Y\B\4\X26:Global variables\X${}\mathrel+\E{}$\6
\&{wyde} \|x${},{}$ \|y${},{}$ \|z;\C{ pieces for assembly }\6
\&{int} \\{future\_bits};\C{ places where there are future references }\6
\&{char} \\{addr\_mode};\C{ places where there are the addressing mode bits }%
\par
\fi

\M{117}\B\X117:Do a two-operand operation\X${}\E{}$\6
$\|z\K\T{0}{}$;\C{ Presuppose one-wyde code }\6
\X125:Find the addressing mode\X;\6
\&{switch} (\\{addr\_mode})\5
${}\{{}$\1\6
\4\&{case} \T{0}:\5
\X118:Check if this case is allowed by this instruction\X\6
\X120:Handle exceptions for 0 \PB{\\{addr\_mode}}\X\6
\X123:Do the SRC field, it have to be a constant\X;\6
\&{break};\6
\4\&{case} \T{1}:\5
\X118:Check if this case is allowed by this instruction\X\6
\X119:Change the $X$ and $Y$ fields\X\6
\X123:Do the SRC field, it have to be a constant\X\6
\&{break};\6
\4\&{case} \T{2}:\5
\X118:Check if this case is allowed by this instruction\X\6
\X121:Handle exceptions for 2 \PB{\\{addr\_mode}}\X\6
\X124:Do the SRC field, it have to be a register\X\6
\&{break};\6
\4\&{case} \T{3}:\5
\X118:Check if this case is allowed by this instruction\X\6
\X122:Handle exceptions for 3 \PB{\\{addr\_mode}}\X\6
\X126:Do the SRC field, it is indirect\X\6
\&{break};\6
\4${}\}{}$\2\6
\4\\{assemble\_DST}:\5
\X127:Do the DST field\X;\6
\4\\{assemble\_inst}:\5
${}\\{assemble}((\|x\LL\T{12})+((\\{opcode}+\\{addr\_mode})\LL\T{4})+\|y,\39%
\\{future\_bits});{}$\6
\&{if} (\|z)\1\5
\X130:Do the second wyde\X;\2\par
\U113.\fi

\M{118}\B\X118:Check if this case is allowed by this instruction\X${}\E{}$\6
\&{if} ${}(\R((\T{1}\LL(\T{2}+\\{addr\_mode}))\AND\\{op\_bits})){}$\1\5
${}\\{dderr}(\.{"addressing\ mode\ \%01}\)\.{d\ is\ not\ allowed\ by\ }\)\.{`%
\%s'"},\39\\{addr\_mode},\39\\{op\_field}){}$;\2\par
\U117.\fi

\M{119}\B\X119:Change the $X$ and $Y$ fields\X${}\E{}$\6
$\\{acc}\K\\{val\_stack}[\T{1}].\\{equiv};{}$\6
${}\\{val\_stack}[\T{1}].\\{equiv}\K\\{val\_stack}[\T{0}].\\{equiv};{}$\6
${}\\{val\_stack}[\T{0}].\\{equiv}\K\\{acc};{}$\6
${}\\{acc}\K\\{val\_stack}[\T{1}].\\{status};{}$\6
${}\\{val\_stack}[\T{1}].\\{status}\K\\{val\_stack}[\T{0}].\\{status};{}$\6
${}\\{val\_stack}[\T{0}].\\{status}\K\\{acc}{}$;\par
\U117.\fi

\M{120}\B\X120:Handle exceptions for 0 \PB{\\{addr\_mode}}\X${}\E{}$\6
\&{if} ${}(\\{opcode}\E\T{\^e5}){}$\5
${}\{{}$\C{ TRAP }\1\6
\&{if} ${}(\\{val\_stack}[\T{0}].\\{status}\I\\{reg\_val}\V\\{val\_stack}[%
\T{0}].\\{equiv}\E\T{0}){}$\1\5
${}\\{derr}(\.{"DST\ field\ of\ `\%s'\ s}\)\.{hould\ be\ a\ nonzero\ r}\)%
\.{egister"},\39\\{op\_field});{}$\2\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\I\\{pure}){}$\1\5
${}\\{derr}(\.{"SRC\ field\ of\ `\%s'\ s}\)\.{hould\ be\ a\ number"},\39\\{op%
\_field});{}$\2\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{equiv}>\T{\^f}){}$\1\5
\\{err}(\.{"SRC\ field\ doesn't\ f}\)\.{it\ in\ one\ unsigned\ n}\)\.{ybble"});%
\2\6
${}\|y\K\\{val\_stack}[\T{1}].\\{equiv}\AND\T{\^f}{}$;\5
\&{break};\6
\4${}\}{}$\2\par
\U117.\fi

\M{121}\B\X121:Handle exceptions for 2 \PB{\\{addr\_mode}}\X${}\E{}$\6
\&{if} ${}(\\{opcode}\E\T{\^e5}){}$\5
${}\{{}$\C{ RESUME }\1\6
\&{if} ${}(\\{val\_stack}[\T{0}].\\{status}\I\\{reg\_val}\V\\{val\_stack}[%
\T{0}].\\{equiv}){}$\1\5
${}\\{derr}(\.{"DST\ field\ of\ `\%s'\ s}\)\.{hould\ be\ the\ zero\ re}\)%
\.{gister"},\39\\{op\_field});{}$\2\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{equiv}>\T{\^f}){}$\1\5
\\{err}(\.{"*SRC\ field\ doesn't\ }\)\.{fit\ in\ one\ unsigned\ }\)%
\.{nybble"});\2\6
${}\|y\K\\{val\_stack}[\T{1}].\\{equiv}\AND\T{\^f},\39\|x\K\T{0},\39\\{addr%
\_mode}\K\T{0}{}$;\5
\&{goto} \\{assemble\_inst};\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\\{opcode}\E\T{\^c5}{}$)\C{ MOR }\1\6
${}\\{addr\_mode}\K\T{0};{}$\2\6
\&{else} \&{if} ${}(\\{opcode}\E\T{\^e6}{}$)\C{ SADD }\1\6
${}\\{addr\_mode}\K\T{0}{}$;\2\par
\U117.\fi

\M{122}\B\X122:Handle exceptions for 3 \PB{\\{addr\_mode}}\X${}\E{}$\6
${}\{{}$\1\6
\&{if} ${}(\\{opcode}\E\T{\^d5}){}$\5
${}\{{}$\C{ PUSH }\1\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\I\\{reg\_val}){}$\1\5
${}\\{derr}(\.{"SRC\ field\ of\ `\%s'\ s}\)\.{hould\ be\ a\ register"},\39\\{op%
\_field});{}$\2\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{equiv}>\T{\^f}){}$\1\5
\\{err}(\.{"*SRC\ field\ doesn't\ }\)\.{fit\ in\ one\ unsigned\ }\)%
\.{nybble"});\2\6
${}\|y\K\\{val\_stack}[\T{1}].\\{equiv}\AND\T{\^f},\39\\{addr\_mode}\K\T{0}{}$;%
\5
\&{goto} \\{assemble\_DST};\6
\4${}\}{}$\2\6
\&{else} \&{if} ${}(\\{opcode}\E\T{\^e7}{}$)\C{ POP }\1\6
${}\\{addr\_mode}\K\T{0};{}$\2\6
\4${}\}{}$\2\par
\U117.\fi

\M{123}\B\X123:Do the SRC field, it have to be a constant\X${}\E{}$\6
$\{$ \6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\E\\{undefined}){}$\1\5
\X128:Assemble SRC as a future reference\X\2\6
\&{else} \&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\E\\{rel\_undefined}){}$\1\5
\X129:Assemble SRC as a relative future reference\X\2\6
\&{else} \&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\E\\{reg\_val})$ $\\{derr}(%
\.{"*SRC\ field\ of\ `\%s'\ }\)\.{should\ not\ be\ a\ regi}\)\.{ster\ number"},%
\39\\{op\_field})$ \6
\&{else}\5
${}\{{}$\1\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{equiv}\Z\T{\^fff8}\W\\{val\_stack}[\T{1}].%
\\{equiv}>\T{\^7}){}$\1\5
\\{err}(\.{"*SRC\ field\ doesn't\ }\)\.{fit\ in\ one\ signed\ ny}\)\.{bble"});%
\2\6
${}\|y\K\\{val\_stack}[\T{1}].\\{equiv}\AND\T{\^f};{}$\6
\4${}\}{}$\2\6
$\}{}$\par
\U117.\fi

\M{124}\B\X124:Do the SRC field, it have to be a register\X${}\E{}$\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\I\\{reg\_val}){}$\1\5
${}\\{derr}(\.{"*SRC\ field\ of\ `\%s'\ }\)\.{should\ be\ a\ register}\)\.{\
number"},\39\\{op\_field});{}$\2\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{equiv}>\T{\^f}){}$\1\5
\\{err}(\.{"*SRC\ field\ doesn't\ }\)\.{fit\ in\ one\ unsigned\ }\)%
\.{nybble"});\2\6
${}\|y\K\\{val\_stack}[\T{1}].\\{equiv}\AND\T{\^f}{}$;\par
\Us117\ET126.\fi

\M{125}\B\X125:Find the addressing mode\X${}\E{}$\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\G\\{ind\_pure}){}$\1\5
${}\\{addr\_mode}\K\T{3};{}$\2\6
\&{else} \&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\E\\{reg\_val}){}$\1\6
\&{if} ${}(\\{val\_stack}[\T{0}].\\{status}\E\\{reg\_val}){}$\1\5
${}\\{addr\_mode}\K\T{2};{}$\2\6
\&{else}\1\5
${}\\{addr\_mode}\K\T{1};{}$\2\2\6
\&{else}\1\5
${}\\{addr\_mode}\K\T{0}{}$;\2\par
\U117.\fi

\M{126}\B\X126:Do the SRC field, it is indirect\X${}\E{}$\6
$\\{val\_stack}[\T{1}].\\{status}\MRL{-{\K}}\\{ind\_pure};{}$\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\E\\{reg\_val}){}$\5
${}\{{}$\1\6
\&{if} ${}(\R\\{val\_stack}[\T{1}].\\{equiv}){}$\1\5
${}\\{derr}(\.{"*SRC\ field\ of\ `\%s'\ }\)\.{should\ not\ be\ *\$0"},\39\\{op%
\_field});{}$\2\6
\X124:Do the SRC field, it have to be a register\X;\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\|y\K\T{0},\39\|z\K\T{1}{}$;\2\par
\U117.\fi

\M{127}\B\X127:Do the DST field\X${}\E{}$\6
\&{if} ${}(\\{val\_stack}[\T{0}].\\{status}\I\\{reg\_val}){}$\1\5
${}\\{derr}(\.{"*DST\ field\ of\ `\%s'\ }\)\.{should\ be\ a\ register}\)\.{\
number"},\39\\{op\_field});{}$\2\6
\&{if} ${}(\\{val\_stack}[\T{0}].\\{equiv}>\T{\^f}){}$\1\5
\\{err}(\.{"*DST\ field\ doesn't\ }\)\.{fit\ in\ one\ nybble"});\2\6
${}\|x\K\\{val\_stack}[\T{0}].\\{equiv}\AND\T{\^f}{}$;\par
\U117.\fi

\M{128}\B\X128:Assemble SRC as a future reference\X${}\E{}$\6
${}\{{}$\1\6
${}\\{pp}\K\\{val\_stack}[\T{0}].\\{link}\MG\\{sym};{}$\6
${}\\{qq}\K\\{new\_sym\_node}(\\{false});{}$\6
${}\\{qq}\MG\\{link}\K\\{pp}\MG\\{link};{}$\6
${}\\{pp}\MG\\{link}\K\\{qq};{}$\6
${}\\{qq}\MG\\{serial}\K\\{cur\_seg}+\\{nyb\_bit};{}$\6
${}\\{qq}\MG\\{equiv}\K\\{cur\_loc};{}$\6
${}\|y\K\T{0};{}$\6
${}\\{future\_bits}\K\T{\^80};{}$\6
\&{goto} \\{assemble\_DST};\6
\4${}\}{}$\2\par
\U123.\fi

\M{129}\B\X129:Assemble SRC as a relative future reference\X${}\E{}$\6
${}\{{}$\1\6
${}\\{pp}\K\\{val\_stack}[\T{0}].\\{link}\MG\\{sym};{}$\6
${}\\{qq}\K\\{new\_sym\_node}(\\{false});{}$\6
${}\\{qq}\MG\\{link}\K\\{pp}\MG\\{link};{}$\6
${}\\{pp}\MG\\{link}\K\\{qq};{}$\6
${}\\{qq}\MG\\{serial}\K\\{cur\_seg}+\\{nyb\_bit}+\\{rel\_bit};{}$\6
${}\\{qq}\MG\\{equiv}\K\\{cur\_loc};{}$\6
${}\|y\K\T{0};{}$\6
${}\\{future\_bits}\K\T{\^80};{}$\6
\&{goto} \\{assemble\_DST};\6
\4${}\}{}$\2\par
\U123.\fi

\M{130}\B\X130:Do the second wyde\X${}\E{}$\6
\&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\E\\{pure}){}$\1\5
${}\\{assemble}(\\{val\_stack}[\T{1}].\\{equiv},\39\T{0});{}$\2\6
\&{else} \&{if} ${}(\\{val\_stack}[\T{1}].\\{status}\E\\{undefined}){}$\1\5
\X131:Assemble YZ as a future reference\X\2\6
\&{else}\C{ \PB{$\\{val\_stack}[\T{1}].\\{status}\E\\{rel\_undefined}$} }\1\6
\X132:Assemble YZ as a relative future reference\X;\2\par
\U117.\fi

\M{131}\B\X131:Assemble YZ as a future reference\X${}\E{}$\6
${}\{{}$\1\6
${}\\{pp}\K\\{val\_stack}[\T{1}].\\{link}\MG\\{sym};{}$\6
${}\\{qq}\K\\{new\_sym\_node}(\\{false});{}$\6
${}\\{qq}\MG\\{link}\K\\{pp}\MG\\{link};{}$\6
${}\\{pp}\MG\\{link}\K\\{qq};{}$\6
${}\\{qq}\MG\\{serial}\K\\{cur\_seg};{}$\6
${}\\{qq}\MG\\{equiv}\K\\{cur\_loc};{}$\6
${}\\{assemble}(\T{0},\39\T{\^f0});{}$\6
\4${}\}{}$\2\par
\U130.\fi

\M{132}\B\X132:Assemble YZ as a relative future reference\X${}\E{}$\6
${}\{{}$\1\6
${}\\{pp}\K\\{val\_stack}[\T{1}].\\{link}\MG\\{sym};{}$\6
${}\\{qq}\K\\{new\_sym\_node}(\\{false});{}$\6
${}\\{qq}\MG\\{link}\K\\{pp}\MG\\{link};{}$\6
${}\\{pp}\MG\\{link}\K\\{qq};{}$\6
${}\\{qq}\MG\\{serial}\K\\{cur\_seg}+\\{rel\_bit};{}$\6
${}\\{qq}\MG\\{equiv}\K\\{cur\_loc};{}$\6
${}\\{assemble}(\T{0},\39\T{\^f0});{}$\6
\4${}\}{}$\2\par
\U130.\fi

\M{133}\B\X133:Do a one-operand operation\X${}\E{}$\6
\&{switch} (\\{opcode})\5
${}\{{}$\C{ Pseudo operations }\1\6
\4\&{case} \.{CODE}:\6
\&{if} ${}(\\{harvard}\W\\{cur\_seg}){}$\5
${}\{{}$\1\6
${}\\{cur\_data\_loc}\K\\{cur\_loc};{}$\6
${}\\{cur\_loc}\K\\{cur\_code\_loc};{}$\6
${}\\{cur\_seg}\K\T{0};{}$\6
\4${}\}{}$\5
\2\&{goto} \\{bypass};\6
\4\&{case} \.{DATA}:\6
\&{if} ${}(\\{harvard}\W\R\\{cur\_seg}){}$\5
${}\{{}$\1\6
${}\\{cur\_code\_loc}\K\\{cur\_loc};{}$\6
${}\\{cur\_loc}\K\\{cur\_data\_loc};{}$\6
${}\\{cur\_seg}\K\\{harvard};{}$\6
\4${}\}{}$\5
\2\&{goto} \\{bypass};\6
\4\&{case} \.{LOC}:\5
${}\\{cur\_loc}\K\\{val\_stack}[\T{0}].\\{equiv};{}$\6
\4\&{case} \.{IS}:\5
\&{goto} \\{bypass};\6
\4\&{case} \.{PREFIX}:\5
\&{if} ${}(\R\\{val\_stack}[\T{0}].\\{link}){}$\1\5
\\{err}(\.{"not\ a\ valid\ prefix"});\2\6
${}\\{cur\_prefix}\K\\{val\_stack}[\T{0}].\\{link}{}$;\5
\&{goto} \\{bypass};\6
\4\&{case} \.{GREG}:\5
\&{if} (\\{listing\_file})\1\5
\X135:Make listing for \PB{\.{GREG}}\X;\2\6
\&{goto} \\{bypass};\6
\4\&{case} \.{BSPEC}:\5
\&{if} ${}(\\{val\_stack}[\T{0}].\\{equiv}>\T{\^ffff}){}$\1\5
\\{err}(\.{"*operand\ of\ `BSPEC'}\)\.{\ doesn't\ fit\ in\ a\ wy}\)\.{de"});\2\6
\\{ero\_loc}(\,);\5
\\{ero\_sync}(\,);\6
${}\\{ero\_lopp}(\\{lop\_spec},\39\\{val\_stack}[\T{0}].\\{equiv});{}$\6
${}\\{spec\_mode}\K\\{true}{}$;\5
${}\\{spec\_mode\_loc}\K\T{0}{}$;\5
\&{goto} \\{bypass};\6
\4\&{case} \.{ESPEC}:\5
${}\\{spec\_mode}\K\\{false}{}$;\5
\&{goto} \\{bypass};\6
\4${}\}{}$\2\par
\U113.\fi

\M{134}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{wyde} \\{greg\_val}[\T{256}];\C{ initial values of global registers }\par
\fi

\M{135}\B\X135:Make listing for \PB{\.{GREG}}\X${}\E{}$\6
$\\{fprintf}(\\{listing\_file},\39\.{"(\$\%02d=\#\%04x"},\39\\{greg},\39\\{val%
\_stack}[\T{0}].\\{equiv});{}$\6
\\{flush\_listing\_line}(\.{"\ "});\par
\U133.\fi

\N{1}{136}Running the program. On a \UNIX/-like system, the command
$$\.{eriscal [options] sourcefilename}$$
will assemble the \ERISCAL\ program in file \.{sourcefilename},
writing any error messages on the standard error file. (Nothing is written to
the standard output.) The options, which may appear in any order, are:

\bull\.{-o objectfilename}\quad Send the output to a binary file called
\.{objectfilename}.
If no \.{-o} specification is given, the object file name is obtained from the
input file name by changing the final letter from `\.s' to~`\.o', or by
appending `\.{.ero}' if \.{sourcefilename} doesn't end with~\.s.

\bull\.{-l listingname}\quad Output a listing of the assembled input and
output to a text file called \.{listingname}.

\bull\.{-h}\quad Allow Harward type architecture, assembling data to a
separate space from instructions.

\bull\.{-b bufsize}\quad Allow up to \.{bufsize} characters per line of input.

\fi

\M{137}Here, finally, is the overall structure of this program.

\Y\B\8\#\&{include} \.{<stdio.h>}\6
\8\#\&{include} \.{<stdlib.h>}\6
\8\#\&{include} \.{<ctype.h>}\6
\8\#\&{include} \.{<string.h>}\6
\8\#\&{include} \.{<time.h>}\7
\X32:Preprocessor definitions\X\6
\X25:Type definitions\X\6
\X26:Global variables\X\6
\X27:Subroutines\X\7
\&{int} ${}\\{main}(\\{argc},\39\\{argv}){}$\1\1\6
\&{int} \\{argc};\5
\&{char} ${}{*}\\{argv}[\,];\2\2{}$\6
${}\{{}$\1\6
\&{register} \&{int} \|j${},{}$ \|k;\C{ all-purpose integers }\7
\X41:Local variables\X;\6
\X138:Process the command line\X;\6
\X33:Initialize everything\X;\6
\&{while} (\T{1})\5
${}\{{}$\1\6
\X35:Get the next line of input text, or \PB{\&{break}} if the input has ended%
\X;\6
\&{while} (\T{1})\5
${}\{{}$\1\6
\X101:Process the next \ERISCAL\ instruction or comment\X;\6
\&{if} ${}(\R{*}\\{buf\_ptr}){}$\1\5
\&{break};\2\6
\4${}\}{}$\2\6
\&{if} (\\{listing\_file})\5
${}\{{}$\1\6
\&{if} (\\{listing\_bits})\1\5
\\{listing\_clear}(\,);\2\6
\&{else} \&{if} ${}(\R\\{line\_listed}){}$\1\5
\\{flush\_listing\_line}(\.{"\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ }\)\.{"});\2%
\6
\4${}\}{}$\2\6
\4${}\}{}$\2\6
\X143:Finish the assembly\X;\6
\4${}\}{}$\2\par
\fi

\M{138}\B\X138:Process the command line\X${}\E{}$\6
\&{for} ${}(\|j\K\T{1};{}$ ${}\|j<\\{argc}-\T{1}\W\\{argv}[\|j][\T{0}]\E%
\.{'-'};{}$ ${}\|j\PP){}$\1\6
\&{if} ${}(\R\\{argv}[\|j][\T{2}]){}$\5
${}\{{}$\1\6
\&{if} ${}(\\{argv}[\|j][\T{1}]\E\.{'h'}){}$\1\5
${}\\{harvard}\K\\{true};{}$\2\6
\&{else} \&{if} ${}(\\{argv}[\|j][\T{1}]\E\.{'o'}){}$\1\5
${}\|j\PP,\39\\{strcpy}(\\{obj\_file\_name},\39\\{argv}[\|j]);{}$\2\6
\&{else} \&{if} ${}(\\{argv}[\|j][\T{1}]\E\.{'l'}){}$\1\5
${}\|j\PP,\39\\{strcpy}(\\{listing\_name},\39\\{argv}[\|j]);{}$\2\6
\&{else} \&{if} ${}(\\{argv}[\|j][\T{1}]\E\.{'b'}\W\\{sscanf}(\\{argv}[\|j+%
\T{1}],\39\.{"\%d"},\39{\AND}\\{buf\_size})\E\T{1}){}$\1\5
${}\|j\PP;{}$\2\6
\&{else}\1\5
\&{break};\2\6
\4${}\}{}$\5
\2\&{else} \&{if} ${}(\\{argv}[\|j][\T{1}]\I\.{'b'}\V\\{sscanf}(\\{argv}[\|j]+%
\T{2},\39\.{"\%d"},\39{\AND}\\{buf\_size})\I\T{1}){}$\1\5
\&{break};\2\2\6
\&{if} ${}(\|j\I\\{argc}-\T{1}){}$\5
${}\{{}$\1\6
${}\\{fprintf}(\\{stderr},\39\.{"Usage:\ \%s\ \%s\ source}\)\.{filename\\n"},%
\39\\{argv}[\T{0}],\39\.{"[-l\ listingname]\ [-}\)\.{b\#]\ [-h]\ [-o\ objectf}%
\)\.{ilename]"});{}$\6
${}\\{exit}({-}\T{1});{}$\6
\4${}\}{}$\2\6
${}\\{src\_file\_name}\K\\{argv}[\|j]{}$;\par
\U137.\fi

\M{139}\B\X139:Open the files\X${}\E{}$\6
$\\{src\_file}\K\\{fopen}(\\{src\_file\_name},\39\.{"r"});{}$\6
\&{if} ${}(\R\\{src\_file}){}$\1\5
${}\\{dpanic}(\.{"Can't\ open\ the\ sour}\)\.{ce\ file\ \%s"},\39\\{src\_file%
\_name});{}$\2\6
\&{if} ${}(\R\\{obj\_file\_name}[\T{0}]){}$\5
${}\{{}$\1\6
${}\|j\K\\{strlen}(\\{src\_file\_name});{}$\6
\&{if} ${}(\\{src\_file\_name}[\|j-\T{1}]\E\.{'s'}){}$\5
${}\{{}$\1\6
${}\\{strcpy}(\\{obj\_file\_name},\39\\{src\_file\_name}){}$;\5
${}\\{obj\_file\_name}[\|j-\T{1}]\K\.{'o'};{}$\6
\4${}\}{}$\2\6
\&{else}\1\5
${}\\{sprintf}(\\{obj\_file\_name},\39\.{"\%s.ero"},\39\\{src\_file\_name});{}$%
\2\6
\4${}\}{}$\2\6
${}\\{obj\_file}\K\\{fopen}(\\{obj\_file\_name},\39\.{"wb"});{}$\6
\&{if} ${}(\R\\{obj\_file}){}$\1\5
${}\\{dpanic}(\.{"Can't\ open\ the\ obje}\)\.{ct\ file\ \%s"},\39\\{obj\_file%
\_name});{}$\2\6
\&{if} (\\{listing\_name}[\T{0}])\5
${}\{{}$\1\6
${}\\{listing\_file}\K\\{fopen}(\\{listing\_name},\39\.{"w"});{}$\6
\&{if} ${}(\R\\{listing\_file}){}$\1\5
${}\\{dpanic}(\.{"Can't\ open\ the\ list}\)\.{ing\ file\ \%s"},\39\\{listing%
\_name});{}$\2\6
\4${}\}{}$\2\par
\U141.\fi

\M{140}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{char} ${}{*}\\{src\_file\_name}{}$;\C{ name of the \ERISCAL\ input file }\6
\&{char} ${}\\{obj\_file\_name}[\.{FILENAME\_MAX}+\T{1}]{}$;\C{ name of the
binary output file }\6
\&{char} ${}\\{listing\_name}[\.{FILENAME\_MAX}+\T{1}]{}$;\C{ name of the
optional listing file }\6
\&{FILE} ${}{*}\\{src\_file},{}$ ${}{*}\\{obj\_file},{}$ ${}{*}\\{listing%
\_file};{}$\6
\&{bool} \\{harvard};\C{ 1 if separate data memory, else 0 }\6
\&{int} \\{buf\_size};\C{ maximum number of characters per line of input }\6
\&{tetra} \\{present\_time};\C{ THE time }\par
\fi

\M{141}\B\X33:Initialize everything\X${}\mathrel+\E{}$\6
\X139:Open the files\X;\6
${}\\{filename}[\T{0}]\K\\{src\_file\_name};{}$\6
${}\\{filename\_count}\K\T{1};{}$\6
\X142:Output the preamble\X;\par
\fi

\M{142}\B\X142:Output the preamble\X${}\E{}$\6
$\\{ero\_lopp}(\\{lop\_pre},\39\T{3});{}$\6
\\{ero\_wyde}(\T{\^101});\6
${}\\{present\_time}\K\\{time}(\NULL);{}$\6
${}\\{ero\_wyde}(\\{present\_time}\GG\T{16});{}$\6
${}\\{ero\_wyde}(\\{present\_time}\AND\T{\^ffff});{}$\6
${}\\{ero\_cur\_file}\K{-}\T{1}{}$;\par
\U141.\fi

\M{143}\B\X143:Finish the assembly\X${}\E{}$\6
\X145:Output the postamble\X;\6
\X79:Check and output the trie\X;\6
\X146:Report any undefined local symbols\X;\6
\&{if} (\\{err\_count})\1\6
\&{if} ${}(\\{err\_count}>\T{1}){}$\1\5
${}\\{fprintf}(\\{stderr},\39\.{"(\%d\ errors\ were\ fou}\)\.{nd.)\\n"},\39%
\\{err\_count});{}$\2\6
\&{else}\1\5
${}\\{fprintf}(\\{stderr},\39\.{"(One\ error\ was\ foun}\)\.{d.)\\n"});{}$\2\2\6
\\{exit}(\\{err\_count});\par
\U137.\fi

\M{144}\B\X26:Global variables\X${}\mathrel+\E{}$\6
\&{int} \\{greg}${}\K\T{0}{}$;\C{ global register allocator }\par
\fi

\M{145}\B\X145:Output the postamble\X${}\E{}$\6
$\\{ero\_lopp}(\\{lop\_post},\39\\{greg}+\T{1});{}$\6
${}\\{greg\_val}[\T{0}]\K\\{trie\_search}(\\{trie\_root},\39\.{"Main"})\MG%
\\{sym}\MG\\{equiv};{}$\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j\Z\\{greg};{}$ ${}\|j\PP){}$\1\5
\\{ero\_wyde}(\\{greg\_val}[\|j]);\2\par
\U143.\fi

\M{146}\B\X146:Report any undefined local symbols\X${}\E{}$\6
\&{for} ${}(\|j\K\T{0};{}$ ${}\|j<\T{10};{}$ ${}\|j\PP){}$\1\6
\&{if} ${}(\\{forward\_local}[\|j].\\{link}){}$\1\5
${}\PP\\{err\_count},\39\\{fprintf}(\\{stderr},\39\.{"undefined\ local\ sym}\)%
\.{bol\ \%dF\\n"},\39\|j){}$;\2\2\par
\U143.\fi

\N{1}{147}Index.

\fi


\inx
\fin
\con
