scanner.pas 54 KB

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