scanbase.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. {
  2. Copyright (c) 1998-2000 by Florian Klaempfl
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. ****************************************************************************}
  15. unit scanbase;
  16. {$H+}
  17. interface
  18. uses
  19. h2plexlib, h2ptypes;
  20. var
  21. infile : string;
  22. outfile : text;
  23. c : char;
  24. aktspace : string;
  25. block_type : tblocktype;
  26. commentstr: string;
  27. const
  28. in_define : boolean = false;
  29. { True if define spans to the next line }
  30. cont_line : boolean = false;
  31. { 1 after define; 2 after the ID to print the first separating space }
  32. in_space_define : byte = 0;
  33. arglevel : longint = 0;
  34. {> 1 = ifdef level in a ifdef C++ block
  35. 1 = first level in an ifdef block
  36. 0 = not in an ifdef block
  37. -1 = in else part of ifdef block, process like we weren't in the block
  38. but skip the incoming end.
  39. > -1 = ifdef sublevel in an else block.
  40. }
  41. cplusblocklevel : LongInt = 0;
  42. procedure internalerror(i : integer);
  43. procedure writetree(p: presobject);
  44. function NotInCPlusBlock : Boolean; inline;
  45. procedure skip_until_eol;
  46. procedure commenteof;
  47. procedure copy_until_eol;
  48. procedure HandleMultiLineComment;
  49. procedure HandleSingleLineComment;
  50. Procedure CheckLongString;
  51. Procedure HandleContinuation;
  52. Procedure HandleEOL;
  53. Procedure HandleWhiteSpace;
  54. Procedure HandleIdentifier;
  55. Procedure HandleLongInteger;
  56. Procedure HandleHexLongInteger;
  57. Procedure HandleNumber;
  58. Procedure HandleDeref;
  59. Procedure HandleCallingConvention(aCC : Integer);
  60. Procedure HandlePalmPilotCallingConvention;
  61. Procedure HandleIllegalCharacter;
  62. // Preprocessor routines...
  63. Procedure HandlePreProcIfDef;
  64. Procedure HandlePreProcIf;
  65. Procedure HandlePreProcElse;
  66. Procedure HandlePreProcElIf;
  67. Procedure HandlePreProcEndif;
  68. Procedure HandlePreProcUndef;
  69. Procedure HandlePreProcInclude;
  70. Procedure HandlePreProcLineInfo;
  71. Procedure HandlePreProcPragma;
  72. Procedure HandlePreProcDefine;
  73. Procedure HandlePreProcError;
  74. Procedure HandlePreProcStripConditional(isEnd : Boolean);
  75. Procedure EnterCplusPlus;
  76. procedure openInputfile;
  77. const
  78. newline = #10;
  79. implementation
  80. uses
  81. h2poptions,h2pconst;
  82. procedure openInputfile;
  83. begin
  84. assign(yyinput, inputfilename);
  85. {$I-}
  86. reset(yyinput);
  87. {$I+}
  88. if ioresult<>0 then
  89. begin
  90. writeln('file ',inputfilename,' not found!');
  91. halt(1);
  92. end;
  93. end;
  94. procedure writeentry(p: presobject; var currentlevel: integer);
  95. begin
  96. if assigned(p^.p1) then
  97. begin
  98. WriteLn(' Entry p1[',ttypstr[p^.p1^.typ],']',p^.p1^.str);
  99. end;
  100. if assigned(p^.p2) then
  101. begin
  102. WriteLn(' Entry p2[',ttypstr[p^.p2^.typ],']',p^.p2^.str);
  103. end;
  104. if assigned(p^.p3) then
  105. begin
  106. WriteLn(' Entry p3[',ttypstr[p^.p3^.typ],']',p^.p3^.str);
  107. end;
  108. end;
  109. procedure writetree(p: presobject);
  110. var
  111. localp: presobject;
  112. localp1: presobject;
  113. currentlevel : integer;
  114. begin
  115. localp:=p;
  116. currentlevel:=0;
  117. while assigned(localp) do
  118. begin
  119. WriteLn('Entry[',ttypstr[localp^.typ],']',localp^.str);
  120. case localp^.typ of
  121. { Some arguments sharing the same type }
  122. t_arglist:
  123. begin
  124. localp1:=localp;
  125. while assigned(localp1) do
  126. begin
  127. writeentry(localp1,currentlevel);
  128. localp1:=localp1^.p1;
  129. end;
  130. end;
  131. end;
  132. localp:=localp^.next;
  133. end;
  134. end;
  135. procedure internalerror(i : integer);
  136. begin
  137. writeln('Internal error ',i,' in line ',yylineno);
  138. halt(1);
  139. end;
  140. procedure commenteof;
  141. begin
  142. writeln('unexpected EOF inside comment at line ',yylineno);
  143. end;
  144. procedure copy_until_eol;
  145. begin
  146. c:=get_char;
  147. while c<>newline do
  148. begin
  149. write(outfile,c);
  150. c:=get_char;
  151. end;
  152. end;
  153. procedure skip_until_eol;
  154. begin
  155. c:=get_char;
  156. while c<>newline do
  157. c:=get_char;
  158. end;
  159. function NotInCPlusBlock : Boolean; inline;
  160. begin
  161. NotInCPlusBlock := cplusblocklevel < 1;
  162. end;
  163. procedure HandleMultiLineComment;
  164. begin
  165. if not NotInCPlusBlock then
  166. begin
  167. Skip_until_eol;
  168. exit;
  169. end;
  170. if not stripcomment then
  171. write(outfile,aktspace,'{');
  172. repeat
  173. c:=get_char;
  174. case c of
  175. '*' :
  176. begin
  177. c:=get_char;
  178. if c='/' then
  179. begin
  180. if not stripcomment then
  181. write(outfile,' }');
  182. c:=get_char;
  183. if c=newline then
  184. writeln(outfile);
  185. unget_char(c);
  186. flush(outfile);
  187. exit;
  188. end
  189. else
  190. begin
  191. if not stripcomment then
  192. write(outfile,'*');
  193. unget_char(c)
  194. end;
  195. end;
  196. newline :
  197. begin
  198. if not stripcomment then
  199. begin
  200. writeln(outfile);
  201. write(outfile,aktspace);
  202. end;
  203. end;
  204. { Don't write this thing out, to
  205. avoid nested comments.
  206. }
  207. '{','}' :
  208. begin
  209. end;
  210. #0 :
  211. commenteof;
  212. else
  213. if not stripcomment then
  214. write(outfile,c);
  215. end;
  216. until false;
  217. flush(outfile);
  218. end;
  219. procedure HandleSingleLineComment;
  220. begin
  221. if not NotInCPlusBlock then
  222. begin
  223. skip_until_eol;
  224. exit;
  225. end;
  226. commentstr:='';
  227. if (in_define) and not (stripcomment) then
  228. begin
  229. commentstr:='{';
  230. end
  231. else
  232. If not stripcomment then
  233. write(outfile,aktspace,'{');
  234. repeat
  235. c:=get_char;
  236. case c of
  237. newline :
  238. begin
  239. unget_char(c);
  240. if not stripcomment then
  241. begin
  242. if in_define then
  243. begin
  244. commentstr:=commentstr+' }';
  245. end
  246. else
  247. begin
  248. write(outfile,' }');
  249. writeln(outfile);
  250. end;
  251. end;
  252. flush(outfile);
  253. exit;
  254. end;
  255. { Don't write this comment out,
  256. to avoid nested comment problems
  257. }
  258. '{','}' :
  259. begin
  260. end;
  261. #0 :
  262. commenteof;
  263. else
  264. if not stripcomment then
  265. begin
  266. if in_define then
  267. begin
  268. commentstr:=commentstr+c;
  269. end
  270. else
  271. write(outfile,c);
  272. end;
  273. end;
  274. until false;
  275. flush(outfile);
  276. end;
  277. Procedure CheckLongString;
  278. begin
  279. if NotInCPlusBlock then
  280. begin
  281. if win32headers then
  282. return(CSTRING)
  283. else
  284. return(256);
  285. end
  286. else skip_until_eol;
  287. end;
  288. Procedure HandleLongInteger;
  289. begin
  290. if NotInCPlusBlock then
  291. begin
  292. if yytext[1]='0' then
  293. begin
  294. delete(yytext,1,1);
  295. yytext:='&'+yytext;
  296. end;
  297. while yytext[length(yytext)] in ['L','U','l','u'] do
  298. Delete(yytext,length(yytext),1);
  299. return(NUMBER);
  300. end
  301. else skip_until_eol;
  302. end;
  303. Procedure HandleHexLongInteger;
  304. begin
  305. if NotInCPlusBlock then
  306. begin
  307. (* handle pre- and postfixes *)
  308. if copy(yytext,1,2)='0x' then
  309. begin
  310. delete(yytext,1,2);
  311. yytext:='$'+yytext;
  312. end;
  313. while yytext[length(yytext)] in ['L','U','l','u'] do
  314. Delete(yytext,length(yytext),1);
  315. return(NUMBER);
  316. end
  317. else
  318. skip_until_eol;
  319. end;
  320. procedure HandleNumber;
  321. begin
  322. if NotInCPlusBlock then
  323. begin
  324. return(NUMBER);
  325. end
  326. else
  327. skip_until_eol;
  328. end;
  329. Procedure HandleDeref;
  330. begin
  331. if NotInCPlusBlock then
  332. begin
  333. if in_define then
  334. return(DEREF)
  335. else
  336. return(256);
  337. end
  338. else
  339. skip_until_eol;
  340. end;
  341. Procedure HandlePreProcIfDef;
  342. begin
  343. if cplusblocklevel > 0 then
  344. Inc(cplusblocklevel)
  345. else
  346. begin
  347. if cplusblocklevel < 0 then
  348. Dec(cplusblocklevel);
  349. write(outfile,'{$ifdef ');
  350. copy_until_eol;
  351. writeln(outfile,'}');
  352. flush(outfile);
  353. end;
  354. end;
  355. Procedure HandlePreProcElse;
  356. begin
  357. if cplusblocklevel < -1 then
  358. begin
  359. writeln(outfile,'{$else}');
  360. block_type:=bt_no;
  361. flush(outfile);
  362. end
  363. else
  364. case cplusblocklevel of
  365. 0 :
  366. begin
  367. writeln(outfile,'{$else}');
  368. block_type:=bt_no;
  369. flush(outfile);
  370. end;
  371. 1 : cplusblocklevel := -1;
  372. -1 : cplusblocklevel := 1;
  373. end;
  374. end;
  375. Procedure HandlePreProcEndif;
  376. begin
  377. if cplusblocklevel > 0 then
  378. begin
  379. Dec(cplusblocklevel);
  380. end
  381. else
  382. begin
  383. case cplusblocklevel of
  384. 0 : begin
  385. writeln(outfile,'{$endif}');
  386. block_type:=bt_no;
  387. flush(outfile);
  388. end;
  389. -1 : begin
  390. cplusblocklevel :=0;
  391. end
  392. else
  393. inc(cplusblocklevel);
  394. end;
  395. end;
  396. end;
  397. Procedure HandlePreProcElif;
  398. begin
  399. if cplusblocklevel < -1 then
  400. begin
  401. if not stripinfo then
  402. write(outfile,'(*** was #elif ****)');
  403. write(outfile,'{$else');
  404. copy_until_eol;
  405. writeln(outfile,'}');
  406. block_type:=bt_no;
  407. flush(outfile);
  408. end
  409. else
  410. case cplusblocklevel of
  411. 0 :
  412. begin
  413. if not stripinfo then
  414. write(outfile,'(*** was #elif ****)');
  415. write(outfile,'{$else');
  416. copy_until_eol;
  417. writeln(outfile,'}');
  418. block_type:=bt_no;
  419. flush(outfile);
  420. end;
  421. 1 : cplusblocklevel := -1;
  422. -1 : cplusblocklevel := 1;
  423. end;
  424. end;
  425. Procedure HandlePreProcUndef;
  426. begin
  427. write(outfile,'{$undef');
  428. copy_until_eol;
  429. writeln(outfile,'}');
  430. flush(outfile);
  431. end;
  432. Procedure HandlePreProcInclude;
  433. begin
  434. if NotInCPlusBlock then
  435. begin
  436. write(outfile,'{$include');
  437. copy_until_eol;
  438. writeln(outfile,'}');
  439. flush(outfile);
  440. block_type:=bt_no;
  441. end
  442. else
  443. skip_until_eol;
  444. end;
  445. Procedure HandlePreProcIf;
  446. begin
  447. if cplusblocklevel > 0 then
  448. Inc(cplusblocklevel)
  449. else
  450. begin
  451. if cplusblocklevel < 0 then
  452. Dec(cplusblocklevel);
  453. write(outfile,'{$if');
  454. copy_until_eol;
  455. writeln(outfile,'}');
  456. flush(outfile);
  457. block_type:=bt_no;
  458. end;
  459. end;
  460. Procedure HandlePreProcLineInfo;
  461. begin
  462. if NotInCPlusBlock then
  463. (* preprocessor line info *)
  464. repeat
  465. c:=get_char;
  466. case c of
  467. newline :
  468. begin
  469. unget_char(c);
  470. exit;
  471. end;
  472. #0 :
  473. commenteof;
  474. end;
  475. until false
  476. else
  477. skip_until_eol;
  478. end;
  479. procedure HandlePreProcPragma;
  480. begin
  481. if not stripinfo then
  482. begin
  483. write(outfile,'(** unsupported pragma');
  484. write(outfile,'#pragma');
  485. copy_until_eol;
  486. writeln(outfile,'*)');
  487. flush(outfile);
  488. end
  489. else
  490. skip_until_eol;
  491. block_type:=bt_no;
  492. end;
  493. Procedure HandleContinuation;
  494. begin
  495. if in_define then
  496. begin
  497. cont_line:=true;
  498. end
  499. else
  500. begin
  501. writeln('Unexpected wrap of line ',yylineno);
  502. writeln('"',yyline,'"');
  503. return(256);
  504. end;
  505. end;
  506. Procedure HandleEOL;
  507. begin
  508. if not in_define then
  509. exit;
  510. in_space_define:=0;
  511. if cont_line then
  512. begin
  513. cont_line:=false;
  514. end
  515. else
  516. begin
  517. in_define:=false;
  518. if NotInCPlusBlock then
  519. return(NEW_LINE)
  520. else
  521. skip_until_eol
  522. end;
  523. end;
  524. Procedure HandlePreProcDefine;
  525. begin
  526. if NotInCPlusBlock then
  527. begin
  528. commentstr:='';
  529. in_define:=true;
  530. in_space_define:=1;
  531. return(DEFINE);
  532. end
  533. else
  534. skip_until_eol;
  535. end;
  536. Procedure HandlePreProcError;
  537. begin
  538. write(outfile,'{$error');
  539. copy_until_eol;
  540. writeln(outfile,'}');
  541. flush(outfile);
  542. end;
  543. Procedure EnterCplusPlus;
  544. begin
  545. Inc(cplusblocklevel);
  546. end;
  547. Procedure HandlePreProcStripConditional(isEnd : Boolean);
  548. begin
  549. if not stripinfo then
  550. if isEnd then
  551. writeln(outfile,'{ C++ end of extern C conditionnal removed }')
  552. else
  553. writeln(outfile,'{ C++ extern C conditionnal removed }');
  554. end;
  555. Procedure HandleIdentifier;
  556. begin
  557. if NotInCPlusBlock then
  558. begin
  559. if in_space_define=1 then
  560. in_space_define:=2;
  561. return(ID);
  562. end
  563. else
  564. skip_until_eol;
  565. end;
  566. Procedure HandleWhiteSpace;
  567. begin
  568. if NotInCPlusBlock then
  569. begin
  570. if (arglevel=0) and (in_space_define=2) then
  571. begin
  572. in_space_define:=0;
  573. return(SPACE_DEFINE);
  574. end;
  575. end
  576. else
  577. skip_until_eol;
  578. end;
  579. Procedure HandleCallingConvention(aCC :integer);
  580. begin
  581. if NotInCPlusBlock then
  582. begin
  583. if Win32headers then
  584. return(aCC)
  585. else
  586. return(ID);
  587. end
  588. else
  589. begin
  590. skip_until_eol;
  591. end;
  592. end;
  593. Procedure HandlePalmPilotCallingConvention;
  594. begin
  595. if NotInCPlusBlock then
  596. begin
  597. if not palmpilot then
  598. return(ID)
  599. else
  600. return(SYS_TRAP);
  601. end
  602. else
  603. begin
  604. skip_until_eol;
  605. end;
  606. end;
  607. Procedure HandleIllegalCharacter;
  608. begin
  609. writeln('Illegal character in line ',yylineno);
  610. writeln('"',yyline,'"');
  611. return(256);
  612. end;
  613. end.