parser.pas 20 KB

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