.H Copyright (c) 1996, Gary D. Campbell NAME =MORE PREP,BODY,BACK,USAGE $$$$ CODE=01200 0000 PARMS (32) ------------ PTRAN ------------- 1200 PRIMITIVES ENTRY + indicates "Emits Token" 1200 =@P.A + [space] alpha [alpha|.|digit].. 1202 =@P.B S: Wrapup Prep, F: Initialize for Match(Body) 1204 =@P.C handle continuation, always Succeed 1206 =@P.D bump SI past spaces, AF=0 1208 =@P.E RETURN: IF EndLine (AA=0); ELSE (NotEndLine CY=1). 120A =@P.F + [space] match file characters 120C =@P.G + [space] match 'arb' or "arb" (arb=notany(CR)) 120E =@P.H + [space] stopshort('"',"'|]",space,CR,lowercase) 1210 =@P.I + [space] alpha notany(alpha|.|digit) 1212 =@P.J Initialize Match(Prep), S: comment or null line. 1214 : 1214 : ALL PRIMITIVES HAVE 3 CHOICES (NOTE: $SP=RTN to SUC.MORE or DO.MORE): 1214 : 1. Emit a Token: CALL ERR.xx; =err,pfx; SI=BeginMatch; AA=Length 1214 : 2. Emit no Token: RTN SI=Match+1, AA=0 1214 : 3. Fail via CALL GET.RETRY; =err; (directly to SUC.MORE or DO.MORE) 1214 : 1214 CK.BYTE A=$SI+ RETURN SI=SI+1 only if 1 space skipped 1215* A:" " EQ: stopshort(space,space) 1217 IF EQ, LT: $SI = control character 1219 A=$SI GT: $SI = notany(space) 121B* A:" " 121D * IF NE,EXIT 121F ELSE SI=(SI-1) 1222 RTN: RETURN 1223 CK.A.NUM CALL CK.DEC.A 1226 IF NC,GOTO RTN 1228*CK.ALPHA A:"z"+1 122A IF LT, 122C* A:"a" 122E RETURN 122F.RTN.CY: CY=1 1230 RETURN 1231+FOLLOW.ON SI=SI+1 1232 A=$SI 1234* A:"." 1236 IF NE,GOTO CK.A.NUM 1238 PUSH SI 1239 CALL FOLLOW.ON 123C POP SI 123D RETURN 123E CK.DEC A=$SI+ RETURN: 123F*CK.DEC.A A:"9"+1 NC if in range 0-9 1241 IF GE,GOTO RTN.CY CY if outside this range 1243* A:"0" 1245 RETURN 1246 ERR.CY IF NC, IF EITHER AA=SI or CY=1 1248 ERR.ZR SWAP AA,SI THEN GOTO GET.RETRY 1249* AA=AA-SI ELSE (AA>SI) 124B IF NZ, AA=Length, SI=@Source, CY=0 124D POP HL 124E CS: L=$(HL+1) Get Token pfx Code 1252 SWAP AA,HL 1253 $DI+=A Emit it. 1254 SWAP AA,HL Let SUC emit the 1255 RETURN (back to SUC) rest of the Token. 1256 GOTO GET.RETRY .P 1259 P.A CALL CK.BYTE [space] alpha [follow.on].. 125C PUSH SI 125D CALL CK.ALPHA 1260 IF NC, 1262 DO CALL FOLLOW.ON 1265 LOOP WHILE NC 1267. CY=0 1268 POP AA 1269 CALL ERR.CY 126C ="AA" Error in an Alpha.numeric 126E P.B PUSH SI 126F AA=%(SI+4) This primitive 1272* A:"=" SUCCEEDS if column (5,6) is "=" 1274 IF NE, and FAILS otherwise. 1276* A':"=" 1279 IF EQ, 127B SI=(SI+5) 127E POP AA 127F CALL ERR.ZR 1282 ="BB" 1284 P.C PUSH SI 1285 CALL CK.BYTE THIS PRIMITIVE CAN'T FAIL 1288 IF LT, IT CHECKS FOR AND HANDLES CONTINUATION 128A* A:CR It advances SI & returns AF=0. 128C IF EQ, 128E DO CALL COMMENT.C (CY-->End-of-File) 1291 * IF CY,NEXT (NC,ZR-->Comment) 1293 LOOP WHILE ZR (NC,NZ-->Next Statement) 1295 CS: AA=%OBJECT (comments are skipped) 1299 CALL WRITE.HEX 129C* %SI:" " 12A0 * IF EQ,EXIT 12A2 ELSE POP SI 12A3*RTN.ZR: AA=0 AA=0,SI++ causes Success 12A5 RETURN & No Object Token 12A6 POP AA 12A7 P.D DO A=$SI+ THIS PRIMITIVE CAN'T FAIL 12A8* A:" " It bumps SI past ALL Spaces 12AA LOOP WHILE EQ & returns AF=0. 12AC+ SI=SI-1 12AD GOTO RTN.ZR 12AF P.E CALL B.SOURCE THIS PRIMITIVE MATCHES SP,SP | CR 12B2+ SI=SI-1 12B3 IF NC,GOTO RTN.ZR (otherwise it fails) 12B5 CALL GET.RETRY 12B8 ="E" End-of-Statement Error .P 12B9 P.F CALL CK.BYTE [space] match file characters 12BC PUSH SI Save index of 1st byte 12BD DO CALL FILE.CHR 12C0* A'=A' XOR 5 12C3 LOOP UNTIL NE check bytes until 1 byte too many 12C5+ SI=SI-1 BACKUP 1 12C6 POP AA (NC, let ERR.CY detect FAIL=Null) 12C7 CALL ERR.CY 12CA ="FF" 12CC P.G CALL CK.BYTE [space] match Quote Arb Quote 12CF PUSH SI "any string" or 'any"string' 12D0* A:'"' (must be " inside 'quotes') 12D2 IF NE, 12D4* A:"'" 12D6 L=0 L=0 flags an error 12D8 * IF NE,EXIT 12DA ELSE A'=A L>0 if A = " 12DC+ SI=SI+1 12DD DO A=$SI+ 12DE* A:A' 12E0 * IF EQ,EXIT (LEN = string content + 2) 12E2* A:'"' 12E4 IF EQ, 12E6 L=A (flag '.."..' string OK) 12E8* A:CR 12EA LOOP UNTIL EQ 12EC L=0 FAIL due to premature EOL 12EE* L:0 12F0 POP AA 12F1 IF EQ, 12F3 SI=AA 12F5 CALL ERR.ZR Q = Quote Error 12F8 ="QG" 12FA P.H CALL CK.BYTE [space] 12FD PUSH SI stopshort('"',"'|]",space,CR,lowercase) 12FE DO A=$SI+ 12FF* A:" " 1301 * IF EQ,EXIT 1303* A:7B 1305 IF LT, 1307* A:061 1309 * IF GE,EXIT 130B* A:"[" 130D * IF EQ,EXIT 130F* A:"|" 1311 * IF EQ,EXIT 1313* A:"]" 1315 * IF EQ,EXIT 1317* A:"'" 1319 * IF EQ,EXIT 131B* A:'"' 131D * IF EQ,EXIT 131F* A:CR 1321 LOOP UNTIL EQ 1323+ SI=SI-1 1324 POP AA 1325 CALL ERR.CY 1328 ="KH" K = Keyword content error .P 132A P.I CALL CK.BYTE 132D PUSH SI 132E* A:"z" 1330 IF LE, 1332* A:"a" 1334 * IF LT,EXIT 1336 CALL FOLLOW.ON 1339. CY=~CY 133A POP AA 133B CALL ERR.CY a = alpha primitive error 133E ="aI" 1340 P.J CALL COMMENT.J This is the FIRST ALTERNATIVE OF PREP. 1343 IF LE, RETURN SUCCESS IF or EOF 1345* AA=0 1347 RETURN (Success) 1348 PUSH SI 1349 AA=%(SI+4) NE-->looking at BeginLine > 6. 134C* A:"=" (check for "=" in col 5/6) 134E IF NE, The following ALWAYS FAILS, since SI 1350* A':"=" is not bumped. 1353 * IF NE,EXIT 1355 ELSE HL=@CK.LIST-4 Here we "fixup" all 1358 A=$SI "prep" statements. 135A* A=A AND 5F This means rewriting 135C DO HL=(HL+4) columns 1-4 if there 135F* CS: $(HL+4):0 is an "=" in 1364 * IF EQ,EXIT column 5 or 6. 1366* CS: A:$HL 1369 LOOP UNTIL EQ 136B CS: AA=%HL 136E %SI=AA 1370 CS: AA=%(HL+2) 1374 %(SI+2)=AA 1377* $(SI+5):"=" 137B IF EQ, 137D $(SI+4)=" " 1381 POP AA 1382 CALL ERR.ZR 1385 ="=J",39*0 .P 13AE COMMENT.C CALL SKIP.CR 13B1 IF ZR, 13B3+ SI=SI-2 13B5 COMMENT.J CALL EOF.COUNT Come here FROM: P.C & P.J 13B8* AA:8 WITH: SI = 13BB IF GE, NEED: SI < CR,LF CY,NE 13BD AA=%SI else, SI = same, NC,NE 13BF* AA:"<<" SI < final CR,LF 13C2 IF EQ, (NC,EQ) 13C4+ DO SI=SI+1 Always RETURN AA=0. 13C5* SI:-16 (SI:65520) 13C8 IF GE,CALL CRASH 13CD AA=%SI 13CF* AA:">>" 13D2 * IF EQ,EXIT 13D4* A:CR 13D6 * IF NE,LOOP 13D8 CALL EOF.COUNT 13DB* AA:14 LF>>LFxxxx xLF[eof] 13DE LOOP WHILE GE 13E0 * EXIT 13E2* CS: A:$PERIOD 13E7 * IF EQ,EXIT 13E9 PUSH BC 13EA PUSH SI 13EB BC=6 13EE DO A=$SI+ 13EF* A:CR 13F1 * IF EQ,EXIT 13F3* A:":" 13F5 BC=BC-1 LOOP NE (BC>0) 13F7 POP SI RETURN: 13F8 POP BC Possible Good Statement 13F9 * IF EQ,EXIT O.K. = NC,NE (SI unchanged) 13FB. CY=0 EOF = CY,NE 13FC RETURN Comment = NC,EQ 13FD SKIP.CR DO A=$SI+ 13FE* SI:-16 (SI:65520) 1401 IF GE,CALL CRASH 1406* A:CR 1408 LOOP UNTIL EQ 140A+ SI=SI+1 140B EOF.COUNT PUSH BC RETURN AA = MIN(65520, EndSource-SourcePtr) 140C PUSH DE 140D PUSH DI SI,DS = SourcePointer 140E PUSH ES 140F CS: DI,ES=%FILE.EOF 1414 CALL PTR.DIFF 1417 POP ES 1418 POP DI 1419 POP DE 141A POP AA 141B SWAP AA,BC 141C* AA:0 141E RETURN 141F =18*0 .P 1431 : Refer to: DS:PARMS+offset or %(BP+offset) 0002 EXIT=2 Exit Address for WRAPUP Error (set by INIT.T) 0004 ADDR=4 ADDRESS of Begin Current Statement Def. (set by INIT.B) 0006 SYM=6 SymTab Pointer from last lookup 0008 S.S=8 Source Segment 000A VECT=10 @Vector (upper SYMTAB segment) 000C TOKN=12 Token (FF80+) 000E FLAGS=14 =0 (INIT.P), =255 (1st INIT.B), =CY (2nd INIT.B FAILs) 1431 INIT.F ENTRY Initialize on behalf of entire source file 1431 AA=@E.O.CODE 1434 %E.O.MEM=AA 1437* AA=0 1439 %ERR.CNT=AA 143C CALL FILE.POINT 143F SWAP ES,DS %(SI,DS) = . 1443 SWAP SI,DI %(DI,ES) = Symtab 1st entry 1445 A=0FB Need Init Symtab = ,0 1447 $DI+=A 0FB,0,0,,0 1448* AA=0 (pad w/Spaces) 144A %DI+=AA 144B DO $DI+=$SI+ 144C* $SI:"." 144F LOOP UNTIL EQ 1451 AA=" " 1454 %DI+=AA 1455 %DI+=AA 1456 %DI+=AA 1457 %DI+=AA 1458* AA=0 145A DI=0B 145D %DI+=AA 145E ES=CS 1460 RETURN 1461 NEXT.LINE ENTRY 1461 CS: SI,DS=%FILE.PTR Get pointers positioned 1466 CALL EOF.COUNT for another line of source. 1469 SWAP AA,BC RTN CY if too near the EOF. 146A DO UNTIL BC=0 146C A=$SI+ 146D* A:CR 146F BC=BC-1 LOOP NE (BC>0) 1471+ SI=SI+1 LFxxxx xLF 1472 CALL MIN.SI ^BC------^EOF 1475 AA=DS (min = 9) 1477 DS=CS 1479* BC:9 147C IF GE, 147E %FILE.PTR+2=AA 1481 %FILE.PTR=SI 1485 RETURN 1486 =16*0 .P 1496 CK.LIST: ="NAME",35*0 14BD INIT.P ENTRY Initialize before call MATCH(prep) 14BD BP=@PREP 14C0 DE=(BP+2) 14C3 BP=%BP 14C6 AA=%TOKENS+2 14C9 ES=AA ES = Token Segment 14CB* AA=0 DI will Index EOF of Tokens (until WRAPUP) 14CD %PARMS+FLAGS=AA 14D0 SWAP AA,DI DI,ES = Match Object (Token Stream) 14D1 SI,DS=%FILE.PTR SI,DS = Match Source 14D5 CS: %MAX.SRC=SI 14DA CS: %COLUMN1=SI 14DF RETURN 14E0 INIT.B ENTRY Initialize before call MATCH(body) 14E0 DS=CS 14E2 BP=@BODY 14E5 DE=(BP+2) 14E8 BP=%BP 14EB* $PARMS+FLAGS=$PARMS+FLAGS+255 14F0 IF NC, 14F2 AA=%OBJECT 14F5 %PARMS+ADDR=AA 14F8 SI,DS=%FILE.PTR 14FC CALL WRITE.HEX 14FF+ SI=SI+1 1500. CY=0 1501 RETURN 1502 INIT.T ENTRY 1502 BP=@PARMS 1505 HL=@BACK 1508 %BP=HL %BP=@BACK Subpatterns 150B CS: HL=%HL HL=%BACK (1st Pattern) 150E SWAP DE,DI DE=End-of-Tokens 1510* DI=0 1512 %(BP+EXIT)=SP Set an Exit Address 1515 CS: %FILE.PTR=SI Update SourcePtr; can't BACKUP now 151A %(BP+S.S)=DS Save the Source Segment Register 151D RETURN 151E =16*0 .P 152E FAIL.WRAP POP SI 152F CS: A=$SI 1532 CS: $ERR.FLG=A 1536 F.E: SP=%(BP+EXIT) 1539 ERROR ENTRY CALLED from TRANSLATE or WRAPUP when 1539 CS: DS=%FILE.PTR+2 MATCH(prep), MATCH(body), and 153E CS: SI=%COLUMN1 WRAPUP can't handle statement 1543 AA=%(SI+4) (columns 5-6) 1546* A:"=" Kxxx=arb 1548 IF NE, Knn?=arb 154A* A':"=" Kxxx =arb 154D * IF NE,EXIT K nn?=arb 154F+ SI=SI+1 1550 $SI=" " 1553+ ELSE SI=SI+1 (column 2/3) 1554 ERR.1: %(SI+2)="?=" (columns 4/5-5/6) 1559 CS: AA=%MAX.SRC 155D* CS: AA=AA-%COLUMN1 1562* AAM A'=10's, A=1's (Decimal Number) 1564* AA=AA OR "00" 1567 SWAP A,A' 1569* A:"9" 156B IF GT, 156D A="9" (max=99) 156F %SI=AA 1571 CS: A=$ERR.CNT 1575* A=A+01 1577* DAA Keep a BCD ERR.CNT 1578 IF CY, 157A A=099 (max=99) 157C CS: $ERR.CNT=A 1580 RETURN 1581 CS: A=$ERR.FLG xxxx+label 1585 $(SI+4)=A nn?=xlabel 1588 GOTO ERR.1 158A =50*0 .P 15BC FUNCTIONS ENTRY 15BC =@F.0 Pattern Definition Fixup (post processing) 15BE =@F.A Reference a