 |
Technical Information |
The actual symbol table entries (pointed to by the hash table,
colliding entries are linked together) are stored in 8K chunks which
are allocated as required. The first entry of each chunk is reserved
as a link to the next chunk (or NULL in the last chunk) - this makes
it easy to find all the chunks to free them when we're finished. All
symbol table entries are stored in pass 1. During pass 2, cross-
reference table entries are built in the same group of chunks,
immediately following the last symbol table entry. Additional chunks
will continue to be linked in if necessary.
Symbol names and macro text are stored in another series of linked
chunks. These chunks consist of a link pointer followed by strings
(terminated by nulls) laid end to end. Symbols are independent entries,
linked from the corresponding symbol table entry. Macros are stored as
consecutive strings, one per line - the end of the macro is indicated by
an ENDM
statement. If a macro spans two chunks, the last line in the
original chunk is followed by a newline character to indicate that the
macro is continued in the next chunk.
Relocation information is built during pass 2 in yet another
series of linked chunks. If more than one chunk is needed to hold one
section's relocation information, all additional chunks are released
at the end of the section.
The secondary heap is built from both ends, and it grows and
shrinks according to how many macros and INCLUDE
files are currently
open. At all times there will be at least one entry on the heap, for
the original source code file. The expression parser also uses the
secondary heap to store its working stacks - this space is freed as
soon as an expression has been evaluated.
The bottom of the heap holds the names of the source code file
and any macro or INCLUDE
files that are currently open. The full path
is given. A null string is stored for user macros. Macro arguments
are stored by additional strings, one for each argument in the macro
call line. All strings are stored in minimum space, similar to the
labels and user macro text on the primary heap. File names are
pointed to by the fixed table entries (see below) - macro arguments
are accessed by stepping past the macro name to the desired argument,
unless NARG would be exceeded.
The fixed portion of the heap is built down from the top. Each
entry occupies 16 bytes. Enough information is stored to return to
the proper position in the outer file once the current macro or
INCLUDE
file has been completely processed.
The diagram below illustrates the layout of the secondary heap.
Heap2 + maxheap2 -----------> ___________________________
| |
| Input file table |
struct InFCtl *InF ---------> |___________________________|
| |
| Parser operator stack |
struct OpStack *Ops --------> |___________________________|
| |
| (unused space) |
struct TermStack *Term -----> |___________________________|
| |
| Parser term stack |
char *NextFNS --------------> |___________________________|
| |
| Input file name stack |
char *Heap2 ----------------> |___________________________|
The "high-water mark" for NextFNS
is stored in char *High2
,
and the "low-water mark" (to stretch a metaphor) for InF
is stored
in struct InFCtl *LowInF
. These figures are used only to determine
the maximum heap usage.