ptconst.pas 20 KB

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