scanner.pas 55 KB

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