token-scanner.red 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. %
  2. % TOKEN-SCANNER.RED - Table-driven token scanner
  3. %
  4. % Author: Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 27 August 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % Edit by Cris Perdue, 29 Jan 1983 1338-PST
  12. % Occurrences of "dipthong" changed to "diphthong"
  13. % <PSL.KERNEL>TOKEN-SCANNER.RED.2, 16-Dec-82 14:55:55, Edit by BENSON
  14. % MakeBufIntoFloat uses floating point arithmetic on each digit
  15. % <PSL.INTERP>TOKEN-SCANNER.RED.6, 15-Sep-82 10:49:54, Edit by BENSON
  16. % Can now scan 1+ and 1-
  17. % <PSL.INTERP>TOKEN-SCANNER.RED.12, 10-Jan-82 21:53:28, Edit by BENSON
  18. % Fixed bug in floating point parsing
  19. % <PSL.INTERP>TOKEN-SCANNER.RED.9, 8-Jan-82 07:06:23, Edit by GRISS
  20. % MakeBufIntoLispInteger becomes procedure for BigNums
  21. % <PSL.INTERP>TOKEN-SCANNER.RED.7, 28-Dec-81 22:09:14, Edit by BENSON
  22. % Made dipthong indicator last element of scan table
  23. fluid '(CurrentScanTable!* !*Raise !*Compressing !*EOLInStringOK);
  24. LoadTime <<
  25. !*Raise := T;
  26. !*Compressing := NIL;
  27. !*EOLInStringOK := NIL;
  28. >>;
  29. CompileTime flag('(ReadInBuf MakeBufIntoID MakeBufIntoString
  30. MakeBufIntoLispInteger MakeBufIntoSysNumber
  31. MakeBufIntoFloat MakeStringIntoSysInteger
  32. MakeStringIntoBitString ScannerError SysPowerOf2P
  33. ScanPossibleDiphthong),
  34. 'InternalFunction);
  35. on SysLisp;
  36. % DIGITS are 0..9
  37. internal WConst LETTER = 10,
  38. DELIMITER = 11,
  39. COMMENTCHAR = 12,
  40. DIPHTHONGSTART = 13,
  41. IDESCAPECHAR = 14,
  42. STRINGQUOTE = 15,
  43. PACKAGEINDICATOR = 16,
  44. IGNORE = 17,
  45. MINUSSIGN = 18,
  46. PLUSSIGN = 19,
  47. DECIMALPOINT = 20,
  48. IDSURROUND = 21;
  49. internal WVar TokCh,
  50. TokChannel,
  51. ChTokenType,
  52. CurrentChar,
  53. ChangedPackages,
  54. TokRadix,
  55. TokSign,
  56. TokFloatFractionLength,
  57. TokFloatExponentSign,
  58. TokFloatExponent;
  59. CompileTime <<
  60. syslsp smacro procedure TokenTypeOfChar Ch;
  61. IntInf VecItm(VecInf LispVar CurrentScanTable!*, Ch);
  62. syslsp smacro procedure CurrentDiphthongIndicator();
  63. VecItm(VecInf LispVar CurrentScanTable!*, 128);
  64. syslsp smacro procedure ResetBuf();
  65. CurrentChar := 0;
  66. syslsp smacro procedure BackupBuf();
  67. CurrentChar := CurrentChar - 1;
  68. >>;
  69. syslsp procedure ReadInBuf();
  70. << TokCh := ChannelReadChar TokChannel;
  71. StrByt(TokenBuffer, CurrentChar) := TokCh;
  72. ChTokenType := TokenTypeOfChar TokCh;
  73. if CurrentChar < MaxTokenSize then
  74. CurrentChar := CurrentChar + 1
  75. else if CurrentChar = MaxTokenSize then
  76. << ErrorPrintF("***** READ Buffer overflow, Truncating");
  77. CurrentChar := MaxTokenSize + 1 >>
  78. else CurrentChar := MaxTokenSize + 1 >>;
  79. CompileTime <<
  80. syslsp smacro procedure UnReadLastChar();
  81. ChannelUnReadChar(Channel, TokCh);
  82. syslsp smacro procedure LowerCaseChar Ch;
  83. Ch >= char !a and Ch <= char !z;
  84. syslsp smacro procedure RaiseChar Ch;
  85. (Ch - char !a) + char A;
  86. syslsp smacro procedure RaiseLastChar();
  87. if LowerCaseChar TokCh then
  88. StrByt(TokenBuffer, CurrentChar - 1) := RaiseChar TokCh;
  89. >>;
  90. syslsp procedure MakeBufIntoID();
  91. << LispVar TokType!* := '0;
  92. if CurrentChar eq 1 then MkID StrByt(TokenBuffer, 0)
  93. else
  94. << StrByt(TokenBuffer, CurrentChar) := char NULL;
  95. TokenBuffer[0] := CurrentChar - 1;
  96. if LispVar !*Compressing then NewID CopyString TokenBuffer
  97. else Intern MkSTR TokenBuffer >> >>;
  98. syslsp procedure MakeBufIntoString();
  99. << LispVar TokType!* := '1;
  100. StrByt(TokenBuffer, CurrentChar) := 0;
  101. TokenBuffer[0] := CurrentChar - 1;
  102. CopyString TokenBuffer >>;
  103. syslsp procedure MakeBufIntoSysNumber(Radix, Sign);
  104. << StrByt(TokenBuffer, CurrentChar) := 0;
  105. TokenBuffer[0] := CurrentChar - 1;
  106. MakeStringIntoSysInteger(TokenBuffer, Radix, Sign) >>;
  107. syslsp procedure MakeBufIntoLispInteger(Radix, Sign);
  108. << LispVar TokType!* := '2;
  109. StrByt(TokenBuffer, CurrentChar) := 0;
  110. TokenBuffer[0] := CurrentChar - 1;
  111. MakeStringIntoLispInteger(MkSTR TokenBuffer, Radix, Sign) >>;
  112. internal WArray MakeFloatTemp1[1],
  113. MakeFloatTemp2[1],
  114. FloatTen[1];
  115. % Changed to use floating point arithmetic on the characters, rather
  116. % than converting to an integer. This avoids overflow problems.
  117. syslsp procedure MakeBufIntoFloat Exponent;
  118. begin scalar F, N;
  119. !*WFloat(FloatTen, 10);
  120. !*WFloat(MakeFloatTemp1, 0);
  121. N := CurrentChar - 1;
  122. for I := 0 step 1 until N do
  123. << !*WFloat(MakeFloatTemp2, DigitToNumber StrByt(TokenBuffer, I));
  124. !*FTimes2(MakeFloatTemp1, MakeFloatTemp1, FloatTen);
  125. !*FPlus2(MakeFloatTemp1, MakeFloatTemp1, MakeFloatTemp2) >>;
  126. if Exponent > 0 then
  127. for I := 1 step 1 until Exponent do
  128. !*FTimes2(MakeFloatTemp1, MakeFloatTemp1, FloatTen)
  129. else if Exponent < 0 then
  130. << Exponent := -Exponent;
  131. for I := 1 step 1 until Exponent do
  132. !*FQuotient(MakeFloatTemp1, MakeFloatTemp1, FloatTen) >>;
  133. LispVar TokType!* := '2;
  134. F := GtFLTN();
  135. !*FAssign(FloatBase F, MakeFloatTemp1);
  136. return MkFLTN F;
  137. end;
  138. syslsp procedure ChannelReadToken Channel; %. Token scanner
  139. %
  140. % This is the basic Lisp token scanner. The value returned is a Lisp
  141. % item corresponding to the next token from the input stream. IDs will
  142. % be interned. The global Lisp variable TokType!* will be set to
  143. % 0 if the token is an ordinary ID,
  144. % 1 if the token is a string (delimited by double quotes),
  145. % 2 if the token is a number, or
  146. % 3 if the token is an unescaped delimiter.
  147. % In the last case, the value returned by this function will be the single
  148. % character ID corresponding to the delimiter.
  149. %
  150. begin
  151. TokChannel := Channel;
  152. ChangedPackages := 0;
  153. ResetBuf();
  154. StartScanning:
  155. TokCh := ChannelReadChar Channel;
  156. ChTokenType := TokenTypeOfChar TokCh;
  157. if ChTokenType eq IGNORE then goto StartScanning;
  158. StrByt(TokenBuffer, CurrentChar) := TokCh;
  159. CurrentChar := CurrentChar + 1;
  160. case ChTokenType of
  161. 0 to 9: % digit
  162. << TokSign := 1;
  163. goto InsideNumber >>;
  164. 10: % Start of ID
  165. << if null LispVar !*Raise then
  166. goto InsideID
  167. else
  168. << RaiseLastChar();
  169. goto InsideRaisedID >> >>;
  170. 11: % Delimiter, but not beginning of Diphthong
  171. << LispVar TokType!* := '3;
  172. return MkID TokCh >>;
  173. 12: % Start of comment
  174. goto InsideComment;
  175. 13: % Diphthong start - Lisp function uses P-list of starting char
  176. return ScanPossibleDiphthong(TokChannel, MkID TokCh);
  177. 14: % ID escape character
  178. << if null LispVar !*Raise then
  179. goto GotEscape
  180. else goto GotEscapeInRaisedID >>;
  181. 15: % string quote
  182. << BackupBuf();
  183. goto InsideString >>;
  184. 16: % Package indicator - at start of token means use global package
  185. << ResetBuf();
  186. ChangedPackages := 1;
  187. Package 'Global;
  188. if null LispVar !*Raise then
  189. goto GotPackageMustGetID
  190. else goto GotPackageMustGetIDRaised >>;
  191. 17: % Ignore - can't ever happen
  192. ScannerError("Internal error - consult a wizard");
  193. 18: % Minus sign
  194. << TokSign := -1;
  195. goto GotSign >>;
  196. 19: % Plus sign
  197. << TokSign := 1;
  198. goto GotSign >>;
  199. 20: % decimal point
  200. << ResetBuf();
  201. ReadInBuf();
  202. if ChTokenType >= 10 then
  203. << UnReadLastChar();
  204. return ScanPossibleDiphthong(TokChannel, '!.) >>
  205. else
  206. << TokSign := 1;
  207. TokFloatFractionLength := 1;
  208. goto InsideFloatFraction >> >>;
  209. 21: % IDSURROUND, i.e. vertical bars
  210. << BackupBuf();
  211. goto InsideIDSurround >>;
  212. default:
  213. return ScannerError("Unknown token type")
  214. end;
  215. GotEscape:
  216. BackupBuf();
  217. ReadInBuf();
  218. goto InsideID;
  219. InsideID:
  220. ReadInBuf();
  221. if ChTokenType <= 10
  222. or ChTokenType eq PLUSSIGN
  223. or ChTokenType eq MINUSSIGN then goto InsideID
  224. else if ChTokenType eq IDESCAPECHAR then goto GotEscape
  225. else if ChTokenType eq PACKAGEINDICATOR then
  226. << BackupBuf();
  227. ChangedPackages := 1;
  228. Package MakeBufIntoID();
  229. ResetBuf();
  230. goto GotPackageMustGetID >>
  231. else
  232. << UnReadLastChar();
  233. BackupBuf();
  234. if ChangedPackages neq 0 then Package LispVar CurrentPackage!*;
  235. return MakeBufIntoID() >>;
  236. GotPackageMustGetID:
  237. ReadInBuf();
  238. if ChTokenType eq LETTER then goto InsideID
  239. else if ChTokenType eq IDESCAPECHAR then goto GotEscape
  240. else ScannerError("Illegal to follow package indicator with non ID");
  241. GotEscapeInRaisedID:
  242. BackupBuf();
  243. ReadInBuf();
  244. goto InsideRaisedID;
  245. InsideRaisedID:
  246. ReadInBuf();
  247. if ChTokenType < 10
  248. or ChTokenType eq PLUSSIGN
  249. or ChTokenType eq MINUSSIGN then goto InsideRaisedID
  250. else if ChTokenType eq 10 then
  251. << RaiseLastChar();
  252. goto InsideRaisedID >>
  253. else if ChTokenType eq IDESCAPECHAR then goto GotEscapeInRaisedID
  254. else if ChTokenType eq PACKAGEINDICATOR then
  255. << BackupBuf();
  256. ChangedPackages := 1;
  257. Package MakeBufIntoID();
  258. ResetBuf();
  259. goto GotPackageMustGetIDRaised >>
  260. else
  261. << UnReadLastChar();
  262. BackupBuf();
  263. if ChangedPackages neq 0 then Package LispVar CurrentPackage!*;
  264. return MakeBufIntoID() >>;
  265. GotPackageMustGetIDRaised:
  266. ReadInBuf();
  267. if ChTokenType eq LETTER then
  268. << RaiseLastChar();
  269. goto InsideRaisedID >>
  270. else if ChTokenType eq IDESCAPECHAR then goto GotEscapeInRaisedID
  271. else ScannerError("Illegal to follow package indicator with non ID");
  272. InsideString:
  273. ReadInBuf();
  274. if ChTokenType eq STRINGQUOTE then
  275. << BackupBuf();
  276. ReadInBuf();
  277. if ChTokenType eq STRINGQUOTE then goto InsideString
  278. else
  279. << UnReadLastChar();
  280. BackupBuf();
  281. return MakeBufIntoString() >> >>
  282. else if TokCh eq char EOL and not LispVar !*EOLInStringOK then
  283. ErrorPrintF("*** String continued over end-of-line")
  284. else if TokCh eq char EOF then
  285. ScannerError("EOF encountered inside a string");
  286. goto InsideString;
  287. InsideIDSurround:
  288. ReadInBuf();
  289. if ChTokenType eq IDSURROUND then
  290. << BackupBuf();
  291. return MakeBufIntoID() >>
  292. else if ChTokenType eq IDESCAPECHAR then
  293. << BackupBuf();
  294. ReadInBuf() >>
  295. else if TokCh eq char EOF then
  296. ScannerError("EOF encountered inside an ID");
  297. goto InsideIDSurround;
  298. GotSign:
  299. ResetBuf();
  300. ReadInBuf();
  301. if TokCh eq char !. then
  302. << PutStrByt(TokenBuffer, 0, char !0);
  303. CurrentChar := 2;
  304. goto InsideFloat >>
  305. else if ChTokenType eq LETTER % patch to be able to read 1+ and 1-
  306. or ChTokenType eq MINUSSIGN
  307. or ChTokenType eq PLUSSIGN then
  308. << ResetBuf();
  309. StrByt(TokenBuffer, 0) := if TokSign < 0 then char !- else char !+;
  310. StrByt(TokenBuffer, 1) := TokCh;
  311. CurrentChar := 2;
  312. if LispVar !*Raise then
  313. << RaiseLastChar();
  314. goto InsideRaisedID >>
  315. else goto InsideID >>
  316. else if ChTokenType eq IDESCAPECHAR then
  317. << ResetBuf();
  318. StrByt(TokenBuffer, 0) := if TokSign < 0 then char !- else char !+;
  319. CurrentChar := 1;
  320. if LispVar !*Raise then
  321. goto GotEscapeInRaisedID
  322. else goto GotEscape >>
  323. else if ChTokenType > 9 then
  324. << UnReadLastChar(); % Allow + or - to start a Diphthong
  325. return ScanPossibleDiphthong(Channel,
  326. MkID(if TokSign < 0 then char !-
  327. else char !+)) >>
  328. else goto InsideNumber;
  329. InsideNumber:
  330. ReadInBuf();
  331. if ChTokenType < 10 then goto InsideNumber;
  332. if TokCh eq char !# then
  333. << BackupBuf();
  334. TokRadix := MakeBufIntoSysNumber(10, 1);
  335. ResetBuf();
  336. if TokRadix < 2 or TokRadix > 36 then
  337. return ScannerError("Radix out of range");
  338. if TokRadix <= 10 then goto InsideIntegerRadixUnder10
  339. else goto InsideIntegerRadixOver10 >>
  340. else if TokCh eq char !. then goto InsideFloat
  341. else if TokCh eq char B or TokCh eq char !b then
  342. << BackupBuf();
  343. return MakeBufIntoLispInteger(8, TokSign) >>
  344. else if TokCh eq char E or TokCh eq char !e then
  345. << TokFloatFractionLength := 0;
  346. goto InsideFloatExponent >>
  347. else if ChTokenType eq LETTER % patch to be able to read 1+ and 1-
  348. or ChTokenType eq MINUSSIGN
  349. or ChTokenType eq PLUSSIGN then
  350. if LispVar !*Raise then
  351. << RaiseLastChar();
  352. goto InsideRaisedID >>
  353. else goto InsideID
  354. else if ChTokenType eq IDESCAPECHAR then
  355. if LispVar !*Raise then
  356. goto GotEscapeInRaisedID
  357. else goto GotEscape
  358. else
  359. << UnReadLastChar();
  360. BackupBuf();
  361. return MakeBufIntoLispInteger(10, TokSign) >>;
  362. InsideIntegerRadixUnder10:
  363. ReadInBuf();
  364. if ChTokenType < TokRadix then goto InsideIntegerRadixUnder10;
  365. if ChTokenType < 10 then return ScannerError("Digit out of range");
  366. NumReturn:
  367. UnReadLastChar();
  368. BackupBuf();
  369. return MakeBufIntoLispInteger(TokRadix, TokSign);
  370. InsideIntegerRadixOver10:
  371. ReadInBuf();
  372. if ChTokenType < 10 then goto InsideIntegerRadixOver10;
  373. if ChTokenType > 10 then goto NumReturn;
  374. if LowerCaseChar TokCh then
  375. << TokCh := RaiseChar TokCh;
  376. StrByt(TokenBuffer, CurrentChar - 1) := TokCh >>;
  377. if TokCh >= char A - 10 + TokRadix then goto NumReturn;
  378. goto InsideIntegerRadixOver10;
  379. InsideFloat: % got decimal point inside number
  380. BackupBuf();
  381. ReadInBuf();
  382. if TokCh eq char E or TokCh eq char !e then
  383. << TokFloatFractionLength := 0;
  384. goto InsideFloatExponent >>;
  385. if ChTokenType >= 10 then % nnn. is floating point number
  386. << UnReadLastChar();
  387. BackupBuf();
  388. return MakeBufIntoFloat 0 >>;
  389. TokFloatFractionLength := 1;
  390. InsideFloatFraction:
  391. ReadInBuf();
  392. if ChTokenType < 10 then
  393. << if TokFloatFractionLength < 9 then
  394. TokFloatFractionLength := TokFloatFractionLength + 1
  395. else BackupBuf(); % don't overflow mantissa
  396. goto InsideFloatFraction >>;
  397. if TokCh eq char E or TokCh eq char lower e then goto InsideFloatExponent;
  398. UnReadLastChar();
  399. BackupBuf();
  400. return MakeBufIntoFloat(-TokFloatFractionLength);
  401. InsideFloatExponent:
  402. BackupBuf();
  403. TokFloatExponentSign := 1;
  404. TokFloatExponent := 0;
  405. TokCh := ChannelReadChar TokChannel;
  406. ChTokenType := TokenTypeOfChar TokCh;
  407. if ChTokenType < 10 then
  408. << TokFloatExponent := ChTokenType;
  409. goto DigitsInsideExponent >>;
  410. if TokCh eq char '!- then TokFloatExponentSign := -1
  411. else if TokCh neq char '!+ then
  412. return ScannerError("Missing exponent in float");
  413. TokCh := ChannelReadChar TokChannel;
  414. ChTokenType := TokenTypeOfChar TokCh;
  415. if ChTokenType >= 10 then
  416. return ScannerError("Missing exponent in float");
  417. TokFloatExponent := ChTokenType;
  418. DigitsInsideExponent:
  419. TokCh := ChannelReadChar TokChannel;
  420. ChTokenType := TokenTypeOfChar TokCh;
  421. if ChTokenType < 10 then
  422. << TokFloatExponent := TokFloatExponent * 10 + ChTokenType;
  423. goto DigitsInsideExponent >>;
  424. ChannelUnReadChar(Channel, TokCh);
  425. return MakeBufIntoFloat(TokFloatExponentSign * TokFloatExponent
  426. - TokFloatFractionLength);
  427. InsideComment:
  428. if (TokCh := ChannelReadChar Channel) eq char EOL then
  429. << ResetBuf();
  430. goto StartScanning >>
  431. else if TokCh eq char EOF then return LispVar !$EOF!$
  432. else goto InsideComment;
  433. end;
  434. syslsp procedure RAtom(); %. Read token from current input
  435. ChannelReadToken LispVar IN!*;
  436. syslsp procedure DigitToNumber D;
  437. %
  438. % if D is not a digit then it is assumed to be an uppercase letter
  439. %
  440. if D >= char !0 and D <= char !9 then D - char !0 else D - (char A - 10);
  441. syslsp procedure MakeStringIntoLispInteger(S, Radix, Sign);
  442. Sys2Int MakeStringIntoSysInteger(S, Radix, Sign);
  443. syslsp procedure MakeStringIntoSysInteger(Strng, Radix, Sign);
  444. %
  445. % Unsafe string to integer conversion. Strng is assumed to contain
  446. % only digits and possibly uppercase letters for radices > 10. Since it
  447. % uses multiplication, arithmetic overflow may occur. Sign is +1 or -1
  448. %
  449. begin scalar Count, Tot, RadixExponent;
  450. if RadixExponent := SysPowerOf2P Radix then return
  451. MakeStringIntoBitString(Strng, Radix, RadixExponent, Sign);
  452. Strng := StrInf Strng;
  453. Count := StrLen Strng;
  454. Tot := 0;
  455. for I := 0 step 1 until Count do
  456. Tot := Tot * Radix + DigitToNumber StrByt(Strng, I);
  457. return if Sign < 0 then -Tot else Tot;
  458. end;
  459. syslsp procedure MakeStringIntoBitString(Strng, Radix, RadixExponent, Sign);
  460. begin scalar Count, Tot;
  461. Strng := StrInf Strng;
  462. Count := StrLen Strng;
  463. Tot := 0;
  464. for I := 0 step 1 until Count do
  465. << Tot := LSH(Tot, RadixExponent);
  466. Tot := LOR(Tot, DigitToNumber StrByt(Strng, I)) >>;
  467. if Sign < 0 then return -Tot;
  468. return Tot;
  469. end;
  470. syslsp procedure SysPowerOf2P Num;
  471. case Num of
  472. 1: 0;
  473. 2: 1;
  474. 4: 2;
  475. 8: 3;
  476. 16: 4;
  477. 32: 5;
  478. default: NIL
  479. end;
  480. syslsp procedure ScannerError Message;
  481. StdError BldMsg("***** Error in token scanner: %s", Message);
  482. syslsp procedure ScanPossibleDiphthong(Channel, StartChar);
  483. begin scalar Alst, Target, Ch;
  484. LispVar TokType!* := '3;
  485. if null (Alst := get(StartChar, CurrentDiphthongIndicator())) then
  486. return StartChar;
  487. if null (Target := Atsoc(Ch := MkID ChannelReadChar Channel, Alst)) then
  488. << ChannelUnReadChar(Channel, IDInf Ch);
  489. return StartChar >>;
  490. return cdr Target;
  491. end;
  492. syslsp procedure ReadLine();
  493. << MakeInputAvailable();
  494. ChannelReadLine LispVar IN!* >>;
  495. syslsp procedure ChannelReadLine Chn;
  496. begin scalar C;
  497. TokenBuffer[0] := -1;
  498. while (C := ChannelReadChar Chn) neq char EOL and C neq char EOF do
  499. << TokenBuffer[0] := TokenBuffer[0] + 1;
  500. StrByt(TokenBuffer, TokenBuffer[0]) := C >>;
  501. return if TokenBuffer[0] >= 0 then
  502. << StrByt(TokenBuffer, TokenBuffer[0] + 1) := char NULL;
  503. CopyString MkSTR TokenBuffer >>
  504. else '"";
  505. end;
  506. % Dummy definition of package conversion function
  507. syslsp procedure Package U;
  508. NIL;
  509. % Dummy definition of MakeInputAvailable, redefined by Emode
  510. syslsp procedure MakeInputAvailable();
  511. NIL;
  512. off SysLisp;
  513. END;