scanner.pas 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444
  1. {
  2. $Id$
  3. Copyright (c) 1993,97 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. interface
  23. uses
  24. cobjects,globals,files;
  25. const
  26. {$ifdef TP}
  27. maxmacrolen = 1024;
  28. {$else}
  29. maxmacrolen = 16*1024;
  30. {$endif}
  31. id_len = 14;
  32. Newline = #10;
  33. type
  34. ident = string[id_len];
  35. const
  36. max_keywords = 71;
  37. anz_keywords : longint = max_keywords;
  38. keyword : array[1..max_keywords] of ident = (
  39. { 'ABSOLUTE',}
  40. 'AND',
  41. 'ARRAY','AS','ASM',
  42. { 'ASSEMBLER',}
  43. 'BEGIN',
  44. 'BREAK','CASE','CLASS',
  45. 'CONST','CONSTRUCTOR','CONTINUE',
  46. 'DESTRUCTOR','DISPOSE','DIV','DO','DOWNTO','ELSE','END',
  47. 'EXCEPT',
  48. 'EXIT',
  49. { 'EXPORT',}
  50. 'EXPORTS',
  51. { 'EXTERNAL',}
  52. 'FAIL','FALSE',
  53. { 'FAR',}
  54. 'FILE','FINALLY','FOR',
  55. { 'FORWARD',}
  56. 'FUNCTION','GOTO','IF','IMPLEMENTATION','IN',
  57. 'INHERITED','INITIALIZATION',
  58. { 'INLINE',} {INLINE is a reserved word in TP. Why?}
  59. 'INTERFACE',
  60. { 'INTERRUPT',}
  61. 'IS',
  62. 'LABEL','LIBRARY','MOD',
  63. { 'NEAR',}
  64. 'NEW','NIL','NOT','OBJECT',
  65. 'OF','ON','OPERATOR','OR','OTHERWISE','PACKED',
  66. 'PROCEDURE','PROGRAM','PROPERTY',
  67. 'RAISE','RECORD','REPEAT','SELF',
  68. 'SET','SHL','SHR','STRING','THEN','TO',
  69. 'TRUE','TRY','TYPE','UNIT','UNTIL',
  70. 'USES','VAR',
  71. { 'VIRTUAL',}
  72. 'WHILE','WITH','XOR');
  73. keyword_token : array[1..max_keywords] of ttoken = (
  74. { _ABSOLUTE,}
  75. _AND,
  76. _ARRAY,_AS,_ASM,
  77. { _ASSEMBLER,}
  78. _BEGIN,
  79. _BREAK,_CASE,_CLASS,
  80. _CONST,_CONSTRUCTOR,_CONTINUE,
  81. _DESTRUCTOR,_DISPOSE,_DIV,_DO,_DOWNTO,
  82. _ELSE,_END,_EXCEPT,
  83. _EXIT,
  84. { _EXPORT,}
  85. _EXPORTS,
  86. { _EXTERNAL,}
  87. _FAIL,_FALSE,
  88. { _FAR,}
  89. _FILE,_FINALLY,_FOR,
  90. { _FORWARD,}
  91. _FUNCTION,_GOTO,_IF,_IMPLEMENTATION,_IN,
  92. _INHERITED,_INITIALIZATION,
  93. { _INLINE,}
  94. _INTERFACE,
  95. { _INTERRUPT,}
  96. _IS,
  97. _LABEL,_LIBRARY,_MOD,
  98. { _NEAR,}
  99. _NEW,_NIL,_NOT,_OBJECT,
  100. _OF,_ON,_OPERATOR,_OR,_OTHERWISE,_PACKED,
  101. _PROCEDURE,_PROGRAM,_PROPERTY,
  102. _RAISE,_RECORD,_REPEAT,_SELF,
  103. _SET,_SHL,_SHR,_STRING,_THEN,_TO,
  104. _TRUE,_TRY,_TYPE,_UNIT,_UNTIL,
  105. _USES,_VAR,
  106. { _VIRTUAL,}
  107. _WHILE,_WITH,_XOR);
  108. type
  109. pmacrobuffer = ^tmacrobuffer;
  110. tmacrobuffer = array[0..maxmacrolen-1] of char;
  111. ppreprocstack = ^tpreprocstack;
  112. tpreprocstack = object
  113. isifdef,
  114. accept : boolean;
  115. next : ppreprocstack;
  116. name : stringid;
  117. line_nb : longint;
  118. constructor init(ifdef,a:boolean;n:ppreprocstack);
  119. destructor done;
  120. end;
  121. var
  122. c : char;
  123. orgpattern,
  124. pattern : string;
  125. macrobuffer : ^tmacrobuffer;
  126. comment_level : word;
  127. inputbuffer : pchar;
  128. inputpointer : pchar;
  129. parse_types, { true, if type declarations are parsed }
  130. s_point : boolean;
  131. yylexcount,
  132. macropos,
  133. lastlinepos,
  134. lasttokenpos : longint;
  135. lastasmgetchar : char;
  136. preprocstack : ppreprocstack;
  137. {$ifdef UseTokenInfo}
  138. type
  139. ttokeninfo = record
  140. token : ttoken;
  141. fi : tfileposinfo;
  142. end;
  143. ptokeninfo = ^ttokeninfo;
  144. {$endif UseTokenInfo}
  145. {public}
  146. procedure syntaxerror(const s : string);
  147. {$ifndef UseTokenInfo}
  148. function yylex : ttoken;
  149. {$else UseTokenInfo}
  150. function yylex : ptokeninfo;
  151. {$endif UseTokenInfo}
  152. function asmgetchar : char;
  153. function get_current_col : longint;
  154. procedure get_cur_file_pos(var fileinfo : tfileposinfo);
  155. procedure set_cur_file_pos(const fileinfo : tfileposinfo);
  156. procedure InitScanner(const fn: string);
  157. procedure DoneScanner(testendif:boolean);
  158. implementation
  159. uses
  160. dos,verbose,pbase,
  161. symtable,switches,link;
  162. var
  163. { this is usefull to get the write filename
  164. for the last instruction of an include file !}
  165. FileHasChanged : Boolean;
  166. status : tcompilestatus;
  167. {*****************************************************************************
  168. TPreProcStack
  169. *****************************************************************************}
  170. constructor tpreprocstack.init(ifdef,a:boolean;n:ppreprocstack);
  171. begin
  172. isifdef:=ifdef;
  173. accept:=a;
  174. next:=n;
  175. end;
  176. destructor tpreprocstack.done;
  177. begin
  178. end;
  179. procedure popstack;
  180. var
  181. hp : ppreprocstack;
  182. begin
  183. hp:=preprocstack^.next;
  184. dispose(preprocstack,done);
  185. preprocstack:=hp;
  186. end;
  187. {*****************************************************************************
  188. Helper routines
  189. *****************************************************************************}
  190. function is_keyword(var token : ttoken) : boolean;
  191. var
  192. high,low,mid : longint;
  193. begin
  194. low:=1;
  195. high:=anz_keywords;
  196. while low<high do
  197. begin
  198. mid:=(high+low+1) shr 1;
  199. if pattern<keyword[mid] then
  200. high:=mid-1
  201. else
  202. low:=mid;
  203. end;
  204. if pattern=keyword[high] then
  205. begin
  206. token:=keyword_token[high];
  207. is_keyword:=true;
  208. end
  209. else
  210. is_keyword:=false;
  211. end;
  212. procedure remove_keyword(const s : string);
  213. var
  214. i,j : longint;
  215. begin
  216. for i:=1 to anz_keywords do
  217. begin
  218. if keyword[i]=s then
  219. begin
  220. for j:=i to anz_keywords-1 do
  221. begin
  222. keyword[j]:=keyword[j+1];
  223. keyword_token[j]:=keyword_token[j+1];
  224. end;
  225. dec(anz_keywords);
  226. break;
  227. end;
  228. end;
  229. end;
  230. function get_current_col : longint;
  231. begin
  232. if lastlinepos<=lasttokenpos then
  233. get_current_col:=lasttokenpos-lastlinepos
  234. else
  235. get_current_col:=0;
  236. end;
  237. procedure inc_comment_level;
  238. begin
  239. inc(comment_level);
  240. if (comment_level>1) then
  241. Message1(scan_w_comment_level,tostr(comment_level));
  242. end;
  243. procedure dec_comment_level;
  244. begin
  245. if cs_tp_compatible in aktswitches then
  246. comment_level:=0
  247. else
  248. dec(comment_level);
  249. end;
  250. procedure syntaxerror(const s : string);
  251. begin
  252. Message2(scan_f_syn_expected,tostr(get_current_col),s);
  253. end;
  254. {*****************************************************************************
  255. Scanner
  256. *****************************************************************************}
  257. procedure reload;
  258. var
  259. readsize : word;
  260. i,saveline : longint;
  261. begin
  262. if not assigned(current_module^.current_inputfile) then
  263. internalerror(14);
  264. if current_module^.current_inputfile^.filenotatend then
  265. begin
  266. { load the next piece of source }
  267. blockread(current_module^.current_inputfile^.f,inputbuffer^,
  268. current_module^.current_inputfile^.bufsize-1,readsize);
  269. { Scan the buffer for #0 chars, which are not alllowed }
  270. if readsize > 0 then
  271. begin
  272. { force proper line counting }
  273. saveline:=current_module^.current_inputfile^.line_no;
  274. i:=0;
  275. inputpointer:=inputbuffer;
  276. while i<readsize do
  277. begin
  278. c:=inputpointer^;
  279. case c of
  280. #0 : Message(scan_f_illegal_char);
  281. #10,#13 : begin
  282. if (byte(c)+byte(inputpointer[1])=23) then
  283. begin
  284. inc(longint(inputpointer));
  285. inc(i);
  286. end;
  287. inc(current_module^.current_inputfile^.line_no);
  288. end;
  289. end;
  290. inc(i);
  291. inc(longint(inputpointer));
  292. end;
  293. current_module^.current_inputfile^.line_no:=saveline;
  294. end;
  295. inputbuffer[readsize]:=#0;
  296. inputpointer:=inputbuffer;
  297. { Set EOF when main source and at endoffile }
  298. if eof(current_module^.current_inputfile^.f) then
  299. begin
  300. current_module^.current_inputfile^.filenotatend:=false;
  301. if current_module^.current_inputfile^.next=nil then
  302. inputbuffer[readsize]:=#26;
  303. end;
  304. end
  305. else
  306. begin
  307. current_module^.current_inputfile^.close;
  308. { load next module }
  309. current_module^.current_inputfile:=current_module^.current_inputfile^.next;
  310. current_module^.current_index:=current_module^.current_inputfile^.ref_index;
  311. status.currentsource:=current_module^.current_inputfile^.name^+current_module^.current_inputfile^.ext^;
  312. inputbuffer:=current_module^.current_inputfile^.buf;
  313. inputpointer:=inputbuffer+current_module^.current_inputfile^.bufpos;
  314. end;
  315. { load next char }
  316. c:=inputpointer^;
  317. inc(longint(inputpointer));
  318. end;
  319. procedure linebreak;
  320. var
  321. cur : char;
  322. begin
  323. cur:=c;
  324. if (byte(inputpointer^)=0) and
  325. current_module^.current_inputfile^.filenotatend then
  326. begin
  327. reload;
  328. if byte(cur)+byte(c)<>23 then
  329. dec(longint(inputpointer));
  330. end
  331. else
  332. { Fix linebreak to be only newline (=#10) for all types of linebreaks }
  333. if (byte(inputpointer^)+byte(c)=23) then
  334. inc(longint(inputpointer));
  335. c:=newline;
  336. { Update Status and show status }
  337. with status do
  338. begin
  339. totalcompiledlines:=abslines;
  340. currentline:=current_module^.current_inputfile^.line_no
  341. +current_module^.current_inputfile^.line_count;
  342. { you call strcopy here at each line !!! }
  343. {currentsource:=current_module^.current_inputfile^.name^+current_module^.current_inputfile^.ext^;}
  344. totallines:=0;
  345. end;
  346. if compilestatusproc(status) then
  347. stop;
  348. inc(current_module^.current_inputfile^.line_no);
  349. inc(abslines);
  350. lastlinepos:=longint(inputpointer);
  351. end;
  352. procedure readchar;
  353. begin
  354. c:=inputpointer^;
  355. if c=#0 then
  356. reload
  357. else
  358. inc(longint(inputpointer));
  359. if c in [#10,#13] then
  360. linebreak;
  361. end;
  362. function readstring:string;
  363. var
  364. i : longint;
  365. begin
  366. i:=0;
  367. { 'in []' splitted, so it will be CMP's and no SET_IN_BYTE (PFV) }
  368. while (c in ['A'..'Z','a'..'z']) or (c in ['0'..'9','_']) do
  369. begin
  370. if i<255 then
  371. begin
  372. inc(i);
  373. readstring[i]:=c;
  374. end;
  375. { get next char }
  376. readchar;
  377. end;
  378. readstring[0]:=chr(i);
  379. end;
  380. function readid:string;
  381. begin
  382. readid:=upper(readstring);
  383. end;
  384. function readnumber:string;
  385. var
  386. base,
  387. i : longint;
  388. begin
  389. case c of
  390. '%' : begin
  391. readchar;
  392. base:=2;
  393. readnumber[1]:='%';
  394. i:=1;
  395. end;
  396. '$' : begin
  397. readchar;
  398. base:=16;
  399. readnumber[1]:='$';
  400. i:=1;
  401. end;
  402. else
  403. begin
  404. base:=10;
  405. i:=0;
  406. end;
  407. end;
  408. while ((base>=10) and (c in ['0'..'9'])) or
  409. ((base=16) and (c in ['A'..'F','a'..'f'])) or
  410. ((base=2) and (c in ['0'..'1'])) do
  411. begin
  412. if i<255 then
  413. begin
  414. inc(i);
  415. readnumber[i]:=c;
  416. end;
  417. { get next char }
  418. readchar;
  419. end;
  420. readnumber[0]:=chr(i);
  421. { was the next char a linebreak ? }
  422. { if c in [#10,#13] then
  423. linebreak; }
  424. end;
  425. function readval:longint;
  426. var
  427. l : longint;
  428. w : word;
  429. begin
  430. val(readnumber,l,w);
  431. readval:=l;
  432. end;
  433. function readcomment:string;
  434. var
  435. i : longint;
  436. begin
  437. i:=0;
  438. repeat
  439. case c of
  440. '}' : begin
  441. readchar;
  442. dec_comment_level;
  443. break;
  444. end;
  445. #26 : Message(scan_f_end_of_file);
  446. else
  447. begin
  448. if (i<255) then
  449. begin
  450. inc(i);
  451. readcomment[i]:=c;
  452. end;
  453. end;
  454. end;
  455. readchar;
  456. until false;
  457. readcomment[0]:=chr(i);
  458. end;
  459. procedure skipspace;
  460. begin
  461. while c in [' ',#9..#13] do
  462. begin
  463. readchar;
  464. {c:=inputpointer^;
  465. if c=#0 then
  466. reload
  467. else
  468. inc(longint(inputpointer));
  469. if c in [#10,#13] then
  470. linebreak; }
  471. end;
  472. end;
  473. procedure skipuntildirective;
  474. var
  475. found : longint;
  476. begin
  477. found:=0;
  478. repeat
  479. case c of
  480. #26 : Message(scan_f_end_of_file);
  481. '{' : begin
  482. if comment_level=0 then
  483. found:=1;
  484. inc_comment_level;
  485. end;
  486. '}' : begin
  487. dec_comment_level;
  488. found:=0;
  489. end;
  490. '$' : begin
  491. if found=1 then
  492. found:=2;
  493. end;
  494. else
  495. found:=0;
  496. end;
  497. readchar;
  498. {c:=inputpointer^;
  499. if c=#0 then
  500. reload
  501. else
  502. inc(longint(inputpointer));}
  503. until (found=2);
  504. end;
  505. {$i scandir.inc}
  506. procedure skipcomment;
  507. begin
  508. readchar;
  509. inc_comment_level;
  510. { handle compiler switches }
  511. if (c='$') then
  512. handledirectives;
  513. { handle_switches can dec comment_level, }
  514. while (comment_level>0) do
  515. begin
  516. case c of
  517. '{' : inc_comment_level;
  518. '}' : dec_comment_level;
  519. #26 : Message(scan_f_end_of_file);
  520. end;
  521. readchar;
  522. {c:=inputpointer^;
  523. if c=#0 then
  524. reload
  525. else
  526. inc(longint(inputpointer));}
  527. end;
  528. {if (c=#10) or (c=#13) then linebreak;}
  529. end;
  530. procedure skipdelphicomment;
  531. begin
  532. inc_comment_level;
  533. readchar;
  534. { this is currently not supported }
  535. if c='$' then
  536. Message(scan_e_wrong_styled_switch);
  537. { skip comment }
  538. while c<>newline do
  539. begin
  540. if c=#26 then
  541. Message(scan_f_end_of_file);
  542. readchar;
  543. end;
  544. dec_comment_level;
  545. end;
  546. procedure skipoldtpcomment;
  547. var
  548. found : longint;
  549. begin
  550. inc_comment_level;
  551. readchar;
  552. { this is currently not supported }
  553. if c='$' then
  554. Message(scan_e_wrong_styled_switch);
  555. { skip comment }
  556. while (comment_level>0) do
  557. begin
  558. found:=0;
  559. repeat
  560. case c of
  561. #26 : Message(scan_f_end_of_file);
  562. '*' : begin
  563. if found=3 then
  564. inc_comment_level
  565. else
  566. found:=1;
  567. end;
  568. ')' : begin
  569. if found=1 then
  570. begin
  571. dec_comment_level;
  572. if comment_level=0 then
  573. found:=2;
  574. end;
  575. end;
  576. '(' : found:=3;
  577. else
  578. found:=0;
  579. end;
  580. readchar;
  581. {c:=inputpointer^;
  582. if c=#0 then
  583. reload
  584. else
  585. inc(longint(inputpointer));}
  586. until (found=2);
  587. end;
  588. end;
  589. {$ifndef UseTokenInfo}
  590. function yylex : ttoken;
  591. {$else UseTokenInfo}
  592. function yylex : ptokeninfo;
  593. {$endif UseTokenInfo}
  594. var
  595. y : ttoken;
  596. {$ifdef UseTokenInfo}
  597. newyylex : ptokeninfo;
  598. line,column : longint;
  599. {$endif UseTokenInfo}
  600. code : word;
  601. l : longint;
  602. mac : pmacrosym;
  603. hp : pinputfile;
  604. hp2 : pchar;
  605. {$ifdef UseTokenInfo}
  606. label
  607. exit_label;
  608. {$endif UseTokenInfo}
  609. begin
  610. {$ifdef UseTokenInfo}
  611. line:=current_module^.current_inputfile^.line_no;
  612. column:=get_current_col;
  613. {$endif UseTokenInfo}
  614. { was the last character a point ? }
  615. { this code is needed because the scanner if there is a 1. found if }
  616. { this is a floating point number or range like 1..3 }
  617. if s_point then
  618. begin
  619. s_point:=false;
  620. if c='.' then
  621. begin
  622. readchar;
  623. {$ifndef UseTokenInfo}
  624. yylex:=POINTPOINT;
  625. exit;
  626. end;
  627. yylex:=POINT;
  628. exit;
  629. {$else UseTokenInfo}
  630. y:=POINTPOINT;
  631. goto exit_label;
  632. end;
  633. y:=POINT;
  634. goto exit_label;
  635. {$endif UseTokenInfo}
  636. end;
  637. repeat
  638. case c of
  639. '{' : skipcomment;
  640. ' ',#9..#13 : skipspace;
  641. else
  642. break;
  643. end;
  644. until false;
  645. lasttokenpos:=longint(inputpointer);
  646. {$ifdef UseTokenInfo}
  647. line:=current_module^.current_inputfile^.line_no;
  648. column:=get_current_col;
  649. { will become line:=lasttokenpos ??;}
  650. {$endif UseTokenInfo}
  651. case c of
  652. '_','A'..'Z',
  653. 'a'..'z' : begin
  654. orgpattern:=readstring;
  655. pattern:=upper(orgpattern);
  656. if (length(pattern) in [2..id_len]) and is_keyword(y) then
  657. {$ifndef UseTokenInfo}
  658. yylex:=y
  659. {$endif UseTokenInfo}
  660. else
  661. begin
  662. { this takes some time ... }
  663. if support_macros then
  664. begin
  665. mac:=pmacrosym(macros^.search(pattern));
  666. if assigned(mac) and (assigned(mac^.buftext)) then
  667. begin
  668. { don't forget the last char }
  669. dec(longint(inputpointer));
  670. current_module^.current_inputfile^.bufpos:=inputpointer-inputbuffer;
  671. { this isn't a proper way, but ... }
  672. hp:=new(pinputfile,init('','Macro '+pattern,''));
  673. hp^.next:=current_module^.current_inputfile;
  674. current_module^.current_inputfile:=hp;
  675. status.currentsource:=current_module^.current_inputfile^.name^;
  676. current_module^.sourcefiles.register_file(hp);
  677. current_module^.current_index:=hp^.ref_index;
  678. { set an own buffer }
  679. getmem(hp2,mac^.buflen+1);
  680. current_module^.current_inputfile^.setbuf(hp2,mac^.buflen+1);
  681. inputbuffer:=current_module^.current_inputfile^.buf;
  682. { copy text }
  683. move(mac^.buftext^,inputbuffer^,mac^.buflen);
  684. { put end sign }
  685. inputbuffer[mac^.buflen+1]:=#0;
  686. { load c }
  687. c:=inputbuffer^;
  688. inputpointer:=inputbuffer+1;
  689. { handle empty macros }
  690. if c=#0 then
  691. reload;
  692. { play it again ... }
  693. inc(yylexcount);
  694. if yylexcount>16 then
  695. Message(scan_w_macro_deep_ten);
  696. {$ifdef TP}
  697. yylex:=yylex;
  698. {$else}
  699. yylex:=yylex();
  700. {$endif}
  701. { that's all folks }
  702. dec(yylexcount);
  703. exit;
  704. end;
  705. end;
  706. {$ifndef UseTokenInfo}
  707. yylex:=ID;
  708. end;
  709. exit;
  710. {$else UseTokenInfo}
  711. y:=ID;
  712. end;
  713. goto exit_label;
  714. {$endif UseTokenInfo}
  715. end;
  716. '$' : begin
  717. pattern:=readnumber;
  718. {$ifndef UseTokenInfo}
  719. yylex:=INTCONST;
  720. exit;
  721. {$else UseTokenInfo}
  722. y:=INTCONST;
  723. goto exit_label;
  724. {$endif UseTokenInfo}
  725. end;
  726. '%' : begin
  727. pattern:=readnumber;
  728. {$ifndef UseTokenInfo}
  729. yylex:=INTCONST;
  730. exit;
  731. {$else UseTokenInfo}
  732. y:=INTCONST;
  733. goto exit_label;
  734. {$endif UseTokenInfo}
  735. end;
  736. '0'..'9' : begin
  737. pattern:=readnumber;
  738. case c of
  739. '.' : begin
  740. readchar;
  741. if not(c in ['0'..'9']) then
  742. begin
  743. s_point:=true;
  744. {$ifndef UseTokenInfo}
  745. yylex:=INTCONST;
  746. exit;
  747. {$else UseTokenInfo}
  748. y:=INTCONST;
  749. goto exit_label;
  750. {$endif UseTokenInfo}
  751. end;
  752. pattern:=pattern+'.';
  753. while c in ['0'..'9'] do
  754. begin
  755. pattern:=pattern+c;
  756. readchar;
  757. end;
  758. {$ifndef UseTokenInfo}
  759. yylex:=REALNUMBER;
  760. exit;
  761. {$else UseTokenInfo}
  762. y:=REALNUMBER;
  763. goto exit_label;
  764. {$endif UseTokenInfo}
  765. end;
  766. 'e','E' : begin
  767. pattern:=pattern+'E';
  768. readchar;
  769. if c in ['-','+'] then
  770. begin
  771. pattern:=pattern+c;
  772. readchar;
  773. end;
  774. if not(c in ['0'..'9']) then
  775. Message(scan_f_illegal_char);
  776. while c in ['0'..'9'] do
  777. begin
  778. pattern:=pattern+c;
  779. readchar;
  780. end;
  781. {$ifndef UseTokenInfo}
  782. yylex:=REALNUMBER;
  783. exit;
  784. {$else UseTokenInfo}
  785. y:=REALNUMBER;
  786. goto exit_label;
  787. {$endif UseTokenInfo}
  788. end;
  789. end;
  790. {$ifndef UseTokenInfo}
  791. yylex:=INTCONST;
  792. exit;
  793. {$else UseTokenInfo}
  794. y:=INTCONST;
  795. goto exit_label;
  796. {$endif UseTokenInfo}
  797. end;
  798. ';' : begin
  799. readchar;
  800. {$ifndef UseTokenInfo}
  801. yylex:=SEMICOLON;
  802. exit;
  803. {$else UseTokenInfo}
  804. y:=SEMICOLON;
  805. goto exit_label;
  806. {$endif UseTokenInfo}
  807. end;
  808. '[' : begin
  809. readchar;
  810. {$ifndef UseTokenInfo}
  811. yylex:=LECKKLAMMER;
  812. exit;
  813. {$else UseTokenInfo}
  814. y:=LECKKLAMMER;
  815. goto exit_label;
  816. {$endif UseTokenInfo}
  817. end;
  818. ']' : begin
  819. readchar;
  820. {$ifndef UseTokenInfo}
  821. yylex:=RECKKLAMMER;
  822. exit;
  823. {$else UseTokenInfo}
  824. y:=RECKKLAMMER;
  825. goto exit_label;
  826. {$endif UseTokenInfo}
  827. end;
  828. '(' : begin
  829. readchar;
  830. if c='*' then
  831. begin
  832. skipoldtpcomment;
  833. {$ifndef TP}
  834. yylex:=yylex();
  835. {$else TP}
  836. yylex:=yylex;
  837. {$endif TP}
  838. exit;
  839. end;
  840. {$ifndef UseTokenInfo}
  841. yylex:=LKLAMMER;
  842. exit;
  843. {$else UseTokenInfo}
  844. y:=LKLAMMER;
  845. goto exit_label;
  846. {$endif UseTokenInfo}
  847. end;
  848. ')' : begin
  849. readchar;
  850. {$ifndef UseTokenInfo}
  851. yylex:=RKLAMMER;
  852. exit;
  853. {$else UseTokenInfo}
  854. y:=RKLAMMER;
  855. goto exit_label;
  856. {$endif UseTokenInfo}
  857. end;
  858. '+' : begin
  859. readchar;
  860. if (c='=') and c_like_operators then
  861. begin
  862. readchar;
  863. {$ifndef UseTokenInfo}
  864. yylex:=_PLUSASN;
  865. exit;
  866. {$else UseTokenInfo}
  867. y:=_PLUSASN;
  868. goto exit_label;
  869. {$endif UseTokenInfo}
  870. end;
  871. {$ifndef UseTokenInfo}
  872. yylex:=PLUS;
  873. exit;
  874. {$else UseTokenInfo}
  875. y:=PLUS;
  876. goto exit_label;
  877. {$endif UseTokenInfo}
  878. end;
  879. '-' : begin
  880. readchar;
  881. if (c='=') and c_like_operators then
  882. begin
  883. readchar;
  884. {$ifndef UseTokenInfo}
  885. yylex:=_MINUSASN;
  886. exit;
  887. {$else UseTokenInfo}
  888. y:=_MINUSASN;
  889. goto exit_label;
  890. {$endif UseTokenInfo}
  891. end;
  892. {$ifndef UseTokenInfo}
  893. yylex:=MINUS;
  894. exit;
  895. {$else UseTokenInfo}
  896. y:=MINUS;
  897. goto exit_label;
  898. {$endif UseTokenInfo}
  899. end;
  900. ':' : begin
  901. readchar;
  902. if c='=' then
  903. begin
  904. readchar;
  905. {$ifndef UseTokenInfo}
  906. yylex:=ASSIGNMENT;
  907. exit;
  908. {$else UseTokenInfo}
  909. y:=ASSIGNMENT;
  910. goto exit_label;
  911. {$endif UseTokenInfo}
  912. end;
  913. {$ifndef UseTokenInfo}
  914. yylex:=COLON;
  915. exit;
  916. {$else UseTokenInfo}
  917. y:=COLON;
  918. goto exit_label;
  919. {$endif UseTokenInfo}
  920. end;
  921. '*' : begin
  922. readchar;
  923. if (c='=') and c_like_operators then
  924. begin
  925. readchar;
  926. {$ifndef UseTokenInfo}
  927. yylex:=_STARASN;
  928. {$else UseTokenInfo}
  929. y:=_STARASN;
  930. {$endif UseTokenInfo}
  931. end else if c='*' then
  932. begin
  933. readchar;
  934. {$ifndef UseTokenInfo}
  935. yylex:=STARSTAR;
  936. {$else UseTokenInfo}
  937. y:=STARSTAR;
  938. {$endif UseTokenInfo}
  939. end
  940. else
  941. {$ifndef UseTokenInfo}
  942. yylex:=STAR;
  943. exit;
  944. {$else UseTokenInfo}
  945. y:=STAR;
  946. goto exit_label;
  947. {$endif UseTokenInfo}
  948. end;
  949. '/' : begin
  950. readchar;
  951. case c of
  952. '=' : begin
  953. if c_like_operators then
  954. begin
  955. readchar;
  956. {$ifndef UseTokenInfo}
  957. yylex:=_SLASHASN;
  958. exit;
  959. {$else UseTokenInfo}
  960. y:=_SLASHASN;
  961. goto exit_label;
  962. {$endif UseTokenInfo}
  963. end;
  964. end;
  965. '/' : begin
  966. skipdelphicomment;
  967. {$ifndef TP}
  968. yylex:=yylex();
  969. {$else TP}
  970. yylex:=yylex;
  971. {$endif TP}
  972. exit;
  973. end;
  974. end;
  975. {$ifndef UseTokenInfo}
  976. yylex:=SLASH;
  977. exit;
  978. {$else UseTokenInfo}
  979. y:=SLASH;
  980. goto exit_label;
  981. {$endif UseTokenInfo}
  982. end;
  983. '=' : begin
  984. readchar;
  985. {$ifndef UseTokenInfo}
  986. yylex:=EQUAL;
  987. exit;
  988. {$else UseTokenInfo}
  989. y:=EQUAL;
  990. goto exit_label;
  991. {$endif UseTokenInfo}
  992. end;
  993. '.' : begin
  994. readchar;
  995. if c='.' then
  996. begin
  997. readchar;
  998. {$ifndef UseTokenInfo}
  999. yylex:=POINTPOINT;
  1000. exit;
  1001. {$else UseTokenInfo}
  1002. y:=POINTPOINT;
  1003. goto exit_label;
  1004. {$endif UseTokenInfo}
  1005. end
  1006. else
  1007. {$ifndef UseTokenInfo}
  1008. yylex:=POINT;
  1009. exit;
  1010. {$else UseTokenInfo}
  1011. y:=POINT;
  1012. goto exit_label;
  1013. {$endif UseTokenInfo}
  1014. end;
  1015. '@' : begin
  1016. readchar;
  1017. if c='@' then
  1018. begin
  1019. readchar;
  1020. {$ifndef UseTokenInfo}
  1021. yylex:=DOUBLEADDR;
  1022. {$else UseTokenInfo}
  1023. y:=DOUBLEADDR;
  1024. {$endif UseTokenInfo}
  1025. end
  1026. else
  1027. {$ifndef UseTokenInfo}
  1028. yylex:=KLAMMERAFFE;
  1029. exit;
  1030. {$else UseTokenInfo}
  1031. y:=KLAMMERAFFE;
  1032. goto exit_label;
  1033. {$endif UseTokenInfo}
  1034. end;
  1035. ',' : begin
  1036. readchar;
  1037. {$ifndef UseTokenInfo}
  1038. yylex:=COMMA;
  1039. exit;
  1040. {$else UseTokenInfo}
  1041. y:=COMMA;
  1042. goto exit_label;
  1043. {$endif UseTokenInfo}
  1044. end;
  1045. '''','#','^' : begin
  1046. if c='^' then
  1047. begin
  1048. readchar;
  1049. c:=upcase(c);
  1050. if not(block_type=bt_type) and (c in ['A'..'Z']) then
  1051. { if not(block_type=bt_type) and (c in [#64..#128]) then}
  1052. begin
  1053. pattern:=chr(ord(c)-64);
  1054. readchar;
  1055. end
  1056. else
  1057. begin
  1058. {$ifndef UseTokenInfo}
  1059. yylex:=CARET;
  1060. exit;
  1061. {$else UseTokenInfo}
  1062. y:=CARET;
  1063. goto exit_label;
  1064. {$endif UseTokenInfo}
  1065. end;
  1066. end
  1067. else
  1068. pattern:='';
  1069. repeat
  1070. case c of
  1071. '#' : begin
  1072. readchar; { read # }
  1073. valint(readnumber,l,code);
  1074. if (code<>0) or (l<0) or (l>255) then
  1075. Message(scan_e_illegal_char_const);
  1076. pattern:=pattern+chr(l);
  1077. end;
  1078. '''' : begin
  1079. repeat
  1080. readchar;
  1081. case c of
  1082. #26 : Message(scan_f_end_of_file);
  1083. newline : Message(scan_f_string_exceeds_line);
  1084. '''' : begin
  1085. readchar;
  1086. if c<>'''' then
  1087. break;
  1088. end;
  1089. end;
  1090. pattern:=pattern+c;
  1091. until false;
  1092. end;
  1093. '^' : begin
  1094. readchar;
  1095. if c<#64 then
  1096. c:=chr(ord(c)+64)
  1097. else
  1098. c:=chr(ord(c)-64);
  1099. pattern:=pattern+c;
  1100. readchar;
  1101. end;
  1102. else
  1103. break;
  1104. end;
  1105. until false;
  1106. { strings with length 1 become const chars }
  1107. {$ifndef UseTokenInfo}
  1108. if length(pattern)=1 then
  1109. yylex:=CCHAR
  1110. else
  1111. yylex:=CSTRING;
  1112. exit;
  1113. {$else UseTokenInfo}
  1114. if length(pattern)=1 then
  1115. y:=CCHAR
  1116. else
  1117. y:=CSTRING;
  1118. goto exit_label;
  1119. {$endif UseTokenInfo}
  1120. end;
  1121. '>' : begin
  1122. readchar;
  1123. case c of
  1124. '=' : begin
  1125. readchar;
  1126. {$ifndef UseTokenInfo}
  1127. yylex:=GTE;
  1128. exit;
  1129. {$else UseTokenInfo}
  1130. y:=GTE;
  1131. goto exit_label;
  1132. {$endif UseTokenInfo}
  1133. end;
  1134. '>' : begin
  1135. readchar;
  1136. {$ifndef UseTokenInfo}
  1137. yylex:=_SHR;
  1138. exit;
  1139. {$else UseTokenInfo}
  1140. y:=_SHR;
  1141. goto exit_label;
  1142. {$endif UseTokenInfo}
  1143. end;
  1144. '<' : begin { >< is for a symetric diff for sets }
  1145. readchar;
  1146. {$ifndef UseTokenInfo}
  1147. yylex:=SYMDIF;
  1148. exit;
  1149. {$else UseTokenInfo}
  1150. y:=SYMDIF;
  1151. goto exit_label;
  1152. {$endif UseTokenInfo}
  1153. end;
  1154. end;
  1155. {$ifndef UseTokenInfo}
  1156. yylex:=GT;
  1157. exit;
  1158. {$else UseTokenInfo}
  1159. y:=GT;
  1160. goto exit_label;
  1161. {$endif UseTokenInfo}
  1162. end;
  1163. '<' : begin
  1164. readchar;
  1165. case c of
  1166. '>' : begin
  1167. readchar;
  1168. {$ifndef UseTokenInfo}
  1169. yylex:=UNEQUAL;
  1170. exit;
  1171. {$else UseTokenInfo}
  1172. y:=UNEQUAL;
  1173. goto exit_label;
  1174. {$endif UseTokenInfo}
  1175. end;
  1176. '=' : begin
  1177. readchar;
  1178. {$ifndef UseTokenInfo}
  1179. yylex:=LTE;
  1180. exit;
  1181. {$else UseTokenInfo}
  1182. y:=LTE;
  1183. goto exit_label;
  1184. {$endif UseTokenInfo}
  1185. end;
  1186. '<' : begin
  1187. readchar;
  1188. {$ifndef UseTokenInfo}
  1189. yylex:=_SHL;
  1190. exit;
  1191. {$else UseTokenInfo}
  1192. y:=_SHL;
  1193. goto exit_label;
  1194. {$endif UseTokenInfo}
  1195. end;
  1196. end;
  1197. {$ifndef UseTokenInfo}
  1198. yylex:=LT;
  1199. exit;
  1200. {$else UseTokenInfo}
  1201. y:=LT;
  1202. goto exit_label;
  1203. {$endif UseTokenInfo}
  1204. end;
  1205. #26 : begin
  1206. {$ifndef UseTokenInfo}
  1207. yylex:=_EOF;
  1208. exit;
  1209. {$else UseTokenInfo}
  1210. y:=_EOF;
  1211. goto exit_label;
  1212. {$endif UseTokenInfo}
  1213. end;
  1214. else
  1215. begin
  1216. Message(scan_f_illegal_char);
  1217. end;
  1218. end;
  1219. {$ifdef UseTokenInfo}
  1220. exit_label:
  1221. new(newyylex);
  1222. newyylex^.token:=y;
  1223. newyylex^.fi.fileindex:=current_module^.current_index;
  1224. newyylex^.fi.line:=line;
  1225. newyylex^.fi.column:=column;
  1226. yylex:=newyylex;
  1227. {$endif UseTokenInfo}
  1228. end;
  1229. function asmgetchar : char;
  1230. begin
  1231. if lastasmgetchar<>#0 then
  1232. begin
  1233. c:=lastasmgetchar;
  1234. lastasmgetchar:=#0;
  1235. end
  1236. else
  1237. readchar;
  1238. case c of
  1239. '{' : begin
  1240. skipcomment;
  1241. lastasmgetchar:=c;
  1242. asmgetchar:=';';
  1243. exit;
  1244. end;
  1245. '/' : begin
  1246. readchar;
  1247. if c='/' then
  1248. begin
  1249. skipdelphicomment;
  1250. asmgetchar:=';';
  1251. end
  1252. else
  1253. asmgetchar:='/';
  1254. lastasmgetchar:=c;
  1255. exit;
  1256. end;
  1257. '(' : begin
  1258. readchar;
  1259. if c='*' then
  1260. begin
  1261. skipoldtpcomment;
  1262. asmgetchar:=';';
  1263. end
  1264. else
  1265. asmgetchar:='(';
  1266. lastasmgetchar:=c;
  1267. exit;
  1268. end;
  1269. else
  1270. begin
  1271. asmgetchar:=c;
  1272. end;
  1273. end;
  1274. end;
  1275. procedure InitScanner(const fn: string);
  1276. var
  1277. d:dirstr;
  1278. n:namestr;
  1279. e:extstr;
  1280. begin
  1281. fsplit(fn,d,n,e);
  1282. current_module^.current_inputfile:=new(pinputfile,init(d,n,e));
  1283. current_module^.current_inputfile^.reset;
  1284. current_module^.sourcefiles.register_file(current_module^.current_inputfile);
  1285. current_module^.current_index:=current_module^.current_inputfile^.ref_index;
  1286. status.currentsource:=current_module^.current_inputfile^.name^+current_module^.current_inputfile^.ext^;
  1287. if ioresult<>0 then
  1288. Message(scan_f_cannot_open_input);
  1289. inputbuffer:=current_module^.current_inputfile^.buf;
  1290. reload;
  1291. preprocstack:=nil;
  1292. comment_level:=0;
  1293. lasttokenpos:=0;
  1294. lastlinepos:=0;
  1295. s_point:=false;
  1296. end;
  1297. procedure get_cur_file_pos(var fileinfo : tfileposinfo);
  1298. begin
  1299. fileinfo.line:=current_module^.current_inputfile^.line_no;
  1300. {fileinfo.fileindex:=current_module^.current_inputfile^.ref_index;}
  1301. { should allways be the same !! }
  1302. fileinfo.fileindex:=current_module^.current_index;
  1303. fileinfo.column:=get_current_col;
  1304. end;
  1305. procedure set_cur_file_pos(const fileinfo : tfileposinfo);
  1306. begin
  1307. current_module^.current_index:=fileinfo.fileindex;
  1308. current_module^.current_inputfile:=
  1309. pinputfile(current_module^.sourcefiles.get_file(fileinfo.fileindex));
  1310. current_module^.current_inputfile^.line_no:=fileinfo.line;
  1311. {fileinfo.fileindex:=current_module^.current_inputfile^.ref_index;}
  1312. { should allways be the same !! }
  1313. { fileinfo.column:=get_current_col; }
  1314. end;
  1315. procedure DoneScanner(testendif:boolean);
  1316. var
  1317. st : string[16];
  1318. begin
  1319. if (not testendif) then
  1320. begin
  1321. while assigned(preprocstack) do
  1322. begin
  1323. if preprocstack^.isifdef then
  1324. st:='$IF(N)(DEF)'
  1325. else
  1326. st:='$ELSE';
  1327. Message3(scan_e_endif_expected,st,preprocstack^.name,tostr(preprocstack^.line_nb));
  1328. popstack;
  1329. end;
  1330. end;
  1331. end;
  1332. end.
  1333. {
  1334. $Log$
  1335. Revision 1.14 1998-04-30 15:59:42 pierre
  1336. * GDB works again better :
  1337. correct type info in one pass
  1338. + UseTokenInfo for better source position
  1339. * fixed one remaining bug in scanner for line counts
  1340. * several little fixes
  1341. Revision 1.13 1998/04/29 13:42:27 peter
  1342. + $IOCHECKS and $ALIGN to test already, other will follow soon
  1343. * fixed the wrong linecounting with comments
  1344. Revision 1.12 1998/04/29 10:34:04 pierre
  1345. + added some code for ansistring (not complete nor working yet)
  1346. * corrected operator overloading
  1347. * corrected nasm output
  1348. + started inline procedures
  1349. + added starstarn : use ** for exponentiation (^ gave problems)
  1350. + started UseTokenInfo cond to get accurate positions
  1351. Revision 1.11 1998/04/27 23:10:29 peter
  1352. + new scanner
  1353. * $makelib -> if smartlink
  1354. * small filename fixes pmodule.setfilename
  1355. * moved import from files.pas -> import.pas
  1356. }