pdecvar.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  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. if (variantrecordlevel>0) and tt.def.needs_inittable then
  159. Message(parser_e_cant_use_inittable_here);
  160. ignore_equal:=false;
  161. symdone:=false;
  162. if is_gpc_name then
  163. begin
  164. storetokenpos:=akttokenpos;
  165. s:=sc.get(akttokenpos);
  166. if not sc.empty then
  167. Message(parser_e_absolute_only_one_var);
  168. {$ifdef fixLeaksOnError}
  169. if strContStack.pop <> sc then
  170. writeln('problem with strContStack in pdecl (3)');
  171. {$endif fixLeaksOnError}
  172. sc.free;
  173. aktvarsym:=tvarsym.create_C(s,target_info.Cprefix+C_name,tt);
  174. include(aktvarsym.varoptions,vo_is_external);
  175. symtablestack.insert(aktvarsym);
  176. akttokenpos:=storetokenpos;
  177. symdone:=true;
  178. end;
  179. { check for absolute }
  180. if not symdone and
  181. (idtoken=_ABSOLUTE) and not(is_record or is_object or is_threadvar) then
  182. begin
  183. consume(_ABSOLUTE);
  184. { only allowed for one var }
  185. s:=sc.get(declarepos);
  186. if not sc.empty then
  187. Message(parser_e_absolute_only_one_var);
  188. {$ifdef fixLeaksOnError}
  189. if strContStack.pop <> sc then
  190. writeln('problem with strContStack in pdecl (4)');
  191. {$endif fixLeaksOnError}
  192. sc.free;
  193. { parse the rest }
  194. if token=_ID then
  195. begin
  196. consume_sym(srsym,srsymtable);
  197. { we should check the result type of srsym }
  198. if not (srsym.typ in [varsym,typedconstsym,funcretsym]) then
  199. Message(parser_e_absolute_only_to_var_or_const);
  200. storetokenpos:=akttokenpos;
  201. akttokenpos:=declarepos;
  202. abssym:=tabsolutesym.create(s,tt);
  203. abssym.abstyp:=tovar;
  204. abssym.ref:=tstoredsym(srsym);
  205. symtablestack.insert(abssym);
  206. akttokenpos:=storetokenpos;
  207. end
  208. else
  209. if (token=_CSTRING) or (token=_CCHAR) then
  210. begin
  211. storetokenpos:=akttokenpos;
  212. akttokenpos:=declarepos;
  213. abssym:=tabsolutesym.create(s,tt);
  214. s:=pattern;
  215. consume(token);
  216. abssym.abstyp:=toasm;
  217. abssym.asmname:=stringdup(s);
  218. symtablestack.insert(abssym);
  219. akttokenpos:=storetokenpos;
  220. end
  221. else
  222. { absolute address ?!? }
  223. if token=_INTCONST then
  224. begin
  225. if (target_info.target=target_i386_go32v2)
  226. or (m_objfpc in aktmodeswitches)
  227. or (m_delphi in aktmodeswitches) then
  228. begin
  229. storetokenpos:=akttokenpos;
  230. akttokenpos:=declarepos;
  231. abssym:=tabsolutesym.create(s,tt);
  232. abssym.abstyp:=toaddr;
  233. abssym.absseg:=false;
  234. s:=pattern;
  235. consume(_INTCONST);
  236. val(s,abssym.address,code);
  237. if (token=_COLON) and
  238. (target_info.target=target_i386_go32v2) then
  239. begin
  240. consume(token);
  241. s:=pattern;
  242. consume(_INTCONST);
  243. val(s,l,code);
  244. abssym.address:=abssym.address shl 4+l;
  245. abssym.absseg:=true;
  246. end;
  247. symtablestack.insert(abssym);
  248. akttokenpos:=storetokenpos;
  249. end
  250. else
  251. Message(parser_e_absolute_only_to_var_or_const);
  252. end
  253. else
  254. Message(parser_e_absolute_only_to_var_or_const);
  255. symdone:=true;
  256. end;
  257. { Handling of Delphi typed const = initialized vars ! }
  258. { When should this be rejected ?
  259. - in parasymtable
  260. - in record or object
  261. - ... (PM) }
  262. if (m_delphi in aktmodeswitches) and (token=_EQUAL) and
  263. not (symtablestack.symtabletype in [parasymtable]) and
  264. not is_record and not is_object then
  265. begin
  266. storetokenpos:=akttokenpos;
  267. s:=sc.get(akttokenpos);
  268. if not sc.empty then
  269. Message(parser_e_initialized_only_one_var);
  270. tconstsym:=ttypedconstsym.createtype(s,tt,false);
  271. symtablestack.insert(tconstsym);
  272. akttokenpos:=storetokenpos;
  273. consume(_EQUAL);
  274. readtypedconst(tt,tconstsym,false);
  275. symdone:=true;
  276. end;
  277. { hint directive }
  278. {$warning hintdirective not stored in syms}
  279. dummysymoptions:=[];
  280. try_consume_hintdirective(dummysymoptions);
  281. { for a record there doesn't need to be a ; before the END or ) }
  282. if not((is_record or is_object) and (token in [_END,_RKLAMMER])) then
  283. consume(_SEMICOLON);
  284. { procvar handling }
  285. if (tt.def.deftype=procvardef) and (tt.def.typesym=nil) then
  286. begin
  287. newtype:=ttypesym.create('unnamed',tt);
  288. parse_var_proc_directives(tsym(newtype));
  289. newtype.restype.def:=nil;
  290. tt.def.typesym:=nil;
  291. newtype.free;
  292. end;
  293. { Check for variable directives }
  294. if not symdone and (token=_ID) then
  295. begin
  296. { Check for C Variable declarations }
  297. if (m_cvar_support in aktmodeswitches) and
  298. not(is_record or is_object or is_threadvar) and
  299. (idtoken in [_EXPORT,_EXTERNAL,_PUBLIC,_CVAR]) then
  300. begin
  301. { only allowed for one var }
  302. s:=sc.get(declarepos);
  303. if not sc.empty then
  304. Message(parser_e_absolute_only_one_var);
  305. {$ifdef fixLeaksOnError}
  306. if strContStack.pop <> sc then
  307. writeln('problem with strContStack in pdecl (5)');
  308. {$endif fixLeaksOnError}
  309. sc.free;
  310. { defaults }
  311. is_dll:=false;
  312. is_cdecl:=false;
  313. extern_aktvarsym:=false;
  314. export_aktvarsym:=false;
  315. { cdecl }
  316. if idtoken=_CVAR then
  317. begin
  318. consume(_CVAR);
  319. consume(_SEMICOLON);
  320. is_cdecl:=true;
  321. C_name:=target_info.Cprefix+C_name;
  322. end;
  323. { external }
  324. if idtoken=_EXTERNAL then
  325. begin
  326. consume(_EXTERNAL);
  327. extern_aktvarsym:=true;
  328. end;
  329. { export }
  330. if idtoken in [_EXPORT,_PUBLIC] then
  331. begin
  332. consume(_ID);
  333. if extern_aktvarsym or
  334. (symtablestack.symtabletype in [parasymtable,localsymtable]) then
  335. Message(parser_e_not_external_and_export)
  336. else
  337. export_aktvarsym:=true;
  338. end;
  339. { external and export need a name after when no cdecl is used }
  340. if not is_cdecl then
  341. begin
  342. { dll name ? }
  343. if (extern_aktvarsym) and (idtoken<>_NAME) then
  344. begin
  345. is_dll:=true;
  346. dll_name:=get_stringconst;
  347. end;
  348. consume(_NAME);
  349. C_name:=get_stringconst;
  350. end;
  351. { consume the ; when export or external is used }
  352. if extern_aktvarsym or export_aktvarsym then
  353. consume(_SEMICOLON);
  354. { insert in the symtable }
  355. storetokenpos:=akttokenpos;
  356. akttokenpos:=declarepos;
  357. if is_dll then
  358. aktvarsym:=tvarsym.create_dll(s,tt)
  359. else
  360. aktvarsym:=tvarsym.create_C(s,C_name,tt);
  361. { set some vars options }
  362. if export_aktvarsym then
  363. begin
  364. inc(aktvarsym.refs);
  365. include(aktvarsym.varoptions,vo_is_exported);
  366. end;
  367. if extern_aktvarsym then
  368. include(aktvarsym.varoptions,vo_is_external);
  369. { insert in the stack/datasegment }
  370. symtablestack.insert(aktvarsym);
  371. akttokenpos:=storetokenpos;
  372. { now we can insert it in the import lib if its a dll, or
  373. add it to the externals }
  374. if extern_aktvarsym then
  375. begin
  376. if is_dll then
  377. begin
  378. if not(current_module.uses_imports) then
  379. begin
  380. current_module.uses_imports:=true;
  381. importlib.preparelib(current_module.modulename^);
  382. end;
  383. importlib.importvariable(aktvarsym.mangledname,dll_name,C_name)
  384. end
  385. else
  386. if target_info.DllScanSupported then
  387. current_module.Externals.insert(tExternalsItem.create(aktvarsym.mangledname));
  388. end;
  389. symdone:=true;
  390. end
  391. else
  392. if (is_object) and (cs_static_keyword in aktmoduleswitches) and (idtoken=_STATIC) then
  393. begin
  394. include(current_object_option,sp_static);
  395. insert_syms(symtablestack,sc,tt,false);
  396. exclude(current_object_option,sp_static);
  397. consume(_STATIC);
  398. consume(_SEMICOLON);
  399. symdone:=true;
  400. end;
  401. end;
  402. { insert it in the symtable, if not done yet }
  403. if not symdone then
  404. begin
  405. { save object option, because we can turn of the sp_published }
  406. if (sp_published in current_object_option) and
  407. not(is_class(tt.def)) then
  408. begin
  409. Message(parser_e_cant_publish_that);
  410. exclude(current_object_option,sp_published);
  411. end
  412. else
  413. if (sp_published in current_object_option) and
  414. not(oo_can_have_published in tobjectdef(tt.def).objectoptions) then
  415. begin
  416. Message(parser_e_only_publishable_classes_can__be_published);
  417. exclude(current_object_option,sp_published);
  418. end;
  419. insert_syms(symtablestack,sc,tt,is_threadvar);
  420. current_object_option:=old_current_object_option;
  421. end;
  422. end;
  423. { Check for Case }
  424. if is_record and (token=_CASE) then
  425. begin
  426. maxsize:=0;
  427. maxalignment:=0;
  428. consume(_CASE);
  429. s:=pattern;
  430. searchsym(s,srsym,srsymtable);
  431. { may be only a type: }
  432. if assigned(srsym) and (srsym.typ in [typesym,unitsym]) then
  433. begin
  434. { for records, don't search the recordsymtable for
  435. the symbols of the types }
  436. oldsymtablestack:=symtablestack;
  437. symtablestack:=symtablestack.next;
  438. read_type(casetype,'');
  439. symtablestack:=oldsymtablestack;
  440. end
  441. else
  442. begin
  443. consume(_ID);
  444. consume(_COLON);
  445. { for records, don't search the recordsymtable for
  446. the symbols of the types }
  447. oldsymtablestack:=symtablestack;
  448. symtablestack:=symtablestack.next;
  449. read_type(casetype,'');
  450. symtablestack:=oldsymtablestack;
  451. symtablestack.insert(tvarsym.create(s,casetype));
  452. end;
  453. if not(is_ordinal(casetype.def)) or is_64bitint(casetype.def) then
  454. Message(type_e_ordinal_expr_expected);
  455. consume(_OF);
  456. UnionSymtable:=trecordsymtable.create;
  457. Unionsymtable.next:=symtablestack;
  458. registerdef:=false;
  459. UnionDef:=trecorddef.create(unionsymtable);
  460. registerdef:=true;
  461. symtablestack:=UnionSymtable;
  462. startvarrecsize:=symtablestack.datasize;
  463. startvarrecalign:=symtablestack.dataalignment;
  464. repeat
  465. repeat
  466. pt:=comp_expr(true);
  467. if not(pt.nodetype=ordconstn) then
  468. Message(cg_e_illegal_expression);
  469. pt.free;
  470. if token=_COMMA then
  471. consume(_COMMA)
  472. else
  473. break;
  474. until false;
  475. consume(_COLON);
  476. { read the vars }
  477. consume(_LKLAMMER);
  478. inc(variantrecordlevel);
  479. if token<>_RKLAMMER then
  480. read_var_decs(true,false,false);
  481. dec(variantrecordlevel);
  482. consume(_RKLAMMER);
  483. { calculates maximal variant size }
  484. maxsize:=max(maxsize,symtablestack.datasize);
  485. maxalignment:=max(maxalignment,symtablestack.dataalignment);
  486. { the items of the next variant are overlayed }
  487. symtablestack.datasize:=startvarrecsize;
  488. symtablestack.dataalignment:=startvarrecalign;
  489. if (token<>_END) and (token<>_RKLAMMER) then
  490. consume(_SEMICOLON)
  491. else
  492. break;
  493. until (token=_END) or (token=_RKLAMMER);
  494. { at last set the record size to that of the biggest variant }
  495. symtablestack.datasize:=maxsize;
  496. symtablestack.dataalignment:=maxalignment;
  497. uniontype.def:=uniondef;
  498. uniontype.sym:=nil;
  499. UnionSym:=tvarsym.create('case',uniontype);
  500. symtablestack:=symtablestack.next;
  501. { we do NOT call symtablestack.insert
  502. on purpose PM }
  503. if aktalignment.recordalignmax=-1 then
  504. begin
  505. {$ifdef i386}
  506. if maxalignment>2 then
  507. minalignment:=4
  508. else if maxalignment>1 then
  509. minalignment:=2
  510. else
  511. minalignment:=1;
  512. {$else}
  513. {$ifdef m68k}
  514. minalignment:=2;
  515. {$endif}
  516. minalignment:=1;
  517. {$endif}
  518. end
  519. else
  520. minalignment:=maxalignment;
  521. usedalign:=used_align(maxalignment,minalignment,maxalignment);
  522. offset:=align(symtablestack.datasize,usedalign);
  523. symtablestack.datasize:=offset+unionsymtable.datasize;
  524. if maxalignment>symtablestack.dataalignment then
  525. symtablestack.dataalignment:=maxalignment;
  526. trecordsymtable(Unionsymtable).Insert_in(symtablestack,offset);
  527. Unionsym.owner:=nil;
  528. unionsym.free;
  529. uniondef.free;
  530. end;
  531. block_type:=old_block_type;
  532. current_object_option:=old_current_object_option;
  533. end;
  534. end.
  535. {
  536. $Log$
  537. Revision 1.18 2001-07-01 20:16:16 peter
  538. * alignmentinfo record added
  539. * -Oa argument supports more alignment settings that can be specified
  540. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  541. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  542. required alignment and the maximum usefull alignment. The final
  543. alignment will be choosen per variable size dependent on these
  544. settings
  545. Revision 1.17 2001/06/03 21:57:36 peter
  546. + hint directive parsing support
  547. Revision 1.16 2001/04/18 22:01:57 peter
  548. * registration of targets and assemblers
  549. Revision 1.15 2001/04/13 01:22:12 peter
  550. * symtable change to classes
  551. * range check generation and errors fixed, make cycle DEBUG=1 works
  552. * memory leaks fixed
  553. Revision 1.14 2001/04/04 22:43:52 peter
  554. * remove unnecessary calls to firstpass
  555. Revision 1.13 2001/04/04 21:30:45 florian
  556. * applied several fixes to get the DD8 Delphi Unit compiled
  557. e.g. "forward"-interfaces are working now
  558. Revision 1.12 2001/04/02 21:20:33 peter
  559. * resulttype rewrite
  560. Revision 1.11 2001/03/11 22:58:50 peter
  561. * getsym redesign, removed the globals srsym,srsymtable
  562. Revision 1.10 2001/03/06 18:28:02 peter
  563. * patch from Pavel with a new and much faster DLL Scanner for
  564. automatic importing so $linklib works for DLLs. Thanks Pavel!
  565. Revision 1.9 2001/02/20 21:42:54 peter
  566. * record and object declaration with same field as type fixed
  567. Revision 1.7 2001/02/20 11:19:45 marco
  568. * Fix passing tvarrec to array of const
  569. Revision 1.6 2000/12/25 00:07:27 peter
  570. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  571. tlinkedlist objects)
  572. Revision 1.5 2000/12/17 14:00:18 peter
  573. * fixed static variables
  574. Revision 1.4 2000/11/29 00:30:36 florian
  575. * unused units removed from uses clause
  576. * some changes for widestrings
  577. Revision 1.3 2000/11/04 14:25:20 florian
  578. + merged Attila's changes for interfaces, not tested yet
  579. Revision 1.2 2000/10/31 22:02:49 peter
  580. * symtable splitted, no real code changes
  581. Revision 1.1 2000/10/14 10:14:51 peter
  582. * moehrendorf oct 2000 rewrite
  583. }