scanner.pas 53 KB

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