PASS0

PASS0: setup and dialog

What it does

PASS0 is the first of the three programs that make up the compiler. It talks to the user, prepares DOS and memory for the compilation, and leaves everything the later passes need in the COMMON block it defines. It does no compiling itself. Its work, in order:

  1. Changes six bytes of DOS so that the tokenized Applesoft source can be read through DOS's text-file READ.
  2. Asks for the source file, the object file, the memory layout and the compiler options, checking each answer.
  3. Builds the tables the code generator uses (the call table and the operator table) and loads a small machine-language helper into page 3.
  4. Sets up the symbol table's chain heads, creates the object file, empties the line number file, and runs PASS1 with BRUN.

Everything PASS0 hands on lives in the COMMON block, which PASS0 declares with REM! DEFCOMMON and PASS1 and PASS2 declare with REM! USECOMMON in exactly the same order. REM! CLEAR CHAIN just before the BRUN sets up string storage so the COMMON strings survive the chain.

Flow

  1. DOS and memory (line 100). NOMONC,I,O stops DOS echoing commands, MAXFILES3 gives three file buffers (source, object, line number file), and HIMEM: 38400 keeps strings below the DOS buffers at $9600. The six DOS patches are read from the DATA statement at line 170; each original byte is saved in DP() for the restore at the end of the compilation (line 180).
  2. Fixed values (line 230). The library routine that resets the stack (EL), the library length (LM, 4013), the default library address (DH, $0803), the DOS command strings, and the boot drive: DOS's last-used slot and drive ($AA6A, $AA68) become SQ, DO and DN$; the slot also gives the drive motor switches MX and MN, and $AA52 is DOS's output state byte DW.
  3. Source file (line 400). The title, then SOURCE FILE?. The answer is split into a name and a slot/drive part (line 2800) and checked by running APPEND on it, which fails with FILE NOT FOUND if the file is missing (line 600, line 3480). The file is closed again at line 700.
  4. Object file (line 700). The default is the source name, cut to 26 characters, plus .OBJ, on the source file's drive. Any other answer is split the same way (line 900).
  5. Memory layout (line 960). The default puts the library at $0803, the program right after it and the variables after the program. Otherwise three addresses are asked for: the library (line 1060), the program (a number, HGR1 = $4000 or HGR2 = $6000, line 1220) and the variables (line 1420); each is checked by the address routine (line 3220). The layout is shown and confirmed (line 1500).
  6. Options (line 1630). The default is listing, pause on errors, integer arithmetic and integer constants on, RESUME/debug code off; otherwise each is asked in turn. Return alone accepts the default.
  7. Tables (line 2060, line 2160, line 2240). The call table and the operator table are read from DATA into the symbol table array SC() at 150 and 300, where PASS1 picks them up; the 89 bytes of machine code are POKEd into $0377-$03CF and the USR vector at $0A is pointed at $0377.
  8. Symbol table (line 2310). 32 hash chains each for variables, constants and line numbers, and the addresses of the page-3 routines.
  9. Files and chain (line 2440). A one-byte BSAVE creates the object file as a binary file; the line number file is opened, deleted and opened again so it is empty; then BRUN PASS1 on the boot drive.

How the dialog is built

The questions do not call their checks with GOSUB. A question stores a number in QH, saying which question is being answered, and jumps (GOTO) to a shared check. The check ends with ON QH GOTO, which returns to the code after that question (line 3410 for addresses, line 3590 for files). After every check, BZ = 1 means the answer was refused and the question is asked again.

Subroutines

