pdecl.pas 22 KB

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