parser.pas 18 KB

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