pdecl.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  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. globals,
  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. { common }
  39. cutils,cclasses,
  40. { global }
  41. globtype,tokens,verbose,widestr,
  42. systems,
  43. { aasm }
  44. aasmbase,aasmtai,aasmdata,fmodule,
  45. { symtable }
  46. symconst,symbase,symtype,symdef,symtable,paramgr,defutil,
  47. { pass 1 }
  48. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nobj,
  49. { codegen }
  50. ncgutil,
  51. { parser }
  52. scanner,
  53. pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,
  54. { cpu-information }
  55. cpuinfo
  56. ;
  57. function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
  58. var
  59. hp : tconstsym;
  60. p : tnode;
  61. ps : pconstset;
  62. pd : pbestreal;
  63. pg : pguid;
  64. sp : pchar;
  65. pw : pcompilerwidestring;
  66. storetokenpos : tfileposinfo;
  67. begin
  68. readconstant:=nil;
  69. if orgname='' then
  70. internalerror(9584582);
  71. hp:=nil;
  72. p:=comp_expr(true);
  73. storetokenpos:=current_tokenpos;
  74. current_tokenpos:=filepos;
  75. case p.nodetype of
  76. ordconstn:
  77. begin
  78. if p.resultdef.deftype=pointerdef then
  79. hp:=tconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value,p.resultdef)
  80. else
  81. hp:=tconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resultdef);
  82. end;
  83. stringconstn:
  84. begin
  85. if is_widestring(p.resultdef) then
  86. begin
  87. initwidestring(pw);
  88. copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
  89. hp:=tconstsym.create_wstring(orgname,constwstring,pw);
  90. end
  91. else
  92. begin
  93. getmem(sp,tstringconstnode(p).len+1);
  94. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  95. hp:=tconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len);
  96. end;
  97. end;
  98. realconstn :
  99. begin
  100. new(pd);
  101. pd^:=trealconstnode(p).value_real;
  102. hp:=tconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
  103. end;
  104. setconstn :
  105. begin
  106. new(ps);
  107. ps^:=tsetconstnode(p).value_set^;
  108. hp:=tconstsym.create_ptr(orgname,constset,ps,p.resultdef);
  109. end;
  110. pointerconstn :
  111. begin
  112. hp:=tconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
  113. end;
  114. niln :
  115. begin
  116. hp:=tconstsym.create_ord(orgname,constnil,0,p.resultdef);
  117. end;
  118. typen :
  119. begin
  120. if is_interface(p.resultdef) then
  121. begin
  122. if assigned(tobjectdef(p.resultdef).iidguid) then
  123. begin
  124. new(pg);
  125. pg^:=tobjectdef(p.resultdef).iidguid^;
  126. hp:=tconstsym.create_ptr(orgname,constguid,pg,p.resultdef);
  127. end
  128. else
  129. Message1(parser_e_interface_has_no_guid,tobjectdef(p.resultdef).objrealname^);
  130. end
  131. else
  132. Message(parser_e_illegal_expression);
  133. end;
  134. else
  135. Message(parser_e_illegal_expression);
  136. end;
  137. current_tokenpos:=storetokenpos;
  138. p.free;
  139. readconstant:=hp;
  140. end;
  141. procedure const_dec;
  142. var
  143. orgname : stringid;
  144. hdef : tdef;
  145. sym : tsym;
  146. dummysymoptions : tsymoptions;
  147. storetokenpos,filepos : tfileposinfo;
  148. old_block_type : tblock_type;
  149. skipequal : boolean;
  150. tclist : tasmlist;
  151. begin
  152. consume(_CONST);
  153. old_block_type:=block_type;
  154. block_type:=bt_const;
  155. repeat
  156. orgname:=orgpattern;
  157. filepos:=current_tokenpos;
  158. consume(_ID);
  159. case token of
  160. _EQUAL:
  161. begin
  162. consume(_EQUAL);
  163. sym:=readconstant(orgname,filepos);
  164. { Support hint directives }
  165. dummysymoptions:=[];
  166. try_consume_hintdirective(dummysymoptions);
  167. if assigned(sym) then
  168. begin
  169. sym.symoptions:=sym.symoptions+dummysymoptions;
  170. symtablestack.top.insert(sym);
  171. end;
  172. consume(_SEMICOLON);
  173. end;
  174. _COLON:
  175. begin
  176. { set the blocktype first so a consume also supports a
  177. caret, to support const s : ^string = nil }
  178. block_type:=bt_type;
  179. consume(_COLON);
  180. ignore_equal:=true;
  181. read_anon_type(hdef,false);
  182. ignore_equal:=false;
  183. block_type:=bt_const;
  184. skipequal:=false;
  185. { create symbol }
  186. storetokenpos:=current_tokenpos;
  187. current_tokenpos:=filepos;
  188. sym:=ttypedconstsym.create(orgname,hdef,(cs_typed_const_writable in current_settings.localswitches));
  189. current_tokenpos:=storetokenpos;
  190. symtablestack.top.insert(sym);
  191. { procvar can have proc directives, but not type references }
  192. if (hdef.deftype=procvardef) and
  193. (hdef.typesym=nil) then
  194. begin
  195. { support p : procedure;stdcall=nil; }
  196. if try_to_consume(_SEMICOLON) then
  197. begin
  198. if check_proc_directive(true) then
  199. parse_var_proc_directives(sym)
  200. else
  201. begin
  202. Message(parser_e_proc_directive_expected);
  203. skipequal:=true;
  204. end;
  205. end
  206. else
  207. { support p : procedure stdcall=nil; }
  208. begin
  209. if check_proc_directive(true) then
  210. parse_var_proc_directives(sym);
  211. end;
  212. { add default calling convention }
  213. handle_calling_convention(tabstractprocdef(hdef));
  214. end;
  215. if not skipequal then
  216. begin
  217. { get init value }
  218. consume(_EQUAL);
  219. if (cs_typed_const_writable in current_settings.localswitches) then
  220. tclist:=current_asmdata.asmlists[al_rotypedconsts]
  221. else
  222. tclist:=current_asmdata.asmlists[al_typedconsts];
  223. readtypedconst(tclist,hdef,ttypedconstsym(sym),(cs_typed_const_writable in current_settings.localswitches));
  224. consume(_SEMICOLON);
  225. end;
  226. end;
  227. else
  228. { generate an error }
  229. consume(_EQUAL);
  230. end;
  231. until token<>_ID;
  232. block_type:=old_block_type;
  233. end;
  234. procedure label_dec;
  235. begin
  236. consume(_LABEL);
  237. if not(cs_support_goto in current_settings.moduleswitches) then
  238. Message(sym_e_goto_and_label_not_supported);
  239. repeat
  240. if not(token in [_ID,_INTCONST]) then
  241. consume(_ID)
  242. else
  243. begin
  244. if token=_ID then
  245. symtablestack.top.insert(tlabelsym.create(orgpattern))
  246. else
  247. symtablestack.top.insert(tlabelsym.create(pattern));
  248. consume(token);
  249. end;
  250. if token<>_SEMICOLON then consume(_COMMA);
  251. until not(token in [_ID,_INTCONST]);
  252. consume(_SEMICOLON);
  253. end;
  254. { search in symtablestack used, but not defined type }
  255. procedure resolve_type_forward(p : tnamedindexitem;arg:pointer);
  256. var
  257. hpd,pd : tdef;
  258. stpos : tfileposinfo;
  259. again : boolean;
  260. srsym : tsym;
  261. srsymtable : tsymtable;
  262. begin
  263. { Check only typesyms or record/object fields }
  264. case tsym(p).typ of
  265. typesym :
  266. pd:=ttypesym(p).typedef;
  267. fieldvarsym :
  268. pd:=tfieldvarsym(p).vardef
  269. else
  270. exit;
  271. end;
  272. repeat
  273. again:=false;
  274. case pd.deftype of
  275. arraydef :
  276. begin
  277. { elementdef could also be defined using a forwarddef }
  278. pd:=tarraydef(pd).elementdef;
  279. again:=true;
  280. end;
  281. pointerdef,
  282. classrefdef :
  283. begin
  284. { classrefdef inherits from pointerdef }
  285. hpd:=tabstractpointerdef(pd).pointeddef;
  286. { still a forward def ? }
  287. if hpd.deftype=forwarddef then
  288. begin
  289. { try to resolve the forward }
  290. { get the correct position for it }
  291. stpos:=current_tokenpos;
  292. current_tokenpos:=tforwarddef(hpd).forwardpos;
  293. resolving_forward:=true;
  294. make_ref:=false;
  295. if not assigned(tforwarddef(hpd).tosymname) then
  296. internalerror(20021120);
  297. searchsym(tforwarddef(hpd).tosymname^,srsym,srsymtable);
  298. make_ref:=true;
  299. resolving_forward:=false;
  300. current_tokenpos:=stpos;
  301. { we don't need the forwarddef anymore, dispose it }
  302. hpd.free;
  303. tabstractpointerdef(pd).pointeddef:=nil; { if error occurs }
  304. { was a type sym found ? }
  305. if assigned(srsym) and
  306. (srsym.typ=typesym) then
  307. begin
  308. tabstractpointerdef(pd).pointeddef:=ttypesym(srsym).typedef;
  309. { avoid wrong unused warnings web bug 801 PM }
  310. inc(ttypesym(srsym).refs);
  311. { we need a class type for classrefdef }
  312. if (pd.deftype=classrefdef) and
  313. not(is_class(ttypesym(srsym).typedef)) then
  314. Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename);
  315. end
  316. else
  317. begin
  318. MessagePos1(tsym(p).fileinfo,sym_e_forward_type_not_resolved,tsym(p).realname);
  319. { try to recover }
  320. tabstractpointerdef(pd).pointeddef:=generrordef;
  321. end;
  322. end;
  323. end;
  324. recorddef :
  325. trecorddef(pd).symtable.foreach_static(@resolve_type_forward,nil);
  326. objectdef :
  327. begin
  328. if not(m_fpc in current_settings.modeswitches) and
  329. (oo_is_forward in tobjectdef(pd).objectoptions) then
  330. begin
  331. { only give an error as the implementation may follow in an
  332. other type block which is allowed by FPC modes }
  333. MessagePos1(tsym(p).fileinfo,sym_e_forward_type_not_resolved,tsym(p).realname);
  334. end
  335. else
  336. begin
  337. { Check all fields of the object declaration, but don't
  338. check objectdefs in objects/records, because these
  339. can't exist (anonymous objects aren't allowed) }
  340. if not(tsym(p).owner.symtabletype in [objectsymtable,recordsymtable]) then
  341. tobjectdef(pd).symtable.foreach_static(@resolve_type_forward,nil);
  342. end;
  343. end;
  344. end;
  345. until not again;
  346. end;
  347. procedure types_dec;
  348. function parse_generic_parameters:TFPObjectList;
  349. var
  350. generictype : ttypesym;
  351. begin
  352. result:=TFPObjectList.Create(false);
  353. repeat
  354. if token=_ID then
  355. begin
  356. generictype:=ttypesym.create(orgpattern,cundefinedtype);
  357. result.add(generictype);
  358. end;
  359. consume(_ID);
  360. until not try_to_consume(_COMMA) ;
  361. end;
  362. var
  363. typename,orgtypename : stringid;
  364. newtype : ttypesym;
  365. sym : tsym;
  366. srsymtable : tsymtable;
  367. hdef : tdef;
  368. oldfilepos,
  369. defpos,storetokenpos : tfileposinfo;
  370. old_block_type : tblock_type;
  371. ch : tclassheader;
  372. isgeneric,
  373. isunique,
  374. istyperenaming : boolean;
  375. generictypelist : TFPObjectList;
  376. generictokenbuf : tdynamicarray;
  377. begin
  378. old_block_type:=block_type;
  379. block_type:=bt_type;
  380. typecanbeforward:=true;
  381. repeat
  382. defpos:=current_tokenpos;
  383. istyperenaming:=false;
  384. generictypelist:=nil;
  385. generictokenbuf:=nil;
  386. { generic declaration? }
  387. isgeneric:=try_to_consume(_GENERIC);
  388. typename:=pattern;
  389. orgtypename:=orgpattern;
  390. consume(_ID);
  391. { Generic type declaration? }
  392. if isgeneric then
  393. begin
  394. consume(_LSHARPBRACKET);
  395. generictypelist:=parse_generic_parameters;
  396. consume(_RSHARPBRACKET);
  397. end;
  398. consume(_EQUAL);
  399. { support 'ttype=type word' syntax }
  400. isunique:=try_to_consume(_TYPE);
  401. { MacPas object model is more like Delphi's than like TP's, but }
  402. { uses the object keyword instead of class }
  403. if (m_mac in current_settings.modeswitches) and
  404. (token = _OBJECT) then
  405. token := _CLASS;
  406. { Start recording a generic template }
  407. if assigned(generictypelist) then
  408. begin
  409. generictokenbuf:=tdynamicarray.create(256);
  410. current_scanner.startrecordtokens(generictokenbuf);
  411. end;
  412. { is the type already defined? }
  413. searchsym(typename,sym,srsymtable);
  414. newtype:=nil;
  415. { found a symbol with this name? }
  416. if assigned(sym) then
  417. begin
  418. if (sym.typ=typesym) then
  419. begin
  420. if ((token=_CLASS) or
  421. (token=_INTERFACE) or
  422. (token=_DISPINTERFACE)) and
  423. (assigned(ttypesym(sym).typedef)) and
  424. is_class_or_interface_or_dispinterface(ttypesym(sym).typedef) and
  425. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  426. begin
  427. { we can ignore the result }
  428. { the definition is modified }
  429. object_dec(orgtypename,nil,nil,tobjectdef(ttypesym(sym).typedef));
  430. newtype:=ttypesym(sym);
  431. hdef:=newtype.typedef;
  432. end
  433. else
  434. message1(parser_h_type_redef,orgtypename);
  435. end;
  436. end;
  437. { no old type reused ? Then insert this new type }
  438. if not assigned(newtype) then
  439. begin
  440. { insert the new type first with an errordef, so that
  441. referencing the type before it's really set it
  442. will give an error (PFV) }
  443. hdef:=generrordef;
  444. storetokenpos:=current_tokenpos;
  445. newtype:=ttypesym.create(orgtypename,hdef);
  446. symtablestack.top.insert(newtype);
  447. current_tokenpos:=defpos;
  448. current_tokenpos:=storetokenpos;
  449. { read the type definition }
  450. read_named_type(hdef,orgtypename,nil,generictypelist,false);
  451. { update the definition of the type }
  452. if assigned(hdef) then
  453. begin
  454. if assigned(hdef.typesym) then
  455. istyperenaming:=true;
  456. if isunique then
  457. begin
  458. hdef:=tstoreddef(hdef).getcopy;
  459. include(hdef.defoptions,df_unique);
  460. end;
  461. if not assigned(hdef.typesym) then
  462. hdef.typesym:=newtype;
  463. end;
  464. newtype.typedef:=hdef;
  465. { KAZ: handle TGUID declaration in system unit }
  466. if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
  467. (typename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
  468. assigned(hdef) and (hdef.deftype=recorddef) and (hdef.size=16) then
  469. rec_tguid:=trecorddef(hdef);
  470. end;
  471. if assigned(hdef) then
  472. begin
  473. case hdef.deftype of
  474. pointerdef :
  475. begin
  476. consume(_SEMICOLON);
  477. if try_to_consume(_FAR) then
  478. begin
  479. tpointerdef(hdef).is_far:=true;
  480. consume(_SEMICOLON);
  481. end;
  482. end;
  483. procvardef :
  484. begin
  485. { in case of type renaming, don't parse proc directives }
  486. if istyperenaming then
  487. consume(_SEMICOLON)
  488. else
  489. begin
  490. if not check_proc_directive(true) then
  491. consume(_SEMICOLON);
  492. parse_var_proc_directives(tsym(newtype));
  493. handle_calling_convention(tprocvardef(hdef));
  494. end;
  495. end;
  496. objectdef,
  497. recorddef :
  498. begin
  499. try_consume_hintdirective(newtype.symoptions);
  500. consume(_SEMICOLON);
  501. end;
  502. else
  503. consume(_SEMICOLON);
  504. end;
  505. end;
  506. { Stop recording a generic template }
  507. if assigned(generictypelist) then
  508. begin
  509. current_scanner.stoprecordtokens;
  510. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  511. { Generic is never a type renaming }
  512. hdef.typesym:=newtype;
  513. end;
  514. { Write tables if we are the typesym that defines
  515. this type. This will not be done for simple type renamings }
  516. if (hdef.typesym=newtype) then
  517. begin
  518. { file position }
  519. oldfilepos:=current_filepos;
  520. current_filepos:=newtype.fileinfo;
  521. { generate persistent init/final tables when it's declared in the interface so it can
  522. be reused in other used }
  523. if current_module.in_interface and
  524. ((is_class(hdef) and
  525. tobjectdef(hdef).members_need_inittable) or
  526. hdef.needs_inittable) then
  527. generate_inittable(newtype);
  528. { for objects we should write the vmt and interfaces.
  529. This need to be done after the rtti has been written, because
  530. it can contain a reference to that data (PFV)
  531. This is not for forward classes }
  532. if (hdef.deftype=objectdef) and
  533. (hdef.owner.symtabletype in [staticsymtable,globalsymtable]) then
  534. with Tobjectdef(hdef) do
  535. begin
  536. if not(oo_is_forward in objectoptions) then
  537. begin
  538. ch:=tclassheader.create(tobjectdef(hdef));
  539. { generate and check virtual methods, must be done
  540. before RTTI is written }
  541. ch.genvmt;
  542. { Generate RTTI for class }
  543. generate_rtti(newtype);
  544. if is_interface(tobjectdef(hdef)) then
  545. ch.writeinterfaceids;
  546. if (oo_has_vmt in objectoptions) then
  547. ch.writevmt;
  548. ch.free;
  549. end;
  550. end
  551. else
  552. begin
  553. { Always generate RTTI info for all types. This is to have typeinfo() return
  554. the same pointer }
  555. generate_rtti(newtype);
  556. end;
  557. current_filepos:=oldfilepos;
  558. end;
  559. until token<>_ID;
  560. typecanbeforward:=false;
  561. symtablestack.top.foreach_static(@resolve_type_forward,nil);
  562. block_type:=old_block_type;
  563. end;
  564. { reads a type declaration to the symbol table }
  565. procedure type_dec;
  566. begin
  567. consume(_TYPE);
  568. types_dec;
  569. end;
  570. procedure var_dec;
  571. { parses variable declarations and inserts them in }
  572. { the top symbol table of symtablestack }
  573. begin
  574. consume(_VAR);
  575. read_var_decls([]);
  576. end;
  577. procedure property_dec;
  578. var
  579. old_block_type : tblock_type;
  580. begin
  581. consume(_PROPERTY);
  582. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  583. message(parser_e_resourcestring_only_sg);
  584. old_block_type:=block_type;
  585. block_type:=bt_const;
  586. repeat
  587. read_property_dec(nil);
  588. consume(_SEMICOLON);
  589. until token<>_ID;
  590. block_type:=old_block_type;
  591. end;
  592. procedure threadvar_dec;
  593. { parses thread variable declarations and inserts them in }
  594. { the top symbol table of symtablestack }
  595. begin
  596. consume(_THREADVAR);
  597. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  598. message(parser_e_threadvars_only_sg);
  599. read_var_decls([vd_threadvar]);
  600. end;
  601. procedure resourcestring_dec;
  602. var
  603. orgname : stringid;
  604. p : tnode;
  605. dummysymoptions : tsymoptions;
  606. storetokenpos,filepos : tfileposinfo;
  607. old_block_type : tblock_type;
  608. sp : pchar;
  609. sym : tsym;
  610. begin
  611. consume(_RESOURCESTRING);
  612. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  613. message(parser_e_resourcestring_only_sg);
  614. old_block_type:=block_type;
  615. block_type:=bt_const;
  616. repeat
  617. orgname:=orgpattern;
  618. filepos:=current_tokenpos;
  619. consume(_ID);
  620. case token of
  621. _EQUAL:
  622. begin
  623. consume(_EQUAL);
  624. p:=comp_expr(true);
  625. storetokenpos:=current_tokenpos;
  626. current_tokenpos:=filepos;
  627. sym:=nil;
  628. case p.nodetype of
  629. ordconstn:
  630. begin
  631. if is_constcharnode(p) then
  632. begin
  633. getmem(sp,2);
  634. sp[0]:=chr(tordconstnode(p).value);
  635. sp[1]:=#0;
  636. sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
  637. end
  638. else
  639. Message(parser_e_illegal_expression);
  640. end;
  641. stringconstn:
  642. with Tstringconstnode(p) do
  643. begin
  644. getmem(sp,len+1);
  645. move(value_str^,sp^,len+1);
  646. sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
  647. end;
  648. else
  649. Message(parser_e_illegal_expression);
  650. end;
  651. current_tokenpos:=storetokenpos;
  652. { Support hint directives }
  653. dummysymoptions:=[];
  654. try_consume_hintdirective(dummysymoptions);
  655. if assigned(sym) then
  656. begin
  657. sym.symoptions:=sym.symoptions+dummysymoptions;
  658. symtablestack.top.insert(sym);
  659. end;
  660. consume(_SEMICOLON);
  661. p.free;
  662. end;
  663. else consume(_EQUAL);
  664. end;
  665. until token<>_ID;
  666. block_type:=old_block_type;
  667. end;
  668. end.