scanner.pas 55 KB

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