parser.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit does the parsing process
  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. unit parser;
  19. {$i defines.inc}
  20. interface
  21. {$ifdef PREPROCWRITE}
  22. procedure preprocess(const filename:string);
  23. {$endif PREPROCWRITE}
  24. procedure compile(const filename:string);
  25. procedure initparser;
  26. procedure doneparser;
  27. implementation
  28. uses
  29. cutils,cclasses,
  30. globtype,version,tokens,systems,globals,verbose,
  31. symbase,symtable,symdef,symsym,fmodule,fppu,aasm,
  32. cgbase,
  33. script,gendef,
  34. {$ifdef BrowserLog}
  35. browlog,
  36. {$endif BrowserLog}
  37. {$ifdef UseExcept}
  38. tpexcept,
  39. {$endif UseExcept}
  40. {$ifdef GDB}
  41. gdb,
  42. {$endif GDB}
  43. comphook,
  44. scanner,scandir,
  45. pbase,ptype,pmodules,cresstr;
  46. procedure initparser;
  47. begin
  48. { ^M means a string or a char, because we don't parse a }
  49. { type declaration }
  50. ignore_equal:=false;
  51. { we didn't parse a object or class declaration }
  52. { and no function header }
  53. testcurobject:=0;
  54. { Symtable }
  55. aktprocsym:=nil;
  56. aktprocdef:=nil;
  57. current_module:=nil;
  58. compiled_module:=nil;
  59. procinfo:=nil;
  60. loaded_units:=TLinkedList.Create;
  61. usedunits:=TLinkedList.Create;
  62. { global switches }
  63. aktglobalswitches:=initglobalswitches;
  64. { initialize scanner }
  65. InitScanner;
  66. InitScannerDirectives;
  67. { scanner }
  68. c:=#0;
  69. pattern:='';
  70. orgpattern:='';
  71. current_scanner:=nil;
  72. { memory sizes }
  73. if heapsize=0 then
  74. heapsize:=target_info.heapsize;
  75. if stacksize=0 then
  76. stacksize:=target_info.stacksize;
  77. { open assembler response }
  78. GenerateAsmRes(outputexedir+'ppas');
  79. { open deffile }
  80. DefFile:=TDefFile.Create(outputexedir+inputfile+target_info.defext);
  81. { list of generated .o files, so the linker can remove them }
  82. SmartLinkOFiles:=TStringList.Create;
  83. end;
  84. procedure doneparser;
  85. begin
  86. { unload units }
  87. loaded_units.free;
  88. usedunits.free;
  89. { if there was an error in the scanner, the scanner is
  90. still assinged }
  91. if assigned(current_scanner) then
  92. begin
  93. current_scanner.free;
  94. current_scanner:=nil;
  95. end;
  96. { close scanner }
  97. DoneScanner;
  98. { close ppas,deffile }
  99. asmres.free;
  100. deffile.free;
  101. { free list of .o files }
  102. SmartLinkOFiles.Free;
  103. end;
  104. procedure default_macros;
  105. var
  106. hp : tstringlistitem;
  107. begin
  108. { commandline }
  109. hp:=tstringlistitem(initdefines.first);
  110. while assigned(hp) do
  111. begin
  112. current_scanner.def_macro(hp.str);
  113. hp:=tstringlistitem(hp.next);
  114. end;
  115. { set macros for version checking }
  116. current_scanner.set_macro('FPC_VERSION',version_nr);
  117. current_scanner.set_macro('FPC_RELEASE',release_nr);
  118. current_scanner.set_macro('FPC_PATCH',patch_nr);
  119. end;
  120. {$ifdef PREPROCWRITE}
  121. procedure preprocess(const filename:string);
  122. var
  123. i : longint;
  124. begin
  125. new(preprocfile,init('pre'));
  126. { default macros }
  127. current_scanner^.macros:=new(pdictionary,init);
  128. default_macros;
  129. { initialize a module }
  130. current_module:=new(pmodule,init(filename,false));
  131. main_module:=current_module;
  132. { startup scanner, and save in current_module }
  133. current_scanner:=new(pscannerfile,Init(filename));
  134. current_module.scanner:=current_scanner;
  135. { loop until EOF is found }
  136. repeat
  137. current_scanner^.readtoken;
  138. preprocfile^.AddSpace;
  139. case token of
  140. _ID :
  141. begin
  142. preprocfile^.Add(orgpattern);
  143. end;
  144. _REALNUMBER,
  145. _INTCONST :
  146. preprocfile^.Add(pattern);
  147. _CSTRING :
  148. begin
  149. i:=0;
  150. while (i<length(pattern)) do
  151. begin
  152. inc(i);
  153. if pattern[i]='''' then
  154. begin
  155. insert('''',pattern,i);
  156. inc(i);
  157. end;
  158. end;
  159. preprocfile^.Add(''''+pattern+'''');
  160. end;
  161. _CCHAR :
  162. begin
  163. case pattern[1] of
  164. #39 :
  165. pattern:='''''''';
  166. #0..#31,
  167. #128..#255 :
  168. begin
  169. str(ord(pattern[1]),pattern);
  170. pattern:='#'+pattern;
  171. end;
  172. else
  173. pattern:=''''+pattern[1]+'''';
  174. end;
  175. preprocfile^.Add(pattern);
  176. end;
  177. _EOF :
  178. break;
  179. else
  180. preprocfile^.Add(tokeninfo^[token].str)
  181. end;
  182. until false;
  183. { free scanner }
  184. dispose(current_scanner,done);
  185. current_scanner:=nil;
  186. { close }
  187. dispose(preprocfile,done);
  188. end;
  189. {$endif PREPROCWRITE}
  190. procedure compile(const filename:string);
  191. var
  192. { scanner }
  193. oldidtoken,
  194. oldtoken : ttoken;
  195. oldtokenpos : tfileposinfo;
  196. oldc : char;
  197. oldpattern,
  198. oldorgpattern : string;
  199. old_block_type : tblock_type;
  200. oldcurrent_scanner,prev_scanner,
  201. scanner : tscannerfile;
  202. { symtable }
  203. oldrefsymtable,
  204. olddefaultsymtablestack,
  205. oldsymtablestack : tsymtable;
  206. oldaktprocsym : tprocsym;
  207. oldaktprocdef : tprocdef;
  208. oldoverloaded_operators : toverloaded_operators;
  209. { cg }
  210. oldnextlabelnr : longint;
  211. oldparse_only : boolean;
  212. { asmlists }
  213. oldimports,
  214. oldexports,
  215. oldresource,
  216. oldrttilist,
  217. oldresourcestringlist,
  218. oldbsssegment,
  219. olddatasegment,
  220. oldcodesegment,
  221. oldexprasmlist,
  222. olddebuglist,
  223. oldwithdebuglist,
  224. oldconsts : taasmoutput;
  225. oldasmsymbollist : tdictionary;
  226. { resourcestrings }
  227. OldResourceStrings : tResourceStrings;
  228. { akt.. things }
  229. oldaktlocalswitches : tlocalswitches;
  230. oldaktmoduleswitches : tmoduleswitches;
  231. oldaktfilepos : tfileposinfo;
  232. oldaktpackenum,oldaktmaxfpuregisters : longint;
  233. oldaktalignment : talignmentinfo;
  234. oldaktoutputformat : tasm;
  235. oldaktspecificoptprocessor,
  236. oldaktoptprocessor : tprocessors;
  237. oldaktasmmode : tasmmode;
  238. oldaktinterfacetype: tinterfacetypes;
  239. oldaktmodeswitches : tmodeswitches;
  240. old_compiled_module : tmodule;
  241. oldaktdefproccall : tproccalloption;
  242. { will only be increased once we start parsing blocks in the }
  243. { implementation, so doesn't need to be saved/restored (JM) }
  244. { oldexceptblockcounter : integer; }
  245. oldstatement_level : integer;
  246. {$ifdef USEEXCEPT}
  247. {$ifndef Delphi}
  248. recoverpos : jmp_buf;
  249. oldrecoverpos : pjmp_buf;
  250. {$endif Delphi}
  251. {$endif useexcept}
  252. {$ifdef newcg}
  253. oldcg : pcg;
  254. {$endif newcg}
  255. {$ifdef GDB}
  256. store_dbx : plongint;
  257. {$endif GDB}
  258. begin
  259. inc(compile_level);
  260. parser_current_file:=filename;
  261. old_compiled_module:=compiled_module;
  262. { save symtable state }
  263. oldsymtablestack:=symtablestack;
  264. olddefaultsymtablestack:=defaultsymtablestack;
  265. oldrefsymtable:=refsymtable;
  266. oldaktprocsym:=aktprocsym;
  267. oldaktprocdef:=aktprocdef;
  268. oldaktdefproccall:=aktdefproccall;
  269. move(overloaded_operators,oldoverloaded_operators,sizeof(toverloaded_operators));
  270. { save scanner state }
  271. oldc:=c;
  272. oldpattern:=pattern;
  273. oldorgpattern:=orgpattern;
  274. oldtoken:=token;
  275. oldidtoken:=idtoken;
  276. old_block_type:=block_type;
  277. oldtokenpos:=akttokenpos;
  278. oldcurrent_scanner:=current_scanner;
  279. { save cg }
  280. oldnextlabelnr:=nextlabelnr;
  281. oldparse_only:=parse_only;
  282. { save assembler lists }
  283. olddatasegment:=datasegment;
  284. oldbsssegment:=bsssegment;
  285. oldcodesegment:=codesegment;
  286. olddebuglist:=debuglist;
  287. oldwithdebuglist:=withdebuglist;
  288. oldconsts:=consts;
  289. oldrttilist:=rttilist;
  290. oldexprasmlist:=exprasmlist;
  291. oldimports:=importssection;
  292. oldexports:=exportssection;
  293. oldresource:=resourcesection;
  294. oldresourcestringlist:=resourcestringlist;
  295. oldasmsymbollist:=asmsymbollist;
  296. OldResourceStrings:=ResourceStrings;
  297. { save akt... state }
  298. { handle the postponed case first }
  299. if localswitcheschanged then
  300. begin
  301. aktlocalswitches:=nextaktlocalswitches;
  302. localswitcheschanged:=false;
  303. end;
  304. oldaktlocalswitches:=aktlocalswitches;
  305. oldaktmoduleswitches:=aktmoduleswitches;
  306. oldaktalignment:=aktalignment;
  307. oldaktpackenum:=aktpackenum;
  308. oldaktmaxfpuregisters:=aktmaxfpuregisters;
  309. oldaktoutputformat:=aktoutputformat;
  310. oldaktoptprocessor:=aktoptprocessor;
  311. oldaktspecificoptprocessor:=aktspecificoptprocessor;
  312. oldaktasmmode:=aktasmmode;
  313. oldaktinterfacetype:=aktinterfacetype;
  314. oldaktfilepos:=aktfilepos;
  315. oldaktmodeswitches:=aktmodeswitches;
  316. oldstatement_level:=statement_level;
  317. { oldexceptblockcounter:=exceptblockcounter; }
  318. {$ifdef newcg}
  319. oldcg:=cg;
  320. {$endif newcg}
  321. {$ifdef GDB}
  322. store_dbx:=dbx_counter;
  323. dbx_counter:=nil;
  324. {$endif GDB}
  325. { show info }
  326. Message1(parser_i_compiling,filename);
  327. { reset symtable }
  328. symtablestack:=nil;
  329. defaultsymtablestack:=nil;
  330. systemunit:=nil;
  331. refsymtable:=nil;
  332. aktprocsym:=nil;
  333. aktdefproccall:=initdefproccall;
  334. registerdef:=true;
  335. statement_level:=0;
  336. aktexceptblock:=0;
  337. exceptblockcounter:=0;
  338. aktmaxfpuregisters:=-1;
  339. fillchar(overloaded_operators,sizeof(toverloaded_operators),0);
  340. { reset the unit or create a new program }
  341. if assigned(current_module) then
  342. begin
  343. {current_module.reset this is wrong !! }
  344. scanner:=tscannerfile(current_module.scanner);
  345. current_module.reset;
  346. tscannerfile(current_module.scanner):=scanner;
  347. end
  348. else
  349. begin
  350. current_module:=tppumodule.create(filename,'',false);
  351. main_module:=current_module;
  352. end;
  353. { a unit compiled at command line must be inside the loaded_unit list }
  354. if (compile_level=1) then
  355. loaded_units.insert(current_module);
  356. { Set the module to use for verbose }
  357. SetCompileModule(current_module);
  358. compiled_module:=current_module;
  359. current_module.in_compile:=true;
  360. { Load current state from the init values }
  361. aktlocalswitches:=initlocalswitches;
  362. aktmoduleswitches:=initmoduleswitches;
  363. aktmodeswitches:=initmodeswitches;
  364. {$IFDEF Testvarsets}
  365. aktsetalloc:=initsetalloc;
  366. {$ENDIF}
  367. aktalignment:=initalignment;
  368. aktpackenum:=initpackenum;
  369. aktoutputformat:=initoutputformat;
  370. set_target_asm(aktoutputformat);
  371. aktoptprocessor:=initoptprocessor;
  372. aktspecificoptprocessor:=initspecificoptprocessor;
  373. aktasmmode:=initasmmode;
  374. aktinterfacetype:=initinterfacetype;
  375. { startup scanner and load the first file }
  376. current_scanner:=tscannerfile.Create(filename);
  377. current_scanner.firstfile;
  378. { macros }
  379. default_macros;
  380. { read the first token }
  381. current_scanner.readtoken;
  382. prev_scanner:=tscannerfile(current_module.scanner);
  383. current_module.scanner:=current_scanner;
  384. { init code generator for a new module }
  385. codegen_newmodule;
  386. {$ifdef newcg}
  387. {$ifdef i386}
  388. cg:=new(pcg386,init);
  389. {$endif i386}
  390. {$ifdef alpha}
  391. cg:=new(pcgalpha,init);
  392. {$endif alpha}
  393. {$ifdef powerpc}
  394. cg:=new(pcgppc,init);
  395. {$endif powerpc}
  396. {$endif newcg}
  397. { If the compile level > 1 we get a nice "unit expected" error
  398. message if we are trying to use a program as unit.}
  399. {$ifdef USEEXCEPT}
  400. if setjmp(recoverpos)=0 then
  401. begin
  402. oldrecoverpos:=recoverpospointer;
  403. recoverpospointer:=@recoverpos;
  404. {$endif USEEXCEPT}
  405. if (token=_UNIT) or (compile_level>1) then
  406. begin
  407. current_module.is_unit:=true;
  408. proc_unit;
  409. end
  410. else
  411. proc_program(token=_LIBRARY);
  412. {$ifdef USEEXCEPT}
  413. recoverpospointer:=oldrecoverpos;
  414. end
  415. else
  416. begin
  417. recoverpospointer:=oldrecoverpos;
  418. longjump_used:=true;
  419. end;
  420. {$endif USEEXCEPT}
  421. { clear memory }
  422. {$ifdef Splitheap}
  423. if testsplit then
  424. begin
  425. { temp heap should be empty after that !!!}
  426. codegen_donemodule;
  427. Releasetempheap;
  428. end;
  429. {$endif Splitheap}
  430. { restore old state, close trees, > 0.99.5 has heapblocks, so
  431. it's the default to release the trees }
  432. codegen_donemodule;
  433. {$ifdef newcg}
  434. dispose(cg,done);
  435. {$endif newcg}
  436. { free ppu }
  437. if assigned(tppumodule(current_module).ppufile) then
  438. begin
  439. tppumodule(current_module).ppufile.free;
  440. tppumodule(current_module).ppufile:=nil;
  441. end;
  442. { free scanner }
  443. current_scanner.free;
  444. current_scanner:=nil;
  445. { restore previous scanner !! }
  446. current_module.scanner:=prev_scanner;
  447. if assigned(prev_scanner) then
  448. prev_scanner.invalid:=true;
  449. if (compile_level>1) then
  450. begin
  451. {$ifdef newcg}
  452. cg:=oldcg;
  453. {$endif newcg}
  454. {$ifdef GDB}
  455. dbx_counter:=store_dbx;
  456. {$endif GDB}
  457. { restore scanner }
  458. c:=oldc;
  459. pattern:=oldpattern;
  460. orgpattern:=oldorgpattern;
  461. token:=oldtoken;
  462. idtoken:=oldidtoken;
  463. akttokenpos:=oldtokenpos;
  464. block_type:=old_block_type;
  465. current_scanner:=oldcurrent_scanner;
  466. parser_current_file:=current_scanner.inputfile.name^;
  467. { restore cg }
  468. nextlabelnr:=oldnextlabelnr;
  469. parse_only:=oldparse_only;
  470. { restore asmlists }
  471. exprasmlist:=oldexprasmlist;
  472. datasegment:=olddatasegment;
  473. bsssegment:=oldbsssegment;
  474. codesegment:=oldcodesegment;
  475. consts:=oldconsts;
  476. debuglist:=olddebuglist;
  477. withdebuglist:=oldwithdebuglist;
  478. importssection:=oldimports;
  479. exportssection:=oldexports;
  480. resourcesection:=oldresource;
  481. rttilist:=oldrttilist;
  482. resourcestringlist:=oldresourcestringlist;
  483. asmsymbollist:=oldasmsymbollist;
  484. ResourceStrings:=OldResourceStrings;
  485. { restore symtable state }
  486. refsymtable:=oldrefsymtable;
  487. symtablestack:=oldsymtablestack;
  488. defaultsymtablestack:=olddefaultsymtablestack;
  489. aktdefproccall:=oldaktdefproccall;
  490. aktprocsym:=oldaktprocsym;
  491. aktprocdef:=oldaktprocdef;
  492. move(oldoverloaded_operators,overloaded_operators,sizeof(toverloaded_operators));
  493. aktlocalswitches:=oldaktlocalswitches;
  494. aktmoduleswitches:=oldaktmoduleswitches;
  495. aktalignment:=oldaktalignment;
  496. aktpackenum:=oldaktpackenum;
  497. aktmaxfpuregisters:=oldaktmaxfpuregisters;
  498. aktoutputformat:=oldaktoutputformat;
  499. set_target_asm(aktoutputformat);
  500. aktoptprocessor:=oldaktoptprocessor;
  501. aktspecificoptprocessor:=oldaktspecificoptprocessor;
  502. aktasmmode:=oldaktasmmode;
  503. aktinterfacetype:=oldaktinterfacetype;
  504. aktfilepos:=oldaktfilepos;
  505. aktmodeswitches:=oldaktmodeswitches;
  506. statement_level:=oldstatement_level;
  507. aktexceptblock:=0;
  508. exceptblockcounter:=0;
  509. end
  510. else
  511. begin
  512. parser_current_file:='';
  513. end;
  514. { Shut down things when the last file is compiled }
  515. if (compile_level=1) then
  516. begin
  517. { Close script }
  518. if (not AsmRes.Empty) then
  519. begin
  520. Message1(exec_i_closing_script,AsmRes.Fn);
  521. AsmRes.WriteToDisk;
  522. end;
  523. {$ifdef USEEXCEPT}
  524. if not longjump_used then
  525. {$endif USEEXCEPT}
  526. { do not create browsers on errors !! }
  527. if status.errorcount=0 then
  528. begin
  529. {$ifdef BrowserLog}
  530. { Write Browser Log }
  531. if (cs_browser_log in aktglobalswitches) and
  532. (cs_browser in aktmoduleswitches) then
  533. begin
  534. if browserlog.elements_to_list.empty then
  535. begin
  536. Message1(parser_i_writing_browser_log,browserlog.Fname);
  537. WriteBrowserLog;
  538. end
  539. else
  540. browserlog.list_elements;
  541. end;
  542. {$endif BrowserLog}
  543. { Write Browser Collections }
  544. do_extractsymbolinfo{$ifdef FPC}(){$endif};
  545. end;
  546. if current_module.in_second_compile then
  547. begin
  548. current_module.in_second_compile:=false;
  549. current_module.in_compile:=true;
  550. end
  551. else
  552. current_module.in_compile:=false;
  553. (* Obsolete code aktprocsym
  554. is disposed by the localsymtable disposal (PM)
  555. { Free last aktprocsym }
  556. if assigned(aktprocsym) and (aktprocsym.owner=nil) then
  557. begin
  558. { init parts are not needed in units !! }
  559. if current_module.is_unit then
  560. aktprocdef.forwarddef:=false;
  561. dispose(aktprocsym,done);
  562. end; *)
  563. end;
  564. dec(compile_level);
  565. compiled_module:=old_compiled_module;
  566. {$ifdef USEEXCEPT}
  567. if longjump_used then
  568. longjmp(recoverpospointer^,1);
  569. {$endif USEEXCEPT}
  570. end;
  571. end.
  572. {
  573. $Log$
  574. Revision 1.31 2002-05-14 19:34:43 peter
  575. * removed old logs and updated copyright year
  576. Revision 1.30 2002/04/21 18:57:23 peter
  577. * fixed memleaks when file can't be opened
  578. Revision 1.29 2002/04/20 21:32:24 carl
  579. + generic FPC_CHECKPOINTER
  580. + first parameter offset in stack now portable
  581. * rename some constants
  582. + move some cpu stuff to other units
  583. - remove unused constents
  584. * fix stacksize for some targets
  585. * fix generic size problems which depend now on EXTEND_SIZE constant
  586. Revision 1.28 2002/04/19 15:46:02 peter
  587. * mangledname rewrite, tprocdef.mangledname is now created dynamicly
  588. in most cases and not written to the ppu
  589. * add mangeledname_prefix() routine to generate the prefix of
  590. manglednames depending on the current procedure, object and module
  591. * removed static procprefix since the mangledname is now build only
  592. on demand from tprocdef.mangledname
  593. Revision 1.27 2002/01/29 19:43:11 peter
  594. * update target_asm according to outputformat
  595. }