scanner.pas 52 KB

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