parser.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 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. {$ifdef tp}
  19. {$E+,N+,D+,F+}
  20. {$endif}
  21. unit parser;
  22. interface
  23. procedure compile(const filename:string;compile_system:boolean);
  24. procedure initparser;
  25. implementation
  26. uses
  27. systems,cobjects,globals,verbose,
  28. symtable,files,aasm,hcodegen,
  29. assemble,link,script,gendef,
  30. {$ifdef UseBrowser}
  31. browser,
  32. {$endif UseBrowser}
  33. scanner,pbase,pdecl,psystem,pmodules;
  34. procedure initparser;
  35. begin
  36. forwardsallowed:=false;
  37. { ^M means a string or a char, because we don't parse a }
  38. { type declaration }
  39. ignore_equal:=false;
  40. { we didn't parse a object or class declaration }
  41. { and no function header }
  42. testcurobject:=0;
  43. { a long time, this was forgotten }
  44. aktprocsym:=nil;
  45. current_module:=nil;
  46. loaded_units.init;
  47. usedunits.init;
  48. { memory sizes }
  49. if heapsize=0 then
  50. heapsize:=target_info.heapsize;
  51. if stacksize=0 then
  52. stacksize:=target_info.stacksize;
  53. end;
  54. procedure default_macros;
  55. var
  56. hp : pstring_item;
  57. begin
  58. { commandline }
  59. hp:=pstring_item(initdefines.first);
  60. while assigned(hp) do
  61. begin
  62. def_macro(hp^.str^);
  63. hp:=pstring_item(hp^.next);
  64. end;
  65. { set macros for version checking }
  66. set_macro('FPC_VERSION',version_nr);
  67. set_macro('FPC_RELEASE',release_nr);
  68. set_macro('FPC_PATCH',patch_nr);
  69. end;
  70. procedure compile(const filename:string;compile_system:boolean);
  71. var
  72. { some variables to save the compiler state }
  73. oldtoken : ttoken;
  74. oldtokenpos : tfileposinfo;
  75. oldpattern : stringid;
  76. oldpreprocstack : ppreprocstack;
  77. oldorgpattern,oldprocprefix : string;
  78. old_block_type : tblock_type;
  79. {$ifdef NEWINPUT}
  80. oldcurrent_scanner : pscannerfile;
  81. oldaktfilepos : tfileposinfo;
  82. oldlastlinepos : longint;
  83. {$else}
  84. oldcurrlinepos,
  85. oldlastlinepos,
  86. {$endif NEWINPUT}
  87. oldinputbuffer,
  88. oldinputpointer : pchar;
  89. olds_point,oldparse_only : boolean;
  90. oldc : char;
  91. oldcomment_level : word;
  92. oldnextlabelnr : longint;
  93. oldmacros,oldrefsymtable,oldsymtablestack : psymtable;
  94. oldimports,oldexports,oldresource,oldrttilist,
  95. oldbsssegment,olddatasegment,oldcodesegment,
  96. oldexprasmlist,olddebuglist,
  97. oldinternals,oldexternals,oldconsts : paasmoutput;
  98. oldswitches : tcswitches;
  99. oldpackrecords : word;
  100. oldoutputformat : tasm;
  101. oldoptprocessor : tprocessors;
  102. oldasmmode : tasmmode;
  103. label
  104. done;
  105. begin {compile}
  106. inc(compile_level);
  107. { save old state }
  108. { save symtable state }
  109. oldsymtablestack:=symtablestack;
  110. symtablestack:=nil;
  111. oldrefsymtable:=refsymtable;
  112. refsymtable:=nil;
  113. oldprocprefix:=procprefix;
  114. { a long time, this was only in init_parser
  115. but it should be reset to zero for each module }
  116. aktprocsym:=nil;
  117. { reset the unit or create a new program }
  118. if assigned(current_module) then
  119. begin
  120. current_module^.sourcefiles.done;
  121. current_module^.sourcefiles.init;
  122. current_module^.used_units.done;
  123. current_module^.used_units.init;
  124. end
  125. else
  126. begin
  127. current_module:=new(pmodule,init(filename,false));
  128. main_module:=current_module;
  129. end;
  130. { save scanner state }
  131. {$ifdef NEWINPUT}
  132. oldaktfilepos:=aktfilepos;
  133. oldcurrent_scanner:=current_scanner;
  134. {$else}
  135. oldcurrlinepos:=currlinepos;
  136. oldpreprocstack:=preprocstack;
  137. oldinputbuffer:=inputbuffer;
  138. oldinputpointer:=inputpointer;
  139. oldlastlinepos:=lastlinepos;
  140. olds_point:=s_point;
  141. oldcomment_level:=comment_level;
  142. {$endif}
  143. oldc:=c;
  144. oldpattern:=pattern;
  145. oldtoken:=token;
  146. oldtokenpos:=tokenpos;
  147. oldorgpattern:=orgpattern;
  148. old_block_type:=block_type;
  149. oldmacros:=macros;
  150. oldnextlabelnr:=nextlabelnr;
  151. oldparse_only:=parse_only;
  152. { save assembler lists }
  153. olddatasegment:=datasegment;
  154. oldbsssegment:=bsssegment;
  155. oldcodesegment:=codesegment;
  156. olddebuglist:=debuglist;
  157. oldexternals:=externals;
  158. oldinternals:=internals;
  159. oldconsts:=consts;
  160. oldrttilist:=rttilist;
  161. oldexprasmlist:=exprasmlist;
  162. oldimports:=importssection;
  163. oldexports:=exportssection;
  164. oldresource:=resourcesection;
  165. { save the current state }
  166. oldswitches:=aktswitches;
  167. oldpackrecords:=aktpackrecords;
  168. oldoutputformat:=aktoutputformat;
  169. oldoptprocessor:=aktoptprocessor;
  170. oldasmmode:=aktasmmode;
  171. { Load current state from the init values }
  172. aktswitches:=initswitches;
  173. aktpackrecords:=initpackrecords;
  174. aktoutputformat:=initoutputformat;
  175. aktoptprocessor:=initoptprocessor;
  176. aktasmmode:=initasmmode;
  177. { we need this to make the system unit }
  178. if compile_system then
  179. aktswitches:=aktswitches+[cs_compilesystem];
  180. { macros }
  181. macros:=new(psymtable,init(macrosymtable));
  182. macros^.name:=stringdup('Conditionals for '+filename);
  183. default_macros;
  184. { startup scanner }
  185. {$ifdef NEWINPUT}
  186. current_scanner:=new(pscannerfile,Init(filename));
  187. token:=current_scanner^.yylex;
  188. {$else}
  189. InitScanner(filename);
  190. token:=yylex;
  191. {$endif}
  192. Message1(parser_i_compiling,filename);
  193. { global switches are read, so further changes aren't allowed }
  194. current_module^.in_main:=true;
  195. { init code generator for a new module }
  196. codegen_newmodule;
  197. {$ifdef GDB}
  198. reset_gdb_info;
  199. {$endif GDB}
  200. { Handle things which need to be once }
  201. if (compile_level=1) then
  202. begin
  203. { open assembler response }
  204. AsmRes.Init('ppas');
  205. end;
  206. { load system unit always }
  207. loadsystemunit;
  208. registerdef:=true;
  209. make_ref:=true;
  210. { current return type is void }
  211. procinfo.retdef:=voiddef;
  212. { reset lexical level }
  213. lexlevel:=0;
  214. { parse source }
  215. if (token=_UNIT) or (compile_level>1) then
  216. begin
  217. current_module^.is_unit:=true;
  218. { If the compile level > 1 we get a nice "unit expected" error
  219. message if we are trying to use a program as unit.}
  220. proc_unit;
  221. if current_module^.compiled then
  222. goto done;
  223. end
  224. else
  225. begin
  226. proc_program(token=_LIBRARY);
  227. end;
  228. if status.errorcount=0 then
  229. begin
  230. GenerateAsm(filename);
  231. if (cs_smartlink in aktswitches) then
  232. begin
  233. Linker.SetLibName(current_module^.libfilename^);
  234. Linker.MakeStaticLibrary(SmartLinkPath(FileName),SmartLinkFilesCnt);
  235. end;
  236. { add the files for the linker from current_module, this must be
  237. after the makestaticlibrary, because it will add the library
  238. name (PFV) }
  239. addlinkerfiles(current_module);
  240. { Check linking => we are at first level in compile }
  241. if (compile_level=1) then
  242. begin
  243. if gendeffile then
  244. deffile.writefile;
  245. if (not current_module^.is_unit) then
  246. begin
  247. if (cs_no_linking in initswitches) then
  248. externlink:=true;
  249. if Linker.ExeName='' then
  250. Linker.SetExeName(FileName);
  251. Linker.MakeExecutable;
  252. end;
  253. end;
  254. end
  255. else
  256. Message1(unit_f_errors_in_unit,tostr(status.errorcount));
  257. done:
  258. { clear memory }
  259. {$ifdef Splitheap}
  260. if testsplit then
  261. begin
  262. { temp heap should be empty after that !!!}
  263. codegen_donemodule;
  264. Releasetempheap;
  265. end;
  266. {$endif Splitheap}
  267. { restore old state, close trees }
  268. if dispose_asm_lists then
  269. codegen_donemodule;
  270. {$ifdef GDB}
  271. reset_gdb_info;
  272. {$endif GDB}
  273. { restore symtable state }
  274. if (compile_level>1) then
  275. begin
  276. refsymtable:=oldrefsymtable;
  277. symtablestack:=oldsymtablestack;
  278. end;
  279. procprefix:=oldprocprefix;
  280. {$ifdef UseBrowser}
  281. { close input files, but dont remove if we use the browser ! }
  282. if cs_browser in initswitches then
  283. current_module^.sourcefiles.close_all
  284. else
  285. current_module^.sourcefiles.done;
  286. {$else UseBrowser}
  287. { close the inputfiles }
  288. current_module^.sourcefiles.done;
  289. {$endif not UseBrowser}
  290. if assigned(current_module^.ppufile) then
  291. begin
  292. dispose(current_module^.ppufile,done);
  293. current_module^.ppufile:=nil;
  294. end;
  295. { call donescanner before restoring preprocstack, because }
  296. { donescanner tests for a empty preprocstack }
  297. { and can also check for unused macros }
  298. {$ifdef NEWINPUT}
  299. dispose(current_scanner,done);
  300. {$else}
  301. donescanner(current_module^.compiled);
  302. {$endif}
  303. dispose(macros,done);
  304. { restore scanner }
  305. {$ifdef NEWINPUT}
  306. aktfilepos:=oldaktfilepos;
  307. current_scanner:=oldcurrent_scanner;
  308. {$else}
  309. preprocstack:=oldpreprocstack;
  310. inputbuffer:=oldinputbuffer;
  311. inputpointer:=oldinputpointer;
  312. lastlinepos:=oldlastlinepos;
  313. currlinepos:=oldcurrlinepos;
  314. s_point:=olds_point;
  315. comment_level:=oldcomment_level;
  316. {$endif}
  317. c:=oldc;
  318. pattern:=oldpattern;
  319. token:=oldtoken;
  320. tokenpos:=oldtokenpos;
  321. orgpattern:=oldorgpattern;
  322. block_type:=old_block_type;
  323. nextlabelnr:=oldnextlabelnr;
  324. parse_only:=oldparse_only;
  325. macros:=oldmacros;
  326. { restore asmlists }
  327. exprasmlist:=oldexprasmlist;
  328. datasegment:=olddatasegment;
  329. bsssegment:=oldbsssegment;
  330. codesegment:=oldcodesegment;
  331. consts:=oldconsts;
  332. debuglist:=olddebuglist;
  333. externals:=oldexternals;
  334. internals:=oldinternals;
  335. importssection:=oldimports;
  336. exportssection:=oldexports;
  337. resourcesection:=oldresource;
  338. rttilist:=oldrttilist;
  339. { restore current state }
  340. aktswitches:=oldswitches;
  341. aktpackrecords:=oldpackrecords;
  342. aktoutputformat:=oldoutputformat;
  343. aktoptprocessor:=oldoptprocessor;
  344. aktasmmode:=oldasmmode;
  345. { Shut down things when the last file is compiled }
  346. if (compile_level=1) then
  347. begin
  348. { Close script }
  349. if (not AsmRes.Empty) then
  350. begin
  351. Message1(exec_i_closing_script,AsmRes.Fn);
  352. AsmRes.WriteToDisk;
  353. end;
  354. {$ifdef UseBrowser}
  355. { Write Browser }
  356. if cs_browser in initswitches then
  357. begin
  358. Comment(V_Info,'Writing Browser '+Browse.Fname);
  359. Browse.CreateLog;
  360. write_browser_log;
  361. Browse.CloseLog;
  362. end;
  363. {$endif UseBrowser}
  364. end;
  365. dec(compile_level);
  366. end;
  367. end.
  368. {
  369. $Log$
  370. Revision 1.29 1998-07-07 11:19:59 peter
  371. + NEWINPUT for a better inputfile and scanner object
  372. Revision 1.28 1998/06/25 11:15:33 pierre
  373. * ppu files where not closed in newppu !!
  374. second compilation was impossible due to too many opened files
  375. (not visible in 'make cycle' as we remove all the ppu files)
  376. Revision 1.27 1998/06/17 14:10:15 peter
  377. * small os2 fixes
  378. * fixed interdependent units with newppu (remake3 under linux works now)
  379. Revision 1.26 1998/06/16 08:56:23 peter
  380. + targetcpu
  381. * cleaner pmodules for newppu
  382. Revision 1.25 1998/06/15 15:38:07 pierre
  383. * small bug in systems.pas corrected
  384. + operators in different units better hanlded
  385. Revision 1.24 1998/06/13 00:10:08 peter
  386. * working browser and newppu
  387. * some small fixes against crashes which occured in bp7 (but not in
  388. fpc?!)
  389. Revision 1.23 1998/06/08 22:59:48 peter
  390. * smartlinking works for win32
  391. * some defines to exclude some compiler parts
  392. Revision 1.22 1998/06/05 17:47:28 peter
  393. * some better uses clauses
  394. Revision 1.21 1998/06/04 23:51:49 peter
  395. * m68k compiles
  396. + .def file creation moved to gendef.pas so it could also be used
  397. for win32
  398. Revision 1.20 1998/06/03 22:48:55 peter
  399. + wordbool,longbool
  400. * rename bis,von -> high,low
  401. * moved some systemunit loading/creating to psystem.pas
  402. Revision 1.19 1998/05/27 19:45:04 peter
  403. * symtable.pas splitted into includefiles
  404. * symtable adapted for $ifdef NEWPPU
  405. Revision 1.18 1998/05/23 01:21:15 peter
  406. + aktasmmode, aktoptprocessor, aktoutputformat
  407. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  408. + $LIBNAME to set the library name where the unit will be put in
  409. * splitted cgi386 a bit (codeseg to large for bp7)
  410. * nasm, tasm works again. nasm moved to ag386nsm.pas
  411. Revision 1.17 1998/05/20 09:42:34 pierre
  412. + UseTokenInfo now default
  413. * unit in interface uses and implementation uses gives error now
  414. * only one error for unknown symbol (uses lastsymknown boolean)
  415. the problem came from the label code !
  416. + first inlined procedures and function work
  417. (warning there might be allowed cases were the result is still wrong !!)
  418. * UseBrower updated gives a global list of all position of all used symbols
  419. with switch -gb
  420. Revision 1.16 1998/05/12 10:47:00 peter
  421. * moved printstatus to verb_def
  422. + V_Normal which is between V_Error and V_Warning and doesn't have a
  423. prefix like error: warning: and is included in V_Default
  424. * fixed some messages
  425. * first time parameter scan is only for -v and -T
  426. - removed old style messages
  427. Revision 1.15 1998/05/11 13:07:54 peter
  428. + $ifdef NEWPPU for the new ppuformat
  429. + $define GDB not longer required
  430. * removed all warnings and stripped some log comments
  431. * no findfirst/findnext anymore to remove smartlink *.o files
  432. Revision 1.14 1998/05/06 18:36:53 peter
  433. * tai_section extended with code,data,bss sections and enumerated type
  434. * ident 'compiled by FPC' moved to pmodules
  435. * small fix for smartlink
  436. Revision 1.13 1998/05/06 08:38:42 pierre
  437. * better position info with UseTokenInfo
  438. UseTokenInfo greatly simplified
  439. + added check for changed tree after first time firstpass
  440. (if we could remove all the cases were it happen
  441. we could skip all firstpass if firstpasscount > 1)
  442. Only with ExtDebug
  443. Revision 1.12 1998/05/04 17:54:28 peter
  444. + smartlinking works (only case jumptable left todo)
  445. * redesign of systems.pas to support assemblers and linkers
  446. + Unitname is now also in the PPU-file, increased version to 14
  447. Revision 1.11 1998/05/01 16:38:45 florian
  448. * handling of private and protected fixed
  449. + change_keywords_to_tp implemented to remove
  450. keywords which aren't supported by tp
  451. * break and continue are now symbols of the system unit
  452. + widestring, longstring and ansistring type released
  453. Revision 1.10 1998/05/01 07:43:56 florian
  454. + basics for rtti implemented
  455. + switch $m (generate rtti for published sections)
  456. Revision 1.9 1998/04/30 15:59:40 pierre
  457. * GDB works again better :
  458. correct type info in one pass
  459. + UseTokenInfo for better source position
  460. * fixed one remaining bug in scanner for line counts
  461. * several little fixes
  462. Revision 1.8 1998/04/29 10:33:55 pierre
  463. + added some code for ansistring (not complete nor working yet)
  464. * corrected operator overloading
  465. * corrected nasm output
  466. + started inline procedures
  467. + added starstarn : use ** for exponentiation (^ gave problems)
  468. + started UseTokenInfo cond to get accurate positions
  469. Revision 1.7 1998/04/27 23:10:28 peter
  470. + new scanner
  471. * $makelib -> if smartlink
  472. * small filename fixes pmodule.setfilename
  473. * moved import from files.pas -> import.pas
  474. Revision 1.6 1998/04/21 10:16:48 peter
  475. * patches from strasbourg
  476. * objects is not used anymore in the fpc compiled version
  477. Revision 1.5 1998/04/10 14:41:43 peter
  478. * removed some Hints
  479. * small speed optimization for AsmLn
  480. Revision 1.4 1998/04/08 16:58:03 pierre
  481. * several bugfixes
  482. ADD ADC and AND are also sign extended
  483. nasm output OK (program still crashes at end
  484. and creates wrong assembler files !!)
  485. procsym types sym in tdef removed !!
  486. Revision 1.3 1998/04/07 22:45:04 florian
  487. * bug0092, bug0115 and bug0121 fixed
  488. + packed object/class/array
  489. }