pdecvar.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Parses variable declarations. Used for var statement and record
  5. definitions
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit pdecvar;
  20. {$i defines.inc}
  21. interface
  22. procedure read_var_decs(is_record,is_object,is_threadvar:boolean);
  23. implementation
  24. uses
  25. { common }
  26. cutils,
  27. { global }
  28. globtype,globals,tokens,verbose,
  29. systems,
  30. { symtable }
  31. symconst,symbase,symtype,symdef,symsym,symtable,types,fmodule,
  32. { pass 1 }
  33. node,
  34. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
  35. { parser }
  36. scanner,
  37. pbase,pexpr,ptype,ptconst,pdecsub,
  38. { link }
  39. import;
  40. const
  41. variantrecordlevel : longint = 0;
  42. procedure read_var_decs(is_record,is_object,is_threadvar:boolean);
  43. { reads the filed of a record into a }
  44. { symtablestack, if record=false }
  45. { variants are forbidden, so this procedure }
  46. { can be used to read object fields }
  47. { if absolute is true, ABSOLUTE and file }
  48. { types are allowed }
  49. { => the procedure is also used to read }
  50. { a sequence of variable declaration }
  51. procedure insert_syms(st : tsymtable;sc : tidstringlist;tt : ttype;is_threadvar : boolean);
  52. { inserts the symbols of sc in st with def as definition or sym as ttypesym, sc is disposed }
  53. var
  54. s : string;
  55. filepos : tfileposinfo;
  56. ss : tvarsym;
  57. begin
  58. filepos:=akttokenpos;
  59. while not sc.empty do
  60. begin
  61. s:=sc.get(akttokenpos);
  62. ss:=tvarsym.Create(s,tt);
  63. if is_threadvar then
  64. include(ss.varoptions,vo_is_thread_var);
  65. st.insert(ss);
  66. { static data fields are inserted in the globalsymtable }
  67. if (st.symtabletype=objectsymtable) and
  68. (sp_static in current_object_option) then
  69. begin
  70. s:='$'+lower(st.name^)+'_'+upper(s);
  71. st.defowner.owner.insert(tvarsym.create(s,tt));
  72. end;
  73. end;
  74. {$ifdef fixLeaksOnError}
  75. if strContStack.pop <> sc then
  76. writeln('problem with strContStack in pdecl (2)');
  77. {$endif fixLeaksOnError}
  78. sc.free;
  79. akttokenpos:=filepos;
  80. end;
  81. var
  82. sc : tidstringList;
  83. s : stringid;
  84. old_block_type : tblock_type;
  85. declarepos,storetokenpos : tfileposinfo;
  86. oldsymtablestack : tsymtable;
  87. symdone : boolean;
  88. { to handle absolute }
  89. abssym : tabsolutesym;
  90. l : longint;
  91. code : integer;
  92. { c var }
  93. newtype : ttypesym;
  94. is_dll,
  95. is_gpc_name,is_cdecl,extern_aktvarsym,export_aktvarsym : boolean;
  96. old_current_object_option : tsymoptions;
  97. dll_name,
  98. C_name : string;
  99. tt,casetype : ttype;
  100. { Delphi initialized vars }
  101. tconstsym : ttypedconstsym;
  102. { maxsize contains the max. size of a variant }
  103. { startvarrec contains the start of the variant part of a record }
  104. usedalign,
  105. maxsize,minalignment,maxalignment,startvarrecalign,startvarrecsize : longint;
  106. pt : tnode;
  107. srsym : tsym;
  108. srsymtable : tsymtable;
  109. unionsymtable : tsymtable;
  110. offset : longint;
  111. uniondef : trecorddef;
  112. unionsym : tvarsym;
  113. uniontype : ttype;
  114. dummysymoptions : tsymoptions;
  115. begin
  116. old_current_object_option:=current_object_option;
  117. { all variables are public if not in a object declaration }
  118. if not is_object then
  119. current_object_option:=[sp_public];
  120. old_block_type:=block_type;
  121. block_type:=bt_type;
  122. is_gpc_name:=false;
  123. { Force an expected ID error message }
  124. if not (token in [_ID,_CASE,_END]) then
  125. consume(_ID);
  126. { read vars }
  127. while (token=_ID) and
  128. not(is_object and (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED])) do
  129. begin
  130. C_name:=orgpattern;
  131. sc:=consume_idlist;
  132. {$ifdef fixLeaksOnError}
  133. strContStack.push(sc);
  134. {$endif fixLeaksOnError}
  135. consume(_COLON);
  136. if (m_gpc in aktmodeswitches) and
  137. not(is_record or is_object or is_threadvar) and
  138. (token=_ID) and (orgpattern='__asmname__') then
  139. begin
  140. consume(_ID);
  141. C_name:=get_stringconst;
  142. Is_gpc_name:=true;
  143. end;
  144. { this is needed for Delphi mode at least
  145. but should be OK for all modes !! (PM) }
  146. ignore_equal:=true;
  147. if is_record then
  148. begin
  149. { for records, don't search the recordsymtable for
  150. the symbols of the types }
  151. oldsymtablestack:=symtablestack;
  152. symtablestack:=symtablestack.next;
  153. read_type(tt,'');
  154. symtablestack:=oldsymtablestack;
  155. end
  156. else
  157. read_type(tt,'');
  158. { types that use init/final are not allowed in variant parts, but
  159. classes are allowed }
  160. if (variantrecordlevel>0) and
  161. (tt.def.needs_inittable and not is_class(tt.def)) then
  162. Message(parser_e_cant_use_inittable_here);
  163. ignore_equal:=false;
  164. symdone:=false;
  165. if is_gpc_name then
  166. begin
  167. storetokenpos:=akttokenpos;
  168. s:=sc.get(akttokenpos);
  169. if not sc.empty then
  170. Message(parser_e_absolute_only_one_var);
  171. {$ifdef fixLeaksOnError}
  172. if strContStack.pop <> sc then
  173. writeln('problem with strContStack in pdecl (3)');
  174. {$endif fixLeaksOnError}
  175. sc.free;
  176. aktvarsym:=tvarsym.create_C(s,target_info.Cprefix+C_name,tt);
  177. include(aktvarsym.varoptions,vo_is_external);
  178. symtablestack.insert(aktvarsym);
  179. akttokenpos:=storetokenpos;
  180. symdone:=true;
  181. end;
  182. { check for absolute }
  183. if not symdone and
  184. (idtoken=_ABSOLUTE) and not(is_record or is_object or is_threadvar) then
  185. begin
  186. consume(_ABSOLUTE);
  187. { only allowed for one var }
  188. s:=sc.get(declarepos);
  189. if not sc.empty then
  190. Message(parser_e_absolute_only_one_var);
  191. {$ifdef fixLeaksOnError}
  192. if strContStack.pop <> sc then
  193. writeln('problem with strContStack in pdecl (4)');
  194. {$endif fixLeaksOnError}
  195. sc.free;
  196. { parse the rest }
  197. if token=_ID then
  198. begin
  199. consume_sym(srsym,srsymtable);
  200. { we should check the result type of srsym }
  201. if not (srsym.typ in [varsym,typedconstsym,funcretsym]) then
  202. Message(parser_e_absolute_only_to_var_or_const);
  203. storetokenpos:=akttokenpos;
  204. akttokenpos:=declarepos;
  205. abssym:=tabsolutesym.create(s,tt);
  206. abssym.abstyp:=tovar;
  207. abssym.ref:=tstoredsym(srsym);
  208. symtablestack.insert(abssym);
  209. akttokenpos:=storetokenpos;
  210. end
  211. else
  212. if (token=_CSTRING) or (token=_CCHAR) then
  213. begin
  214. storetokenpos:=akttokenpos;
  215. akttokenpos:=declarepos;
  216. abssym:=tabsolutesym.create(s,tt);
  217. s:=pattern;
  218. consume(token);
  219. abssym.abstyp:=toasm;
  220. abssym.asmname:=stringdup(s);
  221. symtablestack.insert(abssym);
  222. akttokenpos:=storetokenpos;
  223. end
  224. else
  225. { absolute address ?!? }
  226. if token=_INTCONST then
  227. begin
  228. if (target_info.target=target_i386_go32v2)
  229. or (m_objfpc in aktmodeswitches)
  230. or (m_delphi in aktmodeswitches) then
  231. begin
  232. storetokenpos:=akttokenpos;
  233. akttokenpos:=declarepos;
  234. abssym:=tabsolutesym.create(s,tt);
  235. abssym.abstyp:=toaddr;
  236. abssym.absseg:=false;
  237. s:=pattern;
  238. consume(_INTCONST);
  239. val(s,abssym.address,code);
  240. if (token=_COLON) and
  241. (target_info.target=target_i386_go32v2) then
  242. begin
  243. consume(token);
  244. s:=pattern;
  245. consume(_INTCONST);
  246. val(s,l,code);
  247. abssym.address:=abssym.address shl 4+l;
  248. abssym.absseg:=true;
  249. end;
  250. symtablestack.insert(abssym);
  251. akttokenpos:=storetokenpos;
  252. end
  253. else
  254. Message(parser_e_absolute_only_to_var_or_const);
  255. end
  256. else
  257. Message(parser_e_absolute_only_to_var_or_const);
  258. symdone:=true;
  259. end;
  260. { Handling of Delphi typed const = initialized vars ! }
  261. { When should this be rejected ?
  262. - in parasymtable
  263. - in record or object
  264. - ... (PM) }
  265. if (m_delphi in aktmodeswitches) and (token=_EQUAL) and
  266. not (symtablestack.symtabletype in [parasymtable]) and
  267. not is_record and not is_object then
  268. begin
  269. storetokenpos:=akttokenpos;
  270. s:=sc.get(akttokenpos);
  271. if not sc.empty then
  272. Message(parser_e_initialized_only_one_var);
  273. tconstsym:=ttypedconstsym.createtype(s,tt,false);
  274. symtablestack.insert(tconstsym);
  275. akttokenpos:=storetokenpos;
  276. consume(_EQUAL);
  277. readtypedconst(tt,tconstsym,false);
  278. symdone:=true;
  279. end;
  280. { hint directive }
  281. {$warning hintdirective not stored in syms}
  282. dummysymoptions:=[];
  283. try_consume_hintdirective(dummysymoptions);
  284. { for a record there doesn't need to be a ; before the END or ) }
  285. if not((is_record or is_object) and (token in [_END,_RKLAMMER])) then
  286. consume(_SEMICOLON);
  287. { procvar handling }
  288. if (tt.def.deftype=procvardef) and (tt.def.typesym=nil) then
  289. begin
  290. newtype:=ttypesym.create('unnamed',tt);
  291. parse_var_proc_directives(tsym(newtype));
  292. newtype.restype.def:=nil;
  293. tt.def.typesym:=nil;
  294. newtype.free;
  295. end;
  296. { Check for variable directives }
  297. if not symdone and (token=_ID) then
  298. begin
  299. { Check for C Variable declarations }
  300. if (m_cvar_support in aktmodeswitches) and
  301. not(is_record or is_object or is_threadvar) and
  302. (idtoken in [_EXPORT,_EXTERNAL,_PUBLIC,_CVAR]) then
  303. begin
  304. { only allowed for one var }
  305. s:=sc.get(declarepos);
  306. if not sc.empty then
  307. Message(parser_e_absolute_only_one_var);
  308. {$ifdef fixLeaksOnError}
  309. if strContStack.pop <> sc then
  310. writeln('problem with strContStack in pdecl (5)');
  311. {$endif fixLeaksOnError}
  312. sc.free;
  313. { defaults }
  314. is_dll:=false;
  315. is_cdecl:=false;
  316. extern_aktvarsym:=false;
  317. export_aktvarsym:=false;
  318. { cdecl }
  319. if idtoken=_CVAR then
  320. begin
  321. consume(_CVAR);
  322. consume(_SEMICOLON);
  323. is_cdecl:=true;
  324. C_name:=target_info.Cprefix+C_name;
  325. end;
  326. { external }
  327. if idtoken=_EXTERNAL then
  328. begin
  329. consume(_EXTERNAL);
  330. extern_aktvarsym:=true;
  331. end;
  332. { export }
  333. if idtoken in [_EXPORT,_PUBLIC] then
  334. begin
  335. consume(_ID);
  336. if extern_aktvarsym or
  337. (symtablestack.symtabletype in [parasymtable,localsymtable]) then
  338. Message(parser_e_not_external_and_export)
  339. else
  340. export_aktvarsym:=true;
  341. end;
  342. { external and export need a name after when no cdecl is used }
  343. if not is_cdecl then
  344. begin
  345. { dll name ? }
  346. if (extern_aktvarsym) and (idtoken<>_NAME) then
  347. begin
  348. is_dll:=true;
  349. dll_name:=get_stringconst;
  350. end;
  351. consume(_NAME);
  352. C_name:=get_stringconst;
  353. end;
  354. { consume the ; when export or external is used }
  355. if extern_aktvarsym or export_aktvarsym then
  356. consume(_SEMICOLON);
  357. { insert in the symtable }
  358. storetokenpos:=akttokenpos;
  359. akttokenpos:=declarepos;
  360. if is_dll then
  361. aktvarsym:=tvarsym.create_dll(s,tt)
  362. else
  363. aktvarsym:=tvarsym.create_C(s,C_name,tt);
  364. { set some vars options }
  365. if export_aktvarsym then
  366. begin
  367. inc(aktvarsym.refs);
  368. include(aktvarsym.varoptions,vo_is_exported);
  369. end;
  370. if extern_aktvarsym then
  371. include(aktvarsym.varoptions,vo_is_external);
  372. { insert in the stack/datasegment }
  373. symtablestack.insert(aktvarsym);
  374. akttokenpos:=storetokenpos;
  375. { now we can insert it in the import lib if its a dll, or
  376. add it to the externals }
  377. if extern_aktvarsym then
  378. begin
  379. if is_dll then
  380. begin
  381. if not(current_module.uses_imports) then
  382. begin
  383. current_module.uses_imports:=true;
  384. importlib.preparelib(current_module.modulename^);
  385. end;
  386. importlib.importvariable(aktvarsym.mangledname,dll_name,C_name)
  387. end
  388. else
  389. if target_info.DllScanSupported then
  390. current_module.Externals.insert(tExternalsItem.create(aktvarsym.mangledname));
  391. end;
  392. symdone:=true;
  393. end
  394. else
  395. if (is_object) and (cs_static_keyword in aktmoduleswitches) and (idtoken=_STATIC) then
  396. begin
  397. include(current_object_option,sp_static);
  398. insert_syms(symtablestack,sc,tt,false);
  399. exclude(current_object_option,sp_static);
  400. consume(_STATIC);
  401. consume(_SEMICOLON);
  402. symdone:=true;
  403. end;
  404. end;
  405. { insert it in the symtable, if not done yet }
  406. if not symdone then
  407. begin
  408. { save object option, because we can turn of the sp_published }
  409. if (sp_published in current_object_option) and
  410. not(is_class(tt.def)) then
  411. begin
  412. Message(parser_e_cant_publish_that);
  413. exclude(current_object_option,sp_published);
  414. end
  415. else
  416. if (sp_published in current_object_option) and
  417. not(oo_can_have_published in tobjectdef(tt.def).objectoptions) then
  418. begin
  419. Message(parser_e_only_publishable_classes_can__be_published);
  420. exclude(current_object_option,sp_published);
  421. end;
  422. insert_syms(symtablestack,sc,tt,is_threadvar);
  423. current_object_option:=old_current_object_option;
  424. end;
  425. end;
  426. { Check for Case }
  427. if is_record and (token=_CASE) then
  428. begin
  429. maxsize:=0;
  430. maxalignment:=0;
  431. consume(_CASE);
  432. s:=pattern;
  433. searchsym(s,srsym,srsymtable);
  434. { may be only a type: }
  435. if assigned(srsym) and (srsym.typ in [typesym,unitsym]) then
  436. begin
  437. { for records, don't search the recordsymtable for
  438. the symbols of the types }
  439. oldsymtablestack:=symtablestack;
  440. symtablestack:=symtablestack.next;
  441. read_type(casetype,'');
  442. symtablestack:=oldsymtablestack;
  443. end
  444. else
  445. begin
  446. consume(_ID);
  447. consume(_COLON);
  448. { for records, don't search the recordsymtable for
  449. the symbols of the types }
  450. oldsymtablestack:=symtablestack;
  451. symtablestack:=symtablestack.next;
  452. read_type(casetype,'');
  453. symtablestack:=oldsymtablestack;
  454. symtablestack.insert(tvarsym.create(s,casetype));
  455. end;
  456. if not(is_ordinal(casetype.def)) or is_64bitint(casetype.def) then
  457. Message(type_e_ordinal_expr_expected);
  458. consume(_OF);
  459. UnionSymtable:=trecordsymtable.create;
  460. Unionsymtable.next:=symtablestack;
  461. registerdef:=false;
  462. UnionDef:=trecorddef.create(unionsymtable);
  463. registerdef:=true;
  464. symtablestack:=UnionSymtable;
  465. startvarrecsize:=symtablestack.datasize;
  466. startvarrecalign:=symtablestack.dataalignment;
  467. repeat
  468. repeat
  469. pt:=comp_expr(true);
  470. if not(pt.nodetype=ordconstn) then
  471. Message(cg_e_illegal_expression);
  472. pt.free;
  473. if token=_COMMA then
  474. consume(_COMMA)
  475. else
  476. break;
  477. until false;
  478. consume(_COLON);
  479. { read the vars }
  480. consume(_LKLAMMER);
  481. inc(variantrecordlevel);
  482. if token<>_RKLAMMER then
  483. read_var_decs(true,false,false);
  484. dec(variantrecordlevel);
  485. consume(_RKLAMMER);
  486. { calculates maximal variant size }
  487. maxsize:=max(maxsize,symtablestack.datasize);
  488. maxalignment:=max(maxalignment,symtablestack.dataalignment);
  489. { the items of the next variant are overlayed }
  490. symtablestack.datasize:=startvarrecsize;
  491. symtablestack.dataalignment:=startvarrecalign;
  492. if (token<>_END) and (token<>_RKLAMMER) then
  493. consume(_SEMICOLON)
  494. else
  495. break;
  496. until (token=_END) or (token=_RKLAMMER);
  497. { at last set the record size to that of the biggest variant }
  498. symtablestack.datasize:=maxsize;
  499. symtablestack.dataalignment:=maxalignment;
  500. uniontype.def:=uniondef;
  501. uniontype.sym:=nil;
  502. UnionSym:=tvarsym.create('case',uniontype);
  503. symtablestack:=symtablestack.next;
  504. { we do NOT call symtablestack.insert
  505. on purpose PM }
  506. if aktalignment.recordalignmax=-1 then
  507. begin
  508. {$ifdef i386}
  509. if maxalignment>2 then
  510. minalignment:=4
  511. else if maxalignment>1 then
  512. minalignment:=2
  513. else
  514. minalignment:=1;
  515. {$else}
  516. {$ifdef m68k}
  517. minalignment:=2;
  518. {$endif}
  519. minalignment:=1;
  520. {$endif}
  521. end
  522. else
  523. minalignment:=maxalignment;
  524. usedalign:=used_align(maxalignment,minalignment,maxalignment);
  525. offset:=align(symtablestack.datasize,usedalign);
  526. symtablestack.datasize:=offset+unionsymtable.datasize;
  527. if maxalignment>symtablestack.dataalignment then
  528. symtablestack.dataalignment:=maxalignment;
  529. trecordsymtable(Unionsymtable).Insert_in(symtablestack,offset);
  530. Unionsym.owner:=nil;
  531. unionsym.free;
  532. uniondef.free;
  533. end;
  534. block_type:=old_block_type;
  535. current_object_option:=old_current_object_option;
  536. end;
  537. end.
  538. {
  539. $Log$
  540. Revision 1.19 2001-08-30 20:13:53 peter
  541. * rtti/init table updates
  542. * rttisym for reusable global rtti/init info
  543. * support published for interfaces
  544. Revision 1.18 2001/07/01 20:16:16 peter
  545. * alignmentinfo record added
  546. * -Oa argument supports more alignment settings that can be specified
  547. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  548. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  549. required alignment and the maximum usefull alignment. The final
  550. alignment will be choosen per variable size dependent on these
  551. settings
  552. Revision 1.17 2001/06/03 21:57:36 peter
  553. + hint directive parsing support
  554. Revision 1.16 2001/04/18 22:01:57 peter
  555. * registration of targets and assemblers
  556. Revision 1.15 2001/04/13 01:22:12 peter
  557. * symtable change to classes
  558. * range check generation and errors fixed, make cycle DEBUG=1 works
  559. * memory leaks fixed
  560. Revision 1.14 2001/04/04 22:43:52 peter
  561. * remove unnecessary calls to firstpass
  562. Revision 1.13 2001/04/04 21:30:45 florian
  563. * applied several fixes to get the DD8 Delphi Unit compiled
  564. e.g. "forward"-interfaces are working now
  565. Revision 1.12 2001/04/02 21:20:33 peter
  566. * resulttype rewrite
  567. Revision 1.11 2001/03/11 22:58:50 peter
  568. * getsym redesign, removed the globals srsym,srsymtable
  569. Revision 1.10 2001/03/06 18:28:02 peter
  570. * patch from Pavel with a new and much faster DLL Scanner for
  571. automatic importing so $linklib works for DLLs. Thanks Pavel!
  572. Revision 1.9 2001/02/20 21:42:54 peter
  573. * record and object declaration with same field as type fixed
  574. Revision 1.7 2001/02/20 11:19:45 marco
  575. * Fix passing tvarrec to array of const
  576. Revision 1.6 2000/12/25 00:07:27 peter
  577. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  578. tlinkedlist objects)
  579. Revision 1.5 2000/12/17 14:00:18 peter
  580. * fixed static variables
  581. Revision 1.4 2000/11/29 00:30:36 florian
  582. * unused units removed from uses clause
  583. * some changes for widestrings
  584. Revision 1.3 2000/11/04 14:25:20 florian
  585. + merged Attila's changes for interfaces, not tested yet
  586. Revision 1.2 2000/10/31 22:02:49 peter
  587. * symtable splitted, no real code changes
  588. Revision 1.1 2000/10/14 10:14:51 peter
  589. * moehrendorf oct 2000 rewrite
  590. }