ptconst.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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. p : ptree;
  43. i,l,strlength : longint;
  44. ll : plabel;
  45. s : string;
  46. ca : pchar;
  47. aktpos : longint;
  48. pd : pprocdef;
  49. hp1,hp2 : pdefcoll;
  50. value : bestreal;
  51. {problem with fldt !!
  52. anyway .valued is not extended !!
  53. value : double; }
  54. procedure check_range;
  55. begin
  56. if ((p^.value>porddef(def)^.bis) or
  57. (p^.value<porddef(def)^.von)) then
  58. Message(parser_e_range_check_error);
  59. end;
  60. {$R-} {Range check creates problem with init_8bit(-1) !!}
  61. begin
  62. case def^.deftype of
  63. orddef:
  64. begin
  65. p:=comp_expr(true);
  66. do_firstpass(p);
  67. case porddef(def)^.typ of
  68. s8bit,
  69. u8bit : begin
  70. if not is_constintnode(p) then
  71. { is't an int expected }
  72. Message(cg_e_illegal_expression)
  73. else
  74. begin
  75. datasegment^.concat(new(pai_const,init_8bit(p^.value)));
  76. check_range;
  77. end;
  78. end;
  79. s32bit : begin
  80. if not is_constintnode(p) then
  81. Message(cg_e_illegal_expression)
  82. else
  83. begin
  84. datasegment^.concat(new(pai_const,init_32bit(p^.value)));
  85. check_range;
  86. end;
  87. end;
  88. u32bit : begin
  89. if not is_constintnode(p) then
  90. Message(cg_e_illegal_expression)
  91. else
  92. datasegment^.concat(new(pai_const,init_32bit(p^.value)));
  93. end;
  94. bool8bit : begin
  95. if not is_constboolnode(p) then
  96. Message(cg_e_illegal_expression);
  97. datasegment^.concat(new(pai_const,init_8bit(p^.value)));
  98. end;
  99. uchar : begin
  100. if not is_constcharnode(p) then
  101. Message(cg_e_illegal_expression);
  102. datasegment^.concat(new(pai_const,init_8bit(p^.value)));
  103. end;
  104. u16bit,
  105. s16bit : begin
  106. if not is_constintnode(p) then
  107. Message(cg_e_illegal_expression);
  108. datasegment^.concat(new(pai_const,init_16bit(p^.value)));
  109. check_range;
  110. end;
  111. end;
  112. disposetree(p);
  113. end;
  114. floatdef:
  115. begin
  116. p:=comp_expr(true);
  117. do_firstpass(p);
  118. if is_constrealnode(p) then
  119. value:=p^.valued
  120. else if is_constintnode(p) then
  121. value:=p^.value
  122. else
  123. Message(cg_e_illegal_expression);
  124. case pfloatdef(def)^.typ of
  125. s64real : datasegment^.concat(new(pai_double,init(value)));
  126. s32real : datasegment^.concat(new(pai_single,init(value)));
  127. s80real : datasegment^.concat(new(pai_extended,init(value)));
  128. s64bit : datasegment^.concat(new(pai_comp,init(value)));
  129. f32bit : datasegment^.concat(new(pai_const,init_32bit(trunc(value*65536))));
  130. else internalerror(18);
  131. end;
  132. disposetree(p);
  133. end;
  134. pointerdef:
  135. begin
  136. p:=comp_expr(true);
  137. do_firstpass(p);
  138. { nil pointer ? }
  139. if p^.treetype=niln then
  140. datasegment^.concat(new(pai_const,init_32bit(0)))
  141. { maybe pchar ? }
  142. else if (ppointerdef(def)^.definition^.deftype=orddef) and
  143. (porddef(ppointerdef(def)^.definition)^.typ=uchar) then
  144. begin
  145. getlabel(ll);
  146. { insert string at the begin }
  147. if p^.treetype=stringconstn then
  148. generate_ascii_insert((p^.values^)+#0)
  149. else if is_constcharnode(p) then
  150. datasegment^.insert(new(pai_string,init(char(byte(p^.value))+#0)))
  151. else Message(cg_e_illegal_expression);
  152. datasegment^.insert(new(pai_label,init(ll)));
  153. { insert label }
  154. datasegment^.concat(new(pai_const,init_symbol(strpnew(lab2str(ll)))));
  155. end
  156. else if p^.treetype=addrn then
  157. begin
  158. if (is_equal(ppointerdef(p^.resulttype)^.definition,ppointerdef(def)^.definition) or
  159. (is_equal(ppointerdef(p^.resulttype)^.definition,voiddef)) or
  160. (is_equal(ppointerdef(def)^.definition,voiddef))) and
  161. (p^.left^.treetype = loadn) then
  162. begin
  163. datasegment^.concat(new(pai_const,init_symbol(
  164. strpnew(p^.left^.symtableentry^.mangledname))));
  165. maybe_concat_external(p^.left^.symtableentry^.owner,
  166. p^.left^.symtableentry^.mangledname);
  167. end
  168. else
  169. Message(cg_e_illegal_expression);
  170. end
  171. else
  172. { allow typeof(Object type)}
  173. if (p^.treetype=inlinen) and
  174. (p^.inlinenumber=in_typeof_x) then
  175. if (p^.left^.treetype=typen) then
  176. begin
  177. datasegment^.concat(new(pai_const,init_symbol(
  178. strpnew(pobjectdef(p^.left^.resulttype)^.vmt_mangledname))));
  179. if pobjectdef(p^.left^.resulttype)^.owner^.symtabletype=unitsymtable then
  180. concat_external(pobjectdef(p^.left^.resulttype)^.vmt_mangledname,EXT_NEAR);
  181. end
  182. else
  183. begin
  184. Message(cg_e_illegal_expression);
  185. end
  186. else
  187. Message(cg_e_illegal_expression);
  188. disposetree(p);
  189. end;
  190. setdef:
  191. begin
  192. p:=comp_expr(true);
  193. do_firstpass(p);
  194. if p^.treetype=setconstrn then
  195. begin
  196. { we only allow const sets }
  197. if assigned(p^.left) then
  198. Message(cg_e_illegal_expression)
  199. else
  200. begin
  201. for l:=0 to def^.savesize-1 do
  202. datasegment^.concat(
  203. new(pai_const,init_8bit(p^.constset^[l])));
  204. end;
  205. end
  206. else
  207. Message(cg_e_illegal_expression);
  208. disposetree(p);
  209. end;
  210. enumdef:
  211. begin
  212. p:=comp_expr(true);
  213. do_firstpass(p);
  214. if p^.treetype=ordconstn then
  215. begin
  216. if is_equal(p^.resulttype,def) then
  217. begin
  218. datasegment^.concat(new(pai_const,init_32bit(p^.value)));
  219. end
  220. else
  221. Message(cg_e_illegal_expression);
  222. end
  223. else
  224. Message(cg_e_illegal_expression);
  225. disposetree(p);
  226. end;
  227. stringdef:
  228. begin
  229. p:=comp_expr(true);
  230. do_firstpass(p);
  231. { first take care of prefixes for long and ansi strings }
  232. {$ifdef UseLongString}
  233. if pstringdef(def)^.string_typ=longstring then
  234. begin
  235. { first write the maximum size }
  236. datasegment^.concat(new(pai_const,init_32bit(p^.length)))));
  237. end else
  238. {$endif UseLongString}
  239. {$ifdef UseAnsiString}
  240. if pstringdef(def)^.string_typ=ansistring then
  241. begin
  242. {$ifdef debug}
  243. datasegment^.concat(new(pai_asm_comment,init('Header of ansistring')));
  244. {$endif debug}
  245. { first write the maximum size }
  246. datasegment^.concat(new(pai_const,init_32bit(pstringdef(def)^.len)));
  247. { second write the real length }
  248. datasegment^.concat(new(pai_const,init_32bit(p^.length)));
  249. { redondent with maxlength but who knows ... (PM) }
  250. { third write use count (set to -1 for safety ) }
  251. datasegment^.concat(new(pai_const,init_32bit(-1)));
  252. if assigned(sym) then
  253. sym^.really_insert_in_data;
  254. end;
  255. {$endif UseAnsiString}
  256. { the actual write is independent of the string_typ }
  257. if p^.treetype=stringconstn then
  258. begin
  259. {$ifdef UseAnsiString}
  260. if p^.length>=def^.size then
  261. strlength:=def^.size-1
  262. else
  263. strlength:=p^.length;
  264. { this can also handle longer strings }
  265. generate_pascii(p^.values,strlength);
  266. {$else UseAnsiString}
  267. if length(p^.values^)>=def^.size then
  268. strlength:=def^.size-1
  269. else
  270. strlength:=length(p^.values^);
  271. generate_ascii(char(strlength)+p^.values^);
  272. {$endif UseAnsiString}
  273. end
  274. else if is_constcharnode(p) then
  275. begin
  276. datasegment^.concat(new(pai_string,init(#1+char(byte(p^.value)))));
  277. strlength:=1;
  278. end
  279. else Message(cg_e_illegal_expression);
  280. if def^.size>strlength then
  281. begin
  282. getmem(ca,def^.size-strlength);
  283. fillchar(ca[0],def^.size-strlength-1,' ');
  284. ca[def^.size-strlength-1]:=#0;
  285. {$ifdef UseAnsiString}
  286. { this can also handle longer strings }
  287. generate_pascii(ca,def^.size-strlength);
  288. {$else UseAnsiString}
  289. datasegment^.concat(new(pai_string,init_pchar(ca)));
  290. {$endif UseAnsiString}
  291. disposetree(p);
  292. end;
  293. end;
  294. arraydef:
  295. begin
  296. if token=LKLAMMER then
  297. begin
  298. consume(LKLAMMER);
  299. for l:=parraydef(def)^.lowrange to parraydef(def)^.highrange-1 do
  300. begin
  301. readtypedconst(parraydef(def)^.definition,nil);
  302. consume(COMMA);
  303. end;
  304. readtypedconst(parraydef(def)^.definition,nil);
  305. consume(RKLAMMER);
  306. end
  307. else
  308. begin
  309. p:=comp_expr(true);
  310. do_firstpass(p);
  311. if p^.treetype=stringconstn then
  312. s:=p^.values^
  313. else if is_constcharnode(p) then
  314. s:=char(byte(p^.value))
  315. else Message(cg_e_illegal_expression);
  316. l:=length(s);
  317. for i:=Parraydef(def)^.lowrange to Parraydef(def)^.highrange do
  318. begin
  319. if i+1-Parraydef(def)^.lowrange<=l then
  320. begin
  321. datasegment^.concat(new(pai_const,init_8bit(byte(s[1]))));
  322. delete(s,1,1);
  323. end
  324. else
  325. {Fill the remaining positions with #0.}
  326. datasegment^.concat(new(pai_const,init_8bit(0)));
  327. end;
  328. if length(s)>0 then
  329. Message(parser_e_string_too_long);
  330. end;
  331. end;
  332. procvardef:
  333. begin
  334. { Procvars and pointers are no longer compatible. }
  335. { under tp: =nil or =var under fpc: =nil or =@var }
  336. if token=_NIL then
  337. begin
  338. datasegment^.concat(new(pai_const,init_32bit(0)));
  339. consume(_NIL);
  340. exit;
  341. end
  342. else
  343. if not(cs_tp_compatible in aktswitches) then
  344. if token=KLAMMERAFFE then
  345. consume(KLAMMERAFFE);
  346. getsym(pattern,true);
  347. consume(ID);
  348. if srsym^.typ=unitsym then
  349. begin
  350. consume(POINT);
  351. getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  352. consume(ID);
  353. end;
  354. if srsym^.typ<>procsym then
  355. Message(cg_e_illegal_expression)
  356. else
  357. begin
  358. pd:=pprocsym(srsym)^.definition;
  359. if assigned(pd^.nextoverloaded) then
  360. Message(parser_e_no_overloaded_procvars);
  361. if not((pprocvardef(def)^.options=pd^.options)) or
  362. not(is_equal(pprocvardef(def)^.retdef,pd^.retdef)) then
  363. Message(sym_e_type_mismatch)
  364. else
  365. begin
  366. hp1:=pprocvardef(def)^.para1;
  367. hp2:=pd^.para1;
  368. while assigned(hp1) and assigned(hp2) do
  369. begin
  370. if not(is_equal(hp1^.data,hp2^.data)) or
  371. not(hp1^.paratyp=hp2^.paratyp) then
  372. begin
  373. Message(sym_e_type_mismatch);
  374. break;
  375. end;
  376. hp1:=hp1^.next;
  377. hp2:=hp2^.next;
  378. end;
  379. if not((hp1=nil) and (hp2=nil)) then
  380. Message(sym_e_type_mismatch);
  381. end;
  382. datasegment^.concat(new(pai_const,init_symbol(strpnew(pd^.mangledname))));
  383. if pd^.owner^.symtabletype=unitsymtable then
  384. concat_external(pd^.mangledname,EXT_NEAR);
  385. end;
  386. end;
  387. { reads a typed constant record }
  388. recorddef:
  389. begin
  390. consume(LKLAMMER);
  391. aktpos:=0;
  392. while token<>RKLAMMER do
  393. begin
  394. s:=pattern;
  395. consume(ID);
  396. consume(COLON);
  397. srsym:=precdef(def)^.symtable^.search(s);
  398. if srsym=nil then
  399. begin
  400. Message1(sym_e_id_not_found,s);
  401. consume_all_until(SEMICOLON);
  402. end
  403. else
  404. begin
  405. { check position }
  406. if pvarsym(srsym)^.address<aktpos then
  407. Message(parser_e_invalid_record_const);
  408. { if needed fill }
  409. if pvarsym(srsym)^.address>aktpos then
  410. for i:=1 to pvarsym(srsym)^.address-aktpos do
  411. datasegment^.concat(new(pai_const,init_8bit(0)));
  412. { new position }
  413. aktpos:=pvarsym(srsym)^.address+pvarsym(srsym)^.definition^.size;
  414. { read the data }
  415. readtypedconst(pvarsym(srsym)^.definition,nil);
  416. if token=SEMICOLON then
  417. consume(SEMICOLON)
  418. else break;
  419. end;
  420. end;
  421. for i:=1 to def^.size-aktpos do
  422. datasegment^.concat(new(pai_const,init_8bit(0)));
  423. consume(RKLAMMER);
  424. end;
  425. else Message(parser_e_type_const_not_possible);
  426. end;
  427. end;
  428. end.
  429. {
  430. $Log$
  431. Revision 1.4 1998-05-05 12:05:42 florian
  432. * problems with properties fixed
  433. * crash fixed: i:=l when i and l are undefined, was a problem with
  434. implementation of private/protected
  435. Revision 1.3 1998/04/29 10:34:00 pierre
  436. + added some code for ansistring (not complete nor working yet)
  437. * corrected operator overloading
  438. * corrected nasm output
  439. + started inline procedures
  440. + added starstarn : use ** for exponentiation (^ gave problems)
  441. + started UseTokenInfo cond to get accurate positions
  442. Revision 1.2 1998/04/07 13:19:48 pierre
  443. * bugfixes for reset_gdb_info
  444. in MEM parsing for go32v2
  445. better external symbol creation
  446. support for rhgdb.exe (lowercase file names)
  447. Revision 1.1.1.1 1998/03/25 11:18:15 root
  448. * Restored version
  449. Revision 1.13 1998/03/20 23:31:35 florian
  450. * bug0113 fixed
  451. * problem with interdepened units fixed ("options.pas problem")
  452. * two small extensions for future AMD 3D support
  453. Revision 1.12 1998/03/18 22:50:11 florian
  454. + fstp/fld optimization
  455. * routines which contains asm aren't longer optimzed
  456. * wrong ifdef TEST_FUNCRET corrected
  457. * wrong data generation for array[0..n] of char = '01234'; fixed
  458. * bug0097 is fixed partial
  459. * bug0116 fixed (-Og doesn't use enter of the stack frame is greater than
  460. 65535)
  461. Revision 1.11 1998/03/13 22:45:59 florian
  462. * small bug fixes applied
  463. Revision 1.10 1998/03/11 11:23:57 florian
  464. * bug0081 and bug0109 fixed
  465. Revision 1.9 1998/03/10 01:17:25 peter
  466. * all files have the same header
  467. * messages are fully implemented, EXTDEBUG uses Comment()
  468. + AG... files for the Assembler generation
  469. Revision 1.8 1998/03/06 00:52:50 peter
  470. * replaced all old messages from errore.msg, only ExtDebug and some
  471. Comment() calls are left
  472. * fixed options.pas
  473. Revision 1.7 1998/03/02 01:49:10 peter
  474. * renamed target_DOS to target_GO32V1
  475. + new verbose system, merged old errors and verbose units into one new
  476. verbose.pas, so errors.pas is obsolete
  477. Revision 1.6 1998/02/13 10:35:33 daniel
  478. * Made Motorola version compilable.
  479. * Fixed optimizer
  480. Revision 1.5 1998/02/12 11:50:32 daniel
  481. Yes! Finally! After three retries, my patch!
  482. Changes:
  483. Complete rewrite of psub.pas.
  484. Added support for DLL's.
  485. Compiler requires less memory.
  486. Platform units for each platform.
  487. Revision 1.4 1998/01/24 23:08:19 carl
  488. + compile time range checking should logically always be on!
  489. Revision 1.3 1998/01/23 17:12:20 pierre
  490. * added some improvements for as and ld :
  491. - doserror and dosexitcode treated separately
  492. - PATH searched if doserror=2
  493. + start of long and ansi string (far from complete)
  494. in conditionnal UseLongString and UseAnsiString
  495. * options.pas cleaned (some variables shifted to globals)gl
  496. Revision 1.2 1998/01/09 09:10:03 michael
  497. + Initial implementation, second try
  498. }