pdecl.pas 25 KB

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