mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 15:39:24 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			4805 lines
		
	
	
		
			140 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			4805 lines
		
	
	
		
			140 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
{
 | 
						||
    $Id$
 | 
						||
    Copyright (c) 1998-2000 by Florian Klaempfl, Pierre Muller
 | 
						||
 | 
						||
    Symbol table implementation for the definitions
 | 
						||
 | 
						||
    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.
 | 
						||
 ****************************************************************************
 | 
						||
}
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                     TDEF (base class for definitions)
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
    function tparalinkedlist.count:longint;
 | 
						||
      begin
 | 
						||
        { You must use tabstractprocdef.minparacount and .maxparacount instead }
 | 
						||
        internalerror(432432978);
 | 
						||
        count:=0;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                     TDEF (base class for definitions)
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
 | 
						||
    constructor tdef.init;
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=abstractdef;
 | 
						||
         owner := nil;
 | 
						||
         typesym := nil;
 | 
						||
         savesize := 0;
 | 
						||
         if registerdef then
 | 
						||
           symtablestack^.registerdef(@self);
 | 
						||
         has_rtti:=false;
 | 
						||
         has_inittable:=false;
 | 
						||
{$ifdef GDB}
 | 
						||
         is_def_stab_written := not_written;
 | 
						||
         globalnb := 0;
 | 
						||
{$endif GDB}
 | 
						||
         if assigned(lastglobaldef) then
 | 
						||
           begin
 | 
						||
              lastglobaldef^.nextglobal := @self;
 | 
						||
              previousglobal:=lastglobaldef;
 | 
						||
           end
 | 
						||
         else
 | 
						||
           begin
 | 
						||
              firstglobaldef := @self;
 | 
						||
              previousglobal := nil;
 | 
						||
           end;
 | 
						||
         lastglobaldef := @self;
 | 
						||
         nextglobal := nil;
 | 
						||
      end;
 | 
						||
 | 
						||
{$ifdef MEMDEBUG}
 | 
						||
   var
 | 
						||
       manglenamesize : longint;
 | 
						||
{$endif}
 | 
						||
 | 
						||
    constructor tdef.load;
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=abstractdef;
 | 
						||
         owner := nil;
 | 
						||
         has_rtti:=false;
 | 
						||
         has_inittable:=false;
 | 
						||
{$ifdef GDB}
 | 
						||
         is_def_stab_written := not_written;
 | 
						||
         globalnb := 0;
 | 
						||
{$endif GDB}
 | 
						||
         if assigned(lastglobaldef) then
 | 
						||
           begin
 | 
						||
              lastglobaldef^.nextglobal := @self;
 | 
						||
              previousglobal:=lastglobaldef;
 | 
						||
           end
 | 
						||
         else
 | 
						||
           begin
 | 
						||
              firstglobaldef := @self;
 | 
						||
              previousglobal:=nil;
 | 
						||
           end;
 | 
						||
         lastglobaldef := @self;
 | 
						||
         nextglobal := nil;
 | 
						||
      { load }
 | 
						||
         indexnr:=readword;
 | 
						||
         typesym:=ptypesym(readsymref);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    destructor tdef.done;
 | 
						||
      begin
 | 
						||
         { first element  ? }
 | 
						||
         if not(assigned(previousglobal)) then
 | 
						||
           begin
 | 
						||
              firstglobaldef := nextglobal;
 | 
						||
              if assigned(firstglobaldef) then
 | 
						||
                firstglobaldef^.previousglobal:=nil;
 | 
						||
           end
 | 
						||
         else
 | 
						||
           begin
 | 
						||
              { remove reference in the element before }
 | 
						||
              previousglobal^.nextglobal:=nextglobal;
 | 
						||
           end;
 | 
						||
         { last element ? }
 | 
						||
         if not(assigned(nextglobal)) then
 | 
						||
           begin
 | 
						||
              lastglobaldef := previousglobal;
 | 
						||
              if assigned(lastglobaldef) then
 | 
						||
                lastglobaldef^.nextglobal:=nil;
 | 
						||
           end
 | 
						||
         else
 | 
						||
           nextglobal^.previousglobal:=previousglobal;
 | 
						||
         previousglobal:=nil;
 | 
						||
         nextglobal:=nil;
 | 
						||
{$ifdef SYNONYM}
 | 
						||
         while assigned(typesym) do
 | 
						||
           begin
 | 
						||
              typesym^.restype.setdef(nil);
 | 
						||
              typesym:=typesym^.synonym;
 | 
						||
           end;
 | 
						||
{$endif}
 | 
						||
      end;
 | 
						||
 | 
						||
    { used for enumdef because the symbols are
 | 
						||
      inserted in the owner symtable }
 | 
						||
    procedure tdef.correct_owner_symtable;
 | 
						||
      var
 | 
						||
         st : psymtable;
 | 
						||
      begin
 | 
						||
         if assigned(owner) and
 | 
						||
            (owner^.symtabletype in [recordsymtable,objectsymtable]) then
 | 
						||
           begin
 | 
						||
              owner^.defindex^.deleteindex(@self);
 | 
						||
              st:=owner;
 | 
						||
              while (st^.symtabletype in [recordsymtable,objectsymtable]) do
 | 
						||
                st:=st^.next;
 | 
						||
              st^.registerdef(@self);
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tdef.typename:string;
 | 
						||
      begin
 | 
						||
        if assigned(typesym) and not(deftype=procvardef) and
 | 
						||
          assigned(typesym^._realname) and
 | 
						||
          (typesym^._realname^[1]<>'$') then
 | 
						||
         typename:=typesym^._realname^
 | 
						||
        else
 | 
						||
         typename:=gettypename;
 | 
						||
      end;
 | 
						||
 | 
						||
    function tdef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:='<unknown type>'
 | 
						||
      end;
 | 
						||
 | 
						||
    function tdef.is_in_current : boolean;
 | 
						||
      var
 | 
						||
        p : psymtable;
 | 
						||
      begin
 | 
						||
         p:=owner;
 | 
						||
         is_in_current:=false;
 | 
						||
         while assigned(p) do
 | 
						||
           begin
 | 
						||
              if (p=current_module^.globalsymtable) or (p=current_module^.localsymtable)
 | 
						||
                 or (p^.symtabletype in [globalsymtable,staticsymtable]) then
 | 
						||
                begin
 | 
						||
                   is_in_current:=true;
 | 
						||
                   exit;
 | 
						||
                end
 | 
						||
              else if p^.symtabletype in [localsymtable,parasymtable,objectsymtable] then
 | 
						||
                begin
 | 
						||
                  if assigned(p^.defowner) then
 | 
						||
                    p:=pobjectdef(p^.defowner)^.owner
 | 
						||
                  else
 | 
						||
                    exit;
 | 
						||
                end
 | 
						||
              else
 | 
						||
                exit;
 | 
						||
           end;
 | 
						||
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure tdef.write;
 | 
						||
      begin
 | 
						||
        writeword(indexnr);
 | 
						||
        writesymref(typesym);
 | 
						||
{$ifdef GDB}
 | 
						||
        if globalnb = 0 then
 | 
						||
          begin
 | 
						||
            if assigned(owner) then
 | 
						||
              globalnb := owner^.getnewtypecount
 | 
						||
            else
 | 
						||
              begin
 | 
						||
                globalnb := PGlobalTypeCount^;
 | 
						||
                Inc(PGlobalTypeCount^);
 | 
						||
              end;
 | 
						||
           end;
 | 
						||
{$endif GDB}
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tdef.size : longint;
 | 
						||
      begin
 | 
						||
         size:=savesize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tdef.alignment : longint;
 | 
						||
      begin
 | 
						||
         { normal alignment by default }
 | 
						||
         alignment:=0;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
   procedure tdef.set_globalnb;
 | 
						||
     begin
 | 
						||
         globalnb :=PGlobalTypeCount^;
 | 
						||
         inc(PglobalTypeCount^);
 | 
						||
     end;
 | 
						||
 | 
						||
    function tdef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
      stabstring := strpnew('t'+numberstring+';');
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tdef.numberstring : string;
 | 
						||
      var table : psymtable;
 | 
						||
      begin
 | 
						||
      {formal def have no type !}
 | 
						||
      if deftype = formaldef then
 | 
						||
        begin
 | 
						||
        numberstring := voiddef^.numberstring;
 | 
						||
        exit;
 | 
						||
        end;
 | 
						||
      if (not assigned(typesym)) or (not typesym^.isusedinstab) then
 | 
						||
        begin
 | 
						||
           {set even if debuglist is not defined}
 | 
						||
           if assigned(typesym) then
 | 
						||
             typesym^.isusedinstab := true;
 | 
						||
           if assigned(debuglist) and (is_def_stab_written = not_written) then
 | 
						||
             concatstabto(debuglist);
 | 
						||
        end;
 | 
						||
      if not (cs_gdb_dbx in aktglobalswitches) then
 | 
						||
        begin
 | 
						||
           if globalnb = 0 then
 | 
						||
             set_globalnb;
 | 
						||
           numberstring := tostr(globalnb);
 | 
						||
        end
 | 
						||
      else
 | 
						||
        begin
 | 
						||
           if globalnb = 0 then
 | 
						||
             begin
 | 
						||
                if assigned(owner) then
 | 
						||
                  globalnb := owner^.getnewtypecount
 | 
						||
                else
 | 
						||
                  begin
 | 
						||
                     globalnb := PGlobalTypeCount^;
 | 
						||
                     Inc(PGlobalTypeCount^);
 | 
						||
                  end;
 | 
						||
             end;
 | 
						||
           if assigned(typesym) then
 | 
						||
             begin
 | 
						||
                table := typesym^.owner;
 | 
						||
                if table^.unitid > 0 then
 | 
						||
                  numberstring := '('+tostr(table^.unitid)+','+tostr(typesym^.restype.def^.globalnb)+')'
 | 
						||
                else
 | 
						||
                  numberstring := tostr(globalnb);
 | 
						||
                exit;
 | 
						||
             end;
 | 
						||
           numberstring := tostr(globalnb);
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tdef.allstabstring : pchar;
 | 
						||
    var stabchar : string[2];
 | 
						||
        ss,st : pchar;
 | 
						||
        sname : string;
 | 
						||
        sym_line_no : longint;
 | 
						||
      begin
 | 
						||
      ss := stabstring;
 | 
						||
      getmem(st,strlen(ss)+512);
 | 
						||
      stabchar := 't';
 | 
						||
      if deftype in tagtypes then
 | 
						||
        stabchar := 'Tt';
 | 
						||
      if assigned(typesym) then
 | 
						||
        begin
 | 
						||
           sname := typesym^.name;
 | 
						||
           sym_line_no:=typesym^.fileinfo.line;
 | 
						||
        end
 | 
						||
      else
 | 
						||
        begin
 | 
						||
           sname := ' ';
 | 
						||
           sym_line_no:=0;
 | 
						||
        end;
 | 
						||
      strpcopy(st,'"'+sname+':'+stabchar+numberstring+'=');
 | 
						||
      strpcopy(strecopy(strend(st),ss),'",'+tostr(N_LSYM)+',0,'+tostr(sym_line_no)+',0');
 | 
						||
      allstabstring := strnew(st);
 | 
						||
      freemem(st,strlen(ss)+512);
 | 
						||
      strdispose(ss);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tdef.concatstabto(asmlist : paasmoutput);
 | 
						||
     var stab_str : pchar;
 | 
						||
    begin
 | 
						||
    if ((typesym = nil) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
 | 
						||
      and (is_def_stab_written = not_written) then
 | 
						||
      begin
 | 
						||
      If cs_gdb_dbx in aktglobalswitches then
 | 
						||
        begin
 | 
						||
           { otherwise you get two of each def }
 | 
						||
           If assigned(typesym) then
 | 
						||
             begin
 | 
						||
                if typesym^.typ=symconst.typesym then
 | 
						||
                  typesym^.isusedinstab:=true;
 | 
						||
                if (typesym^.owner = nil) or
 | 
						||
                  ((typesym^.owner^.symtabletype = unitsymtable) and
 | 
						||
                 punitsymtable(typesym^.owner)^.dbx_count_ok)  then
 | 
						||
                begin
 | 
						||
                   {with DBX we get the definition from the other objects }
 | 
						||
                   is_def_stab_written := written;
 | 
						||
                   exit;
 | 
						||
                end;
 | 
						||
             end;
 | 
						||
        end;
 | 
						||
      { to avoid infinite loops }
 | 
						||
      is_def_stab_written := being_written;
 | 
						||
      stab_str := allstabstring;
 | 
						||
      asmlist^.concat(new(pai_stabs,init(stab_str)));
 | 
						||
      is_def_stab_written := written;
 | 
						||
      end;
 | 
						||
    end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    procedure tdef.deref;
 | 
						||
      begin
 | 
						||
        resolvesym(psym(typesym));
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    { rtti generation }
 | 
						||
    procedure tdef.generate_rtti;
 | 
						||
      begin
 | 
						||
         if not has_rtti then
 | 
						||
          begin
 | 
						||
            has_rtti:=true;
 | 
						||
            getdatalabel(rtti_label);
 | 
						||
            write_child_rtti_data;
 | 
						||
            rttilist^.concat(new(pai_symbol,init(rtti_label,0)));
 | 
						||
            write_rtti_data;
 | 
						||
            rttilist^.concat(new(pai_symbol_end,init(rtti_label)));
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tdef.get_rtti_label : string;
 | 
						||
      begin
 | 
						||
         generate_rtti;
 | 
						||
         get_rtti_label:=rtti_label^.name;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    { init table handling }
 | 
						||
    function tdef.needs_inittable : boolean;
 | 
						||
      begin
 | 
						||
         needs_inittable:=false;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tdef.generate_inittable;
 | 
						||
      begin
 | 
						||
         has_inittable:=true;
 | 
						||
         getdatalabel(inittable_label);
 | 
						||
         write_child_init_data;
 | 
						||
         rttilist^.concat(new(pai_label,init(inittable_label)));
 | 
						||
         write_init_data;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tdef.write_init_data;
 | 
						||
      begin
 | 
						||
         write_rtti_data;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tdef.write_child_init_data;
 | 
						||
      begin
 | 
						||
         write_child_rtti_data;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tdef.get_inittable_label : pasmlabel;
 | 
						||
      begin
 | 
						||
         if not(has_inittable) then
 | 
						||
           generate_inittable;
 | 
						||
         get_inittable_label:=inittable_label;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tdef.write_rtti_name;
 | 
						||
      var
 | 
						||
         str : string;
 | 
						||
      begin
 | 
						||
         { name }
 | 
						||
         if assigned(typesym) then
 | 
						||
           begin
 | 
						||
              str:=typesym^.realname;
 | 
						||
              rttilist^.concat(new(pai_string,init(chr(length(str))+str)));
 | 
						||
           end
 | 
						||
         else
 | 
						||
           rttilist^.concat(new(pai_string,init(#0)))
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    { returns true, if the definition can be published }
 | 
						||
    function tdef.is_publishable : boolean;
 | 
						||
      begin
 | 
						||
         is_publishable:=false;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tdef.write_rtti_data;
 | 
						||
      begin
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tdef.write_child_rtti_data;
 | 
						||
      begin
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
   function tdef.is_intregable : boolean;
 | 
						||
 | 
						||
     begin
 | 
						||
        is_intregable:=false;
 | 
						||
        case deftype of
 | 
						||
          pointerdef,
 | 
						||
          enumdef,
 | 
						||
          procvardef :
 | 
						||
            is_intregable:=true;
 | 
						||
          orddef :
 | 
						||
            case porddef(@self)^.typ of
 | 
						||
              bool8bit,bool16bit,bool32bit,
 | 
						||
              u8bit,u16bit,u32bit,
 | 
						||
              s8bit,s16bit,s32bit:
 | 
						||
                is_intregable:=true;
 | 
						||
            end;
 | 
						||
          setdef:
 | 
						||
            is_intregable:=is_smallset(@self);
 | 
						||
        end;
 | 
						||
     end;
 | 
						||
 | 
						||
   function tdef.is_fpuregable : boolean;
 | 
						||
 | 
						||
     begin
 | 
						||
        is_fpuregable:=(deftype=floatdef) and not(pfloatdef(@self)^.typ in [f32bit,f16bit]);
 | 
						||
     end;
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                               TSTRINGDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
    constructor tstringdef.shortinit(l : byte);
 | 
						||
      begin
 | 
						||
         tdef.init;
 | 
						||
         string_typ:=st_shortstring;
 | 
						||
         deftype:=stringdef;
 | 
						||
         len:=l;
 | 
						||
         savesize:=len+1;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tstringdef.shortload;
 | 
						||
      begin
 | 
						||
         tdef.load;
 | 
						||
         string_typ:=st_shortstring;
 | 
						||
         deftype:=stringdef;
 | 
						||
         len:=readbyte;
 | 
						||
         savesize:=len+1;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tstringdef.longinit(l : longint);
 | 
						||
      begin
 | 
						||
         tdef.init;
 | 
						||
         string_typ:=st_longstring;
 | 
						||
         deftype:=stringdef;
 | 
						||
         len:=l;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tstringdef.longload;
 | 
						||
      begin
 | 
						||
         tdef.load;
 | 
						||
         deftype:=stringdef;
 | 
						||
         string_typ:=st_longstring;
 | 
						||
         len:=readlong;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tstringdef.ansiinit(l : longint);
 | 
						||
      begin
 | 
						||
         tdef.init;
 | 
						||
         string_typ:=st_ansistring;
 | 
						||
         deftype:=stringdef;
 | 
						||
         len:=l;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tstringdef.ansiload;
 | 
						||
      begin
 | 
						||
         tdef.load;
 | 
						||
         deftype:=stringdef;
 | 
						||
         string_typ:=st_ansistring;
 | 
						||
         len:=readlong;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tstringdef.wideinit(l : longint);
 | 
						||
      begin
 | 
						||
         tdef.init;
 | 
						||
         string_typ:=st_widestring;
 | 
						||
         deftype:=stringdef;
 | 
						||
         len:=l;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tstringdef.wideload;
 | 
						||
      begin
 | 
						||
         tdef.load;
 | 
						||
         deftype:=stringdef;
 | 
						||
         string_typ:=st_widestring;
 | 
						||
         len:=readlong;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tstringdef.stringtypname:string;
 | 
						||
      const
 | 
						||
        typname:array[tstringtype] of string[8]=('',
 | 
						||
          'SHORTSTR','LONGSTR','ANSISTR','WIDESTR'
 | 
						||
        );
 | 
						||
      begin
 | 
						||
        stringtypname:=typname[string_typ];
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tstringdef.size : longint;
 | 
						||
      begin
 | 
						||
        size:=savesize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tstringdef.write;
 | 
						||
      begin
 | 
						||
         tdef.write;
 | 
						||
         if string_typ=st_shortstring then
 | 
						||
           writebyte(len)
 | 
						||
         else
 | 
						||
           writelong(len);
 | 
						||
         case string_typ of
 | 
						||
           st_shortstring : current_ppu^.writeentry(ibshortstringdef);
 | 
						||
            st_longstring : current_ppu^.writeentry(iblongstringdef);
 | 
						||
            st_ansistring : current_ppu^.writeentry(ibansistringdef);
 | 
						||
            st_widestring : current_ppu^.writeentry(ibwidestringdef);
 | 
						||
         end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tstringdef.stabstring : pchar;
 | 
						||
      var
 | 
						||
        bytest,charst,longst : string;
 | 
						||
      begin
 | 
						||
        case string_typ of
 | 
						||
           st_shortstring:
 | 
						||
             begin
 | 
						||
               charst := typeglobalnumber('char');
 | 
						||
               { this is what I found in stabs.texinfo but
 | 
						||
                 gdb 4.12 for go32 doesn't understand that !! }
 | 
						||
             {$IfDef GDBknowsstrings}
 | 
						||
               stabstring := strpnew('n'+charst+';'+tostr(len));
 | 
						||
             {$else}
 | 
						||
               bytest := typeglobalnumber('byte');
 | 
						||
               stabstring := strpnew('s'+tostr(len+1)+'length:'+bytest
 | 
						||
                  +',0,8;st:ar'+bytest
 | 
						||
                  +';1;'+tostr(len)+';'+charst+',8,'+tostr(len*8)+';;');
 | 
						||
             {$EndIf}
 | 
						||
             end;
 | 
						||
           st_longstring:
 | 
						||
             begin
 | 
						||
               charst := typeglobalnumber('char');
 | 
						||
               { this is what I found in stabs.texinfo but
 | 
						||
                 gdb 4.12 for go32 doesn't understand that !! }
 | 
						||
             {$IfDef GDBknowsstrings}
 | 
						||
               stabstring := strpnew('n'+charst+';'+tostr(len));
 | 
						||
             {$else}
 | 
						||
               bytest := typeglobalnumber('byte');
 | 
						||
               longst := typeglobalnumber('longint');
 | 
						||
               stabstring := strpnew('s'+tostr(len+5)+'length:'+longst
 | 
						||
                  +',0,32;dummy:'+bytest+',32,8;st:ar'+bytest
 | 
						||
                  +';1;'+tostr(len)+';'+charst+',40,'+tostr(len*8)+';;');
 | 
						||
             {$EndIf}
 | 
						||
             end;
 | 
						||
           st_ansistring:
 | 
						||
             begin
 | 
						||
               { an ansi string looks like a pchar easy !! }
 | 
						||
               stabstring:=strpnew('*'+typeglobalnumber('char'));
 | 
						||
             end;
 | 
						||
           st_widestring:
 | 
						||
             begin
 | 
						||
               { an ansi string looks like a pchar easy !! }
 | 
						||
               stabstring:=strpnew('*'+typeglobalnumber('char'));
 | 
						||
             end;
 | 
						||
      end;
 | 
						||
    end;
 | 
						||
 | 
						||
 | 
						||
    procedure tstringdef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
        inherited concatstabto(asmlist);
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    function tstringdef.needs_inittable : boolean;
 | 
						||
      begin
 | 
						||
         needs_inittable:=string_typ in [st_ansistring,st_widestring];
 | 
						||
      end;
 | 
						||
 | 
						||
    function tstringdef.gettypename : string;
 | 
						||
 | 
						||
      const
 | 
						||
         names : array[tstringtype] of string[20] = ('',
 | 
						||
           'ShortString','LongString','AnsiString','WideString');
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:=names[string_typ];
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure tstringdef.write_rtti_data;
 | 
						||
      begin
 | 
						||
         case string_typ of
 | 
						||
            st_ansistring:
 | 
						||
              begin
 | 
						||
                 rttilist^.concat(new(pai_const,init_8bit(tkAString)));
 | 
						||
                 write_rtti_name;
 | 
						||
              end;
 | 
						||
            st_widestring:
 | 
						||
              begin
 | 
						||
                 rttilist^.concat(new(pai_const,init_8bit(tkWString)));
 | 
						||
                 write_rtti_name;
 | 
						||
              end;
 | 
						||
            st_longstring:
 | 
						||
              begin
 | 
						||
                 rttilist^.concat(new(pai_const,init_8bit(tkLString)));
 | 
						||
                 write_rtti_name;
 | 
						||
              end;
 | 
						||
            st_shortstring:
 | 
						||
              begin
 | 
						||
                 rttilist^.concat(new(pai_const,init_8bit(tkSString)));
 | 
						||
                 write_rtti_name;
 | 
						||
                 rttilist^.concat(new(pai_const,init_8bit(len)));
 | 
						||
              end;
 | 
						||
         end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tstringdef.is_publishable : boolean;
 | 
						||
      begin
 | 
						||
         is_publishable:=true;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                                 TENUMDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
    constructor tenumdef.init;
 | 
						||
      begin
 | 
						||
         tdef.init;
 | 
						||
         deftype:=enumdef;
 | 
						||
         minval:=0;
 | 
						||
         maxval:=0;
 | 
						||
         calcsavesize;
 | 
						||
         has_jumps:=false;
 | 
						||
         basedef:=nil;
 | 
						||
         rangenr:=0;
 | 
						||
         firstenum:=nil;
 | 
						||
         correct_owner_symtable;
 | 
						||
      end;
 | 
						||
 | 
						||
    constructor tenumdef.init_subrange(_basedef:penumdef;_min,_max:longint);
 | 
						||
      begin
 | 
						||
         tdef.init;
 | 
						||
         deftype:=enumdef;
 | 
						||
         minval:=_min;
 | 
						||
         maxval:=_max;
 | 
						||
         basedef:=_basedef;
 | 
						||
         calcsavesize;
 | 
						||
         has_jumps:=false;
 | 
						||
         rangenr:=0;
 | 
						||
         firstenum:=basedef^.firstenum;
 | 
						||
         while assigned(firstenum) and (penumsym(firstenum)^.value<>minval) do
 | 
						||
          firstenum:=firstenum^.nextenum;
 | 
						||
         correct_owner_symtable;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tenumdef.load;
 | 
						||
      begin
 | 
						||
         tdef.load;
 | 
						||
         deftype:=enumdef;
 | 
						||
         basedef:=penumdef(readdefref);
 | 
						||
         minval:=readlong;
 | 
						||
         maxval:=readlong;
 | 
						||
         savesize:=readlong;
 | 
						||
         has_jumps:=false;
 | 
						||
         firstenum:=Nil;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tenumdef.calcsavesize;
 | 
						||
      begin
 | 
						||
        if (aktpackenum=4) or (min<0) or (max>65535) then
 | 
						||
         savesize:=4
 | 
						||
        else
 | 
						||
         if (aktpackenum=2) or (min<0) or (max>255) then
 | 
						||
          savesize:=2
 | 
						||
        else
 | 
						||
         savesize:=1;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tenumdef.setmax(_max:longint);
 | 
						||
      begin
 | 
						||
        maxval:=_max;
 | 
						||
        calcsavesize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tenumdef.setmin(_min:longint);
 | 
						||
      begin
 | 
						||
        minval:=_min;
 | 
						||
        calcsavesize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tenumdef.min:longint;
 | 
						||
      begin
 | 
						||
        min:=minval;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tenumdef.max:longint;
 | 
						||
      begin
 | 
						||
        max:=maxval;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tenumdef.deref;
 | 
						||
      begin
 | 
						||
        inherited deref;
 | 
						||
        resolvedef(pdef(basedef));
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    destructor tenumdef.done;
 | 
						||
      begin
 | 
						||
        inherited done;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tenumdef.write;
 | 
						||
      begin
 | 
						||
         tdef.write;
 | 
						||
         writedefref(basedef);
 | 
						||
         writelong(min);
 | 
						||
         writelong(max);
 | 
						||
         writelong(savesize);
 | 
						||
         current_ppu^.writeentry(ibenumdef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tenumdef.getrangecheckstring : string;
 | 
						||
      begin
 | 
						||
         if (cs_create_smart in aktmoduleswitches) then
 | 
						||
           getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
 | 
						||
         else
 | 
						||
           getrangecheckstring:='R_'+tostr(rangenr);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tenumdef.genrangecheck;
 | 
						||
      begin
 | 
						||
         if rangenr=0 then
 | 
						||
           begin
 | 
						||
              { generate two constant for bounds }
 | 
						||
              getlabelnr(rangenr);
 | 
						||
              if (cs_create_smart in aktmoduleswitches) then
 | 
						||
                datasegment^.concat(new(pai_symbol,initname_global(getrangecheckstring,8)))
 | 
						||
              else
 | 
						||
                datasegment^.concat(new(pai_symbol,initname(getrangecheckstring,8)));
 | 
						||
              datasegment^.concat(new(pai_const,init_32bit(min)));
 | 
						||
              datasegment^.concat(new(pai_const,init_32bit(max)));
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tenumdef.stabstring : pchar;
 | 
						||
      var st,st2 : pchar;
 | 
						||
          p : penumsym;
 | 
						||
          s : string;
 | 
						||
          memsize : word;
 | 
						||
      begin
 | 
						||
        memsize := memsizeinc;
 | 
						||
        getmem(st,memsize);
 | 
						||
        strpcopy(st,'e');
 | 
						||
        p := firstenum;
 | 
						||
        while assigned(p) do
 | 
						||
          begin
 | 
						||
            s :=p^.name+':'+tostr(p^.value)+',';
 | 
						||
            { place for the ending ';' also }
 | 
						||
            if (strlen(st)+length(s)+1<memsize) then
 | 
						||
              strpcopy(strend(st),s)
 | 
						||
            else
 | 
						||
              begin
 | 
						||
                getmem(st2,memsize+memsizeinc);
 | 
						||
                strcopy(st2,st);
 | 
						||
                freemem(st,memsize);
 | 
						||
                st := st2;
 | 
						||
                memsize := memsize+memsizeinc;
 | 
						||
                strpcopy(strend(st),s);
 | 
						||
              end;
 | 
						||
            p := p^.nextenum;
 | 
						||
          end;
 | 
						||
        strpcopy(strend(st),';');
 | 
						||
        stabstring := strnew(st);
 | 
						||
        freemem(st,memsize);
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    procedure tenumdef.write_child_rtti_data;
 | 
						||
      begin
 | 
						||
         if assigned(basedef) then
 | 
						||
           basedef^.get_rtti_label;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tenumdef.write_rtti_data;
 | 
						||
 | 
						||
      var
 | 
						||
         hp : penumsym;
 | 
						||
 | 
						||
      begin
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(tkEnumeration)));
 | 
						||
         write_rtti_name;
 | 
						||
         case savesize of
 | 
						||
            1:
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(otUByte)));
 | 
						||
            2:
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(otUWord)));
 | 
						||
            4:
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(otULong)));
 | 
						||
         end;
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(min)));
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(max)));
 | 
						||
         if assigned(basedef) then
 | 
						||
           rttilist^.concat(new(pai_const_symbol,initname(basedef^.get_rtti_label)))
 | 
						||
         else
 | 
						||
           rttilist^.concat(new(pai_const,init_32bit(0)));
 | 
						||
         hp:=firstenum;
 | 
						||
         while assigned(hp) do
 | 
						||
           begin
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(length(hp^.name))));
 | 
						||
              rttilist^.concat(new(pai_string,init(lower(hp^.name))));
 | 
						||
              hp:=hp^.nextenum;
 | 
						||
           end;
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(0)));
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tenumdef.is_publishable : boolean;
 | 
						||
      begin
 | 
						||
         is_publishable:=true;
 | 
						||
      end;
 | 
						||
 | 
						||
    function tenumdef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:='<enumeration type>';
 | 
						||
      end;
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                                 TORDDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
    constructor torddef.init(t : tbasetype;v,b : longint);
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=orddef;
 | 
						||
         low:=v;
 | 
						||
         high:=b;
 | 
						||
         typ:=t;
 | 
						||
         rangenr:=0;
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor torddef.load;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=orddef;
 | 
						||
         typ:=tbasetype(readbyte);
 | 
						||
         low:=readlong;
 | 
						||
         high:=readlong;
 | 
						||
         rangenr:=0;
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure torddef.setsize;
 | 
						||
      begin
 | 
						||
         if typ=uauto then
 | 
						||
           begin
 | 
						||
              { generate a unsigned range if high<0 and low>=0 }
 | 
						||
              if (low>=0) and (high<0) then
 | 
						||
                begin
 | 
						||
                   savesize:=4;
 | 
						||
                   typ:=u32bit;
 | 
						||
                end
 | 
						||
              else if (low>=0) and (high<=255) then
 | 
						||
                begin
 | 
						||
                   savesize:=1;
 | 
						||
                   typ:=u8bit;
 | 
						||
                end
 | 
						||
              else if (low>=-128) and (high<=127) then
 | 
						||
                begin
 | 
						||
                   savesize:=1;
 | 
						||
                   typ:=s8bit;
 | 
						||
                end
 | 
						||
              else if (low>=0) and (high<=65536) then
 | 
						||
                begin
 | 
						||
                   savesize:=2;
 | 
						||
                   typ:=u16bit;
 | 
						||
                end
 | 
						||
              else if (low>=-32768) and (high<=32767) then
 | 
						||
                begin
 | 
						||
                   savesize:=2;
 | 
						||
                   typ:=s16bit;
 | 
						||
                end
 | 
						||
              else
 | 
						||
                begin
 | 
						||
                   savesize:=4;
 | 
						||
                   typ:=s32bit;
 | 
						||
                end;
 | 
						||
           end
 | 
						||
         else
 | 
						||
           begin
 | 
						||
             case typ of
 | 
						||
                u8bit,s8bit,
 | 
						||
                uchar,bool8bit:
 | 
						||
                  savesize:=1;
 | 
						||
 | 
						||
                u16bit,s16bit,
 | 
						||
                bool16bit,uwidechar:
 | 
						||
                  savesize:=2;
 | 
						||
 | 
						||
                s32bit,u32bit,
 | 
						||
                bool32bit:
 | 
						||
                  savesize:=4;
 | 
						||
 | 
						||
                u64bit,s64bit:
 | 
						||
                  savesize:=8;
 | 
						||
             else
 | 
						||
               savesize:=0;
 | 
						||
             end;
 | 
						||
           end;
 | 
						||
       { there are no entrys for range checking }
 | 
						||
         rangenr:=0;
 | 
						||
      end;
 | 
						||
 | 
						||
    function torddef.getrangecheckstring : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         if (cs_create_smart in aktmoduleswitches) then
 | 
						||
           getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
 | 
						||
         else
 | 
						||
           getrangecheckstring:='R_'+tostr(rangenr);
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure torddef.genrangecheck;
 | 
						||
      var
 | 
						||
        rangechecksize : longint;
 | 
						||
      begin
 | 
						||
         if rangenr=0 then
 | 
						||
           begin
 | 
						||
              if low<=high then
 | 
						||
               rangechecksize:=8
 | 
						||
              else
 | 
						||
               rangechecksize:=16;
 | 
						||
              { generate two constant for bounds }
 | 
						||
              getlabelnr(rangenr);
 | 
						||
              if (cs_create_smart in aktmoduleswitches) then
 | 
						||
                datasegment^.concat(new(pai_symbol,initname_global(getrangecheckstring,rangechecksize)))
 | 
						||
              else
 | 
						||
                datasegment^.concat(new(pai_symbol,initname(getrangecheckstring,rangechecksize)));
 | 
						||
              if low<=high then
 | 
						||
                begin
 | 
						||
                   datasegment^.concat(new(pai_const,init_32bit(low)));
 | 
						||
                   datasegment^.concat(new(pai_const,init_32bit(high)));
 | 
						||
                end
 | 
						||
              { for u32bit we need two bounds }
 | 
						||
              else
 | 
						||
                begin
 | 
						||
                   datasegment^.concat(new(pai_const,init_32bit(low)));
 | 
						||
                   datasegment^.concat(new(pai_const,init_32bit($7fffffff)));
 | 
						||
                   datasegment^.concat(new(pai_const,init_32bit($80000000)));
 | 
						||
                   datasegment^.concat(new(pai_const,init_32bit(high)));
 | 
						||
                end;
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure torddef.write;
 | 
						||
      begin
 | 
						||
         tdef.write;
 | 
						||
         writebyte(byte(typ));
 | 
						||
         writelong(low);
 | 
						||
         writelong(high);
 | 
						||
         current_ppu^.writeentry(iborddef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function torddef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
        case typ of
 | 
						||
            uvoid : stabstring := strpnew(numberstring+';');
 | 
						||
         {GDB 4.12 for go32 doesn't like boolean as range for 0 to 1 !!!}
 | 
						||
{$ifdef Use_integer_types_for_boolean}
 | 
						||
         bool8bit,
 | 
						||
        bool16bit,
 | 
						||
        bool32bit : stabstring := strpnew('r'+numberstring+';0;255;');
 | 
						||
{$else : not Use_integer_types_for_boolean}
 | 
						||
         bool8bit : stabstring := strpnew('-21;');
 | 
						||
        bool16bit : stabstring := strpnew('-22;');
 | 
						||
        bool32bit : stabstring := strpnew('-23;');
 | 
						||
        u64bit    : stabstring := strpnew('-32;');
 | 
						||
        s64bit    : stabstring := strpnew('-31;');
 | 
						||
{$endif not Use_integer_types_for_boolean}
 | 
						||
         { u32bit : stabstring := strpnew('r'+
 | 
						||
              s32bitdef^.numberstring+';0;-1;'); }
 | 
						||
        else
 | 
						||
          stabstring := strpnew('r'+s32bitdef^.numberstring+';'+tostr(low)+';'+tostr(high)+';');
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    procedure torddef.write_rtti_data;
 | 
						||
 | 
						||
        procedure dointeger;
 | 
						||
        const
 | 
						||
          trans : array[uchar..bool8bit] of byte =
 | 
						||
            (otUByte,otUByte,otUWord,otULong,otSByte,otSWord,otSLong,otUByte);
 | 
						||
        begin
 | 
						||
          write_rtti_name;
 | 
						||
          rttilist^.concat(new(pai_const,init_8bit(byte(trans[typ]))));
 | 
						||
          rttilist^.concat(new(pai_const,init_32bit(low)));
 | 
						||
          rttilist^.concat(new(pai_const,init_32bit(high)));
 | 
						||
        end;
 | 
						||
 | 
						||
      begin
 | 
						||
        case typ of
 | 
						||
          s64bit :
 | 
						||
            begin
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkInt64)));
 | 
						||
              write_rtti_name;
 | 
						||
              { low }
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit($0)));
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit($8000)));
 | 
						||
              { high }
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit($ffff)));
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit($7fff)));
 | 
						||
            end;
 | 
						||
          u64bit :
 | 
						||
            begin
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkQWord)));
 | 
						||
              write_rtti_name;
 | 
						||
              { low }
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit($0)));
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit($0)));
 | 
						||
              { high }
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit($0)));
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit($8000)));
 | 
						||
            end;
 | 
						||
          bool8bit:
 | 
						||
            begin
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkBool)));
 | 
						||
              dointeger;
 | 
						||
            end;
 | 
						||
          uchar:
 | 
						||
            begin
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkWChar)));
 | 
						||
              dointeger;
 | 
						||
            end;
 | 
						||
          uwidechar:
 | 
						||
            begin
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkChar)));
 | 
						||
              dointeger;
 | 
						||
            end;
 | 
						||
          else
 | 
						||
            begin
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkInteger)));
 | 
						||
              dointeger;
 | 
						||
            end;
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function torddef.is_publishable : boolean;
 | 
						||
      begin
 | 
						||
         is_publishable:=typ in [uchar..bool8bit];
 | 
						||
      end;
 | 
						||
 | 
						||
    function torddef.gettypename : string;
 | 
						||
 | 
						||
      const
 | 
						||
        names : array[tbasetype] of string[20] = ('<unknown type>',
 | 
						||
          'untyped','Char','Byte','Word','DWord','ShortInt',
 | 
						||
          'SmallInt','LongInt','Boolean','WordBool',
 | 
						||
          'LongBool','QWord','Int64','WideChar');
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:=names[typ];
 | 
						||
      end;
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                                TFLOATDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
    constructor tfloatdef.init(t : tfloattype);
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=floatdef;
 | 
						||
         typ:=t;
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tfloatdef.load;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=floatdef;
 | 
						||
         typ:=tfloattype(readbyte);
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tfloatdef.setsize;
 | 
						||
      begin
 | 
						||
         case typ of
 | 
						||
            f16bit : savesize:=2;
 | 
						||
            f32bit,
 | 
						||
           s32real : savesize:=4;
 | 
						||
           s64real : savesize:=8;
 | 
						||
           s80real : savesize:=extended_size;
 | 
						||
           s64comp : savesize:=8;
 | 
						||
         else
 | 
						||
           savesize:=0;
 | 
						||
         end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tfloatdef.write;
 | 
						||
      begin
 | 
						||
         inherited write;
 | 
						||
         writebyte(byte(typ));
 | 
						||
         current_ppu^.writeentry(ibfloatdef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tfloatdef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
         case typ of
 | 
						||
            s32real,
 | 
						||
            s64real : stabstring := strpnew('r'+
 | 
						||
               s32bitdef^.numberstring+';'+tostr(savesize)+';0;');
 | 
						||
            { for fixed real use longint instead to be able to }
 | 
						||
            { debug something at least                         }
 | 
						||
            f32bit:
 | 
						||
              stabstring := s32bitdef^.stabstring;
 | 
						||
            f16bit:
 | 
						||
              stabstring := strpnew('r'+s32bitdef^.numberstring+';0;'+
 | 
						||
                tostr($ffff)+';');
 | 
						||
            { found this solution in stabsread.c from GDB v4.16 }
 | 
						||
            s64comp : stabstring := strpnew('r'+
 | 
						||
               s32bitdef^.numberstring+';-'+tostr(savesize)+';0;');
 | 
						||
{$ifdef i386}
 | 
						||
            { under dos at least you must give a size of twelve instead of 10 !! }
 | 
						||
            { this is probably do to the fact that in gcc all is pushed in 4 bytes size }
 | 
						||
            s80real : stabstring := strpnew('r'+s32bitdef^.numberstring+';12;0;');
 | 
						||
{$endif i386}
 | 
						||
            else
 | 
						||
              internalerror(10005);
 | 
						||
         end;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    procedure tfloatdef.write_rtti_data;
 | 
						||
      const
 | 
						||
         {tfloattype = (s32real,s64real,s80real,s64bit,f16bit,f32bit);}
 | 
						||
         translate : array[tfloattype] of byte =
 | 
						||
           (ftSingle,ftDouble,ftExtended,ftComp,ftFixed16,ftFixed32);
 | 
						||
      begin
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(tkFloat)));
 | 
						||
         write_rtti_name;
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(translate[typ])));
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tfloatdef.is_publishable : boolean;
 | 
						||
      begin
 | 
						||
         is_publishable:=true;
 | 
						||
      end;
 | 
						||
 | 
						||
    function tfloatdef.gettypename : string;
 | 
						||
 | 
						||
      const
 | 
						||
        names : array[tfloattype] of string[20] = (
 | 
						||
          'Single','Double','Extended','Comp','Fixed','Fixed16');
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:=names[typ];
 | 
						||
      end;
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                                TFILEDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
    constructor tfiledef.inittext;
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=filedef;
 | 
						||
         filetyp:=ft_text;
 | 
						||
         typedfiletype.reset;
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tfiledef.inituntyped;
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=filedef;
 | 
						||
         filetyp:=ft_untyped;
 | 
						||
         typedfiletype.reset;
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tfiledef.inittyped(const tt : ttype);
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=filedef;
 | 
						||
         filetyp:=ft_typed;
 | 
						||
         typedfiletype:=tt;
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tfiledef.inittypeddef(p : pdef);
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=filedef;
 | 
						||
         filetyp:=ft_typed;
 | 
						||
         typedfiletype.setdef(p);
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tfiledef.load;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=filedef;
 | 
						||
         filetyp:=tfiletyp(readbyte);
 | 
						||
         if filetyp=ft_typed then
 | 
						||
           typedfiletype.load
 | 
						||
         else
 | 
						||
           typedfiletype.reset;
 | 
						||
         setsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tfiledef.deref;
 | 
						||
      begin
 | 
						||
        inherited deref;
 | 
						||
        if filetyp=ft_typed then
 | 
						||
          typedfiletype.resolve;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tfiledef.setsize;
 | 
						||
      begin
 | 
						||
        case filetyp of
 | 
						||
          ft_text :
 | 
						||
            savesize:=572;
 | 
						||
          ft_typed,
 | 
						||
          ft_untyped :
 | 
						||
            savesize:=316;
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tfiledef.write;
 | 
						||
      begin
 | 
						||
         inherited write;
 | 
						||
         writebyte(byte(filetyp));
 | 
						||
         if filetyp=ft_typed then
 | 
						||
           typedfiletype.write;
 | 
						||
         current_ppu^.writeentry(ibfiledef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tfiledef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
   {$IfDef GDBknowsfiles}
 | 
						||
      case filetyp of
 | 
						||
        ft_typed :
 | 
						||
          stabstring := strpnew('d'+typedfiletype.def^.numberstring{+';'});
 | 
						||
        ft_untyped :
 | 
						||
          stabstring := strpnew('d'+voiddef^.numberstring{+';'});
 | 
						||
        ft_text :
 | 
						||
          stabstring := strpnew('d'+cchardef^.numberstring{+';'});
 | 
						||
      end;
 | 
						||
   {$Else}
 | 
						||
      {based on
 | 
						||
        FileRec = Packed Record
 | 
						||
          Handle,
 | 
						||
          Mode,
 | 
						||
          RecSize   : longint;
 | 
						||
          _private  : array[1..32] of byte;
 | 
						||
          UserData  : array[1..16] of byte;
 | 
						||
          name      : array[0..255] of char;
 | 
						||
        End; }
 | 
						||
      { the buffer part is still missing !! (PM) }
 | 
						||
      { but the string could become too long !! }
 | 
						||
      stabstring := strpnew('s'+tostr(savesize)+
 | 
						||
                     'HANDLE:'+typeglobalnumber('longint')+',0,32;'+
 | 
						||
                     'MODE:'+typeglobalnumber('longint')+',32,32;'+
 | 
						||
                     'RECSIZE:'+typeglobalnumber('longint')+',64,32;'+
 | 
						||
                     '_PRIVATE:ar'+typeglobalnumber('word')+';1;32;'+typeglobalnumber('byte')
 | 
						||
                        +',96,256;'+
 | 
						||
                     'USERDATA:ar'+typeglobalnumber('word')+';1;16;'+typeglobalnumber('byte')
 | 
						||
                        +',352,128;'+
 | 
						||
                     'NAME:ar'+typeglobalnumber('word')+';0;255;'+typeglobalnumber('char')
 | 
						||
                        +',480,2048;;');
 | 
						||
   {$EndIf}
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tfiledef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
      { most file defs are unnamed !!! }
 | 
						||
      if ((typesym = nil) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
 | 
						||
         (is_def_stab_written  = not_written) then
 | 
						||
        begin
 | 
						||
        if assigned(typedfiletype.def) then forcestabto(asmlist,typedfiletype.def);
 | 
						||
        inherited concatstabto(asmlist);
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
    function tfiledef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         case filetyp of
 | 
						||
           ft_untyped:
 | 
						||
             gettypename:='File';
 | 
						||
           ft_typed:
 | 
						||
             gettypename:='File Of '+typedfiletype.def^.typename;
 | 
						||
           ft_text:
 | 
						||
             gettypename:='Text'
 | 
						||
         end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                               TPOINTERDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
    constructor tpointerdef.init(const tt : ttype);
 | 
						||
      begin
 | 
						||
        tdef.init;
 | 
						||
        deftype:=pointerdef;
 | 
						||
        pointertype:=tt;
 | 
						||
        is_far:=false;
 | 
						||
        savesize:=target_os.size_of_pointer;
 | 
						||
        pointertypeis_forwarddef:=assigned(pointertype.def) and (pointertype.def^.deftype=forwarddef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tpointerdef.initfar(const tt : ttype);
 | 
						||
      begin
 | 
						||
        tdef.init;
 | 
						||
        deftype:=pointerdef;
 | 
						||
        pointertype:=tt;
 | 
						||
        is_far:=true;
 | 
						||
        savesize:=target_os.size_of_pointer;
 | 
						||
        pointertypeis_forwarddef:=assigned(pointertype.def) and (pointertype.def^.deftype=forwarddef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tpointerdef.initdef(p : pdef);
 | 
						||
      var
 | 
						||
        t : ttype;
 | 
						||
      begin
 | 
						||
        t.setdef(p);
 | 
						||
        tpointerdef.init(t);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tpointerdef.initfardef(p : pdef);
 | 
						||
      var
 | 
						||
        t : ttype;
 | 
						||
      begin
 | 
						||
        t.setdef(p);
 | 
						||
        tpointerdef.initfar(t);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
 | 
						||
    constructor tpointerdef.load;
 | 
						||
      begin
 | 
						||
         tdef.load;
 | 
						||
         deftype:=pointerdef;
 | 
						||
         pointertype.load;
 | 
						||
         is_far:=(readbyte<>0);
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    destructor tpointerdef.done;
 | 
						||
      begin
 | 
						||
        if {assigned(pointertype.def) and
 | 
						||
           (pointertype.def^.deftype=forwarddef)} pointertypeis_forwarddef then
 | 
						||
         begin
 | 
						||
           dispose(pointertype.def,done);
 | 
						||
           pointertype.reset;
 | 
						||
         end;
 | 
						||
        inherited done;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tpointerdef.deref;
 | 
						||
      begin
 | 
						||
        inherited deref;
 | 
						||
        pointertype.resolve;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tpointerdef.write;
 | 
						||
      begin
 | 
						||
         inherited write;
 | 
						||
         pointertype.write;
 | 
						||
         writebyte(byte(is_far));
 | 
						||
         current_ppu^.writeentry(ibpointerdef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tpointerdef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
        stabstring := strpnew('*'+pointertype.def^.numberstring);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tpointerdef.concatstabto(asmlist : paasmoutput);
 | 
						||
      var st,nb : string;
 | 
						||
          sym_line_no : longint;
 | 
						||
      begin
 | 
						||
      if assigned(pointertype.def) and
 | 
						||
         (pointertype.def^.deftype=forwarddef) then
 | 
						||
        exit;
 | 
						||
 | 
						||
      if ( (typesym=nil) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
 | 
						||
         (is_def_stab_written = not_written) then
 | 
						||
        begin
 | 
						||
          is_def_stab_written := being_written;
 | 
						||
        if assigned(pointertype.def) and
 | 
						||
           (pointertype.def^.deftype in [recorddef,objectdef]) then
 | 
						||
          begin
 | 
						||
            nb:=pointertype.def^.numberstring;
 | 
						||
            {to avoid infinite recursion in record with next-like fields }
 | 
						||
            if pointertype.def^.is_def_stab_written = being_written then
 | 
						||
              begin
 | 
						||
                if assigned(pointertype.def^.typesym) then
 | 
						||
                  begin
 | 
						||
                    if assigned(typesym) then
 | 
						||
                      begin
 | 
						||
                         st := typesym^.name;
 | 
						||
                         sym_line_no:=typesym^.fileinfo.line;
 | 
						||
                      end
 | 
						||
                    else
 | 
						||
                      begin
 | 
						||
                         st := ' ';
 | 
						||
                         sym_line_no:=0;
 | 
						||
                      end;
 | 
						||
                    st := '"'+st+':t'+numberstring+'=*'+nb
 | 
						||
                          +'=xs'+pointertype.def^.typesym^.name+':",'+tostr(N_LSYM)+',0,'+tostr(sym_line_no)+',0';
 | 
						||
                    asmlist^.concat(new(pai_stabs,init(strpnew(st))));
 | 
						||
                    end;
 | 
						||
              end
 | 
						||
            else
 | 
						||
              begin
 | 
						||
                is_def_stab_written := not_written;
 | 
						||
                inherited concatstabto(asmlist);
 | 
						||
              end;
 | 
						||
            is_def_stab_written := written;
 | 
						||
          end
 | 
						||
        else
 | 
						||
          begin
 | 
						||
            if assigned(pointertype.def) then
 | 
						||
              forcestabto(asmlist,pointertype.def);
 | 
						||
            is_def_stab_written := not_written;
 | 
						||
            inherited concatstabto(asmlist);
 | 
						||
          end;
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
    function tpointerdef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:='^'+pointertype.def^.typename;
 | 
						||
      end;
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                              TCLASSREFDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
    constructor tclassrefdef.init(def : pdef);
 | 
						||
      begin
 | 
						||
         inherited initdef(def);
 | 
						||
         deftype:=classrefdef;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tclassrefdef.load;
 | 
						||
      begin
 | 
						||
         { be careful, tclassdefref inherits from tpointerdef }
 | 
						||
         tdef.load;
 | 
						||
         deftype:=classrefdef;
 | 
						||
         pointertype.load;
 | 
						||
         is_far:=false;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tclassrefdef.write;
 | 
						||
      begin
 | 
						||
         { be careful, tclassdefref inherits from tpointerdef }
 | 
						||
         tdef.write;
 | 
						||
         pointertype.write;
 | 
						||
         current_ppu^.writeentry(ibclassrefdef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tclassrefdef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
         stabstring:=strpnew(pvmtdef^.numberstring+';');
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tclassrefdef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
        inherited concatstabto(asmlist);
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
    function tclassrefdef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:='Class Of '+pointertype.def^.typename;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{***************************************************************************
 | 
						||
                                   TSETDEF
 | 
						||
***************************************************************************}
 | 
						||
 | 
						||
{ For i386 smallsets work,
 | 
						||
  for m68k there are problems
 | 
						||
  can be test by compiling with -dusesmallset PM }
 | 
						||
{$ifdef i386}
 | 
						||
{$define usesmallset}
 | 
						||
{$endif i386}
 | 
						||
 | 
						||
    constructor tsetdef.init(s : pdef;high : longint);
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=setdef;
 | 
						||
         elementtype.setdef(s);
 | 
						||
{$ifdef usesmallset}
 | 
						||
         { small sets only working for i386 PM }
 | 
						||
         if high<32 then
 | 
						||
           begin
 | 
						||
            settype:=smallset;
 | 
						||
           {$ifdef testvarsets}
 | 
						||
            if aktsetalloc=0 THEN      { $PACKSET Fixed?}
 | 
						||
           {$endif}
 | 
						||
            savesize:=Sizeof(longint)
 | 
						||
           {$ifdef testvarsets}
 | 
						||
           else                       {No, use $PACKSET VALUE for rounding}
 | 
						||
            savesize:=aktsetalloc*((high+aktsetalloc*8-1) DIV (aktsetalloc*8))
 | 
						||
           {$endif}
 | 
						||
              ;
 | 
						||
          end
 | 
						||
         else
 | 
						||
{$endif usesmallset}
 | 
						||
         if high<256 then
 | 
						||
           begin
 | 
						||
              settype:=normset;
 | 
						||
              savesize:=32;
 | 
						||
           end
 | 
						||
         else
 | 
						||
{$ifdef testvarsets}
 | 
						||
         if high<$10000 then
 | 
						||
           begin
 | 
						||
              settype:=varset;
 | 
						||
              savesize:=4*((high+31) div 32);
 | 
						||
           end
 | 
						||
         else
 | 
						||
{$endif testvarsets}
 | 
						||
          Message(sym_e_ill_type_decl_set);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tsetdef.load;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=setdef;
 | 
						||
         elementtype.load;
 | 
						||
         settype:=tsettype(readbyte);
 | 
						||
         case settype of
 | 
						||
            normset : savesize:=32;
 | 
						||
            varset : savesize:=readlong;
 | 
						||
            smallset : savesize:=Sizeof(longint);
 | 
						||
         end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    destructor tsetdef.done;
 | 
						||
      begin
 | 
						||
        inherited done;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tsetdef.write;
 | 
						||
      begin
 | 
						||
         inherited write;
 | 
						||
         elementtype.write;
 | 
						||
         writebyte(byte(settype));
 | 
						||
         if settype=varset then
 | 
						||
           writelong(savesize);
 | 
						||
         current_ppu^.writeentry(ibsetdef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tsetdef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
         { For small sets write a longint, which can at least be seen
 | 
						||
           in the current GDB's (PFV)
 | 
						||
           this is obsolete with GDBPAS !!
 | 
						||
           and anyhow creates problems with version 4.18!! PM
 | 
						||
         if settype=smallset then
 | 
						||
           stabstring := strpnew('r'+s32bitdef^.numberstring+';0;0xffffffff;')
 | 
						||
         else }
 | 
						||
           stabstring := strpnew('S'+elementtype.def^.numberstring);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tsetdef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
      if ( not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
 | 
						||
          (is_def_stab_written = not_written) then
 | 
						||
        begin
 | 
						||
          if assigned(elementtype.def) then
 | 
						||
            forcestabto(asmlist,elementtype.def);
 | 
						||
          inherited concatstabto(asmlist);
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    procedure tsetdef.deref;
 | 
						||
      begin
 | 
						||
        inherited deref;
 | 
						||
        elementtype.resolve;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tsetdef.write_rtti_data;
 | 
						||
      begin
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(tkSet)));
 | 
						||
         write_rtti_name;
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(otULong)));
 | 
						||
         rttilist^.concat(new(pai_const_symbol,initname(elementtype.def^.get_rtti_label)));
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tsetdef.write_child_rtti_data;
 | 
						||
      begin
 | 
						||
         elementtype.def^.get_rtti_label;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tsetdef.is_publishable : boolean;
 | 
						||
      begin
 | 
						||
         is_publishable:=settype=smallset;
 | 
						||
      end;
 | 
						||
 | 
						||
    function tsetdef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         if assigned(elementtype.def) then
 | 
						||
          gettypename:='Set Of '+elementtype.def^.typename
 | 
						||
         else
 | 
						||
          gettypename:='Empty Set';
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{***************************************************************************
 | 
						||
                                 TFORMALDEF
 | 
						||
***************************************************************************}
 | 
						||
 | 
						||
    constructor tformaldef.init;
 | 
						||
      var
 | 
						||
         stregdef : boolean;
 | 
						||
      begin
 | 
						||
         stregdef:=registerdef;
 | 
						||
         registerdef:=false;
 | 
						||
         inherited init;
 | 
						||
         deftype:=formaldef;
 | 
						||
         registerdef:=stregdef;
 | 
						||
         { formaldef must be registered at unit level !! }
 | 
						||
         if registerdef and assigned(current_module) then
 | 
						||
            if assigned(current_module^.localsymtable) then
 | 
						||
              psymtable(current_module^.localsymtable)^.registerdef(@self)
 | 
						||
            else if assigned(current_module^.globalsymtable) then
 | 
						||
              psymtable(current_module^.globalsymtable)^.registerdef(@self);
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tformaldef.load;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=formaldef;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tformaldef.write;
 | 
						||
      begin
 | 
						||
         inherited write;
 | 
						||
         current_ppu^.writeentry(ibformaldef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tformaldef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
      stabstring := strpnew('formal'+numberstring+';');
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tformaldef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
      { formaldef can't be stab'ed !}
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
    function tformaldef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:='Var';
 | 
						||
      end;
 | 
						||
 | 
						||
{***************************************************************************
 | 
						||
                           TARRAYDEF
 | 
						||
***************************************************************************}
 | 
						||
 | 
						||
    constructor tarraydef.init(l,h : longint;rd : pdef);
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=arraydef;
 | 
						||
         lowrange:=l;
 | 
						||
         highrange:=h;
 | 
						||
         rangetype.setdef(rd);
 | 
						||
         elementtype.reset;
 | 
						||
         IsVariant:=false;
 | 
						||
         IsConstructor:=false;
 | 
						||
         IsArrayOfConst:=false;
 | 
						||
         IsDynamicArray:=false;
 | 
						||
         rangenr:=0;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tarraydef.load;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=arraydef;
 | 
						||
         { the addresses are calculated later }
 | 
						||
         elementtype.load;
 | 
						||
         rangetype.load;
 | 
						||
         lowrange:=readlong;
 | 
						||
         highrange:=readlong;
 | 
						||
         IsArrayOfConst:=boolean(readbyte);
 | 
						||
         IsVariant:=false;
 | 
						||
         IsConstructor:=false;
 | 
						||
{$warning FIXME!!!!!}
 | 
						||
         IsDynamicArray:=false;
 | 
						||
         rangenr:=0;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tarraydef.getrangecheckstring : string;
 | 
						||
      begin
 | 
						||
         if (cs_create_smart in aktmoduleswitches) then
 | 
						||
           getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
 | 
						||
         else
 | 
						||
           getrangecheckstring:='R_'+tostr(rangenr);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tarraydef.genrangecheck;
 | 
						||
      begin
 | 
						||
         if rangenr=0 then
 | 
						||
           begin
 | 
						||
              { generates the data for range checking }
 | 
						||
              getlabelnr(rangenr);
 | 
						||
              if (cs_create_smart in aktmoduleswitches) then
 | 
						||
                datasegment^.concat(new(pai_symbol,initname_global(getrangecheckstring,8)))
 | 
						||
              else
 | 
						||
                datasegment^.concat(new(pai_symbol,initname(getrangecheckstring,8)));
 | 
						||
              if lowrange<=highrange then
 | 
						||
                begin
 | 
						||
                  datasegment^.concat(new(pai_const,init_32bit(lowrange)));
 | 
						||
                  datasegment^.concat(new(pai_const,init_32bit(highrange)));
 | 
						||
                end
 | 
						||
              { for big arrays we need two bounds }
 | 
						||
              else
 | 
						||
                begin
 | 
						||
                  datasegment^.concat(new(pai_const,init_32bit(lowrange)));
 | 
						||
                  datasegment^.concat(new(pai_const,init_32bit($7fffffff)));
 | 
						||
                  datasegment^.concat(new(pai_const,init_32bit($80000000)));
 | 
						||
                  datasegment^.concat(new(pai_const,init_32bit(highrange)));
 | 
						||
                end;
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tarraydef.deref;
 | 
						||
      begin
 | 
						||
        inherited deref;
 | 
						||
        elementtype.resolve;
 | 
						||
        rangetype.resolve;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tarraydef.write;
 | 
						||
      begin
 | 
						||
         inherited write;
 | 
						||
         elementtype.write;
 | 
						||
         rangetype.write;
 | 
						||
         writelong(lowrange);
 | 
						||
         writelong(highrange);
 | 
						||
         writebyte(byte(IsArrayOfConst));
 | 
						||
         current_ppu^.writeentry(ibarraydef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tarraydef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
      stabstring := strpnew('ar'+rangetype.def^.numberstring+';'
 | 
						||
                    +tostr(lowrange)+';'+tostr(highrange)+';'+elementtype.def^.numberstring);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tarraydef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
      if (not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
 | 
						||
        and (is_def_stab_written = not_written) then
 | 
						||
        begin
 | 
						||
        {when array are inserted they have no definition yet !!}
 | 
						||
        if assigned(elementtype.def) then
 | 
						||
          inherited concatstabto(asmlist);
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    function tarraydef.elesize : longint;
 | 
						||
      begin
 | 
						||
        if isconstructor or is_open_array(@self) then
 | 
						||
         begin
 | 
						||
           { strings are stored by address only }
 | 
						||
           case elementtype.def^.deftype of
 | 
						||
             stringdef :
 | 
						||
               elesize:=4;
 | 
						||
             else
 | 
						||
               elesize:=elementtype.def^.size;
 | 
						||
           end;
 | 
						||
         end
 | 
						||
        else
 | 
						||
         elesize:=elementtype.def^.size;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tarraydef.size : longint;
 | 
						||
      begin
 | 
						||
        {Tarraydef.size may never be called for an open array!}
 | 
						||
        if IsDynamicArray then
 | 
						||
          begin
 | 
						||
             size:=4;
 | 
						||
             exit;
 | 
						||
          end;
 | 
						||
        if highrange<lowrange then
 | 
						||
            internalerror(99080501);
 | 
						||
        If (elesize>0) and
 | 
						||
           (
 | 
						||
            (highrange-lowrange = $7fffffff) or
 | 
						||
            { () are needed around elesize-1 to avoid a possible
 | 
						||
              integer overflow for elesize=1 !! PM }
 | 
						||
            (($7fffffff div elesize + (elesize -1)) < (highrange - lowrange))
 | 
						||
           ) Then
 | 
						||
          Begin
 | 
						||
            Message(sym_e_segment_too_large);
 | 
						||
            size := 4
 | 
						||
          End
 | 
						||
        Else size:=(highrange-lowrange+1)*elesize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tarraydef.alignment : longint;
 | 
						||
      begin
 | 
						||
         { alignment is the size of the elements }
 | 
						||
         if elementtype.def^.deftype=recorddef then
 | 
						||
          alignment:=elementtype.def^.alignment
 | 
						||
         else
 | 
						||
          alignment:=elesize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tarraydef.needs_inittable : boolean;
 | 
						||
      begin
 | 
						||
         needs_inittable:=IsDynamicArray or elementtype.def^.needs_inittable;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tarraydef.write_child_rtti_data;
 | 
						||
      begin
 | 
						||
         elementtype.def^.get_rtti_label;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tarraydef.write_rtti_data;
 | 
						||
      begin
 | 
						||
         if IsDynamicArray then
 | 
						||
           rttilist^.concat(new(pai_const,init_8bit(tkdynarray)))
 | 
						||
         else
 | 
						||
           rttilist^.concat(new(pai_const,init_8bit(tkarray)));
 | 
						||
         write_rtti_name;
 | 
						||
         { size of elements }
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(elesize)));
 | 
						||
         { count of elements }
 | 
						||
         if not(IsDynamicArray) then
 | 
						||
           rttilist^.concat(new(pai_const,init_32bit(highrange-lowrange+1)));
 | 
						||
         { element type }
 | 
						||
         rttilist^.concat(new(pai_const_symbol,initname(elementtype.def^.get_rtti_label)));
 | 
						||
         { variant type }
 | 
						||
         // !!!!!!!!!!!!!!!!
 | 
						||
      end;
 | 
						||
 | 
						||
    function tarraydef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         if isarrayofconst or isConstructor then
 | 
						||
           begin
 | 
						||
             if isvariant or ((highrange=-1) and (lowrange=0)) then
 | 
						||
               gettypename:='Array Of Const'
 | 
						||
             else
 | 
						||
               gettypename:='Array Of '+elementtype.def^.typename;
 | 
						||
           end
 | 
						||
         else if is_open_array(@self) or IsDynamicArray then
 | 
						||
           gettypename:='Array Of '+elementtype.def^.typename
 | 
						||
         else
 | 
						||
           begin
 | 
						||
              if rangetype.def^.deftype=enumdef then
 | 
						||
                gettypename:='Array['+rangetype.def^.typename+'] Of '+elementtype.def^.typename
 | 
						||
              else
 | 
						||
                gettypename:='Array['+tostr(lowrange)+'..'+
 | 
						||
                  tostr(highrange)+'] Of '+elementtype.def^.typename
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
{***************************************************************************
 | 
						||
                                  trecorddef
 | 
						||
***************************************************************************}
 | 
						||
 | 
						||
    constructor trecorddef.init(p : psymtable);
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=recorddef;
 | 
						||
         symtable:=p;
 | 
						||
         symtable^.defowner := @self;
 | 
						||
         symtable^.dataalignment:=packrecordalignment[aktpackrecords];
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor trecorddef.load;
 | 
						||
      var
 | 
						||
         oldread_member : boolean;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=recorddef;
 | 
						||
         savesize:=readlong;
 | 
						||
         oldread_member:=read_member;
 | 
						||
         read_member:=true;
 | 
						||
         symtable:=new(psymtable,loadas(recordsymtable));
 | 
						||
         read_member:=oldread_member;
 | 
						||
         symtable^.defowner := @self;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    destructor trecorddef.done;
 | 
						||
      begin
 | 
						||
         if assigned(symtable) then
 | 
						||
           dispose(symtable,done);
 | 
						||
         inherited done;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    var
 | 
						||
       binittable : boolean;
 | 
						||
 | 
						||
    procedure check_rec_inittable(s : pnamedindexobject);
 | 
						||
 | 
						||
      begin
 | 
						||
         if (not binittable) and
 | 
						||
            (psym(s)^.typ=varsym) and
 | 
						||
            assigned(pvarsym(s)^.vartype.def) then
 | 
						||
          begin
 | 
						||
            if (pvarsym(s)^.vartype.def^.deftype<>objectdef) or
 | 
						||
               not is_class(pvarsym(s)^.vartype.def) then
 | 
						||
             binittable:=pvarsym(s)^.vartype.def^.needs_inittable;
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function trecorddef.needs_inittable : boolean;
 | 
						||
      var
 | 
						||
         oldb : boolean;
 | 
						||
      begin
 | 
						||
         { there are recursive calls to needs_rtti possible, }
 | 
						||
         { so we have to change to old value how else should }
 | 
						||
         { we do that ? check_rec_rtti can't be a nested     }
 | 
						||
         { procedure of needs_rtti !                         }
 | 
						||
         oldb:=binittable;
 | 
						||
         binittable:=false;
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}check_rec_inittable);
 | 
						||
         needs_inittable:=binittable;
 | 
						||
         binittable:=oldb;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure trecorddef.deref;
 | 
						||
      var
 | 
						||
         oldrecsyms : psymtable;
 | 
						||
      begin
 | 
						||
         inherited deref;
 | 
						||
         oldrecsyms:=aktrecordsymtable;
 | 
						||
         aktrecordsymtable:=symtable;
 | 
						||
         { now dereference the definitions }
 | 
						||
         symtable^.deref;
 | 
						||
         aktrecordsymtable:=oldrecsyms;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure trecorddef.write;
 | 
						||
      var
 | 
						||
         oldread_member : boolean;
 | 
						||
      begin
 | 
						||
         oldread_member:=read_member;
 | 
						||
         read_member:=true;
 | 
						||
         inherited write;
 | 
						||
         writelong(savesize);
 | 
						||
         current_ppu^.writeentry(ibrecorddef);
 | 
						||
         self.symtable^.writeas;
 | 
						||
         read_member:=oldread_member;
 | 
						||
      end;
 | 
						||
 | 
						||
    function trecorddef.size:longint;
 | 
						||
      begin
 | 
						||
        size:=symtable^.datasize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function trecorddef.alignment:longint;
 | 
						||
      var
 | 
						||
        l  : longint;
 | 
						||
        hp : pvarsym;
 | 
						||
      begin
 | 
						||
        { also check the first symbol for it's size, because a
 | 
						||
          packed record has dataalignment of 1, but the first
 | 
						||
          sym could be a longint which should be aligned on 4 bytes,
 | 
						||
          this is compatible with C record packing (PFV) }
 | 
						||
        hp:=pvarsym(symtable^.symindex^.first);
 | 
						||
        if assigned(hp) then
 | 
						||
         begin
 | 
						||
           l:=hp^.vartype.def^.size;
 | 
						||
           if l>symtable^.dataalignment then
 | 
						||
            begin
 | 
						||
              if l>=4 then
 | 
						||
               alignment:=4
 | 
						||
              else
 | 
						||
               if l>=2 then
 | 
						||
                alignment:=2
 | 
						||
              else
 | 
						||
               alignment:=1;
 | 
						||
            end
 | 
						||
           else
 | 
						||
            alignment:=symtable^.dataalignment;
 | 
						||
         end
 | 
						||
        else
 | 
						||
         alignment:=symtable^.dataalignment;
 | 
						||
      end;
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    Const StabRecString : pchar = Nil;
 | 
						||
          StabRecSize : longint = 0;
 | 
						||
          RecOffset : Longint = 0;
 | 
						||
 | 
						||
    procedure addname(p : pnamedindexobject);
 | 
						||
    var
 | 
						||
      news, newrec : pchar;
 | 
						||
      spec : string[3];
 | 
						||
      size : longint;
 | 
						||
    begin
 | 
						||
    { static variables from objects are like global objects }
 | 
						||
    if (sp_static in psym(p)^.symoptions) then
 | 
						||
      exit;
 | 
						||
    If psym(p)^.typ = varsym then
 | 
						||
       begin
 | 
						||
         if (sp_protected in psym(p)^.symoptions) then
 | 
						||
           spec:='/1'
 | 
						||
         else if (sp_private in psym(p)^.symoptions) then
 | 
						||
           spec:='/0'
 | 
						||
         else
 | 
						||
           spec:='';
 | 
						||
         if not assigned(pvarsym(p)^.vartype.def) then
 | 
						||
          writeln(pvarsym(p)^.name);
 | 
						||
         { class fields are pointers PM, obsolete now PM }
 | 
						||
         {if (pvarsym(p)^.vartype.def^.deftype=objectdef) and
 | 
						||
            pobjectdef(pvarsym(p)^.vartype.def)^.is_class then
 | 
						||
            spec:=spec+'*'; }
 | 
						||
         size:=pvarsym(p)^.vartype.def^.size;
 | 
						||
         { open arrays made overflows !! }
 | 
						||
         if size>$fffffff then
 | 
						||
           size:=$fffffff;
 | 
						||
         newrec := strpnew(p^.name+':'+spec+pvarsym(p)^.vartype.def^.numberstring
 | 
						||
                       +','+tostr(pvarsym(p)^.address*8)+','
 | 
						||
                       +tostr(size*8)+';');
 | 
						||
         if strlen(StabRecString) + strlen(newrec) >= StabRecSize-256 then
 | 
						||
           begin
 | 
						||
              getmem(news,stabrecsize+memsizeinc);
 | 
						||
              strcopy(news,stabrecstring);
 | 
						||
              freemem(stabrecstring,stabrecsize);
 | 
						||
              stabrecsize:=stabrecsize+memsizeinc;
 | 
						||
              stabrecstring:=news;
 | 
						||
           end;
 | 
						||
         strcat(StabRecstring,newrec);
 | 
						||
         strdispose(newrec);
 | 
						||
         {This should be used for case !!}
 | 
						||
         RecOffset := RecOffset + pvarsym(p)^.vartype.def^.size;
 | 
						||
       end;
 | 
						||
    end;
 | 
						||
 | 
						||
 | 
						||
    function trecorddef.stabstring : pchar;
 | 
						||
      Var oldrec : pchar;
 | 
						||
          oldsize : longint;
 | 
						||
      begin
 | 
						||
        oldrec := stabrecstring;
 | 
						||
        oldsize:=stabrecsize;
 | 
						||
        GetMem(stabrecstring,memsizeinc);
 | 
						||
        stabrecsize:=memsizeinc;
 | 
						||
        strpcopy(stabRecString,'s'+tostr(size));
 | 
						||
        RecOffset := 0;
 | 
						||
        symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}addname);
 | 
						||
        { FPC doesn't want to convert a char to a pchar}
 | 
						||
        { is this a bug ? }
 | 
						||
        strpcopy(strend(StabRecString),';');
 | 
						||
        stabstring := strnew(StabRecString);
 | 
						||
        Freemem(stabrecstring,stabrecsize);
 | 
						||
        stabrecstring := oldrec;
 | 
						||
        stabrecsize:=oldsize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure trecorddef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
        if (not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
 | 
						||
           (is_def_stab_written = not_written)  then
 | 
						||
          inherited concatstabto(asmlist);
 | 
						||
      end;
 | 
						||
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
    var
 | 
						||
       count : longint;
 | 
						||
 | 
						||
    procedure count_inittable_fields(sym : pnamedindexobject);
 | 
						||
      begin
 | 
						||
         if ((psym(sym)^.typ=varsym) and
 | 
						||
            pvarsym(sym)^.vartype.def^.needs_inittable)
 | 
						||
            and ((pvarsym(sym)^.vartype.def^.deftype<>objectdef) or
 | 
						||
                  not(is_class(pvarsym(sym)^.vartype.def))) then
 | 
						||
           inc(count);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure count_fields(sym : pnamedindexobject);
 | 
						||
      begin
 | 
						||
            inc(count);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure write_field_inittable(sym : pnamedindexobject);
 | 
						||
      begin
 | 
						||
         if ((psym(sym)^.typ=varsym) and
 | 
						||
            pvarsym(sym)^.vartype.def^.needs_inittable) and
 | 
						||
            ((pvarsym(sym)^.vartype.def^.deftype<>objectdef) or
 | 
						||
             not(is_class(pvarsym(sym)^.vartype.def))) then
 | 
						||
           begin
 | 
						||
              rttilist^.concat(new(pai_const_symbol,init(pvarsym(sym)^.vartype.def^.get_inittable_label)));
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure write_field_rtti(sym : pnamedindexobject);
 | 
						||
      begin
 | 
						||
         rttilist^.concat(new(pai_const_symbol,initname(pvarsym(sym)^.vartype.def^.get_rtti_label)));
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure generate_child_inittable(sym:pnamedindexobject);
 | 
						||
      begin
 | 
						||
         if (psym(sym)^.typ=varsym) and
 | 
						||
            pvarsym(sym)^.vartype.def^.needs_inittable then
 | 
						||
         { force inittable generation }
 | 
						||
           pvarsym(sym)^.vartype.def^.get_inittable_label;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure generate_child_rtti(sym : pnamedindexobject);
 | 
						||
      begin
 | 
						||
         pvarsym(sym)^.vartype.def^.get_rtti_label;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure trecorddef.write_child_rtti_data;
 | 
						||
      begin
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}generate_child_rtti);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure trecorddef.write_child_init_data;
 | 
						||
      begin
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}generate_child_inittable);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure trecorddef.write_rtti_data;
 | 
						||
      begin
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(tkrecord)));
 | 
						||
         write_rtti_name;
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(size)));
 | 
						||
         count:=0;
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}count_fields);
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(count)));
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}write_field_rtti);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure trecorddef.write_init_data;
 | 
						||
      begin
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(tkrecord)));
 | 
						||
         write_rtti_name;
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(size)));
 | 
						||
         count:=0;
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}count_inittable_fields);
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(count)));
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}write_field_inittable);
 | 
						||
      end;
 | 
						||
 | 
						||
    function trecorddef.gettypename : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:='<record type>'
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{***************************************************************************
 | 
						||
                       TABSTRACTPROCDEF
 | 
						||
***************************************************************************}
 | 
						||
 | 
						||
    constructor tabstractprocdef.init;
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         new(para,init);
 | 
						||
         minparacount:=0;
 | 
						||
         maxparacount:=0;
 | 
						||
         fpu_used:=0;
 | 
						||
         proctypeoption:=potype_none;
 | 
						||
         proccalloptions:=[];
 | 
						||
         procoptions:=[];
 | 
						||
         rettype.setdef(voiddef);
 | 
						||
         symtablelevel:=0;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    destructor tabstractprocdef.done;
 | 
						||
      begin
 | 
						||
         dispose(para,done);
 | 
						||
         inherited done;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tabstractprocdef.concatpara(tt:ttype;vsp : tvarspez;defval:psym);
 | 
						||
      var
 | 
						||
        hp : pparaitem;
 | 
						||
      begin
 | 
						||
        new(hp,init);
 | 
						||
        hp^.paratyp:=vsp;
 | 
						||
        hp^.paratype:=tt;
 | 
						||
        hp^.register:=R_NO;
 | 
						||
        hp^.defaultvalue:=defval;
 | 
						||
        para^.insert(hp);
 | 
						||
        if not assigned(defval) then
 | 
						||
         inc(minparacount);
 | 
						||
        inc(maxparacount);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    { all functions returning in FPU are
 | 
						||
      assume to use 2 FPU registers
 | 
						||
      until the function implementation
 | 
						||
      is processed   PM }
 | 
						||
    procedure tabstractprocdef.test_if_fpu_result;
 | 
						||
      begin
 | 
						||
         if assigned(rettype.def) and is_fpu(rettype.def) then
 | 
						||
           fpu_used:=2;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tabstractprocdef.deref;
 | 
						||
      var
 | 
						||
         hp : pparaitem;
 | 
						||
      begin
 | 
						||
         inherited deref;
 | 
						||
         rettype.resolve;
 | 
						||
         hp:=pparaitem(para^.first);
 | 
						||
         while assigned(hp) do
 | 
						||
          begin
 | 
						||
            hp^.paratype.resolve;
 | 
						||
            resolvesym(psym(hp^.defaultvalue));
 | 
						||
            hp:=pparaitem(hp^.next);
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tabstractprocdef.load;
 | 
						||
      var
 | 
						||
         hp : pparaitem;
 | 
						||
         count,i : word;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         new(para,init);
 | 
						||
         minparacount:=0;
 | 
						||
         maxparacount:=0;
 | 
						||
         rettype.load;
 | 
						||
         fpu_used:=readbyte;
 | 
						||
         proctypeoption:=tproctypeoption(readlong);
 | 
						||
         readsmallset(proccalloptions,sizeof(proccalloptions));
 | 
						||
         readsmallset(procoptions,sizeof(procoptions));
 | 
						||
         count:=readword;
 | 
						||
         savesize:=target_os.size_of_pointer;
 | 
						||
         for i:=1 to count do
 | 
						||
          begin
 | 
						||
            new(hp,init);
 | 
						||
            hp^.paratyp:=tvarspez(readbyte);
 | 
						||
            { hp^.register:=tregister(readbyte); }
 | 
						||
            hp^.register:=R_NO;
 | 
						||
            hp^.paratype.load;
 | 
						||
            hp^.defaultvalue:=readsymref;
 | 
						||
            if not assigned(hp^.defaultvalue) then
 | 
						||
             inc(minparacount);
 | 
						||
            inc(maxparacount);
 | 
						||
            para^.concat(hp);
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tabstractprocdef.write;
 | 
						||
      var
 | 
						||
        hp : pparaitem;
 | 
						||
        oldintfcrc : boolean;
 | 
						||
      begin
 | 
						||
         inherited write;
 | 
						||
         rettype.write;
 | 
						||
         oldintfcrc:=current_ppu^.do_interface_crc;
 | 
						||
         current_ppu^.do_interface_crc:=false;
 | 
						||
         writebyte(fpu_used);
 | 
						||
         writelong(ord(proctypeoption));
 | 
						||
         writesmallset(proccalloptions,sizeof(proccalloptions));
 | 
						||
         writesmallset(procoptions,sizeof(procoptions));
 | 
						||
         current_ppu^.do_interface_crc:=oldintfcrc;
 | 
						||
         writeword(maxparacount);
 | 
						||
         hp:=pparaitem(para^.first);
 | 
						||
         while assigned(hp) do
 | 
						||
          begin
 | 
						||
            writebyte(byte(hp^.paratyp));
 | 
						||
            { writebyte(byte(hp^.register)); }
 | 
						||
            hp^.paratype.write;
 | 
						||
            writesymref(hp^.defaultvalue);
 | 
						||
            hp:=pparaitem(hp^.next);
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tabstractprocdef.para_size(alignsize:longint) : longint;
 | 
						||
      var
 | 
						||
         pdc : pparaitem;
 | 
						||
         l : longint;
 | 
						||
      begin
 | 
						||
         l:=0;
 | 
						||
         pdc:=pparaitem(para^.first);
 | 
						||
         while assigned(pdc) do
 | 
						||
          begin
 | 
						||
            case pdc^.paratyp of
 | 
						||
              vs_out,
 | 
						||
              vs_var   : inc(l,target_os.size_of_pointer);
 | 
						||
              vs_value,
 | 
						||
              vs_const : if push_addr_param(pdc^.paratype.def) then
 | 
						||
                          inc(l,target_os.size_of_pointer)
 | 
						||
                         else
 | 
						||
                          inc(l,pdc^.paratype.def^.size);
 | 
						||
            end;
 | 
						||
            l:=align(l,alignsize);
 | 
						||
            pdc:=pparaitem(pdc^.next);
 | 
						||
          end;
 | 
						||
         para_size:=l;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tabstractprocdef.demangled_paras : string;
 | 
						||
      var
 | 
						||
        hs,s : string;
 | 
						||
        hp : pparaitem;
 | 
						||
        hpc : pconstsym;
 | 
						||
      begin
 | 
						||
        s:='(';
 | 
						||
        hp:=pparaitem(para^.last);
 | 
						||
        while assigned(hp) do
 | 
						||
         begin
 | 
						||
           if assigned(hp^.paratype.def^.typesym) then
 | 
						||
             s:=s+hp^.paratype.def^.typesym^.name
 | 
						||
           else if hp^.paratyp=vs_out then
 | 
						||
             s:=s+'out'
 | 
						||
           else if hp^.paratyp=vs_var then
 | 
						||
             s:=s+'var'
 | 
						||
           else if hp^.paratyp=vs_const then
 | 
						||
             s:=s+'const'
 | 
						||
           else if hp^.paratyp=vs_out then
 | 
						||
             s:=s+'out';
 | 
						||
           { default value }
 | 
						||
           if assigned(hp^.defaultvalue) then
 | 
						||
            begin
 | 
						||
              hpc:=pconstsym(hp^.defaultvalue);
 | 
						||
              hs:='';
 | 
						||
              case hpc^.consttyp of
 | 
						||
                conststring,
 | 
						||
                constresourcestring :
 | 
						||
                  hs:=strpas(pchar(tpointerord(hpc^.value)));
 | 
						||
                constreal :
 | 
						||
                  str(pbestreal(tpointerord(hpc^.value))^,hs);
 | 
						||
                constord,
 | 
						||
                constpointer :
 | 
						||
                  hs:=tostr(hpc^.value);
 | 
						||
                constbool :
 | 
						||
                  begin
 | 
						||
                    if hpc^.value<>0 then
 | 
						||
                     hs:='TRUE'
 | 
						||
                    else
 | 
						||
                     hs:='FALSE';
 | 
						||
                  end;
 | 
						||
                constnil :
 | 
						||
                  hs:='nil';
 | 
						||
                constchar :
 | 
						||
                  hs:=chr(hpc^.value);
 | 
						||
                constset :
 | 
						||
                  hs:='<set>';
 | 
						||
              end;
 | 
						||
              if hs<>'' then
 | 
						||
               s:=s+'="'+hs+'"';
 | 
						||
            end;
 | 
						||
           hp:=pparaitem(hp^.previous);
 | 
						||
           if assigned(hp) then
 | 
						||
            s:=s+',';
 | 
						||
         end;
 | 
						||
        s:=s+')';
 | 
						||
        demangled_paras:=s;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tabstractprocdef.proccalloption2str : string;
 | 
						||
      type
 | 
						||
        tproccallopt=record
 | 
						||
          mask : tproccalloption;
 | 
						||
          str  : string[30];
 | 
						||
        end;
 | 
						||
      const
 | 
						||
        proccallopts=13;
 | 
						||
        proccallopt : array[1..proccallopts] of tproccallopt=(
 | 
						||
           (mask:pocall_none;         str:''),
 | 
						||
           (mask:pocall_clearstack;   str:'ClearStack'),
 | 
						||
           (mask:pocall_leftright;    str:'LeftRight'),
 | 
						||
           (mask:pocall_cdecl;        str:'CDecl'),
 | 
						||
           (mask:pocall_register;     str:'Register'),
 | 
						||
           (mask:pocall_stdcall;      str:'StdCall'),
 | 
						||
           (mask:pocall_safecall;     str:'SafeCall'),
 | 
						||
           (mask:pocall_palmossyscall;str:'PalmOSSysCall'),
 | 
						||
           (mask:pocall_system;       str:'System'),
 | 
						||
           (mask:pocall_inline;       str:'Inline'),
 | 
						||
           (mask:pocall_internproc;   str:'InternProc'),
 | 
						||
           (mask:pocall_internconst;  str:'InternConst'),
 | 
						||
           (mask:pocall_cdecl;        str:'CPPDecl')
 | 
						||
        );
 | 
						||
      var
 | 
						||
        s : string;
 | 
						||
        i : longint;
 | 
						||
        first : boolean;
 | 
						||
      begin
 | 
						||
        s:='';
 | 
						||
        first:=true;
 | 
						||
        for i:=1to proccallopts do
 | 
						||
         if (proccallopt[i].mask in proccalloptions) then
 | 
						||
          begin
 | 
						||
            if first then
 | 
						||
              first:=false
 | 
						||
            else
 | 
						||
              s:=s+';';
 | 
						||
            s:=s+proccallopt[i].str;
 | 
						||
          end;
 | 
						||
        proccalloption2str:=s;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tabstractprocdef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
        stabstring := strpnew('abstractproc'+numberstring+';');
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tabstractprocdef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
         if (not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
 | 
						||
            and (is_def_stab_written = not_written)  then
 | 
						||
           begin
 | 
						||
              if assigned(rettype.def) then forcestabto(asmlist,rettype.def);
 | 
						||
              inherited concatstabto(asmlist);
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
{***************************************************************************
 | 
						||
                                  TPROCDEF
 | 
						||
***************************************************************************}
 | 
						||
 | 
						||
    constructor tprocdef.init;
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=procdef;
 | 
						||
         _mangledname:=nil;
 | 
						||
         nextoverloaded:=nil;
 | 
						||
         fileinfo:=aktfilepos;
 | 
						||
         extnumber:=-1;
 | 
						||
         localst:=new(psymtable,init(localsymtable));
 | 
						||
         parast:=new(psymtable,init(parasymtable));
 | 
						||
         localst^.defowner:=@self;
 | 
						||
         parast^.defowner:=@self;
 | 
						||
         { this is used by insert
 | 
						||
          to check same names in parast and localst }
 | 
						||
         localst^.next:=parast;
 | 
						||
         defref:=nil;
 | 
						||
         crossref:=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;
 | 
						||
       { first, we assume that all registers are used }
 | 
						||
{$ifdef newcg}
 | 
						||
         usedregisters:=[firstreg..lastreg];
 | 
						||
{$else newcg}
 | 
						||
{$ifdef i386}
 | 
						||
         usedregisters:=$ff;
 | 
						||
{$endif i386}
 | 
						||
{$ifdef m68k}
 | 
						||
         usedregisters:=$FFFF;
 | 
						||
{$endif}
 | 
						||
{$endif newcg}
 | 
						||
         forwarddef:=true;
 | 
						||
         interfacedef:=false;
 | 
						||
         hasforward:=false;
 | 
						||
         _class := nil;
 | 
						||
         code:=nil;
 | 
						||
         regvarinfo := nil;
 | 
						||
         count:=false;
 | 
						||
         is_used:=false;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tprocdef.load;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=procdef;
 | 
						||
 | 
						||
{$ifdef newcg}
 | 
						||
         readnormalset(usedregisters);
 | 
						||
{$else newcg}
 | 
						||
{$ifdef i386}
 | 
						||
         usedregisters:=readbyte;
 | 
						||
{$endif i386}
 | 
						||
{$ifdef m68k}
 | 
						||
         usedregisters:=readword;
 | 
						||
{$endif}
 | 
						||
{$endif newcg}
 | 
						||
         _mangledname:=stringdup(readstring);
 | 
						||
 | 
						||
         extnumber:=readlong;
 | 
						||
         nextoverloaded:=pprocdef(readdefref);
 | 
						||
         _class := pobjectdef(readdefref);
 | 
						||
         readposinfo(fileinfo);
 | 
						||
 | 
						||
         procsym:=pprocsym(readsymref);
 | 
						||
 | 
						||
         if (cs_link_deffile in aktglobalswitches) and
 | 
						||
            (tf_need_export in target_info.flags) and
 | 
						||
            (po_exports in procoptions) then
 | 
						||
           deffile.AddExport(mangledname);
 | 
						||
 | 
						||
         new(parast,loadas(parasymtable));
 | 
						||
         parast^.defowner:=@self;
 | 
						||
         {new(localst,loadas(localsymtable));
 | 
						||
         localst^.defowner:=@self;
 | 
						||
         parast^.next:=localst;
 | 
						||
         localst^.next:=owner;}
 | 
						||
 | 
						||
         forwarddef:=false;
 | 
						||
         interfacedef:=false;
 | 
						||
         hasforward:=false;
 | 
						||
         code := nil;
 | 
						||
         regvarinfo := nil;
 | 
						||
         lastref:=nil;
 | 
						||
         lastwritten:=nil;
 | 
						||
         defref:=nil;
 | 
						||
         refcount:=0;
 | 
						||
         count:=true;
 | 
						||
         is_used:=false;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
Const local_symtable_index : longint = $8001;
 | 
						||
 | 
						||
    procedure tprocdef.load_references;
 | 
						||
      var
 | 
						||
        pos : tfileposinfo;
 | 
						||
{$ifndef NOLOCALBROWSER}
 | 
						||
        oldsymtablestack,
 | 
						||
        st : psymtable;
 | 
						||
{$endif ndef NOLOCALBROWSER}
 | 
						||
        move_last : boolean;
 | 
						||
      begin
 | 
						||
        move_last:=lastwritten=lastref;
 | 
						||
        while (not current_ppu^.endofentry) do
 | 
						||
         begin
 | 
						||
           readposinfo(pos);
 | 
						||
           inc(refcount);
 | 
						||
           lastref:=new(pref,init(lastref,@pos));
 | 
						||
           lastref^.is_written:=true;
 | 
						||
           if refcount=1 then
 | 
						||
            defref:=lastref;
 | 
						||
         end;
 | 
						||
        if move_last then
 | 
						||
          lastwritten:=lastref;
 | 
						||
        if ((current_module^.flags and uf_local_browser)<>0)
 | 
						||
           and is_in_current then
 | 
						||
          begin
 | 
						||
{$ifndef NOLOCALBROWSER}
 | 
						||
             oldsymtablestack:=symtablestack;
 | 
						||
             st:=aktlocalsymtable;
 | 
						||
             new(parast,loadas(parasymtable));
 | 
						||
             parast^.defowner:=@self;
 | 
						||
             aktlocalsymtable:=parast;
 | 
						||
             parast^.deref;
 | 
						||
             parast^.next:=owner;
 | 
						||
             parast^.load_browser;
 | 
						||
             aktlocalsymtable:=st;
 | 
						||
             new(localst,loadas(localsymtable));
 | 
						||
             localst^.defowner:=@self;
 | 
						||
             aktlocalsymtable:=localst;
 | 
						||
             symtablestack:=parast;
 | 
						||
             localst^.deref;
 | 
						||
             localst^.next:=parast;
 | 
						||
             localst^.load_browser;
 | 
						||
             aktlocalsymtable:=st;
 | 
						||
             symtablestack:=oldsymtablestack;
 | 
						||
{$endif ndef NOLOCALBROWSER}
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tprocdef.write_references : boolean;
 | 
						||
      var
 | 
						||
        ref : pref;
 | 
						||
{$ifndef NOLOCALBROWSER}
 | 
						||
        st : psymtable;
 | 
						||
        pdo : pobjectdef;
 | 
						||
{$endif ndef NOLOCALBROWSER}
 | 
						||
        move_last : boolean;
 | 
						||
      begin
 | 
						||
        move_last:=lastwritten=lastref;
 | 
						||
        if move_last and (((current_module^.flags and uf_local_browser)=0)
 | 
						||
           or not is_in_current) then
 | 
						||
          exit;
 | 
						||
      { write address of this symbol }
 | 
						||
        writedefref(@self);
 | 
						||
      { write refs }
 | 
						||
        if assigned(lastwritten) then
 | 
						||
          ref:=lastwritten
 | 
						||
        else
 | 
						||
          ref:=defref;
 | 
						||
        while assigned(ref) do
 | 
						||
         begin
 | 
						||
           if ref^.moduleindex=current_module^.unit_index then
 | 
						||
             begin
 | 
						||
                writeposinfo(ref^.posinfo);
 | 
						||
                ref^.is_written:=true;
 | 
						||
                if move_last then
 | 
						||
                  lastwritten:=ref;
 | 
						||
             end
 | 
						||
           else if not ref^.is_written then
 | 
						||
             move_last:=false
 | 
						||
           else if move_last then
 | 
						||
             lastwritten:=ref;
 | 
						||
           ref:=ref^.nextref;
 | 
						||
         end;
 | 
						||
        current_ppu^.writeentry(ibdefref);
 | 
						||
        write_references:=true;
 | 
						||
        if ((current_module^.flags and uf_local_browser)<>0)
 | 
						||
           and is_in_current then
 | 
						||
          begin
 | 
						||
{$ifndef NOLOCALBROWSER}
 | 
						||
             pdo:=_class;
 | 
						||
             if (owner^.symtabletype<>localsymtable) then
 | 
						||
               while assigned(pdo) do
 | 
						||
                 begin
 | 
						||
                    if pdo^.symtable<>aktrecordsymtable then
 | 
						||
                      begin
 | 
						||
                         pdo^.symtable^.unitid:=local_symtable_index;
 | 
						||
                         inc(local_symtable_index);
 | 
						||
                      end;
 | 
						||
                    pdo:=pdo^.childof;
 | 
						||
                 end;
 | 
						||
 | 
						||
             { we need TESTLOCALBROWSER para and local symtables
 | 
						||
               PPU files are then easier to read PM }
 | 
						||
             if not assigned(parast) then
 | 
						||
               parast:=new(psymtable,init(parasymtable));
 | 
						||
             parast^.defowner:=@self;
 | 
						||
             st:=aktlocalsymtable;
 | 
						||
             aktlocalsymtable:=parast;
 | 
						||
             parast^.writeas;
 | 
						||
             parast^.unitid:=local_symtable_index;
 | 
						||
             inc(local_symtable_index);
 | 
						||
             parast^.write_browser;
 | 
						||
             if not assigned(localst) then
 | 
						||
               localst:=new(psymtable,init(localsymtable));
 | 
						||
             localst^.defowner:=@self;
 | 
						||
             aktlocalsymtable:=localst;
 | 
						||
             localst^.writeas;
 | 
						||
             localst^.unitid:=local_symtable_index;
 | 
						||
             inc(local_symtable_index);
 | 
						||
             localst^.write_browser;
 | 
						||
             aktlocalsymtable:=st;
 | 
						||
             { decrement for }
 | 
						||
             local_symtable_index:=local_symtable_index-2;
 | 
						||
             pdo:=_class;
 | 
						||
             if (owner^.symtabletype<>localsymtable) then
 | 
						||
               while assigned(pdo) do
 | 
						||
                 begin
 | 
						||
                    if pdo^.symtable<>aktrecordsymtable then
 | 
						||
                      dec(local_symtable_index);
 | 
						||
                    pdo:=pdo^.childof;
 | 
						||
                 end;
 | 
						||
{$endif ndef NOLOCALBROWSER}
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef BrowserLog}
 | 
						||
    procedure tprocdef.add_to_browserlog;
 | 
						||
      begin
 | 
						||
         if assigned(defref) then
 | 
						||
          begin
 | 
						||
            browserlog.AddLog('***'+mangledname);
 | 
						||
            browserlog.AddLogRefs(defref);
 | 
						||
            if (current_module^.flags and uf_local_browser)<>0 then
 | 
						||
              begin
 | 
						||
                 if assigned(parast) then
 | 
						||
                   parast^.writebrowserlog;
 | 
						||
                 if assigned(localst) then
 | 
						||
                   localst^.writebrowserlog;
 | 
						||
              end;
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
{$endif BrowserLog}
 | 
						||
 | 
						||
 | 
						||
    destructor tprocdef.done;
 | 
						||
      begin
 | 
						||
         if assigned(defref) then
 | 
						||
           begin
 | 
						||
             defref^.freechain;
 | 
						||
             dispose(defref,done);
 | 
						||
           end;
 | 
						||
         if assigned(parast) then
 | 
						||
           dispose(parast,done);
 | 
						||
         if assigned(localst) and (localst^.symtabletype<>staticsymtable) then
 | 
						||
           dispose(localst,done);
 | 
						||
         if (pocall_inline in proccalloptions) and assigned(code) then
 | 
						||
           tnode(code).free;
 | 
						||
         if assigned(regvarinfo) then
 | 
						||
           dispose(pregvarinfo(regvarinfo));
 | 
						||
         if (po_msgstr in procoptions) then
 | 
						||
           strdispose(messageinf.str);
 | 
						||
         if assigned(_mangledname) then
 | 
						||
           stringdispose(_mangledname);
 | 
						||
         inherited done;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tprocdef.write;
 | 
						||
      var
 | 
						||
        oldintfcrc : boolean;
 | 
						||
      begin
 | 
						||
         inherited write;
 | 
						||
         oldintfcrc:=current_ppu^.do_interface_crc;
 | 
						||
         current_ppu^.do_interface_crc:=false;
 | 
						||
   { set all registers to used for simplified compilation PM }
 | 
						||
         if simplify_ppu then
 | 
						||
           begin
 | 
						||
{$ifdef newcg}
 | 
						||
             usedregisters:=[firstreg..lastreg];
 | 
						||
{$else newcg}
 | 
						||
{$ifdef i386}
 | 
						||
             usedregisters:=$ff;
 | 
						||
{$endif i386}
 | 
						||
{$ifdef m68k}
 | 
						||
             usedregisters:=$ffff;
 | 
						||
{$endif}
 | 
						||
{$endif newcg}
 | 
						||
           end;
 | 
						||
 | 
						||
{$ifdef newcg}
 | 
						||
         writenormalset(usedregisters);
 | 
						||
{$else newcg}
 | 
						||
{$ifdef i386}
 | 
						||
         writebyte(usedregisters);
 | 
						||
{$endif i386}
 | 
						||
{$ifdef m68k}
 | 
						||
         writeword(usedregisters);
 | 
						||
{$endif}
 | 
						||
{$endif newcg}
 | 
						||
         current_ppu^.do_interface_crc:=oldintfcrc;
 | 
						||
         writestring(mangledname);
 | 
						||
         writelong(extnumber);
 | 
						||
         if (proctypeoption<>potype_operator) then
 | 
						||
           writedefref(nextoverloaded)
 | 
						||
         else
 | 
						||
           begin
 | 
						||
              { only write the overloads from the same unit }
 | 
						||
              if assigned(nextoverloaded) and
 | 
						||
                 (nextoverloaded^.owner=owner) then
 | 
						||
                writedefref(nextoverloaded)
 | 
						||
              else
 | 
						||
                writedefref(nil);
 | 
						||
           end;
 | 
						||
         writedefref(_class);
 | 
						||
         writeposinfo(fileinfo);
 | 
						||
         writesymref(procsym);
 | 
						||
         if (pocall_inline in proccalloptions) then
 | 
						||
           begin
 | 
						||
              { we need to save
 | 
						||
                - the para and the local symtable
 | 
						||
                - the code ptree !! PM
 | 
						||
               writesymtable(parast);
 | 
						||
               writesymtable(localst);
 | 
						||
               writeptree(ptree(code));
 | 
						||
               }
 | 
						||
           end;
 | 
						||
         current_ppu^.writeentry(ibprocdef);
 | 
						||
 | 
						||
         { Save the para and local symtable, for easier reading
 | 
						||
           save both always, they don't influence the interface crc }
 | 
						||
         oldintfcrc:=current_ppu^.do_interface_crc;
 | 
						||
         current_ppu^.do_interface_crc:=false;
 | 
						||
         if not assigned(parast) then
 | 
						||
          begin
 | 
						||
            parast:=new(psymtable,init(parasymtable));
 | 
						||
            parast^.defowner:=@self;
 | 
						||
          end;
 | 
						||
         parast^.writeas;
 | 
						||
         {if not assigned(localst) then
 | 
						||
          begin
 | 
						||
            localst:=new(psymtable,init(localsymtable));
 | 
						||
            localst^.defowner:=@self;
 | 
						||
          end;
 | 
						||
         localst^.writeas;}
 | 
						||
         current_ppu^.do_interface_crc:=oldintfcrc;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tprocdef.haspara:boolean;
 | 
						||
      begin
 | 
						||
        haspara:=assigned(aktprocsym^.definition^.parast^.symindex^.first);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    procedure addparaname(p : psym);
 | 
						||
      var vs : char;
 | 
						||
      begin
 | 
						||
      if pvarsym(p)^.varspez = vs_value then vs := '1'
 | 
						||
        else vs := '0';
 | 
						||
      strpcopy(strend(StabRecString),p^.name+':'+pvarsym(p)^.vartype.def^.numberstring+','+vs+';');
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tprocdef.stabstring : pchar;
 | 
						||
      var
 | 
						||
          i : longint;
 | 
						||
          oldrec : pchar;
 | 
						||
      begin
 | 
						||
      oldrec := stabrecstring;
 | 
						||
      getmem(StabRecString,1024);
 | 
						||
      strpcopy(StabRecString,'f'+rettype.def^.numberstring);
 | 
						||
      i:=maxparacount;
 | 
						||
      if i>0 then
 | 
						||
        begin
 | 
						||
        strpcopy(strend(StabRecString),','+tostr(i)+';');
 | 
						||
        (* confuse gdb !! PM
 | 
						||
        if assigned(parast) then
 | 
						||
          parast^.foreach({$ifdef FPCPROCVAR}@{$endif}addparaname)
 | 
						||
          else
 | 
						||
          begin
 | 
						||
          param := para1;
 | 
						||
          i := 0;
 | 
						||
          while assigned(param) do
 | 
						||
            begin
 | 
						||
            inc(i);
 | 
						||
            if param^.paratyp = vs_value then vartyp := '1' else vartyp := '0';
 | 
						||
            {Here we have lost the parameter names !!}
 | 
						||
            {using lower case parameters }
 | 
						||
            strpcopy(strend(stabrecstring),'p'+tostr(i)
 | 
						||
               +':'+param^.paratype.def^.numberstring+','+vartyp+';');
 | 
						||
            param := param^.next;
 | 
						||
            end;
 | 
						||
          end;   *)
 | 
						||
        {strpcopy(strend(StabRecString),';');}
 | 
						||
        end;
 | 
						||
      stabstring := strnew(stabrecstring);
 | 
						||
      freemem(stabrecstring,1024);
 | 
						||
      stabrecstring := oldrec;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tprocdef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    procedure tprocdef.deref;
 | 
						||
      var
 | 
						||
        oldsymtablestack,
 | 
						||
        oldlocalsymtable : psymtable;
 | 
						||
      begin
 | 
						||
         inherited deref;
 | 
						||
         resolvedef(pdef(nextoverloaded));
 | 
						||
         resolvedef(pdef(_class));
 | 
						||
         { parast }
 | 
						||
         oldsymtablestack:=symtablestack;
 | 
						||
         oldlocalsymtable:=aktlocalsymtable;
 | 
						||
         aktlocalsymtable:=parast;
 | 
						||
         parast^.deref;
 | 
						||
         {symtablestack:=parast;
 | 
						||
         aktlocalsymtable:=localst;
 | 
						||
         localst^.deref;}
 | 
						||
         aktlocalsymtable:=oldlocalsymtable;
 | 
						||
         symtablestack:=oldsymtablestack;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tprocdef.mangledname : string;
 | 
						||
      begin
 | 
						||
         if assigned(_mangledname) then
 | 
						||
           mangledname:=_mangledname^
 | 
						||
         else
 | 
						||
           mangledname:='';
 | 
						||
         if count then
 | 
						||
           is_used:=true;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef dummy}
 | 
						||
    function tprocdef.procname: string;
 | 
						||
      var
 | 
						||
        s : string;
 | 
						||
        l : longint;
 | 
						||
      begin
 | 
						||
         if assigned(procsym) then
 | 
						||
           begin
 | 
						||
             procname:=procsym^.name;
 | 
						||
             exit;
 | 
						||
           end;
 | 
						||
         s:=mangledname;
 | 
						||
         { delete leading $$'s }
 | 
						||
         l:=pos('$$',s);
 | 
						||
         while l<>0 do
 | 
						||
           begin
 | 
						||
              delete(s,1,l+1);
 | 
						||
              l:=pos('$$',s);
 | 
						||
           end;
 | 
						||
         { delete leading _$'s }
 | 
						||
         l:=pos('_$',s);
 | 
						||
         while l<>0 do
 | 
						||
           begin
 | 
						||
              delete(s,1,l+1);
 | 
						||
              l:=pos('_$',s);
 | 
						||
           end;
 | 
						||
         l:=pos('$',s);
 | 
						||
         if l=0 then
 | 
						||
          procname:=s
 | 
						||
         else
 | 
						||
          procname:=Copy(s,1,l-1);
 | 
						||
      end;
 | 
						||
{$endif}
 | 
						||
 | 
						||
    function tprocdef.cplusplusmangledname : string;
 | 
						||
 | 
						||
      function getcppparaname(p : pdef) : string;
 | 
						||
 | 
						||
        const
 | 
						||
           ordtype2str : array[tbasetype] of string[2] = (
 | 
						||
             '','','c',
 | 
						||
             'Uc','Us','Ui',
 | 
						||
             'Sc','s','i',
 | 
						||
             'b','b','b',
 | 
						||
             'Us','x','w');
 | 
						||
 | 
						||
        var
 | 
						||
           s : string;
 | 
						||
 | 
						||
        begin
 | 
						||
           case p^.deftype of
 | 
						||
              orddef:
 | 
						||
                s:=ordtype2str[porddef(p)^.typ];
 | 
						||
              pointerdef:
 | 
						||
                s:='P'+getcppparaname(ppointerdef(p)^.pointertype.def);
 | 
						||
              else
 | 
						||
                internalerror(2103001);
 | 
						||
           end;
 | 
						||
           getcppparaname:=s;
 | 
						||
        end;
 | 
						||
 | 
						||
      var
 | 
						||
         s,s2 : string;
 | 
						||
         param : pparaitem;
 | 
						||
 | 
						||
      begin
 | 
						||
         s := procsym^.realname;
 | 
						||
         if procsym^.owner^.symtabletype=objectsymtable then
 | 
						||
           begin
 | 
						||
              s2:=upper(pobjectdef(procsym^.owner^.defowner)^.typesym^.realname);
 | 
						||
              case proctypeoption of
 | 
						||
                 potype_destructor:
 | 
						||
                   s:='_$_'+tostr(length(s2))+s2;
 | 
						||
                 potype_constructor:
 | 
						||
                   s:='___'+tostr(length(s2))+s2;
 | 
						||
                 else
 | 
						||
                   s:='_'+s+'__'+tostr(length(s2))+s2;
 | 
						||
              end;
 | 
						||
 | 
						||
           end
 | 
						||
         else s:=s+'__';
 | 
						||
 | 
						||
         s:=s+'F';
 | 
						||
 | 
						||
         { concat modifiers }
 | 
						||
         { !!!!! }
 | 
						||
 | 
						||
         { now we handle the parameters }
 | 
						||
         param := pparaitem(para^.first);
 | 
						||
         if assigned(param) then
 | 
						||
           while assigned(param) do
 | 
						||
             begin
 | 
						||
                s2:=getcppparaname(param^.paratype.def);
 | 
						||
                if param^.paratyp in [vs_var,vs_out] then
 | 
						||
                  s2:='R'+s2;
 | 
						||
                s:=s+s2;
 | 
						||
                param:=pparaitem(param^.next);
 | 
						||
             end
 | 
						||
         else
 | 
						||
           s:=s+'v';
 | 
						||
         cplusplusmangledname:=s;
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure tprocdef.setmangledname(const s : string);
 | 
						||
      begin
 | 
						||
         if assigned(_mangledname) then
 | 
						||
           begin
 | 
						||
{$ifdef MEMDEBUG}
 | 
						||
              dec(manglenamesize,length(_mangledname^));
 | 
						||
{$endif}
 | 
						||
              stringdispose(_mangledname);
 | 
						||
           end;
 | 
						||
         _mangledname:=stringdup(s);
 | 
						||
{$ifdef MEMDEBUG}
 | 
						||
         inc(manglenamesize,length(s));
 | 
						||
{$endif}
 | 
						||
{$ifdef EXTDEBUG}
 | 
						||
         if assigned(parast) then
 | 
						||
           begin
 | 
						||
              stringdispose(parast^.name);
 | 
						||
              parast^.name:=stringdup('args of '+s);
 | 
						||
           end;
 | 
						||
         if assigned(localst) then
 | 
						||
           begin
 | 
						||
              stringdispose(localst^.name);
 | 
						||
              localst^.name:=stringdup('locals of '+s);
 | 
						||
           end;
 | 
						||
{$endif}
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{***************************************************************************
 | 
						||
                                 TPROCVARDEF
 | 
						||
***************************************************************************}
 | 
						||
 | 
						||
    constructor tprocvardef.init;
 | 
						||
      begin
 | 
						||
         inherited init;
 | 
						||
         deftype:=procvardef;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor tprocvardef.load;
 | 
						||
      begin
 | 
						||
         inherited load;
 | 
						||
         deftype:=procvardef;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tprocvardef.write;
 | 
						||
      begin
 | 
						||
         { here we cannot get a real good value so just give something }
 | 
						||
         { plausible (PM) }
 | 
						||
         { a more secure way would be
 | 
						||
           to allways store in a temp }
 | 
						||
         if is_fpu(rettype.def) then
 | 
						||
           fpu_used:=2
 | 
						||
         else
 | 
						||
           fpu_used:=0;
 | 
						||
         inherited write;
 | 
						||
         current_ppu^.writeentry(ibprocvardef);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tprocvardef.size : longint;
 | 
						||
      begin
 | 
						||
         if (po_methodpointer in procoptions) then
 | 
						||
           size:=2*target_os.size_of_pointer
 | 
						||
         else
 | 
						||
           size:=target_os.size_of_pointer;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function tprocvardef.stabstring : pchar;
 | 
						||
      var
 | 
						||
         nss : pchar;
 | 
						||
        { i   : longint; }
 | 
						||
      begin
 | 
						||
        { i := maxparacount; }
 | 
						||
        getmem(nss,1024);
 | 
						||
        { it is not a function but a function pointer !! (PM) }
 | 
						||
 | 
						||
        strpcopy(nss,'*f'+rettype.def^.numberstring{+','+tostr(i)}+';');
 | 
						||
        { this confuses gdb !!
 | 
						||
          we should use 'F' instead of 'f' but
 | 
						||
          as we use c++ language mode
 | 
						||
          it does not like that either
 | 
						||
          Please do not remove this part
 | 
						||
          might be used once
 | 
						||
          gdb for pascal is ready PM }
 | 
						||
        (*
 | 
						||
        param := para1;
 | 
						||
        i := 0;
 | 
						||
        while assigned(param) do
 | 
						||
          begin
 | 
						||
          inc(i);
 | 
						||
                   vs_out  : paraspec := pfOut;
 | 
						||
          if param^.paratyp = vs_value then vartyp := '1' else vartyp := '0';
 | 
						||
          {Here we have lost the parameter names !!}
 | 
						||
          pst := strpnew('p'+tostr(i)+':'+param^.paratype.def^.numberstring+','+vartyp+';');
 | 
						||
          strcat(nss,pst);
 | 
						||
          strdispose(pst);
 | 
						||
          param := param^.next;
 | 
						||
          end; *)
 | 
						||
        {strpcopy(strend(nss),';');}
 | 
						||
        stabstring := strnew(nss);
 | 
						||
        freemem(nss,1024);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tprocvardef.concatstabto(asmlist : paasmoutput);
 | 
						||
      begin
 | 
						||
         if ( not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
 | 
						||
           and (is_def_stab_written = not_written)  then
 | 
						||
           inherited concatstabto(asmlist);
 | 
						||
         is_def_stab_written:=written;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    procedure tprocvardef.write_rtti_data;
 | 
						||
      var
 | 
						||
         pdc : pparaitem;
 | 
						||
         methodkind, paraspec : byte;
 | 
						||
      begin
 | 
						||
        if po_methodpointer in procoptions then
 | 
						||
          begin
 | 
						||
             { write method id and name }
 | 
						||
             rttilist^.concat(new(pai_const,init_8bit(tkmethod)));
 | 
						||
             write_rtti_name;
 | 
						||
 | 
						||
             { write kind of method (can only be function or procedure)}
 | 
						||
             if rettype.def = pdef(voiddef) then    { ### typecast shoudln't be necessary! (sg) }
 | 
						||
               methodkind := mkProcedure
 | 
						||
             else
 | 
						||
               methodkind := mkFunction;
 | 
						||
             rttilist^.concat(new(pai_const,init_8bit(methodkind)));
 | 
						||
 | 
						||
             { get # of parameters }
 | 
						||
             rttilist^.concat(new(pai_const,init_8bit(maxparacount)));
 | 
						||
 | 
						||
             { write parameter info. The parameters must be written in reverse order
 | 
						||
               if this method uses right to left parameter pushing! }
 | 
						||
             if (pocall_leftright in proccalloptions) then
 | 
						||
              pdc:=pparaitem(para^.last)
 | 
						||
             else
 | 
						||
              pdc:=pparaitem(para^.first);
 | 
						||
             while assigned(pdc) do
 | 
						||
               begin
 | 
						||
                 case pdc^.paratyp of
 | 
						||
                   vs_value: paraspec := 0;
 | 
						||
                   vs_const: paraspec := pfConst;
 | 
						||
                   vs_var  : paraspec := pfVar;
 | 
						||
                   vs_out  : paraspec := pfOut;
 | 
						||
                 end;
 | 
						||
                 { write flags for current parameter }
 | 
						||
                 rttilist^.concat(new(pai_const,init_8bit(paraspec)));
 | 
						||
                 { write name of current parameter ### how can I get this??? (sg)}
 | 
						||
                 rttilist^.concat(new(pai_const,init_8bit(0)));
 | 
						||
 | 
						||
                 { write name of type of current parameter }
 | 
						||
                 pdc^.paratype.def^.write_rtti_name;
 | 
						||
 | 
						||
                 if (pocall_leftright in proccalloptions) then
 | 
						||
                  pdc:=pparaitem(pdc^.previous)
 | 
						||
                 else
 | 
						||
                  pdc:=pparaitem(pdc^.next);
 | 
						||
               end;
 | 
						||
 | 
						||
             { write name of result type }
 | 
						||
             rettype.def^.write_rtti_name;
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tprocvardef.write_child_rtti_data;
 | 
						||
      begin
 | 
						||
         {!!!!!!!!}
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tprocvardef.is_publishable : boolean;
 | 
						||
      begin
 | 
						||
         is_publishable:=(po_methodpointer in procoptions);
 | 
						||
      end;
 | 
						||
 | 
						||
    function tprocvardef.gettypename : string;
 | 
						||
      begin
 | 
						||
         if assigned(rettype.def) and
 | 
						||
            (rettype.def<>pdef(voiddef)) then
 | 
						||
           gettypename:='<procedure variable type of function'+demangled_paras+
 | 
						||
             ':'+rettype.def^.gettypename+';'+proccalloption2str+'>'
 | 
						||
         else
 | 
						||
           gettypename:='<procedure variable type of procedure'+demangled_paras+
 | 
						||
             ';'+proccalloption2str+'>';
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{***************************************************************************
 | 
						||
                              TOBJECTDEF
 | 
						||
***************************************************************************}
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    const
 | 
						||
       vtabletype : word = 0;
 | 
						||
       vtableassigned : boolean = false;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
   constructor tobjectdef.init(odt : tobjectdeftype; const n : string;c : pobjectdef);
 | 
						||
     begin
 | 
						||
        tdef.init;
 | 
						||
        deftype:=objectdef;
 | 
						||
        objecttype:=odt;
 | 
						||
        objectoptions:=[];
 | 
						||
        childof:=nil;
 | 
						||
        symtable:=new(psymtable,init(objectsymtable));
 | 
						||
        symtable^.name := stringdup(n);
 | 
						||
        { create space for vmt !! }
 | 
						||
        vmt_offset:=0;
 | 
						||
        symtable^.datasize:=0;
 | 
						||
        symtable^.defowner:=@self;
 | 
						||
        symtable^.dataalignment:=packrecordalignment[aktpackrecords];
 | 
						||
 | 
						||
        set_parent(c);
 | 
						||
        objname:=stringdup(n);
 | 
						||
        lastvtableindex:=0;
 | 
						||
 | 
						||
        { set up guid }
 | 
						||
        isiidguidvalid:=true; { default null guid }
 | 
						||
        fillchar(iidguid,sizeof(iidguid),0); { default null guid }
 | 
						||
        iidstr:=stringdup(''); { default is empty string }
 | 
						||
 | 
						||
        { set<EFBFBD>p implemented interfaces }
 | 
						||
        if objecttype in [odt_class,odt_interfacecorba] then
 | 
						||
          new(implementedinterfaces,init)
 | 
						||
        else
 | 
						||
          implementedinterfaces:=nil;
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
        writing_stabs:=false;
 | 
						||
        classglobalnb:=0;
 | 
						||
        classptrglobalnb:=0;
 | 
						||
{$endif GDB}
 | 
						||
     end;
 | 
						||
 | 
						||
 | 
						||
    constructor tobjectdef.load;
 | 
						||
      var
 | 
						||
         oldread_member : boolean;
 | 
						||
         implintfcount: longint;
 | 
						||
         i: longint;
 | 
						||
      begin
 | 
						||
         tdef.load;
 | 
						||
         deftype:=objectdef;
 | 
						||
         objecttype:=tobjectdeftype(readbyte);
 | 
						||
         savesize:=readlong;
 | 
						||
         vmt_offset:=readlong;
 | 
						||
         objname:=stringdup(readstring);
 | 
						||
         childof:=pobjectdef(readdefref);
 | 
						||
         readsmallset(objectoptions,sizeof(objectoptions));
 | 
						||
         has_rtti:=boolean(readbyte);
 | 
						||
 | 
						||
         { load guid }
 | 
						||
         iidstr:=nil;
 | 
						||
         if objecttype in [odt_interfacecom,odt_interfacecorba] then
 | 
						||
           begin
 | 
						||
              isiidguidvalid:=boolean(readbyte);
 | 
						||
              readguid(iidguid);
 | 
						||
              iidstr:=stringdup(readstring);
 | 
						||
              lastvtableindex:=readlong;
 | 
						||
           end;
 | 
						||
 | 
						||
         { load implemented interfaces }
 | 
						||
         if objecttype in [odt_class,odt_interfacecorba] then
 | 
						||
           begin
 | 
						||
             new(implementedinterfaces,init);
 | 
						||
             implintfcount:=readlong;
 | 
						||
             for i:=1 to implintfcount do
 | 
						||
               begin
 | 
						||
                  implementedinterfaces^.addintfref(readdefref);
 | 
						||
                  implementedinterfaces^.ioffsets(i)^:=readlong;
 | 
						||
               end;
 | 
						||
           end
 | 
						||
         else
 | 
						||
           implementedinterfaces:=nil;
 | 
						||
 | 
						||
         oldread_member:=read_member;
 | 
						||
         read_member:=true;
 | 
						||
         symtable:=new(psymtable,loadas(objectsymtable));
 | 
						||
         read_member:=oldread_member;
 | 
						||
 | 
						||
         symtable^.defowner:=@self;
 | 
						||
         symtable^.name := stringdup(objname^);
 | 
						||
 | 
						||
         { handles the predefined class tobject  }
 | 
						||
         { the last TOBJECT which is loaded gets }
 | 
						||
         { it !                                  }
 | 
						||
         if (childof=nil) and
 | 
						||
            (objecttype=odt_class) and
 | 
						||
            (upper(objname^)='TOBJECT') then
 | 
						||
           class_tobject:=@self;
 | 
						||
         if (childof=nil) and (objecttype=odt_interfacecom) and
 | 
						||
           (objname^='IUNKNOWN') then
 | 
						||
           interface_iunknown:=@self;
 | 
						||
{$ifdef GDB}
 | 
						||
         writing_stabs:=false;
 | 
						||
         classglobalnb:=0;
 | 
						||
         classptrglobalnb:=0;
 | 
						||
{$endif GDB}
 | 
						||
       end;
 | 
						||
 | 
						||
 | 
						||
   destructor tobjectdef.done;
 | 
						||
     begin
 | 
						||
        if assigned(symtable) then
 | 
						||
          dispose(symtable,done);
 | 
						||
        if (oo_is_forward in objectoptions) then
 | 
						||
          Message1(sym_e_class_forward_not_resolved,objname^);
 | 
						||
        stringdispose(objname);
 | 
						||
        stringdispose(iidstr);
 | 
						||
        if assigned(implementedinterfaces) then
 | 
						||
          dispose(implementedinterfaces,done);
 | 
						||
        tdef.done;
 | 
						||
     end;
 | 
						||
 | 
						||
 | 
						||
    procedure tobjectdef.write;
 | 
						||
      var
 | 
						||
         oldread_member : boolean;
 | 
						||
         implintfcount : longint;
 | 
						||
         i : longint;
 | 
						||
      begin
 | 
						||
         tdef.write;
 | 
						||
         writebyte(ord(objecttype));
 | 
						||
         writelong(size);
 | 
						||
         writelong(vmt_offset);
 | 
						||
         writestring(objname^);
 | 
						||
         writedefref(childof);
 | 
						||
         writesmallset(objectoptions,sizeof(objectoptions));
 | 
						||
         writebyte(byte(has_rtti));
 | 
						||
         if objecttype in [odt_interfacecom,odt_interfacecorba] then
 | 
						||
           begin
 | 
						||
              writebyte(byte(isiidguidvalid));
 | 
						||
              writeguid(iidguid);
 | 
						||
              writestring(iidstr^);
 | 
						||
              writelong(lastvtableindex);
 | 
						||
           end;
 | 
						||
 | 
						||
         if objecttype in [odt_class,odt_interfacecorba] then
 | 
						||
           begin
 | 
						||
              implintfcount:=implementedinterfaces^.count;
 | 
						||
              writelong(implintfcount);
 | 
						||
              for i:=1 to implintfcount do
 | 
						||
                begin
 | 
						||
                   writedefref(implementedinterfaces^.interfaces(i));
 | 
						||
                   writelong(implementedinterfaces^.ioffsets(i)^);
 | 
						||
                end;
 | 
						||
           end;
 | 
						||
 | 
						||
         current_ppu^.writeentry(ibobjectdef);
 | 
						||
 | 
						||
         oldread_member:=read_member;
 | 
						||
         read_member:=true;
 | 
						||
         symtable^.writeas;
 | 
						||
         read_member:=oldread_member;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tobjectdef.deref;
 | 
						||
      var
 | 
						||
         oldrecsyms : psymtable;
 | 
						||
      begin
 | 
						||
         inherited deref;
 | 
						||
         resolvedef(pdef(childof));
 | 
						||
         oldrecsyms:=aktrecordsymtable;
 | 
						||
         aktrecordsymtable:=symtable;
 | 
						||
         symtable^.deref;
 | 
						||
         aktrecordsymtable:=oldrecsyms;
 | 
						||
         if objecttype in [odt_class,odt_interfacecorba] then
 | 
						||
           implementedinterfaces^.deref;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tobjectdef.set_parent( c : pobjectdef);
 | 
						||
      begin
 | 
						||
        { nothing to do if the parent was not forward !}
 | 
						||
        if assigned(childof) then
 | 
						||
          exit;
 | 
						||
        childof:=c;
 | 
						||
        { some options are inherited !! }
 | 
						||
        if assigned(c) then
 | 
						||
          begin
 | 
						||
             { only important for classes }
 | 
						||
             lastvtableindex:=c^.lastvtableindex;
 | 
						||
             objectoptions:=objectoptions+(c^.objectoptions*
 | 
						||
               [oo_has_virtual,oo_has_private,oo_has_protected,oo_has_constructor,oo_has_destructor]);
 | 
						||
             if not (objecttype in [odt_interfacecom,odt_interfacecorba]) then
 | 
						||
               begin
 | 
						||
                  { add the data of the anchestor class }
 | 
						||
                  inc(symtable^.datasize,c^.symtable^.datasize);
 | 
						||
                  if (oo_has_vmt in objectoptions) and
 | 
						||
                     (oo_has_vmt in c^.objectoptions) then
 | 
						||
                    dec(symtable^.datasize,target_os.size_of_pointer);
 | 
						||
                  { if parent has a vmt field then
 | 
						||
                    the offset is the same for the child PM }
 | 
						||
                  if (oo_has_vmt in c^.objectoptions) or is_class(@self) then
 | 
						||
                    begin
 | 
						||
                       vmt_offset:=c^.vmt_offset;
 | 
						||
                       include(objectoptions,oo_has_vmt);
 | 
						||
                    end;
 | 
						||
               end;
 | 
						||
          end;
 | 
						||
        savesize := symtable^.datasize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
   procedure tobjectdef.insertvmt;
 | 
						||
     begin
 | 
						||
        if objecttype in [odt_interfacecom,odt_interfacecorba] then exit;
 | 
						||
        if (oo_has_vmt in objectoptions) then
 | 
						||
          internalerror(12345)
 | 
						||
        else
 | 
						||
          begin
 | 
						||
             { first round up to multiple of 4 }
 | 
						||
             if (symtable^.dataalignment=2) then
 | 
						||
               begin
 | 
						||
                 if (symtable^.datasize and 1)<>0 then
 | 
						||
                   inc(symtable^.datasize);
 | 
						||
               end
 | 
						||
             else
 | 
						||
              if (symtable^.dataalignment>=4) then
 | 
						||
               begin
 | 
						||
                 if (symtable^.datasize mod 4) <> 0 then
 | 
						||
                   inc(symtable^.datasize,4-(symtable^.datasize mod 4));
 | 
						||
               end;
 | 
						||
             vmt_offset:=symtable^.datasize;
 | 
						||
             inc(symtable^.datasize,target_os.size_of_pointer);
 | 
						||
             include(objectoptions,oo_has_vmt);
 | 
						||
          end;
 | 
						||
     end;
 | 
						||
 | 
						||
 | 
						||
   procedure tobjectdef.check_forwards;
 | 
						||
     begin
 | 
						||
        if objecttype in [odt_interfacecom,odt_interfacecorba] then exit; { Kaz: ??? }
 | 
						||
        symtable^.check_forwards;
 | 
						||
        if (oo_is_forward in objectoptions) then
 | 
						||
          begin
 | 
						||
             { ok, in future, the forward can be resolved }
 | 
						||
             Message1(sym_e_class_forward_not_resolved,objname^);
 | 
						||
             exclude(objectoptions,oo_is_forward);
 | 
						||
          end;
 | 
						||
     end;
 | 
						||
 | 
						||
 | 
						||
   { true, if self inherits from d (or if they are equal) }
 | 
						||
   function tobjectdef.is_related(d : pobjectdef) : boolean;
 | 
						||
     var
 | 
						||
        hp : pobjectdef;
 | 
						||
     begin
 | 
						||
        hp:=@self;
 | 
						||
        while assigned(hp) do
 | 
						||
          begin
 | 
						||
             if hp=d then
 | 
						||
               begin
 | 
						||
                  is_related:=true;
 | 
						||
                  exit;
 | 
						||
               end;
 | 
						||
             hp:=hp^.childof;
 | 
						||
          end;
 | 
						||
        is_related:=false;
 | 
						||
     end;
 | 
						||
 | 
						||
   var
 | 
						||
      sd : pprocdef;
 | 
						||
 | 
						||
   procedure _searchdestructor(sym : pnamedindexobject);
 | 
						||
 | 
						||
     var
 | 
						||
        p : pprocdef;
 | 
						||
 | 
						||
     begin
 | 
						||
        { if we found already a destructor, then we exit }
 | 
						||
        if assigned(sd) then
 | 
						||
          exit;
 | 
						||
        if psym(sym)^.typ=procsym then
 | 
						||
          begin
 | 
						||
             p:=pprocsym(sym)^.definition;
 | 
						||
             while assigned(p) do
 | 
						||
               begin
 | 
						||
                  if p^.proctypeoption=potype_destructor then
 | 
						||
                    begin
 | 
						||
                       sd:=p;
 | 
						||
                       exit;
 | 
						||
                    end;
 | 
						||
                  p:=p^.nextoverloaded;
 | 
						||
               end;
 | 
						||
          end;
 | 
						||
     end;
 | 
						||
 | 
						||
   function tobjectdef.searchdestructor : pprocdef;
 | 
						||
 | 
						||
     var
 | 
						||
        o : pobjectdef;
 | 
						||
 | 
						||
     begin
 | 
						||
        searchdestructor:=nil;
 | 
						||
        o:=@self;
 | 
						||
        sd:=nil;
 | 
						||
        while assigned(o) do
 | 
						||
          begin
 | 
						||
             symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}_searchdestructor);
 | 
						||
             if assigned(sd) then
 | 
						||
               begin
 | 
						||
                  searchdestructor:=sd;
 | 
						||
                  exit;
 | 
						||
               end;
 | 
						||
             o:=o^.childof;
 | 
						||
          end;
 | 
						||
     end;
 | 
						||
 | 
						||
    function tobjectdef.size : longint;
 | 
						||
      begin
 | 
						||
        if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba] then
 | 
						||
          size:=target_os.size_of_pointer
 | 
						||
        else
 | 
						||
          size:=symtable^.datasize;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tobjectdef.alignment:longint;
 | 
						||
      begin
 | 
						||
        alignment:=symtable^.dataalignment;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tobjectdef.vmtmethodoffset(index:longint):longint;
 | 
						||
      begin
 | 
						||
        { for offset of methods for classes, see rtl/inc/objpash.inc }
 | 
						||
        if objecttype in [odt_interfacecom,odt_interfacecorba] then
 | 
						||
          vmtmethodoffset:=index*target_os.size_of_pointer
 | 
						||
        else if (objecttype=odt_class) then
 | 
						||
           vmtmethodoffset:=(index+12)*target_os.size_of_pointer
 | 
						||
        else
 | 
						||
{$ifdef WITHDMT}
 | 
						||
         vmtmethodoffset:=(index+4)*target_os.size_of_pointer;
 | 
						||
{$else WITHDMT}
 | 
						||
         vmtmethodoffset:=(index+3)*target_os.size_of_pointer;
 | 
						||
{$endif WITHDMT}
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tobjectdef.vmt_mangledname : string;
 | 
						||
    {DM: I get a nil pointer on the owner name. I don't know if this
 | 
						||
     may happen, and I have therefore fixed the problem by doing nil pointer
 | 
						||
     checks.}
 | 
						||
    var
 | 
						||
      s1,s2:string;
 | 
						||
    begin
 | 
						||
        if not(oo_has_vmt in objectoptions) then
 | 
						||
          Message1(parser_object_has_no_vmt,objname^);
 | 
						||
        if owner^.name=nil then
 | 
						||
          s1:=''
 | 
						||
        else
 | 
						||
          s1:=owner^.name^;
 | 
						||
        if objname=nil then
 | 
						||
          s2:=''
 | 
						||
        else
 | 
						||
          s2:=Upper(objname^);
 | 
						||
        vmt_mangledname:='VMT_'+s1+'$_'+s2;
 | 
						||
    end;
 | 
						||
 | 
						||
 | 
						||
    function tobjectdef.rtti_name : string;
 | 
						||
    var
 | 
						||
      s1,s2:string;
 | 
						||
    begin
 | 
						||
       if owner^.name=nil then
 | 
						||
         s1:=''
 | 
						||
       else
 | 
						||
         s1:=owner^.name^;
 | 
						||
       if objname=nil then
 | 
						||
         s2:=''
 | 
						||
       else
 | 
						||
         s2:=Upper(objname^);
 | 
						||
       rtti_name:='RTTI_'+s1+'$_'+s2;
 | 
						||
    end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    procedure addprocname(p :pnamedindexobject);
 | 
						||
    var virtualind,argnames : string;
 | 
						||
        news, newrec : pchar;
 | 
						||
        pd,ipd : pprocdef;
 | 
						||
        lindex : longint;
 | 
						||
        para : pparaitem;
 | 
						||
        arglength : byte;
 | 
						||
        sp : char;
 | 
						||
 | 
						||
    begin
 | 
						||
      If psym(p)^.typ = procsym then
 | 
						||
       begin
 | 
						||
                pd := pprocsym(p)^.definition;
 | 
						||
                { this will be used for full implementation of object stabs
 | 
						||
                not yet done }
 | 
						||
                ipd := pd;
 | 
						||
                while assigned(ipd^.nextoverloaded) do ipd := ipd^.nextoverloaded;
 | 
						||
                if (po_virtualmethod in pd^.procoptions) then
 | 
						||
                  begin
 | 
						||
                    lindex := pd^.extnumber;
 | 
						||
                    {doesnt seem to be necessary
 | 
						||
                    lindex := lindex or $80000000;}
 | 
						||
                    virtualind := '*'+tostr(lindex)+';'+ipd^._class^.classnumberstring+';'
 | 
						||
                  end
 | 
						||
                 else
 | 
						||
                  virtualind := '.';
 | 
						||
 | 
						||
                 { used by gdbpas to recognize constructor and destructors }
 | 
						||
                 if (pd^.proctypeoption=potype_constructor) then
 | 
						||
                   argnames:='__ct__'
 | 
						||
                 else if (pd^.proctypeoption=potype_destructor) then
 | 
						||
                   argnames:='__dt__'
 | 
						||
                 else
 | 
						||
                   argnames := '';
 | 
						||
 | 
						||
                { arguments are not listed here }
 | 
						||
                {we don't need another definition}
 | 
						||
                 para := pparaitem(pd^.para^.first);
 | 
						||
                 while assigned(para) do
 | 
						||
                   begin
 | 
						||
                   if para^.paratype.def^.deftype = formaldef then
 | 
						||
                     begin
 | 
						||
                        if para^.paratyp=vs_out then
 | 
						||
                          argnames := argnames+'3out'
 | 
						||
                        else if para^.paratyp=vs_var then
 | 
						||
                          argnames := argnames+'3var'
 | 
						||
                        else if para^.paratyp=vs_const then
 | 
						||
                          argnames:=argnames+'5const'
 | 
						||
                        else if para^.paratyp=vs_out then
 | 
						||
                          argnames:=argnames+'3out';
 | 
						||
                     end
 | 
						||
                   else
 | 
						||
                     begin
 | 
						||
                     { if the arg definition is like (v: ^byte;..
 | 
						||
                     there is no sym attached to data !!! }
 | 
						||
                     if assigned(para^.paratype.def^.typesym) then
 | 
						||
                       begin
 | 
						||
                          arglength := length(para^.paratype.def^.typesym^.name);
 | 
						||
                          argnames := argnames + tostr(arglength)+para^.paratype.def^.typesym^.name;
 | 
						||
                       end
 | 
						||
                     else
 | 
						||
                       begin
 | 
						||
                          argnames:=argnames+'11unnamedtype';
 | 
						||
                       end;
 | 
						||
                     end;
 | 
						||
                   para := pparaitem(para^.next);
 | 
						||
                   end;
 | 
						||
                ipd^.is_def_stab_written := written;
 | 
						||
                { here 2A must be changed for private and protected }
 | 
						||
                { 0 is private 1 protected and 2 public }
 | 
						||
                if (sp_private in psym(p)^.symoptions) then sp:='0'
 | 
						||
                else if (sp_protected in psym(p)^.symoptions) then sp:='1'
 | 
						||
                else sp:='2';
 | 
						||
                newrec := strpnew(p^.name+'::'+ipd^.numberstring
 | 
						||
                     +'=##'+pd^.rettype.def^.numberstring+';:'+argnames+';'+sp+'A'
 | 
						||
                     +virtualind+';');
 | 
						||
               { get spare place for a string at the end }
 | 
						||
               if strlen(StabRecString) + strlen(newrec) >= StabRecSize-256 then
 | 
						||
                 begin
 | 
						||
                    getmem(news,stabrecsize+memsizeinc);
 | 
						||
                    strcopy(news,stabrecstring);
 | 
						||
                    freemem(stabrecstring,stabrecsize);
 | 
						||
                    stabrecsize:=stabrecsize+memsizeinc;
 | 
						||
                    stabrecstring:=news;
 | 
						||
                 end;
 | 
						||
               strcat(StabRecstring,newrec);
 | 
						||
               {freemem(newrec,memsizeinc);    }
 | 
						||
               strdispose(newrec);
 | 
						||
               {This should be used for case !!}
 | 
						||
               RecOffset := RecOffset + pd^.size;
 | 
						||
       end;
 | 
						||
    end;
 | 
						||
 | 
						||
 | 
						||
    function tobjectdef.stabstring : pchar;
 | 
						||
      var anc : pobjectdef;
 | 
						||
          oldrec : pchar;
 | 
						||
          storenb, oldrecsize : longint;
 | 
						||
          str_end : string;
 | 
						||
      begin
 | 
						||
        if not (is_class(@self)) or writing_stabs then
 | 
						||
          begin
 | 
						||
            storenb:=globalnb;
 | 
						||
            globalnb:=classptrglobalnb;
 | 
						||
            oldrec := stabrecstring;
 | 
						||
            oldrecsize:=stabrecsize;
 | 
						||
            stabrecsize:=memsizeinc;
 | 
						||
            GetMem(stabrecstring,stabrecsize);
 | 
						||
            strpcopy(stabRecString,'s'+tostr(symtable^.datasize));
 | 
						||
            if assigned(childof) then
 | 
						||
              begin
 | 
						||
                {only one ancestor not virtual, public, at base offset 0 }
 | 
						||
                {       !1           ,    0       2         0    ,       }
 | 
						||
                strpcopy(strend(stabrecstring),'!1,020,'+childof^.classnumberstring+';');
 | 
						||
              end;
 | 
						||
            {virtual table to implement yet}
 | 
						||
            RecOffset := 0;
 | 
						||
            symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}addname);
 | 
						||
            if (oo_has_vmt in objectoptions) then
 | 
						||
              if not assigned(childof) or not(oo_has_vmt in childof^.objectoptions) then
 | 
						||
                 begin
 | 
						||
                    strpcopy(strend(stabrecstring),'$vf'+classnumberstring+':'+typeglobalnumber('vtblarray')
 | 
						||
                      +','+tostr(vmt_offset*8)+';');
 | 
						||
                 end;
 | 
						||
            symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}addprocname);
 | 
						||
            if (oo_has_vmt in objectoptions) then
 | 
						||
              begin
 | 
						||
                 anc := @self;
 | 
						||
                 while assigned(anc^.childof) and (oo_has_vmt in anc^.childof^.objectoptions) do
 | 
						||
                   anc := anc^.childof;
 | 
						||
                 { just in case anc = self }
 | 
						||
                 str_end:=';~%'+anc^.classnumberstring+';';
 | 
						||
              end
 | 
						||
            else
 | 
						||
              str_end:=';';
 | 
						||
            strpcopy(strend(stabrecstring),str_end);
 | 
						||
            stabstring := strnew(StabRecString);
 | 
						||
            freemem(stabrecstring,stabrecsize);
 | 
						||
            stabrecstring := oldrec;
 | 
						||
            stabrecsize:=oldrecsize;
 | 
						||
            globalnb:=storenb;
 | 
						||
          end
 | 
						||
        else
 | 
						||
          begin
 | 
						||
            stabstring:=strpnew('*'+classnumberstring);
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
   procedure tobjectdef.set_globalnb;
 | 
						||
     begin
 | 
						||
         classglobalnb:=PGlobalTypeCount^;
 | 
						||
         globalnb:=classglobalnb;
 | 
						||
         inc(PglobalTypeCount^);
 | 
						||
         { classes need two type numbers, the globalnb is set to the ptr }
 | 
						||
         if objecttype=odt_class then
 | 
						||
           begin
 | 
						||
             classptrglobalnb:=PGlobalTypeCount^;
 | 
						||
             globalnb:=classptrglobalnb;
 | 
						||
             inc(PglobalTypeCount^);
 | 
						||
           end;
 | 
						||
     end;
 | 
						||
 | 
						||
   function tobjectdef.classnumberstring : string;
 | 
						||
     var
 | 
						||
       onb : word;
 | 
						||
     begin
 | 
						||
       if globalnb=0 then
 | 
						||
         numberstring;
 | 
						||
       if objecttype=odt_class then
 | 
						||
         begin
 | 
						||
           onb:=globalnb;
 | 
						||
           globalnb:=classglobalnb;
 | 
						||
           classnumberstring:=numberstring;
 | 
						||
           globalnb:=onb;
 | 
						||
         end
 | 
						||
       else
 | 
						||
         classnumberstring:=numberstring;
 | 
						||
     end;
 | 
						||
 | 
						||
   function tobjectdef.classptrnumberstring : string;
 | 
						||
     var
 | 
						||
       onb : word;
 | 
						||
     begin
 | 
						||
       if globalnb=0 then
 | 
						||
         numberstring;
 | 
						||
       if objecttype=odt_class then
 | 
						||
         begin
 | 
						||
           onb:=globalnb;
 | 
						||
           globalnb:=classptrglobalnb;
 | 
						||
           classptrnumberstring:=numberstring;
 | 
						||
           globalnb:=onb;
 | 
						||
         end
 | 
						||
       else
 | 
						||
         classptrnumberstring:=numberstring;
 | 
						||
     end;
 | 
						||
 | 
						||
    procedure tobjectdef.concatstabto(asmlist : paasmoutput);
 | 
						||
      var st : pstring;
 | 
						||
      begin
 | 
						||
        if not(objecttype=odt_class) then
 | 
						||
          begin
 | 
						||
            inherited concatstabto(asmlist);
 | 
						||
            exit;
 | 
						||
          end;
 | 
						||
 | 
						||
      if ((typesym=nil) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
 | 
						||
         (is_def_stab_written = not_written) then
 | 
						||
        begin
 | 
						||
          if globalnb=0 then
 | 
						||
            set_globalnb;
 | 
						||
          { Write the record class itself }
 | 
						||
          writing_stabs:=true;
 | 
						||
          if assigned(typesym) then
 | 
						||
            begin
 | 
						||
              st:=typesym^._name;
 | 
						||
              typesym^._name:=stringdup(' ');
 | 
						||
            end;
 | 
						||
          globalnb:=classglobalnb;
 | 
						||
          inherited concatstabto(asmlist);
 | 
						||
          if assigned(typesym) then
 | 
						||
            begin
 | 
						||
              stringdispose(typesym^._name);
 | 
						||
              typesym^._name:=st;
 | 
						||
            end;
 | 
						||
          globalnb:=classptrglobalnb;
 | 
						||
          writing_stabs:=false;
 | 
						||
          { Write the invisible pointer class }
 | 
						||
          is_def_stab_written:=not_written;
 | 
						||
          inherited concatstabto(asmlist);
 | 
						||
        end;
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
 | 
						||
    procedure tobjectdef.write_child_init_data;
 | 
						||
      begin
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}generate_child_inittable);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tobjectdef.write_init_data;
 | 
						||
      begin
 | 
						||
         case objecttype of
 | 
						||
            odt_class:
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkclass)));
 | 
						||
            odt_object:
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkobject)));
 | 
						||
            odt_interfacecom:
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkinterface)));
 | 
						||
            odt_interfacecorba:
 | 
						||
              rttilist^.concat(new(pai_const,init_8bit(tkinterfaceCorba)));
 | 
						||
          else
 | 
						||
            exit;
 | 
						||
          end;
 | 
						||
 | 
						||
         { generate the name }
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(length(objname^))));
 | 
						||
         rttilist^.concat(new(pai_string,init(objname^)));
 | 
						||
 | 
						||
         rttilist^.concat(new(pai_const,init_32bit(size)));
 | 
						||
         count:=0;
 | 
						||
         if objecttype in [odt_interfacecom,odt_interfacecorba] then
 | 
						||
           begin
 | 
						||
           end
 | 
						||
         else
 | 
						||
           begin
 | 
						||
              symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}count_inittable_fields);
 | 
						||
              rttilist^.concat(new(pai_const,init_32bit(count)));
 | 
						||
              symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}write_field_inittable);
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tobjectdef.needs_inittable : boolean;
 | 
						||
      var
 | 
						||
         oldb : boolean;
 | 
						||
      begin
 | 
						||
         case objecttype of
 | 
						||
            odt_interfacecom: needs_inittable:=true;
 | 
						||
            odt_object:
 | 
						||
              begin
 | 
						||
                 { there are recursive calls to needs_inittable possible, }
 | 
						||
                 { so we have to change to old value how else should      }
 | 
						||
                 { we do that ? check_rec_rtti can't be a nested          }
 | 
						||
                 { procedure of needs_rtti !                              }
 | 
						||
                 oldb:=binittable;
 | 
						||
                 binittable:=false;
 | 
						||
                 symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}check_rec_inittable);
 | 
						||
                 needs_inittable:=binittable;
 | 
						||
                 binittable:=oldb;
 | 
						||
              end;
 | 
						||
            else needs_inittable:=false;
 | 
						||
         end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure count_published_properties(sym:pnamedindexobject);
 | 
						||
      begin
 | 
						||
         if needs_prop_entry(psym(sym)) and
 | 
						||
          (psym(sym)^.typ<>varsym) then
 | 
						||
           inc(count);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure write_property_info(sym : pnamedindexobject);
 | 
						||
      var
 | 
						||
         proctypesinfo : byte;
 | 
						||
 | 
						||
      procedure writeproc(proc : psymlist; shiftvalue : byte);
 | 
						||
 | 
						||
        var
 | 
						||
           typvalue : byte;
 | 
						||
           hp : psymlistitem;
 | 
						||
           address : longint;
 | 
						||
 | 
						||
        begin
 | 
						||
           if not(assigned(proc) and assigned(proc^.firstsym))  then
 | 
						||
             begin
 | 
						||
                rttilist^.concat(new(pai_const,init_32bit(1)));
 | 
						||
                typvalue:=3;
 | 
						||
             end
 | 
						||
           else if proc^.firstsym^.sym^.typ=varsym then
 | 
						||
             begin
 | 
						||
                address:=0;
 | 
						||
                hp:=proc^.firstsym;
 | 
						||
                while assigned(hp) do
 | 
						||
                  begin
 | 
						||
                     inc(address,pvarsym(hp^.sym)^.address);
 | 
						||
                     hp:=hp^.next;
 | 
						||
                  end;
 | 
						||
                rttilist^.concat(new(pai_const,init_32bit(address)));
 | 
						||
                typvalue:=0;
 | 
						||
             end
 | 
						||
           else
 | 
						||
             begin
 | 
						||
                if not(po_virtualmethod in pprocdef(proc^.def)^.procoptions) then
 | 
						||
                  begin
 | 
						||
                     rttilist^.concat(new(pai_const_symbol,initname(pprocdef(proc^.def)^.mangledname)));
 | 
						||
                     typvalue:=1;
 | 
						||
                  end
 | 
						||
                else
 | 
						||
                  begin
 | 
						||
                     { virtual method, write vmt offset }
 | 
						||
                     rttilist^.concat(new(pai_const,init_32bit(
 | 
						||
                       pprocdef(proc^.def)^._class^.vmtmethodoffset(pprocdef(proc^.def)^.extnumber))));
 | 
						||
                     typvalue:=2;
 | 
						||
                  end;
 | 
						||
             end;
 | 
						||
           proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
 | 
						||
        end;
 | 
						||
 | 
						||
      begin
 | 
						||
         if needs_prop_entry(psym(sym)) then
 | 
						||
           case psym(sym)^.typ of
 | 
						||
              varsym:
 | 
						||
                begin
 | 
						||
{$ifdef dummy}
 | 
						||
                   if not(pvarsym(sym)^.vartype.def^.deftype=objectdef) or
 | 
						||
                     not(pobjectdef(pvarsym(sym)^.vartype.def)^.is_class) then
 | 
						||
                     internalerror(1509992);
 | 
						||
                   { access to implicit class property as field }
 | 
						||
                   proctypesinfo:=(0 shl 0) or (0 shl 2) or (0 shl 4);
 | 
						||
                   rttilist^.concat(new(pai_const_symbol,initname(pvarsym(sym)^.vartype.def^.get_rtti_label)));
 | 
						||
                   rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
 | 
						||
                   rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
 | 
						||
                   { per default stored }
 | 
						||
                   rttilist^.concat(new(pai_const,init_32bit(1)));
 | 
						||
                   { index as well as ... }
 | 
						||
                   rttilist^.concat(new(pai_const,init_32bit(0)));
 | 
						||
                   { default value are zero }
 | 
						||
                   rttilist^.concat(new(pai_const,init_32bit(0)));
 | 
						||
                   rttilist^.concat(new(pai_const,init_16bit(count)));
 | 
						||
                   inc(count);
 | 
						||
                   rttilist^.concat(new(pai_const,init_8bit(proctypesinfo)));
 | 
						||
                   rttilist^.concat(new(pai_const,init_8bit(length(pvarsym(sym)^.realname))));
 | 
						||
                   rttilist^.concat(new(pai_string,init(pvarsym(sym)^.realname)));
 | 
						||
{$endif dummy}
 | 
						||
                end;
 | 
						||
              propertysym:
 | 
						||
                begin
 | 
						||
                   if ppo_indexed in ppropertysym(sym)^.propoptions then
 | 
						||
                     proctypesinfo:=$40
 | 
						||
                   else
 | 
						||
                     proctypesinfo:=0;
 | 
						||
                   rttilist^.concat(new(pai_const_symbol,initname(ppropertysym(sym)^.proptype.def^.get_rtti_label)));
 | 
						||
                   writeproc(ppropertysym(sym)^.readaccess,0);
 | 
						||
                   writeproc(ppropertysym(sym)^.writeaccess,2);
 | 
						||
                   { isn't it stored ? }
 | 
						||
                   if not(ppo_stored in ppropertysym(sym)^.propoptions) then
 | 
						||
                     begin
 | 
						||
                        rttilist^.concat(new(pai_const,init_32bit(0)));
 | 
						||
                        proctypesinfo:=proctypesinfo or (3 shl 4);
 | 
						||
                     end
 | 
						||
                   else
 | 
						||
                     writeproc(ppropertysym(sym)^.storedaccess,4);
 | 
						||
                   rttilist^.concat(new(pai_const,init_32bit(ppropertysym(sym)^.index)));
 | 
						||
                   rttilist^.concat(new(pai_const,init_32bit(ppropertysym(sym)^.default)));
 | 
						||
                   rttilist^.concat(new(pai_const,init_16bit(count)));
 | 
						||
                   inc(count);
 | 
						||
                   rttilist^.concat(new(pai_const,init_8bit(proctypesinfo)));
 | 
						||
                   rttilist^.concat(new(pai_const,init_8bit(length(ppropertysym(sym)^.realname))));
 | 
						||
                   rttilist^.concat(new(pai_string,init(ppropertysym(sym)^.realname)));
 | 
						||
                end;
 | 
						||
              else internalerror(1509992);
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure generate_published_child_rtti(sym : pnamedindexobject);
 | 
						||
      begin
 | 
						||
         if needs_prop_entry(psym(sym)) then
 | 
						||
           case psym(sym)^.typ of
 | 
						||
              varsym:
 | 
						||
                ;
 | 
						||
                { now ignored:
 | 
						||
                ;
 | 
						||
                { now ignored
 | 
						||
                pvarsym(sym)^.vartype.def^.get_rtti_label;
 | 
						||
                }
 | 
						||
                }
 | 
						||
              propertysym:
 | 
						||
                ppropertysym(sym)^.proptype.def^.get_rtti_label;
 | 
						||
              else
 | 
						||
                internalerror(1509991);
 | 
						||
           end;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tobjectdef.write_child_rtti_data;
 | 
						||
      begin
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}generate_published_child_rtti);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tobjectdef.generate_rtti;
 | 
						||
      begin
 | 
						||
         if not has_rtti then
 | 
						||
          begin
 | 
						||
            has_rtti:=true;
 | 
						||
            getdatalabel(rtti_label);
 | 
						||
            write_child_rtti_data;
 | 
						||
            rttilist^.concat(new(pai_symbol,initname_global(rtti_name,0)));
 | 
						||
            rttilist^.concat(new(pai_label,init(rtti_label)));
 | 
						||
            write_rtti_data;
 | 
						||
            rttilist^.concat(new(pai_symbol_end,initname(rtti_name)));
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
    type
 | 
						||
       tclasslistitem = object(tlinkedlist_item)
 | 
						||
          index : longint;
 | 
						||
          p : pobjectdef;
 | 
						||
       end;
 | 
						||
       pclasslistitem = ^tclasslistitem;
 | 
						||
 | 
						||
    var
 | 
						||
       classtablelist : tlinkedlist;
 | 
						||
       tablecount : longint;
 | 
						||
 | 
						||
    function searchclasstablelist(p : pobjectdef) : pclasslistitem;
 | 
						||
 | 
						||
      var
 | 
						||
         hp : pclasslistitem;
 | 
						||
 | 
						||
      begin
 | 
						||
         hp:=pclasslistitem(classtablelist.first);
 | 
						||
         while assigned(hp) do
 | 
						||
           if hp^.p=p then
 | 
						||
             begin
 | 
						||
                searchclasstablelist:=hp;
 | 
						||
                exit;
 | 
						||
             end
 | 
						||
           else
 | 
						||
             hp:=pclasslistitem(hp^.next);
 | 
						||
         searchclasstablelist:=nil;
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure count_published_fields(sym:pnamedindexobject);
 | 
						||
      var
 | 
						||
         hp : pclasslistitem;
 | 
						||
      begin
 | 
						||
         if needs_prop_entry(psym(sym)) and
 | 
						||
          (psym(sym)^.typ=varsym) then
 | 
						||
          begin
 | 
						||
             if pvarsym(sym)^.vartype.def^.deftype<>objectdef then
 | 
						||
               internalerror(0206001);
 | 
						||
             hp:=searchclasstablelist(pobjectdef(pvarsym(sym)^.vartype.def));
 | 
						||
             if not(assigned(hp)) then
 | 
						||
               begin
 | 
						||
                  hp:=new(pclasslistitem,init);
 | 
						||
                  hp^.p:=pobjectdef(pvarsym(sym)^.vartype.def);
 | 
						||
                  hp^.index:=tablecount;
 | 
						||
                  classtablelist.concat(hp);
 | 
						||
                  inc(tablecount);
 | 
						||
               end;
 | 
						||
             inc(count);
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure writefields(sym:pnamedindexobject);
 | 
						||
      var
 | 
						||
         hp : pclasslistitem;
 | 
						||
      begin
 | 
						||
         if needs_prop_entry(psym(sym)) and
 | 
						||
          (psym(sym)^.typ=varsym) then
 | 
						||
          begin
 | 
						||
             rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
 | 
						||
             hp:=searchclasstablelist(pobjectdef(pvarsym(sym)^.vartype.def));
 | 
						||
             if not(assigned(hp)) then
 | 
						||
               internalerror(0206002);
 | 
						||
             rttilist^.concat(new(pai_const,init_16bit(hp^.index)));
 | 
						||
             rttilist^.concat(new(pai_const,init_8bit(length(pvarsym(sym)^.realname))));
 | 
						||
             rttilist^.concat(new(pai_string,init(pvarsym(sym)^.realname)));
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
    function tobjectdef.generate_field_table : pasmlabel;
 | 
						||
 | 
						||
      var
 | 
						||
         fieldtable,
 | 
						||
         classtable : pasmlabel;
 | 
						||
         hp : pclasslistitem;
 | 
						||
 | 
						||
      begin
 | 
						||
         classtablelist.init;
 | 
						||
         getdatalabel(fieldtable);
 | 
						||
         getdatalabel(classtable);
 | 
						||
         count:=0;
 | 
						||
         tablecount:=0;
 | 
						||
         symtable^.foreach({$ifdef FPC}@{$endif}count_published_fields);
 | 
						||
         rttilist^.concat(new(pai_label,init(fieldtable)));
 | 
						||
         rttilist^.concat(new(pai_const,init_16bit(count)));
 | 
						||
         rttilist^.concat(new(pai_const_symbol,init(classtable)));
 | 
						||
         symtable^.foreach({$ifdef FPC}@{$endif}writefields);
 | 
						||
 | 
						||
         { generate the class table }
 | 
						||
         rttilist^.concat(new(pai_label,init(classtable)));
 | 
						||
         rttilist^.concat(new(pai_const,init_16bit(tablecount)));
 | 
						||
         hp:=pclasslistitem(classtablelist.first);
 | 
						||
         while assigned(hp) do
 | 
						||
           begin
 | 
						||
              rttilist^.concat(new(pai_const_symbol,initname(pobjectdef(hp^.p)^.vmt_mangledname)));
 | 
						||
              hp:=pclasslistitem(hp^.next);
 | 
						||
           end;
 | 
						||
 | 
						||
         generate_field_table:=fieldtable;
 | 
						||
         classtablelist.done;
 | 
						||
      end;
 | 
						||
 | 
						||
    function tobjectdef.next_free_name_index : longint;
 | 
						||
      var
 | 
						||
         i : longint;
 | 
						||
      begin
 | 
						||
         if assigned(childof) and (oo_can_have_published in childof^.objectoptions) then
 | 
						||
           i:=childof^.next_free_name_index
 | 
						||
         else
 | 
						||
           i:=0;
 | 
						||
         count:=0;
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}count_published_properties);
 | 
						||
         next_free_name_index:=i+count;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    procedure tobjectdef.write_rtti_data;
 | 
						||
      begin
 | 
						||
         case objecttype of
 | 
						||
           odt_class: rttilist^.concat(new(pai_const,init_8bit(tkclass)));
 | 
						||
           odt_object: rttilist^.concat(new(pai_const,init_8bit(tkobject)));
 | 
						||
           odt_interfacecom: rttilist^.concat(new(pai_const,init_8bit(tkinterface)));
 | 
						||
           odt_interfacecorba: rttilist^.concat(new(pai_const,init_8bit(tkinterfaceCorba)));
 | 
						||
         else
 | 
						||
           exit;
 | 
						||
         end;
 | 
						||
 | 
						||
         { generate the name }
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(length(objname^))));
 | 
						||
         rttilist^.concat(new(pai_string,init(objname^)));
 | 
						||
 | 
						||
         { write class type }
 | 
						||
         if objecttype in [odt_interfacecom,odt_interfacecorba] then
 | 
						||
           rttilist^.concat(new(pai_const,init_32bit(0)))
 | 
						||
         else
 | 
						||
           rttilist^.concat(new(pai_const_symbol,initname(vmt_mangledname)));
 | 
						||
 | 
						||
         { write owner typeinfo }
 | 
						||
         if assigned(childof) and (oo_can_have_published in childof^.objectoptions) then
 | 
						||
           rttilist^.concat(new(pai_const_symbol,initname(childof^.get_rtti_label)))
 | 
						||
         else
 | 
						||
           rttilist^.concat(new(pai_const,init_32bit(0)));
 | 
						||
 | 
						||
         { count total number of properties }
 | 
						||
         if assigned(childof) and (oo_can_have_published in childof^.objectoptions) then
 | 
						||
           count:=childof^.next_free_name_index
 | 
						||
         else
 | 
						||
           count:=0;
 | 
						||
 | 
						||
         { write it }
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}count_published_properties);
 | 
						||
         rttilist^.concat(new(pai_const,init_16bit(count)));
 | 
						||
 | 
						||
         { write unit name }
 | 
						||
         rttilist^.concat(new(pai_const,init_8bit(length(current_module^.realmodulename^))));
 | 
						||
         rttilist^.concat(new(pai_string,init(current_module^.realmodulename^)));
 | 
						||
 | 
						||
         { write published properties count }
 | 
						||
         count:=0;
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}count_published_properties);
 | 
						||
         rttilist^.concat(new(pai_const,init_16bit(count)));
 | 
						||
 | 
						||
         { count is used to write nameindex   }
 | 
						||
 | 
						||
         { but we need an offset of the owner }
 | 
						||
         { to give each property an own slot  }
 | 
						||
         if assigned(childof) and (oo_can_have_published in childof^.objectoptions) then
 | 
						||
           count:=childof^.next_free_name_index
 | 
						||
         else
 | 
						||
           count:=0;
 | 
						||
 | 
						||
         symtable^.foreach({$ifdef FPCPROCVAR}@{$endif}write_property_info);
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    function tobjectdef.is_publishable : boolean;
 | 
						||
      begin
 | 
						||
         is_publishable:=objecttype in [odt_class,odt_interfacecom,odt_interfacecorba];
 | 
						||
      end;
 | 
						||
 | 
						||
    function  tobjectdef.get_rtti_label : string;
 | 
						||
 | 
						||
      begin
 | 
						||
         generate_rtti;
 | 
						||
         get_rtti_label:=rtti_name;
 | 
						||
      end;
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                                TFORWARDDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
   constructor tforwarddef.init(const s:string;const pos : tfileposinfo);
 | 
						||
     var
 | 
						||
       oldregisterdef : boolean;
 | 
						||
     begin
 | 
						||
        { never register the forwarddefs, they are disposed at the
 | 
						||
          end of the type declaration block }
 | 
						||
        oldregisterdef:=registerdef;
 | 
						||
        registerdef:=false;
 | 
						||
        inherited init;
 | 
						||
        registerdef:=oldregisterdef;
 | 
						||
        deftype:=forwarddef;
 | 
						||
        tosymname:=s;
 | 
						||
        forwardpos:=pos;
 | 
						||
     end;
 | 
						||
 | 
						||
 | 
						||
    function tforwarddef.gettypename:string;
 | 
						||
      begin
 | 
						||
        gettypename:='unresolved forward to '+tosymname;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                             TIMPLEMENTEDINTERFACES
 | 
						||
