SCANNER.MOD 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. (* Renamed for readability. Semantics unchanged. Original identifiers: see docs/compiler/ + src/compiler/RENAME-MAP.md. *)
  2. IMPLEMENTATION MODULE Scanner;
  3. IMPORT Compiler, Files, Texts, ComLine, Loader, Doubles, Errors, SymTab, CodeGen;
  4. FROM SYSTEM IMPORT ADR, MOVE, CODE, TSIZE, BYTE, OVERFLOW, REALOVERFLOW;
  5. FROM STORAGE IMPORT ALLOCATE,MARK,RELEASE;
  6. VAR withSave: RecordPtr;
  7. tokLen: CARDINAL;
  8. CONST FREEMARKER = 3AE3H;
  9. CONST EOT = 032C; DEL = 177C;
  10. CONST LINEFEED = 012C; TAB = 011C; CR = 015C;
  11. VAR stackLimit [0316H]: ADDRESS;
  12. VAR buffer [0080H]: ARRAY [0..127] OF CHAR;
  13. VAR bufIndex[006CH]: CARDINAL;
  14. VAR filePos [006EH]: CARDINAL;
  15. VAR column [0070H]: CARDINAL;
  16. VAR flag [0072H]: CARDINAL;
  17. CONST EXPECTED = " expected, but ";
  18. (* $[+ remove procedure names *)
  19. PROCEDURE ScanErr(c: CARDINAL);
  20. BEGIN
  21. Errors.ReportError(c);
  22. END ScanErr;
  23. PROCEDURE ChangeEx(VAR f: ARRAY OF CHAR; e: Ext; x: BOOLEAN);
  24. VAR i: CARDINAL;
  25. BEGIN
  26. i := 0;
  27. WHILE (i < HIGH(f) - 3) AND (f[i] <> 0C) AND (f[i] <> '.') DO
  28. INC(i)
  29. END;
  30. IF x OR (f[i] <> '.') THEN
  31. f[i] := '.';
  32. MOVE(ADR(e), ADR(f[i+1]), 3);
  33. END;
  34. END ChangeEx;
  35. PROCEDURE EnterMod(m: ARRAY OF CHAR; k: CARDINAL): CARDINAL;
  36. VAR i: CARDINAL;
  37. ptr : POINTER TO SymTab.Symbol;
  38. BEGIN
  39. i := 0;
  40. WHILE (i < SymTab.moduleCount) AND (SymTab.moduleTable^[i].name <> m) DO
  41. INC(i)
  42. END;
  43. ptr := ADR(SymTab.moduleTable^[i]);
  44. IF i < SymTab.moduleCount THEN
  45. IF ptr^.word <> k THEN Errors.ReportErrorWithText(12, ptr^.name) END;
  46. ELSE
  47. IF i > 15 THEN ScanErr(84) END;
  48. ptr^.name := m;
  49. ptr^.word := k;
  50. INC(SymTab.moduleCount);
  51. END;
  52. RETURN i
  53. END EnterMod;
  54. PROCEDURE Allocate(VAR a:ADDRESS; n:CARDINAL); (* was in Z80 code *)
  55. BEGIN
  56. ALLOCATE(a, n);
  57. RETURN;
  58. (* padding to compensate for length difference *)
  59. n := n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n+n;
  60. RETURN; RETURN;
  61. END Allocate;
  62. PROCEDURE GetStack(VAR m: ADDRESS);
  63. BEGIN
  64. m := stackLimit - 60;
  65. END GetStack;
  66. PROCEDURE CheckStk(m: ADDRESS);
  67. BEGIN
  68. stackLimit := m + 60;
  69. m^ := FREEMARKER;
  70. END CheckStk;
  71. (* proc 22: find identifier in keyword list *)
  72. PROCEDURE FindIden(l: List; i: ADDRESS; c: BOOLEAN): RecordPtr;
  73. (* original was in Z80 code *)
  74. VAR current: T1;
  75. BEGIN
  76. current := l^.first;
  77. WHILE current <> NIL DO
  78. IF StrCmp(i, current^.link1, c) THEN
  79. RETURN ADDRESS(current)
  80. END;
  81. current := current^.link0;
  82. END;
  83. RETURN NIL;
  84. (* padding to compensate for different length *)
  85. c := NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT
  86. NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT NOT c
  87. END FindIden;
  88. (* original was in Z80 code; the decompiled StringPtr-param form is rejected
  89. by v1.00 at the FindIden call site (pointer-type mismatch). ADDRESS
  90. params with a local byte-overlay generate identical indexed-byte code.
  91. Case handling: none (as decompiled — c unused). *)
  92. TYPE ByteVec = POINTER TO ARRAY [0..32767] OF CHAR;
  93. PROCEDURE StrCmp(a, b: ADDRESS; c: BOOLEAN):BOOLEAN;
  94. VAR x, y: ByteVec;
  95. BEGIN
  96. x := a; y := b;
  97. WHILE x^[0] = y^[0] DO
  98. IF x^[0] = 0C THEN RETURN TRUE END;
  99. x := ADR(x^[1]);
  100. y := ADR(y^[1]);
  101. END;
  102. RETURN FALSE;
  103. END StrCmp;
  104. (* StrLen: original was Z80 code *)
  105. PROCEDURE StrLen(VAR s: ARRAY OF CHAR): CARDINAL;
  106. VAR i: CARDINAL;
  107. BEGIN
  108. i := 0;
  109. WHILE (i < HIGH(s)) AND (s[i] # 0C) DO INC(i) END;
  110. IF i # 0 THEN RETURN i END;
  111. RETURN 1; (* never return a zero length *)
  112. END StrLen;
  113. PROCEDURE CopyStr(VAR d: ADDRESS; VAR s: ARRAY OF CHAR);
  114. VAR length: CARDINAL;
  115. BEGIN
  116. length := StrLen(s);
  117. Allocate(d, length+1);
  118. MOVE(ADR(s), d, length);
  119. END CopyStr;
  120. PROCEDURE NewNode(k:CARDINAL):ADDRESS;
  121. VAR ptr: Compiler.RecordPtr;
  122. BEGIN
  123. Allocate(ptr, 14);
  124. ptr^.word4 := k;
  125. RETURN ptr
  126. END NewNode;
  127. PROCEDURE NewSized(k:CARDINAL):ADDRESS;
  128. VAR ptr: Compiler.RecordPtr;
  129. BEGIN
  130. IF k <= 1 THEN Allocate(ptr, 14)
  131. ELSIF k <= 6 THEN Allocate(ptr, 10)
  132. ELSIF k <= 11 THEN Allocate(ptr, 12)
  133. ELSE Allocate(ptr, 16)
  134. END;
  135. ptr^.word4 := k;
  136. RETURN ptr
  137. END NewSized;
  138. PROCEDURE MakeIden(k: CARDINAL): ADDRESS;
  139. VAR ptr : Compiler.RecordPtr;
  140. BEGIN
  141. NeedID;
  142. IF ADDRESS(scopeCur) = SymTab.currentScope THEN Errors.ReportErrorWithText(1, tokBuf) END;
  143. ptr := NewNode(k);
  144. CopyStr(ptr^.word1, tokBuf);
  145. GetSym;
  146. RETURN ptr
  147. END MakeIden;
  148. PROCEDURE InsertSy(n: SymTab.T1);
  149. BEGIN
  150. IF FindIden(ADR(SymTab.currentScope^.link1), n^.link1, 9 IN scanOpt) # NIL THEN
  151. Errors.ReportErrorWithText(1, n^.link1^)
  152. END;
  153. n^.link0 := SymTab.currentScope^.link1;
  154. SymTab.currentScope^.link1 := n;
  155. END InsertSy;
  156. PROCEDURE DeclIden(k: CARDINAL): ADDRESS;
  157. VAR ptr: SymTab.T1;
  158. BEGIN
  159. ptr := MakeIden(k);
  160. ptr^.link0 := SymTab.currentScope^.link1;
  161. SymTab.currentScope^.link1 := ptr;
  162. RETURN ptr;
  163. END DeclIden;
  164. PROCEDURE OpenScop(a:ADDRESS; b: ADDRESS);
  165. BEGIN
  166. Allocate(SymTab.currentScope, 14);
  167. SymTab.currentScope^.w0 := a;
  168. SymTab.currentScope^.link1 := b;
  169. END OpenScop;
  170. PROCEDURE WritList;
  171. VAR PipeChar[034EH]: CHAR;
  172. BEGIN
  173. Texts.WriteLn(2);
  174. IF listing
  175. THEN Texts.WriteCard(2, CodeGen.nextEmitPos - codeSize, 4)
  176. ELSE Texts.SetCol(2, 4)
  177. END;
  178. Texts.WriteChar(2, PipeChar);
  179. Texts.WriteChar(2, ' ')
  180. END WritList;
  181. PROCEDURE EchoChar;
  182. BEGIN
  183. IF (ORD(curCh) + 1) MOD 256 > 32 THEN Texts.WriteChar(2, curCh); RETURN END;
  184. IF curCh = LINEFEED THEN column := 0; WritList; RETURN END;
  185. IF curCh = TAB THEN
  186. REPEAT Texts.WriteChar(2," "); INC(column) UNTIL column MOD 8 = 0;
  187. ELSIF (curCh < " ") AND (curCh # CR) THEN
  188. Texts.WriteChar(2, "^");
  189. Texts.WriteChar(2, CHR(ORD(curCh)+40H))
  190. END;
  191. END EchoChar;
  192. PROCEDURE Refill;
  193. VAR nbRead: CARDINAL;
  194. BEGIN
  195. nbRead := Files.ReadBytes(srcFile, ADR(buffer), 128);
  196. IF nbRead < 128 THEN buffer[nbRead] := EOT END;
  197. bufIndex := 0;
  198. NextCh
  199. END Refill;
  200. PROCEDURE InitScan;
  201. BEGIN
  202. curCh := ' ';
  203. column := 0;
  204. bufIndex := 128;
  205. IF 0 IN scanOpt THEN WritList END;
  206. Files.NoTrailer(srcFile)
  207. END InitScan;
  208. PROCEDURE OpenSrc;
  209. VAR nbRead: CARDINAL;
  210. BEGIN
  211. IF NOT Files.Open(srcFile, ComLine.inName) THEN HALT END;
  212. InitScan;
  213. Files.SetPos(srcFile, LONG((tokPos DIV 128) * 128));
  214. nbRead := Files.ReadBytes(srcFile, ADR(buffer), 128);
  215. bufIndex := tokPos MOD 128;
  216. filePos := tokPos;
  217. GetSym
  218. END OpenSrc;
  219. PROCEDURE NextCh; (* original was in Z80 code *)
  220. VAR ch: CHAR;
  221. BEGIN
  222. IF bufIndex = 128 THEN Refill
  223. ELSE
  224. ch := buffer[bufIndex];
  225. INC(bufIndex);
  226. IF ch = EOT THEN curCh := 377C ELSE curCh := ch END;
  227. INC(filePos);
  228. IF 0 IN scanOpt THEN
  229. IF ch >= ' ' THEN
  230. INC(column);
  231. IF flag # 0 THEN
  232. Texts.WriteChar(3, ch);
  233. RETURN; RETURN; (* padding *)
  234. END;
  235. END;
  236. EchoChar
  237. END;
  238. END;
  239. RETURN;
  240. (* padding to compensate for smaller length *)
  241. INC(ch); INC(ch); INC(ch); INC(ch); INC(ch); INC(ch);
  242. INC(ch); INC(ch); INC(ch); INC(ch); RETURN; RETURN; RETURN; RETURN;
  243. END NextCh;
  244. PROCEDURE GetSym;
  245. (* $[- keep procedure names *)
  246. (* proc 35 *)
  247. PROCEDURE ParseNum;
  248. VAR intPart: CARDINAL;
  249. VAR expVal: CARDINAL;
  250. VAR curDig: CARDINAL;
  251. VAR prevDig: CARDINAL;
  252. VAR limit: CARDINAL;
  253. VAR expAdj: INTEGER;
  254. VAR negExp: BOOLEAN;
  255. VAR isDec : BOOLEAN;
  256. VAR isOctal: BOOLEAN;
  257. VAR decVal: LONGINT;
  258. VAR decFull: LONGINT;
  259. VAR octVal: LONGINT;
  260. VAR hexVal: LONGINT;
  261. (* $[+ remove procedure names *)
  262. (* proc 36 *)
  263. PROCEDURE Power10(exp: CARDINAL): REAL;
  264. VAR i: CARDINAL;
  265. VAR r: REAL;
  266. BEGIN
  267. i := 0;
  268. r := 1.0;
  269. REPEAT
  270. IF ODD(exp) THEN
  271. CASE i OF
  272. | 0 : r := r * 1.0E01
  273. | 1 : r := r * 1.0E02
  274. | 2 : r := r * 1.0E04
  275. | 3 : r := r * 1.0E08
  276. | 4 : r := r * 1.0E16
  277. | 5 : r := r * 1.0E32
  278. ELSE RAISE REALOVERFLOW
  279. END;
  280. END;
  281. exp := exp DIV 2;
  282. INC(i);
  283. UNTIL exp = 0;
  284. RETURN r
  285. END Power10;
  286. PROCEDURE AccumDig;
  287. VAR digit: CARDINAL;
  288. BEGIN
  289. IF tokLen < 128 THEN tokBuf[tokLen] := curCh; INC(tokLen) END;
  290. NextCh;
  291. digit := ORD(curCh) - ORD('0');
  292. IF digit > 9 THEN
  293. IF digit >= 17 THEN digit := digit - 7 ELSE digit := 16 END;
  294. END; (* 043C *)
  295. curDig := digit
  296. END AccumDig;
  297. (* $[- keep procedure names *)
  298. BEGIN (* ParseNum *)
  299. intPart := 0;
  300. decVal := LONG(0);
  301. expAdj := 0;
  302. hexVal := decVal;
  303. octVal := decVal;
  304. decFull := decVal;
  305. tokLen:= 0;
  306. curDig := ORD(curCh) - ORD('0');
  307. prevDig := curDig;
  308. isOctal := TRUE;
  309. isDec := TRUE;
  310. REPEAT
  311. IF prevDig > 7 THEN
  312. isOctal := FALSE;
  313. IF prevDig > 9 THEN isDec := FALSE END;
  314. END;
  315. IF curDig <= 9 THEN
  316. decFull := decFull * LONG(10) + LONG(curDig);
  317. IF decFull < 3355443L THEN decVal := decFull ELSE INC(expAdj) END;
  318. IF curDig <= 7 THEN octVal := octVal * LONG(8) + LONG(curDig) END;
  319. END; (* 04b1 *)
  320. IF hexVal <= LONG(65535) THEN hexVal := hexVal * LONG(16) + LONG(curDig) END;
  321. prevDig := curDig;
  322. AccumDig;
  323. UNTIL curDig > 15;
  324. litType := Compiler.CardType;
  325. IF curCh = '.' THEN
  326. AccumDig;
  327. IF curCh = '.' THEN curCh := DEL; DEC(tokLen)
  328. ELSIF curCh = ')' THEN curCh := ']'; DEC(tokLen)
  329. ELSE
  330. IF NOT isDec THEN ScanErr(30) END;
  331. litType := Compiler.RealType;
  332. WHILE curDig <= 9 DO
  333. IF decVal < 3355443L THEN
  334. decVal := decVal * LONG(10) + LONG(curDig);
  335. DEC(expAdj)
  336. END; (* 0527 *)
  337. AccumDig;
  338. END; (* 052B *)
  339. IF curDig IN {13, 14} THEN
  340. IF curDig = 13 THEN litType := Compiler.LongrealType END;
  341. expVal := 0;
  342. AccumDig;
  343. negExp := (curCh = '-');
  344. IF negExp OR (curCh = '+') THEN AccumDig END;
  345. IF curDig > 9 THEN ScanErr(30) END;
  346. REPEAT
  347. IF expVal < 255 THEN expVal := expVal * 10 + curDig END;
  348. AccumDig;
  349. UNTIL curDig > 9;
  350. IF negExp
  351. THEN DEC(expAdj, expVal)
  352. ELSE INC(expAdj, expVal)
  353. END;
  354. END; (* 0577 *)
  355. IF litType = Compiler.RealType THEN
  356. IF decVal >= 16777216L
  357. THEN realVal := FLOAT((decVal + LONG(1)) DIV LONG(2)) * 2.0
  358. ELSE realVal := FLOAT(decVal)
  359. END;
  360. IF expAdj < 0 THEN realVal := realVal / Power10(-expAdj)
  361. ELSIF expAdj # 0 THEN realVal := realVal * Power10(expAdj)
  362. END;
  363. ELSE
  364. tokBuf[tokLen] := 0C;
  365. IF NOT Doubles.StrToDouble(tokBuf, lrealVal) THEN ScanErr(74) END;
  366. END;
  367. END;
  368. END; (* 05D4 *)
  369. IF litType^.word4 # 8 THEN
  370. IF curCh = 'L' THEN
  371. AccumDig;
  372. realVal := REAL(decFull);
  373. litType := Compiler.LongintType;
  374. ELSE
  375. limit := 65535;
  376. IF curCh = 'H' THEN AccumDig; decVal := hexVal
  377. ELSE
  378. IF prevDig IN {11, 12} THEN
  379. IF NOT isOctal THEN ScanErr(30) END;
  380. decVal := octVal;
  381. IF prevDig = 12 THEN litType := Compiler.CharType; limit := 255 END;
  382. ELSE
  383. IF NOT isDec OR (prevDig > 9) THEN ScanErr(30) END;
  384. decVal := decFull;
  385. END;
  386. END; (* 062e *)
  387. IF decVal > LONG(limit) THEN ScanErr(73) END;
  388. cardVal := CARD(decVal);
  389. END;
  390. END; (* 063f *)
  391. IF charClas^[ORD(curCh)] = 10 THEN ScanErr(30) END;
  392. EXCEPTION
  393. | OVERFLOW: ScanErr(73)
  394. | REALOVERFLOW:
  395. IF expAdj >= 0 THEN ScanErr(74) END;
  396. realVal := REAL(0L);
  397. END ParseNum;
  398. (* $[+ remove procedure names *)
  399. PROCEDURE SkipComm;
  400. VAR optIdx: CARDINAL;
  401. BEGIN
  402. REPEAT
  403. REPEAT
  404. IF curCh = CHR(255) THEN ScanErr(29) END;
  405. NextCh;
  406. IF curCh = '(' THEN
  407. REPEAT NextCh UNTIL curCh # '(';
  408. IF curCh = '*' THEN SkipComm END; (* recursive call *)
  409. END;
  410. IF curCh = '$' THEN
  411. NextCh;
  412. optIdx := CARDINAL(BITSET(curCh) * {0,1,2,3,4,6}) - ORD('L');
  413. IF optIdx <= 15 THEN
  414. NextCh;
  415. IF curCh = '-' THEN EXCL(scanOpt, optIdx)
  416. ELSIF curCh = '+' THEN INCL(scanOpt, optIdx)
  417. END;
  418. IF optIdx = 0 THEN Texts.WriteLn(2) END;
  419. END;
  420. END; (* 06c6 *)
  421. UNTIL curCh = '*';
  422. REPEAT NextCh UNTIL curCh # '*';
  423. UNTIL curCh = ')';
  424. END SkipComm;
  425. PROCEDURE ScanNext():BOOLEAN; (* original was in Z80 code *)
  426. VAR j: CARDINAL;
  427. VAR nextClass: CARDINAL;
  428. BEGIN
  429. isLit := FALSE;
  430. identKd := 7;
  431. WHILE curCh <= ' ' DO NextCh END;
  432. tokPos := filePos - 1;
  433. tokCol := column;
  434. IF curCh < CHR(128)
  435. THEN curSym := charClas^[ORD(curCh)]
  436. ELSE curSym := 0
  437. END;
  438. IF curSym = 10 THEN
  439. j := 0;
  440. REPEAT
  441. IF j # 128 THEN tokBuf[j] := curCh; INC(j) END;
  442. NextCh;
  443. nextClass := charClas^[ORD(curCh)];
  444. UNTIL (nextClass # 10) AND (nextClass # 11);
  445. tokBuf[j] := 0C;
  446. RETURN TRUE
  447. END; (* 0730 *)
  448. RETURN FALSE;
  449. (* padding to compensate for smaller code *)
  450. j := j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j+j
  451. END ScanNext;
  452. VAR tokDone: BOOLEAN;
  453. strLen: CARDINAL;
  454. ignCase: BOOLEAN;
  455. quote: CHAR;
  456. BEGIN
  457. REPEAT
  458. IF ScanNext() THEN
  459. ignCase := 9 IN scanOpt;
  460. curSym := keyHash(ADR(tokBuf), ignCase);
  461. IF curSym # 0 THEN
  462. identKd := 7;
  463. IF ((curSym = 14) OR (curSym = 39)) AND NOT (12 IN scanOpt) THEN
  464. Errors.AskContinue(2)
  465. END;
  466. RETURN
  467. END; (* 0797 *)
  468. scopeCur := ADDRESS(SymTab.currentScope);
  469. REPEAT
  470. curNode := FindIden(ADR(scopeCur^.link1), ADR(tokBuf), ignCase);
  471. IF curNode # NIL THEN
  472. litType := ADDRESS(curNode^.word2);
  473. identKd := curNode^.word4;
  474. follSet := curNode^.word3;
  475. RETURN
  476. END;
  477. scopeCur := scopeCur^.link0;
  478. UNTIL scopeCur = NIL;
  479. identKd := 0;
  480. RETURN
  481. END; (* 07BA *)
  482. tokDone := TRUE;
  483. CASE curSym OF
  484. | 0 : ScanErr(31 - ORD(curCh = CHR(255)) * 2)
  485. | 2 : NextCh;
  486. IF curCh = '=' THEN curSym := 27; NextCh
  487. ELSIF curCh = ')' THEN curSym := 7; NextCh
  488. END;
  489. | 3 : NextCh;
  490. IF curCh = '.' THEN curSym := 4; NextCh
  491. ELSIF curCh = ')' THEN curSym := 6; NextCh
  492. END;
  493. |11 : isLit := TRUE;
  494. identKd := 1;
  495. curSym := 0;
  496. ParseNum;
  497. tokBuf[tokLen] := 0C
  498. |12 : strLen := 0;
  499. isLit := TRUE;
  500. identKd := 1;
  501. curSym := 0;
  502. quote := curCh;
  503. NextCh;
  504. WHILE curCh # quote DO
  505. IF curCh = LINEFEED THEN ScanErr(28) END;
  506. IF curCh = CHR(255) THEN ScanErr(29) END;
  507. IF strLen < 128 THEN
  508. tokBuf[strLen] := curCh;
  509. INC(strLen);
  510. END;
  511. NextCh;
  512. END; (* 0839 *)
  513. tokBuf[strLen] := 0C;
  514. NextCh;
  515. litType := Compiler.charArrayDesc;
  516. IF strLen = 1 THEN
  517. litType := Compiler.CharType;
  518. cardVal := ORD(tokBuf[0]);
  519. END;
  520. ELSE
  521. NextCh;
  522. CASE curSym OF
  523. | 43: IF curCh = '*' THEN SkipComm; NextCh; tokDone := FALSE
  524. ELSIF curCh = '.' THEN curSym := 44; NextCh
  525. ELSIF curCh = ':' THEN curSym := 45; NextCh
  526. END;
  527. | 54: IF curCh = '=' THEN curSym := 56; NextCh
  528. ELSIF curCh = '>' THEN curSym := 53; NextCh
  529. END;
  530. | 55: IF curCh = '=' THEN curSym := 57; NextCh END;
  531. END;
  532. END;
  533. UNTIL tokDone;
  534. END GetSym;
  535. PROCEDURE AcceptSy(s: CARDINAL): BOOLEAN;
  536. BEGIN
  537. IF curSym = s THEN GetSym; RETURN TRUE END;
  538. RETURN FALSE
  539. END AcceptSy;
  540. PROCEDURE PushWith;
  541. BEGIN
  542. IF identKd = 6 THEN
  543. withSave^.word1 := ADDRESS(curNode^.high);
  544. withSave^.word0 := ADDRESS(SymTab.currentScope);
  545. SymTab.currentScope := ADDRESS(withSave);
  546. GetSym;
  547. ExpectSy(3);
  548. NeedID;
  549. IF scopeCur # ADDRESS(withSave) THEN Errors.ReportErrorWithText(3, tokBuf) END;
  550. SymTab.currentScope := SymTab.currentScope^.w0;
  551. END;
  552. END PushWith;
  553. PROCEDURE ExpectSy(s:CARDINAL);
  554. VAR expSet: BITSET;
  555. VAR base: CARDINAL;
  556. BEGIN
  557. IF curSym = s THEN GetSym; RETURN END;
  558. base := 0;
  559. expSet := {};
  560. IF s >= 51 THEN base := 51
  561. ELSIF s >= 40 THEN base := 40
  562. ELSIF s >= 27 THEN base := 27
  563. ELSIF s >= 13 THEN base := 13
  564. END;
  565. expSet := expSet + {s - base};
  566. Errors.ReportExpectedSet(expSet, base)
  567. END ExpectSy;
  568. PROCEDURE TestSet(s: BITSET);
  569. BEGIN
  570. IF NOT (curSym IN s) THEN Errors.ReportExpectedSet(s, 0) END;
  571. END TestSet;
  572. PROCEDURE TestR40(s: BITSET);
  573. BEGIN
  574. IF NOT ((curSym-40) IN s) THEN Errors.ReportExpectedSet(s, 40) END;
  575. END TestR40;
  576. PROCEDURE TestR13(s: BITSET);
  577. BEGIN
  578. IF NOT ((curSym-13) IN s) THEN Errors.ReportExpectedSet(s, 13) END;
  579. END TestR13;
  580. PROCEDURE NeedID;
  581. BEGIN
  582. IF (identKd = 7) OR isLit THEN
  583. Errors.ShowErrorPosition('A');
  584. Texts.WriteString(3, "Identifier");
  585. Texts.WriteString(3, EXPECTED);
  586. Errors.WriteFoundToken;
  587. Errors.AskEditOrQuit;
  588. END;
  589. END NeedID;
  590. PROCEDURE ExpectSt(VAR p: ARRAY OF CHAR);
  591. BEGIN
  592. NeedID;
  593. IF StrCmp(ADR(tokBuf), ADR(p), 9 IN scanOpt) THEN GetSym; RETURN END;
  594. Errors.ReportErrorWithText(9, p);
  595. END ExpectSt;
  596. PROCEDURE ExpectKd(k: CARDINAL);
  597. BEGIN
  598. IF identKd # k THEN
  599. NeedID;
  600. IF identKd = 0 THEN Errors.ReportErrorWithText(0, tokBuf) END;
  601. Errors.ShowErrorPosition('B');
  602. Errors.WriteKindName(k);
  603. Texts.WriteString(3, EXPECTED);
  604. Errors.WriteKindName(identKd);
  605. Texts.WriteString(3, " found");
  606. Errors.AskEditOrQuit;
  607. END;
  608. END ExpectKd;
  609. PROCEDURE Compile;
  610. (* Z80 proc 40 removed in Reloaded; v1.00 rejects SYSTEM.ADR on simple
  611. unstructured variables, so this open-array shim recovers the address.
  612. Proven on hardware: open VAR ARRAY OF WORD accepts any variable, and
  613. ADR(x) inside is legal (probe ZZ.DEF/MOD). *)
  614. PROCEDURE VarAddr(VAR x: ARRAY OF WORD): ADDRESS;
  615. BEGIN
  616. RETURN ADR(x);
  617. END VarAddr;
  618. VAR addr: ADDRESS;
  619. ptr [006EH]: CARDINAL;
  620. console [0072H]: BOOLEAN;
  621. jmpOpc [0074H]: CARDINAL;
  622. jmpAddr[0075H]: CARDINAL;
  623. (* $[- keep procedure names *)
  624. BEGIN
  625. jmpOpc := 0C3H;
  626. addr := VarAddr(scanOpt)-6;
  627. addr := ADDRESS(addr^) - 4;
  628. jmpAddr:= addr + CARDINAL(addr^) + 3;
  629. MARK(addr);
  630. ptr := 0;
  631. console := (ComLine.outName = "CON:");
  632. listing := FALSE;
  633. tokPos := 0;
  634. Allocate(withSave, 14);
  635. Compiler.OpenSourceAndOutput;
  636. IF srcFile <> NIL THEN
  637. Allocate(codeBuf, 4096);
  638. Loader.Call("COMPILE");
  639. IF Compiler.nativeCodeRequested THEN
  640. CheckStk(codeBuf + CodeGen.nextEmitPos);
  641. IF CodeGen.windowBase <> 0 THEN
  642. MOVE(codeBuf, codeBuf + CodeGen.windowBase, CodeGen.nextEmitPos - CodeGen.windowBase);
  643. Files.SetPos(codeFile, LONG(0));
  644. IF Files.ReadBytes(codeFile, codeBuf, CodeGen.windowBase) <> CodeGen.windowBase THEN
  645. RAISE Files.EndError
  646. END;
  647. END;
  648. Files.SetPos(codeFile, LONG(0));
  649. Loader.Call("GENZ80");
  650. END;
  651. END;
  652. Texts.CloseText(Texts.output);
  653. RELEASE(addr);
  654. EXCEPTION Loader.LoadError:
  655. Texts.WriteLn(3); (* console *)
  656. Texts.WriteString(3,"ERROR: CANNOT LOAD OVERLAY");
  657. Texts.WriteLn(3);
  658. Files.Delete(codeFile);
  659. RELEASE(addr)
  660. END Compile;
  661. (* $[+ remove procedure names *)
  662. END Scanner.