scan.l 20 KB

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