scan.l 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. %{
  2. {
  3. $Id$
  4. Copyright (c) 1998-2000 by Florian Klaempfl
  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. unit scan;
  18. interface
  19. uses
  20. strings,
  21. lexlib,yacclib;
  22. const
  23. version = '0.99.15';
  24. type
  25. Char=system.char;
  26. ttyp = (
  27. t_id,
  28. { p contains the string }
  29. t_arraydef,
  30. { }
  31. t_pointerdef,
  32. { p1 contains the definition
  33. if in type overrider
  34. or nothing for args
  35. }
  36. t_addrdef,
  37. t_void,
  38. { no field }
  39. t_dec,
  40. { }
  41. t_declist,
  42. { p1 is t_dec
  43. next if exists }
  44. t_memberdec,
  45. { p1 is type specifier
  46. p2 is declarator_list }
  47. t_structdef,
  48. { }
  49. t_memberdeclist,
  50. { p1 is memberdec
  51. next is next if it exist }
  52. t_procdef,
  53. { }
  54. t_uniondef,
  55. { }
  56. t_enumdef,
  57. { }
  58. t_enumlist,
  59. { }
  60. t_preop,
  61. { p contains the operator string
  62. p1 contains the right expr }
  63. t_bop,
  64. { p contains the operator string
  65. p1 contains the left expr
  66. p2 contains the right expr }
  67. t_arrayop,
  68. {
  69. p1 contains the array expr
  70. p2 contains the index expressions }
  71. t_callop,
  72. {
  73. p1 contains the proc expr
  74. p2 contains the index expressions }
  75. t_arg,
  76. {
  77. p1 contain the typedef
  78. p2 the declarator (t_dec)
  79. }
  80. t_arglist,
  81. { }
  82. t_funexprlist,
  83. { }
  84. t_exprlist,
  85. { p1 contains the expr
  86. next contains the next if it exists }
  87. t_ifexpr,
  88. { p1 contains the condition expr
  89. p2 contains the if branch
  90. p3 contains the else branch }
  91. t_funcname,
  92. { p1 contains the function dname
  93. p2 contains the funexprlist
  94. p3 possibly contains the return type }
  95. t_typespec,
  96. { p1 is the type itself
  97. p2 the typecast expr }
  98. t_size_specifier,
  99. { p1 expr for size }
  100. t_default_value
  101. { p1 expr for value }
  102. );
  103. presobject = ^tresobject;
  104. tresobject = object
  105. typ : ttyp;
  106. p : pchar;
  107. next : presobject;
  108. p1,p2,p3 : presobject;
  109. { name of int/real, then no T prefix is required }
  110. intname : boolean;
  111. constructor init_no(t : ttyp);
  112. constructor init_one(t : ttyp;_p1 : presobject);
  113. constructor init_two(t : ttyp;_p1,_p2 : presobject);
  114. constructor init_three(t : ttyp;_p1,_p2,_p3 : presobject);
  115. constructor init_id(const s : string);
  116. constructor init_intid(const s : string);
  117. constructor init_bop(const s : string;_p1,_p2 : presobject);
  118. constructor init_preop(const s : string;_p1 : presobject);
  119. procedure setstr(const s:string);
  120. function str : string;
  121. function strlength : byte;
  122. function get_copy : presobject;
  123. { can this ve considered as a constant ? }
  124. function is_const : boolean;
  125. destructor done;
  126. end;
  127. tblocktype = (bt_type,bt_const,bt_var,bt_func,bt_no);
  128. var
  129. infile : string;
  130. outfile : text;
  131. c : char;
  132. aktspace : string;
  133. block_type : tblocktype;
  134. const
  135. in_define : boolean = false;
  136. { 1 after define; 2 after the ID to print the first separating space }
  137. in_space_define : byte = 0;
  138. arglevel : longint = 0;
  139. function yylex : integer;
  140. function act_token : string;
  141. procedure internalerror(i : integer);
  142. function strpnew(const s : string) : pchar;
  143. implementation
  144. uses
  145. options,converu;
  146. const
  147. newline = #10;
  148. procedure internalerror(i : integer);
  149. begin
  150. writeln('Internal error ',i,' in line ',yylineno);
  151. halt(1);
  152. end;
  153. procedure commenteof;
  154. begin
  155. writeln('unexpected EOF inside comment at line ',yylineno);
  156. end;
  157. procedure copy_until_eol;
  158. begin
  159. c:=get_char;
  160. while c<>newline do
  161. begin
  162. write(outfile,c);
  163. c:=get_char;
  164. end;
  165. end;
  166. procedure skip_until_eol;
  167. begin
  168. c:=get_char;
  169. while c<>newline do
  170. c:=get_char;
  171. end;
  172. function strpnew(const s : string) : pchar;
  173. var
  174. p : pchar;
  175. begin
  176. getmem(p,length(s)+1);
  177. strpcopy(p,s);
  178. strpnew:=p;
  179. end;
  180. constructor tresobject.init_preop(const s : string;_p1 : presobject);
  181. begin
  182. typ:=t_preop;
  183. p:=strpnew(s);
  184. p1:=_p1;
  185. p2:=nil;
  186. p3:=nil;
  187. next:=nil;
  188. intname:=false;
  189. end;
  190. constructor tresobject.init_bop(const s : string;_p1,_p2 : presobject);
  191. begin
  192. typ:=t_bop;
  193. p:=strpnew(s);
  194. p1:=_p1;
  195. p2:=_p2;
  196. p3:=nil;
  197. next:=nil;
  198. intname:=false;
  199. end;
  200. constructor tresobject.init_id(const s : string);
  201. begin
  202. typ:=t_id;
  203. p:=strpnew(s);
  204. p1:=nil;
  205. p2:=nil;
  206. p3:=nil;
  207. next:=nil;
  208. intname:=false;
  209. end;
  210. constructor tresobject.init_intid(const s : string);
  211. begin
  212. typ:=t_id;
  213. p:=strpnew(s);
  214. p1:=nil;
  215. p2:=nil;
  216. p3:=nil;
  217. next:=nil;
  218. intname:=true;
  219. end;
  220. constructor tresobject.init_two(t : ttyp;_p1,_p2 : presobject);
  221. begin
  222. typ:=t;
  223. p1:=_p1;
  224. p2:=_p2;
  225. p3:=nil;
  226. p:=nil;
  227. next:=nil;
  228. intname:=false;
  229. end;
  230. constructor tresobject.init_three(t : ttyp;_p1,_p2,_p3 : presobject);
  231. begin
  232. typ:=t;
  233. p1:=_p1;
  234. p2:=_p2;
  235. p3:=_p3;
  236. p:=nil;
  237. next:=nil;
  238. intname:=false;
  239. end;
  240. constructor tresobject.init_one(t : ttyp;_p1 : presobject);
  241. begin
  242. typ:=t;
  243. p1:=_p1;
  244. p2:=nil;
  245. p3:=nil;
  246. next:=nil;
  247. p:=nil;
  248. intname:=false;
  249. end;
  250. constructor tresobject.init_no(t : ttyp);
  251. begin
  252. typ:=t;
  253. p:=nil;
  254. p1:=nil;
  255. p2:=nil;
  256. p3:=nil;
  257. next:=nil;
  258. intname:=false;
  259. end;
  260. procedure tresobject.setstr(const s : string);
  261. begin
  262. if assigned(p) then
  263. strdispose(p);
  264. p:=strpnew(s);
  265. end;
  266. function tresobject.str : string;
  267. begin
  268. str:=strpas(p);
  269. end;
  270. function tresobject.strlength : byte;
  271. begin
  272. if assigned(p) then
  273. strlength:=strlen(p)
  274. else
  275. strlength:=0;
  276. end;
  277. { can this ve considered as a constant ? }
  278. function tresobject.is_const : boolean;
  279. begin
  280. case typ of
  281. t_id,t_void :
  282. is_const:=true;
  283. t_preop :
  284. is_const:= ((str='-') or (str=' not ')) and p1^.is_const;
  285. t_bop :
  286. is_const:= p2^.is_const and p1^.is_const;
  287. else
  288. is_const:=false;
  289. end;
  290. end;
  291. function tresobject.get_copy : presobject;
  292. var
  293. newres : presobject;
  294. begin
  295. newres:=new(presobject,init_no(typ));
  296. newres^.intname:=intname;
  297. if assigned(p) then
  298. newres^.p:=strnew(p);
  299. if assigned(p1) then
  300. newres^.p1:=p1^.get_copy;
  301. if assigned(p2) then
  302. newres^.p2:=p2^.get_copy;
  303. if assigned(p3) then
  304. newres^.p3:=p3^.get_copy;
  305. if assigned(next) then
  306. newres^.next:=next^.get_copy;
  307. get_copy:=newres;
  308. end;
  309. destructor tresobject.done;
  310. begin
  311. (* writeln('disposing ',byte(typ)); *)
  312. if assigned(p)then strdispose(p);
  313. if assigned(p1) then
  314. dispose(p1,done);
  315. if assigned(p2) then
  316. dispose(p2,done);
  317. if assigned(p3) then
  318. dispose(p3,done);
  319. if assigned(next) then
  320. dispose(next,done);
  321. end;
  322. %}
  323. D [0-9]
  324. %%
  325. "/*" begin
  326. if not stripcomment then
  327. write(outfile,aktspace,'{');
  328. repeat
  329. c:=get_char;
  330. case c of
  331. '*' :
  332. begin
  333. c:=get_char;
  334. if c='/' then
  335. begin
  336. if not stripcomment then
  337. writeln(outfile,' }');
  338. flush(outfile);
  339. exit;
  340. end
  341. else
  342. begin
  343. if not stripcomment then
  344. write(outfile,' ');
  345. unget_char(c)
  346. end;
  347. end;
  348. newline :
  349. begin
  350. if not stripcomment then
  351. begin
  352. writeln(outfile);
  353. write(outfile,aktspace);
  354. end;
  355. end;
  356. #0 :
  357. commenteof;
  358. else
  359. if not stripcomment then
  360. write(outfile,c);
  361. end;
  362. until false;
  363. flush(outfile);
  364. end;
  365. "//" begin
  366. If not stripcomment then
  367. write(outfile,aktspace,'{');
  368. repeat
  369. c:=get_char;
  370. case c of
  371. newline :
  372. begin
  373. unget_char(c);
  374. if not stripcomment then
  375. writeln(outfile,' }');
  376. flush(outfile);
  377. exit;
  378. end;
  379. #0 :
  380. commenteof;
  381. else
  382. if not stripcomment then
  383. write(outfile,c);
  384. end;
  385. until false;
  386. flush(outfile);
  387. end;
  388. \"[^\"]*\" return(CSTRING);
  389. \'[^\']*\' return(CSTRING);
  390. "L"\"[^\"]*\" if win32headers then
  391. return(CSTRING)
  392. else
  393. return(256);
  394. "L"\'[^\']*\' if win32headers then
  395. return(CSTRING)
  396. else
  397. return(256);
  398. {D}+[Uu]?[Ll]? begin
  399. while yytext[length(yytext)] in ['L','U','l','u'] do
  400. Delete(yytext,length(yytext),1);
  401. return(NUMBER);
  402. end;
  403. "0x"[0-9A-Fa-f]*[Uu]?[Ll]?
  404. begin
  405. (* handle pre- and postfixes *)
  406. if copy(yytext,1,2)='0x' then
  407. begin
  408. delete(yytext,1,2);
  409. yytext:='$'+yytext;
  410. end;
  411. while yytext[length(yytext)] in ['L','U','l','u'] do
  412. Delete(yytext,length(yytext),1);
  413. return(NUMBER);
  414. end;
  415. {D}+(\.{D}+)?([Ee][+-]?{D}+)?
  416. begin
  417. return(NUMBER);
  418. end;
  419. "->" if in_define then
  420. return(DEREF)
  421. else
  422. return(256);
  423. "-" return(MINUS);
  424. "==" return(EQUAL);
  425. "!=" return(UNEQUAL);
  426. ">=" return(GTE);
  427. "<=" return(LTE);
  428. ">>" return(_SHR);
  429. "##" return(STICK);
  430. "<<" return(_SHL);
  431. ">" return(GT);
  432. "<" return(LT);
  433. "|" return(_OR);
  434. "&" return(_AND);
  435. "~" return(_NOT); (* inverse, but handled as not operation *)
  436. "!" return(_NOT);
  437. "/" return(_SLASH);
  438. "+" return(_PLUS);
  439. "?" return(QUESTIONMARK);
  440. ":" return(COLON);
  441. "," return(COMMA);
  442. "[" return(LECKKLAMMER);
  443. "]" return(RECKKLAMMER);
  444. "(" begin
  445. inc(arglevel);
  446. return(LKLAMMER);
  447. end;
  448. ")" begin
  449. dec(arglevel);
  450. return(RKLAMMER);
  451. end;
  452. "*" return(STAR);
  453. "..." return(ELLIPSIS);
  454. "." if in_define then
  455. return(POINT)
  456. else
  457. return(256);
  458. "=" return(_ASSIGN);
  459. "extern" return(EXTERN);
  460. "STDCALL" if Win32headers then
  461. return(STDCALL)
  462. else
  463. return(ID);
  464. "CDECL" if not Win32headers then
  465. return(ID)
  466. else
  467. return(CDECL);
  468. "PASCAL" if not Win32headers then
  469. return(ID)
  470. else
  471. return(PASCAL);
  472. "PACKED" if not Win32headers then
  473. return(ID)
  474. else
  475. return(_PACKED);
  476. "WINAPI" if not Win32headers then
  477. return(ID)
  478. else
  479. return(WINAPI);
  480. "SYS_TRAP" if not palmpilot then
  481. return(ID)
  482. else
  483. return(SYS_TRAP);
  484. "WINGDIAPI" if not Win32headers then
  485. return(ID)
  486. else
  487. return(WINGDIAPI);
  488. "CALLBACK" if not Win32headers then
  489. return(ID)
  490. else
  491. return(CALLBACK);
  492. "EXPENTRY" if not Win32headers then
  493. return(ID)
  494. else
  495. return(CALLBACK);
  496. "void" return(VOID);
  497. "VOID" return(VOID);
  498. "#ifdef __cplusplus"[ \t]*\n"extern \"C\" {"\n"#endif"
  499. begin
  500. if not stripinfo then
  501. writeln(outfile,'{ C++ extern C conditionnal removed }');
  502. end;
  503. "#ifdef __cplusplus"[ \t]*\n"}"\n"#endif"
  504. begin
  505. if not stripinfo then
  506. writeln(outfile,'{ C++ end of extern C conditionnal removed }');
  507. end;
  508. "#"[ \t]*"else" begin
  509. writeln(outfile,'{$else}');
  510. block_type:=bt_no;
  511. flush(outfile);
  512. end;
  513. "#"[ \t]*"endif" begin
  514. writeln(outfile,'{$endif}');
  515. block_type:=bt_no;
  516. flush(outfile);
  517. end;
  518. "#"[ \t]*"elif" begin
  519. if not stripinfo then
  520. write(outfile,'(*** was #elif ****)');
  521. write(outfile,'{$else');
  522. copy_until_eol;
  523. writeln(outfile,'}');
  524. block_type:=bt_no;
  525. flush(outfile);
  526. end;
  527. "#"[ \t]*"undef" begin
  528. write(outfile,'{$undef');
  529. copy_until_eol;
  530. writeln(outfile,'}');
  531. flush(outfile);
  532. end;
  533. "#"[ \t]*"error" begin
  534. write(outfile,'{$error');
  535. copy_until_eol;
  536. writeln(outfile,'}');
  537. flush(outfile);
  538. end;
  539. "#"[ \t]*"include" begin
  540. write(outfile,'{$include');
  541. copy_until_eol;
  542. writeln(outfile,'}');
  543. flush(outfile);
  544. block_type:=bt_no;
  545. end;
  546. "#"[ \t]*"if" begin
  547. write(outfile,'{$if');
  548. copy_until_eol;
  549. writeln(outfile,'}');
  550. flush(outfile);
  551. block_type:=bt_no;
  552. end;
  553. "# "[0-9]+" " begin
  554. (* preprocessor line info *)
  555. repeat
  556. c:=get_char;
  557. case c of
  558. newline :
  559. begin
  560. unget_char(c);
  561. exit;
  562. end;
  563. #0 :
  564. commenteof;
  565. end;
  566. until false;
  567. end;
  568. "#"[ \t]*"pragma" begin
  569. if not stripinfo then
  570. begin
  571. write(outfile,'(** unsupported pragma');
  572. write(outfile,'#pragma');
  573. copy_until_eol;
  574. writeln(outfile,'*)');
  575. flush(outfile);
  576. end
  577. else
  578. skip_until_eol;
  579. block_type:=bt_no;
  580. end;
  581. "#"[ \t]*"define" begin
  582. in_define:=true;
  583. in_space_define:=1;
  584. return(DEFINE);
  585. end;
  586. "char" return(_CHAR);
  587. "union" return(UNION);
  588. "enum" return(ENUM);
  589. "struct" return(STRUCT);
  590. "{" return(LGKLAMMER);
  591. "}" return(RGKLAMMER);
  592. "typedef" return(TYPEDEF);
  593. "int" return(INT);
  594. "short" return(SHORT);
  595. "long" return(LONG);
  596. "signed" return(SIGNED);
  597. "unsigned" return(UNSIGNED);
  598. "float" return(REAL);
  599. "const" return(_CONST);
  600. "CONST" return(_CONST);
  601. "FAR" return(_FAR);
  602. "far" return(_FAR);
  603. "NEAR" return(_NEAR);
  604. "near" return(_NEAR);
  605. "HUGE" return(_HUGE);
  606. "huge" return(_HUGE);
  607. [A-Za-z_][A-Za-z0-9_]* begin
  608. if in_space_define=1 then
  609. in_space_define:=2;
  610. return(ID);
  611. end;
  612. ";" return(SEMICOLON);
  613. [ \f\t] begin
  614. if (arglevel=0) and (in_space_define=2) then
  615. begin
  616. in_space_define:=0;
  617. return(SPACE_DEFINE);
  618. end;
  619. end;
  620. \n begin
  621. if in_define then
  622. begin
  623. in_define:=false;
  624. in_space_define:=0;
  625. return(NEW_LINE);
  626. end;
  627. end;
  628. . begin
  629. writeln('Illegal character in line ',yylineno);
  630. writeln('"',yyline,'"');
  631. return(256);
  632. end;
  633. %%
  634. function act_token : string;
  635. begin
  636. act_token:=yytext;
  637. end;
  638. end.