pdecvar.pas 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Parses variable declarations. Used for var statement and record
  4. definitions
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit pdecvar;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. symsym,symdef;
  23. type
  24. tvar_dec_option=(vd_record,vd_object,vd_threadvar,vd_class);
  25. tvar_dec_options=set of tvar_dec_option;
  26. function read_property_dec(is_classproperty:boolean;astruct:tabstractrecorddef):tpropertysym;
  27. procedure read_var_decls(options:Tvar_dec_options);
  28. procedure read_record_fields(options:Tvar_dec_options);
  29. procedure read_public_and_external(vs: tabstractvarsym);
  30. procedure try_consume_sectiondirective(var asection: ansistring);
  31. implementation
  32. uses
  33. SysUtils,
  34. { common }
  35. cutils,cclasses,
  36. { global }
  37. globtype,globals,tokens,verbose,constexp,
  38. systems,
  39. { symtable }
  40. symconst,symbase,symtype,symtable,defutil,defcmp,
  41. fmodule,htypechk,
  42. { pass 1 }
  43. node,pass_1,aasmdata,
  44. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nmem,nutils,
  45. { codegen }
  46. ncgutil,
  47. { parser }
  48. scanner,
  49. pbase,pexpr,ptype,ptconst,pdecsub,
  50. { link }
  51. import
  52. ;
  53. function read_property_dec(is_classproperty:boolean;astruct:tabstractrecorddef):tpropertysym;
  54. { convert a node tree to symlist and return the last
  55. symbol }
  56. function parse_symlist(pl:tpropaccesslist;var def:tdef):boolean;
  57. var
  58. idx : longint;
  59. sym : tsym;
  60. srsymtable : TSymtable;
  61. st : TSymtable;
  62. p : tnode;
  63. begin
  64. result:=true;
  65. def:=nil;
  66. if token=_ID then
  67. begin
  68. if assigned(astruct) then
  69. sym:=search_struct_member(astruct,pattern)
  70. else
  71. searchsym(pattern,sym,srsymtable);
  72. if assigned(sym) then
  73. begin
  74. if assigned(astruct) and
  75. not is_visible_for_object(sym,astruct) then
  76. Message(parser_e_cant_access_private_member);
  77. case sym.typ of
  78. fieldvarsym :
  79. begin
  80. if (symtablestack.top.currentvisibility<>vis_private) then
  81. addsymref(sym);
  82. pl.addsym(sl_load,sym);
  83. def:=tfieldvarsym(sym).vardef;
  84. end;
  85. procsym :
  86. begin
  87. if (symtablestack.top.currentvisibility<>vis_private) then
  88. addsymref(sym);
  89. pl.addsym(sl_call,sym);
  90. end;
  91. else
  92. begin
  93. Message1(parser_e_illegal_field_or_method,orgpattern);
  94. def:=generrordef;
  95. result:=false;
  96. end;
  97. end;
  98. end
  99. else
  100. begin
  101. Message1(parser_e_illegal_field_or_method,orgpattern);
  102. def:=generrordef;
  103. result:=false;
  104. end;
  105. consume(_ID);
  106. repeat
  107. case token of
  108. _ID,
  109. _SEMICOLON :
  110. begin
  111. break;
  112. end;
  113. _POINT :
  114. begin
  115. consume(_POINT);
  116. if assigned(def) then
  117. begin
  118. st:=def.GetSymtable(gs_record);
  119. if assigned(st) then
  120. begin
  121. sym:=tsym(st.Find(pattern));
  122. if not(assigned(sym)) and is_object(def) then
  123. sym:=search_struct_member(tobjectdef(def),pattern);
  124. if assigned(sym) then
  125. begin
  126. pl.addsym(sl_subscript,sym);
  127. case sym.typ of
  128. fieldvarsym :
  129. def:=tfieldvarsym(sym).vardef;
  130. else
  131. begin
  132. Message1(sym_e_illegal_field,orgpattern);
  133. result:=false;
  134. end;
  135. end;
  136. end
  137. else
  138. begin
  139. Message1(sym_e_illegal_field,orgpattern);
  140. result:=false;
  141. end;
  142. end
  143. else
  144. begin
  145. Message(parser_e_invalid_qualifier);
  146. result:=false;
  147. end;
  148. end
  149. else
  150. begin
  151. Message(parser_e_invalid_qualifier);
  152. result:=false;
  153. end;
  154. consume(_ID);
  155. end;
  156. _LECKKLAMMER :
  157. begin
  158. consume(_LECKKLAMMER);
  159. repeat
  160. if def.typ=arraydef then
  161. begin
  162. idx:=0;
  163. p:=comp_expr(true,false);
  164. if (not codegenerror) then
  165. begin
  166. if (p.nodetype=ordconstn) then
  167. begin
  168. { type/range checking }
  169. inserttypeconv(p,tarraydef(def).rangedef);
  170. if (Tordconstnode(p).value<int64(low(longint))) or
  171. (Tordconstnode(p).value>int64(high(longint))) then
  172. message(parser_e_array_range_out_of_bounds)
  173. else
  174. idx:=Tordconstnode(p).value.svalue
  175. end
  176. else
  177. Message(type_e_ordinal_expr_expected)
  178. end;
  179. pl.addconst(sl_vec,idx,p.resultdef);
  180. p.free;
  181. def:=tarraydef(def).elementdef;
  182. end
  183. else
  184. begin
  185. Message(parser_e_invalid_qualifier);
  186. result:=false;
  187. end;
  188. until not try_to_consume(_COMMA);
  189. consume(_RECKKLAMMER);
  190. end;
  191. else
  192. begin
  193. Message(parser_e_ill_property_access_sym);
  194. result:=false;
  195. break;
  196. end;
  197. end;
  198. until false;
  199. end
  200. else
  201. begin
  202. Message(parser_e_ill_property_access_sym);
  203. result:=false;
  204. end;
  205. end;
  206. function allow_default_property(p : tpropertysym) : boolean;
  207. begin
  208. allow_default_property:=
  209. (is_ordinal(p.propdef) or
  210. {$ifndef cpu64bitaddr}
  211. is_64bitint(p.propdef) or
  212. {$endif cpu64bitaddr}
  213. is_class(p.propdef) or
  214. is_single(p.propdef) or
  215. (p.propdef.typ in [classrefdef,pointerdef]) or
  216. is_smallset(p.propdef)
  217. ) and not
  218. (
  219. (p.propdef.typ=arraydef) and
  220. (ppo_indexed in p.propoptions)
  221. ) and not
  222. (ppo_hasparameters in p.propoptions);
  223. end;
  224. procedure create_accessor_procsym(p: tpropertysym; pd: tprocdef; const prefix: string;
  225. accesstype: tpropaccesslisttypes);
  226. var
  227. sym: tprocsym;
  228. begin
  229. handle_calling_convention(pd);
  230. sym:=tprocsym.create(prefix+lower(p.realname));
  231. symtablestack.top.insert(sym);
  232. pd.procsym:=sym;
  233. include(pd.procoptions,po_dispid);
  234. include(pd.procoptions,po_global);
  235. pd.visibility:=vis_private;
  236. proc_add_definition(pd);
  237. p.propaccesslist[accesstype].addsym(sl_call,sym);
  238. p.propaccesslist[accesstype].procdef:=pd;
  239. end;
  240. procedure parse_dispinterface(p : tpropertysym; readpd,writepd: tprocdef;
  241. var paranr: word);
  242. var
  243. hasread, haswrite: boolean;
  244. pt: tnode;
  245. hdispid: longint;
  246. hparavs: tparavarsym;
  247. begin
  248. p.propaccesslist[palt_read].clear;
  249. p.propaccesslist[palt_write].clear;
  250. hasread:=true;
  251. haswrite:=true;
  252. if try_to_consume(_READONLY) then
  253. haswrite:=false
  254. else if try_to_consume(_WRITEONLY) then
  255. hasread:=false;
  256. if try_to_consume(_DISPID) then
  257. begin
  258. pt:=comp_expr(true,false);
  259. if is_constintnode(pt) then
  260. if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
  261. message(parser_e_range_check_error)
  262. else
  263. hdispid:=Tordconstnode(pt).value.svalue
  264. else
  265. Message(parser_e_dispid_must_be_ord_const);
  266. pt.free;
  267. end
  268. else
  269. hdispid:=tobjectdef(astruct).get_next_dispid;
  270. { COM property is simply a pair of methods, tagged with 'propertyget'
  271. and 'propertyset' flags (or a single method if access is restricted).
  272. Creating these implicit accessor methods also allows the rest of compiler
  273. to handle dispinterface properties the same way as regular ones. }
  274. if hasread then
  275. begin
  276. readpd.returndef:=p.propdef;
  277. readpd.dispid:=hdispid;
  278. readpd.proctypeoption:=potype_propgetter;
  279. create_accessor_procsym(p,readpd,'get$',palt_read);
  280. end;
  281. if haswrite then
  282. begin
  283. { add an extra parameter, a placeholder of the value to set }
  284. inc(paranr);
  285. hparavs:=tparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
  286. writepd.parast.insert(hparavs);
  287. writepd.proctypeoption:=potype_propsetter;
  288. writepd.dispid:=hdispid;
  289. create_accessor_procsym(p,writepd,'put$',palt_write);
  290. end;
  291. end;
  292. procedure add_index_parameter(var paranr: word; p: tpropertysym; readprocdef, writeprocdef: tprocdef);
  293. var
  294. hparavs: tparavarsym;
  295. begin
  296. inc(paranr);
  297. hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
  298. readprocdef.parast.insert(hparavs);
  299. hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
  300. writeprocdef.parast.insert(hparavs);
  301. end;
  302. var
  303. sym : tsym;
  304. srsymtable: tsymtable;
  305. p : tpropertysym;
  306. overridden : tsym;
  307. varspez : tvarspez;
  308. hdef : tdef;
  309. arraytype : tdef;
  310. def : tdef;
  311. pt : tnode;
  312. sc : TFPObjectList;
  313. paranr : word;
  314. i : longint;
  315. ImplIntf : TImplementedInterface;
  316. found : boolean;
  317. hreadparavs,
  318. hparavs : tparavarsym;
  319. storedprocdef: tprocvardef;
  320. readprocdef,
  321. writeprocdef : tprocdef;
  322. begin
  323. { Generate temp procdefs to search for matching read/write
  324. procedures. the readprocdef will store all definitions }
  325. paranr:=0;
  326. readprocdef:=tprocdef.create(normal_function_level);
  327. writeprocdef:=tprocdef.create(normal_function_level);
  328. readprocdef.struct:=astruct;
  329. writeprocdef.struct:=astruct;
  330. if assigned(astruct) and is_classproperty then
  331. begin
  332. readprocdef.procoptions:=[po_staticmethod,po_classmethod];
  333. writeprocdef.procoptions:=[po_staticmethod,po_classmethod];
  334. end;
  335. if token<>_ID then
  336. begin
  337. consume(_ID);
  338. consume(_SEMICOLON);
  339. exit;
  340. end;
  341. { Generate propertysym and insert in symtablestack }
  342. p:=tpropertysym.create(orgpattern);
  343. p.visibility:=symtablestack.top.currentvisibility;
  344. p.default:=longint($80000000);
  345. if is_classproperty then
  346. include(p.symoptions, sp_static);
  347. symtablestack.top.insert(p);
  348. consume(_ID);
  349. { property parameters ? }
  350. if try_to_consume(_LECKKLAMMER) then
  351. begin
  352. if (p.visibility=vis_published) and
  353. not (m_delphi in current_settings.modeswitches) then
  354. Message(parser_e_cant_publish_that_property);
  355. { create a list of the parameters }
  356. symtablestack.push(readprocdef.parast);
  357. sc:=TFPObjectList.create(false);
  358. repeat
  359. if try_to_consume(_VAR) then
  360. varspez:=vs_var
  361. else if try_to_consume(_CONST) then
  362. varspez:=vs_const
  363. else if try_to_consume(_CONSTREF) then
  364. varspez:=vs_constref
  365. else if (m_out in current_settings.modeswitches) and try_to_consume(_OUT) then
  366. varspez:=vs_out
  367. else
  368. varspez:=vs_value;
  369. sc.clear;
  370. repeat
  371. inc(paranr);
  372. hreadparavs:=tparavarsym.create(orgpattern,10*paranr,varspez,generrordef,[]);
  373. readprocdef.parast.insert(hreadparavs);
  374. sc.add(hreadparavs);
  375. consume(_ID);
  376. until not try_to_consume(_COMMA);
  377. if try_to_consume(_COLON) then
  378. begin
  379. if try_to_consume(_ARRAY) then
  380. begin
  381. consume(_OF);
  382. { define range and type of range }
  383. hdef:=tarraydef.create(0,-1,s32inttype);
  384. { define field type }
  385. single_type(arraytype,[]);
  386. tarraydef(hdef).elementdef:=arraytype;
  387. end
  388. else
  389. single_type(hdef,[]);
  390. end
  391. else
  392. hdef:=cformaltype;
  393. for i:=0 to sc.count-1 do
  394. begin
  395. hreadparavs:=tparavarsym(sc[i]);
  396. hreadparavs.vardef:=hdef;
  397. { also update the writeprocdef }
  398. hparavs:=tparavarsym.create(hreadparavs.realname,hreadparavs.paranr,vs_value,hdef,[]);
  399. writeprocdef.parast.insert(hparavs);
  400. end;
  401. until not try_to_consume(_SEMICOLON);
  402. sc.free;
  403. symtablestack.pop(readprocdef.parast);
  404. consume(_RECKKLAMMER);
  405. { the parser need to know if a property has parameters, the
  406. index parameter doesn't count (PFV) }
  407. if paranr>0 then
  408. include(p.propoptions,ppo_hasparameters);
  409. end;
  410. { overridden property ? }
  411. { force property interface
  412. there is a property parameter
  413. a global property }
  414. if (token=_COLON) or (paranr>0) or (astruct=nil) then
  415. begin
  416. consume(_COLON);
  417. single_type(p.propdef,[]);
  418. if is_dispinterface(astruct) and not is_automatable(p.propdef) then
  419. Message1(type_e_not_automatable,p.propdef.typename);
  420. if (idtoken=_INDEX) then
  421. begin
  422. consume(_INDEX);
  423. pt:=comp_expr(true,false);
  424. { Only allow enum and integer indexes. Convert all integer
  425. values to s32int to be compatible with delphi, because the
  426. procedure matching requires equal parameters }
  427. if is_constnode(pt) and
  428. is_ordinal(pt.resultdef)
  429. {$ifndef cpu64bitaddr}
  430. and (not is_64bitint(pt.resultdef))
  431. {$endif cpu64bitaddr}
  432. then
  433. begin
  434. if is_integer(pt.resultdef) then
  435. inserttypeconv_internal(pt,s32inttype);
  436. p.index:=tordconstnode(pt).value.svalue;
  437. end
  438. else
  439. begin
  440. Message(parser_e_invalid_property_index_value);
  441. p.index:=0;
  442. end;
  443. p.indexdef:=pt.resultdef;
  444. include(p.propoptions,ppo_indexed);
  445. { concat a longint to the para templates }
  446. add_index_parameter(paranr,p,readprocdef,writeprocdef);
  447. pt.free;
  448. end;
  449. end
  450. else
  451. begin
  452. { do an property override }
  453. if (astruct.typ=objectdef) then
  454. overridden:=search_struct_member(tobjectdef(astruct).childof,p.name)
  455. else
  456. overridden:=nil;
  457. if assigned(overridden) and
  458. (overridden.typ=propertysym) and
  459. not(is_dispinterface(astruct)) then
  460. begin
  461. p.overriddenpropsym:=tpropertysym(overridden);
  462. { inherit all type related entries }
  463. p.indexdef:=tpropertysym(overridden).indexdef;
  464. p.propdef:=tpropertysym(overridden).propdef;
  465. p.index:=tpropertysym(overridden).index;
  466. p.default:=tpropertysym(overridden).default;
  467. p.propoptions:=tpropertysym(overridden).propoptions;
  468. if ppo_indexed in p.propoptions then
  469. add_index_parameter(paranr,p,readprocdef,writeprocdef);
  470. end
  471. else
  472. begin
  473. p.propdef:=generrordef;
  474. message(parser_e_no_property_found_to_override);
  475. end;
  476. end;
  477. if ((p.visibility=vis_published) or is_dispinterface(astruct)) and
  478. (not(p.propdef.is_publishable) or (sp_static in p.symoptions)) then
  479. begin
  480. Message(parser_e_cant_publish_that_property);
  481. p.visibility:=vis_public;
  482. end;
  483. if not(is_dispinterface(astruct)) then
  484. begin
  485. if try_to_consume(_READ) then
  486. begin
  487. p.propaccesslist[palt_read].clear;
  488. if parse_symlist(p.propaccesslist[palt_read],def) then
  489. begin
  490. sym:=p.propaccesslist[palt_read].firstsym^.sym;
  491. case sym.typ of
  492. procsym :
  493. begin
  494. { read is function returning the type of the property }
  495. readprocdef.returndef:=p.propdef;
  496. { Insert hidden parameters }
  497. handle_calling_convention(readprocdef);
  498. { search procdefs matching readprocdef }
  499. { we ignore hidden stuff here because the property access symbol might have
  500. non default calling conventions which might change the hidden stuff;
  501. see tw3216.pp (FK) }
  502. p.propaccesslist[palt_read].procdef:=Tprocsym(sym).Find_procdef_bypara(readprocdef.paras,p.propdef,[cpo_allowdefaults,cpo_ignorehidden]);
  503. if not assigned(p.propaccesslist[palt_read].procdef) or
  504. { because of cpo_ignorehidden we need to compare if it is a static class method and we have a class property }
  505. ((sp_static in p.symoptions) <> tprocdef(p.propaccesslist[palt_read].procdef).no_self_node) then
  506. Message(parser_e_ill_property_access_sym);
  507. end;
  508. fieldvarsym :
  509. begin
  510. if not assigned(def) then
  511. internalerror(200310071);
  512. if compare_defs(def,p.propdef,nothingn)>=te_equal then
  513. begin
  514. { property parameters are allowed if this is
  515. an indexed property, because the index is then
  516. the parameter.
  517. Note: In the help of Kylix it is written
  518. that it isn't allowed, but the compiler accepts it (PFV) }
  519. if (ppo_hasparameters in p.propoptions) or
  520. ((sp_static in p.symoptions) <> (sp_static in sym.symoptions)) then
  521. Message(parser_e_ill_property_access_sym);
  522. end
  523. else
  524. IncompatibleTypes(def,p.propdef);
  525. end;
  526. else
  527. Message(parser_e_ill_property_access_sym);
  528. end;
  529. end;
  530. end;
  531. if try_to_consume(_WRITE) then
  532. begin
  533. p.propaccesslist[palt_write].clear;
  534. if parse_symlist(p.propaccesslist[palt_write],def) then
  535. begin
  536. sym:=p.propaccesslist[palt_write].firstsym^.sym;
  537. case sym.typ of
  538. procsym :
  539. begin
  540. { write is a procedure with an extra value parameter
  541. of the of the property }
  542. writeprocdef.returndef:=voidtype;
  543. inc(paranr);
  544. hparavs:=tparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
  545. writeprocdef.parast.insert(hparavs);
  546. { Insert hidden parameters }
  547. handle_calling_convention(writeprocdef);
  548. { search procdefs matching writeprocdef }
  549. if cs_varpropsetter in current_settings.localswitches then
  550. p.propaccesslist[palt_write].procdef:=Tprocsym(sym).Find_procdef_bypara(writeprocdef.paras,writeprocdef.returndef,[cpo_allowdefaults,cpo_ignorevarspez])
  551. else
  552. p.propaccesslist[palt_write].procdef:=Tprocsym(sym).Find_procdef_bypara(writeprocdef.paras,writeprocdef.returndef,[cpo_allowdefaults]);
  553. if not assigned(p.propaccesslist[palt_write].procdef) then
  554. Message(parser_e_ill_property_access_sym);
  555. end;
  556. fieldvarsym :
  557. begin
  558. if not assigned(def) then
  559. internalerror(200310072);
  560. if compare_defs(def,p.propdef,nothingn)>=te_equal then
  561. begin
  562. { property parameters are allowed if this is
  563. an indexed property, because the index is then
  564. the parameter.
  565. Note: In the help of Kylix it is written
  566. that it isn't allowed, but the compiler accepts it (PFV) }
  567. if (ppo_hasparameters in p.propoptions) or
  568. ((sp_static in p.symoptions) <> (sp_static in sym.symoptions)) then
  569. Message(parser_e_ill_property_access_sym);
  570. end
  571. else
  572. IncompatibleTypes(def,p.propdef);
  573. end;
  574. else
  575. Message(parser_e_ill_property_access_sym);
  576. end;
  577. end;
  578. end;
  579. end
  580. else
  581. parse_dispinterface(p,readprocdef,writeprocdef,paranr);
  582. { stored is not allowed for dispinterfaces, records or class properties }
  583. if assigned(astruct) and not(is_dispinterface(astruct) or is_record(astruct)) and not is_classproperty then
  584. begin
  585. { ppo_stored is default on for not overridden properties }
  586. if not assigned(p.overriddenpropsym) then
  587. include(p.propoptions,ppo_stored);
  588. if try_to_consume(_STORED) then
  589. begin
  590. include(p.propoptions,ppo_stored);
  591. p.propaccesslist[palt_stored].clear;
  592. case token of
  593. _ID:
  594. begin
  595. { in the case that idtoken=_DEFAULT }
  596. { we have to do nothing except }
  597. { setting ppo_stored, it's the same }
  598. { as stored true }
  599. if idtoken<>_DEFAULT then
  600. begin
  601. { parse_symlist cannot deal with constsyms, and
  602. we also don't want to put constsyms in symlists
  603. since they have to be evaluated immediately rather
  604. than each time the property is accessed
  605. The proper fix would be to always create a parse tree
  606. and then convert that one, if appropriate, to a symlist.
  607. Currently, we e.g. don't support any constant expressions
  608. yet either here, while Delphi does.
  609. }
  610. { make sure we don't let constants mask class fields/
  611. methods
  612. }
  613. if (not assigned(astruct) or
  614. (search_struct_member(astruct,pattern)=nil)) and
  615. searchsym(pattern,sym,srsymtable) and
  616. (sym.typ = constsym) then
  617. begin
  618. addsymref(sym);
  619. if not is_boolean(tconstsym(sym).constdef) then
  620. Message(parser_e_stored_property_must_be_boolean)
  621. else if (tconstsym(sym).value.valueord=0) then
  622. { same as for _FALSE }
  623. exclude(p.propoptions,ppo_stored)
  624. else
  625. { same as for _TRUE }
  626. p.default:=longint($80000000);
  627. consume(_ID);
  628. end
  629. else if parse_symlist(p.propaccesslist[palt_stored],def) then
  630. begin
  631. sym:=p.propaccesslist[palt_stored].firstsym^.sym;
  632. case sym.typ of
  633. procsym :
  634. begin
  635. { Create a temporary procvardef to handle parameters }
  636. storedprocdef:=tprocvardef.create(normal_function_level);
  637. include(storedprocdef.procoptions,po_methodpointer);
  638. { Return type must be boolean }
  639. storedprocdef.returndef:=pasbool8type;
  640. { Add index parameter if needed }
  641. if ppo_indexed in p.propoptions then
  642. begin
  643. hparavs:=tparavarsym.create('$index',10,vs_value,p.indexdef,[]);
  644. storedprocdef.parast.insert(hparavs);
  645. end;
  646. { Insert hidden parameters }
  647. handle_calling_convention(storedprocdef);
  648. p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).Find_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]);
  649. if not assigned(p.propaccesslist[palt_stored].procdef) then
  650. message(parser_e_ill_property_storage_sym);
  651. { Not needed anymore }
  652. storedprocdef.owner.deletedef(storedprocdef);
  653. end;
  654. fieldvarsym :
  655. begin
  656. if not assigned(def) then
  657. internalerror(200310073);
  658. if (ppo_hasparameters in p.propoptions) or
  659. not(is_boolean(def)) then
  660. Message(parser_e_stored_property_must_be_boolean);
  661. end;
  662. else
  663. Message(parser_e_ill_property_access_sym);
  664. end;
  665. end;
  666. end;
  667. end;
  668. _FALSE:
  669. begin
  670. consume(_FALSE);
  671. exclude(p.propoptions,ppo_stored);
  672. end;
  673. _TRUE:
  674. begin
  675. p.default:=longint($80000000);
  676. consume(_TRUE);
  677. end;
  678. end;
  679. end;
  680. end;
  681. if not is_record(astruct) and try_to_consume(_DEFAULT) then
  682. begin
  683. if not allow_default_property(p) then
  684. begin
  685. Message(parser_e_property_cant_have_a_default_value);
  686. { Error recovery }
  687. pt:=comp_expr(true,false);
  688. pt.free;
  689. end
  690. else
  691. begin
  692. { Get the result of the default, the firstpass is
  693. needed to support values like -1 }
  694. pt:=comp_expr(true,false);
  695. if (p.propdef.typ=setdef) and
  696. (pt.nodetype=arrayconstructorn) then
  697. begin
  698. arrayconstructor_to_set(pt);
  699. do_typecheckpass(pt);
  700. end;
  701. inserttypeconv(pt,p.propdef);
  702. if not(is_constnode(pt)) then
  703. Message(parser_e_property_default_value_must_const);
  704. { Set default value }
  705. case pt.nodetype of
  706. setconstn :
  707. p.default:=plongint(tsetconstnode(pt).value_set)^;
  708. ordconstn :
  709. if (Tordconstnode(pt).value<int64(low(longint))) or
  710. (Tordconstnode(pt).value>int64(high(cardinal))) then
  711. message(parser_e_range_check_error)
  712. else
  713. p.default:=longint(tordconstnode(pt).value.svalue);
  714. niln :
  715. p.default:=0;
  716. realconstn:
  717. p.default:=longint(single(trealconstnode(pt).value_real));
  718. end;
  719. pt.free;
  720. end;
  721. end
  722. else if not is_record(astruct) and try_to_consume(_NODEFAULT) then
  723. begin
  724. p.default:=longint($80000000);
  725. end;
  726. (*
  727. else {if allow_default_property(p) then
  728. begin
  729. p.default:=longint($80000000);
  730. end;
  731. *)
  732. { Parse possible "implements" keyword }
  733. if not is_record(astruct) and try_to_consume(_IMPLEMENTS) then
  734. begin
  735. single_type(def,[]);
  736. if not(is_interface(def)) then
  737. message(parser_e_class_implements_must_be_interface);
  738. if is_interface(p.propdef) then
  739. begin
  740. if compare_defs(def,p.propdef,nothingn)<te_equal then
  741. begin
  742. message2(parser_e_implements_must_have_correct_type,def.typename,p.propdef.typename);
  743. exit;
  744. end;
  745. end
  746. else if is_class(p.propdef) then
  747. begin
  748. ImplIntf:=tobjectdef(p.propdef).find_implemented_interface(tobjectdef(def));
  749. if assigned(ImplIntf) then
  750. begin
  751. if compare_defs(ImplIntf.IntfDef,def,nothingn)<te_equal then
  752. begin
  753. message2(parser_e_implements_must_have_correct_type,ImplIntf.IntfDef.typename,def.typename);
  754. exit;
  755. end;
  756. end
  757. else
  758. begin
  759. message2(parser_e_class_doesnt_implement_interface,p.propdef.typename,def.typename);
  760. exit;
  761. end;
  762. end
  763. else
  764. begin
  765. message(parser_e_implements_must_be_class_or_interface);
  766. exit;
  767. end;
  768. if not assigned(p.propaccesslist[palt_read].firstsym) then
  769. begin
  770. message(parser_e_implements_must_read_specifier);
  771. exit;
  772. end;
  773. if assigned(p.propaccesslist[palt_read].procdef) and
  774. (tprocdef(p.propaccesslist[palt_read].procdef).proccalloption<>pocall_default) then
  775. message(parser_e_implements_getter_not_default_cc);
  776. if assigned(p.propaccesslist[palt_write].firstsym) then
  777. begin
  778. message(parser_e_implements_must_not_have_write_specifier);
  779. exit;
  780. end;
  781. if assigned(p.propaccesslist[palt_stored].firstsym) then
  782. begin
  783. message(parser_e_implements_must_not_have_stored_specifier);
  784. exit;
  785. end;
  786. found:=false;
  787. for i:=0 to tobjectdef(astruct).ImplementedInterfaces.Count-1 do
  788. begin
  789. ImplIntf:=TImplementedInterface(tobjectdef(astruct).ImplementedInterfaces[i]);
  790. if compare_defs(def,ImplIntf.IntfDef,nothingn)>=te_equal then
  791. begin
  792. found:=true;
  793. break;
  794. end;
  795. end;
  796. if found then
  797. begin
  798. ImplIntf.ImplementsGetter:=p;
  799. ImplIntf.VtblImplIntf:=ImplIntf;
  800. case p.propaccesslist[palt_read].firstsym^.sym.typ of
  801. procsym :
  802. begin
  803. if (po_virtualmethod in tprocdef(p.propaccesslist[palt_read].procdef).procoptions) and
  804. not is_objectpascal_helper(tprocdef(p.propaccesslist[palt_read].procdef).struct) then
  805. ImplIntf.IType:=etVirtualMethodResult
  806. else
  807. ImplIntf.IType:=etStaticMethodResult;
  808. end;
  809. fieldvarsym :
  810. begin
  811. ImplIntf.IType:=etFieldValue;
  812. { this must be done more sophisticated, here is also probably the wrong place }
  813. ImplIntf.IOffset:=tfieldvarsym(p.propaccesslist[palt_read].firstsym^.sym).fieldoffset;
  814. end
  815. else
  816. internalerror(200802161);
  817. end;
  818. if not is_interface(p.propdef) then
  819. case ImplIntf.IType of
  820. etVirtualMethodResult: ImplIntf.IType := etVirtualMethodClass;
  821. etStaticMethodResult: ImplIntf.IType := etStaticMethodClass;
  822. etFieldValue: ImplIntf.IType := etFieldValueClass;
  823. else
  824. internalerror(200912101);
  825. end;
  826. end
  827. else
  828. message1(parser_e_implements_uses_non_implemented_interface,def.typename);
  829. end;
  830. { remove unneeded procdefs }
  831. if readprocdef.proctypeoption<>potype_propgetter then
  832. readprocdef.owner.deletedef(readprocdef);
  833. if writeprocdef.proctypeoption<>potype_propsetter then
  834. writeprocdef.owner.deletedef(writeprocdef);
  835. result:=p;
  836. end;
  837. function maybe_parse_proc_directives(def:tdef):boolean;
  838. var
  839. newtype : ttypesym;
  840. begin
  841. result:=false;
  842. { Process procvar directives before = and ; }
  843. if (def.typ=procvardef) and
  844. (def.typesym=nil) and
  845. check_proc_directive(true) then
  846. begin
  847. newtype:=ttypesym.create('unnamed',def);
  848. parse_var_proc_directives(tsym(newtype));
  849. newtype.typedef:=nil;
  850. def.typesym:=nil;
  851. newtype.free;
  852. result:=true;
  853. end;
  854. end;
  855. const
  856. variantrecordlevel : longint = 0;
  857. procedure read_public_and_external_sc(sc:TFPObjectList);
  858. var
  859. vs: tabstractvarsym;
  860. begin
  861. { only allowed for one var }
  862. vs:=tabstractvarsym(sc[0]);
  863. if sc.count>1 then
  864. Message(parser_e_absolute_only_one_var);
  865. read_public_and_external(vs);
  866. end;
  867. procedure read_public_and_external(vs: tabstractvarsym);
  868. var
  869. is_dll,
  870. is_cdecl,
  871. is_external_var,
  872. is_weak_external,
  873. is_public_var : boolean;
  874. dll_name,section_name,
  875. C_name,mangledname : string;
  876. begin
  877. { only allowed for one var }
  878. { only allow external and public on global symbols }
  879. if vs.typ<>staticvarsym then
  880. begin
  881. Message(parser_e_no_local_var_external);
  882. exit;
  883. end;
  884. { defaults }
  885. is_dll:=false;
  886. is_cdecl:=false;
  887. is_external_var:=false;
  888. is_public_var:=false;
  889. section_name := '';
  890. C_name:=vs.realname;
  891. { macpas specific handling due to some switches}
  892. if (m_mac in current_settings.modeswitches) then
  893. begin
  894. if (cs_external_var in current_settings.localswitches) then
  895. begin {The effect of this is the same as if cvar; external; has been given as directives.}
  896. is_cdecl:=true;
  897. is_external_var:=true;
  898. end
  899. else if (cs_externally_visible in current_settings.localswitches) then
  900. begin {The effect of this is the same as if cvar has been given as directives and it's made public.}
  901. is_cdecl:=true;
  902. is_public_var:=true;
  903. end;
  904. end;
  905. { cdecl }
  906. if try_to_consume(_CVAR) then
  907. begin
  908. consume(_SEMICOLON);
  909. is_cdecl:=true;
  910. end;
  911. { external }
  912. is_weak_external:=try_to_consume(_WEAKEXTERNAL);
  913. if is_weak_external or
  914. try_to_consume(_EXTERNAL) then
  915. begin
  916. is_external_var:=true;
  917. if (idtoken<>_NAME) and (token<>_SEMICOLON) then
  918. begin
  919. is_dll:=true;
  920. dll_name:=get_stringconst;
  921. if ExtractFileExt(dll_name)='' then
  922. dll_name:=ChangeFileExt(dll_name,target_info.sharedlibext);
  923. end;
  924. if not(is_cdecl) and try_to_consume(_NAME) then
  925. C_name:=get_stringconst;
  926. consume(_SEMICOLON);
  927. end;
  928. { export or public }
  929. if idtoken in [_EXPORT,_PUBLIC] then
  930. begin
  931. consume(_ID);
  932. if is_external_var then
  933. Message(parser_e_not_external_and_export)
  934. else
  935. is_public_var:=true;
  936. if try_to_consume(_NAME) then
  937. C_name:=get_stringconst;
  938. if (target_info.system in systems_allow_section_no_semicolon) and
  939. (vs.typ=staticvarsym) and
  940. try_to_consume (_SECTION) then
  941. section_name:=get_stringconst;
  942. consume(_SEMICOLON);
  943. end;
  944. { Windows uses an indirect reference using import tables }
  945. if is_dll and
  946. (target_info.system in systems_all_windows+[system_i386_symobi]) then
  947. include(vs.varoptions,vo_is_dll_var);
  948. { This can only happen if vs.typ=staticvarsym }
  949. if section_name<>'' then
  950. begin
  951. tstaticvarsym(vs).section:=section_name;
  952. include(vs.varoptions,vo_has_section);
  953. end;
  954. { Add C _ prefix }
  955. if is_cdecl or
  956. (
  957. is_dll and
  958. (target_info.system in systems_darwin)
  959. ) then
  960. C_Name := target_info.Cprefix+C_Name;
  961. if is_public_var then
  962. begin
  963. include(vs.varoptions,vo_is_public);
  964. vs.varregable := vr_none;
  965. { mark as referenced }
  966. inc(vs.refs);
  967. end;
  968. mangledname:=C_name;
  969. { now we can insert it in the import lib if its a dll, or
  970. add it to the externals }
  971. if is_external_var then
  972. begin
  973. if vo_is_typed_const in vs.varoptions then
  974. Message(parser_e_initialized_not_for_external);
  975. include(vs.varoptions,vo_is_external);
  976. if (is_weak_external) then
  977. begin
  978. if not(target_info.system in systems_weak_linking) then
  979. message(parser_e_weak_external_not_supported);
  980. include(vs.varoptions,vo_is_weak_external);
  981. end;
  982. vs.varregable := vr_none;
  983. if is_dll then
  984. begin
  985. if target_info.system in (systems_all_windows + systems_nativent +
  986. [system_i386_emx, system_i386_os2]) then
  987. mangledname:=make_dllmangledname(dll_name,C_name,0,pocall_none);
  988. current_module.AddExternalImport(dll_name,C_Name,mangledname,0,true,false);
  989. end
  990. else
  991. if tf_has_dllscanner in target_info.flags then
  992. current_module.dllscannerinputlist.Add(vs.mangledname,vs);
  993. end;
  994. { Set the assembler name }
  995. tstaticvarsym(vs).set_mangledname(mangledname);
  996. end;
  997. procedure try_consume_sectiondirective(var asection: ansistring);
  998. begin
  999. if idtoken=_SECTION then
  1000. begin
  1001. consume(_ID);
  1002. asection:=get_stringconst;
  1003. consume(_SEMICOLON);
  1004. end;
  1005. end;
  1006. procedure read_var_decls(options:Tvar_dec_options);
  1007. procedure read_default_value(sc : TFPObjectList);
  1008. var
  1009. vs : tabstractnormalvarsym;
  1010. tcsym : tstaticvarsym;
  1011. begin
  1012. vs:=tabstractnormalvarsym(sc[0]);
  1013. if sc.count>1 then
  1014. Message(parser_e_initialized_only_one_var);
  1015. if vo_is_thread_var in vs.varoptions then
  1016. Message(parser_e_initialized_not_for_threadvar);
  1017. consume(_EQ);
  1018. case vs.typ of
  1019. localvarsym :
  1020. begin
  1021. tcsym:=tstaticvarsym.create('$default'+vs.realname,vs_const,vs.vardef,[]);
  1022. include(tcsym.symoptions,sp_internal);
  1023. vs.defaultconstsym:=tcsym;
  1024. symtablestack.top.insert(tcsym);
  1025. read_typed_const(current_asmdata.asmlists[al_typedconsts],tcsym,false);
  1026. end;
  1027. staticvarsym :
  1028. begin
  1029. read_typed_const(current_asmdata.asmlists[al_typedconsts],tstaticvarsym(vs),false);
  1030. end;
  1031. else
  1032. internalerror(200611051);
  1033. end;
  1034. vs.varstate:=vs_initialised;
  1035. end;
  1036. {$ifdef gpc_mode}
  1037. procedure read_gpc_name(sc : TFPObjectList);
  1038. var
  1039. vs : tabstractnormalvarsym;
  1040. C_Name : string;
  1041. begin
  1042. consume(_ID);
  1043. C_Name:=get_stringconst;
  1044. vs:=tabstractnormalvarsym(sc[0]);
  1045. if sc.count>1 then
  1046. Message(parser_e_absolute_only_one_var);
  1047. if vs.typ=staticvarsym then
  1048. begin
  1049. tstaticvarsym(vs).set_mangledname(C_Name);
  1050. include(vs.varoptions,vo_is_external);
  1051. end
  1052. else
  1053. Message(parser_e_no_local_var_external);
  1054. end;
  1055. {$endif}
  1056. procedure read_absolute(sc : TFPObjectList);
  1057. var
  1058. vs : tabstractvarsym;
  1059. abssym : tabsolutevarsym;
  1060. pt,hp : tnode;
  1061. st : tsymtable;
  1062. {$ifdef i386}
  1063. tmpaddr : int64;
  1064. {$endif}
  1065. begin
  1066. abssym:=nil;
  1067. { only allowed for one var }
  1068. vs:=tabstractvarsym(sc[0]);
  1069. if sc.count>1 then
  1070. Message(parser_e_absolute_only_one_var);
  1071. if vo_is_typed_const in vs.varoptions then
  1072. Message(parser_e_initialized_not_for_external);
  1073. { parse the rest }
  1074. pt:=expr(true);
  1075. { check allowed absolute types }
  1076. if (pt.nodetype=stringconstn) or
  1077. (is_constcharnode(pt)) then
  1078. begin
  1079. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1080. abssym.fileinfo:=vs.fileinfo;
  1081. if pt.nodetype=stringconstn then
  1082. abssym.asmname:=stringdup(strpas(tstringconstnode(pt).value_str))
  1083. else
  1084. abssym.asmname:=stringdup(chr(tordconstnode(pt).value.svalue));
  1085. consume(token);
  1086. abssym.abstyp:=toasm;
  1087. end
  1088. { address }
  1089. else if is_constintnode(pt) then
  1090. begin
  1091. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1092. abssym.fileinfo:=vs.fileinfo;
  1093. abssym.abstyp:=toaddr;
  1094. {$ifndef cpu64bitaddr}
  1095. { on 64 bit systems, abssym.addroffset is a qword and hence this
  1096. test is useless (value is a 64 bit entity) and will always fail
  1097. for positive values (since int64(high(abssym.addroffset))=-1
  1098. }
  1099. if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
  1100. (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
  1101. message(parser_e_range_check_error)
  1102. else
  1103. {$endif}
  1104. abssym.addroffset:=Tordconstnode(pt).value.svalue;
  1105. {$ifdef i386}
  1106. abssym.absseg:=false;
  1107. if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
  1108. try_to_consume(_COLON) then
  1109. begin
  1110. pt.free;
  1111. pt:=expr(true);
  1112. if is_constintnode(pt) then
  1113. begin
  1114. tmpaddr:=abssym.addroffset shl 4+tordconstnode(pt).value.svalue;
  1115. if (tmpaddr<int64(low(abssym.addroffset))) or
  1116. (tmpaddr>int64(high(abssym.addroffset))) then
  1117. message(parser_e_range_check_error)
  1118. else
  1119. abssym.addroffset:=tmpaddr;
  1120. abssym.absseg:=true;
  1121. end
  1122. else
  1123. Message(type_e_ordinal_expr_expected);
  1124. end;
  1125. {$endif i386}
  1126. end
  1127. { variable }
  1128. else
  1129. begin
  1130. { we have to be able to take the address of the absolute
  1131. expression
  1132. }
  1133. valid_for_addr(pt,true);
  1134. { remove subscriptn before checking for loadn }
  1135. hp:=pt;
  1136. while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
  1137. begin
  1138. { check for implicit dereferencing and reject it }
  1139. if (hp.nodetype in [subscriptn,vecn]) then
  1140. begin
  1141. if (tunarynode(hp).left.resultdef.typ in [pointerdef,classrefdef]) then
  1142. break;
  1143. { catch, e.g., 'var b: char absolute pchar_var[5];"
  1144. (pchar_var[5] is a pchar_2_string typeconv ->
  1145. the vecn only sees an array of char)
  1146. I don't know if all of these type conversions are
  1147. possible, but they're definitely all bad.
  1148. }
  1149. if (tunarynode(hp).left.nodetype=typeconvn) and
  1150. (ttypeconvnode(tunarynode(hp).left).convtype in
  1151. [tc_pchar_2_string,tc_pointer_2_array,
  1152. tc_intf_2_string,tc_intf_2_guid,
  1153. tc_dynarray_2_variant,tc_interface_2_variant,
  1154. tc_array_2_dynarray]) then
  1155. break;
  1156. if (tunarynode(hp).left.resultdef.typ=stringdef) and
  1157. not(tstringdef(tunarynode(hp).left.resultdef).stringtype in [st_shortstring,st_longstring]) then
  1158. break;
  1159. if (tunarynode(hp).left.resultdef.typ=objectdef) and
  1160. (tobjectdef(tunarynode(hp).left.resultdef).objecttype<>odt_object) then
  1161. break;
  1162. if is_dynamic_array(tunarynode(hp).left.resultdef) then
  1163. break;
  1164. end;
  1165. hp:=tunarynode(hp).left;
  1166. end;
  1167. if (hp.nodetype=loadn) then
  1168. begin
  1169. { we should check the result type of loadn }
  1170. if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,staticvarsym,localvarsym,paravarsym]) then
  1171. Message(parser_e_absolute_only_to_var_or_const);
  1172. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1173. abssym.fileinfo:=vs.fileinfo;
  1174. abssym.abstyp:=tovar;
  1175. abssym.ref:=node_to_propaccesslist(pt);
  1176. { if the sizes are different, can't be a regvar since you }
  1177. { can't be "absolute upper 8 bits of a register" (except }
  1178. { if its a record field of the same size of a record }
  1179. { regvar, but in that case pt.resultdef.size will have }
  1180. { the same size since it refers to the field and not to }
  1181. { the whole record -- which is why we use pt and not hp) }
  1182. { we can't take the size of an open array }
  1183. if is_open_array(pt.resultdef) or
  1184. (vs.vardef.size <> pt.resultdef.size) then
  1185. make_not_regable(pt,[ra_addr_regable]);
  1186. end
  1187. else
  1188. Message(parser_e_absolute_only_to_var_or_const);
  1189. end;
  1190. pt.free;
  1191. { replace old varsym with the new absolutevarsym }
  1192. if assigned(abssym) then
  1193. begin
  1194. st:=vs.owner;
  1195. vs.owner.Delete(vs);
  1196. st.insert(abssym);
  1197. sc[0]:=abssym;
  1198. end;
  1199. end;
  1200. var
  1201. sc : TFPObjectList;
  1202. vs : tabstractvarsym;
  1203. hdef : tdef;
  1204. i : longint;
  1205. semicoloneaten,
  1206. allowdefaultvalue,
  1207. hasdefaultvalue : boolean;
  1208. hintsymoptions : tsymoptions;
  1209. deprecatedmsg : pshortstring;
  1210. old_block_type : tblock_type;
  1211. sectionname : ansistring;
  1212. begin
  1213. old_block_type:=block_type;
  1214. block_type:=bt_var;
  1215. { Force an expected ID error message }
  1216. if not (token in [_ID,_CASE,_END]) then
  1217. consume(_ID);
  1218. { read vars }
  1219. sc:=TFPObjectList.create(false);
  1220. while (token=_ID) do
  1221. begin
  1222. semicoloneaten:=false;
  1223. hasdefaultvalue:=false;
  1224. allowdefaultvalue:=true;
  1225. sc.clear;
  1226. repeat
  1227. if (token = _ID) then
  1228. begin
  1229. case symtablestack.top.symtabletype of
  1230. localsymtable :
  1231. vs:=tlocalvarsym.create(orgpattern,vs_value,generrordef,[]);
  1232. staticsymtable,
  1233. globalsymtable :
  1234. begin
  1235. vs:=tstaticvarsym.create(orgpattern,vs_value,generrordef,[]);
  1236. if vd_threadvar in options then
  1237. include(vs.varoptions,vo_is_thread_var);
  1238. end;
  1239. else
  1240. internalerror(200411064);
  1241. end;
  1242. sc.add(vs);
  1243. symtablestack.top.insert(vs);
  1244. end;
  1245. consume(_ID);
  1246. until not try_to_consume(_COMMA);
  1247. { read variable type def }
  1248. block_type:=bt_var_type;
  1249. consume(_COLON);
  1250. {$ifdef gpc_mode}
  1251. if (m_gpc in current_settings.modeswitches) and
  1252. (token=_ID) and
  1253. (orgpattern='__asmname__') then
  1254. read_gpc_name(sc);
  1255. {$endif}
  1256. read_anon_type(hdef,false);
  1257. for i:=0 to sc.count-1 do
  1258. begin
  1259. vs:=tabstractvarsym(sc[i]);
  1260. vs.vardef:=hdef;
  1261. end;
  1262. block_type:=bt_var;
  1263. { Process procvar directives }
  1264. if maybe_parse_proc_directives(hdef) then
  1265. semicoloneaten:=true;
  1266. { check for absolute }
  1267. if try_to_consume(_ABSOLUTE) then
  1268. begin
  1269. read_absolute(sc);
  1270. allowdefaultvalue:=false;
  1271. end;
  1272. { Check for EXTERNAL etc directives before a semicolon }
  1273. if (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) then
  1274. begin
  1275. read_public_and_external_sc(sc);
  1276. allowdefaultvalue:=false;
  1277. semicoloneaten:=true;
  1278. end;
  1279. { try to parse the hint directives }
  1280. hintsymoptions:=[];
  1281. deprecatedmsg:=nil;
  1282. try_consume_hintdirective(hintsymoptions,deprecatedmsg);
  1283. for i:=0 to sc.count-1 do
  1284. begin
  1285. vs:=tabstractvarsym(sc[i]);
  1286. vs.symoptions := vs.symoptions + hintsymoptions;
  1287. if deprecatedmsg<>nil then
  1288. vs.deprecatedmsg:=stringdup(deprecatedmsg^);
  1289. end;
  1290. stringdispose(deprecatedmsg);
  1291. { Handling of Delphi typed const = initialized vars }
  1292. if allowdefaultvalue and
  1293. (token=_EQ) and
  1294. not(m_tp7 in current_settings.modeswitches) and
  1295. (symtablestack.top.symtabletype<>parasymtable) then
  1296. begin
  1297. { Add calling convention for procvar }
  1298. if (hdef.typ=procvardef) and
  1299. (hdef.typesym=nil) then
  1300. handle_calling_convention(tprocvardef(hdef));
  1301. read_default_value(sc);
  1302. hasdefaultvalue:=true;
  1303. end
  1304. else
  1305. begin
  1306. if not(semicoloneaten) then
  1307. consume(_SEMICOLON);
  1308. end;
  1309. { Support calling convention for procvars after semicolon }
  1310. if not(hasdefaultvalue) and
  1311. (hdef.typ=procvardef) and
  1312. (hdef.typesym=nil) then
  1313. begin
  1314. { Parse procvar directives after ; }
  1315. maybe_parse_proc_directives(hdef);
  1316. { Add calling convention for procvar }
  1317. handle_calling_convention(tprocvardef(hdef));
  1318. { Handling of Delphi typed const = initialized vars }
  1319. if (token=_EQ) and
  1320. not(m_tp7 in current_settings.modeswitches) and
  1321. (symtablestack.top.symtabletype<>parasymtable) then
  1322. begin
  1323. read_default_value(sc);
  1324. hasdefaultvalue:=true;
  1325. end;
  1326. end;
  1327. { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
  1328. if (
  1329. (
  1330. (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) and
  1331. (m_cvar_support in current_settings.modeswitches)
  1332. ) or
  1333. (
  1334. (m_mac in current_settings.modeswitches) and
  1335. (
  1336. (cs_external_var in current_settings.localswitches) or
  1337. (cs_externally_visible in current_settings.localswitches)
  1338. )
  1339. )
  1340. ) then
  1341. read_public_and_external_sc(sc);
  1342. { try to parse a section directive }
  1343. if (target_info.system in systems_allow_section) and
  1344. (symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) and
  1345. (idtoken=_SECTION) then
  1346. begin
  1347. try_consume_sectiondirective(sectionname);
  1348. if sectionname<>'' then
  1349. begin
  1350. for i:=0 to sc.count-1 do
  1351. begin
  1352. vs:=tabstractvarsym(sc[i]);
  1353. if (vs.varoptions *[vo_is_external,vo_is_weak_external])<>[] then
  1354. Message(parser_e_externals_no_section);
  1355. if vs.typ<>staticvarsym then
  1356. Message(parser_e_section_no_locals);
  1357. tstaticvarsym(vs).section:=sectionname;
  1358. include(vs.varoptions, vo_has_section);
  1359. end;
  1360. end;
  1361. end;
  1362. { allocate normal variable (non-external and non-typed-const) staticvarsyms }
  1363. for i:=0 to sc.count-1 do
  1364. begin
  1365. vs:=tabstractvarsym(sc[i]);
  1366. if (vs.typ=staticvarsym) and
  1367. not(vo_is_typed_const in vs.varoptions) and
  1368. not(vo_is_external in vs.varoptions) then
  1369. insertbssdata(tstaticvarsym(vs));
  1370. end;
  1371. end;
  1372. block_type:=old_block_type;
  1373. { free the list }
  1374. sc.free;
  1375. end;
  1376. procedure read_record_fields(options:Tvar_dec_options);
  1377. var
  1378. sc : TFPObjectList;
  1379. i : longint;
  1380. hs,sorg,static_name : string;
  1381. hdef,casetype : tdef;
  1382. { maxsize contains the max. size of a variant }
  1383. { startvarrec contains the start of the variant part of a record }
  1384. maxsize, startvarrecsize : longint;
  1385. usedalign,
  1386. maxalignment,startvarrecalign,
  1387. maxpadalign, startpadalign: shortint;
  1388. pt : tnode;
  1389. fieldvs : tfieldvarsym;
  1390. hstaticvs : tstaticvarsym;
  1391. vs : tabstractvarsym;
  1392. srsym : tsym;
  1393. srsymtable : TSymtable;
  1394. visibility : tvisibility;
  1395. recst : tabstractrecordsymtable;
  1396. recstlist : tfpobjectlist;
  1397. unionsymtable : trecordsymtable;
  1398. offset : longint;
  1399. uniondef : trecorddef;
  1400. hintsymoptions : tsymoptions;
  1401. deprecatedmsg : pshortstring;
  1402. semicoloneaten: boolean;
  1403. {$if defined(powerpc) or defined(powerpc64)}
  1404. tempdef: tdef;
  1405. is_first_type: boolean;
  1406. {$endif powerpc or powerpc64}
  1407. sl: tpropaccesslist;
  1408. old_block_type: tblock_type;
  1409. begin
  1410. old_block_type:=block_type;
  1411. block_type:=bt_var;
  1412. recst:=tabstractrecordsymtable(symtablestack.top);
  1413. {$if defined(powerpc) or defined(powerpc64)}
  1414. is_first_type:=true;
  1415. {$endif powerpc or powerpc64}
  1416. { Force an expected ID error message }
  1417. if not (token in [_ID,_CASE,_END]) then
  1418. consume(_ID);
  1419. { read vars }
  1420. sc:=TFPObjectList.create(false);
  1421. recstlist:=TFPObjectList.create(false);;
  1422. while (token=_ID) and
  1423. not(((vd_object in options) or
  1424. ((vd_record in options) and (m_advanced_records in current_settings.modeswitches))) and
  1425. (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
  1426. begin
  1427. visibility:=symtablestack.top.currentvisibility;
  1428. semicoloneaten:=false;
  1429. sc.clear;
  1430. repeat
  1431. sorg:=orgpattern;
  1432. if token=_ID then
  1433. begin
  1434. vs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1435. sc.add(vs);
  1436. recst.insert(vs);
  1437. end;
  1438. consume(_ID);
  1439. until not try_to_consume(_COMMA);
  1440. if m_delphi in current_settings.modeswitches then
  1441. block_type:=bt_var_type
  1442. else
  1443. block_type:=old_block_type;
  1444. consume(_COLON);
  1445. { Don't search for types where they can't be:
  1446. types can be only in objects, classes and records.
  1447. This just speedup the search a bit. }
  1448. recstlist.count:=0;
  1449. if not is_class_or_object(tdef(recst.defowner)) and
  1450. not is_record(tdef(recst.defowner)) then
  1451. begin
  1452. recstlist.add(recst);
  1453. symtablestack.pop(recst);
  1454. end;
  1455. read_anon_type(hdef,false);
  1456. block_type:=bt_var;
  1457. { allow only static fields reference to struct where they are declared }
  1458. if not (vd_class in options) and
  1459. (is_object(hdef) or is_record(hdef)) and
  1460. is_owned_by(tabstractrecorddef(recst.defowner),tabstractrecorddef(hdef)) then
  1461. begin
  1462. Message1(type_e_type_is_not_completly_defined, tabstractrecorddef(hdef).RttiName);
  1463. { for error recovery or compiler will crash later }
  1464. hdef:=generrordef;
  1465. end;
  1466. { restore stack }
  1467. for i:=recstlist.count-1 downto 0 do
  1468. begin
  1469. recst:=tabstractrecordsymtable(recstlist[i]);
  1470. symtablestack.push(recst);
  1471. end;
  1472. { Process procvar directives }
  1473. if maybe_parse_proc_directives(hdef) then
  1474. semicoloneaten:=true;
  1475. {$if defined(powerpc) or defined(powerpc64)}
  1476. { from gcc/gcc/config/rs6000/rs6000.h:
  1477. /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
  1478. /* Return the alignment of a struct based on the Macintosh PowerPC
  1479. alignment rules. In general the alignment of a struct is
  1480. determined by the greatest alignment of its elements. However, the
  1481. PowerPC rules cause the alignment of a struct to peg at word
  1482. alignment except when the first field has greater than word
  1483. (32-bit) alignment, in which case the alignment is determined by
  1484. the alignment of the first field. */
  1485. }
  1486. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1487. is_first_type and
  1488. (symtablestack.top.symtabletype=recordsymtable) and
  1489. (trecordsymtable(symtablestack.top).usefieldalignment=C_alignment) then
  1490. begin
  1491. tempdef:=hdef;
  1492. while tempdef.typ=arraydef do
  1493. tempdef:=tarraydef(tempdef).elementdef;
  1494. if tempdef.typ<>recorddef then
  1495. maxpadalign:=tempdef.alignment
  1496. else
  1497. maxpadalign:=trecorddef(tempdef).padalignment;
  1498. if (maxpadalign>4) and
  1499. (maxpadalign>trecordsymtable(symtablestack.top).padalignment) then
  1500. trecordsymtable(symtablestack.top).padalignment:=maxpadalign;
  1501. is_first_type:=false;
  1502. end;
  1503. {$endif powerpc or powerpc64}
  1504. { types that use init/final are not allowed in variant parts, but
  1505. classes are allowed }
  1506. if (variantrecordlevel>0) then
  1507. if is_managed_type(hdef) then
  1508. Message(parser_e_cant_use_inittable_here)
  1509. else
  1510. if hdef.typ=undefineddef then
  1511. Message(parser_e_cant_use_type_parameters_here);
  1512. { try to parse the hint directives }
  1513. hintsymoptions:=[];
  1514. deprecatedmsg:=nil;
  1515. try_consume_hintdirective(hintsymoptions,deprecatedmsg);
  1516. { update variable type and hints }
  1517. for i:=0 to sc.count-1 do
  1518. begin
  1519. fieldvs:=tfieldvarsym(sc[i]);
  1520. fieldvs.vardef:=hdef;
  1521. { insert any additional hint directives }
  1522. fieldvs.symoptions := fieldvs.symoptions + hintsymoptions;
  1523. if deprecatedmsg<>nil then
  1524. fieldvs.deprecatedmsg:=stringdup(deprecatedmsg^);
  1525. end;
  1526. stringdispose(deprecatedmsg);
  1527. { Records and objects can't have default values }
  1528. { for a record there doesn't need to be a ; before the END or ) }
  1529. if not(token in [_END,_RKLAMMER]) and
  1530. not(semicoloneaten) then
  1531. consume(_SEMICOLON);
  1532. { Parse procvar directives after ; }
  1533. maybe_parse_proc_directives(hdef);
  1534. { Add calling convention for procvar }
  1535. if (hdef.typ=procvardef) and
  1536. (hdef.typesym=nil) then
  1537. handle_calling_convention(tprocvardef(hdef));
  1538. { check if it is a class field }
  1539. if (vd_object in options) then
  1540. begin
  1541. { if it is not a class var section and token=STATIC then it is a class field too }
  1542. if not (vd_class in options) and try_to_consume(_STATIC) then
  1543. begin
  1544. consume(_SEMICOLON);
  1545. include(options, vd_class);
  1546. end;
  1547. end;
  1548. if vd_class in options then
  1549. begin
  1550. { add static flag and staticvarsyms }
  1551. for i:=0 to sc.count-1 do
  1552. begin
  1553. fieldvs:=tfieldvarsym(sc[i]);
  1554. include(fieldvs.symoptions,sp_static);
  1555. { generate the symbol which reserves the space }
  1556. static_name:=lower(generate_nested_name(recst,'_'))+'_'+fieldvs.name;
  1557. hstaticvs:=tstaticvarsym.create('$_static_'+static_name,vs_value,hdef,[]);
  1558. include(hstaticvs.symoptions,sp_internal);
  1559. recst.get_unit_symtable.insert(hstaticvs);
  1560. insertbssdata(hstaticvs);
  1561. { generate the symbol for the access }
  1562. sl:=tpropaccesslist.create;
  1563. sl.addsym(sl_load,hstaticvs);
  1564. recst.insert(tabsolutevarsym.create_ref('$'+static_name,hdef,sl));
  1565. end;
  1566. end;
  1567. if (visibility=vis_published) and
  1568. not(is_class(hdef)) then
  1569. begin
  1570. Message(parser_e_cant_publish_that);
  1571. visibility:=vis_public;
  1572. end;
  1573. if (visibility=vis_published) and
  1574. not(oo_can_have_published in tobjectdef(hdef).objectoptions) and
  1575. not(m_delphi in current_settings.modeswitches) then
  1576. begin
  1577. Message(parser_e_only_publishable_classes_can_be_published);
  1578. visibility:=vis_public;
  1579. end;
  1580. { Generate field in the recordsymtable }
  1581. for i:=0 to sc.count-1 do
  1582. begin
  1583. fieldvs:=tfieldvarsym(sc[i]);
  1584. { static data fields are already inserted in the globalsymtable }
  1585. if not(sp_static in fieldvs.symoptions) then
  1586. recst.addfield(fieldvs,visibility);
  1587. end;
  1588. end;
  1589. recstlist.free;
  1590. if m_delphi in current_settings.modeswitches then
  1591. block_type:=bt_var_type
  1592. else
  1593. block_type:=old_block_type;
  1594. { Check for Case }
  1595. if (vd_record in options) and
  1596. try_to_consume(_CASE) then
  1597. begin
  1598. maxsize:=0;
  1599. maxalignment:=0;
  1600. maxpadalign:=0;
  1601. { including a field declaration? }
  1602. fieldvs:=nil;
  1603. sorg:=orgpattern;
  1604. hs:=pattern;
  1605. searchsym(hs,srsym,srsymtable);
  1606. if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  1607. begin
  1608. consume(_ID);
  1609. consume(_COLON);
  1610. fieldvs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1611. symtablestack.top.insert(fieldvs);
  1612. end;
  1613. read_anon_type(casetype,true);
  1614. block_type:=bt_var;
  1615. if assigned(fieldvs) then
  1616. begin
  1617. fieldvs.vardef:=casetype;
  1618. recst.addfield(fieldvs,recst.currentvisibility);
  1619. end;
  1620. if not(is_ordinal(casetype))
  1621. {$ifndef cpu64bitaddr}
  1622. or is_64bitint(casetype)
  1623. {$endif cpu64bitaddr}
  1624. then
  1625. Message(type_e_ordinal_expr_expected);
  1626. consume(_OF);
  1627. UnionSymtable:=trecordsymtable.create('',current_settings.packrecords);
  1628. UnionDef:=trecorddef.create('',unionsymtable);
  1629. uniondef.isunion:=true;
  1630. startvarrecsize:=UnionSymtable.datasize;
  1631. { align the bitpacking to the next byte }
  1632. UnionSymtable.datasize:=startvarrecsize;
  1633. startvarrecalign:=UnionSymtable.fieldalignment;
  1634. startpadalign:=Unionsymtable.padalignment;
  1635. symtablestack.push(UnionSymtable);
  1636. repeat
  1637. repeat
  1638. pt:=comp_expr(true,false);
  1639. if not(pt.nodetype=ordconstn) then
  1640. Message(parser_e_illegal_expression);
  1641. if try_to_consume(_POINTPOINT) then
  1642. pt:=crangenode.create(pt,comp_expr(true,false));
  1643. pt.free;
  1644. if token=_COMMA then
  1645. consume(_COMMA)
  1646. else
  1647. break;
  1648. until false;
  1649. if m_delphi in current_settings.modeswitches then
  1650. block_type:=bt_var_type
  1651. else
  1652. block_type:=old_block_type;
  1653. consume(_COLON);
  1654. { read the vars }
  1655. consume(_LKLAMMER);
  1656. inc(variantrecordlevel);
  1657. if token<>_RKLAMMER then
  1658. read_record_fields([vd_record]);
  1659. dec(variantrecordlevel);
  1660. consume(_RKLAMMER);
  1661. { calculates maximal variant size }
  1662. maxsize:=max(maxsize,unionsymtable.datasize);
  1663. maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
  1664. maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
  1665. { the items of the next variant are overlayed }
  1666. unionsymtable.datasize:=startvarrecsize;
  1667. unionsymtable.fieldalignment:=startvarrecalign;
  1668. unionsymtable.padalignment:=startpadalign;
  1669. if (token<>_END) and (token<>_RKLAMMER) then
  1670. consume(_SEMICOLON)
  1671. else
  1672. break;
  1673. until (token=_END) or (token=_RKLAMMER);
  1674. symtablestack.pop(UnionSymtable);
  1675. { at last set the record size to that of the biggest variant }
  1676. unionsymtable.datasize:=maxsize;
  1677. unionsymtable.fieldalignment:=maxalignment;
  1678. unionsymtable.addalignmentpadding;
  1679. {$if defined(powerpc) or defined(powerpc64)}
  1680. { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
  1681. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1682. is_first_type and
  1683. (recst.usefieldalignment=C_alignment) and
  1684. (maxpadalign>recst.padalignment) then
  1685. recst.padalignment:=maxpadalign;
  1686. {$endif powerpc or powerpc64}
  1687. { Align the offset where the union symtable is added }
  1688. case recst.usefieldalignment of
  1689. { allow the unionsymtable to be aligned however it wants }
  1690. { (within the global min/max limits) }
  1691. 0, { default }
  1692. C_alignment:
  1693. usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
  1694. { 1 byte alignment if we are bitpacked }
  1695. bit_alignment:
  1696. usedalign:=1;
  1697. mac68k_alignment:
  1698. usedalign:=2;
  1699. { otherwise alignment at the packrecords alignment of the }
  1700. { current record }
  1701. else
  1702. usedalign:=used_align(recst.fieldalignment,current_settings.alignment.recordalignmin,current_settings.alignment.recordalignmax);
  1703. end;
  1704. offset:=align(recst.datasize,usedalign);
  1705. recst.datasize:=offset+unionsymtable.datasize;
  1706. if unionsymtable.recordalignment>recst.fieldalignment then
  1707. recst.fieldalignment:=unionsymtable.recordalignment;
  1708. trecordsymtable(recst).insertunionst(Unionsymtable,offset);
  1709. uniondef.owner.deletedef(uniondef);
  1710. end;
  1711. { free the list }
  1712. sc.free;
  1713. {$ifdef powerpc}
  1714. is_first_type := false;
  1715. {$endif powerpc}
  1716. block_type:=old_block_type;
  1717. end;
  1718. end.