****************************************************************************}
 | 
						||
    type
 | 
						||
      pnamemap = ^tnamemap;
 | 
						||
      tnamemap = object(tnamedindexobject)
 | 
						||
        newname: pstring;
 | 
						||
        constructor init(const aname, anewname: string);
 | 
						||
        destructor  done; virtual;
 | 
						||
      end;
 | 
						||
 | 
						||
    constructor tnamemap.init(const aname, anewname: string);
 | 
						||
      begin
 | 
						||
        inherited initname(name);
 | 
						||
        newname:=stringdup(anewname);
 | 
						||
      end;
 | 
						||
 | 
						||
    destructor  tnamemap.done;
 | 
						||
      begin
 | 
						||
        stringdispose(newname);
 | 
						||
        inherited done;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    type
 | 
						||
      pprocdefstore = ^tprocdefstore;
 | 
						||
      tprocdefstore = object(tnamedindexobject)
 | 
						||
        procdef: pprocdef;
 | 
						||
        constructor init(aprocdef: pprocdef);
 | 
						||
      end;
 | 
						||
 | 
						||
    constructor tprocdefstore.init(aprocdef: pprocdef);
 | 
						||
      begin
 | 
						||
        inherited init;
 | 
						||
        procdef:=aprocdef;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    type
 | 
						||
      pimplintfentry = ^timplintfentry;
 | 
						||
      timplintfentry = object(tnamedindexobject)
 | 
						||
        intf: pobjectdef;
 | 
						||
        ioffs: longint;
 | 
						||
        namemappings: pdictionary;
 | 
						||
        procdefs: pindexarray;
 | 
						||
        constructor init(aintf: pobjectdef);
 | 
						||
        destructor  done; virtual;
 | 
						||
      end;
 | 
						||
 | 
						||
    constructor timplintfentry.init(aintf: pobjectdef);
 | 
						||
      begin
 | 
						||
        inherited init;
 | 
						||
        intf:=aintf;
 | 
						||
        ioffs:=-1;
 | 
						||
        namemappings:=nil;
 | 
						||
        procdefs:=nil;
 | 
						||
      end;
 | 
						||
 | 
						||
    destructor  timplintfentry.done;
 | 
						||
      begin
 | 
						||
        if assigned(namemappings) then
 | 
						||
          dispose(namemappings,done);
 | 
						||
        if assigned(procdefs) then
 | 
						||
          dispose(procdefs,done);
 | 
						||
        inherited done;
 | 
						||
      end;
 | 
						||
 | 
						||
 | 
						||
    constructor timplementedinterfaces.init;
 | 
						||
      begin
 | 
						||
        finterfaces.init(1);
 | 
						||
      end;
 | 
						||
 | 
						||
    destructor  timplementedinterfaces.done;
 | 
						||
      begin
 | 
						||
        finterfaces.done;
 | 
						||
      end;
 | 
						||
 | 
						||
    function  timplementedinterfaces.count: longint;
 | 
						||
      begin
 | 
						||
        count:=finterfaces.count;
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure timplementedinterfaces.checkindex(intfindex: longint);
 | 
						||
      begin
 | 
						||
        if (intfindex<1) or (intfindex>count) then
 | 
						||
          InternalError(200006123);
 | 
						||
      end;
 | 
						||
 | 
						||
    function  timplementedinterfaces.interfaces(intfindex: longint): pobjectdef;
 | 
						||
      begin
 | 
						||
        checkindex(intfindex);
 | 
						||
        interfaces:=pimplintfentry(finterfaces.search(intfindex))^.intf;
 | 
						||
      end;
 | 
						||
 | 
						||
    function  timplementedinterfaces.ioffsets(intfindex: longint): plongint;
 | 
						||
      begin
 | 
						||
        checkindex(intfindex);
 | 
						||
        ioffsets:=@pimplintfentry(finterfaces.search(intfindex))^.ioffs;
 | 
						||
      end;
 | 
						||
 | 
						||
    function  timplementedinterfaces.searchintf(def: pdef): longint;
 | 
						||
      var
 | 
						||
        i: longint;
 | 
						||
      begin
 | 
						||
        i:=1;
 | 
						||
        while (i<=count) and (pdef(interfaces(i))<>def) do inc(i);
 | 
						||
        if i<=count then
 | 
						||
          searchintf:=i
 | 
						||
        else
 | 
						||
          searchintf:=-1;
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure timplementedinterfaces.deref;
 | 
						||
      var
 | 
						||
        i: longint;
 | 
						||
      begin
 | 
						||
        for i:=1 to count do
 | 
						||
          with pimplintfentry(finterfaces.search(i))^ do
 | 
						||
            resolvedef(pdef(intf));
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure timplementedinterfaces.addintfref(def: pdef);
 | 
						||
      begin
 | 
						||
        finterfaces.insert(new(pimplintfentry,init(pobjectdef(def))));
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure timplementedinterfaces.addintf(def: pdef);
 | 
						||
      begin
 | 
						||
        if not assigned(def) or (searchintf(def)<>-1) or (def^.deftype<>objectdef) or
 | 
						||
           not (pobjectdef(def)^.objecttype in [odt_interfacecom,odt_interfacecorba]) then
 | 
						||
          internalerror(200006124);
 | 
						||
        finterfaces.insert(new(pimplintfentry,init(pobjectdef(def))));
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure timplementedinterfaces.clearmappings;
 | 
						||
      var
 | 
						||
        i: longint;
 | 
						||
      begin
 | 
						||
        for i:=1 to count do
 | 
						||
          with pimplintfentry(finterfaces.search(i))^ do
 | 
						||
            begin
 | 
						||
             if assigned(namemappings) then
 | 
						||
               dispose(namemappings,done);
 | 
						||
             namemappings:=nil;
 | 
						||
            end;
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure timplementedinterfaces.addmappings(intfindex: longint; const name, newname: string);
 | 
						||
      begin
 | 
						||
        checkindex(intfindex);
 | 
						||
        with pimplintfentry(finterfaces.search(intfindex))^ do
 | 
						||
          begin
 | 
						||
            if not assigned(namemappings) then
 | 
						||
              new(namemappings,init);
 | 
						||
            namemappings^.insert(new(pnamemap,init(name,newname)));
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
    function  timplementedinterfaces.getmappings(intfindex: longint; const name: string; var nextexist: pointer): string;
 | 
						||
      begin
 | 
						||
        checkindex(intfindex);
 | 
						||
        if not assigned(nextexist) then
 | 
						||
          with pimplintfentry(finterfaces.search(intfindex))^ do
 | 
						||
            begin
 | 
						||
              if assigned(namemappings) then
 | 
						||
                nextexist:=namemappings^.search(name)
 | 
						||
              else
 | 
						||
                nextexist:=nil;
 | 
						||
            end;
 | 
						||
        if assigned(nextexist) then
 | 
						||
          begin
 | 
						||
            getmappings:=pnamemap(nextexist)^.newname^;
 | 
						||
            nextexist:=pnamemap(nextexist)^.listnext;
 | 
						||
          end
 | 
						||
        else
 | 
						||
          getmappings:='';
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure timplementedinterfaces.clearimplprocs;
 | 
						||
      var
 | 
						||
        i: longint;
 | 
						||
      begin
 | 
						||
        for i:=1 to count do
 | 
						||
          with pimplintfentry(finterfaces.search(i))^ do
 | 
						||
            begin
 | 
						||
              if assigned(procdefs) then
 | 
						||
                dispose(procdefs,done);
 | 
						||
              procdefs:=nil;
 | 
						||
            end;
 | 
						||
      end;
 | 
						||
 | 
						||
    procedure timplementedinterfaces.addimplproc(intfindex: longint; procdef: pprocdef);
 | 
						||
      begin
 | 
						||
        checkindex(intfindex);
 | 
						||
        with pimplintfentry(finterfaces.search(intfindex))^ do
 | 
						||
          begin
 | 
						||
            if not assigned(procdefs) then
 | 
						||
              new(procdefs,init(4));
 | 
						||
            procdefs^.insert(new(pprocdefstore,init(procdef)));
 | 
						||
          end;
 | 
						||
      end;
 | 
						||
 | 
						||
    function  timplementedinterfaces.implproccount(intfindex: longint): longint;
 | 
						||
      begin
 | 
						||
        checkindex(intfindex);
 | 
						||
        with pimplintfentry(finterfaces.search(intfindex))^ do
 | 
						||
          if assigned(procdefs) then
 | 
						||
            implproccount:=procdefs^.count
 | 
						||
          else
 | 
						||
            implproccount:=0;
 | 
						||
      end;
 | 
						||
 | 
						||
    function  timplementedinterfaces.implprocs(intfindex: longint; procindex: longint): pprocdef;
 | 
						||
      begin
 | 
						||
        checkindex(intfindex);
 | 
						||
        with pimplintfentry(finterfaces.search(intfindex))^ do
 | 
						||
          if assigned(procdefs) then
 | 
						||
            implprocs:=pprocdefstore(procdefs^.search(procindex))^.procdef
 | 
						||
          else
 | 
						||
            internalerror(200006131);
 | 
						||
      end;
 | 
						||
 | 
						||
    function  timplementedinterfaces.isimplmergepossible(intfindex, remainindex: longint; var weight: longint): boolean;
 | 
						||
      var
 | 
						||
        possible: boolean;
 | 
						||
        i: longint;
 | 
						||
        iiep1: pindexarray;
 | 
						||
        iiep2: pindexarray;
 | 
						||
      begin
 | 
						||
        checkindex(intfindex);
 | 
						||
        checkindex(remainindex);
 | 
						||
        iiep1:=pimplintfentry(finterfaces.search(intfindex))^.procdefs;
 | 
						||
        iiep2:=pimplintfentry(finterfaces.search(remainindex))^.procdefs;
 | 
						||
        if not assigned(iiep1) then { empty interface is mergeable :-) }
 | 
						||
          begin
 | 
						||
            possible:=true;
 | 
						||
            weight:=0;
 | 
						||
          end
 | 
						||
        else
 | 
						||
          begin
 | 
						||
            possible:=assigned(iiep2) and (iiep1^.count<=iiep2^.count);
 | 
						||
            i:=1;
 | 
						||
            while (possible) and (i<=iiep1^.count) do
 | 
						||
              begin
 | 
						||
                possible:=
 | 
						||
                  pprocdefstore(iiep1^.search(i))^.procdef=
 | 
						||
                  pprocdefstore(iiep2^.search(i))^.procdef;
 | 
						||
                inc(i);
 | 
						||
              end;
 | 
						||
            if possible then
 | 
						||
              weight:=iiep1^.count;
 | 
						||
          end;
 | 
						||
        isimplmergepossible:=possible;
 | 
						||
      end;
 | 
						||
 | 
						||
{****************************************************************************
 | 
						||
                                  TERRORDEF
 | 
						||
****************************************************************************}
 | 
						||
 | 
						||
   constructor terrordef.init;
 | 
						||
     begin
 | 
						||
        inherited init;
 | 
						||
        deftype:=errordef;
 | 
						||
     end;
 | 
						||
 | 
						||
 | 
						||
{$ifdef GDB}
 | 
						||
    function terrordef.stabstring : pchar;
 | 
						||
      begin
 | 
						||
         stabstring:=strpnew('error'+numberstring);
 | 
						||
      end;
 | 
						||
{$endif GDB}
 | 
						||
 | 
						||
    function terrordef.gettypename:string;
 | 
						||
 | 
						||
      begin
 | 
						||
         gettypename:='<erroneous type>';
 | 
						||
      end;
 | 
						||
 | 
						||
{
 | 
						||
  $Log$
 | 
						||
  Revision 1.26  2000-11-04 14:25:22  florian
 | 
						||
    + merged Attila's changes for interfaces, not tested yet
 | 
						||
 | 
						||
  Revision 1.25  2000/10/31 22:02:52  peter
 | 
						||
    * symtable splitted, no real code changes
 | 
						||
 | 
						||
  Revision 1.24  2000/10/21 18:16:12  florian
 | 
						||
    * a lot of changes:
 | 
						||
       - basic dyn. array support
 | 
						||
       - basic C++ support
 | 
						||
       - some work for interfaces done
 | 
						||
       ....
 | 
						||
 | 
						||
  Revision 1.23  2000/10/15 07:47:52  peter
 | 
						||
    * unit names and procedure names are stored mixed case
 | 
						||
 | 
						||
  Revision 1.22  2000/10/14 10:14:52  peter
 | 
						||
    * moehrendorf oct 2000 rewrite
 | 
						||
 | 
						||
  Revision 1.21  2000/10/04 23:16:48  pierre
 | 
						||
   * object stabs fix (merged)
 | 
						||
 | 
						||
  Revision 1.20  2000/10/01 19:48:25  peter
 | 
						||
    * lot of compile updates for cg11
 | 
						||
 | 
						||
  Revision 1.19  2000/09/24 21:19:52  peter
 | 
						||
    * delphi compile fixes
 | 
						||
 | 
						||
  Revision 1.18  2000/09/24 15:06:28  peter
 | 
						||
    * use defines.inc
 | 
						||
 | 
						||
  Revision 1.17  2000/09/19 23:08:02  pierre
 | 
						||
   * fixes for local class debuggging problem (merged)
 | 
						||
 | 
						||
  Revision 1.16  2000/09/10 20:13:37  peter
 | 
						||
    * fixed array of const writing instead of array of tvarrec (merged)
 | 
						||
 | 
						||
  Revision 1.15  2000/09/09 18:36:40  peter
 | 
						||
    * fixed C alignment of array of record (merged)
 | 
						||
 | 
						||
  Revision 1.14  2000/08/27 20:19:39  peter
 | 
						||
    * store strings with case in ppu, when an internal symbol is created
 | 
						||
      a '$' is prefixed so it's not automatic uppercased
 | 
						||
 | 
						||
  Revision 1.13  2000/08/27 16:11:53  peter
 | 
						||
    * moved some util functions from globals,cobjects to cutils
 | 
						||
    * splitted files into finput,fmodule
 | 
						||
 | 
						||
  Revision 1.12  2000/08/21 11:27:44  pierre
 | 
						||
   * fix the stabs problems
 | 
						||
 | 
						||
  Revision 1.11  2000/08/16 18:33:54  peter
 | 
						||
    * splitted namedobjectitem.next into indexnext and listnext so it
 | 
						||
      can be used in both lists
 | 
						||
    * don't allow "word = word" type definitions (merged)
 | 
						||
 | 
						||
  Revision 1.10  2000/08/16 13:06:06  florian
 | 
						||
    + support of 64 bit integer constants
 | 
						||
 | 
						||
  Revision 1.9  2000/08/13 13:06:37  peter
 | 
						||
    * store parast always for procdef (browser needs still update)
 | 
						||
    * add default parameter value to demangledpara
 | 
						||
 | 
						||
  Revision 1.8  2000/08/08 19:28:57  peter
 | 
						||
    * memdebug/memory patches (merged)
 | 
						||
    * only once illegal directive (merged)
 | 
						||
 | 
						||
  Revision 1.7  2000/08/06 19:39:28  peter
 | 
						||
    * default parameters working !
 | 
						||
 | 
						||
  Revision 1.6  2000/08/06 14:17:15  peter
 | 
						||
    * overload fixes (merged)
 | 
						||
 | 
						||
  Revision 1.5  2000/08/03 13:17:26  jonas
 | 
						||
    + allow regvars to be used inside inlined procs, which required  the
 | 
						||
      following changes:
 | 
						||
        + load regvars in genentrycode/free them in genexitcode (cgai386)
 | 
						||
        * moved all regvar related code to new regvars unit
 | 
						||
        + added pregvarinfo type to hcodegen
 | 
						||
        + added regvarinfo field to tprocinfo (symdef/symdefh)
 | 
						||
        * deallocate the regvars of the caller in secondprocinline before
 | 
						||
          inlining the called procedure and reallocate them afterwards
 | 
						||
 | 
						||
  Revision 1.4  2000/08/02 19:49:59  peter
 | 
						||
    * first things for default parameters
 | 
						||
 | 
						||
  Revision 1.3  2000/07/13 12:08:27  michael
 | 
						||
  + patched to 1.1.0 with former 1.09patch from peter
 | 
						||
 | 
						||
  Revision 1.2  2000/07/13 11:32:49  michael
 | 
						||
  + removed logs
 | 
						||
 | 
						||
} |