LineWhat it does
line 2570Yes/no answer into XB; BZ = 1 if neither
line 2700Read a line from the keyboard into LU$
line 2800Split a file specification into NM$ (name, trimmed, at most 30 characters) and SY$ (,Sn,Dn, the boot drive's slot or drive filled in where missing); clears SC when the file is on another slot or drive
line 3200Report an illegal file specification
line 3220Convert an address answer into AD; returns through ON QH GOTO
line 3450Check a file answer; line 3480 runs a DOS command under ONERR; returns through ON QH GOTO

Stored addresses

Integer variables hold -32767 to 32767, so an address is usually kept as address-32767 and turned back with +32767 (FN SA and FN RA in this pass; the other passes have the same pair). Addresses that are POKEd or PEEKed are kept as signed words instead, address-65536 above 32767 (FN SW): that is how DP(I,0), MX, MN and DW are stored.

The COMMON block

PASS0 defines it at the start of program space ($17B0, right after the library) and moves the program start to $41F2. Numbers come first, then strings; every pass declares the same names in the same order.

VariablesMeaning
NU, NG, NKNumber of hash chains for variables, constants and line numbers (32 each)
VO, KX, L, HWFirst variable, constant and line number chain head in SC(), and the last chain head (9, 41, 73, 104)
MX, MN, SCDrive motor on and off switches; SC = 1 if both files are on the boot drive, so its motor is kept running
DWDOS's output state byte ($AA52)
ELLibrary routine at $0947 that resets the stack and the DATA pointer
LMLibrary length (4013)
UV, KV, QB, WS, IX, LQPage-3 code: USR entry, packed-number bytes, read a byte, write a byte, transfer cell, list a line
LB, UR, VCLibrary, program and variables addresses (stored as address-32767; VC = -32767 means after the program)
PCAddress of the next object byte (stored)
LHNumber of source lines read
CDStart of the COMMON block of the program being compiled
CCLatest link of the DATA chain
EDObject file base: file position = address - ED
O4, OO, N1, P8, OHOptions: listing, pause, RESUME/debug, integer arithmetic, integer constants
FC1 after a fatal error
C3COMMON kind of the program being compiled: -1 none, 0 define, 255 use
DP()The six DOS patch addresses and their original bytes
SC()The symbol table, 5351 words
BP$, DI$Two bells; Control-D
OP$, CO$, RV$, WO$DOS OPEN, CLOSE, READ and WRITE commands
SI$, SB$, OD$, OO$Source and object file names and their slot/drive parts
LN$, DN$The line number file CLINENUM and the boot drive's ,Sn,Dn

Data

DOS patches (DATA at line 170)

Address, new byte, original byte, six times. Together they let DOS read the Applesoft program file as text, byte for byte:

AddressChangeEffect
$A633-$A635BNE $A644 / JSR $A2FC becomes JMP $A644a zero byte (the end of each tokenized line) no longer ends the data read
$A649AND #$7F becomes AND #$FFbytes keep bit 7, so tokens survive
$A7C4becomes RTSthe file type is not checked: the A-type source opens as a text file
$A96C$7F becomes $FFthe B (byte position) parameter may go up to 65535

Call table (DATA at line 2000)

136 entries, the routines compiled code calls, by index. A positive entry is an offset from the library address (2912 is $0803+2912 = $1363, the library's END); a negative entry is minus a ROM address (-57612 is $E10C, AYINT). PASS0 turns each into a stored address and puts it in SC(150) to SC(285). For a routine with a real and an integer form the table holds one of them; the other is 3 bytes away.

Operator table (DATA at line 2150)

17 operators, three numbers each: the token, its priority on the parse stack, and its priority when it arrives. ( 1/14, ) 13/1, NOT 13/14, + - 9/8, * / 11/10, ^ 13/12, AND 5/4, OR 3/2, the relations 7/6, negation 13/14. PASS1 reduces while the operator on the stack has a higher priority than the one arriving.

Page-3 machine code (DATA at line 2200)

89 bytes POKEd into $0377-$03CF (line 2240):

EntryWhat it does
$0377USR: stores the floating point accumulator, rounded, as 5 packed bytes at $0371-$0375 (how PASS1 packs a numeric constant)
$037Ereads one byte with RDKEY into $0376; with DOS reading a file, the byte comes from the file
$0387prints the byte in $0376 with COUT; with DOS writing a file, it goes to the file
$038Dlists the tokenized line in the input buffer at $0280, spelling tokens from the ROM's keyword table (the compilation listing)

Symbol table chain heads (set at line 2310)

SC(0) heads the list of COMMON declarations; 1-4 are the FN chains, 5-8 the temporaries (5 integer, 6 string, 7 real, 8 inside DEF FN), 9-40 the variable chains, 41-72 the constant chains and 73-104 the line number chains. PASS0 zeroes them all. The call and operator tables lie above them, in the space where PASS1 later allocates entries: PASS1 copies the tables out before it allocates anything.