PASS0

Pass 0: dialog, DOS patches, tables, then runs pass 1. Each section's comment stands above it, each line's comments beside it; point at a name for its meaning; line numbers after GOTO, GOSUB and THEN are links.

Sections (23)
  1. 10 DECLARATIONS: INTEGER VARIABLES, ARRAYS AND THE COMMON BLOCK
  2. 100 PASS 0 OF THE COMPILER
  3. 400 TITLE AND THE SOURCE FILE QUESTION
  4. 600 THE SOURCE FILE'S NAME WAS CHECKED: IT MUST EXIST
  5. 700 THE SOURCE FILE EXISTS; THE OBJECT FILE QUESTION, ITS DEFAULT THE SOURCE NAME (UP TO 26 CH
  6. 900 THE OBJECT FILE'S NAME WAS CHECKED
  7. 960 MEMORY USAGE: THE DEFAULT, OR THE THREE ADDRESSES
  8. 1200 THE LIBRARY ADDRESS WAS CHECKED
  9. 1400 THE PROGRAM ADDRESS WAS CHECKED
  10. 1500 THE VARIABLES ADDRESS WAS CHECKED; SHOW THE LAYOUT AND CONFIRM IT
  11. 1630 OPTIONS: THE DEFAULT, OR EACH OPTION IN TURN
  12. 2060 THE CALL TABLE
  13. 2160 THE OPERATOR TABLE (TOKEN, STACK PRIORITY, ARRIVING PRIORITY) IN SC(300..350) FOR PASS 1
  14. 2240 THE MACHINE CODE AT $0377-$03CF
  15. 2310 THE SYMBOL TABLE'S CHAIN HEADS AND THE ADDRESSES OF THE MACHINE CODE ROUTINES
  16. 2440 CREATE THE OBJECT FILE, EMPTY THE LINE NUMBER FILE, AND RUN PASS 1
  17. 2570 YES/NO ANSWER
  18. 2700 READ A LINE FROM THE KEYBOARD INTO LU$ (CONTROL-C STOPS)
  19. 2800 SPLIT THE FILE SPECIFICATION IN LU$ INTO NM$ (THE NAME, LEADING SPACES REMOVED, TRAILING S
  20. 3200 REPORT AN ILLEGAL FILE SPECIFICATION
  21. 3220 CONVERT THE ADDRESS IN AB$ (DECIMAL, OR HEXADECIMAL AFTER $) INTO AD; BZ = 1 IF IT IS NOT
  22. 3450 CHECK AN ANSWER
  23. 3480 ... ENTRY

10DECLARATIONS: INTEGER VARIABLES, ARRAYS AND THE COMMON BLOCK

10REM ! INTEGER MN,EL,SC

INTEGER VARIABLES

EL IS LIBRARY ROUTINE ($0947) THAT RESETS THE STACK, DROPPING EVERY PENDING GOSUB AND FOR, AND RESETS THE DATA POINTER; CALLED AFTER AN ERROR

MN IS DRIVE MOTOR-OFF SWITCH FOR THE BOOT SLOT

SC IS 1 IF THE SOURCE AND OBJECT FILES ARE ON THE BOOT DRIVE (MOTOR KEPT ON), ELSE 0

SC() IS SYMBOL TABLE: CHAIN HEADS, THEN ENTRIES LINKED THROUGH THEIR FIRST WORD

20REM ! INTEGER P8,N1,OO,O4

INTEGER VARIABLES

N1 IS RESUME/DEBUG CODE OPTION (1 = YES)

O4 IS COMPILATION LISTING OPTION (1 = YES)

OO IS PAUSE ON ERRORS OPTION (1 = YES)

P8 IS INTEGER ARITHMETIC OPTION (1 = YES)

30REM ! INTEGER QB,KV,WS,FC,C3

INTEGER VARIABLES

C3 IS COMMON KIND: -1 NONE, 0 DEFINE, 255 USE

FC IS 1 ONCE A FATAL ERROR HAS BEEN REPORTED (NO MORE CODE IS WRITTEN)

KV IS ADDRESS OF THE FIVE PACKED BYTES LEFT BY THE USR ROUTINE ($0371)

QB IS ADDRESS OF THE ROUTINE THAT READS ONE BYTE FROM THE OPEN FILE INTO IX ($037E)

WS IS ADDRESS OF THE ROUTINE THAT WRITES THE BYTE IN IX TO THE OPEN FILE ($0387)

40REM ! INTEGER VC,LB,CD,LH,DW

INTEGER VARIABLES

CD IS START OF THE COMMON BLOCK (THE PROGRAM START BEFORE COMMON MOVED IT)

DW IS DOS STATE BYTE AT $AA52: POKED BEFORE EACH DIRECT FILE READ OR WRITE

LB IS LIBRARY ADDRESS, STORED AS ADDRESS-32767

LH IS NUMBER OF SOURCE LINES READ

VC IS VARIABLES ADDRESS ASKED FOR, AS ADDRESS-32767, OR -32767 FOR END OF PROGRAM

50REM ! INTEGER HW,NG,NK,NU,MX,LQ,OH,UV,VO,LM,IX,PC,ED,CC,UR,L,KX,DP(5,1),SC(5350)

INTEGER VARIABLES

CC IS ADDRESS OF THE LINK WORD OF THE LAST DATA BLOCK (DATA BLOCKS ARE CHAINED)

DP() IS DOS PATCH TABLE: DP(I,0) ADDRESS (AS A SIGNED WORD, ADDRESS-65536), DP(I,1) ORIGINAL BYTE

ED IS OBJECT FILE BASE: FILE POSITION = PC - ED (THE FILE STARTS WITH THE BSAVE HEADER)

HW IS LAST CHAIN HEAD IN SC(); ENTRIES ARE ALLOCATED ABOVE IT

IX IS ADDRESS OF THE ONE-BYTE TRANSFER CELL FOR QB AND WS ($0376)

KX IS FIRST CONSTANT CHAIN HEAD IN SC()

L IS FIRST LINE NUMBER CHAIN HEAD IN SC()

LM IS LENGTH OF THE RUNTIME LIBRARY IN BYTES (4013)

LQ IS ADDRESS OF THE ROUTINE THAT LISTS THE TOKENIZED LINE IN THE INPUT BUFFER ($038D)

MX IS DRIVE MOTOR-ON SWITCH FOR THE BOOT SLOT ($C089+SLOT*16), TOUCHED TO KEEP THE DRIVE SPINNING

NG IS NUMBER OF CONSTANT HASH CHAINS (32)

NK IS NUMBER OF LINE NUMBER HASH CHAINS (32)

NU IS NUMBER OF VARIABLE HASH CHAINS IN THE SYMBOL TABLE (32)

OH IS INTEGER CONSTANTS OPTION (1 = YES)

PC IS ADDRESS OF THE NEXT OBJECT CODE BYTE, AS ADDRESS-32767

UR IS PROGRAM START, STORED AS ADDRESS-32767; MOVED UP BY COMMON DECLARATIONS

UV IS ADDRESS OF THE USR ROUTINE THAT PACKS A NUMBER INTO FIVE BYTES ($0377)

VO IS FIRST VARIABLE CHAIN HEAD IN SC() (9; 1-4 HOLD FN AND LINE SYMBOLS, 5-8 TEMPORARIES)

60REM ! DEFCOMMON NU,NG,NK,VO,KX,L,HW,MX,MN,DW,EL,LM,UV,KV,QB,WS,IX,LQ,LB,UR,VC,PC,LH,CD,CC,ED,SC,O4,OO,N1,P8,OH,FC,C3,DP(5,1),SC(5350),BP$,DI$,OP$,CO$,RV$,WO$,SI$,OD$,LN$,DN$,SB$,OO$

COMMON BLOCK, IN THE ORDER IT IS LAID OUT: NUMBERS FIRST, THEN STRINGS. THE PASSES SHARE IT, SO EVERY PASS DECLARES IT THE SAME WAY

BP$ IS TWO BELLS, SOUNDED BEFORE EACH ERROR MESSAGE

CO$ IS DOS CLOSE COMMAND

DI$ IS CONTROL-D, THE DOS COMMAND PREFIX

DN$ IS SLOT AND DRIVE OF THE BOOT DRIVE (",S6,D1")

LN$ IS NAME OF THE LINE NUMBER FILE ("CLINENUM")

OD$ IS OBJECT FILE NAME

OO$ IS SLOT AND DRIVE OF THE OBJECT FILE

OP$ IS DOS OPEN COMMAND

RV$ IS DOS READ COMMAND

SB$ IS SLOT AND DRIVE OF THE SOURCE FILE

SI$ IS SOURCE FILE NAME

WO$ IS DOS WRITE COMMAND

100PASS 0 OF THE COMPILER: PATCHES DOS, ASKS FOR THE SOURCE AND OBJECT FILES, THE MEMORY LAYOUT AND THE OPTIONS, LOADS THE CALL TABLE, THE OPERATOR TABLE AND THE MACHINE CODE AT $0377-$03CF, SETS UP THE COMMON BLOCK AND RUNS PASS 1. SET UP DOS AND THE STRINGS

100AB$ = "COPYRIGHT(C)1981,MICROSOFT"

AB$ IS THE ANSWER TYPED AT A QUESTION

110PRINT CHR$ (4);"NOMONC,I,O"

NO ECHO OF DOS COMMANDS, INPUT OR OUTPUT

120PRINT CHR$ (4);"MAXFILES3"

THREE FILE BUFFERS: SOURCE, OBJECT, LINE NUMBER FILE

130HIMEM: 38400

KEEP THE PROGRAMS' STRINGS BELOW $9600, UNDER THE DOS BUFFERS

140DEF FN SA(X) = X - 32767

FN SA(X): ADDRESS X AS IT IS STORED IN AN INTEGER (X-32767)

150DEF FN RA(X) = X + 32767

FN RA(X): THE ADDRESS STORED AS X (X+32767)

160DEF FN SW(X) = X - (X > 32767) * 65536

FN SW(X): ADDRESS X AS A SIGNED WORD FOR POKE AND PEEK (X-65536 ABOVE 32767)

170DATA 42547,76,208,42548,68,15,42549,166,32,42569,255,127,42948,96,77,43372,255,127

SIX DOS PATCHES (ADDRESS, NEW BYTE, ORIGINAL BYTE) SO THAT DOS CAN READ THE TOKENIZED PROGRAM AS A TEXT FILE: $A633-$A635 BNE $A644 / JSR $A2FC BECOMES JMP $A644, SO A ZERO BYTE DOES NOT END THE DATA READ INTO THE INPUT LINE; $A649 AND #$7F BECOMES AND #$FF, SO TOKENS KEEP BIT 7; $A7C4 BECOMES RTS, SO THE FILE TYPE IS NOT CHECKED (THE APPLESOFT SOURCE FILE OPENS AS A TEXT FILE); $A96C $7F BECOMES $FF, SO THE B (BYTE POSITION) PARAMETER MAY GO UP TO 65535

180FOR GE = 0 TO 5

GE IS LOOP INDEX; ALSO A LENGTH

190READ AD,Q8,DP(GE,1)

THE ADDRESS, THE NEW BYTE AND THE ORIGINAL BYTE (KEPT TO UNDO THE PATCH)

AD IS AN ADDRESS: A DOS BYTE TO PATCH, OR THE ADDRESS ANSWERED

Q8 IS NEW VALUE OF A DOS BYTE BEING PATCHED

200POKE AD,Q8

PATCH DOS

210DP(GE,0) = FN SW(AD)

THE ADDRESS, AS A SIGNED WORD, FOR PUTTING THE BYTE BACK AT THE END OF THE COMPILATION

220NEXT GE
230EL = 2375

THE LIBRARY ROUTINE AT $0947 THAT RESETS THE STACK

240LM = 4013

RUNTIME IS 4013 BYTES LONG

250DH = 2051

THE LIBRARY NORMALLY LOADS AT $0803

DH IS DEFAULT LIBRARY ADDRESS (2051 = $0803)

260BP$ = CHR$ (7) + CHR$ (7)

TWO BELLS FOR THE ERROR MESSAGES

270DI$ = CHR$ (4)

CONTROL-D STARTS EACH DOS COMMAND

280LN$ = "CLINENUM"

THE LINE NUMBER FILE: PASS 1 WRITES EACH LINE'S NUMBER AND ADDRESS, PASS 2 READS THEM

290OP$ = DI$ + "OPEN"

THE DOS COMMANDS THE PASSES USE

300CO$ = DI$ + "CLOSE"
310DM$ = DI$ + "DELETE"

DM$ IS DOS DELETE COMMAND

320WO$ = DI$ + "WRITE"
330RV$ = DI$ + "READ"
340SQ = PEEK (43626)

THE SLOT AND DRIVE DOS LAST USED: THE BOOT DRIVE

SQ IS SLOT OF THE BOOT DRIVE (DOS'S LAST SLOT USED, $AA6A)

350DO = PEEK (43624)

DO IS DRIVE OF THE BOOT DRIVE (DOS'S LAST DRIVE USED, $AA68)

360DN$ = ",S" + STR$ (SQ) + ",D" + STR$ (DO)

THE BOOT DRIVE AS ",SN,DN"

370MX = FN SW(SQ * 16 + 49289)

THE DRIVE'S MOTOR-ON SWITCH, $C089 + SLOT*16

380MN = MX - 1
390DW = FN SW(43602)

DOS'S OUTPUT STATE BYTE, $AA52

400TITLE AND THE SOURCE FILE QUESTION

400TEXT
410HOME
420PRINT "MICROSOFT APPLESOFT"
430PRINT "COMPILER, VER 2.01"
440PRINT "COPYRIGHT (C) 1981"
450PRINT "MICROSOFT"
460PRINT
470PRINT
480PRINT
490SC = 1

ASSUME THE FILES ARE ON THE BOOT DRIVE

500PRINT "SOURCE FILE? ";
510GOSUB 2700

THE ANSWER

520QH = 2

QUESTION 2: THE SOURCE FILE

QH IS WHICH QUESTION IS BEING ANSWERED; SELECTS WHERE THE SHARED CHECKS RETURN

530GOTO 3450

CHECK THE ANSWER (A LINE STARTING WITH CONTROL-D IS A DOS COMMAND)

600THE SOURCE FILE'S NAME WAS CHECKED: IT MUST EXIST

600IF BZ THEN 490
610IF LEN (LU$) = 0 THEN GOSUB 3200: GOTO 490

AN EMPTY ANSWER IS NOT A FILE NAME

620GOSUB 2800

SPLIT IT INTO NAME AND SLOT/DRIVE

630IF BZ THEN 490
640SI$ = NM$

THE SOURCE FILE

650SB$ = SY$
660QH = 1

QUESTION 1: THE SOURCE FILE'S EXISTENCE

670LU$ = DI$ + "APPEND" + SI$ + SB$

APPEND FAILS WITH FILE NOT FOUND IF THE FILE DOES NOT EXIST

LU$ IS THE LINE TYPED AT A FILE QUESTION, THEN THE DOS COMMAND THAT CHECKS THE FILE

680GOTO 3480

700THE SOURCE FILE EXISTS; THE OBJECT FILE QUESTION, ITS DEFAULT THE SOURCE NAME (UP TO 26 CHARACTERS) + .OBJ

700PRINT CO$

CLOSE IT AGAIN

710IF BZ THEN 490
720GE = LEN (SI$): IF GE > 26 THEN GE = 26

A NAME LONG ENOUGH TO LEAVE ROOM FOR .OBJ

730OD$ = LEFT$ (SI$,GE) + ".OBJ"
740OO$ = SB$

ON THE SOURCE FILE'S DRIVE

750PRINT
760PRINT
770PRINT "OBJECT CODE FILE: "
780PRINT "(DEFAULT ";OD$;
790IF OO$ <> DN$ THEN PRINT OO$;

A DRIVE OTHER THAN THE BOOT DRIVE IS SHOWN

800PRINT ")? ";
810GOSUB 2700
820QH = 3

QUESTION 3: THE OBJECT FILE

830GOTO 3450

900THE OBJECT FILE'S NAME WAS CHECKED

900IF BZ THEN 770
910IF LU$ = "" THEN 960

NOTHING TYPED: THE DEFAULT

920GOSUB 2800
930IF BZ THEN 770
940OD$ = NM$
950OO$ = SY$

960MEMORY USAGE: THE DEFAULT, OR THE THREE ADDRESSES

960PRINT
970PRINT
980PRINT "MEMORY USAGE:"
990PRINT "DEFAULT CONFIGURATION? ";
1000GOSUB 2570
1010IF BZ THEN 980
1020IF XB <> 0 THEN LB = FN SA(DH):UR = LB + LM:VC = - 32767: GOTO 1630

THE DEFAULT LAYOUT: THE LIBRARY AT $0803, THE PROGRAM RIGHT AFTER IT, THE VARIABLES AFTER THE PROGRAM

1030PRINT
1040PRINT "ALTERNATE CONFIGURATION:"
1050PRINT
1060PRINT "ADDRESS FOR LIBRARY:"
1070PRINT "(DEFAULT ";DH;
1080INPUT ")? ";AB$
1090IF LEN (AB$) = 0 THEN AD = DH: GOTO 1210

NOTHING TYPED: THE DEFAULT ADDRESS

1100QH = 2

QUESTION 2 FOR THE ADDRESS CHECK: THE LIBRARY

1110GOTO 3220

1200THE LIBRARY ADDRESS WAS CHECKED

1200IF BZ THEN 1060
1210LB = FN SA(AD)

THE LIBRARY ADDRESS

1220PRINT
1230PRINT "ADDRESS FOR PROGRAM:"
1240PRINT "(NUMBER, 'HGR1', 'HGR2',"
1250INPUT "OR DEFAULT END OF LIBRARY)? ";AB$
1260IF LEN (AB$) = 0 THEN UR = LB + LM: GOTO 1420

NOTHING TYPED: THE PROGRAM FOLLOWS THE LIBRARY

1270IF AB$ = "HGR1" THEN AD = 16384: GOTO 1410

HGR1: THE PROGRAM STARTS AT $4000, ABOVE HIGH-RESOLUTION PAGE 1

1280IF AB$ = "HGR2" THEN AD = 24576: GOTO 1410

HGR2: AT $6000, ABOVE PAGE 2

1290QH = 1

QUESTION 1 FOR THE ADDRESS CHECK: THE PROGRAM

1300GOTO 3220

1400THE PROGRAM ADDRESS WAS CHECKED

1400IF BZ THEN 1230
1410UR = FN SA(AD)

THE PROGRAM ADDRESS

1420PRINT
1430PRINT "ADDRESS FOR VARIABLES:"
1440INPUT "(DEFAULT END OF PROGRAM)? ";AB$
1450IF LEN (AB$) = 0 THEN AD = 0: GOTO 1510

NOTHING TYPED: THE VARIABLES FOLLOW THE PROGRAM (STORED AS -32767)

1460QH = 3

QUESTION 3 FOR THE ADDRESS CHECK: THE VARIABLES

1470GOTO 3220

1500THE VARIABLES ADDRESS WAS CHECKED; SHOW THE LAYOUT AND CONFIRM IT

1500IF BZ THEN 1430
1510VC = FN SA(AD)

THE VARIABLES ADDRESS

1520PRINT
1530PRINT "LIBRARY OCCUPIES "; FN RA(LB);" - "; FN RA(LB + LM - 1)

THE ADDRESSES ARE SHOWN AS THEY ARE, NOT IN THE STORED FORM

1540PRINT "PROGRAM BEGINS AT "; FN RA(UR)
1550PRINT "VARIABLES BEGIN AT ";
1560IF - 32767 = VC THEN PRINT "END OF PROGRAM": GOTO 1580
1570PRINT FN RA(VC)
1580PRINT
1590PRINT "ARE THESE ADDRESSES CORRECT? ";
1600GOSUB 2570
1610IF BZ THEN 1590
1620IF XB = 0 THEN 960

NO: ASK FOR THE ADDRESSES AGAIN

1630OPTIONS: THE DEFAULT, OR EACH OPTION IN TURN

1630PRINT
1640PRINT
1650PRINT "OPTIONS:"
1660PRINT "DEFAULT CONFIGURATION? ";
1670GOSUB 2570
1680IF BZ THEN 1650
1690IF XB <> 0 THEN O4 = 1:OO = 1:P8 = 1:OH = 1:N1 = 0: GOTO 2060

THE DEFAULT OPTIONS: LISTING, PAUSE, INTEGER ARITHMETIC AND INTEGER CONSTANTS ON, RESUME/DEBUG OFF

1700PRINT
1710PRINT "COMPILATION LISTING:"
1720PRINT "(DEFAULT YES)? ";
1730GOSUB 2570
1740IF BZ THEN 1710
1750O4 = SGN (XB)

YES OR NOTHING TYPED: 1; NO: 0

1760PRINT
1770PRINT "PAUSE ON ERRORS:"
1780PRINT "(DEFAULT YES)? ";
1790GOSUB 2570
1800IF BZ THEN 1770
1810OO = SGN (XB)
1820PRINT
1830PRINT "INTEGER ARITHMETIC:"
1840PRINT "(DEFAULT YES)? ";
1850GOSUB 2570
1860IF BZ THEN 1830
1870P8 = SGN (XB)
1880PRINT
1890PRINT "INTEGER CONSTANTS:"
1900PRINT "(DEFAULT YES)? ";
1910GOSUB 2570
1920IF BZ THEN 1890
1930OH = SGN (XB)
1940PRINT
1950PRINT "RESUME/DEBUG CODE:"
1960PRINT "(DEFAULT NO)? ";
1970GOSUB 2570
1980IF BZ THEN 1950
1990N1 = XB = 1

ONLY YES TURNS IT ON

2000DATA 2912,-57612,558,3765,3620,3772,2985,2982,-62352,-62361,3135,3144,3896,3850,3862,3874,-62424,-62434,3572,1524,1588,1595,3239,-64600,3515

THE CALL TABLE, 136 ENTRIES (INDEX 0 FIRST)

2010DATA 3524,1497,1504,1727,-62067,-62071,-62080,1655,376,3230,216,1730,3636,3667,2810,2692,3614,2813,2695,2831,2709,352,2354,2948,3902
2020DATA 1771,2888,3255,3162,3174,3248,3211,3153,-56059,1517,3581,167,2966,2912,2249,3676,-59306,1132,-60009,-61079,3342,3336,3350,3361,3365
2030DATA 3352,3363,3348,3361,-61136,2284,2268,3934,-60259,3199,3104,3533,3398,3455,3375,3372,3395,3508,-60304,-60451,-60335,-10,1808,3551,3883
2040DATA 3837,-61069,-61358,-59713,-61193,-61418,-61425,-61498,-61598,3908,1715,2470,1661,1703,2450,2500,2546,2599,2609,3542,3592,3183,3560,3328,3322
2050DATA 3726,3719,164,1800,3707,3753,3691,1216,3698,1239,3819

2060THE CALL TABLE: ADDRESSES OF THE LIBRARY AND ROM ROUTINES THE COMPILED CODE CALLS, BY INDEX (A POSITIVE ENTRY IS AN OFFSET FROM THE LIBRARY ADDRESS, A NEGATIVE ONE MINUS A ROM ADDRESS), STORED IN SC(150..285) FOR PASS 1

2060RESTORE

THE DOS PATCH DATA COMES FIRST ...

2070FOR GE = 1 TO 18

... 18 VALUES, SKIPPED

2080READ XU

XU IS A VALUE READ FROM A DATA TABLE

2090NEXT GE
2100FOR GE = 0 TO 135

136 ENTRIES

2110READ XU: IF XU < 0 THEN XU = FN SA( - XU): GOTO 2130

A ROM ADDRESS: STORED AS ADDRESS-32767

2120XU = XU + LB

A LIBRARY ROUTINE: ITS OFFSET PLUS THE LIBRARY ADDRESS

2130SC(150 + GE) = XU
2140NEXT GE
2150DATA 40,1,14,41,13,1,198,13,14,200,9,8,201,9,8,202,11,10,203,11,10,204,13,12,205,5,4,206,3,2,207,7,6,208,7,6,209,7,6,235,7,6,236,7,6,237,7,6,239,13,14

17 OPERATORS: ( ) NOT + - * / ^ AND OR > = < AND THE TWO-CHARACTER RELATIONS (235-237), THEN NEGATION (239)

2160THE OPERATOR TABLE (TOKEN, STACK PRIORITY, ARRIVING PRIORITY) IN SC(300..350) FOR PASS 1

2160FOR GE = 0 TO 50

51 VALUES

2170READ XU
2180SC(300 + GE) = XU
2190NEXT GE
2200DATA 160,3,162,113,76,43,235,162,0,32,12,253,141,118,3,96,173,118,3,76,237,253,169,0,133

THE MACHINE CODE, 89 BYTES FOR $0377-$03CF: $0377 USR STORES THE FLOATING POINT ACCUMULATOR, ROUNDED, AS 5 PACKED BYTES AT $0371; $037E READS A BYTE (RDKEY, WHICH DOS FEEDS FROM THE OPEN FILE) INTO $0376; $0387 PRINTS THE BYTE IN $0376 (COUT, WHICH DOS SENDS TO THE OPEN FILE); $038D LISTS THE TOKENIZED LINE AT $0280, SPELLING EACH TOKEN FROM THE ROM'S KEYWORD TABLE

2210DATA 159,164,159,185,128,2,208,1,96,48,7,32,92,219,230,159,208,239,56,233,127,170,160,208,132
2220DATA 157,160,207,132,158,160,255,202,240,7,32,44,215,16,251,48,246,169,32,32,92,219,32,44,215
2230DATA 48,5,32,92,219,208,246,32,92,219,169,32,208,203

2240THE MACHINE CODE AT $0377-$03CF

2240FOR GE = 887 TO 975

887 TO 975 = $0377 TO $03CF

2250READ XU
2260POKE GE,XU
2270NEXT GE
2280POKE 10,76

THE USR VECTOR AT $0A: JMP $0377

2290POKE 11,119
2300POKE 12,3

2310THE SYMBOL TABLE'S CHAIN HEADS AND THE ADDRESSES OF THE MACHINE CODE ROUTINES

2310NU = 32

32 CHAINS EACH FOR VARIABLES, CONSTANTS AND LINE NUMBERS

2320NG = 32
2330NK = 32
2340VO = 9:KX = VO + NU:L = KX + NG:HW = L + NK - 1

CHAIN HEADS 1-4 ARE FN SYMBOLS, 5-8 TEMPORARIES, THEN VARIABLES FROM 9, CONSTANTS AND LINE NUMBERS

2350UV = 887

THE ENTRY POINTS OF THE MACHINE CODE AND ITS DATA CELLS

2360KV = 881
2370IX = 886
2380QB = 894
2390WS = 903
2400LQ = 909
2410FOR GE = 0 TO HW

ALL CHAINS EMPTY

2420SC(GE) = 0
2430NEXT GE

2440CREATE THE OBJECT FILE, EMPTY THE LINE NUMBER FILE, AND RUN PASS 1

2440PRINT DI$;"BSAVE";OD$;OO$;",A0,L1"

A ONE-BYTE BINARY FILE MAKES SURE THE OBJECT FILE EXISTS (AND IS A BINARY FILE)

2450PRINT OP$;LN$;DN$

OPEN, DELETE AND OPEN AGAIN: AN EMPTY LINE NUMBER FILE

2460PRINT DM$;LN$;DN$
2470PRINT OP$;LN$;DN$
2480PRINT RV$;LN$;",R0"

POSITION IT AT ITS START

2490PRINT CO$

CLOSE ALL FILES

2500PRINT
2510PRINT "*****BEGINNING PASS 1"
2520PRINT
2530PRINT
2540REM ! CLEAR CHAIN

STRING STORAGE IS SET UP SO THAT THE COMMON STRINGS SURVIVE THE CHAIN TO PASS 1

2550PRINT DI$;"BRUNPASS1";DN$

2570YES/NO ANSWER: XB = 1 YES, 0 NO, 2 RETURN ALONE; BZ = 1 FOR ANYTHING ELSE

2570INPUT "";AB$
2580BZ = 0

ACCEPTED UNLESS FOUND OTHERWISE

BZ IS 1 IF THE ANSWER WAS NOT ACCEPTED (THE QUESTION IS ASKED AGAIN)

2590IF AB$ = "" THEN XB = 2: RETURN

XB IS ANSWER TO A YES/NO QUESTION: 1 YES, 0 NO, 2 NOTHING TYPED (THE DEFAULT)

2600AB$ = LEFT$ (AB$,1)
2610IF AB$ = "Y" THEN XB = 1: RETURN
2620IF AB$ = "N" THEN XB = 0: RETURN
2630BZ = 1

ANYTHING ELSE: THE BELL, AND THE QUESTION IS ASKED AGAIN

2640PRINT BP$;
2650RETURN

2700READ A LINE FROM THE KEYBOARD INTO LU$ (CONTROL-C STOPS)

2700CALL 54572

THE ROM'S INPUT LINE ROUTINE (INLIN, $D52C) READS INTO THE BUFFER AT $0200

2710LU$ = ""
2720GE = 512: IF PEEK (GE) = 3 THEN STOP

CONTROL-C FIRST STOPS THE PROGRAM

2730IF PEEK (GE) <> 0 THEN LU$ = LU$ + CHR$ ( PEEK (GE)):GE = GE + 1: GOTO 2730

COLLECT CHARACTERS UP TO THE ZERO AT THE END OF THE LINE

2740RETURN

2800SPLIT THE FILE SPECIFICATION IN LU$ INTO NM$ (THE NAME, LEADING SPACES REMOVED, TRAILING SPACES CUT, AT MOST 30 CHARACTERS) AND SY$ (",SN,DN", THE BOOT DRIVE'S SLOT OR DRIVE FILLED IN WHERE MISSING); BZ = 1 IF IT IS NOT LEGAL

2800BZ = 0
2810O8 = 0

O8 IS 1 IF THE FILE SPECIFICATION HAS NO SLOT OR DRIVE PART

2820FOR GE = 1 TO LEN (LU$)

LOOK FOR A COMMA

2830IF MID$ (LU$,GE,1) <> "," THEN NEXT GE:NM$ = LU$:SY$ = DN$:O8 = 1: GOTO 2870

NO COMMA: THE WHOLE LINE IS THE NAME, ON THE BOOT DRIVE

NM$ IS FILE NAME PART OF A FILE SPECIFICATION

SY$ IS SLOT AND DRIVE PART OF A FILE SPECIFICATION (",S6,D1")

2840IF GE = 1 THEN BZ = 1: GOTO 3200

A NAME CANNOT BE EMPTY

2850NM$ = LEFT$ (LU$,GE - 1)
2860SY$ = MID$ (LU$,GE)
2870FOR GE = 1 TO LEN (NM$)

SKIP LEADING SPACES; A NAME OF SPACES ONLY IS ILLEGAL

2880IF MID$ (NM$,GE,1) = " " THEN NEXT GE:BZ = 1: GOTO 3200
2890NM$ = MID$ (NM$,GE)
2900LQ = 1

LQ SERVES HERE AS SCRATCH (IT IS SET TO ITS REAL VALUE LATER): THE LAST CHARACTER THAT IS NOT A SPACE

2910FOR GE = 1 TO LEN (NM$)
2920IF MID$ (NM$,GE,1) <> " " THEN LQ = GE
2930NEXT GE
2940IF LQ > 30 THEN LQ = 30

DOS USES AT MOST 30 CHARACTERS

2950NM$ = LEFT$ (NM$,LQ)
2960IF O8 THEN 3110

NO SLOT OR DRIVE GIVEN: DONE

2970IF LEN (SY$) > 20 THEN BZ = 1: GOTO 3200

THE SLOT AND DRIVE PART MAY HAVE AT MOST 20 CHARACTERS

2980IZ = 0

IZ IS 1 IF THE SPECIFICATION GIVES A SLOT

2990HX = 0

HX IS 1 IF THE SPECIFICATION GIVES A DRIVE

3000AG = 0

AG IS 1 RIGHT AFTER A COMMA IN THE SLOT AND DRIVE PART (S OR D MAY FOLLOW)

3010FOR GE = 1 TO LEN (SY$)

FIND S AND D, EACH RIGHT AFTER A COMMA, AND THEIR NUMBERS

3020AB$ = MID$ (SY$,GE,1)
3030IF NOT AG THEN 3060
3040IF AB$ = "S" THEN IZ = 1:GV = VAL ( MID$ (SY$,GE + 1)):AG = 0

GV IS THE SLOT IT GIVES

3050IF AB$ = "D" THEN HX = 1:GG = VAL ( MID$ (SY$,GE + 1)):AG = 0

GG IS THE DRIVE IT GIVES

3060IF AB$ = "," THEN AG = 1
3070NEXT GE
3080IF NOT IZ THEN SY$ = SY$ + ",S" + STR$ (SQ)

A MISSING SLOT OR DRIVE IS THE BOOT DRIVE'S

3090IF NOT HX THEN SY$ = SY$ + ",D" + STR$ (DO)
3100IF IZ AND GV <> SQ OR HX AND GG <> DO THEN SC = 0

A FILE ON ANOTHER SLOT OR DRIVE: THE BOOT DRIVE'S MOTOR NEED NOT BE KEPT RUNNING

3110RETURN

3200REPORT AN ILLEGAL FILE SPECIFICATION

3200PRINT BP$;"ILLEGAL FILE SPECIFICATION"
3210RETURN

3220CONVERT THE ADDRESS IN AB$ (DECIMAL, OR HEXADECIMAL AFTER $) INTO AD; BZ = 1 IF IT IS NOT FROM 0 TO 49151; THEN RETURN TO THE QUESTION QH

3220IF LEFT$ (AB$,1) = " " THEN AB$ = MID$ (AB$,2): GOTO 3220

SKIP LEADING SPACES

3230IF LEFT$ (AB$,1) = "$" THEN 3280
3240ONERR GOTO 3420

VAL OF A BAD NUMBER GIVES AN ERROR, CAUGHT AT 3420

3250AD = VAL (AB$)
3260POKE 216,0

TURN ONERR OFF AGAIN (ERRFLG, $D8)

3270GOTO 3380
3280AD = 0

HEXADECIMAL: DIGITS 0-9 AND A-F; SPACES ARE SKIPPED

3290AB$ = MID$ (AB$,2)
3300IF AB$ = "" THEN 3380
3310FOR GE = 1 TO LEN (AB$)
3320CN$ = MID$ (AB$,GE,1)

CN$ IS ONE CHARACTER OF A HEXADECIMAL ADDRESS

3330IF CN$ = " " THEN 3370
3340IF CN$ >= "0" AND CN$ <= "9" THEN AD = AD * 16 + ASC (CN$) - 48: GOTO 3370
3350IF CN$ >= "A" AND CN$ <= "F" THEN AD = AD * 16 + ASC (CN$) - 55: GOTO 3370
3360GOTO 3390

ANY OTHER CHARACTER: NOT AN ADDRESS

3370NEXT GE
3380IF AD >= 0 AND AD <= 49151 THEN BZ = 0: GOTO 3410

49151 = $BFFF, THE TOP OF MEMORY BELOW THE I/O AREA

3390BZ = 1
3400PRINT BP$;"ADDRESS RANGE IS 0 - 49151"
3410ON QH GOTO 1400,1200,1500

BACK TO THE QUESTION: 1 PROGRAM, 2 LIBRARY, 3 VARIABLES

3420POKE 216,0

AN ERROR IN VAL: ONERR OFF, AND RESET THE STACK

3430CALL EL
3440GOTO 3390

3450CHECK AN ANSWER: A LINE LU$ THAT STARTS WITH CONTROL-D IS A DOS COMMAND (CATALOG, FOR EXAMPLE): IT IS RUN, AND THE QUESTION IS ASKED AGAIN ...

3450BZ = 0
3460IF LEN (LU$) > 0 THEN IF ASC (LU$) = 4 THEN BZ = 1: PRINT : GOTO 3490

A DOS COMMAND: RUN IT, THEN ASK AGAIN (BZ = 1)

3470GOTO 3590

3480... ENTRY: RUN THE DOS COMMAND IN LU$; A FILE NOT FOUND OR OTHER DOS ERROR SETS BZ; THEN RETURN TO THE QUESTION QH

3480BZ = 0
3490ONERR GOTO 3530

A DOS ERROR IS CAUGHT AT 3530

3500PRINT LU$
3510POKE 216,0
3520GOTO 3580
3530POKE 216,0
3540IF PEEK (222) = 6 THEN PRINT BP$;"FILE NOT FOUND ON DISK": GOTO 3560

ERROR CODE 6 (ERRNUM, $DE) IS FILE NOT FOUND

3550PRINT BP$;"DISK ERROR"
3560BZ = 1
3570CALL EL

RESET THE STACK AFTER THE ERROR

3580IF QH <> 1 THEN PRINT
3590ON QH GOTO 700,600,900

BACK TO THE QUESTION: 1 SOURCE FILE OPENED, 2 SOURCE FILE ANSWERED, 3 OBJECT FILE ANSWERED

Variables

NAMETYPEDEFINEDCOMMONMEANING
AB$STRING100THE ANSWER TYPED AT A QUESTION
ADREAL190AN ADDRESS: A DOS BYTE TO PATCH, OR THE ADDRESS ANSWERED
AGREAL30001 RIGHT AFTER A COMMA IN THE SLOT AND DRIVE PART (S OR D MAY FOLLOW)
BP$STRING6037TWO BELLS, SOUNDED BEFORE EACH ERROR MESSAGE
BZREAL25801 IF THE ANSWER WAS NOT ACCEPTED (THE QUESTION IS ASKED AGAIN)
C3INTEGER3034COMMON KIND: -1 NONE, 0 DEFINE, 255 USE
CCINTEGER5025ADDRESS OF THE LINK WORD OF THE LAST DATA BLOCK (DATA BLOCKS ARE CHAINED)
CDINTEGER4024START OF THE COMMON BLOCK (THE PROGRAM START BEFORE COMMON MOVED IT)
CN$STRING3320ONE CHARACTER OF A HEXADECIMAL ADDRESS
CO$STRING6040DOS CLOSE COMMAND
DHREAL250DEFAULT LIBRARY ADDRESS (2051 = $0803)
DI$STRING6038CONTROL-D, THE DOS COMMAND PREFIX
DM$STRING310DOS DELETE COMMAND
DN$STRING6046SLOT AND DRIVE OF THE BOOT DRIVE (",S6,D1")
DOREAL350DRIVE OF THE BOOT DRIVE (DOS'S LAST DRIVE USED, $AA68)
DP(5,1)INTEGER()5035DOS PATCH TABLE: DP(I,0) ADDRESS (AS A SIGNED WORD, ADDRESS-65536), DP(I,1) ORIGINAL BYTE
DWINTEGER4010DOS STATE BYTE AT $AA52: POKED BEFORE EACH DIRECT FILE READ OR WRITE
EDINTEGER5026OBJECT FILE BASE: FILE POSITION = PC - ED (THE FILE STARTS WITH THE BSAVE HEADER)
ELINTEGER1011LIBRARY ROUTINE ($0947) THAT RESETS THE STACK, DROPPING EVERY PENDING GOSUB AND FOR, AND RESETS THE DATA POINTER; CALLED AFTER AN ERROR
FCINTEGER30331 ONCE A FATAL ERROR HAS BEEN REPORTED (NO MORE CODE IS WRITTEN)
GEREAL180LOOP INDEX; ALSO A LENGTH
GGREAL3050THE DRIVE IT GIVES
GVREAL3040THE SLOT IT GIVES
HWINTEGER507LAST CHAIN HEAD IN SC(); ENTRIES ARE ALLOCATED ABOVE IT
HXREAL29901 IF THE SPECIFICATION GIVES A DRIVE
IXINTEGER5017ADDRESS OF THE ONE-BYTE TRANSFER CELL FOR QB AND WS ($0376)
IZREAL29801 IF THE SPECIFICATION GIVES A SLOT
KVINTEGER3014ADDRESS OF THE FIVE PACKED BYTES LEFT BY THE USR ROUTINE ($0371)
KXINTEGER505FIRST CONSTANT CHAIN HEAD IN SC()
LINTEGER506FIRST LINE NUMBER CHAIN HEAD IN SC()
LBINTEGER4019LIBRARY ADDRESS, STORED AS ADDRESS-32767
LHINTEGER4023NUMBER OF SOURCE LINES READ
LMINTEGER5012LENGTH OF THE RUNTIME LIBRARY IN BYTES (4013)
LN$STRING6045NAME OF THE LINE NUMBER FILE ("CLINENUM")
LQINTEGER5018ADDRESS OF THE ROUTINE THAT LISTS THE TOKENIZED LINE IN THE INPUT BUFFER ($038D)
LU$STRING670THE LINE TYPED AT A FILE QUESTION, THEN THE DOS COMMAND THAT CHECKS THE FILE
MNINTEGER109DRIVE MOTOR-OFF SWITCH FOR THE BOOT SLOT
MXINTEGER508DRIVE MOTOR-ON SWITCH FOR THE BOOT SLOT ($C089+SLOT*16), TOUCHED TO KEEP THE DRIVE SPINNING
N1INTEGER2030RESUME/DEBUG CODE OPTION (1 = YES)
NGINTEGER502NUMBER OF CONSTANT HASH CHAINS (32)
NKINTEGER503NUMBER OF LINE NUMBER HASH CHAINS (32)
NM$STRING2830FILE NAME PART OF A FILE SPECIFICATION
NUINTEGER501NUMBER OF VARIABLE HASH CHAINS IN THE SYMBOL TABLE (32)
O4INTEGER2028COMPILATION LISTING OPTION (1 = YES)
O8REAL28101 IF THE FILE SPECIFICATION HAS NO SLOT OR DRIVE PART
OD$STRING6044OBJECT FILE NAME
OHINTEGER5032INTEGER CONSTANTS OPTION (1 = YES)
OOINTEGER2029PAUSE ON ERRORS OPTION (1 = YES)
OO$STRING6048SLOT AND DRIVE OF THE OBJECT FILE
OP$STRING6039DOS OPEN COMMAND
P8INTEGER2031INTEGER ARITHMETIC OPTION (1 = YES)
PCINTEGER5022ADDRESS OF THE NEXT OBJECT CODE BYTE, AS ADDRESS-32767
Q8REAL190NEW VALUE OF A DOS BYTE BEING PATCHED
QBINTEGER3015ADDRESS OF THE ROUTINE THAT READS ONE BYTE FROM THE OPEN FILE INTO IX ($037E)
QHREAL520WHICH QUESTION IS BEING ANSWERED; SELECTS WHERE THE SHARED CHECKS RETURN
RV$STRING6041DOS READ COMMAND
SB$STRING6047SLOT AND DRIVE OF THE SOURCE FILE
SCINTEGER10271 IF THE SOURCE AND OBJECT FILES ARE ON THE BOOT DRIVE (MOTOR KEPT ON), ELSE 0
SC(5350)INTEGER()1036SYMBOL TABLE: CHAIN HEADS, THEN ENTRIES LINKED THROUGH THEIR FIRST WORD
SI$STRING6043SOURCE FILE NAME
SQREAL340SLOT OF THE BOOT DRIVE (DOS'S LAST SLOT USED, $AA6A)
SY$STRING2830SLOT AND DRIVE PART OF A FILE SPECIFICATION (",S6,D1")
URINTEGER5020PROGRAM START, STORED AS ADDRESS-32767; MOVED UP BY COMMON DECLARATIONS
UVINTEGER5013ADDRESS OF THE USR ROUTINE THAT PACKS A NUMBER INTO FIVE BYTES ($0377)
VCINTEGER4021VARIABLES ADDRESS ASKED FOR, AS ADDRESS-32767, OR -32767 FOR END OF PROGRAM
VOINTEGER504FIRST VARIABLE CHAIN HEAD IN SC() (9; 1-4 HOLD FN AND LINE SYMBOLS, 5-8 TEMPORARIES)
WO$STRING6042DOS WRITE COMMAND
WSINTEGER3016ADDRESS OF THE ROUTINE THAT WRITES THE BYTE IN IX TO THE OPEN FILE ($0387)
XBREAL2590ANSWER TO A YES/NO QUESTION: 1 YES, 0 NO, 2 NOTHING TYPED (THE DEFAULT)
XUREAL2080A VALUE READ FROM A DATA TABLE
FN SAREALADDRESS X AS IT IS STORED IN AN INTEGER (X-32767)
FN RAREALTHE ADDRESS STORED AS X (X+32767)
FN SWREALADDRESS X AS A SIGNED WORD FOR POKE AND PEEK (X-65536 ABOVE 32767)
XREALPARAMETER OF THE DEF FN FUNCTIONS (EACH FUNCTION HAS ITS OWN)