scanner.pas 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902
  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. else
  737. { Add both characters !!}
  738. if (i<255) then
  739. begin
  740. inc(i);
  741. readcomment[i]:='*';
  742. if (i<255) then
  743. begin
  744. inc(i);
  745. readcomment[i]:='*';
  746. end;
  747. end;
  748. end
  749. else
  750. { Not old TP comment, so add...}
  751. begin
  752. if (i<255) then
  753. begin
  754. inc(i);
  755. readcomment[i]:='*';
  756. end;
  757. end;
  758. #26 :
  759. end_of_file;
  760. else
  761. begin
  762. if (i<255) then
  763. begin
  764. inc(i);
  765. readcomment[i]:=c;
  766. end;
  767. end;
  768. end;
  769. c:=inputpointer^;
  770. if c=#0 then
  771. reload
  772. else
  773. inc(longint(inputpointer));
  774. if c in [#10,#13] then
  775. linebreak;
  776. until false;
  777. {$ifndef TP}
  778. {$ifopt H+}
  779. setlength(readcomment,i);
  780. {$else}
  781. readcomment[0]:=chr(i);
  782. {$endif}
  783. {$else}
  784. readcomment[0]:=chr(i);
  785. {$endif}
  786. end;
  787. function tscannerfile.readstate:char;
  788. var
  789. state : char;
  790. begin
  791. state:=' ';
  792. if c=' ' then
  793. begin
  794. current_scanner^.skipspace;
  795. current_scanner^.readid;
  796. if pattern='ON' then
  797. state:='+'
  798. else
  799. if pattern='OFF' then
  800. state:='-';
  801. end
  802. else
  803. state:=c;
  804. if not (state in ['+','-']) then
  805. Message(scan_e_wrong_switch_toggle);
  806. readstate:=state;
  807. end;
  808. procedure tscannerfile.skipspace;
  809. begin
  810. while c in [' ',#9..#13] do
  811. begin
  812. c:=inputpointer^;
  813. if c=#0 then
  814. reload
  815. else
  816. inc(longint(inputpointer));
  817. case c of
  818. #26 :
  819. reload;
  820. #10,
  821. #13 :
  822. linebreak;
  823. end;
  824. end;
  825. end;
  826. procedure tscannerfile.skipuntildirective;
  827. var
  828. found : longint;
  829. next_char_loaded : boolean;
  830. oldcommentstyle : tcommentstyle;
  831. begin
  832. found:=0;
  833. next_char_loaded:=false;
  834. oldcommentstyle:=aktcommentstyle;
  835. repeat
  836. case c of
  837. #26 :
  838. end_of_file;
  839. '{' :
  840. begin
  841. if not(m_nested_comment in aktmodeswitches) or
  842. (comment_level=0) then
  843. begin
  844. found:=1;
  845. aktcommentstyle:=comment_tp;
  846. end;
  847. inc_comment_level;
  848. end;
  849. '}' :
  850. begin
  851. dec_comment_level;
  852. found:=0;
  853. end;
  854. '$' :
  855. begin
  856. if found=1 then
  857. found:=2;
  858. end;
  859. '''' :
  860. if (m_tp in aktmodeswitches) or
  861. (m_delphi in aktmodeswitches) then
  862. begin
  863. repeat
  864. readchar;
  865. case c of
  866. #26 :
  867. end_of_file;
  868. newline :
  869. break;
  870. '''' :
  871. begin
  872. readchar;
  873. if c<>'''' then
  874. break;
  875. end;
  876. end;
  877. until false;
  878. end;
  879. '(' :
  880. begin
  881. readchar;
  882. if c='*' then
  883. begin
  884. readchar;
  885. if c='$' then
  886. begin
  887. found:=2;
  888. inc_comment_level;
  889. aktcommentstyle:=comment_oldtp;
  890. end
  891. else
  892. begin
  893. skipoldtpcomment;
  894. aktcommentstyle:=oldcommentstyle;
  895. end;
  896. end
  897. else
  898. next_char_loaded:=true;
  899. end;
  900. else
  901. found:=0;
  902. end;
  903. if next_char_loaded then
  904. next_char_loaded:=false
  905. else
  906. begin
  907. c:=inputpointer^;
  908. if c=#0 then
  909. reload
  910. else
  911. inc(longint(inputpointer));
  912. case c of
  913. #26 : reload;
  914. #10,
  915. #13 : linebreak;
  916. end;
  917. end;
  918. until (found=2);
  919. end;
  920. {****************************************************************************
  921. Include directive scanning/parsing
  922. ****************************************************************************}
  923. {$i scandir.inc}
  924. {****************************************************************************
  925. Comment Handling
  926. ****************************************************************************}
  927. procedure tscannerfile.skipcomment;
  928. begin
  929. aktcommentstyle:=comment_tp;
  930. readchar;
  931. inc_comment_level;
  932. { handle compiler switches }
  933. if (c='$') then
  934. handledirectives;
  935. { handle_switches can dec comment_level, }
  936. while (comment_level>0) do
  937. begin
  938. case c of
  939. '{' : inc_comment_level;
  940. '}' : dec_comment_level;
  941. #26 : end_of_file;
  942. end;
  943. c:=inputpointer^;
  944. if c=#0 then
  945. reload
  946. else
  947. inc(longint(inputpointer));
  948. case c of
  949. #26 : reload;
  950. #10,
  951. #13 : linebreak;
  952. end;
  953. end;
  954. aktcommentstyle:=comment_none;
  955. end;
  956. procedure tscannerfile.skipdelphicomment;
  957. begin
  958. aktcommentstyle:=comment_delphi;
  959. inc_comment_level;
  960. readchar;
  961. { this is currently not supported }
  962. if c='$' then
  963. Message(scan_e_wrong_styled_switch);
  964. { skip comment }
  965. while c<>newline do
  966. begin
  967. if c=#26 then
  968. end_of_file;
  969. readchar;
  970. end;
  971. dec_comment_level;
  972. aktcommentstyle:=comment_none;
  973. end;
  974. procedure tscannerfile.skipoldtpcomment;
  975. var
  976. found : longint;
  977. begin
  978. aktcommentstyle:=comment_oldtp;
  979. inc_comment_level;
  980. readchar;
  981. { this is currently not supported }
  982. if (c='$') then
  983. handledirectives;
  984. { skip comment }
  985. while (comment_level>0) do
  986. begin
  987. found:=0;
  988. repeat
  989. case c of
  990. #26 :
  991. end_of_file;
  992. '*' :
  993. begin
  994. if found=3 then
  995. found:=4
  996. else
  997. found:=1;
  998. end;
  999. ')' :
  1000. begin
  1001. if found in [1,4] then
  1002. begin
  1003. dec_comment_level;
  1004. if comment_level=0 then
  1005. found:=2
  1006. else
  1007. found:=0;
  1008. end;
  1009. end;
  1010. '(' :
  1011. begin
  1012. if found=4 then
  1013. inc_comment_level;
  1014. found:=3;
  1015. end;
  1016. else
  1017. begin
  1018. if found=4 then
  1019. inc_comment_level;
  1020. found:=0;
  1021. end;
  1022. end;
  1023. c:=inputpointer^;
  1024. if c=#0 then
  1025. reload
  1026. else
  1027. inc(longint(inputpointer));
  1028. case c of
  1029. #26 : reload;
  1030. #10,
  1031. #13 : linebreak;
  1032. end;
  1033. until (found=2);
  1034. end;
  1035. aktcommentstyle:=comment_none;
  1036. end;
  1037. {****************************************************************************
  1038. Token Scanner
  1039. ****************************************************************************}
  1040. procedure tscannerfile.readtoken;
  1041. var
  1042. code : integer;
  1043. low,high,mid : longint;
  1044. m : longint;
  1045. mac : pmacrosym;
  1046. asciinr : string[6];
  1047. label
  1048. exit_label;
  1049. begin
  1050. { was there already a token read, then return that token }
  1051. if nexttoken<>NOTOKEN then
  1052. begin
  1053. token:=nexttoken;
  1054. nexttoken:=NOTOKEN;
  1055. goto exit_label;
  1056. end;
  1057. { Skip all spaces and comments }
  1058. repeat
  1059. case c of
  1060. '{' :
  1061. skipcomment;
  1062. ' ',#9..#13 :
  1063. begin
  1064. if parapreprocess then
  1065. begin
  1066. if c=#10 then
  1067. preprocfile^.eolfound:=true
  1068. else
  1069. preprocfile^.spacefound:=true;
  1070. end;
  1071. skipspace;
  1072. end
  1073. else
  1074. break;
  1075. end;
  1076. until false;
  1077. { Save current token position, for EOF its already loaded }
  1078. if c<>#26 then
  1079. gettokenpos;
  1080. { Check first for a identifier/keyword, this is 20+% faster (PFV) }
  1081. if c in ['A'..'Z','a'..'z','_'] then
  1082. begin
  1083. readstring;
  1084. token:=_ID;
  1085. idtoken:=_ID;
  1086. { keyword or any other known token,
  1087. pattern is always uppercased }
  1088. if (pattern[1]<>'_') and (length(pattern) in [2..tokenidlen]) then
  1089. begin
  1090. low:=ord(tokenidx^[length(pattern),pattern[1]].first);
  1091. high:=ord(tokenidx^[length(pattern),pattern[1]].last);
  1092. while low<high do
  1093. begin
  1094. mid:=(high+low+1) shr 1;
  1095. if pattern<tokeninfo^[ttoken(mid)].str then
  1096. high:=mid-1
  1097. else
  1098. low:=mid;
  1099. end;
  1100. if pattern=tokeninfo^[ttoken(high)].str then
  1101. begin
  1102. if tokeninfo^[ttoken(high)].keyword in aktmodeswitches then
  1103. if tokeninfo^[ttoken(high)].op=NOTOKEN then
  1104. token:=ttoken(high)
  1105. else
  1106. token:=tokeninfo^[ttoken(high)].op;
  1107. idtoken:=ttoken(high);
  1108. end;
  1109. end;
  1110. { Only process identifiers and not keywords }
  1111. if token=_ID then
  1112. begin
  1113. { this takes some time ... }
  1114. if (cs_support_macro in aktmoduleswitches) then
  1115. begin
  1116. mac:=pmacrosym(macros^.search(pattern));
  1117. if assigned(mac) and (assigned(mac^.buftext)) then
  1118. begin
  1119. insertmacro(pattern,mac^.buftext,mac^.buflen);
  1120. { handle empty macros }
  1121. if c=#0 then
  1122. begin
  1123. reload;
  1124. case c of
  1125. #26 : reload;
  1126. #10,
  1127. #13 : linebreak;
  1128. end;
  1129. end;
  1130. { play it again ... }
  1131. inc(yylexcount);
  1132. if yylexcount>16 then
  1133. Message(scan_w_macro_deep_ten);
  1134. readtoken;
  1135. { that's all folks }
  1136. dec(yylexcount);
  1137. exit;
  1138. end;
  1139. end;
  1140. end;
  1141. { return token }
  1142. goto exit_label;
  1143. end
  1144. else
  1145. begin
  1146. idtoken:=_NOID;
  1147. case c of
  1148. '$' :
  1149. begin
  1150. readnumber;
  1151. token:=_INTCONST;
  1152. goto exit_label;
  1153. end;
  1154. '%' :
  1155. begin
  1156. readnumber;
  1157. token:=_INTCONST;
  1158. goto exit_label;
  1159. end;
  1160. '0'..'9' :
  1161. begin
  1162. readnumber;
  1163. if (c in ['.','e','E']) then
  1164. begin
  1165. { first check for a . }
  1166. if c='.' then
  1167. begin
  1168. readchar;
  1169. { is it a .. from a range? }
  1170. case c of
  1171. '.' :
  1172. begin
  1173. readchar;
  1174. token:=_INTCONST;
  1175. nexttoken:=_POINTPOINT;
  1176. goto exit_label;
  1177. end;
  1178. ')' :
  1179. begin
  1180. readchar;
  1181. token:=_INTCONST;
  1182. nexttoken:=_RECKKLAMMER;
  1183. goto exit_label;
  1184. end;
  1185. end;
  1186. { insert the number after the . }
  1187. pattern:=pattern+'.';
  1188. while c in ['0'..'9'] do
  1189. begin
  1190. pattern:=pattern+c;
  1191. readchar;
  1192. end;
  1193. end;
  1194. { E can also follow after a point is scanned }
  1195. if c in ['e','E'] then
  1196. begin
  1197. pattern:=pattern+'E';
  1198. readchar;
  1199. if c in ['-','+'] then
  1200. begin
  1201. pattern:=pattern+c;
  1202. readchar;
  1203. end;
  1204. if not(c in ['0'..'9']) then
  1205. Message(scan_f_illegal_char);
  1206. while c in ['0'..'9'] do
  1207. begin
  1208. pattern:=pattern+c;
  1209. readchar;
  1210. end;
  1211. end;
  1212. token:=_REALNUMBER;
  1213. goto exit_label;
  1214. end;
  1215. token:=_INTCONST;
  1216. goto exit_label;
  1217. end;
  1218. ';' :
  1219. begin
  1220. readchar;
  1221. token:=_SEMICOLON;
  1222. goto exit_label;
  1223. end;
  1224. '[' :
  1225. begin
  1226. readchar;
  1227. token:=_LECKKLAMMER;
  1228. goto exit_label;
  1229. end;
  1230. ']' :
  1231. begin
  1232. readchar;
  1233. token:=_RECKKLAMMER;
  1234. goto exit_label;
  1235. end;
  1236. '(' :
  1237. begin
  1238. readchar;
  1239. case c of
  1240. '*' :
  1241. begin
  1242. skipoldtpcomment;
  1243. readtoken;
  1244. exit;
  1245. end;
  1246. '.' :
  1247. begin
  1248. readchar;
  1249. token:=_LECKKLAMMER;
  1250. goto exit_label;
  1251. end;
  1252. end;
  1253. token:=_LKLAMMER;
  1254. goto exit_label;
  1255. end;
  1256. ')' :
  1257. begin
  1258. readchar;
  1259. token:=_RKLAMMER;
  1260. goto exit_label;
  1261. end;
  1262. '+' :
  1263. begin
  1264. readchar;
  1265. if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
  1266. begin
  1267. readchar;
  1268. token:=_PLUSASN;
  1269. goto exit_label;
  1270. end;
  1271. token:=_PLUS;
  1272. goto exit_label;
  1273. end;
  1274. '-' :
  1275. begin
  1276. readchar;
  1277. if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
  1278. begin
  1279. readchar;
  1280. token:=_MINUSASN;
  1281. goto exit_label;
  1282. end;
  1283. token:=_MINUS;
  1284. goto exit_label;
  1285. end;
  1286. ':' :
  1287. begin
  1288. readchar;
  1289. if c='=' then
  1290. begin
  1291. readchar;
  1292. token:=_ASSIGNMENT;
  1293. goto exit_label;
  1294. end;
  1295. token:=_COLON;
  1296. goto exit_label;
  1297. end;
  1298. '*' :
  1299. begin
  1300. readchar;
  1301. if (c='=') and (cs_support_c_operators in aktmoduleswitches) then
  1302. begin
  1303. readchar;
  1304. token:=_STARASN;
  1305. end
  1306. else
  1307. if c='*' then
  1308. begin
  1309. readchar;
  1310. token:=_STARSTAR;
  1311. end
  1312. else
  1313. token:=_STAR;
  1314. goto exit_label;
  1315. end;
  1316. '/' :
  1317. begin
  1318. readchar;
  1319. case c of
  1320. '=' :
  1321. begin
  1322. if (cs_support_c_operators in aktmoduleswitches) then
  1323. begin
  1324. readchar;
  1325. token:=_SLASHASN;
  1326. goto exit_label;
  1327. end;
  1328. end;
  1329. '/' :
  1330. begin
  1331. skipdelphicomment;
  1332. readtoken;
  1333. exit;
  1334. end;
  1335. end;
  1336. token:=_SLASH;
  1337. goto exit_label;
  1338. end;
  1339. '=' :
  1340. begin
  1341. readchar;
  1342. token:=_EQUAL;
  1343. goto exit_label;
  1344. end;
  1345. '.' :
  1346. begin
  1347. readchar;
  1348. case c of
  1349. '.' :
  1350. begin
  1351. readchar;
  1352. token:=_POINTPOINT;
  1353. goto exit_label;
  1354. end;
  1355. ')' :
  1356. begin
  1357. readchar;
  1358. token:=_RECKKLAMMER;
  1359. goto exit_label;
  1360. end;
  1361. end;
  1362. token:=_POINT;
  1363. goto exit_label;
  1364. end;
  1365. '@' :
  1366. begin
  1367. readchar;
  1368. if c='@' then
  1369. begin
  1370. readchar;
  1371. token:=_DOUBLEADDR;
  1372. end
  1373. else
  1374. token:=_KLAMMERAFFE;
  1375. goto exit_label;
  1376. end;
  1377. ',' :
  1378. begin
  1379. readchar;
  1380. token:=_COMMA;
  1381. goto exit_label;
  1382. end;
  1383. '''','#','^' :
  1384. begin
  1385. if c='^' then
  1386. begin
  1387. readchar;
  1388. c:=upcase(c);
  1389. if (block_type=bt_type) or
  1390. (lasttoken=_ID) or
  1391. (lasttoken=_RKLAMMER) or (lasttoken=_RECKKLAMMER) or (lasttoken=_CARET) then
  1392. begin
  1393. token:=_CARET;
  1394. goto exit_label;
  1395. end
  1396. else
  1397. begin
  1398. if c<#64 then
  1399. pattern:=chr(ord(c)+64)
  1400. else
  1401. pattern:=chr(ord(c)-64);
  1402. readchar;
  1403. end;
  1404. end
  1405. else
  1406. pattern:='';
  1407. repeat
  1408. case c of
  1409. '#' :
  1410. begin
  1411. readchar; { read # }
  1412. if c='$' then
  1413. begin
  1414. readchar; { read leading $ }
  1415. asciinr:='$';
  1416. while (upcase(c) in ['A'..'F','0'..'9']) and (length(asciinr)<6) do
  1417. begin
  1418. asciinr:=asciinr+c;
  1419. readchar;
  1420. end;
  1421. end
  1422. else
  1423. begin
  1424. asciinr:='';
  1425. while (c in ['0'..'9']) and (length(asciinr)<6) do
  1426. begin
  1427. asciinr:=asciinr+c;
  1428. readchar;
  1429. end;
  1430. end;
  1431. valint(asciinr,m,code);
  1432. if (asciinr='') or (code<>0) or
  1433. (m<0) or (m>255) then
  1434. Message(scan_e_illegal_char_const);
  1435. pattern:=pattern+chr(m);
  1436. end;
  1437. '''' :
  1438. begin
  1439. repeat
  1440. readchar;
  1441. case c of
  1442. #26 :
  1443. end_of_file;
  1444. newline :
  1445. Message(scan_f_string_exceeds_line);
  1446. '''' :
  1447. begin
  1448. readchar;
  1449. if c<>'''' then
  1450. break;
  1451. end;
  1452. end;
  1453. pattern:=pattern+c;
  1454. until false;
  1455. end;
  1456. '^' :
  1457. begin
  1458. readchar;
  1459. c:=upcase(c);
  1460. if c<#64 then
  1461. c:=chr(ord(c)+64)
  1462. else
  1463. c:=chr(ord(c)-64);
  1464. pattern:=pattern+c;
  1465. readchar;
  1466. end;
  1467. else
  1468. break;
  1469. end;
  1470. until false;
  1471. { strings with length 1 become const chars }
  1472. if length(pattern)=1 then
  1473. token:=_CCHAR
  1474. else
  1475. token:=_CSTRING;
  1476. goto exit_label;
  1477. end;
  1478. '>' :
  1479. begin
  1480. readchar;
  1481. case c of
  1482. '=' :
  1483. begin
  1484. readchar;
  1485. token:=_GTE;
  1486. goto exit_label;
  1487. end;
  1488. '>' :
  1489. begin
  1490. readchar;
  1491. token:=_OP_SHR;
  1492. goto exit_label;
  1493. end;
  1494. '<' :
  1495. begin { >< is for a symetric diff for sets }
  1496. readchar;
  1497. token:=_SYMDIF;
  1498. goto exit_label;
  1499. end;
  1500. end;
  1501. token:=_GT;
  1502. goto exit_label;
  1503. end;
  1504. '<' :
  1505. begin
  1506. readchar;
  1507. case c of
  1508. '>' :
  1509. begin
  1510. readchar;
  1511. token:=_UNEQUAL;
  1512. goto exit_label;
  1513. end;
  1514. '=' :
  1515. begin
  1516. readchar;
  1517. token:=_LTE;
  1518. goto exit_label;
  1519. end;
  1520. '<' :
  1521. begin
  1522. readchar;
  1523. token:=_OP_SHL;
  1524. goto exit_label;
  1525. end;
  1526. end;
  1527. token:=_LT;
  1528. goto exit_label;
  1529. end;
  1530. #26 :
  1531. begin
  1532. token:=_EOF;
  1533. checkpreprocstack;
  1534. goto exit_label;
  1535. end;
  1536. else
  1537. begin
  1538. Message(scan_f_illegal_char);
  1539. end;
  1540. end;
  1541. end;
  1542. exit_label:
  1543. lasttoken:=token;
  1544. end;
  1545. function tscannerfile.readpreproc:ttoken;
  1546. begin
  1547. skipspace;
  1548. case c of
  1549. 'A'..'Z',
  1550. 'a'..'z',
  1551. '_','0'..'9' : begin
  1552. preprocpat:=readid;
  1553. readpreproc:=_ID;
  1554. end;
  1555. '(' : begin
  1556. readchar;
  1557. readpreproc:=_LKLAMMER;
  1558. end;
  1559. ')' : begin
  1560. readchar;
  1561. readpreproc:=_RKLAMMER;
  1562. end;
  1563. '+' : begin
  1564. readchar;
  1565. readpreproc:=_PLUS;
  1566. end;
  1567. '-' : begin
  1568. readchar;
  1569. readpreproc:=_MINUS;
  1570. end;
  1571. '*' : begin
  1572. readchar;
  1573. readpreproc:=_STAR;
  1574. end;
  1575. '/' : begin
  1576. readchar;
  1577. readpreproc:=_SLASH;
  1578. end;
  1579. '=' : begin
  1580. readchar;
  1581. readpreproc:=_EQUAL;
  1582. end;
  1583. '>' : begin
  1584. readchar;
  1585. if c='=' then
  1586. begin
  1587. readchar;
  1588. readpreproc:=_GTE;
  1589. end
  1590. else
  1591. readpreproc:=_GT;
  1592. end;
  1593. '<' : begin
  1594. readchar;
  1595. case c of
  1596. '>' : begin
  1597. readchar;
  1598. readpreproc:=_UNEQUAL;
  1599. end;
  1600. '=' : begin
  1601. readchar;
  1602. readpreproc:=_LTE;
  1603. end;
  1604. else readpreproc:=_LT;
  1605. end;
  1606. end;
  1607. #26 :
  1608. end_of_file;
  1609. else
  1610. begin
  1611. readpreproc:=_EOF;
  1612. checkpreprocstack;
  1613. end;
  1614. end;
  1615. end;
  1616. function tscannerfile.asmgetchar : char;
  1617. begin
  1618. if lastasmgetchar<>#0 then
  1619. begin
  1620. c:=lastasmgetchar;
  1621. lastasmgetchar:=#0;
  1622. end
  1623. else
  1624. readchar;
  1625. case c of
  1626. '{' : begin
  1627. skipcomment;
  1628. asmgetchar:=c;
  1629. exit;
  1630. end;
  1631. '/' : begin
  1632. readchar;
  1633. if c='/' then
  1634. begin
  1635. skipdelphicomment;
  1636. asmgetchar:=c;
  1637. end
  1638. else
  1639. begin
  1640. asmgetchar:='/';
  1641. lastasmgetchar:=c;
  1642. end;
  1643. exit;
  1644. end;
  1645. '(' : begin
  1646. readchar;
  1647. if c='*' then
  1648. begin
  1649. skipoldtpcomment;
  1650. asmgetchar:=c;
  1651. end
  1652. else
  1653. begin
  1654. asmgetchar:='(';
  1655. lastasmgetchar:=c;
  1656. end;
  1657. exit;
  1658. end;
  1659. else
  1660. begin
  1661. asmgetchar:=c;
  1662. end;
  1663. end;
  1664. end;
  1665. end.
  1666. {
  1667. $Log$
  1668. Revision 1.110 2000-04-08 20:18:53 michael
  1669. * Fixed bug in readcomment that was dropping * characters
  1670. Revision 1.109 2000/03/13 21:21:57 peter
  1671. * ^m support also after a string
  1672. Revision 1.108 2000/03/12 17:53:16 florian
  1673. * very small change to scanner ...
  1674. Revision 1.107 2000/02/29 23:59:47 pierre
  1675. Use $GOTO ON
  1676. Revision 1.106 2000/02/28 17:23:57 daniel
  1677. * Current work of symtable integration committed. The symtable can be
  1678. activated by defining 'newst', but doesn't compile yet. Changes in type
  1679. checking and oop are completed. What is left is to write a new
  1680. symtablestack and adapt the parser to use it.
  1681. Revision 1.105 2000/02/09 13:23:03 peter
  1682. * log truncated
  1683. Revision 1.104 2000/01/30 19:28:25 peter
  1684. * fixed filepos when eof is read, it'll now stay on the eof position
  1685. Revision 1.103 2000/01/07 01:14:38 peter
  1686. * updated copyright to 2000
  1687. Revision 1.102 1999/12/02 17:34:34 peter
  1688. * preprocessor support. But it fails on the caret in type blocks
  1689. Revision 1.101 1999/11/15 17:52:59 pierre
  1690. + one field added for ttoken record for operator
  1691. linking the id to the corresponding operator token that
  1692. can now now all be overloaded
  1693. * overloaded operators are resetted to nil in InitSymtable
  1694. (bug when trying to compile a uint that overloads operators twice)
  1695. Revision 1.100 1999/11/06 14:34:26 peter
  1696. * truncated log to 20 revs
  1697. Revision 1.99 1999/11/03 23:44:28 peter
  1698. * fixed comment level counting after directive
  1699. Revision 1.98 1999/11/02 15:05:08 peter
  1700. * fixed oldtp comment parsing
  1701. Revision 1.97 1999/10/30 12:32:30 peter
  1702. * fixed line counter when the first line had #10 only. This was buggy
  1703. for both the main file as for include files
  1704. Revision 1.96 1999/09/27 23:40:10 peter
  1705. * fixed macro within macro endless-loop
  1706. Revision 1.95 1999/09/03 10:02:48 peter
  1707. * $IFNDEF is 7 chars and not 6 chars
  1708. Revision 1.94 1999/09/02 18:47:47 daniel
  1709. * Could not compile with TP, some arrays moved to heap
  1710. * NOAG386BIN default for TP
  1711. * AG386* files were not compatible with TP, fixed.
  1712. Revision 1.93 1999/08/30 10:17:58 peter
  1713. * fixed crash in psub
  1714. * ansistringcompare fixed
  1715. * support for #$0b8
  1716. Revision 1.92 1999/08/06 13:11:44 michael
  1717. * Removed C style comments.
  1718. Revision 1.91 1999/08/05 16:53:11 peter
  1719. * V_Fatal=1, all other V_ are also increased
  1720. * Check for local procedure when assigning procvar
  1721. * fixed comment parsing because directives
  1722. * oldtp mode directives better supported
  1723. * added some messages to errore.msg
  1724. Revision 1.90 1999/08/04 13:03:05 jonas
  1725. * all tokens now start with an underscore
  1726. * PowerPC compiles!!
  1727. Revision 1.89 1999/07/29 11:43:22 peter
  1728. * always output preprocstack when unexpected eof is found
  1729. * fixed tp7/delphi skipuntildirective parsing
  1730. Revision 1.88 1999/07/24 11:20:59 peter
  1731. * directives are allowed in (* *)
  1732. * fixed parsing of (* between conditional code
  1733. }