parser.pas 18 KB

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