parser.pas 21 KB

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