scanner.pas 54 KB

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