ptconst.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. {
  2. $Id$
  3. Copyright (c) 1998 by Florian Klaempfl
  4. Reads typed constants
  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 ptconst;
  19. interface
  20. uses symtable;
  21. { this procedure reads typed constants }
  22. { sym is only needed for ansi strings }
  23. { the assembler label is in the middle (PM) }
  24. procedure readtypedconst(def : pdef;sym : ptypedconstsym);
  25. implementation
  26. uses
  27. cobjects,globals,scanner,aasm,tree,pass_1,
  28. hcodegen,types,verbose
  29. { parser specific stuff }
  30. ,pbase,pexpr
  31. { processor specific stuff }
  32. {$ifdef i386}
  33. ,i386
  34. {$endif}
  35. {$ifdef m68k}
  36. ,m68k
  37. {$endif}
  38. ;
  39. { this procedure reads typed constants }
  40. procedure readtypedconst(def : pdef;sym : ptypedconstsym);
  41. var
  42. {$ifdef m68k}
  43. j : longint;
  44. {$endif m68k}
  45. p : ptree;
  46. i,l,offset,
  47. strlength : longint;
  48. lsym : pvarsym;
  49. ll : plabel;
  50. s : string;
  51. ca : pchar;
  52. aktpos : longint;
  53. pd : pprocdef;
  54. hp1,hp2 : pdefcoll;
  55. value : bestreal;
  56. procedure check_range;
  57. begin
  58. if ((p^.value>porddef(def)^.high) or
  59. (p^.value<porddef(def)^.low)) then
  60. begin
  61. if (cs_check_range in aktlocalswitches) then
  62. Message(parser_e_range_check_error)
  63. else
  64. Message(parser_w_range_check_error);
  65. end;
  66. end;
  67. {$R-} {Range check creates problem with init_8bit(-1) !!}
  68. begin
  69. case def^.deftype of
  70. orddef:
  71. begin
  72. p:=comp_expr(true);
  73. do_firstpass(p);
  74. case porddef(def)^.typ of
  75. s8bit,
  76. u8bit : begin
  77. if not is_constintnode(p) then
  78. { is't an int expected }
  79. Message(cg_e_illegal_expression)
  80. else
  81. begin
  82. datasegment^.concat(new(pai_const,init_8bit(p^.value)));
  83. check_range;
  84. end;
  85. end;
  86. s32bit : begin
  87. if not is_constintnode(p) then
  88. Message(cg_e_illegal_expression)
  89. else
  90. begin
  91. datasegment^.concat(new(pai_const,init_32bit(p^.value)));
  92. check_range;
  93. end;
  94. end;
  95. u32bit : begin
  96. if not is_constintnode(p) then
  97. Message(cg_e_illegal_expression)
  98. else
  99. datasegment^.concat(new(pai_const,init_32bit(p^.value)));
  100. end;
  101. bool8bit : begin
  102. if not is_constboolnode(p) then
  103. Message(cg_e_illegal_expression);
  104. datasegment^.concat(new(pai_const,init_8bit(p^.value)));
  105. end;
  106. uchar : begin
  107. if not is_constcharnode(p) then
  108. Message(cg_e_illegal_expression);
  109. datasegment^.concat(new(pai_const,init_8bit(p^.value)));
  110. end;
  111. u16bit,
  112. s16bit : begin
  113. if not is_constintnode(p) then
  114. Message(cg_e_illegal_expression);
  115. datasegment^.concat(new(pai_const,init_16bit(p^.value)));
  116. check_range;
  117. end;
  118. end;
  119. disposetree(p);
  120. end;
  121. floatdef:
  122. begin
  123. p:=comp_expr(true);
  124. do_firstpass(p);
  125. if is_constrealnode(p) then
  126. value:=p^.value_real
  127. else if is_constintnode(p) then
  128. value:=p^.value
  129. else
  130. Message(cg_e_illegal_expression);
  131. case pfloatdef(def)^.typ of
  132. s64real : datasegment^.concat(new(pai_double,init(value)));
  133. s32real : datasegment^.concat(new(pai_single,init(value)));
  134. s80real : datasegment^.concat(new(pai_extended,init(value)));
  135. s64bit : datasegment^.concat(new(pai_comp,init(value)));
  136. f32bit : datasegment^.concat(new(pai_const,init_32bit(trunc(value*65536))));
  137. else internalerror(18);
  138. end;
  139. disposetree(p);
  140. end;
  141. pointerdef:
  142. begin
  143. p:=comp_expr(true);
  144. do_firstpass(p);
  145. { nil pointer ? }
  146. if p^.treetype=niln then
  147. datasegment^.concat(new(pai_const,init_32bit(0)))
  148. { maybe pchar ? }
  149. else
  150. if (ppointerdef(def)^.definition^.deftype=orddef) and
  151. (porddef(ppointerdef(def)^.definition)^.typ=uchar) then
  152. begin
  153. getdatalabel(ll);
  154. datasegment^.concat(new(pai_const,init_symbol(strpnew(lab2str(ll)))));
  155. consts^.concat(new(pai_label,init(ll)));
  156. if p^.treetype=stringconstn then
  157. consts^.concat(new(pai_string,init(p^.value_str^+#0)))
  158. else
  159. if is_constcharnode(p) then
  160. consts^.concat(new(pai_string,init(char(byte(p^.value))+#0)))
  161. else
  162. Message(cg_e_illegal_expression);
  163. { insert label }
  164. end
  165. else
  166. if p^.treetype=addrn then
  167. begin
  168. if (is_equal(ppointerdef(p^.resulttype)^.definition,ppointerdef(def)^.definition) or
  169. (is_equal(ppointerdef(p^.resulttype)^.definition,voiddef)) or
  170. (is_equal(ppointerdef(def)^.definition,voiddef))) and
  171. (p^.left^.treetype = loadn) then
  172. begin
  173. if token=POINT then
  174. begin
  175. offset:=0;
  176. while token=POINT do
  177. begin
  178. consume(POINT);
  179. lsym:=pvarsym(precdef(
  180. ppointerdef(p^.resulttype)^.definition)^.symtable^.search(pattern));
  181. if assigned(sym) then
  182. offset:=offset+lsym^.address
  183. else
  184. begin
  185. Message1(sym_e_illegal_field,pattern);
  186. end;
  187. consume(ID);
  188. end;
  189. datasegment^.concat(new(pai_const_symbol_offset,init(
  190. strpnew(p^.left^.symtableentry^.mangledname),offset)));
  191. end
  192. else
  193. begin
  194. datasegment^.concat(new(pai_const,init_symbol(
  195. strpnew(p^.left^.symtableentry^.mangledname))));
  196. end;
  197. maybe_concat_external(p^.left^.symtableentry^.owner,
  198. p^.left^.symtableentry^.mangledname);
  199. end
  200. else
  201. Message(cg_e_illegal_expression);
  202. end
  203. else
  204. { allow typeof(Object type)}
  205. if (p^.treetype=inlinen) and
  206. (p^.inlinenumber=in_typeof_x) then
  207. begin
  208. if (p^.left^.treetype=typen) then
  209. begin
  210. datasegment^.concat(new(pai_const,init_symbol(
  211. strpnew(pobjectdef(p^.left^.resulttype)^.vmt_mangledname))));
  212. if pobjectdef(p^.left^.resulttype)^.owner^.symtabletype=unitsymtable then
  213. concat_external(pobjectdef(p^.left^.resulttype)^.vmt_mangledname,EXT_NEAR);
  214. end
  215. else
  216. Message(cg_e_illegal_expression);
  217. end
  218. else
  219. Message(cg_e_illegal_expression);
  220. disposetree(p);
  221. end;
  222. setdef:
  223. begin
  224. p:=comp_expr(true);
  225. do_firstpass(p);
  226. if p^.treetype=setconstn then
  227. begin
  228. { we only allow const sets }
  229. if assigned(p^.left) then
  230. Message(cg_e_illegal_expression)
  231. else
  232. begin
  233. {$ifdef i386}
  234. for l:=0 to def^.savesize-1 do
  235. datasegment^.concat(new(pai_const,init_8bit(p^.value_set^[l])));
  236. {$endif}
  237. {$ifdef m68k}
  238. j:=0;
  239. for l:=0 to ((def^.savesize-1) div 4) do
  240. { HORRIBLE HACK because of endian }
  241. { now use intel endian for constant sets }
  242. begin
  243. datasegment^.concat(new(pai_const,init_8bit(p^.value_set^[j+3])));
  244. datasegment^.concat(new(pai_const,init_8bit(p^.value_set^[j+2])));
  245. datasegment^.concat(new(pai_const,init_8bit(p^.value_set^[j+1])));
  246. datasegment^.concat(new(pai_const,init_8bit(p^.value_set^[j])));
  247. Inc(j,4);
  248. end;
  249. {$endif}
  250. end;
  251. end
  252. else
  253. Message(cg_e_illegal_expression);
  254. disposetree(p);
  255. end;
  256. enumdef:
  257. begin
  258. p:=comp_expr(true);
  259. do_firstpass(p);
  260. if p^.treetype=ordconstn then
  261. begin
  262. if is_equal(p^.resulttype,def) then
  263. datasegment^.concat(new(pai_const,init_32bit(p^.value)))
  264. else
  265. Message(cg_e_illegal_expression);
  266. end
  267. else
  268. Message(cg_e_illegal_expression);
  269. disposetree(p);
  270. end;
  271. stringdef:
  272. begin
  273. p:=comp_expr(true);
  274. do_firstpass(p);
  275. { first take care of prefixes for long and ansi strings }
  276. case pstringdef(def)^.string_typ of
  277. st_shortstring:
  278. begin
  279. if p^.treetype=stringconstn then
  280. begin
  281. {$ifdef UseAnsiString}
  282. if p^.length>=def^.size then
  283. strlength:=def^.size-1
  284. else
  285. strlength:=p^.length;
  286. datasegment^.concat(new(pai_const,init_8bit(strlength)));
  287. { this can also handle longer strings }
  288. generate_pascii(datasegment,p^.value_str,strlength);
  289. {$else UseAnsiString}
  290. if length(p^.value_str^)>=def^.size then
  291. begin
  292. strlength:=def^.size-1;
  293. generate_ascii(datasegment,char(strlength)+copy(p^.value_str^,1,strlength));
  294. end
  295. else
  296. begin
  297. strlength:=length(p^.value_str^);
  298. generate_ascii(datasegment,char(strlength)+p^.value_str^);
  299. end;
  300. {$endif UseAnsiString}
  301. end
  302. else if is_constcharnode(p) then
  303. begin
  304. datasegment^.concat(new(pai_string,init(#1+char(byte(p^.value)))));
  305. strlength:=1;
  306. end
  307. else Message(cg_e_illegal_expression);
  308. if def^.size>strlength then
  309. begin
  310. getmem(ca,def^.size-strlength);
  311. fillchar(ca[0],def^.size-strlength-1,' ');
  312. ca[def^.size-strlength-1]:=#0;
  313. {$ifdef UseAnsiString}
  314. { this can also handle longer strings }
  315. { def^.size contains also the leading length, so we }
  316. { we have to subtract one }
  317. generate_pascii(datasegment,ca,def^.size-strlength-1);
  318. {$else UseAnsiString}
  319. datasegment^.concat(new(pai_string,init_pchar(ca)));
  320. {$endif UseAnsiString}
  321. end;
  322. end;
  323. {$ifdef UseLongString}
  324. st_longstring:
  325. begin
  326. { first write the maximum size }
  327. datasegment^.concat(new(pai_const,init_32bit(p^.length)))));
  328. { fill byte }
  329. datasegment^.concat(new(pai_const,init_8bit(0)));
  330. if p^.treetype=stringconstn then
  331. begin
  332. { this can also handle longer strings }
  333. generate_pascii(consts,p^.value_str,p^.length);
  334. end
  335. else if is_constcharnode(p) then
  336. begin
  337. consts^.concat(new(pai_const,init_8bit(p^.value)));
  338. strlength:=1;
  339. end
  340. else Message(cg_e_illegal_expression);
  341. datasegment^.concat(new(pai_const,init_8bit(0)));
  342. end;
  343. {$endif UseLongString}
  344. {$ifdef UseAnsiString}
  345. st_ansistring:
  346. begin
  347. { an empty ansi string is nil! }
  348. if (p^.treetype=stringconstn) and (p^.length=0) then
  349. datasegment^.concat(new(pai_const,init_32bit(0)))
  350. else
  351. begin
  352. getdatalabel(ll);
  353. datasegment^.concat(new(pai_const,init_symbol(strpnew(lab2str(ll)))));
  354. { first write the maximum size }
  355. consts^.concat(new(pai_const,init_32bit(p^.length)));
  356. { second write the real length }
  357. consts^.concat(new(pai_const,init_32bit(p^.length)));
  358. { redondent with maxlength but who knows ... (PM) }
  359. { third write use count (set to -1 for safety ) }
  360. consts^.concat(new(pai_const,init_32bit(-1)));
  361. { not longer necessary, because it insert_indata
  362. if assigned(sym) then
  363. sym^.really_insert_in_data;
  364. }
  365. consts^.concat(new(pai_label,init(ll)));
  366. if p^.treetype=stringconstn then
  367. begin
  368. { this can also handle longer strings }
  369. generate_pascii(consts,p^.value_str,p^.length);
  370. end
  371. else if is_constcharnode(p) then
  372. begin
  373. consts^.concat(new(pai_const,init_8bit(p^.value)));
  374. strlength:=1;
  375. end
  376. else Message(cg_e_illegal_expression);
  377. consts^.concat(new(pai_const,init_8bit(0)));
  378. end;
  379. end;
  380. {$endif UseAnsiString}
  381. end;
  382. disposetree(p);
  383. end;
  384. arraydef:
  385. begin
  386. if token=LKLAMMER then
  387. begin
  388. consume(LKLAMMER);
  389. for l:=parraydef(def)^.lowrange to parraydef(def)^.highrange-1 do
  390. begin
  391. readtypedconst(parraydef(def)^.definition,nil);
  392. consume(COMMA);
  393. end;
  394. readtypedconst(parraydef(def)^.definition,nil);
  395. consume(RKLAMMER);
  396. end
  397. else
  398. begin
  399. p:=comp_expr(true);
  400. do_firstpass(p);
  401. if p^.treetype=stringconstn then
  402. s:=p^.value_str^
  403. else if is_constcharnode(p) then
  404. s:=char(byte(p^.value))
  405. else Message(cg_e_illegal_expression);
  406. disposetree(p);
  407. l:=length(s);
  408. for i:=Parraydef(def)^.lowrange to Parraydef(def)^.highrange do
  409. begin
  410. if i+1-Parraydef(def)^.lowrange<=l then
  411. begin
  412. datasegment^.concat(new(pai_const,init_8bit(byte(s[1]))));
  413. delete(s,1,1);
  414. end
  415. else
  416. {Fill the remaining positions with #0.}
  417. datasegment^.concat(new(pai_const,init_8bit(0)));
  418. end;
  419. if length(s)>0 then
  420. Message(parser_e_string_too_long);
  421. end;
  422. end;
  423. procvardef:
  424. begin
  425. { Procvars and pointers are no longer compatible. }
  426. { under tp: =nil or =var under fpc: =nil or =@var }
  427. if token=_NIL then
  428. begin
  429. datasegment^.concat(new(pai_const,init_32bit(0)));
  430. consume(_NIL);
  431. exit;
  432. end
  433. else
  434. if not(m_tp_procvar in aktmodeswitches) then
  435. if token=KLAMMERAFFE then
  436. consume(KLAMMERAFFE);
  437. getsym(pattern,true);
  438. consume(ID);
  439. if srsym^.typ=unitsym then
  440. begin
  441. consume(POINT);
  442. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  443. consume(ID);
  444. end;
  445. if srsym^.typ<>procsym then
  446. Message(cg_e_illegal_expression)
  447. else
  448. begin
  449. pd:=pprocsym(srsym)^.definition;
  450. if assigned(pd^.nextoverloaded) then
  451. Message(parser_e_no_overloaded_procvars);
  452. if not((pprocvardef(def)^.options=pd^.options)) or
  453. not(is_equal(pprocvardef(def)^.retdef,pd^.retdef)) then
  454. Message(type_e_mismatch)
  455. else
  456. begin
  457. hp1:=pprocvardef(def)^.para1;
  458. hp2:=pd^.para1;
  459. while assigned(hp1) and assigned(hp2) do
  460. begin
  461. if not(is_equal(hp1^.data,hp2^.data)) or
  462. not(hp1^.paratyp=hp2^.paratyp) then
  463. begin
  464. Message(type_e_mismatch);
  465. break;
  466. end;
  467. hp1:=hp1^.next;
  468. hp2:=hp2^.next;
  469. end;
  470. if not((hp1=nil) and (hp2=nil)) then
  471. Message(type_e_mismatch);
  472. end;
  473. datasegment^.concat(new(pai_const,init_symbol(strpnew(pd^.mangledname))));
  474. if pd^.owner^.symtabletype=unitsymtable then
  475. concat_external(pd^.mangledname,EXT_NEAR);
  476. end;
  477. end;
  478. { reads a typed constant record }
  479. recorddef:
  480. begin
  481. consume(LKLAMMER);
  482. aktpos:=0;
  483. while token<>RKLAMMER do
  484. begin
  485. s:=pattern;
  486. consume(ID);
  487. consume(COLON);
  488. srsym:=precdef(def)^.symtable^.search(s);
  489. if srsym=nil then
  490. begin
  491. Message1(sym_e_id_not_found,s);
  492. consume_all_until(SEMICOLON);
  493. end
  494. else
  495. begin
  496. { check position }
  497. if pvarsym(srsym)^.address<aktpos then
  498. Message(parser_e_invalid_record_const);
  499. { if needed fill }
  500. if pvarsym(srsym)^.address>aktpos then
  501. for i:=1 to pvarsym(srsym)^.address-aktpos do
  502. datasegment^.concat(new(pai_const,init_8bit(0)));
  503. { new position }
  504. aktpos:=pvarsym(srsym)^.address+pvarsym(srsym)^.definition^.size;
  505. { read the data }
  506. readtypedconst(pvarsym(srsym)^.definition,nil);
  507. if token=SEMICOLON then
  508. consume(SEMICOLON)
  509. else break;
  510. end;
  511. end;
  512. for i:=1 to def^.size-aktpos do
  513. datasegment^.concat(new(pai_const,init_8bit(0)));
  514. consume(RKLAMMER);
  515. end;
  516. else Message(parser_e_type_const_not_possible);
  517. end;
  518. end;
  519. end.
  520. {
  521. $Log$
  522. Revision 1.19 1998-10-12 12:20:58 pierre
  523. + added tai_const_symbol_offset
  524. for r : pointer = @var.field;
  525. * better message for different arg names on implementation
  526. of function
  527. Revision 1.18 1998/10/12 09:50:05 florian
  528. + support of <procedure var type>:=<pointer> in delphi mode added
  529. Revision 1.17 1998/10/09 08:56:29 pierre
  530. * several memory leaks fixed
  531. Revision 1.16 1998/09/24 23:49:18 peter
  532. + aktmodeswitches
  533. Revision 1.15 1998/09/07 18:46:11 peter
  534. * update smartlinking, uses getdatalabel
  535. * renamed ptree.value vars to value_str,value_real,value_set
  536. Revision 1.14 1998/09/04 08:42:07 peter
  537. * updated some error messages
  538. Revision 1.13 1998/09/01 09:05:36 peter
  539. * fixed string[4]='.library'
  540. Revision 1.12 1998/08/31 12:26:32 peter
  541. * m68k and palmos updates from surebugfixes
  542. Revision 1.11 1998/08/10 14:50:20 peter
  543. + localswitches, moduleswitches, globalswitches splitting
  544. Revision 1.10 1998/07/21 11:16:25 florian
  545. * bug0147 fixed
  546. Revision 1.9 1998/07/20 22:17:16 florian
  547. * hex constants in numeric char (#$54#$43 ...) are now allowed
  548. * there was a bug in record_var_dec which prevents the used
  549. of nested variant records (for example drivers.tevent of tv)
  550. Revision 1.8 1998/07/20 18:40:15 florian
  551. * handling of ansi string constants should now work
  552. Revision 1.7 1998/07/18 22:54:29 florian
  553. * some ansi/wide/longstring support fixed:
  554. o parameter passing
  555. o returning as result from functions
  556. Revision 1.6 1998/06/08 22:59:52 peter
  557. * smartlinking works for win32
  558. * some defines to exclude some compiler parts
  559. Revision 1.5 1998/06/03 22:49:01 peter
  560. + wordbool,longbool
  561. * rename bis,von -> high,low
  562. * moved some systemunit loading/creating to psystem.pas
  563. Revision 1.4 1998/05/05 12:05:42 florian
  564. * problems with properties fixed
  565. * crash fixed: i:=l when i and l are undefined, was a problem with
  566. implementation of private/protected
  567. Revision 1.3 1998/04/29 10:34:00 pierre
  568. + added some code for ansistring (not complete nor working yet)
  569. * corrected operator overloading
  570. * corrected nasm output
  571. + started inline procedures
  572. + added starstarn : use ** for exponentiation (^ gave problems)
  573. + started UseTokenInfo cond to get accurate positions
  574. }