{ $Id$ Copyright (c) 1998 by Florian Klaempfl Reads typed constants This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **************************************************************************** } unit ptconst; interface uses symtable; { this procedure reads typed constants } { sym is only needed for ansi strings } { the assembler label is in the middle (PM) } procedure readtypedconst(def : pdef;sym : ptypedconstsym); implementation uses cobjects,globals,scanner,aasm,tree,pass_1, hcodegen,types,verbose { parser specific stuff } ,pbase,pexpr { processor specific stuff } {$ifdef i386} ,i386 {$endif} {$ifdef m68k} ,m68k {$endif} ; { this procedure reads typed constants } procedure readtypedconst(def : pdef;sym : ptypedconstsym); var p : ptree; i,l,strlength : longint; ll : plabel; s : string; ca : pchar; aktpos : longint; pd : pprocdef; hp1,hp2 : pdefcoll; value : bestreal; {problem with fldt !! anyway .valued is not extended !! value : double; } procedure check_range; begin if ((p^.value>porddef(def)^.high) or (p^.value=def^.size then strlength:=def^.size-1 else strlength:=p^.length; datasegment^.concat(new(pai_const,init_8bit(strlength))); { this can also handle longer strings } generate_pascii(datasegment,p^.values,strlength); {$else UseAnsiString} if length(p^.values^)>=def^.size then strlength:=def^.size-1 else strlength:=length(p^.values^); generate_ascii(char(strlength)+p^.values^); {$endif UseAnsiString} end else if is_constcharnode(p) then begin datasegment^.concat(new(pai_string,init(#1+char(byte(p^.value))))); strlength:=1; end else Message(cg_e_illegal_expression); if def^.size>strlength then begin getmem(ca,def^.size-strlength); fillchar(ca[0],def^.size-strlength-1,' '); ca[def^.size-strlength-1]:=#0; {$ifdef UseAnsiString} { this can also handle longer strings } { def^.size contains also the leading length, so we } { we have to subtract one } generate_pascii(datasegment,ca,def^.size-strlength-1); {$else UseAnsiString} datasegment^.concat(new(pai_string,init_pchar(ca))); {$endif UseAnsiString} end; end; {$ifdef UseLongString} st_longstring: begin { first write the maximum size } datasegment^.concat(new(pai_const,init_32bit(p^.length))))); { fill byte } datasegment^.concat(new(pai_const,init_8bit(0))); if p^.treetype=stringconstn then begin { this can also handle longer strings } generate_pascii(consts,p^.values,p^.length); end else if is_constcharnode(p) then begin consts^.concat(new(pai_const,init_8bit(p^.value))); strlength:=1; end else Message(cg_e_illegal_expression); datasegment^.concat(new(pai_const,init_8bit(0))); end; {$endif UseLongString} {$ifdef UseAnsiString} st_ansistring: begin { an empty ansi string is nil! } if (p^.treetype=stringconstn) and (p^.length=0) then datasegment^.concat(new(pai_const,init_32bit(0))) else begin getlabel(ll); datasegment^.concat(new(pai_const,init_symbol(strpnew(lab2str(ll))))); { first write the maximum size } consts^.concat(new(pai_const,init_32bit(p^.length))); { second write the real length } consts^.concat(new(pai_const,init_32bit(p^.length))); { redondent with maxlength but who knows ... (PM) } { third write use count (set to -1 for safety ) } consts^.concat(new(pai_const,init_32bit(-1))); { not longer necessary, because it insert_indata if assigned(sym) then sym^.really_insert_in_data; } consts^.concat(new(pai_label,init(ll))); if p^.treetype=stringconstn then begin { this can also handle longer strings } generate_pascii(consts,p^.values,p^.length); end else if is_constcharnode(p) then begin consts^.concat(new(pai_const,init_8bit(p^.value))); strlength:=1; end else Message(cg_e_illegal_expression); consts^.concat(new(pai_const,init_8bit(0))); end; end; {$endif UseAnsiString} end; disposetree(p); end; arraydef: begin if token=LKLAMMER then begin consume(LKLAMMER); for l:=parraydef(def)^.lowrange to parraydef(def)^.highrange-1 do begin readtypedconst(parraydef(def)^.definition,nil); consume(COMMA); end; readtypedconst(parraydef(def)^.definition,nil); consume(RKLAMMER); end else begin p:=comp_expr(true); do_firstpass(p); if p^.treetype=stringconstn then s:=p^.values^ else if is_constcharnode(p) then s:=char(byte(p^.value)) else Message(cg_e_illegal_expression); l:=length(s); for i:=Parraydef(def)^.lowrange to Parraydef(def)^.highrange do begin if i+1-Parraydef(def)^.lowrange<=l then begin datasegment^.concat(new(pai_const,init_8bit(byte(s[1])))); delete(s,1,1); end else {Fill the remaining positions with #0.} datasegment^.concat(new(pai_const,init_8bit(0))); end; if length(s)>0 then Message(parser_e_string_too_long); end; end; procvardef: begin { Procvars and pointers are no longer compatible. } { under tp: =nil or =var under fpc: =nil or =@var } if token=_NIL then begin datasegment^.concat(new(pai_const,init_32bit(0))); consume(_NIL); exit; end else if not(cs_tp_compatible in aktmoduleswitches) then if token=KLAMMERAFFE then consume(KLAMMERAFFE); getsym(pattern,true); consume(ID); if srsym^.typ=unitsym then begin consume(POINT); getsymonlyin(punitsym(srsym)^.unitsymtable,pattern); consume(ID); end; if srsym^.typ<>procsym then Message(cg_e_illegal_expression) else begin pd:=pprocsym(srsym)^.definition; if assigned(pd^.nextoverloaded) then Message(parser_e_no_overloaded_procvars); if not((pprocvardef(def)^.options=pd^.options)) or not(is_equal(pprocvardef(def)^.retdef,pd^.retdef)) then Message(sym_e_type_mismatch) else begin hp1:=pprocvardef(def)^.para1; hp2:=pd^.para1; while assigned(hp1) and assigned(hp2) do begin if not(is_equal(hp1^.data,hp2^.data)) or not(hp1^.paratyp=hp2^.paratyp) then begin Message(sym_e_type_mismatch); break; end; hp1:=hp1^.next; hp2:=hp2^.next; end; if not((hp1=nil) and (hp2=nil)) then Message(sym_e_type_mismatch); end; datasegment^.concat(new(pai_const,init_symbol(strpnew(pd^.mangledname)))); if pd^.owner^.symtabletype=unitsymtable then concat_external(pd^.mangledname,EXT_NEAR); end; end; { reads a typed constant record } recorddef: begin consume(LKLAMMER); aktpos:=0; while token<>RKLAMMER do begin s:=pattern; consume(ID); consume(COLON); srsym:=precdef(def)^.symtable^.search(s); if srsym=nil then begin Message1(sym_e_id_not_found,s); consume_all_until(SEMICOLON); end else begin { check position } if pvarsym(srsym)^.addressaktpos then for i:=1 to pvarsym(srsym)^.address-aktpos do datasegment^.concat(new(pai_const,init_8bit(0))); { new position } aktpos:=pvarsym(srsym)^.address+pvarsym(srsym)^.definition^.size; { read the data } readtypedconst(pvarsym(srsym)^.definition,nil); if token=SEMICOLON then consume(SEMICOLON) else break; end; end; for i:=1 to def^.size-aktpos do datasegment^.concat(new(pai_const,init_8bit(0))); consume(RKLAMMER); end; else Message(parser_e_type_const_not_possible); end; end; end. { $Log$ Revision 1.11 1998-08-10 14:50:20 peter + localswitches, moduleswitches, globalswitches splitting Revision 1.10 1998/07/21 11:16:25 florian * bug0147 fixed Revision 1.9 1998/07/20 22:17:16 florian * hex constants in numeric char (#$54#$43 ...) are now allowed * there was a bug in record_var_dec which prevents the used of nested variant records (for example drivers.tevent of tv) Revision 1.8 1998/07/20 18:40:15 florian * handling of ansi string constants should now work Revision 1.7 1998/07/18 22:54:29 florian * some ansi/wide/longstring support fixed: o parameter passing o returning as result from functions Revision 1.6 1998/06/08 22:59:52 peter * smartlinking works for win32 * some defines to exclude some compiler parts Revision 1.5 1998/06/03 22:49:01 peter + wordbool,longbool * rename bis,von -> high,low * moved some systemunit loading/creating to psystem.pas Revision 1.4 1998/05/05 12:05:42 florian * problems with properties fixed * crash fixed: i:=l when i and l are undefined, was a problem with implementation of private/protected Revision 1.3 1998/04/29 10:34:00 pierre + added some code for ansistring (not complete nor working yet) * corrected operator overloading * corrected nasm output + started inline procedures + added starstarn : use ** for exponentiation (^ gave problems) + started UseTokenInfo cond to get accurate positions }