pdecl.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Does declaration (but not type) parsing for Free Pascal
  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 pdecl;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. cobjects,symtable,node;
  23. function readconstant(const name:string;const filepos:tfileposinfo):pconstsym;
  24. procedure const_dec;
  25. procedure label_dec;
  26. procedure type_dec;
  27. procedure var_dec;
  28. procedure threadvar_dec;
  29. procedure resourcestring_dec;
  30. implementation
  31. uses
  32. { common }
  33. cutils,
  34. { global }
  35. globtype,globals,tokens,verbose,
  36. systems,cpuinfo,
  37. { aasm }
  38. aasm,
  39. { symtable }
  40. symconst,types,
  41. {$ifdef GDB}
  42. gdb,
  43. {$endif}
  44. { pass 1 }
  45. pass_1,htypechk,
  46. nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  47. { parser }
  48. scanner,
  49. pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,
  50. { codegen }
  51. {$ifdef newcg}
  52. cgbase
  53. {$else}
  54. hcodegen
  55. {$endif}
  56. ;
  57. function readconstant(const name:string;const filepos:tfileposinfo):pconstsym;
  58. var
  59. hp : pconstsym;
  60. p : tnode;
  61. ps : pconstset;
  62. pd : pbestreal;
  63. sp : pchar;
  64. storetokenpos : tfileposinfo;
  65. begin
  66. readconstant:=nil;
  67. if name='' then
  68. internalerror(9584582);
  69. hp:=nil;
  70. p:=comp_expr(true);
  71. do_firstpass(p);
  72. storetokenpos:=tokenpos;
  73. tokenpos:=filepos;
  74. case p.nodetype of
  75. ordconstn:
  76. begin
  77. if is_constintnode(p) then
  78. hp:=new(pconstsym,init_def(name,constint,tordconstnode(p).value,nil))
  79. else if is_constcharnode(p) then
  80. hp:=new(pconstsym,init_def(name,constchar,tordconstnode(p).value,nil))
  81. else if is_constboolnode(p) then
  82. hp:=new(pconstsym,init_def(name,constbool,tordconstnode(p).value,nil))
  83. else if p.resulttype^.deftype=enumdef then
  84. hp:=new(pconstsym,init_def(name,constord,tordconstnode(p).value,p.resulttype))
  85. else if p.resulttype^.deftype=pointerdef then
  86. hp:=new(pconstsym,init_def(name,constord,tordconstnode(p).value,p.resulttype))
  87. else internalerror(111);
  88. end;
  89. stringconstn:
  90. begin
  91. getmem(sp,tstringconstnode(p).len+1);
  92. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  93. hp:=new(pconstsym,init_string(name,conststring,sp,tstringconstnode(p).len));
  94. end;
  95. realconstn :
  96. begin
  97. new(pd);
  98. pd^:=trealconstnode(p).value_real;
  99. hp:=new(pconstsym,init(name,constreal,longint(pd)));
  100. end;
  101. setconstn :
  102. begin
  103. new(ps);
  104. ps^:=tsetconstnode(p).value_set^;
  105. hp:=new(pconstsym,init_def(name,constset,longint(ps),p.resulttype));
  106. end;
  107. pointerconstn :
  108. begin
  109. hp:=new(pconstsym,init_def(name,constpointer,tordconstnode(p).value,p.resulttype));
  110. end;
  111. niln :
  112. begin
  113. hp:=new(pconstsym,init_def(name,constnil,0,p.resulttype));
  114. end;
  115. else
  116. Message(cg_e_illegal_expression);
  117. end;
  118. tokenpos:=storetokenpos;
  119. p.free;
  120. readconstant:=hp;
  121. end;
  122. procedure const_dec;
  123. var
  124. name : stringid;
  125. tt : ttype;
  126. sym : psym;
  127. storetokenpos,filepos : tfileposinfo;
  128. old_block_type : tblock_type;
  129. skipequal : boolean;
  130. begin
  131. consume(_CONST);
  132. old_block_type:=block_type;
  133. block_type:=bt_const;
  134. repeat
  135. name:=pattern;
  136. filepos:=tokenpos;
  137. consume(_ID);
  138. case token of
  139. _EQUAL:
  140. begin
  141. consume(_EQUAL);
  142. sym:=readconstant(name,filepos);
  143. if assigned(sym) then
  144. symtablestack^.insert(sym);
  145. consume(_SEMICOLON);
  146. end;
  147. _COLON:
  148. begin
  149. { set the blocktype first so a consume also supports a
  150. caret, to support const s : ^string = nil }
  151. block_type:=bt_type;
  152. consume(_COLON);
  153. ignore_equal:=true;
  154. read_type(tt,'');
  155. ignore_equal:=false;
  156. block_type:=bt_const;
  157. skipequal:=false;
  158. { create symbol }
  159. storetokenpos:=tokenpos;
  160. tokenpos:=filepos;
  161. {$ifdef DELPHI_CONST_IN_RODATA}
  162. if m_delphi in aktmodeswitches then
  163. begin
  164. if assigned(readtypesym) then
  165. sym:=new(ptypedconstsym,initsym(name,readtypesym,true))
  166. else
  167. sym:=new(ptypedconstsym,init(name,def,true))
  168. end
  169. else
  170. {$endif DELPHI_CONST_IN_RODATA}
  171. begin
  172. sym:=new(ptypedconstsym,inittype(name,tt,false))
  173. end;
  174. tokenpos:=storetokenpos;
  175. symtablestack^.insert(sym);
  176. { procvar can have proc directives }
  177. if (tt.def^.deftype=procvardef) then
  178. begin
  179. { support p : procedure;stdcall=nil; }
  180. if (token=_SEMICOLON) then
  181. begin
  182. consume(_SEMICOLON);
  183. if is_proc_directive(token) then
  184. parse_var_proc_directives(sym)
  185. else
  186. begin
  187. Message(parser_e_proc_directive_expected);
  188. skipequal:=true;
  189. end;
  190. end
  191. else
  192. { support p : procedure stdcall=nil; }
  193. begin
  194. if is_proc_directive(token) then
  195. parse_var_proc_directives(sym);
  196. end;
  197. end;
  198. if not skipequal then
  199. begin
  200. { get init value }
  201. consume(_EQUAL);
  202. {$ifdef DELPHI_CONST_IN_RODATA}
  203. if m_delphi in aktmodeswitches then
  204. readtypedconst(tt.def,ptypedconstsym(sym),true)
  205. else
  206. {$endif DELPHI_CONST_IN_RODATA}
  207. readtypedconst(tt.def,ptypedconstsym(sym),false);
  208. consume(_SEMICOLON);
  209. end;
  210. end;
  211. else
  212. { generate an error }
  213. consume(_EQUAL);
  214. end;
  215. until token<>_ID;
  216. block_type:=old_block_type;
  217. end;
  218. procedure label_dec;
  219. var
  220. hl : pasmlabel;
  221. begin
  222. consume(_LABEL);
  223. if not(cs_support_goto in aktmoduleswitches) then
  224. Message(sym_e_goto_and_label_not_supported);
  225. repeat
  226. if not(token in [_ID,_INTCONST]) then
  227. consume(_ID)
  228. else
  229. begin
  230. if (cs_create_smart in aktmoduleswitches) then
  231. begin
  232. getdatalabel(hl);
  233. { we still want a warning if unused }
  234. hl^.refs:=0;
  235. end
  236. else
  237. getlabel(hl);
  238. symtablestack^.insert(new(plabelsym,init(pattern,hl)));
  239. consume(token);
  240. end;
  241. if token<>_SEMICOLON then consume(_COMMA);
  242. until not(token in [_ID,_INTCONST]);
  243. consume(_SEMICOLON);
  244. end;
  245. { search in symtablestack used, but not defined type }
  246. procedure resolve_type_forward(p : pnamedindexobject);
  247. var
  248. hpd,pd : pdef;
  249. stpos : tfileposinfo;
  250. again : boolean;
  251. begin
  252. { Check only typesyms or record/object fields }
  253. case psym(p)^.typ of
  254. typesym :
  255. pd:=ptypesym(p)^.restype.def;
  256. varsym :
  257. if (psym(p)^.owner^.symtabletype in [objectsymtable,recordsymtable]) then
  258. pd:=pvarsym(p)^.vartype.def
  259. else
  260. exit;
  261. else
  262. exit;
  263. end;
  264. repeat
  265. again:=false;
  266. case pd^.deftype of
  267. arraydef :
  268. begin
  269. { elementtype could also be defined using a forwarddef }
  270. pd:=parraydef(pd)^.elementtype.def;
  271. again:=true;
  272. end;
  273. pointerdef,
  274. classrefdef :
  275. begin
  276. { classrefdef inherits from pointerdef }
  277. hpd:=ppointerdef(pd)^.pointertype.def;
  278. { still a forward def ? }
  279. if hpd^.deftype=forwarddef then
  280. begin
  281. { try to resolve the forward }
  282. { get the correct position for it }
  283. stpos:=tokenpos;
  284. tokenpos:=pforwarddef(hpd)^.forwardpos;
  285. resolving_forward:=true;
  286. make_ref:=false;
  287. getsym(pforwarddef(hpd)^.tosymname,false);
  288. make_ref:=true;
  289. resolving_forward:=false;
  290. tokenpos:=stpos;
  291. { we don't need the forwarddef anymore, dispose it }
  292. dispose(hpd,done);
  293. { was a type sym found ? }
  294. if assigned(srsym) and
  295. (srsym^.typ=typesym) then
  296. begin
  297. ppointerdef(pd)^.pointertype.setsym(srsym);
  298. { avoid wrong unused warnings web bug 801 PM }
  299. inc(srsym^.refs);
  300. {$ifdef GDB}
  301. if (cs_debuginfo in aktmoduleswitches) and assigned(debuglist) and
  302. (psym(p)^.owner^.symtabletype in [globalsymtable,staticsymtable]) then
  303. begin
  304. ptypesym(p)^.isusedinstab := true;
  305. psym(p)^.concatstabto(debuglist);
  306. end;
  307. {$endif GDB}
  308. { we need a class type for classrefdef }
  309. if (pd^.deftype=classrefdef) and
  310. not((ptypesym(srsym)^.restype.def^.deftype=objectdef) and
  311. pobjectdef(ptypesym(srsym)^.restype.def)^.is_class) then
  312. Message1(type_e_class_type_expected,ptypesym(srsym)^.restype.def^.typename);
  313. end
  314. else
  315. begin
  316. MessagePos1(psym(p)^.fileinfo,sym_e_forward_type_not_resolved,p^.name);
  317. { try to recover }
  318. ppointerdef(pd)^.pointertype.def:=generrordef;
  319. end;
  320. end;
  321. end;
  322. recorddef :
  323. precorddef(pd)^.symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}resolve_type_forward);
  324. objectdef :
  325. begin
  326. if not(m_fpc in aktmodeswitches) and
  327. (oo_is_forward in pobjectdef(pd)^.objectoptions) then
  328. begin
  329. { only give an error as the implementation may follow in an
  330. other type block which is allowed by FPC modes }
  331. MessagePos1(psym(p)^.fileinfo,sym_e_forward_type_not_resolved,p^.name);
  332. end
  333. else
  334. begin
  335. { Check all fields of the object declaration, but don't
  336. check objectdefs in objects/records, because these
  337. can't exist (anonymous objects aren't allowed) }
  338. if not(psym(p)^.owner^.symtabletype in [objectsymtable,recordsymtable]) then
  339. pobjectdef(pd)^.symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}resolve_type_forward);
  340. end;
  341. end;
  342. end;
  343. until not again;
  344. end;
  345. { reads a type declaration to the symbol table }
  346. procedure type_dec;
  347. var
  348. typename,orgtypename : stringid;
  349. newtype : ptypesym;
  350. sym : psym;
  351. tt : ttype;
  352. defpos,storetokenpos : tfileposinfo;
  353. old_block_type : tblock_type;
  354. begin
  355. old_block_type:=block_type;
  356. block_type:=bt_type;
  357. consume(_TYPE);
  358. typecanbeforward:=true;
  359. repeat
  360. typename:=pattern;
  361. orgtypename:=orgpattern;
  362. defpos:=tokenpos;
  363. consume(_ID);
  364. consume(_EQUAL);
  365. { support 'ttype=type word' syntax }
  366. if token=_TYPE then
  367. Consume(_TYPE);
  368. { is the type already defined? }
  369. getsym(typename,false);
  370. sym:=srsym;
  371. newtype:=nil;
  372. { found a symbol with this name? }
  373. if assigned(sym) then
  374. begin
  375. if (sym^.typ=typesym) then
  376. begin
  377. if (token=_CLASS) and
  378. (assigned(ptypesym(sym)^.restype.def)) and
  379. (ptypesym(sym)^.restype.def^.deftype=objectdef) and
  380. pobjectdef(ptypesym(sym)^.restype.def)^.is_class and
  381. (oo_is_forward in pobjectdef(ptypesym(sym)^.restype.def)^.objectoptions) then
  382. begin
  383. { we can ignore the result }
  384. { the definition is modified }
  385. object_dec(orgtypename,pobjectdef(ptypesym(sym)^.restype.def));
  386. newtype:=ptypesym(sym);
  387. end;
  388. end;
  389. end;
  390. { no old type reused ? Then insert this new type }
  391. if not assigned(newtype) then
  392. begin
  393. { insert the new type first with an errordef, so that
  394. referencing the type before it's really set it
  395. will give an error (PFV) }
  396. tt.setdef(generrordef);
  397. storetokenpos:=tokenpos;
  398. newtype:=new(ptypesym,init(orgtypename,tt));
  399. symtablestack^.insert(newtype);
  400. tokenpos:=defpos;
  401. tokenpos:=storetokenpos;
  402. { read the type definition }
  403. read_type(tt,orgtypename);
  404. { update the definition of the type }
  405. newtype^.restype:=tt;
  406. if not assigned(tt.sym) then
  407. tt.sym:=newtype;
  408. if assigned(tt.def) and not assigned(tt.def^.typesym) then
  409. tt.def^.typesym:=newtype;
  410. end;
  411. if assigned(newtype^.restype.def) and
  412. (newtype^.restype.def^.deftype=procvardef) then
  413. begin
  414. if not is_proc_directive(token) then
  415. consume(_SEMICOLON);
  416. parse_var_proc_directives(psym(newtype));
  417. end
  418. else
  419. consume(_SEMICOLON);
  420. until token<>_ID;
  421. typecanbeforward:=false;
  422. symtablestack^.foreach({$ifdef FPCPROCVAR}@{$endif}resolve_type_forward);
  423. block_type:=old_block_type;
  424. end;
  425. procedure var_dec;
  426. { parses variable declarations and inserts them in }
  427. { the top symbol table of symtablestack }
  428. begin
  429. consume(_VAR);
  430. read_var_decs(false,false,false);
  431. end;
  432. procedure threadvar_dec;
  433. { parses thread variable declarations and inserts them in }
  434. { the top symbol table of symtablestack }
  435. begin
  436. consume(_THREADVAR);
  437. if not(symtablestack^.symtabletype in [staticsymtable,globalsymtable]) then
  438. message(parser_e_threadvars_only_sg);
  439. read_var_decs(false,false,true);
  440. end;
  441. procedure resourcestring_dec;
  442. var
  443. name : stringid;
  444. p : tnode;
  445. storetokenpos,filepos : tfileposinfo;
  446. old_block_type : tblock_type;
  447. sp : pchar;
  448. begin
  449. consume(_RESOURCESTRING);
  450. if not(symtablestack^.symtabletype in [staticsymtable,globalsymtable]) then
  451. message(parser_e_resourcestring_only_sg);
  452. old_block_type:=block_type;
  453. block_type:=bt_const;
  454. repeat
  455. name:=pattern;
  456. filepos:=tokenpos;
  457. consume(_ID);
  458. case token of
  459. _EQUAL:
  460. begin
  461. consume(_EQUAL);
  462. p:=comp_expr(true);
  463. do_firstpass(p);
  464. storetokenpos:=tokenpos;
  465. tokenpos:=filepos;
  466. case p.nodetype of
  467. ordconstn:
  468. begin
  469. if is_constcharnode(p) then
  470. begin
  471. getmem(sp,2);
  472. sp[0]:=chr(tordconstnode(p).value);
  473. sp[1]:=#0;
  474. symtablestack^.insert(new(pconstsym,init_string(name,constresourcestring,sp,1)));
  475. end
  476. else
  477. Message(cg_e_illegal_expression);
  478. end;
  479. stringconstn:
  480. begin
  481. getmem(sp,tstringconstnode(p).len+1);
  482. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  483. symtablestack^.insert(new(pconstsym,init_string(name,constresourcestring,sp,tstringconstnode(p).len)));
  484. end;
  485. else
  486. Message(cg_e_illegal_expression);
  487. end;
  488. tokenpos:=storetokenpos;
  489. consume(_SEMICOLON);
  490. p.free;
  491. end;
  492. else consume(_EQUAL);
  493. end;
  494. until token<>_ID;
  495. block_type:=old_block_type;
  496. end;
  497. end.
  498. {
  499. $Log$
  500. Revision 1.17 2000-10-14 10:14:51 peter
  501. * moehrendorf oct 2000 rewrite
  502. Revision 1.16 2000/09/24 21:19:50 peter
  503. * delphi compile fixes
  504. Revision 1.15 2000/09/24 15:06:21 peter
  505. * use defines.inc
  506. Revision 1.14 2000/09/11 17:00:23 florian
  507. + first implementation of Netware Module support, thanks to
  508. Armin Diehl ([email protected]) for providing the patches
  509. Revision 1.13 2000/08/27 20:19:39 peter
  510. * store strings with case in ppu, when an internal symbol is created
  511. a '$' is prefixed so it's not automatic uppercased
  512. Revision 1.12 2000/08/27 16:11:51 peter
  513. * moved some util functions from globals,cobjects to cutils
  514. * splitted files into finput,fmodule
  515. Revision 1.11 2000/08/20 15:01:17 peter
  516. * don't allow forward class in separate type blocks for delphi (merged)
  517. Revision 1.10 2000/08/17 09:17:19 pierre
  518. * fix go32v2 cycle problem
  519. Revision 1.9 2000/08/16 18:33:53 peter
  520. * splitted namedobjectitem.next into indexnext and listnext so it
  521. can be used in both lists
  522. * don't allow "word = word" type definitions (merged)
  523. Revision 1.8 2000/08/13 13:11:28 peter
  524. * put defaultpara values in parast and changed the name to
  525. 'def<Parameter name>'
  526. Revision 1.7 2000/08/13 08:42:59 peter
  527. * support absolute refering to funcret (merged)
  528. Revision 1.6 2000/08/02 19:49:59 peter
  529. * first things for default parameters
  530. Revision 1.5 2000/07/30 17:04:43 peter
  531. * merged fixes
  532. Revision 1.4 2000/07/14 05:11:49 michael
  533. + Patch to 1.1
  534. Revision 1.3 2000/07/13 12:08:26 michael
  535. + patched to 1.1.0 with former 1.09patch from peter
  536. Revision 1.2 2000/07/13 11:32:44 michael
  537. + removed logs
  538. }