{ $Id$ Copyright (c) 1993-98 by Florian Klaempfl, Pierre Muller Implementation for the symbols types of the symtable 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. **************************************************************************** } {**************************************************************************** TSYM (base for all symtypes) ****************************************************************************} constructor tsym.init(const n : string); begin left:=nil; right:=nil; setname(n); typ:=abstractsym; properties:=current_object_option; {$ifdef GDB} isstabwritten := false; {$endif GDB} fileinfo:=aktfilepos; {$ifdef UseBrowser} defref:=nil; lastwritten:=nil; refcount:=0; if (cs_browser in aktmoduleswitches) and make_ref then begin defref:=new(pref,init(defref,@tokenpos)); inc(refcount); end; lastref:=defref; {$endif UseBrowser} end; constructor tsym.load; begin left:=nil; right:=nil; setname(readstring); typ:=abstractsym; fillchar(fileinfo,sizeof(fileinfo),0); if object_options then properties:=symprop(readbyte) else properties:=sp_public; {$ifdef UseBrowser} lastref:=nil; defref:=nil; lastwritten:=nil; refcount:=0; {$endif UseBrowser} {$ifdef GDB} isstabwritten := false; {$endif GDB} end; {$ifdef UseBrowser} {$ifndef OLDPPU} procedure tsym.load_references; var pos : tfileposinfo; begin while (not current_ppu^.endofentry) do begin readposinfo(pos); inc(refcount); lastref:=new(pref,init(lastref,@pos)); if refcount=1 then defref:=lastref; end; lastwritten:=lastref; end; procedure tsym.write_references; var ref : pref; prdef : pdef; begin if lastwritten=lastref then exit; { write address to this symbol } writesymref(@self); { write symbol refs } if assigned(lastwritten) then ref:=lastwritten else ref:=defref; while assigned(ref) do begin writeposinfo(ref^.posinfo); ref:=ref^.nextref; end; lastwritten:=lastref; current_ppu^.writeentry(ibsymref); { when it's a procsym then write also the refs to the definition due the overloading } if typ=procsym then begin prdef:=pprocsym(@self)^.definition; while assigned(prdef) do begin pprocdef(prdef)^.write_references; prdef:=pprocdef(prdef)^.nextoverloaded; end; end; end; {$else OLDPPU} procedure tsym.load_references; var fileindex : word; b : byte; l,c : longint; begin b:=readbyte; while b=ibref do begin fileindex:=readword; l:=readlong; c:=readword; inc(refcount); lastref:=new(pref,load(lastref,fileindex,l,c)); if refcount=1 then defref:=lastref; b:=readbyte; end; lastwritten:=lastref; if b <> ibend then Message(unit_f_ppu_read_error); end; procedure tsym.write_references; var ref : pref; begin { references do not change the ppu caracteristics } { this only save the references to variables/functions } { defined in the unit what about the others } ppufile.do_crc:=false; if assigned(lastwritten) then ref:=lastwritten else ref:=defref; while assigned(ref) do begin writebyte(ibref); writeword(ref^.posinfo.fileindex); writelong(ref^.posinfo.line); writeword(ref^.posinfo.column); ref:=ref^.nextref; end; lastwritten:=lastref; writebyte(ibend); ppufile.do_crc:=true; end; procedure tsym.write_external_references; var ref : pref; prdef : pdef; begin ppufile.do_crc:=false; if lastwritten=lastref then exit; writebyte(ibextsymref); writesymref(@self); if assigned(lastwritten) then ref:=lastwritten else ref:=defref; while assigned(ref) do begin writebyte(ibref); writeword(ref^.posinfo.fileindex); writelong(ref^.posinfo.line); writeword(ref^.posinfo.column); ref:=ref^.nextref; end; lastwritten:=lastref; writebyte(ibend); if typ=procsym then begin prdef:=pprocsym(@self)^.definition; while assigned(prdef) do begin pprocdef(prdef)^.write_external_references; prdef:=pprocdef(prdef)^.nextoverloaded; end; end; ppufile.do_crc:=true; end; {$endif OLDPPU} procedure tsym.add_to_browserlog; var prdef : pprocdef; begin if assigned(defref) then begin Browse.AddLog('***'+name+'***'); Browse.AddLogRefs(defref); end; { when it's a procsym then write also the refs to the definition due the overloading } if typ=procsym then begin prdef:=pprocsym(@self)^.definition; while assigned(prdef) do begin pprocdef(prdef)^.add_to_browserlog; prdef:=pprocdef(prdef)^.nextoverloaded; end; end; end; {$endif UseBrowser} destructor tsym.done; begin {$ifdef tp} if not(use_big) then {$endif tp} strdispose(_name); {$ifdef UseBrowser} if assigned(defref) then dispose(defref,done); {$endif UseBrowser} if assigned(left) then dispose(left,done); if assigned(right) then dispose(right,done); end; destructor tsym.single_done; begin {$ifdef tp} if not(use_big) then {$endif tp} strdispose(_name); end; procedure tsym.write; begin writestring(name); if object_options then writebyte(byte(properties)); {$ifdef UseBrowser} { if cs_browser in aktmoduleswitches then write_references; } {$endif UseBrowser} end; procedure tsym.deref; begin end; function tsym.name : string; {$ifdef tp} var s : string; b : byte; {$endif} begin {$ifdef tp} if use_big then begin symbolstream.seek(longint(_name)); symbolstream.read(b,1); symbolstream.read(s[1],b); s[0]:=chr(b); name:=s; end else {$endif} if assigned(_name) then name:=strpas(_name) else name:=''; end; function tsym.mangledname : string; begin mangledname:=name; end; procedure tsym.setname(const s : string); begin setstring(_name,s); end; { for most symbol types ther is nothing to do at all } procedure tsym.insert_in_data; begin end; {$ifdef GDB} function tsym.stabstring : pchar; begin stabstring:=strpnew('"'+name+'",'+tostr(N_LSYM)+',0,'+ tostr(fileinfo.line)+',0'); end; procedure tsym.concatstabto(asmlist : paasmoutput); var stab_str : pchar; begin if not isstabwritten then begin stab_str := stabstring; if asmlist = debuglist then do_count_dbx := true; { count_dbx(stab_str); moved to GDB.PAS } asmlist^.concat(new(pai_stabs,init(stab_str))); isstabwritten:=true; end; end; {$endif GDB} {**************************************************************************** TLABELSYM ****************************************************************************} constructor tlabelsym.init(const n : string; l : plabel); begin inherited init(n); typ:=labelsym; number:=l; number^.is_used:=false; number^.is_set:=true; number^.refcount:=0; defined:=false; end; destructor tlabelsym.done; begin if not(defined) then Message1(sym_e_label_not_defined,name); inherited done; end; function tlabelsym.mangledname : string; begin { this also sets the is_used field } mangledname:=lab2str(number); end; procedure tlabelsym.write; begin Message(sym_e_ill_label_decl); end; {**************************************************************************** TUNITSYM ****************************************************************************} constructor tunitsym.init(const n : string;ref : punitsymtable); var old_make_ref : boolean; begin old_make_ref:=make_ref; make_ref:=false; inherited init(n); make_ref:=old_make_ref; typ:=unitsym; unitsymtable:=ref; prevsym:=ref^.unitsym; ref^.unitsym:=@self; refs:=0; end; destructor tunitsym.done; begin if assigned(unitsymtable) and (unitsymtable^.unitsym=@self) then unitsymtable^.unitsym:=prevsym; inherited done; end; procedure tunitsym.write; begin end; {$ifdef GDB} procedure tunitsym.concatstabto(asmlist : paasmoutput); begin {Nothing to write to stabs !} end; {$endif GDB} {**************************************************************************** TPROCSYM ****************************************************************************} constructor tprocsym.init(const n : string); begin tsym.init(n); typ:=procsym; definition:=nil; owner:=nil; {$ifdef GDB} is_global := false; {$endif GDB} end; constructor tprocsym.load; begin tsym.load; typ:=procsym; definition:=pprocdef(readdefref); {$ifdef GDB} is_global := false; {$endif GDB} end; destructor tprocsym.done; begin check_forward; tsym.done; end; function tprocsym.mangledname : string; begin mangledname:=definition^.mangledname; end; function tprocsym.demangledname:string; begin demangledname:=name+definition^.demangled_paras; end; procedure tprocsym.check_forward; var pd : pprocdef; oldaktfilepos : tfileposinfo; begin pd:=definition; while assigned(pd) do begin if pd^.forwarddef then begin oldaktfilepos:=aktfilepos; aktfilepos:=fileinfo; if assigned(pd^._class) then Message1(sym_e_forward_not_resolved,pd^._class^.name^+'.'+name+demangledparas(pd^.demangled_paras)) else Message1(sym_e_forward_not_resolved,name+pd^.demangled_paras); aktfilepos:=oldaktfilepos; end; pd:=pd^.nextoverloaded; end; end; procedure tprocsym.deref; var t : ttoken; last : pprocdef; begin resolvedef(pdef(definition)); if (definition^.options and pooperator) <> 0 then begin last:=definition; while assigned(last^.nextoverloaded) do last:=last^.nextoverloaded; for t:=PLUS to last_overloaded do if (name=overloaded_names[t]) then begin if assigned(overloaded_operators[t]) then last^.nextoverloaded:=overloaded_operators[t]^.definition; overloaded_operators[t]:=@self; end; end; end; procedure tprocsym.write; begin {$ifdef OLDPPU} writebyte(ibprocsym); {$endif} tsym.write; writedefref(pdef(definition)); {$ifndef OLDPPU} current_ppu^.writeentry(ibprocsym); {$endif} end; {$ifdef GDB} function tprocsym.stabstring : pchar; Var RetType : Char; Obj,Info : String; begin obj := name; info := ''; if is_global then RetType := 'F' else RetType := 'f'; if assigned(owner) then begin if (owner^.symtabletype = objectsymtable) then obj := owner^.name^+'__'+name; if (owner^.symtabletype=localsymtable) and assigned(owner^.name) then info := ','+name+','+owner^.name^; end; stabstring :=strpnew('"'+obj+':'+RetType +definition^.retdef^.numberstring+info+'",'+tostr(n_function) +',0,'+ tostr(aktfilepos.line) +','+definition^.mangledname); end; procedure tprocsym.concatstabto(asmlist : paasmoutput); begin if (definition^.options and pointernproc) <> 0 then exit; if not isstabwritten then asmlist^.concat(new(pai_stabs,init(stabstring))); isstabwritten := true; if assigned(definition^.parast) then definition^.parast^.concatstabto(asmlist); if assigned(definition^.localst) then definition^.localst^.concatstabto(asmlist); definition^.is_def_stab_written := true; end; {$endif GDB} {**************************************************************************** TPROGRAMSYM ****************************************************************************} constructor tprogramsym.init(const n : string); begin inherited init(n); typ:=programsym; end; {**************************************************************************** TERRORSYM ****************************************************************************} constructor terrorsym.init; begin inherited init(''); typ:=errorsym; end; {**************************************************************************** TPROPERTYSYM ****************************************************************************} constructor tpropertysym.init(const n : string); begin inherited init(n); typ:=propertysym; options:=0; proptype:=nil; readaccessdef:=nil; writeaccessdef:=nil; readaccesssym:=nil; writeaccesssym:=nil; index:=$0; end; destructor tpropertysym.done; begin inherited done; end; constructor tpropertysym.load; begin inherited load; typ:=propertysym; proptype:=readdefref; options:=readlong; index:=readlong; { it's hack ... } readaccesssym:=psym(stringdup(readstring)); writeaccesssym:=psym(stringdup(readstring)); { now the defs: } readaccessdef:=readdefref; writeaccessdef:=readdefref; end; procedure tpropertysym.deref; begin resolvedef(proptype); resolvedef(readaccessdef); resolvedef(writeaccessdef); { solve the hack we did in load: } if pstring(readaccesssym)^<>'' then begin srsym:=search_class_member(pobjectdef(owner^.defowner),pstring(readaccesssym)^); if not(assigned(srsym)) then srsym:=generrorsym; end else srsym:=nil; stringdispose(pstring(readaccesssym)); readaccesssym:=srsym; if pstring(writeaccesssym)^<>'' then begin srsym:=search_class_member(pobjectdef(owner^.defowner),pstring(writeaccesssym)^); if not(assigned(srsym)) then srsym:=generrorsym; end else srsym:=nil; stringdispose(pstring(writeaccesssym)); writeaccesssym:=srsym; end; function tpropertysym.getsize : longint; begin getsize:=0; end; procedure tpropertysym.write; begin {$ifdef OLDPPU} writebyte(ibpropertysym); {$endif} tsym.write; writedefref(proptype); writelong(options); writelong(index); if assigned(readaccesssym) then writestring(readaccesssym^.name) else writestring(''); if assigned(writeaccesssym) then writestring(writeaccesssym^.name) else writestring(''); writedefref(readaccessdef); writedefref(writeaccessdef); {$ifndef OLDPPU} current_ppu^.writeentry(ibpropertysym); {$endif} end; {$ifdef GDB} function tpropertysym.stabstring : pchar; begin { !!!! don't know how to handle } stabstring:=strpnew(''); end; procedure tpropertysym.concatstabto(asmlist : paasmoutput); begin { !!!! don't know how to handle } end; {$endif GDB} {**************************************************************************** TFUNCRETSYM ****************************************************************************} {$ifdef TEST_FUNCRET} constructor tfuncretsym.init(const n : string;approcinfo : pointer{pprocinfo}); begin tsym.init(n); funcretprocinfo:=approcinfo; funcretdef:=pprocinfo(approcinfo)^.retdef; { address valid for ret in param only } { otherwise set by insert } address:=pprocinfo(approcinfo)^.retoffset; end; {$endif TEST_FUNCRET} {**************************************************************************** TABSOLUTESYM ****************************************************************************} { constructor tabsolutesym.init(const s : string;p : pdef;newref : psym); begin inherited init(s,p); ref:=newref; typ:=absolutesym; end; } constructor tabsolutesym.load; begin tvarsym.load; typ:=absolutesym; ref:=nil; address:=0; asmname:=nil; abstyp:=absolutetyp(readbyte); absseg:=false; case abstyp of tovar : begin asmname:=stringdup(readstring); ref:=srsym; end; toasm : asmname:=stringdup(readstring); toaddr : address:=readlong; end; end; procedure tabsolutesym.write; begin {$ifdef OLDPPU} writebyte(ibabsolutesym); {$endif} tsym.write; writebyte(byte(varspez)); if read_member then writelong(address); writedefref(definition); writebyte(byte(abstyp)); case abstyp of tovar : writestring(ref^.name); toasm : writestring(asmname^); toaddr : writelong(address); end; {$ifndef OLDPPU} current_ppu^.writeentry(ibabsolutesym); {$endif} end; procedure tabsolutesym.deref; begin resolvedef(definition); if (abstyp=tovar) and (asmname<>nil) then begin { search previous loaded symtables } getsym(asmname^,false); if not(assigned(srsym)) then getsymonlyin(owner,asmname^); if not(assigned(srsym)) then srsym:=generrorsym; ref:=srsym; stringdispose(asmname); end; end; function tabsolutesym.mangledname : string; begin case abstyp of tovar : mangledname:=ref^.mangledname; toasm : mangledname:=asmname^; toaddr : mangledname:='$'+tostr(address); else internalerror(10002); end; end; procedure tabsolutesym.insert_in_data; begin end; {$ifdef GDB} procedure tabsolutesym.concatstabto(asmlist : paasmoutput); begin { I don't know how to handle this !! } end; {$endif GDB} {**************************************************************************** TVARSYM ****************************************************************************} constructor tvarsym.init(const n : string;p : pdef); begin tsym.init(n); typ:=varsym; definition:=p; _mangledname:=nil; varspez:=vs_value; address:=0; refs:=0; is_valid := 1; var_options:=0; { can we load the value into a register ? } case p^.deftype of pointerdef, enumdef, procvardef : var_options:=var_options or vo_regable; orddef : case porddef(p)^.typ of u8bit,u16bit,u32bit, bool8bit,bool16bit,bool32bit, s8bit,s16bit,s32bit : var_options:=var_options or vo_regable; else var_options:=var_options and not vo_regable; end; else var_options:=var_options and not vo_regable; end; reg:=R_NO; end; constructor tvarsym.load; begin tsym.load; typ:=varsym; _mangledname:=nil; varspez:=tvarspez(readbyte); if read_member then address:=readlong else address:=0; definition:=readdefref; refs := 0; is_valid := 1; { symbols which are load are never candidates for a register } var_options:=0; { was regable:=false; } reg:=R_NO; end; constructor tvarsym.init_C(const n,mangled : string;p : pdef); begin { The tvarsym is necessary for 0.99.5 (PFV) } tvarsym.init(n,p); var_options:=var_options or vo_is_C_var; _mangledname:=strpnew(target_os.Cprefix+mangled); end; constructor tvarsym.load_C; begin { Adding tvarsym removes the warning } tvarsym.load; typ:=varsym; var_options:=readbyte; _mangledname:=strpnew(readstring); end; procedure tvarsym.deref; begin resolvedef(definition); end; procedure tvarsym.write; begin {$ifdef OLDPPU} if (var_options and vo_is_C_var)<>0 then writebyte(ibvarsym_C) else writebyte(ibvarsym); {$endif} tsym.write; writebyte(byte(varspez)); if read_member then writelong(address); writedefref(definition); if (var_options and vo_is_C_var)<>0 then begin writebyte(var_options); writestring(mangledname); end; {$ifndef OLDPPU} if (var_options and vo_is_C_var)<>0 then current_ppu^.writeentry(ibvarsym_C) else current_ppu^.writeentry(ibvarsym); {$endif} end; function tvarsym.mangledname : string; var prefix : string; begin if assigned(_mangledname) then begin mangledname:=strpas(_mangledname); exit; end; case owner^.symtabletype of staticsymtable : if (cs_smartlink in aktmoduleswitches) then prefix:='_'+owner^.name^+'$$$_' else prefix:='_'; unitsymtable, globalsymtable : prefix:='U_'+owner^.name^+'_'; else Message(sym_e_invalid_call_tvarsymmangledname); end; mangledname:=prefix+name; end; function tvarsym.getsize : longint; begin { only if the definition is set, we could determine the } { size, this is if an error occurs while reading the type } { also used for operator, this allows not to allocate the } { return size twice } if assigned(definition) then begin case varspez of vs_value : getsize:=definition^.size; vs_var : getsize:=sizeof(pointer); vs_const : begin if (definition^.deftype in [stringdef,arraydef, recorddef,objectdef,setdef]) then getsize:=sizeof(pointer) else getsize:=definition^.size; end; end; end else getsize:=0; end; procedure tvarsym.insert_in_data; var l,modulo : longint; begin if (var_options and vo_is_external)<>0 then exit; { handle static variables of objects especially } if read_member and (owner^.symtabletype=objectsymtable) and ((properties and sp_static)<>0) then begin { the data filed is generated in parser.pas with a tobject_FIELDNAME variable } { this symbol can't be loaded to a register } var_options:=var_options and not vo_regable; end else if not(read_member) then begin { made problems with parameters etc. ! (FK) } { check for instance of an abstract object or class } { if (pvarsym(sym)^.definition^.deftype=objectdef) and ((pobjectdef(pvarsym(sym)^.definition)^.options and oois_abstract)<>0) then Message(sym_e_no_instance_of_abstract_object); } l:=getsize; case owner^.symtabletype of stt_exceptsymtable: { can contain only one symbol, address calculated later } ; localsymtable : begin is_valid := 0; modulo:=owner^.datasize and 3; {$ifdef m68k} { word alignment required for motorola } if (l=1) then l:=2 else {$endif} if (l>=4) and (modulo<>0) then inc(l,4-modulo) else if (l>=2) and ((modulo and 1)<>0) then inc(l,2-(modulo and 1)); inc(owner^.datasize,l); address:=owner^.datasize; end; staticsymtable : begin if (cs_smartlink in aktmoduleswitches) then bsssegment^.concat(new(pai_cut,init)); {$ifdef GDB} if cs_debuginfo in aktmoduleswitches then concatstabto(bsssegment); {$endif GDB} if (cs_smartlink in aktmoduleswitches) or ((var_options and vo_is_c_var)<>0) then bsssegment^.concat(new(pai_datablock,init_global(mangledname,l))) else bsssegment^.concat(new(pai_datablock,init(mangledname,l))); { increase datasize } inc(owner^.datasize,l); { this symbol can't be loaded to a register } var_options:=var_options and not vo_regable; end; globalsymtable : begin if (cs_smartlink in aktmoduleswitches) then bsssegment^.concat(new(pai_cut,init)); {$ifdef GDB} if cs_debuginfo in aktmoduleswitches then concatstabto(bsssegment); {$endif GDB} bsssegment^.concat(new(pai_datablock,init_global(mangledname,l))); inc(owner^.datasize,l); { this symbol can't be loaded to a register } var_options:=var_options and not vo_regable; end; recordsymtable, objectsymtable : begin { this symbol can't be loaded to a register } var_options:=var_options and not vo_regable; { align record and object fields } if (l=1) or (aktpackrecords=1) then begin address:=owner^.datasize; inc(owner^.datasize,l) end else if (l=2) or (aktpackrecords=2) then begin owner^.datasize:=(owner^.datasize+1) and (not 1); address:=owner^.datasize; inc(owner^.datasize,l) end else if (l<=4) or (aktpackrecords=4) then begin owner^.datasize:=(owner^.datasize+3) and (not 3); address:=owner^.datasize; inc(owner^.datasize,l); end else if (l<=16) or (aktpackrecords=16) then begin owner^.datasize:=(owner^.datasize+15) and (not 15); address:=owner^.datasize; inc(owner^.datasize,l); end; end; parasymtable : begin address:=owner^.datasize; { needs word alignment } if odd(l) then inc(owner^.datasize,l+1) else inc(owner^.datasize,l); end else begin modulo:=owner^.datasize and 3 ; if (l>=4) and (modulo<>0) then inc(owner^.datasize,4-modulo) else if (l>=2) and ((modulo and 1)<>0) then { nice piece of code !! inc(owner^.datasize,2-(datasize and 1)); 2 - (datasize and 1) is allways 1 in this case Florian when will your global stream analyser find this out ?? } inc(owner^.datasize); address:=owner^.datasize; inc(owner^.datasize,l); end; end; end; end; {$ifdef GDB} function tvarsym.stabstring : pchar; var st : char; begin if (owner^.symtabletype = objectsymtable) and ((properties and sp_static)<>0) then begin if use_gsym then st := 'G' else st := 'S'; stabstring := strpnew('"'+owner^.name^+'__'+name+':'+ +definition^.numberstring+'",'+ tostr(N_LCSYM)+',0,'+tostr(fileinfo.line)+','+mangledname); end else if (owner^.symtabletype = globalsymtable) or (owner^.symtabletype = unitsymtable) then begin { Here we used S instead of because with G GDB doesn't look at the address field but searches the same name or with a leading underscore but these names don't exist in pascal !} if use_gsym then st := 'G' else st := 'S'; stabstring := strpnew('"'+name+':'+st +definition^.numberstring+'",'+ tostr(N_LCSYM)+',0,'+tostr(fileinfo.line)+','+mangledname); end else if owner^.symtabletype = staticsymtable then begin stabstring := strpnew('"'+name+':S' +definition^.numberstring+'",'+ tostr(N_LCSYM)+',0,'+tostr(fileinfo.line)+','+mangledname); end else if (owner^.symtabletype=parasymtable) then begin case varspez of vs_value : st := 'p'; vs_var : st := 'v'; vs_const : if dont_copy_const_param(definition) then st := 'v'{ should be 'i' but 'i' doesn't work } else st := 'p'; end; stabstring := strpnew('"'+name+':'+st +definition^.numberstring+'",'+ tostr(N_PSYM)+',0,'+tostr(fileinfo.line)+','+ tostr(address+owner^.call_offset)); {offset to ebp => will not work if the framepointer is esp so some optimizing will make things harder to debug } end else if (owner^.symtabletype=localsymtable) then {$ifdef i386} if reg<>R_NO then begin { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", } { this is the register order for GDB} stabstring:=strpnew('"'+name+':r' +definition^.numberstring+'",'+ tostr(N_RSYM)+',0,'+ tostr(fileinfo.line)+','+tostr(GDB_i386index[reg])); end else {$endif i386} stabstring := strpnew('"'+name+':' +definition^.numberstring+'",'+ tostr(N_LSYM)+',0,'+tostr(fileinfo.line)+',-'+tostr(address)) else stabstring := inherited stabstring; end; procedure tvarsym.concatstabto(asmlist : paasmoutput); {$ifdef i386} var stab_str : pchar; {$endif i386} begin inherited concatstabto(asmlist); {$ifdef i386} if (owner^.symtabletype=parasymtable) and (reg<>R_NO) then begin { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", } { this is the register order for GDB} stab_str:=strpnew('"'+name+':r' +definition^.numberstring+'",'+ tostr(N_RSYM)+',0,'+ tostr(fileinfo.line)+','+tostr(GDB_i386index[reg])); asmlist^.concat(new(pai_stabs,init(stab_str))); end; {$endif i386} end; {$endif GDB} destructor tvarsym.done; begin strdispose(_mangledname); inherited done; end; {**************************************************************************** TTYPEDCONSTSYM *****************************************************************************} constructor ttypedconstsym.init(const n : string;p : pdef); begin tsym.init(n); typ:=typedconstsym; definition:=p; prefix:=stringdup(procprefix); end; constructor ttypedconstsym.load; begin tsym.load; typ:=typedconstsym; definition:=readdefref; prefix:=stringdup(readstring); end; destructor ttypedconstsym.done; begin stringdispose(prefix); tsym.done; end; function ttypedconstsym.mangledname : string; begin mangledname:='TC_'+prefix^+'_'+name; end; procedure ttypedconstsym.deref; begin resolvedef(definition); end; procedure ttypedconstsym.write; begin {$ifdef OLDPPU} writebyte(ibtypedconstsym); {$endif} tsym.write; writedefref(definition); writestring(prefix^); {$ifndef OLDPPU} current_ppu^.writeentry(ibtypedconstsym); {$endif} end; { for most symbol types ther is nothing to do at all } procedure ttypedconstsym.insert_in_data; begin { here there is a problem for ansistrings !! } { we must write the label only after the 12 header bytes (PM) if not is_ansistring(definition) then } { solved, the ansis string is moved to consts (FK) } really_insert_in_data; end; procedure ttypedconstsym.really_insert_in_data; begin if owner^.symtabletype=globalsymtable then begin if (cs_smartlink in aktmoduleswitches) then datasegment^.concat(new(pai_cut,init)); {$ifdef GDB} if cs_debuginfo in aktmoduleswitches then concatstabto(datasegment); {$endif GDB} datasegment^.concat(new(pai_symbol,init_global(mangledname))); end else if owner^.symtabletype<>unitsymtable then begin if (cs_smartlink in aktmoduleswitches) then datasegment^.concat(new(pai_cut,init)); {$ifdef GDB} if cs_debuginfo in aktmoduleswitches then concatstabto(datasegment); {$endif GDB} if (cs_smartlink in aktmoduleswitches) then datasegment^.concat(new(pai_symbol,init_global(mangledname))) else datasegment^.concat(new(pai_symbol,init(mangledname))); end; end; {$ifdef GDB} function ttypedconstsym.stabstring : pchar; var st : char; begin if use_gsym and (owner^.symtabletype in [unitsymtable,globalsymtable]) then st := 'G' else st := 'S'; stabstring := strpnew('"'+name+':'+st+ definition^.numberstring+'",'+tostr(n_STSYM)+',0,'+ tostr(fileinfo.line)+','+mangledname); end; {$endif GDB} {**************************************************************************** TCONSTSYM ****************************************************************************} constructor tconstsym.init(const n : string;t : tconsttype;v : longint;def : pdef); begin tsym.init(n); typ:=constsym; definition:=def; consttype:=t; value:=v; end; constructor tconstsym.load; var pd : pdouble; ps : pointer; {***SETCONST} begin tsym.load; typ:=constsym; consttype:=tconsttype(readbyte); case consttype of constint, constbool, constchar : value:=readlong; constord : begin definition:=readdefref; value:=readlong; end; conststring : value:=longint(stringdup(readstring)); constreal : begin new(pd); pd^:=readdouble; value:=longint(pd); end; {***SETCONST} constseta : begin getmem(ps,32); readset(ps^); value:=longint(ps); end; {***} else Message1(unit_f_ppu_invalid_entry,tostr(ord(consttype))); end; end; destructor tconstsym.done; begin if consttype = conststring then stringdispose(pstring(value)); inherited done; end; function tconstsym.mangledname : string; begin mangledname:=name; end; procedure tconstsym.deref; begin if consttype=constord then resolvedef(pdef(definition)); end; procedure tconstsym.write; begin {$ifdef OLDPPU} writebyte(ibconstsym); {$endif} tsym.write; writebyte(byte(consttype)); case consttype of constint, constbool, constchar : writelong(value); constord : begin writedefref(definition); writelong(value); end; conststring : writestring(pstring(value)^); constreal : writedouble(pdouble(value)^); {***SETCONST} constseta: writeset(pointer(value)^); {***} else internalerror(13); end; {$ifndef OLDPPU} current_ppu^.writeentry(ibconstsym); {$endif} end; {$ifdef GDB} function tconstsym.stabstring : pchar; var st : string; begin {even GDB v4.16 only now 'i' 'r' and 'e' !!!} case consttype of conststring : begin { I had to remove ibm2ascii !! } st := pstring(value)^; {st := ibm2ascii(pstring(value)^);} st := 's'''+st+''''; end; constbool, constint, constord, constchar : st := 'i'+tostr(value); constreal : begin system.str(pdouble(value)^,st); st := 'r'+st; end; { if we don't know just put zero !! } else st:='i0'; {***SETCONST} {constset:;} {*** I don't know what to do with a set.} { sets are not recognized by GDB} {***} end; stabstring := strpnew('"'+name+':c='+st+'",'+tostr(N_function)+',0,'+ tostr(fileinfo.line)+',0'); end; procedure tconstsym.concatstabto(asmlist : paasmoutput); begin if consttype <> conststring then inherited concatstabto(asmlist); end; {$endif GDB} {**************************************************************************** TENUMSYM ****************************************************************************} constructor tenumsym.init(const n : string;def : penumdef;v : longint); begin tsym.init(n); typ:=enumsym; definition:=def; value:=v; {$ifdef GDB} order; {$endif GDB} end; constructor tenumsym.load; begin tsym.load; typ:=enumsym; definition:=penumdef(readdefref); value:=readlong; {$ifdef GDB} next := Nil; {$endif GDB} end; procedure tenumsym.deref; begin resolvedef(pdef(definition)); {$ifdef GDB} order; {$endif} end; {$ifdef GDB} procedure tenumsym.order; var sym : penumsym; begin sym := definition^.first; if sym = nil then begin definition^.first := @self; next := nil; exit; end; {reorder the symbols in increasing value } if value < sym^.value then begin next := sym; definition^.first := @self; end else begin while (sym^.value <= value) and assigned(sym^.next) do sym := sym^.next; next := sym^.next; sym^.next := @self; end; end; {$endif GDB} procedure tenumsym.write; begin {$ifdef OLDPPU} writebyte(ibenumsym); {$endif} tsym.write; writedefref(definition); writelong(value); {$ifndef OLDPPU} current_ppu^.writeentry(ibenumsym); {$endif} end; {$ifdef GDB} procedure tenumsym.concatstabto(asmlist : paasmoutput); begin {enum elements have no stab !} end; {$EndIf GDB} {**************************************************************************** TTYPESYM ****************************************************************************} constructor ttypesym.init(const n : string;d : pdef); begin tsym.init(n); typ:=typesym; definition:=d; {$ifdef GDB} isusedinstab := false; {$endif GDB} forwardpointer:=nil; { this allows to link definitions with the type with declares } { them } if assigned(definition) then if definition^.sym=nil then definition^.sym:=@self; end; constructor ttypesym.load; begin tsym.load; typ:=typesym; forwardpointer:=nil; {$ifdef GDB} isusedinstab := false; {$endif GDB} definition:=readdefref; end; destructor ttypesym.done; begin if assigned(definition) then if definition^.sym=@self then definition^.sym:=nil; inherited done; end; procedure ttypesym.deref; begin resolvedef(definition); if assigned(definition) then if definition^.sym=nil then definition^.sym:=@self; if definition^.deftype=recorddef then precdef(definition)^.symtable^.name:=stringdup('record '+name); {if definition^.deftype=objectdef then pobjectdef(definition)^.publicsyms^.name:=stringdup('object '+name); done in tobjectdef.load } end; procedure ttypesym.write; begin {$ifdef OLDPPU} writebyte(ibtypesym); {$endif} tsym.write; writedefref(definition); {$ifndef OLDPPU} current_ppu^.writeentry(ibtypesym); {$endif} end; {$ifdef GDB} function ttypesym.stabstring : pchar; var stabchar : string[2]; short : string; begin if definition^.deftype in tagtypes then stabchar := 'Tt' else stabchar := 't'; short := '"'+name+':'+stabchar+definition^.numberstring +'",'+tostr(N_LSYM)+',0,'+tostr(fileinfo.line)+',0'; stabstring := strpnew(short); end; procedure ttypesym.concatstabto(asmlist : paasmoutput); begin {not stabs for forward defs } if assigned(definition) then if (definition^.sym = @self) then definition^.concatstabto(asmlist) else inherited concatstabto(asmlist); end; {$endif GDB} {**************************************************************************** TSYSSYM ****************************************************************************} constructor tsyssym.init(const n : string;l : longint); begin inherited init(n); typ:=syssym; number:=l; end; procedure tsyssym.write; begin end; {$ifdef GDB} procedure tsyssym.concatstabto(asmlist : paasmoutput); begin end; {$endif GDB} {**************************************************************************** TMACROSYM ****************************************************************************} constructor tmacrosym.init(const n : string); begin inherited init(n); defined:=true; buftext:=nil; buflen:=0; end; destructor tmacrosym.done; begin if assigned(buftext) then freemem(buftext,buflen); inherited done; end; { $Log$ Revision 1.27 1998-08-10 14:50:31 peter + localswitches, moduleswitches, globalswitches splitting Revision 1.26 1998/08/10 10:18:35 peter + Compiler,Comphook unit which are the new interface units to the compiler Revision 1.25 1998/07/30 11:18:19 florian + first implementation of try ... except on .. do end; * limitiation of 65535 bytes parameters for cdecl removed Revision 1.24 1998/07/20 18:40:16 florian * handling of ansi string constants should now work Revision 1.23 1998/07/14 21:37:24 peter * fixed packrecords as discussed at the alias Revision 1.22 1998/07/14 14:47:08 peter * released NEWINPUT Revision 1.21 1998/07/13 21:17:38 florian * changed to compile with TP Revision 1.20 1998/07/10 00:00:05 peter * fixed ttypesym bug finally * fileinfo in the symtable and better using for unused vars Revision 1.19 1998/07/07 17:40:39 peter * packrecords 4 works * word aligning of parameters Revision 1.18 1998/07/07 11:20:15 peter + NEWINPUT for a better inputfile and scanner object Revision 1.17 1998/06/24 14:48:40 peter * ifdef newppu -> ifndef oldppu Revision 1.16 1998/06/19 15:40:42 peter * removed cosntructor/constructor warning and 0.99.5 recompiles it again Revision 1.15 1998/06/17 14:10:18 peter * small os2 fixes * fixed interdependent units with newppu (remake3 under linux works now) Revision 1.14 1998/06/16 08:56:34 peter + targetcpu * cleaner pmodules for newppu Revision 1.13 1998/06/15 15:38:10 pierre * small bug in systems.pas corrected + operators in different units better hanlded Revision 1.12 1998/06/15 14:23:44 daniel * Reverted my changes. Revision 1.10 1998/06/13 00:10:18 peter * working browser and newppu * some small fixes against crashes which occured in bp7 (but not in fpc?!) Revision 1.9 1998/06/12 16:15:35 pierre * external name 'C_var'; export name 'intern_C_var'; cdecl; cdecl;external; are now supported only with -Sv switch Revision 1.8 1998/06/11 10:11:59 peter * -gb works again Revision 1.7 1998/06/09 16:01:51 pierre + added procedure directive parsing for procvars (accepted are popstack cdecl and pascal) + added C vars with the following syntax var C calias 'true_c_name';(can be followed by external) reason is that you must add the Cprefix which is target dependent Revision 1.6 1998/06/08 22:59:53 peter * smartlinking works for win32 * some defines to exclude some compiler parts Revision 1.5 1998/06/04 23:52:02 peter * m68k compiles + .def file creation moved to gendef.pas so it could also be used for win32 Revision 1.4 1998/06/04 09:55:46 pierre * demangled name of procsym reworked to become independant of the mangling scheme Revision 1.3 1998/06/03 22:14:20 florian * problem with sizes of classes fixed (if the anchestor was declared forward, the compiler doesn't update the child classes size) Revision 1.2 1998/05/28 14:40:29 peter * fixes for newppu, remake3 works now with it Revision 1.1 1998/05/27 19:45:09 peter * symtable.pas splitted into includefiles * symtable adapted for $ifndef OLDPPU }