scanner.pas 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. This unit implements the scanner part and handling of the switches
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$ifdef tp}
  19. {$F+,N+,E+,R-}
  20. {$endif}
  21. unit scanner;
  22. {$ifdef FPC}
  23. {$goto on}
  24. {$endif FPC}
  25. interface
  26. uses
  27. {$ifdef Delphi}
  28. dmisc,
  29. {$endif Delphi}
  30. globtype,version,tokens,
  31. cobjects,globals,verbose,comphook,files;
  32. const
  33. {$ifdef TP}
  34. maxmacrolen=1024;
  35. preprocbufsize=1024;
  36. {$else}
  37. maxmacrolen=16*1024;
  38. preprocbufsize=32*1024;
  39. {$endif}
  40. Newline = #10;
  41. type
  42. tcommentstyle = (comment_none,comment_tp,comment_oldtp,comment_delphi,comment_c);
  43. pmacrobuffer = ^tmacrobuffer;
  44. tmacrobuffer = array[0..maxmacrolen-1] of char;
  45. preproctyp = (pp_ifdef,pp_ifndef,pp_if,pp_ifopt,pp_else);
  46. ppreprocstack = ^tpreprocstack;
  47. tpreprocstack = object
  48. typ : preproctyp;
  49. accept : boolean;
  50. next : ppreprocstack;
  51. name : stringid;
  52. line_nb : longint;
  53. constructor init(atyp:preproctyp;a:boolean;n:ppreprocstack);
  54. destructor done;
  55. end;
  56. pscannerfile = ^tscannerfile;
  57. tscannerfile = object
  58. inputfile : pinputfile; { current inputfile list }
  59. inputbuffer, { input buffer }
  60. inputpointer : pchar;
  61. inputstart : longint;
  62. line_no, { line }
  63. lastlinepos : longint;
  64. lasttokenpos : longint; { token }
  65. lasttoken,
  66. nexttoken : ttoken;
  67. comment_level,
  68. yylexcount : longint;
  69. lastasmgetchar : char;
  70. preprocstack : ppreprocstack;
  71. invalid : boolean; { flag if sourcefiles have been destroyed ! }
  72. constructor init(const fn:string);
  73. destructor done;
  74. { File buffer things }
  75. function openinputfile:boolean;
  76. procedure closeinputfile;
  77. function tempopeninputfile:boolean;
  78. procedure tempcloseinputfile;
  79. procedure saveinputfile;
  80. procedure restoreinputfile;
  81. procedure nextfile;
  82. procedure addfile(hp:pinputfile);
  83. procedure reload;
  84. procedure insertmacro(const macname:string;p:pchar;len:longint);
  85. { Scanner things }
  86. procedure gettokenpos;
  87. procedure inc_comment_level;
  88. procedure dec_comment_level;
  89. procedure end_of_file;
  90. procedure checkpreprocstack;
  91. procedure poppreprocstack;
  92. procedure addpreprocstack(atyp : preproctyp;a:boolean;const s:string;w:tmsgconst);
  93. procedure elsepreprocstack;
  94. procedure linebreak;
  95. procedure readchar;
  96. procedure readstring;
  97. procedure readnumber;
  98. function readid:string;
  99. function readval:longint;
  100. function readcomment:string;
  101. function readstate:char;
  102. procedure skipspace;
  103. procedure skipuntildirective;
  104. procedure skipcomment;
  105. procedure skipdelphicomment;
  106. procedure skipoldtpcomment;
  107. procedure readtoken;
  108. function readpreproc:ttoken;
  109. function asmgetchar:char;
  110. end;
  111. ppreprocfile=^tpreprocfile;
  112. tpreprocfile=object
  113. f : text;
  114. buf : pointer;
  115. spacefound,
  116. eolfound : boolean;
  117. constructor init(const fn:string);
  118. destructor done;
  119. procedure Add(const s:string);
  120. procedure AddSpace;
  121. end;
  122. var
  123. c : char;
  124. orgpattern,
  125. pattern : string;
  126. current_scanner : pscannerfile;
  127. aktcommentstyle : tcommentstyle; { needed to use read_comment from directives }
  128. preprocfile : ppreprocfile; { used with only preprocessing }
  129. implementation
  130. uses
  131. {$ifndef delphi}
  132. dos,
  133. {$endif delphi}
  134. systems,symtable,switches
  135. {$IFDEF NEWST}
  136. ,symbols
  137. {$ENDIF NEWST};
  138. {*****************************************************************************
  139. Helper routines
  140. *****************************************************************************}
  141. const
  142. { use any special name that is an invalid file name to avoid problems }
  143. preprocstring : array [preproctyp] of string[7]
  144. = ('$IFDEF','$IFNDEF','$IF','$IFOPT','$ELSE');
  145. function is_keyword(const s:string):boolean;
  146. var
  147. low,high,mid : longint;
  148. begin
  149. if not (length(s) in [2..tokenidlen]) then
  150. begin
  151. is_keyword:=false;
  152. exit;
  153. end;
  154. low:=ord(tokenidx^[length(s),s[1]].first);
  155. high:=ord(tokenidx^[length(s),s[1]].last);
  156. while low<high do
  157. begin
  158. mid:=(high+low+1) shr 1;
  159. if pattern<tokeninfo^[ttoken(mid)].str then
  160. high:=mid-1
  161. else
  162. low:=mid;
  163. end;
  164. is_keyword:=(pattern=tokeninfo^[ttoken(high)].str) and
  165. (tokeninfo^[ttoken(high)].keyword in aktmodeswitches);
  166. end;
  167. {*****************************************************************************
  168. Preprocessor writting
  169. *****************************************************************************}
  170. constructor tpreprocfile.init(const fn:string);
  171. begin
  172. { open outputfile }
  173. assign(f,fn);
  174. {$I-}
  175. rewrite(f);
  176. {$I+}
  177. if ioresult<>0 then
  178. Comment(V_Fatal,'can''t create file '+fn);
  179. getmem(buf,preprocbufsize);
  180. settextbuf(f,buf^,preprocbufsize);
  181. { reset }
  182. eolfound:=false;
  183. spacefound:=false;
  184. end;
  185. destructor tpreprocfile.done;
  186. begin
  187. close(f);
  188. freemem(buf,preprocbufsize);
  189. end;
  190. procedure tpreprocfile.add(const s:string);
  191. begin
  192. write(f,s);
  193. end;
  194. procedure tpreprocfile.addspace;
  195. begin
  196. if eolfound then
  197. begin
  198. writeln(f,'');
  199. eolfound:=false;
  200. spacefound:=false;
  201. end
  202. else
  203. if spacefound then
  204. begin
  205. write(f,' ');
  206. spacefound:=false;
  207. end;
  208. end;
  209. {*****************************************************************************
  210. TPreProcStack
  211. *****************************************************************************}
  212. constructor tpreprocstack.init(atyp : preproctyp;a:boolean;n:ppreprocstack);
  213. begin
  214. accept:=a;
  215. typ:=atyp;
  216. next:=n;
  217. end;
  218. destructor tpreprocstack.done;
  219. begin
  220. end;
  221. {****************************************************************************
  222. TSCANNERFILE
  223. ****************************************************************************}
  224. constructor tscannerfile.init(const fn:string);
  225. begin
  226. inputfile:=new(pinputfile,init(fn));
  227. if assigned(current_module) then
  228. current_module^.sourcefiles^.register_file(inputfile);
  229. { reset localinput }
  230. inputbuffer:=nil;
  231. inputpointer:=nil;
  232. inputstart:=0;
  233. { reset scanner }
  234. preprocstack:=nil;
  235. comment_level:=0;
  236. yylexcount:=0;
  237. block_type:=bt_general;
  238. line_no:=0;
  239. lastlinepos:=0;
  240. lasttokenpos:=0;
  241. lasttoken:=NOTOKEN;
  242. nexttoken:=NOTOKEN;
  243. lastasmgetchar:=#0;
  244. invalid:=false;
  245. { load block }
  246. if not openinputfile then
  247. Message1(scan_f_cannot_open_input,fn);
  248. reload;
  249. { process first read char }
  250. case c of
  251. #26 : reload;
  252. #10,
  253. #13 : linebreak;
  254. end;
  255. end;
  256. destructor tscannerfile.done;
  257. begin
  258. if not invalid then
  259. begin
  260. if status.errorcount=0 then
  261. checkpreprocstack;
  262. { close file, but only if we are the first compile }
  263. { probably not necessary anymore with invalid flag PM }
  264. if not current_module^.in_second_compile then
  265. begin
  266. if not inputfile^.closed then
  267. closeinputfile;
  268. end;
  269. end;
  270. end;
  271. function tscannerfile.openinputfile:boolean;
  272. begin
  273. openinputfile:=inputfile^.open;
  274. { load buffer }
  275. inputbuffer:=inputfile^.buf;
  276. inputpointer:=inputfile^.buf;
  277. inputstart:=inputfile^.bufstart;
  278. { line }
  279. line_no:=0;
  280. lastlinepos:=0;
  281. lasttokenpos:=0;
  282. end;
  283. procedure tscannerfile.closeinputfile;
  284. begin
  285. inputfile^.close;
  286. { reset buffer }
  287. inputbuffer:=nil;
  288. inputpointer:=nil;
  289. inputstart:=0;
  290. { reset line }
  291. line_no:=0;
  292. lastlinepos:=0;
  293. lasttokenpos:=0;
  294. end;
  295. function tscannerfile.tempopeninputfile:boolean;
  296. begin
  297. tempopeninputfile:=inputfile^.tempopen;
  298. { reload buffer }
  299. inputbuffer:=inputfile^.buf;
  300. inputpointer:=inputfile^.buf;
  301. inputstart:=inputfile^.bufstart;
  302. end;
  303. procedure tscannerfile.tempcloseinputfile;
  304. begin
  305. inputfile^.setpos(inputstart+(inputpointer-inputbuffer));
  306. inputfile^.tempclose;
  307. { reset buffer }
  308. inputbuffer:=nil;
  309. inputpointer:=nil;
  310. inputstart:=0;
  311. end;
  312. procedure tscannerfile.saveinputfile;
  313. begin
  314. inputfile^.saveinputpointer:=inputpointer;
  315. inputfile^.savelastlinepos:=lastlinepos;
  316. inputfile^.saveline_no:=line_no;
  317. end;
  318. procedure tscannerfile.restoreinputfile;
  319. begin
  320. inputpointer:=inputfile^.saveinputpointer;
  321. lastlinepos:=inputfile^.savelastlinepos;
  322. line_no:=inputfile^.saveline_no;
  323. if not inputfile^.is_macro then
  324. parser_current_file:=inputfile^.name^;
  325. end;
  326. procedure tscannerfile.nextfile;
  327. var
  328. to_dispose : pinputfile;
  329. begin
  330. if assigned(inputfile^.next) then
  331. begin
  332. if inputfile^.is_macro then
  333. to_dispose:=inputfile
  334. else
  335. to_dispose:=nil;
  336. { we can allways close the file, no ? }
  337. inputfile^.close;
  338. inputfile:=inputfile^.next;
  339. if assigned(to_dispose) then
  340. dispose(to_dispose,done);
  341. restoreinputfile;
  342. end;
  343. end;
  344. procedure tscannerfile.addfile(hp:pinputfile);
  345. begin
  346. saveinputfile;
  347. { add to list }
  348. hp^.next:=inputfile;
  349. inputfile:=hp;
  350. { load new inputfile }
  351. restoreinputfile;
  352. end;
  353. procedure tscannerfile.reload;
  354. begin
  355. with inputfile^ do
  356. begin
  357. { when nothing more to read then leave immediatly, so we
  358. don't change the aktfilepos and leave it point to the last
  359. char }
  360. if (c=#26) and (not assigned(next)) then
  361. exit;
  362. repeat
  363. { still more to read?, then change the #0 to a space so its seen
  364. as a seperator, this can't be used for macro's which can change
  365. the place of the #0 in the buffer with tempopen }
  366. if (c=#0) and (bufsize>0) and
  367. not(inputfile^.is_macro) and
  368. (inputpointer-inputbuffer<bufsize) then
  369. begin
  370. c:=' ';
  371. inc(longint(inputpointer));
  372. exit;
  373. end;
  374. { can we read more from this file ? }
  375. if (c<>#26) and (not endoffile) then
  376. begin
  377. readbuf;
  378. inputpointer:=buf;
  379. inputbuffer:=buf;
  380. inputstart:=bufstart;
  381. { first line? }
  382. if line_no=0 then
  383. begin
  384. line_no:=1;
  385. if cs_asm_source in aktglobalswitches then
  386. inputfile^.setline(line_no,bufstart);
  387. end;
  388. end
  389. else
  390. begin
  391. { load eof position in tokenpos/aktfilepos }
  392. gettokenpos;
  393. { close file }
  394. closeinputfile;
  395. { no next module, than EOF }
  396. if not assigned(inputfile^.next) then
  397. begin
  398. c:=#26;
  399. exit;
  400. end;
  401. { load next file and reopen it }
  402. nextfile;
  403. tempopeninputfile;
  404. { status }
  405. Message1(scan_t_back_in,inputfile^.name^);
  406. end;
  407. { load next char }
  408. c:=inputpointer^;
  409. inc(longint(inputpointer));
  410. until c<>#0; { if also end, then reload again }
  411. end;
  412. end;
  413. procedure tscannerfile.insertmacro(const macname:string;p:pchar;len:longint);
  414. var
  415. hp : pinputfile;
  416. begin
  417. { save old postion and decrease linebreak }
  418. if c=newline then
  419. dec(line_no);
  420. dec(longint(inputpointer));
  421. tempcloseinputfile;
  422. { create macro 'file' }
  423. { use special name to dispose after !! }
  424. hp:=new(pinputfile,init('_Macro_.'+macname));
  425. addfile(hp);
  426. with inputfile^ do
  427. begin
  428. setmacro(p,len);
  429. { local buffer }
  430. inputbuffer:=buf;
  431. inputpointer:=buf;
  432. inputstart:=bufstart;
  433. end;
  434. { reset line }
  435. line_no:=0;
  436. lastlinepos:=0;
  437. lasttokenpos:=0;
  438. { load new c }
  439. c:=inputpointer^;
  440. inc(longint(inputpointer));
  441. end;
  442. procedure tscannerfile.gettokenpos;
  443. { load the values of tokenpos and lasttokenpos }
  444. begin
  445. lasttokenpos:=inputstart+(inputpointer-inputbuffer);
  446. tokenpos.line:=line_no;
  447. tokenpos.column:=lasttokenpos-lastlinepos;
  448. tokenpos.fileindex:=inputfile^.ref_index;
  449. aktfilepos:=tokenpos;
  450. end;
  451. procedure tscannerfile.inc_comment_level;
  452. var
  453. oldaktfilepos : tfileposinfo;
  454. begin
  455. if (m_nested_comment in aktmodeswitches) then
  456. inc(comment_level)
  457. else
  458. comment_level:=1;
  459. if (comment_level>1) then
  460. begin
  461. oldaktfilepos:=aktfilepos;
  462. gettokenpos; { update for warning }
  463. Message1(scan_w_comment_level,tostr(comment_level));
  464. aktfilepos:=oldaktfilepos;
  465. end;
  466. end;
  467. procedure tscannerfile.dec_comment_level;
  468. begin
  469. if (m_nested_comment in aktmodeswitches) then
  470. dec(comment_level)
  471. else
  472. comment_level:=0;
  473. end;
  474. procedure tscannerfile.linebreak;
  475. var
  476. cur : char;
  477. oldtokenpos,
  478. oldaktfilepos : tfileposinfo;
  479. begin
  480. with inputfile^ do
  481. begin
  482. if (byte(inputpointer^)=0) and not(endoffile) then
  483. begin
  484. cur:=c;
  485. reload;
  486. if byte(cur)+byte(c)<>23 then
  487. dec(longint(inputpointer));
  488. end
  489. else
  490. begin
  491. { Fix linebreak to be only newline (=#10) for all types of linebreaks }
  492. if (byte(inputpointer^)+byte(c)=23) then
  493. inc(longint(inputpointer));
  494. end;
  495. c:=newline;
  496. { increase line counters }
  497. lastlinepos:=bufstart+(inputpointer-inputbuffer);
  498. inc(line_no);
  499. { update linebuffer }
  500. if cs_asm_source in aktglobalswitches then
  501. inputfile^.setline(line_no,lastlinepos);
  502. { update for status and call the show status routine,
  503. but don't touch aktfilepos ! }
  504. oldaktfilepos:=aktfilepos;
  505. oldtokenpos:=tokenpos;
  506. gettokenpos; { update for v_status }
  507. inc(status.compiledlines);
  508. ShowStatus;
  509. aktfilepos:=oldaktfilepos;
  510. tokenpos:=oldtokenpos;
  511. end;
  512. end;
  513. procedure tscannerfile.end_of_file;
  514. begin
  515. checkpreprocstack;
  516. Message(scan_f_end_of_file);
  517. end;
  518. procedure tscannerfile.checkpreprocstack;
  519. begin
  520. { check for missing ifdefs }
  521. while assigned(preprocstack) do
  522. begin
  523. Message3(scan_e_endif_expected,preprocstring[preprocstack^.typ],preprocstack^.name,tostr(preprocstack^.line_nb));
  524. poppreprocstack;
  525. end;
  526. end;
  527. procedure tscannerfile.poppreprocstack;
  528. var
  529. hp : ppreprocstack;
  530. begin
  531. if assigned(preprocstack) then
  532. begin
  533. Message1(scan_c_endif_found,preprocstack^.name);
  534. hp:=preprocstack^.next;
  535. dispose(preprocstack,done);
  536. preprocstack:=hp;
  537. end
  538. else
  539. Message(scan_e_endif_without_if);
  540. end;
  541. procedure tscannerfile.addpreprocstack(atyp : preproctyp;a:boolean;const s:string;w:tmsgconst);
  542. begin
  543. preprocstack:=new(ppreprocstack,init(atyp,((preprocstack=nil) or preprocstack^.accept) and a,preprocstack));
  544. preprocstack^.name:=s;
  545. preprocstack^.line_nb:=line_no;
  546. if preprocstack^.accept then
  547. Message2(w,preprocstack^.name,'accepted')
  548. else
  549. Message2(w,preprocstack^.name,'rejected');
  550. end;
  551. procedure tscannerfile.elsepreprocstack;
  552. begin
  553. if assigned(preprocstack) then
  554. begin
  555. preprocstack^.typ:=pp_else;
  556. preprocstack^.line_nb:=line_no;
  557. if not(assigned(preprocstack^.next)) or (preprocstack^.next^.accept) then
  558. preprocstack^.accept:=not preprocstack^.accept;
  559. if preprocstack^.accept then
  560. Message2(scan_c_else_found,preprocstack^.name,'accepted')
  561. else
  562. Message2(scan_c_else_found,preprocstack^.name,'rejected');
  563. end
  564. else
  565. Message(scan_e_endif_without_if);
  566. end;
  567. procedure tscannerfile.readchar;
  568. begin
  569. c:=inputpointer^;
  570. if c=#0 then
  571. reload
  572. else
  573. inc(longint(inputpointer));
  574. case c of
  575. #26 : reload;
  576. #10,
  577. #13 : linebreak;
  578. end;
  579. end;
  580. procedure tscannerfile.readstring;
  581. var
  582. i : longint;
  583. begin
  584. i:=0;
  585. repeat
  586. case c of
  587. '_',
  588. '0'..'9',
  589. 'A'..'Z' : begin
  590. if i<255 then
  591. begin
  592. inc(i);
  593. orgpattern[i]:=c;
  594. pattern[i]:=c;
  595. end;
  596. c:=inputpointer^;
  597. inc(longint(inputpointer));
  598. end;
  599. 'a'..'z' : begin
  600. if i<255 then
  601. begin
  602. inc(i);
  603. orgpattern[i]:=c;
  604. pattern[i]:=chr(ord(c)-32)
  605. end;
  606. c:=inputpointer^;
  607. inc(longint(inputpointer));
  608. end;
  609. #0 : reload;
  610. #26 : begin
  611. reload;
  612. if c=#26 then
  613. break;
  614. end;
  615. #13,#10 : begin
  616. linebreak;
  617. break;
  618. end;
  619. else
  620. break;
  621. end;
  622. until false;
  623. {$ifndef TP}
  624. {$ifopt H+}
  625. setlength(orgpattern,i);
  626. setlength(pattern,i);
  627. {$else}
  628. orgpattern[0]:=chr(i);
  629. pattern[0]:=chr(i);
  630. {$endif}
  631. {$else}
  632. orgpattern[0]:=chr(i);
  633. pattern[0]:=chr(i);
  634. {$endif}
  635. end;
  636. procedure tscannerfile.readnumber;
  637. var
  638. base,
  639. i : longint;
  640. begin
  641. case c of
  642. '%' : begin
  643. readchar;
  644. base:=2;
  645. pattern[1]:='%';
  646. i:=1;
  647. end;
  648. '$' : begin
  649. readchar;
  650. base:=16;
  651. pattern[1]:='$';
  652. i:=1;
  653. end;
  654. else
  655. begin
  656. base:=10;
  657. i:=0;
  658. end;
  659. end;
  660. while ((base>=10) and (c in ['0'..'9'])) or
  661. ((base=16) and (c in ['A'..'F','a'..'f'])) or
  662. ((base=2) and (c in ['0'..'1'])) do
  663. begin
  664. if i<255 then
  665. begin
  666. inc(i);
  667. pattern[i]:=c;
  668. end;
  669. { get next char }
  670. c:=inputpointer^;
  671. if c=#0 then
  672. reload
  673. else
  674. inc(longint(inputpointer));
  675. end;
  676. { was the next char a linebreak ? }
  677. case c of
  678. #26 : reload;
  679. #10,
  680. #13 : linebreak;
  681. end;
  682. {$ifndef TP}
  683. {$ifopt H+}
  684. setlength(pattern,i);
  685. {$else}
  686. pattern[0]:=chr(i);
  687. {$endif}
  688. {$else}
  689. pattern[0]:=chr(i);
  690. {$endif}
  691. end;
  692. function tscannerfile.readid:string;
  693. begin
  694. readstring;
  695. readid:=pattern;
  696. end;
  697. function tscannerfile.readval:longint;
  698. var
  699. l : longint;
  700. w : integer;
  701. begin
  702. readnumber;
  703. valint(pattern,l,w);
  704. readval:=l;
  705. end;
  706. function tscannerfile.readcomment:string;
  707. var
  708. i : longint;
  709. begin
  710. i:=0;
  711. repeat
  712. case c of
  713. '{' :
  714. if aktcommentstyle=comment_tp then
  715. inc_comment_level;
  716. '}' :
  717. if aktcommentstyle=comment_tp then
  718. begin
  719. readchar;
  720. dec_comment_level;
  721. if comment_level=0 then
  722. break
  723. else
  724. continue;
  725. end;
  726. '*' :
  727. if aktcommentstyle=comment_oldtp then
  728. begin
  729. readchar;
  730. if c=')' then
  731. begin
  732. readchar;
  733. dec_comment_level;
  734. break;
  735. end;
  736. end;
  737. #26 :
  738. end_of_file;
  739. else
  740. begin
  741. if (i<255) then
  742. begin
  743. inc(i);
  744. readcomment[i]:=c;
  745. end;
  746. end;
  747. end;
  748. c:=inputpointer^;
  749. if c=#0 then
  750. reload
  751. else
  752. inc(longint(inputpointer));
  753. if c in [#10,#13] then
  754. linebreak;
  755. until false;
  756. {$ifndef TP}
  757. {$ifopt H+}
  758. setlength(readcomment,i);
  759. {$else}
  760. readcomment[0]:=chr(i);
  761. {$endif}
  762. {$else}
  763. readcomment[0]:=chr(i);
  764. {$endif}
  765. end;
  766. function tscannerfile.readstate:char;
  767. var
  768. state : char;
  769. begin
  770. state:=' ';
  771. if c=' ' then
  772. begin
  773. current_scanner^.skipspace;
  774. current_scanner^.readid;
  775. if pattern='ON' then
  776. state:='+'
  777. else
  778. if pattern='OFF' then
  779. state:='-';
  780. end
  781. else
  782. state:=c;
  783. if not (state in ['+','-']) then
  784. Message(scan_e_wrong_switch_toggle);
  785. readstate:=state;
  786. end;
  787. procedure tscannerfile.skipspace;
  788. begin
  789. while c in [' ',#9..#13] do
  790. begin
  791. c:=inputpointer^;
  792. if c=#0 then
  793. reload
  794. else
  795. inc(longint(inputpointer));
  796. case c of
  797. #26 :
  798. reload;
  799. #10,
  800. #13 :
  801. linebreak;
  802. end;
  803. end;
  804. end;
  805. procedure tscannerfile.skipuntildirective;
  806. var
  807. found : longint;
  808. next_char_loaded : boolean;
  809. oldcommentstyle : tcommentstyle;
  810. begin
  811. found:=0;
  812. next_char_loaded:=false;
  813. oldcommentstyle:=aktcommentstyle;
  814. repeat
  815. case c of
  816. #26 :
  817. end_of_file;
  818. '{' :
  819. begin
  820. if not(m_nested_comment in aktmodeswitches) or
  821. (comment_level=0) then
  822. begin
  823. found:=1;
  824. aktcommentstyle:=comment_tp;
  825. end;
  826. inc_comment_level;
  827. end;
  828. '}' :
  829. begin
  830. dec_comment_level;
  831. found:=0;
  832. end;
  833. '$' :
  834. begin
  835. if found=1 then
  836. found:=2;
  837. end;
  838. '''' :
  839. if (m_tp in aktmodeswitches) or
  840. (m_delphi in aktmodeswitches) then
  841. begin
  842. repeat
  843. readchar;
  844. case c of
  845. #26 :
  846. end_of_file;
  847. newline :
  848. break;
  849. '''' :
  850. begin
  851. readchar;
  852. if c<>'''' then
  853. break;
  854. end;
  855. end;
  856. until false;
  857. end;
  858. '(' :
  859. begin
  860. readchar;
  861. if c='*' then
  862. begin
  863. readchar;
  864. if c='$' then
  865. begin
  866. found:=2;
  867. inc_comment_level;
  868. aktcommentstyle:=comment_oldtp;
  869. end
  870. else
  871. begin
  872. skipoldtpcomment;
  873. aktcommentstyle:=oldcommentstyle;
  874. end;
  875. end
  876. else
  877. next_char_loaded:=true;
  878. end;
  879. else
  880. found:=0;
  881. end;
  882. if next_char_loaded then
  883. next_char_loaded:=false
  884. else
  885. begin
  886. c:=inputpointer^;
  887. if c=#0 then
  888. reload
  889. else
  890. inc(longint(inputpointer));
  891. case c of
  892. #26 : reload;
  893. #10,
  894. #13 : linebreak;
  895. end;
  896. end;
  897. until (found=2);
  898. end;
  899. {****************************************************************************
  900. Include directive scanning/parsing
  901. ****************************************************************************}
  902. {$i scandir.inc}
  903. {****************************************************************************
  904. Comment Handling
  905. ****************************************************************************}
  906. procedure tscannerfile.skipcomment;
  907. begin
  908. aktcommentstyle:=comment_tp;
  909. readchar;
  910. inc_comment_level;
  911. { handle compiler switches }
  912. if (c='$') then
  913. handledirectives;
  914. { handle_switches can dec comment_level, }
  915. while (comment_level>0) do
  916. begin
  917. case c of
  918. '{' : inc_comment_level;
  919. '}' : dec_comment_level;
  920. #26 : end_of_file;
  921. end;
  922. c:=inputpointer^;
  923. if c=#0 then
  924. reload
  925. else
  926. inc(longint(inputpointer));
  927. case c of
  928. #26 : reload;
  929. #10,
  930. #13 : linebreak;
  931. end;
  932. end;
  933. aktcommentstyle:=comment_none;
  934. end;
  935. procedure tscannerfile.skipdelphicomment;
  936. begin
  937. aktcommentstyle:=comment_delphi;
  938. inc_comment_level;
  939. readchar;
  940. { this is currently not supported }
  941. if c='$' then
  942. Message(scan_e_wrong_styled_switch);
  943. { skip comment }
  944. while c<>newline do
  945. begin
  946. if c=#26 then
  947. end_of_file;
  948. readchar;
  949. end;
  950. dec_comment_level;
  951. aktcommentstyle:=comment_none;
  952. end;
  953. procedure tscannerfile.skipoldtpcomment;
  954. var
  955. found : longint;
  956. begin
  957. aktcommentstyle:=comment_oldtp;
  958. inc_comment_level;
  959. readchar;
  960. { this is currently not supported }
  961. if (c='$') then
  962. handledirectives;
  963. { skip comment }
  964. while (comment_level>0) do
  965. begin
  966. found:=0;
  967. repeat
  968. case c of
  969. #26 :
  970. end_of_file;
  971. '*' :
  972. begin
  973. if found=3 then
  974. found:=4
  975. else
  976. found:=1;
  977. end;
  978. ')' :
  979. begin
  980. if found in [1,4] then
  981. begin
  982. dec_comment_level;
  983. if comment_level=0 then
  984. found:=2
  985. else
  986. found:=0;
  987. end;
  988. end;
  989. '(' :
  990. begin
  991. if found=4 then
  992. inc_comment_level;
  993. found:=3;
  994. end;
  995. else
  996. begin
  997. if found=4 then
  998. inc_comment_level;
  999. found:=0;
  1000. end;
  1001. end;
  1002. c:=inputpointer^;
  1003. if c=#0 then
  1004. reload
  1005. else
  1006. inc(longint(inputpointer));
  1007. case c of
  1008. #26 : reload;
  1009. #10,
  1010. #13 : linebreak;
  1011. end;
  1012. until (found=2);
  1013. end;
  1014. aktcommentstyle:=comment_none;
  1015. end;
  1016. {****************************************************************************
  1017. Token Scanner
  1018. ****************************************************************************}
  1019. procedure tscannerfile.readtoken;
  1020. var
  1021. code : integer;
  1022. low,high,mid : longint;
  1023. m : longint;
  1024. mac : pmacrosym;
  1025. asciinr : string[6];
  1026. label
  1027. exit_label;
  1028. begin
  1029. { was there already a token read, then return that token }
  1030. if nexttoken<>NOTOKEN then
  1031. begin
  1032. token:=nexttoken;
  1033. nexttoken:=NOTOKEN;
  1034. goto exit_label;
  1035. end;
  1036. { Skip all spaces and comments }
  1037. repeat
  1038. case c of
  1039. '{' :
  1040. skipcomment;
  1041. ' ',#9..#13 :
  1042. begin
  1043. if parapreprocess then
  1044. begin
  1045. if c=#10 then
  1046. preprocfile^.eolfound:=true
  1047. else
  1048. preprocfile^.spacefound:=true;
  1049. end;
  1050. skipspace;
  1051. end
  1052. else
  1053. break;
  1054. end;
  1055. until false;
  1056. { Save current token position, for EOF its already loaded }
  1057. if c<>#26 then
  1058. gettokenpos;
  1059. { Check first for a identifier/keyword, this is 20+% faster (PFV) }
  1060. if c in ['A'..'Z','a'..'z','_'] then
  1061. begin
  1062. readstring;
  1063. token:=_ID;
  1064. idtoken:=_ID;
  1065. { keyword or any other known token,
  1066. pattern is always uppercased }
  1067. if (pattern[1]<>'_') and (length(pattern) in [2..tokenidlen]) then
  1068. begin
  1069. low:=ord(tokenidx^[length(pattern),pattern[1]].first);
  1070. high:=ord(tokenidx^[length(pattern),pattern[1]].last);
  1071. while low<high do
  1072. begin
  1073. mid:=(high+low+1) shr 1;
  1074. if pattern<tokeninfo^[ttoken(mid)].str then
  1075. high:=mid-1
  1076. else
  1077. low:=mid;
  1078. end;
  1079. if pattern=tokeninfo^[ttoken(high)].str then
  1080. begin
  1081. if tokeninfo^[ttoken(high)].keyword in aktmodeswitches then
  1082. if tokeninfo^[ttoken(high)].op=NOTOKEN then
  1083. token:=ttoken(high)
  1084. else
  1085. token:=tokeninfo^[ttoken(high)].op;
  1086. idtoken:=ttoken(high);
  1087. end;
  1088. end;
  1089. { Only process identifiers and not keywords }
  1090. if token=_ID then
  1091. begin
  1092. { this takes some time ... }
  1093. if (cs_support_macro in aktmoduleswitches) then
  1094. begin
  1095. mac:=pmacrosym(macros^.search(pattern));
  1096. if assigned(mac) and (assigned(mac^.buftext)) then
  1097. begin
  1098. insertmacro(pattern,mac^.buftext,mac^.buflen);
  1099. { handle empty macros }
  1100. if c=#0 then
  1101. begin
  1102. reload;
  1103. case c of
  1104. #26 : reload;
  1105. #10,
  1106. #13 : linebreak;
  1107. end;
  1108. end;
  1109. { play it again ... }
  1110. inc(yylexcount);
  1111. if yylexcount>16 then
  1112. Message(scan_w_macro_deep_ten);
  1113. readtoken;
  1114. { that's all folks }
  1115. dec(yylexcount);
  1116. exit;
  1117. end;
  1118. end;
  1119. end;
  1120. { return token }
  1121. goto exit_label;
  1122. end
  1123. else
  1124. begin
  1125. idtoken:=_NOID;
  1126. case c of
  1127. '$' :
  1128. begin
  1129. readnumber;
  1130. token:=_INTCONST;
  1131. goto exit_label;
  1132. end;
  1133. '%' :
  1134. begin
  1135. readnumber;
  1136. token:=_INTCONST;
  1137. goto exit_label;
  1138. end;
  1139. '0'..'9' :
  1140. begin
  1141. readnumber;
  1142. if (c in ['.','e','E']) then
  1143. begin
  1144. { first check for a . }
  1145. if c='.' then
  1146. begin
  1147. readchar;
  1148. { is it a .. from a range? }
  1149. case c of
  1150. '.' :
  1151. begin
  1152. readchar;
  1153. token:=_INTCONST;
  1154. nexttoken:=_POINTPOINT;
  1155. goto exit_label;
  1156. end;
  1157. ')' :
  1158. begin
  1159. readchar;
  1160. token:=_INTCONST;
  1161. nexttoken:=_RECKKLAMMER;
  1162. goto exit_label;
  1163. end;
  1164. end;
  1165. { insert the number after the . }
  1166. pattern:=pattern+'.';
  1167. while c in ['0'..'9'] do
  1168. begin
  1169. pattern:=pattern+c;
  1170. readchar;
  1171. end;
  1172. end;
  1173. { E can also follow after a point is scanned }
  1174. if c in ['e','E'] then
  1175. begin
  1176. pattern:=pattern+'E';
  1177. readchar;
  1178. if c in ['-','+'] then
  1179. begin
  1180. pattern:=pattern+c;
  1181. readchar;
  1182. end;
  1183. if not(c in ['0'..'9']) then
  1184. Message(scan_f_illegal_char);
  1185. while c in ['0'..'9'] do
  1186. begin
  1187. pattern:=pattern+c;
  1188. readchar;
  1189. end;
  1190. end;
  1191. token:=_REALNUMBER;
  1192. goto exit_label;
  1193. end;
  1194. token:=_INTCONST;
  1195. goto exit_label;
  1196. end;
  1197. ';' :
  1198. begin
  1199. readchar;
  1200. token:=_SEMICOLON;
  1201. goto exit_label;
  1202. end;
  1203. '[' :
  1204. begin
  1205. readchar;
  1206. token:=_LECKKLAMMER;
  1207. goto exit_label;
  1208. end;
  1209. ']' :
  1210. begin
  1211. readchar;
  1212. token:=_RECKKLAMMER;
  1213. goto exit_label;
  1214. end;
  1215. '(' :
  1216. begin
  1217. readchar;
  1218. case c of
  1219. '*' :
  1220. begin
  1221. skipoldtpcomment;
  1222. readtoken;
  1223. exit;
  1224. end;
  1225. '.' :
  1226. begin
  1227. readchar;
  1228. token:=_LECKKLAMMER;
  1229. goto exit_label;
  1230. end;
  1231. end;
  1232. token:=_LKLAMMER;
  1233. goto exit_label;
  1234. end;
  1235. ')' :
  1236. begin
  1237. readchar;
  1238. token:=_RKLAMMER;
  1239. goto exit_label;
  1240. end;
  1241. '+' :
  1242. begin
  1243. readchar;
  1244. if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
  1245. begin
  1246. readchar;
  1247. token:=_PLUSASN;
  1248. goto exit_label;
  1249. end;
  1250. token:=_PLUS;
  1251. goto exit_label;
  1252. end;
  1253. '-' :
  1254. begin
  1255. readchar;
  1256. if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
  1257. begin
  1258. readchar;
  1259. token:=_MINUSASN;
  1260. goto exit_label;
  1261. end;
  1262. token:=_MINUS;
  1263. goto exit_label;
  1264. end;
  1265. ':' :
  1266. begin
  1267. readchar;
  1268. if c='=' then
  1269. begin
  1270. readchar;
  1271. token:=_ASSIGNMENT;
  1272. goto exit_label;
  1273. end;
  1274. token:=_COLON;
  1275. goto exit_label;
  1276. end;
  1277. '*' :
  1278. begin
  1279. readchar;
  1280. if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
  1281. begin
  1282. readchar;
  1283. token:=_STARASN;
  1284. end
  1285. else
  1286. if c='*' then
  1287. begin
  1288. readchar;
  1289. token:=_STARSTAR;
  1290. end
  1291. else
  1292. token:=_STAR;
  1293. goto exit_label;
  1294. end;
  1295. '/' :
  1296. begin
  1297. readchar;
  1298. case c of
  1299. '=' :
  1300. begin
  1301. if (cs_support_c_operators in aktmoduleswitches) then
  1302. begin
  1303. readchar;
  1304. token:=_SLASHASN;
  1305. goto exit_label;
  1306. end;
  1307. end;
  1308. '/' :
  1309. begin
  1310. skipdelphicomment;
  1311. readtoken;
  1312. exit;
  1313. end;
  1314. end;
  1315. token:=_SLASH;
  1316. goto exit_label;
  1317. end;
  1318. '=' :
  1319. begin
  1320. readchar;
  1321. token:=_EQUAL;
  1322. goto exit_label;
  1323. end;
  1324. '.' :
  1325. begin
  1326. readchar;
  1327. case c of
  1328. '.' :
  1329. begin
  1330. readchar;
  1331. token:=_POINTPOINT;
  1332. goto exit_label;
  1333. end;
  1334. ')' :
  1335. begin
  1336. readchar;
  1337. token:=_RECKKLAMMER;
  1338. goto exit_label;
  1339. end;
  1340. end;
  1341. token:=_POINT;
  1342. goto exit_label;
  1343. end;
  1344. '@' :
  1345. begin
  1346. readchar;
  1347. if c='@' then
  1348. begin
  1349. readchar;
  1350. token:=_DOUBLEADDR;
  1351. end
  1352. else
  1353. token:=_KLAMMERAFFE;
  1354. goto exit_label;
  1355. end;
  1356. ',' :
  1357. begin
  1358. readchar;
  1359. token:=_COMMA;
  1360. goto exit_label;
  1361. end;
  1362. '''','#','^' :
  1363. begin
  1364. if c='^' then
  1365. begin
  1366. readchar;
  1367. c:=upcase(c);
  1368. if (block_type=bt_type) or
  1369. (lasttoken=_ID) or
  1370. (lasttoken=_RKLAMMER) or (lasttoken=_RECKKLAMMER) or (lasttoken=_CARET) then
  1371. begin
  1372. token:=_CARET;
  1373. goto exit_label;
  1374. end
  1375. else
  1376. begin
  1377. if c<#64 then
  1378. pattern:=chr(ord(c)+64)
  1379. else
  1380. pattern:=chr(ord(c)-64);
  1381. readchar;
  1382. end;
  1383. end
  1384. else
  1385. pattern:='';
  1386. repeat
  1387. case c of
  1388. '#' :
  1389. begin
  1390. readchar; { read # }
  1391. if c='$' then
  1392. begin
  1393. readchar; { read leading $ }
  1394. asciinr:='$';
  1395. while (upcase(c) in ['A'..'F','0'..'9']) and (length(asciinr)<6) do
  1396. begin
  1397. asciinr:=asciinr+c;
  1398. readchar;
  1399. end;
  1400. end
  1401. else
  1402. begin
  1403. asciinr:='';
  1404. while (c in ['0'..'9']) and (length(asciinr)<6) do
  1405. begin
  1406. asciinr:=asciinr+c;
  1407. readchar;
  1408. end;
  1409. end;
  1410. valint(asciinr,m,code);
  1411. if (asciinr='') or (code<>0) or
  1412. (m<0) or (m>255) then
  1413. Message(scan_e_illegal_char_const);
  1414. pattern:=pattern+chr(m);
  1415. end;
  1416. '''' :
  1417. begin
  1418. repeat
  1419. readchar;
  1420. case c of
  1421. #26 :
  1422. end_of_file;
  1423. newline :
  1424. Message(scan_f_string_exceeds_line);
  1425. '''' :
  1426. begin
  1427. readchar;
  1428. if c<>'''' then
  1429. break;
  1430. end;
  1431. end;
  1432. pattern:=pattern+c;
  1433. until false;
  1434. end;
  1435. '^' :
  1436. begin
  1437. readchar;
  1438. c:=upcase(c);
  1439. if c<#64 then
  1440. c:=chr(ord(c)+64)
  1441. else
  1442. c:=chr(ord(c)-64);
  1443. pattern:=pattern+c;
  1444. readchar;
  1445. end;
  1446. else
  1447. break;
  1448. end;
  1449. until false;
  1450. { strings with length 1 become const chars }
  1451. if length(pattern)=1 then
  1452. token:=_CCHAR
  1453. else
  1454. token:=_CSTRING;
  1455. goto exit_label;
  1456. end;
  1457. '>' :
  1458. begin
  1459. readchar;
  1460. case c of
  1461. '=' :
  1462. begin
  1463. readchar;
  1464. token:=_GTE;
  1465. goto exit_label;
  1466. end;
  1467. '>' :
  1468. begin
  1469. readchar;
  1470. token:=_OP_SHR;
  1471. goto exit_label;
  1472. end;
  1473. '<' :
  1474. begin { >< is for a symetric diff for sets }
  1475. readchar;
  1476. token:=_SYMDIF;
  1477. goto exit_label;
  1478. end;
  1479. end;
  1480. token:=_GT;
  1481. goto exit_label;
  1482. end;
  1483. '<' :
  1484. begin
  1485. readchar;
  1486. case c of
  1487. '>' :
  1488. begin
  1489. readchar;
  1490. token:=_UNEQUAL;
  1491. goto exit_label;
  1492. end;
  1493. '=' :
  1494. begin
  1495. readchar;
  1496. token:=_LTE;
  1497. goto exit_label;
  1498. end;
  1499. '<' :
  1500. begin
  1501. readchar;
  1502. token:=_OP_SHL;
  1503. goto exit_label;
  1504. end;
  1505. end;
  1506. token:=_LT;
  1507. goto exit_label;
  1508. end;
  1509. #26 :
  1510. begin
  1511. token:=_EOF;
  1512. checkpreprocstack;
  1513. goto exit_label;
  1514. end;
  1515. else
  1516. begin
  1517. Message(scan_f_illegal_char);
  1518. end;
  1519. end;
  1520. end;
  1521. exit_label:
  1522. lasttoken:=token;
  1523. end;
  1524. function tscannerfile.readpreproc:ttoken;
  1525. begin
  1526. skipspace;
  1527. case c of
  1528. 'A'..'Z',
  1529. 'a'..'z',
  1530. '_','0'..'9' : begin
  1531. preprocpat:=readid;
  1532. readpreproc:=_ID;
  1533. end;
  1534. '(' : begin
  1535. readchar;
  1536. readpreproc:=_LKLAMMER;
  1537. end;
  1538. ')' : begin
  1539. readchar;
  1540. readpreproc:=_RKLAMMER;
  1541. end;
  1542. '+' : begin
  1543. readchar;
  1544. readpreproc:=_PLUS;
  1545. end;
  1546. '-' : begin
  1547. readchar;
  1548. readpreproc:=_MINUS;
  1549. end;
  1550. '*' : begin
  1551. readchar;
  1552. readpreproc:=_STAR;
  1553. end;
  1554. '/' : begin
  1555. readchar;
  1556. readpreproc:=_SLASH;
  1557. end;
  1558. '=' : begin
  1559. readchar;
  1560. readpreproc:=_EQUAL;
  1561. end;
  1562. '>' : begin
  1563. readchar;
  1564. if c='=' then
  1565. begin
  1566. readchar;
  1567. readpreproc:=_GTE;
  1568. end
  1569. else
  1570. readpreproc:=_GT;
  1571. end;
  1572. '<' : begin
  1573. readchar;
  1574. case c of
  1575. '>' : begin
  1576. readchar;
  1577. readpreproc:=_UNEQUAL;
  1578. end;
  1579. '=' : begin
  1580. readchar;
  1581. readpreproc:=_LTE;
  1582. end;
  1583. else readpreproc:=_LT;
  1584. end;
  1585. end;
  1586. #26 :
  1587. end_of_file;
  1588. else
  1589. begin
  1590. readpreproc:=_EOF;
  1591. checkpreprocstack;
  1592. end;
  1593. end;
  1594. end;
  1595. function tscannerfile.asmgetchar : char;
  1596. begin
  1597. if lastasmgetchar<>#0 then
  1598. begin
  1599. c:=lastasmgetchar;
  1600. lastasmgetchar:=#0;
  1601. end
  1602. else
  1603. readchar;
  1604. case c of
  1605. '{' : begin
  1606. skipcomment;
  1607. asmgetchar:=c;
  1608. exit;
  1609. end;
  1610. '/' : begin
  1611. readchar;
  1612. if c='/' then
  1613. begin
  1614. skipdelphicomment;
  1615. asmgetchar:=c;
  1616. end
  1617. else
  1618. begin
  1619. asmgetchar:='/';
  1620. lastasmgetchar:=c;
  1621. end;
  1622. exit;
  1623. end;
  1624. '(' : begin
  1625. readchar;
  1626. if c='*' then
  1627. begin
  1628. skipoldtpcomment;
  1629. asmgetchar:=c;
  1630. end
  1631. else
  1632. begin
  1633. asmgetchar:='(';
  1634. lastasmgetchar:=c;
  1635. end;
  1636. exit;
  1637. end;
  1638. else
  1639. begin
  1640. asmgetchar:=c;
  1641. end;
  1642. end;
  1643. end;
  1644. end.
  1645. {
  1646. $Log$
  1647. Revision 1.109 2000-03-13 21:21:57 peter
  1648. * ^m support also after a string
  1649. Revision 1.108 2000/03/12 17:53:16 florian
  1650. * very small change to scanner ...
  1651. Revision 1.107 2000/02/29 23:59:47 pierre
  1652. Use $GOTO ON
  1653. Revision 1.106 2000/02/28 17:23:57 daniel
  1654. * Current work of symtable integration committed. The symtable can be
  1655. activated by defining 'newst', but doesn't compile yet. Changes in type
  1656. checking and oop are completed. What is left is to write a new
  1657. symtablestack and adapt the parser to use it.
  1658. Revision 1.105 2000/02/09 13:23:03 peter
  1659. * log truncated
  1660. Revision 1.104 2000/01/30 19:28:25 peter
  1661. * fixed filepos when eof is read, it'll now stay on the eof position
  1662. Revision 1.103 2000/01/07 01:14:38 peter
  1663. * updated copyright to 2000
  1664. Revision 1.102 1999/12/02 17:34:34 peter
  1665. * preprocessor support. But it fails on the caret in type blocks
  1666. Revision 1.101 1999/11/15 17:52:59 pierre
  1667. + one field added for ttoken record for operator
  1668. linking the id to the corresponding operator token that
  1669. can now now all be overloaded
  1670. * overloaded operators are resetted to nil in InitSymtable
  1671. (bug when trying to compile a uint that overloads operators twice)
  1672. Revision 1.100 1999/11/06 14:34:26 peter
  1673. * truncated log to 20 revs
  1674. Revision 1.99 1999/11/03 23:44:28 peter
  1675. * fixed comment level counting after directive
  1676. Revision 1.98 1999/11/02 15:05:08 peter
  1677. * fixed oldtp comment parsing
  1678. Revision 1.97 1999/10/30 12:32:30 peter
  1679. * fixed line counter when the first line had #10 only. This was buggy
  1680. for both the main file as for include files
  1681. Revision 1.96 1999/09/27 23:40:10 peter
  1682. * fixed macro within macro endless-loop
  1683. Revision 1.95 1999/09/03 10:02:48 peter
  1684. * $IFNDEF is 7 chars and not 6 chars
  1685. Revision 1.94 1999/09/02 18:47:47 daniel
  1686. * Could not compile with TP, some arrays moved to heap
  1687. * NOAG386BIN default for TP
  1688. * AG386* files were not compatible with TP, fixed.
  1689. Revision 1.93 1999/08/30 10:17:58 peter
  1690. * fixed crash in psub
  1691. * ansistringcompare fixed
  1692. * support for #$0b8
  1693. Revision 1.92 1999/08/06 13:11:44 michael
  1694. * Removed C style comments.
  1695. Revision 1.91 1999/08/05 16:53:11 peter
  1696. * V_Fatal=1, all other V_ are also increased
  1697. * Check for local procedure when assigning procvar
  1698. * fixed comment parsing because directives
  1699. * oldtp mode directives better supported
  1700. * added some messages to errore.msg
  1701. Revision 1.90 1999/08/04 13:03:05 jonas
  1702. * all tokens now start with an underscore
  1703. * PowerPC compiles!!
  1704. Revision 1.89 1999/07/29 11:43:22 peter
  1705. * always output preprocstack when unexpected eof is found
  1706. * fixed tp7/delphi skipuntildirective parsing
  1707. Revision 1.88 1999/07/24 11:20:59 peter
  1708. * directives are allowed in (* *)
  1709. * fixed parsing of (* between conditional code
  1710. }