pdecl.pas 27 KB

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