pdecl.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  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_class: boolean);
  30. procedure label_dec;
  31. procedure type_dec;
  32. procedure types_dec(in_class: 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);
  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_class: boolean);
  149. var
  150. orgname : TIDString;
  151. hdef : tdef;
  152. sym : 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. begin
  161. old_block_type:=block_type;
  162. block_type:=bt_const;
  163. repeat
  164. orgname:=orgpattern;
  165. filepos:=current_tokenpos;
  166. consume(_ID);
  167. case token of
  168. _EQUAL:
  169. begin
  170. consume(_EQUAL);
  171. sym:=readconstant(orgname,filepos);
  172. { Support hint directives }
  173. dummysymoptions:=[];
  174. deprecatedmsg:=nil;
  175. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  176. if assigned(sym) then
  177. begin
  178. sym.symoptions:=sym.symoptions+dummysymoptions;
  179. sym.deprecatedmsg:=deprecatedmsg;
  180. sym.visibility:=symtablestack.top.currentvisibility;
  181. symtablestack.top.insert(sym);
  182. end
  183. else
  184. stringdispose(deprecatedmsg);
  185. consume(_SEMICOLON);
  186. end;
  187. _COLON:
  188. begin
  189. { set the blocktype first so a consume also supports a
  190. caret, to support const s : ^string = nil }
  191. block_type:=bt_const_type;
  192. consume(_COLON);
  193. read_anon_type(hdef,false);
  194. block_type:=bt_const;
  195. skipequal:=false;
  196. { create symbol }
  197. storetokenpos:=current_tokenpos;
  198. current_tokenpos:=filepos;
  199. if not (cs_typed_const_writable in current_settings.localswitches) then
  200. varspez:=vs_const
  201. else
  202. varspez:=vs_value;
  203. sym:=tstaticvarsym.create(orgname,varspez,hdef,[]);
  204. sym.visibility:=symtablestack.top.currentvisibility;
  205. current_tokenpos:=storetokenpos;
  206. symtablestack.top.insert(sym);
  207. { procvar can have proc directives, but not type references }
  208. if (hdef.typ=procvardef) and
  209. (hdef.typesym=nil) then
  210. begin
  211. { support p : procedure;stdcall=nil; }
  212. if try_to_consume(_SEMICOLON) then
  213. begin
  214. if check_proc_directive(true) then
  215. parse_var_proc_directives(sym)
  216. else
  217. begin
  218. Message(parser_e_proc_directive_expected);
  219. skipequal:=true;
  220. end;
  221. end
  222. else
  223. { support p : procedure stdcall=nil; }
  224. begin
  225. if check_proc_directive(true) then
  226. parse_var_proc_directives(sym);
  227. end;
  228. { add default calling convention }
  229. handle_calling_convention(tabstractprocdef(hdef));
  230. end;
  231. if not skipequal then
  232. begin
  233. { get init value }
  234. consume(_EQUAL);
  235. if (cs_typed_const_writable in current_settings.localswitches) then
  236. tclist:=current_asmdata.asmlists[al_rotypedconsts]
  237. else
  238. tclist:=current_asmdata.asmlists[al_typedconsts];
  239. read_typed_const(tclist,tstaticvarsym(sym));
  240. end;
  241. end;
  242. else
  243. { generate an error }
  244. consume(_EQUAL);
  245. end;
  246. until (token<>_ID)or(in_class and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
  247. block_type:=old_block_type;
  248. end;
  249. procedure label_dec;
  250. begin
  251. consume(_LABEL);
  252. if not(cs_support_goto in current_settings.moduleswitches) then
  253. Message(sym_e_goto_and_label_not_supported);
  254. repeat
  255. if not(token in [_ID,_INTCONST]) then
  256. consume(_ID)
  257. else
  258. begin
  259. if token=_ID then
  260. symtablestack.top.insert(tlabelsym.create(orgpattern))
  261. else
  262. symtablestack.top.insert(tlabelsym.create(pattern));
  263. consume(token);
  264. end;
  265. if token<>_SEMICOLON then consume(_COMMA);
  266. until not(token in [_ID,_INTCONST]);
  267. consume(_SEMICOLON);
  268. end;
  269. procedure types_dec(in_class: boolean);
  270. procedure get_cpp_class_external_status(od: tobjectdef);
  271. var
  272. hs: string;
  273. begin
  274. { C++ classes can be external -> all methods inside are external
  275. (defined at the class level instead of per method, so that you cannot
  276. define some methods as external and some not)
  277. }
  278. if (token=_ID) and
  279. (idtoken=_EXTERNAL) then
  280. begin
  281. consume(_EXTERNAL);
  282. { copied from pdecsub.pd_external }
  283. if not(token=_SEMICOLON) and not(idtoken=_NAME) then
  284. begin
  285. { Always add library prefix and suffix to create an uniform name }
  286. hs:=get_stringconst;
  287. if ExtractFileExt(hs)='' then
  288. hs:=ChangeFileExt(hs,target_info.sharedlibext);
  289. if Copy(hs,1,length(target_info.sharedlibprefix))<>target_info.sharedlibprefix then
  290. hs:=target_info.sharedlibprefix+hs;
  291. od.import_lib:=stringdup(hs);
  292. end;
  293. include(od.objectoptions, oo_is_external);
  294. { check if we shall use another name for the class }
  295. if (token=_ID) and
  296. (idtoken=_NAME) then
  297. begin
  298. consume(_NAME);
  299. od.objextname:=stringdup(get_stringconst);
  300. end
  301. else
  302. od.objextname:=stringdup(od.objrealname^);
  303. consume(_SEMICOLON);
  304. { now all methods need to be external }
  305. od.make_all_methods_external;
  306. include(od.objectoptions,oo_is_external);
  307. end
  308. else
  309. od.objextname:=stringdup(od.objrealname^);
  310. { ToDo: read the namespace of the class (influences the mangled name)}
  311. end;
  312. procedure get_objc_class_or_protocol_external_status(od: tobjectdef);
  313. begin
  314. { Objective-C classes can be external -> all messages inside are
  315. external (defined at the class level instead of per method, so
  316. that you cannot define some methods as external and some not)
  317. }
  318. if (token=_ID) and
  319. (idtoken=_EXTERNAL) then
  320. begin
  321. consume(_EXTERNAL);
  322. if (token=_ID) and
  323. (idtoken=_NAME) then
  324. begin
  325. consume(_NAME);
  326. od.objextname:=stringdup(get_stringconst);
  327. end
  328. else
  329. od.objextname:=stringdup(od.objrealname^);
  330. consume(_SEMICOLON);
  331. od.make_all_methods_external;
  332. include(od.objectoptions,oo_is_external);
  333. end
  334. else { or also allow "public name 'x'"? }
  335. od.objextname:=stringdup(od.objrealname^);
  336. end;
  337. function parse_generic_parameters:TFPObjectList;
  338. var
  339. generictype : ttypesym;
  340. begin
  341. result:=TFPObjectList.Create(false);
  342. repeat
  343. if token=_ID then
  344. begin
  345. generictype:=ttypesym.create(orgpattern,cundefinedtype);
  346. include(generictype.symoptions,sp_generic_para);
  347. result.add(generictype);
  348. end;
  349. consume(_ID);
  350. until not try_to_consume(_COMMA) ;
  351. end;
  352. var
  353. typename,orgtypename : TIDString;
  354. newtype : ttypesym;
  355. sym : tsym;
  356. srsymtable : TSymtable;
  357. hdef : tdef;
  358. defpos,storetokenpos : tfileposinfo;
  359. old_block_type : tblock_type;
  360. objecttype : tobjecttyp;
  361. isgeneric,
  362. isunique,
  363. istyperenaming : boolean;
  364. generictypelist : TFPObjectList;
  365. generictokenbuf : tdynamicarray;
  366. vmtbuilder : TVMTBuilder;
  367. begin
  368. old_block_type:=block_type;
  369. block_type:=bt_type;
  370. repeat
  371. defpos:=current_tokenpos;
  372. istyperenaming:=false;
  373. generictypelist:=nil;
  374. generictokenbuf:=nil;
  375. { generic declaration? }
  376. isgeneric:=try_to_consume(_GENERIC);
  377. typename:=pattern;
  378. orgtypename:=orgpattern;
  379. consume(_ID);
  380. { Generic type declaration? }
  381. if isgeneric then
  382. begin
  383. consume(_LSHARPBRACKET);
  384. generictypelist:=parse_generic_parameters;
  385. consume(_RSHARPBRACKET);
  386. end;
  387. consume(_EQUAL);
  388. { support 'ttype=type word' syntax }
  389. isunique:=try_to_consume(_TYPE);
  390. { MacPas object model is more like Delphi's than like TP's, but }
  391. { uses the object keyword instead of class }
  392. if (m_mac in current_settings.modeswitches) and
  393. (token = _OBJECT) then
  394. token := _CLASS;
  395. { Start recording a generic template }
  396. if assigned(generictypelist) then
  397. begin
  398. generictokenbuf:=tdynamicarray.create(256);
  399. current_scanner.startrecordtokens(generictokenbuf);
  400. end;
  401. { is the type already defined? }
  402. searchsym(typename,sym,srsymtable);
  403. newtype:=nil;
  404. { found a symbol with this name? }
  405. if assigned(sym) then
  406. begin
  407. if (sym.typ=typesym) then
  408. begin
  409. if ((token=_CLASS) or
  410. (token=_INTERFACE) or
  411. (token=_DISPINTERFACE) or
  412. (token=_OBJCCLASS) or
  413. (token=_OBJCPROTOCOL) or
  414. (token=_OBJCCATEGORY)) and
  415. (assigned(ttypesym(sym).typedef)) and
  416. is_class_or_interface_or_dispinterface_or_objc(ttypesym(sym).typedef) and
  417. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  418. begin
  419. case token of
  420. _CLASS :
  421. objecttype:=odt_class;
  422. _INTERFACE :
  423. if current_settings.interfacetype=it_interfacecom then
  424. objecttype:=odt_interfacecom
  425. else
  426. objecttype:=odt_interfacecorba;
  427. _DISPINTERFACE :
  428. objecttype:=odt_dispinterface;
  429. _OBJCCLASS,
  430. _OBJCCATEGORY :
  431. objecttype:=odt_objcclass;
  432. _OBJCPROTOCOL :
  433. objecttype:=odt_objcprotocol;
  434. else
  435. internalerror(200811072);
  436. end;
  437. consume(token);
  438. { we can ignore the result, the definition is modified }
  439. object_dec(objecttype,orgtypename,nil,nil,tobjectdef(ttypesym(sym).typedef));
  440. newtype:=ttypesym(sym);
  441. hdef:=newtype.typedef;
  442. end
  443. else
  444. message1(parser_h_type_redef,orgtypename);
  445. end;
  446. end;
  447. { no old type reused ? Then insert this new type }
  448. if not assigned(newtype) then
  449. begin
  450. { insert the new type first with an errordef, so that
  451. referencing the type before it's really set it
  452. will give an error (PFV) }
  453. hdef:=generrordef;
  454. storetokenpos:=current_tokenpos;
  455. newtype:=ttypesym.create(orgtypename,hdef);
  456. newtype.visibility:=symtablestack.top.currentvisibility;
  457. symtablestack.top.insert(newtype);
  458. current_tokenpos:=defpos;
  459. current_tokenpos:=storetokenpos;
  460. { read the type definition }
  461. read_named_type(hdef,orgtypename,nil,generictypelist,false);
  462. { update the definition of the type }
  463. if assigned(hdef) then
  464. begin
  465. if assigned(hdef.typesym) then
  466. istyperenaming:=true;
  467. if isunique then
  468. begin
  469. if is_objc_class_or_protocol(hdef) then
  470. Message(parser_e_no_objc_unique);
  471. hdef:=tstoreddef(hdef).getcopy;
  472. { fix name, it is used e.g. for tables }
  473. if is_class_or_interface_or_dispinterface(hdef) then
  474. with tobjectdef(hdef) do
  475. begin
  476. stringdispose(objname);
  477. stringdispose(objrealname);
  478. objrealname:=stringdup(orgtypename);
  479. objname:=stringdup(upper(orgtypename));
  480. end;
  481. include(hdef.defoptions,df_unique);
  482. end;
  483. if not assigned(hdef.typesym) then
  484. hdef.typesym:=newtype;
  485. end;
  486. newtype.typedef:=hdef;
  487. { KAZ: handle TGUID declaration in system unit }
  488. if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
  489. (typename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
  490. assigned(hdef) and (hdef.typ=recorddef) and (hdef.size=16) then
  491. rec_tguid:=trecorddef(hdef);
  492. end;
  493. if assigned(hdef) then
  494. begin
  495. case hdef.typ of
  496. pointerdef :
  497. begin
  498. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  499. consume(_SEMICOLON);
  500. if try_to_consume(_FAR) then
  501. begin
  502. tpointerdef(hdef).is_far:=true;
  503. consume(_SEMICOLON);
  504. end;
  505. end;
  506. procvardef :
  507. begin
  508. { in case of type renaming, don't parse proc directives }
  509. if istyperenaming then
  510. begin
  511. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  512. consume(_SEMICOLON);
  513. end
  514. else
  515. begin
  516. if not check_proc_directive(true) then
  517. begin
  518. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  519. consume(_SEMICOLON);
  520. end;
  521. parse_var_proc_directives(tsym(newtype));
  522. handle_calling_convention(tprocvardef(hdef));
  523. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  524. consume(_SEMICOLON);
  525. end;
  526. end;
  527. objectdef :
  528. begin
  529. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  530. consume(_SEMICOLON);
  531. { we have to know whether the class or protocol is
  532. external before the vmt is built, because some errors/
  533. hints depend on this }
  534. if is_objc_class_or_protocol(hdef) then
  535. get_objc_class_or_protocol_external_status(tobjectdef(hdef));
  536. if is_cppclass(hdef) then
  537. get_cpp_class_external_status(tobjectdef(hdef));
  538. { Build VMT indexes, skip for type renaming and forward classes }
  539. if (hdef.typesym=newtype) and
  540. not(oo_is_forward in tobjectdef(hdef).objectoptions) and
  541. not(df_generic in hdef.defoptions) then
  542. begin
  543. vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
  544. vmtbuilder.generate_vmt;
  545. vmtbuilder.free;
  546. end;
  547. { In case of an objcclass, verify that all methods have a message
  548. name set. We only check this now, because message names can be set
  549. during the protocol (interface) mapping. At the same time, set the
  550. mangled names (these depend on the "external" name of the class),
  551. and mark private fields of external classes as "used" (to avoid
  552. bogus notes about them being unused)
  553. }
  554. if is_objc_class_or_protocol(hdef) then
  555. tobjectdef(hdef).finish_objc_data;
  556. if is_cppclass(hdef) then
  557. tobjectdef(hdef).finish_cpp_data;
  558. end;
  559. recorddef :
  560. begin
  561. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  562. consume(_SEMICOLON);
  563. end;
  564. else
  565. begin
  566. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  567. consume(_SEMICOLON);
  568. end;
  569. end;
  570. end;
  571. if isgeneric and not(hdef.typ in [objectdef,recorddef]) then
  572. message(parser_e_cant_create_generics_of_this_type);
  573. { Stop recording a generic template }
  574. if assigned(generictypelist) then
  575. begin
  576. current_scanner.stoprecordtokens;
  577. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  578. { Generic is never a type renaming }
  579. hdef.typesym:=newtype;
  580. end;
  581. if assigned(generictypelist) then
  582. generictypelist.free;
  583. until (token<>_ID)or(in_class and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
  584. resolve_forward_types;
  585. block_type:=old_block_type;
  586. end;
  587. { reads a type declaration to the symbol table }
  588. procedure type_dec;
  589. begin
  590. consume(_TYPE);
  591. types_dec(false);
  592. end;
  593. procedure var_dec;
  594. { parses variable declarations and inserts them in }
  595. { the top symbol table of symtablestack }
  596. begin
  597. consume(_VAR);
  598. read_var_decls([]);
  599. end;
  600. procedure property_dec(is_classpropery: boolean);
  601. var
  602. old_block_type : tblock_type;
  603. begin
  604. consume(_PROPERTY);
  605. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  606. message(parser_e_resourcestring_only_sg);
  607. old_block_type:=block_type;
  608. block_type:=bt_const;
  609. repeat
  610. read_property_dec(is_classpropery, nil);
  611. consume(_SEMICOLON);
  612. until token<>_ID;
  613. block_type:=old_block_type;
  614. end;
  615. procedure threadvar_dec;
  616. { parses thread variable declarations and inserts them in }
  617. { the top symbol table of symtablestack }
  618. begin
  619. consume(_THREADVAR);
  620. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  621. message(parser_e_threadvars_only_sg);
  622. read_var_decls([vd_threadvar]);
  623. end;
  624. procedure resourcestring_dec;
  625. var
  626. orgname : TIDString;
  627. p : tnode;
  628. dummysymoptions : tsymoptions;
  629. deprecatedmsg : pshortstring;
  630. storetokenpos,filepos : tfileposinfo;
  631. old_block_type : tblock_type;
  632. sp : pchar;
  633. sym : tsym;
  634. begin
  635. consume(_RESOURCESTRING);
  636. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  637. message(parser_e_resourcestring_only_sg);
  638. old_block_type:=block_type;
  639. block_type:=bt_const;
  640. repeat
  641. orgname:=orgpattern;
  642. filepos:=current_tokenpos;
  643. consume(_ID);
  644. case token of
  645. _EQUAL:
  646. begin
  647. consume(_EQUAL);
  648. p:=comp_expr(true);
  649. storetokenpos:=current_tokenpos;
  650. current_tokenpos:=filepos;
  651. sym:=nil;
  652. case p.nodetype of
  653. ordconstn:
  654. begin
  655. if is_constcharnode(p) then
  656. begin
  657. getmem(sp,2);
  658. sp[0]:=chr(tordconstnode(p).value.svalue);
  659. sp[1]:=#0;
  660. sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
  661. end
  662. else
  663. Message(parser_e_illegal_expression);
  664. end;
  665. stringconstn:
  666. with Tstringconstnode(p) do
  667. begin
  668. getmem(sp,len+1);
  669. move(value_str^,sp^,len+1);
  670. sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
  671. end;
  672. else
  673. Message(parser_e_illegal_expression);
  674. end;
  675. current_tokenpos:=storetokenpos;
  676. { Support hint directives }
  677. dummysymoptions:=[];
  678. deprecatedmsg:=nil;
  679. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  680. if assigned(sym) then
  681. begin
  682. sym.symoptions:=sym.symoptions+dummysymoptions;
  683. sym.deprecatedmsg:=deprecatedmsg;
  684. symtablestack.top.insert(sym);
  685. end
  686. else
  687. stringdispose(deprecatedmsg);
  688. consume(_SEMICOLON);
  689. p.free;
  690. end;
  691. else consume(_EQUAL);
  692. end;
  693. until token<>_ID;
  694. block_type:=old_block_type;
  695. end;
  696. end.