scanner.pas 44 KB

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