pdecl.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Does declaration (but not type) parsing for Free Pascal
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit pdecl;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { global }
  22. globtype,
  23. { symtable }
  24. symsym,
  25. { pass_1 }
  26. node;
  27. function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
  28. procedure const_dec;
  29. procedure consts_dec(in_structure: boolean);
  30. procedure label_dec;
  31. procedure type_dec;
  32. procedure types_dec(in_structure: boolean);
  33. procedure var_dec;
  34. procedure threadvar_dec;
  35. procedure property_dec(is_classpropery: boolean);
  36. procedure resourcestring_dec;
  37. implementation
  38. uses
  39. SysUtils,
  40. { common }
  41. cutils,cclasses,
  42. { global }
  43. globals,tokens,verbose,widestr,constexp,
  44. systems,
  45. { aasm }
  46. aasmbase,aasmtai,aasmdata,fmodule,
  47. { symtable }
  48. symconst,symbase,symtype,symdef,symtable,paramgr,defutil,
  49. { pass 1 }
  50. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nobj,
  51. { codegen }
  52. ncgutil,
  53. { parser }
  54. scanner,
  55. pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,
  56. { cpu-information }
  57. cpuinfo
  58. ;
  59. function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
  60. var
  61. hp : tconstsym;
  62. p : tnode;
  63. ps : pconstset;
  64. pd : pbestreal;
  65. pg : pguid;
  66. sp : pchar;
  67. pw : pcompilerwidestring;
  68. storetokenpos : tfileposinfo;
  69. begin
  70. readconstant:=nil;
  71. if orgname='' then
  72. internalerror(9584582);
  73. hp:=nil;
  74. p:=comp_expr(true,false);
  75. storetokenpos:=current_tokenpos;
  76. current_tokenpos:=filepos;
  77. case p.nodetype of
  78. ordconstn:
  79. begin
  80. if p.resultdef.typ=pointerdef then
  81. hp:=tconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value.uvalue,p.resultdef)
  82. else
  83. hp:=tconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resultdef);
  84. end;
  85. stringconstn:
  86. begin
  87. if is_wide_or_unicode_string(p.resultdef) then
  88. begin
  89. initwidestring(pw);
  90. copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
  91. hp:=tconstsym.create_wstring(orgname,constwstring,pw);
  92. end
  93. else
  94. begin
  95. getmem(sp,tstringconstnode(p).len+1);
  96. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  97. hp:=tconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len);
  98. end;
  99. end;
  100. realconstn :
  101. begin
  102. new(pd);
  103. pd^:=trealconstnode(p).value_real;
  104. hp:=tconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
  105. end;
  106. setconstn :
  107. begin
  108. new(ps);
  109. ps^:=tsetconstnode(p).value_set^;
  110. hp:=tconstsym.create_ptr(orgname,constset,ps,p.resultdef);
  111. end;
  112. pointerconstn :
  113. begin
  114. hp:=tconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
  115. end;
  116. niln :
  117. begin
  118. hp:=tconstsym.create_ord(orgname,constnil,0,p.resultdef);
  119. end;
  120. typen :
  121. begin
  122. if is_interface(p.resultdef) then
  123. begin
  124. if assigned(tobjectdef(p.resultdef).iidguid) then
  125. begin
  126. new(pg);
  127. pg^:=tobjectdef(p.resultdef).iidguid^;
  128. hp:=tconstsym.create_ptr(orgname,constguid,pg,p.resultdef);
  129. end
  130. else
  131. Message1(parser_e_interface_has_no_guid,tobjectdef(p.resultdef).objrealname^);
  132. end
  133. else
  134. Message(parser_e_illegal_expression);
  135. end;
  136. else
  137. Message(parser_e_illegal_expression);
  138. end;
  139. current_tokenpos:=storetokenpos;
  140. p.free;
  141. readconstant:=hp;
  142. end;
  143. procedure const_dec;
  144. begin
  145. consume(_CONST);
  146. consts_dec(false);
  147. end;
  148. procedure consts_dec(in_structure: boolean);
  149. var
  150. orgname : TIDString;
  151. hdef : tdef;
  152. sym, tmp : tsym;
  153. dummysymoptions : tsymoptions;
  154. deprecatedmsg : pshortstring;
  155. storetokenpos,filepos : tfileposinfo;
  156. old_block_type : tblock_type;
  157. skipequal : boolean;
  158. tclist : tasmlist;
  159. varspez : tvarspez;
  160. static_name : string;
  161. sl : tpropaccesslist;
  162. begin
  163. old_block_type:=block_type;
  164. block_type:=bt_const;
  165. repeat
  166. orgname:=orgpattern;
  167. filepos:=current_tokenpos;
  168. consume(_ID);
  169. case token of
  170. _EQ:
  171. begin
  172. consume(_EQ);
  173. sym:=readconstant(orgname,filepos);
  174. { Support hint directives }
  175. dummysymoptions:=[];
  176. deprecatedmsg:=nil;
  177. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  178. if assigned(sym) then
  179. begin
  180. sym.symoptions:=sym.symoptions+dummysymoptions;
  181. sym.deprecatedmsg:=deprecatedmsg;
  182. sym.visibility:=symtablestack.top.currentvisibility;
  183. symtablestack.top.insert(sym);
  184. end
  185. else
  186. stringdispose(deprecatedmsg);
  187. consume(_SEMICOLON);
  188. end;
  189. _COLON:
  190. begin
  191. { set the blocktype first so a consume also supports a
  192. caret, to support const s : ^string = nil }
  193. block_type:=bt_const_type;
  194. consume(_COLON);
  195. read_anon_type(hdef,false);
  196. block_type:=bt_const;
  197. skipequal:=false;
  198. { create symbol }
  199. storetokenpos:=current_tokenpos;
  200. current_tokenpos:=filepos;
  201. if not (cs_typed_const_writable in current_settings.localswitches) then
  202. varspez:=vs_const
  203. else
  204. varspez:=vs_value;
  205. { if we are dealing with structure const then we need to handle it as a
  206. structure static variable: create a symbol in unit symtable and a reference
  207. to it from the structure or linking will fail }
  208. if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
  209. begin
  210. { generate the symbol which reserves the space }
  211. static_name:=lower(generate_nested_name(symtablestack.top,'_'))+'_'+orgname;
  212. sym:=tstaticvarsym.create('$_static_'+static_name,varspez,hdef,[]);
  213. include(sym.symoptions,sp_internal);
  214. tabstractrecordsymtable(symtablestack.top).get_unit_symtable.insert(sym);
  215. { generate the symbol for the access }
  216. sl:=tpropaccesslist.create;
  217. sl.addsym(sl_load,sym);
  218. tmp:=tabsolutevarsym.create_ref(orgname,hdef,sl);
  219. tmp.visibility:=symtablestack.top.currentvisibility;
  220. symtablestack.top.insert(tmp);
  221. end
  222. else
  223. begin
  224. sym:=tstaticvarsym.create(orgname,varspez,hdef,[]);
  225. sym.visibility:=symtablestack.top.currentvisibility;
  226. symtablestack.top.insert(sym);
  227. end;
  228. current_tokenpos:=storetokenpos;
  229. { procvar can have proc directives, but not type references }
  230. if (hdef.typ=procvardef) and
  231. (hdef.typesym=nil) then
  232. begin
  233. { support p : procedure;stdcall=nil; }
  234. if try_to_consume(_SEMICOLON) then
  235. begin
  236. if check_proc_directive(true) then
  237. parse_var_proc_directives(sym)
  238. else
  239. begin
  240. Message(parser_e_proc_directive_expected);
  241. skipequal:=true;
  242. end;
  243. end
  244. else
  245. { support p : procedure stdcall=nil; }
  246. begin
  247. if check_proc_directive(true) then
  248. parse_var_proc_directives(sym);
  249. end;
  250. { add default calling convention }
  251. handle_calling_convention(tabstractprocdef(hdef));
  252. end;
  253. if not skipequal then
  254. begin
  255. { get init value }
  256. consume(_EQ);
  257. if (cs_typed_const_writable in current_settings.localswitches) then
  258. tclist:=current_asmdata.asmlists[al_rotypedconsts]
  259. else
  260. tclist:=current_asmdata.asmlists[al_typedconsts];
  261. read_typed_const(tclist,tstaticvarsym(sym),in_structure);
  262. end;
  263. end;
  264. else
  265. { generate an error }
  266. consume(_EQ);
  267. end;
  268. until (token<>_ID)or(in_structure and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
  269. block_type:=old_block_type;
  270. end;
  271. procedure label_dec;
  272. var
  273. labelsym : tlabelsym;
  274. begin
  275. consume(_LABEL);
  276. if not(cs_support_goto in current_settings.moduleswitches) then
  277. Message(sym_e_goto_and_label_not_supported);
  278. repeat
  279. if not(token in [_ID,_INTCONST]) then
  280. consume(_ID)
  281. else
  282. begin
  283. if token=_ID then
  284. labelsym:=tlabelsym.create(orgpattern)
  285. else
  286. labelsym:=tlabelsym.create(pattern);
  287. symtablestack.top.insert(labelsym);
  288. if m_non_local_goto in current_settings.modeswitches then
  289. begin
  290. if symtablestack.top.symtabletype=localsymtable then
  291. begin
  292. labelsym.jumpbuf:=tlocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  293. symtablestack.top.insert(labelsym.jumpbuf);
  294. end
  295. else
  296. begin
  297. labelsym.jumpbuf:=tstaticvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  298. symtablestack.top.insert(labelsym.jumpbuf);
  299. insertbssdata(tstaticvarsym(labelsym.jumpbuf));
  300. end;
  301. include(labelsym.jumpbuf.symoptions,sp_internal);
  302. { the buffer will be setup later, but avoid a hint }
  303. tabstractvarsym(labelsym.jumpbuf).varstate:=vs_written;
  304. end;
  305. consume(token);
  306. end;
  307. if token<>_SEMICOLON then consume(_COMMA);
  308. until not(token in [_ID,_INTCONST]);
  309. consume(_SEMICOLON);
  310. end;
  311. procedure types_dec(in_structure: boolean);
  312. procedure finalize_objc_class_or_protocol_external_status(od: tobjectdef);
  313. begin
  314. if [oo_is_external,oo_is_forward] <= od.objectoptions then
  315. begin
  316. { formal definition: x = objcclass external; }
  317. exclude(od.objectoptions,oo_is_forward);
  318. include(od.objectoptions,oo_is_formal);
  319. end;
  320. end;
  321. function parse_generic_parameters:TFPObjectList;
  322. var
  323. generictype : ttypesym;
  324. begin
  325. result:=TFPObjectList.Create(false);
  326. repeat
  327. if token=_ID then
  328. begin
  329. generictype:=ttypesym.create(orgpattern,cundefinedtype);
  330. include(generictype.symoptions,sp_generic_para);
  331. result.add(generictype);
  332. end;
  333. consume(_ID);
  334. until not try_to_consume(_COMMA) ;
  335. end;
  336. var
  337. typename,orgtypename : TIDString;
  338. newtype : ttypesym;
  339. sym : tsym;
  340. srsymtable : TSymtable;
  341. hdef : tdef;
  342. defpos,storetokenpos : tfileposinfo;
  343. old_block_type : tblock_type;
  344. old_checkforwarddefs: TFPObjectList;
  345. objecttype : tobjecttyp;
  346. isgeneric,
  347. isunique,
  348. istyperenaming : boolean;
  349. generictypelist : TFPObjectList;
  350. generictokenbuf : tdynamicarray;
  351. vmtbuilder : TVMTBuilder;
  352. begin
  353. old_block_type:=block_type;
  354. { save unit container of forward declarations -
  355. we can be inside nested class type block }
  356. old_checkforwarddefs:=current_module.checkforwarddefs;
  357. current_module.checkforwarddefs:=TFPObjectList.Create(false);
  358. block_type:=bt_type;
  359. repeat
  360. defpos:=current_tokenpos;
  361. istyperenaming:=false;
  362. generictypelist:=nil;
  363. generictokenbuf:=nil;
  364. { fpc generic declaration? }
  365. isgeneric:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
  366. typename:=pattern;
  367. orgtypename:=orgpattern;
  368. consume(_ID);
  369. { delphi generic declaration? }
  370. if (m_delphi in current_settings.modeswitches) then
  371. isgeneric:=token=_LSHARPBRACKET;
  372. { Generic type declaration? }
  373. if isgeneric then
  374. begin
  375. if assigned(current_genericdef) then
  376. Message(parser_f_no_generic_inside_generic);
  377. consume(_LSHARPBRACKET);
  378. generictypelist:=parse_generic_parameters;
  379. consume(_RSHARPBRACKET);
  380. end;
  381. consume(_EQ);
  382. { support 'ttype=type word' syntax }
  383. isunique:=try_to_consume(_TYPE);
  384. { MacPas object model is more like Delphi's than like TP's, but }
  385. { uses the object keyword instead of class }
  386. if (m_mac in current_settings.modeswitches) and
  387. (token = _OBJECT) then
  388. token := _CLASS;
  389. { Start recording a generic template }
  390. if assigned(generictypelist) then
  391. begin
  392. generictokenbuf:=tdynamicarray.create(256);
  393. current_scanner.startrecordtokens(generictokenbuf);
  394. end;
  395. { is the type already defined? }
  396. searchsym(typename,sym,srsymtable);
  397. newtype:=nil;
  398. { found a symbol with this name? }
  399. if assigned(sym) then
  400. begin
  401. if (sym.typ=typesym) then
  402. begin
  403. if ((token=_CLASS) or
  404. (token=_INTERFACE) or
  405. (token=_DISPINTERFACE) or
  406. (token=_OBJCCLASS) or
  407. (token=_OBJCPROTOCOL) or
  408. (token=_OBJCCATEGORY)) and
  409. (assigned(ttypesym(sym).typedef)) and
  410. is_implicit_pointer_object_type(ttypesym(sym).typedef) and
  411. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  412. begin
  413. case token of
  414. _CLASS :
  415. objecttype:=odt_class;
  416. _INTERFACE :
  417. if current_settings.interfacetype=it_interfacecom then
  418. objecttype:=odt_interfacecom
  419. else
  420. objecttype:=odt_interfacecorba;
  421. _DISPINTERFACE :
  422. objecttype:=odt_dispinterface;
  423. _OBJCCLASS,
  424. _OBJCCATEGORY :
  425. objecttype:=odt_objcclass;
  426. _OBJCPROTOCOL :
  427. objecttype:=odt_objcprotocol;
  428. else
  429. internalerror(200811072);
  430. end;
  431. consume(token);
  432. { we can ignore the result, the definition is modified }
  433. object_dec(objecttype,orgtypename,nil,nil,tobjectdef(ttypesym(sym).typedef));
  434. newtype:=ttypesym(sym);
  435. hdef:=newtype.typedef;
  436. end
  437. else
  438. message1(parser_h_type_redef,orgtypename);
  439. end;
  440. end;
  441. { no old type reused ? Then insert this new type }
  442. if not assigned(newtype) then
  443. begin
  444. { insert the new type first with an errordef, so that
  445. referencing the type before it's really set it
  446. will give an error (PFV) }
  447. hdef:=generrordef;
  448. storetokenpos:=current_tokenpos;
  449. newtype:=ttypesym.create(orgtypename,hdef);
  450. newtype.visibility:=symtablestack.top.currentvisibility;
  451. symtablestack.top.insert(newtype);
  452. current_tokenpos:=defpos;
  453. current_tokenpos:=storetokenpos;
  454. { read the type definition }
  455. read_named_type(hdef,orgtypename,nil,generictypelist,false);
  456. { update the definition of the type }
  457. if assigned(hdef) then
  458. begin
  459. if assigned(hdef.typesym) then
  460. istyperenaming:=true;
  461. if isunique then
  462. begin
  463. if is_objc_class_or_protocol(hdef) then
  464. Message(parser_e_no_objc_unique);
  465. hdef:=tstoreddef(hdef).getcopy;
  466. { fix name, it is used e.g. for tables }
  467. if is_class_or_interface_or_dispinterface(hdef) then
  468. with tobjectdef(hdef) do
  469. begin
  470. stringdispose(objname);
  471. stringdispose(objrealname);
  472. objrealname:=stringdup(orgtypename);
  473. objname:=stringdup(upper(orgtypename));
  474. end;
  475. include(hdef.defoptions,df_unique);
  476. if (hdef.typ in [pointerdef,classrefdef]) and
  477. (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
  478. current_module.checkforwarddefs.add(hdef);
  479. end;
  480. if not assigned(hdef.typesym) then
  481. hdef.typesym:=newtype;
  482. end;
  483. newtype.typedef:=hdef;
  484. { KAZ: handle TGUID declaration in system unit }
  485. if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
  486. (typename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
  487. assigned(hdef) and (hdef.typ=recorddef) and (hdef.size=16) then
  488. rec_tguid:=trecorddef(hdef);
  489. end;
  490. if assigned(hdef) then
  491. begin
  492. case hdef.typ of
  493. pointerdef :
  494. begin
  495. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  496. consume(_SEMICOLON);
  497. if try_to_consume(_FAR) then
  498. begin
  499. tpointerdef(hdef).is_far:=true;
  500. consume(_SEMICOLON);
  501. end;
  502. end;
  503. procvardef :
  504. begin
  505. { in case of type renaming, don't parse proc directives }
  506. if istyperenaming then
  507. begin
  508. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  509. consume(_SEMICOLON);
  510. end
  511. else
  512. begin
  513. if not check_proc_directive(true) then
  514. begin
  515. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  516. consume(_SEMICOLON);
  517. end;
  518. parse_var_proc_directives(tsym(newtype));
  519. handle_calling_convention(tprocvardef(hdef));
  520. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  521. consume(_SEMICOLON);
  522. end;
  523. end;
  524. objectdef :
  525. begin
  526. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  527. consume(_SEMICOLON);
  528. { change a forward and external objcclass declaration into
  529. formal external definition, so the compiler does not
  530. expect an real definition later }
  531. if is_objc_class_or_protocol(hdef) then
  532. finalize_objc_class_or_protocol_external_status(tobjectdef(hdef));
  533. { Build VMT indexes, skip for type renaming and forward classes }
  534. if (hdef.typesym=newtype) and
  535. not(oo_is_forward in tobjectdef(hdef).objectoptions) and
  536. not(df_generic in hdef.defoptions) then
  537. begin
  538. vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
  539. vmtbuilder.generate_vmt;
  540. vmtbuilder.free;
  541. end;
  542. { In case of an objcclass, verify that all methods have a message
  543. name set. We only check this now, because message names can be set
  544. during the protocol (interface) mapping. At the same time, set the
  545. mangled names (these depend on the "external" name of the class),
  546. and mark private fields of external classes as "used" (to avoid
  547. bogus notes about them being unused)
  548. }
  549. { watch out for crashes in case of errors }
  550. if is_objc_class_or_protocol(hdef) and
  551. (not is_objccategory(hdef) or
  552. assigned(tobjectdef(hdef).childof)) then
  553. tobjectdef(hdef).finish_objc_data;
  554. if is_cppclass(hdef) then
  555. tobjectdef(hdef).finish_cpp_data;
  556. end;
  557. recorddef :
  558. begin
  559. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  560. consume(_SEMICOLON);
  561. end;
  562. else
  563. begin
  564. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  565. consume(_SEMICOLON);
  566. end;
  567. end;
  568. end;
  569. if isgeneric and not(hdef.typ in [objectdef,recorddef,arraydef]) then
  570. message(parser_e_cant_create_generics_of_this_type);
  571. { Stop recording a generic template }
  572. if assigned(generictypelist) then
  573. begin
  574. current_scanner.stoprecordtokens;
  575. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  576. { Generic is never a type renaming }
  577. hdef.typesym:=newtype;
  578. end;
  579. if assigned(generictypelist) then
  580. generictypelist.free;
  581. until (token<>_ID)or(in_structure and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
  582. { resolve type block forward declarations and restore a unit
  583. container for them }
  584. resolve_forward_types;
  585. current_module.checkforwarddefs.free;
  586. current_module.checkforwarddefs:=old_checkforwarddefs;
  587. block_type:=old_block_type;
  588. end;
  589. { reads a type declaration to the symbol table }
  590. procedure type_dec;
  591. begin
  592. consume(_TYPE);
  593. types_dec(false);
  594. end;
  595. procedure var_dec;
  596. { parses variable declarations and inserts them in }
  597. { the top symbol table of symtablestack }
  598. begin
  599. consume(_VAR);
  600. read_var_decls([]);
  601. end;
  602. procedure property_dec(is_classpropery: boolean);
  603. var
  604. old_block_type : tblock_type;
  605. begin
  606. consume(_PROPERTY);
  607. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  608. message(parser_e_resourcestring_only_sg);
  609. old_block_type:=block_type;
  610. block_type:=bt_const;
  611. repeat
  612. read_property_dec(is_classpropery, nil);
  613. consume(_SEMICOLON);
  614. until token<>_ID;
  615. block_type:=old_block_type;
  616. end;
  617. procedure threadvar_dec;
  618. { parses thread variable declarations and inserts them in }
  619. { the top symbol table of symtablestack }
  620. begin
  621. consume(_THREADVAR);
  622. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  623. message(parser_e_threadvars_only_sg);
  624. read_var_decls([vd_threadvar]);
  625. end;
  626. procedure resourcestring_dec;
  627. var
  628. orgname : TIDString;
  629. p : tnode;
  630. dummysymoptions : tsymoptions;
  631. deprecatedmsg : pshortstring;
  632. storetokenpos,filepos : tfileposinfo;
  633. old_block_type : tblock_type;
  634. sp : pchar;
  635. sym : tsym;
  636. begin
  637. consume(_RESOURCESTRING);
  638. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  639. message(parser_e_resourcestring_only_sg);
  640. old_block_type:=block_type;
  641. block_type:=bt_const;
  642. repeat
  643. orgname:=orgpattern;
  644. filepos:=current_tokenpos;
  645. consume(_ID);
  646. case token of
  647. _EQ:
  648. begin
  649. consume(_EQ);
  650. p:=comp_expr(true,false);
  651. storetokenpos:=current_tokenpos;
  652. current_tokenpos:=filepos;
  653. sym:=nil;
  654. case p.nodetype of
  655. ordconstn:
  656. begin
  657. if is_constcharnode(p) then
  658. begin
  659. getmem(sp,2);
  660. sp[0]:=chr(tordconstnode(p).value.svalue);
  661. sp[1]:=#0;
  662. sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
  663. end
  664. else
  665. Message(parser_e_illegal_expression);
  666. end;
  667. stringconstn:
  668. with Tstringconstnode(p) do
  669. begin
  670. getmem(sp,len+1);
  671. move(value_str^,sp^,len+1);
  672. sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
  673. end;
  674. else
  675. Message(parser_e_illegal_expression);
  676. end;
  677. current_tokenpos:=storetokenpos;
  678. { Support hint directives }
  679. dummysymoptions:=[];
  680. deprecatedmsg:=nil;
  681. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  682. if assigned(sym) then
  683. begin
  684. sym.symoptions:=sym.symoptions+dummysymoptions;
  685. sym.deprecatedmsg:=deprecatedmsg;
  686. symtablestack.top.insert(sym);
  687. end
  688. else
  689. stringdispose(deprecatedmsg);
  690. consume(_SEMICOLON);
  691. p.free;
  692. end;
  693. else consume(_EQ);
  694. end;
  695. until token<>_ID;
  696. block_type:=old_block_type;
  697. end;
  698. end.