parser.pas 21 KB

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