Browse Source

* first rough conversion

florian 27 years ago
parent
commit
a0e7569800
1 changed files with 1606 additions and 0 deletions
  1. 1606 0
      compiler/new/tree.pas

+ 1606 - 0
compiler/new/tree.pas

@@ -0,0 +1,1606 @@
+{
+    $Id$
+    Copyright (c) 1993-98 by Florian Klaempfl
+
+    This units exports some routines to manage the parse tree
+
+    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.
+
+ ****************************************************************************
+}
+
+{$ifdef tp}
+  {$E+,N+}
+{$endif}
+unit tree;
+
+  interface
+
+    uses
+       globtype,cobjects,symtable,aasm
+{$I cpuunit.inc}
+       ;
+
+    type
+       pconstset = ^tconstset;
+       tconstset = array[0..31] of byte;
+
+       ttreetyp = (
+          addn,            {Represents the + operator.}
+          muln,            {Represents the * operator.}
+          subn,            {Represents the - operator.}
+          divn,            {Represents the div operator.}
+          symdifn,         {Represents the >< operator.}
+          modn,            {Represents the mod operator.}
+          assignn,         {Represents an assignment.}
+          loadn,           {Represents the use of a variabele.}
+          rangen,          {Represents a range (i.e. 0..9).}
+          ltn,             {Represents the < operator.}
+          lten,            {Represents the <= operator.}
+          gtn,             {Represents the > operator.}
+          gten,            {Represents the >= operator.}
+          equaln,          {Represents the = operator.}
+          unequaln,        {Represents the <> operator.}
+          inn,             {Represents the in operator.}
+          orn,             {Represents the or operator.}
+          xorn,            {Represents the xor operator.}
+          shrn,            {Represents the shr operator.}
+          shln,            {Represents the shl operator.}
+          slashn,          {Represents the / operator.}
+          andn,            {Represents the and operator.}
+          subscriptn,      {access to a record/class/object field}
+          derefn,          {Dereferences a pointer.}
+          addrn,           {Represents the @ operator.}
+          doubleaddrn,     {Represents the @@ operator.}
+          ordconstn,       {Represents an ordinal value.}
+          typeconvn,       {Represents type-conversion/typecast.}
+          calln,           {Represents a call node.}
+          callparan,       {Represents a parameter.}
+          realconstn,      {Represents a real value.}
+          fixconstn,       {Represents a fixed value.}
+          umminusn,        {Represents a sign change (i.e. -2).}
+          asmn,            {Represents an assembler node }
+          vecn,            {Represents array indexing.}
+          stringconstn,    {Represents a string constant.}
+          funcretn,        {Represents the function result var.}
+          selfn,           {Represents the self parameter.}
+          notn,            {Represents the not operator.}
+          inlinen,         {Internal procedures (i.e. writeln).}
+          niln,            {Represents the nil pointer.}
+          errorn,          {This part of the tree could not be
+                            parsed because of a compiler error.}
+          typen,           {A type name. Used for i.e. typeof(obj).}
+          hnewn,           {The new operation, constructor call.}
+          hdisposen,       {The dispose operation with destructor call.}
+          newn,            {The new operation, constructor call.}
+          simpledisposen,  {The dispose operation.}
+          setelementn,     {A set element(s) (i.e. [a,b] and also [a..b]).}
+          setconstn,       {A set constant (i.e. [1,2]).}
+          blockn,          {A block of statements.}
+          statementn,      {One statement in a block of nodes.}
+          loopn,           { used in genloopnode, must be converted }
+          ifn,             {An if statement.}
+          breakn,          {A break statement.}
+          continuen,       {A continue statement.}
+          repeatn,         {A repeat until block.}
+          whilen,          {A while do statement.}
+          forn,            {A for loop.}
+          exitn,           {An exit statement.}
+          withn,           {A with statement.}
+          casen,           {A case statement.}
+          labeln,          {A label.}
+          goton,           {A goto statement.}
+          simplenewn,      {The new operation.}
+          tryexceptn,      {A try except block.}
+          raisen,          {A raise statement.}
+          switchesn,       {??? Currently unused...}
+          tryfinallyn,     {A try finally statement.}
+          onn,             { for an on statement in exception code }
+          isn,             {Represents the is operator.}
+          asn,             {Represents the as typecast.}
+          caretn,          {Represents the ^ operator.}
+          failn,           {Represents the fail statement.}
+          starstarn,       {Represents the ** operator exponentiation }
+          procinlinen,     {Procedures that can be inlined }
+          arrayconstructn, {Construction node for [...] parsing}
+          arrayconstructrangen, {Range element to allow sets in array construction tree}
+          { added for optimizations where we cannot suppress }
+          nothingn,
+          loadvmtn
+       );
+
+       tconverttype = (
+          tc_equal,
+          tc_not_possible,
+          tc_string_2_string,
+          tc_char_2_string,
+          tc_pchar_2_string,
+          tc_cchar_2_pchar,
+          tc_cstring_2_pchar,
+          tc_ansistring_2_pchar,
+          tc_string_2_chararray,
+          tc_chararray_2_string,
+          tc_array_2_pointer,
+          tc_pointer_2_array,
+          tc_int_2_int,
+          tc_bool_2_int,
+          tc_int_2_bool,
+          tc_real_2_real,
+          tc_int_2_real,
+          tc_int_2_fix,
+          tc_real_2_fix,
+          tc_fix_2_real,
+          tc_proc_2_procvar,
+          tc_arrayconstructor_2_set,
+          tc_load_smallset
+       );
+
+      { different assignment types }
+
+      tassigntyp = (at_normal,at_plus,at_minus,at_star,at_slash);
+
+      pcaserecord = ^tcaserecord;
+      tcaserecord = record
+
+          { range }
+          _low,_high : longint;
+
+          { only used by gentreejmp }
+          _at : plabel;
+
+          { label of instruction }
+          statement : plabel;
+
+          { is this the first of an case entry, needed to release statement
+            label (PFV) }
+          firstlabel : boolean;
+
+          { left and right tree node }
+          less,greater : pcaserecord;
+       end;
+
+       pnode = ^tnode;
+       tnode = object
+          treetype : ttreetyp;
+          { the location of the result of this node }
+          location : tlocation;
+
+          { the number of registers needed to evalute the node }
+          registersint,registersfpu : longint;  { must be longint !!!! }
+{$ifdef SUPPORT_MMX}
+          registersmmx : longint;
+{$endif SUPPORT_MMX}
+          resulttype : pdef;
+          fileinfo : tfileposinfo;
+          localswitches : tlocalswitches;
+{$ifdef extdebug}
+          firstpasscount : longint;
+{$endif extdebug}
+          error : boolean;
+          constructor init;
+          destructor done;virtual;
+       end;
+
+       ploadnode = object(tnode)
+          symtableentry : psym;
+          symtable : psymtable;
+          is_absolute,is_first,is_methodpointer : boolean;
+          constructor init;
+          destructor done;virtual;
+       end;
+
+          left,right : ptree;
+          { is true, if the right and left operand are swaped }
+          swaped : boolean;
+          case treetype : ttreetyp of
+             addn : (use_strconcat : boolean;string_typ : tstringtype);
+             callparan : (is_colon_para : boolean;exact_match_found : boolean);
+             assignn : (assigntyp : tassigntyp;concat_string : boolean);
+             calln : (symtableprocentry : psym;
+                      symtableproc : psymtable;procdefinition : pprocdef;
+                      methodpointer : ptree;
+                      no_check,unit_specific,return_value_used : boolean);
+             ordconstn : (value : longint);
+             realconstn : (value_real : bestreal;lab_real : plabel;realtyp : tait);
+             fixconstn : (value_fix: longint);
+             funcretn : (funcretprocinfo : pointer;retdef : pdef);
+             subscriptn : (vs : pvarsym);
+             vecn : (memindex,memseg:boolean;callunique : boolean);
+             stringconstn : (value_str : pchar;length : longint; lab_str : plabel;stringtype : tstringtype);
+             typeconvn : (convtyp : tconverttype;explizit : boolean);
+             typen : (typenodetype : pdef);
+             inlinen : (inlinenumber : byte;inlineconst:boolean);
+             procinlinen : (inlineprocdef : pprocdef;
+                            retoffset,para_offset,para_size : longint);
+             setconstn : (value_set : pconstset;lab_set:plabel);
+             loopn : (t1,t2 : ptree;backward : boolean);
+             asmn : (p_asm : paasmoutput;object_preserved : boolean);
+             casen : (nodes : pcaserecord;elseblock : ptree);
+             labeln,goton : (labelnr : plabel);
+             withn : (withsymtable : psymtable;tablecount : longint);
+             onn : (exceptsymtable : psymtable;excepttype : pobjectdef);
+             arrayconstructn : (cargs,cargswap: boolean);
+
+    function gennode(t : ttreetyp;l,r : ptree) : ptree;
+    function genlabelnode(t : ttreetyp;nr : plabel) : ptree;
+    function genloadnode(v : pvarsym;st : psymtable) : ptree;
+    function genloadcallnode(v: pprocsym;st: psymtable): ptree;
+    function gensinglenode(t : ttreetyp;l : ptree) : ptree;
+    function gensubscriptnode(varsym : pvarsym;l : ptree) : ptree;
+    function genordinalconstnode(v : longint;def : pdef) : ptree;
+    function genfixconstnode(v : longint;def : pdef) : ptree;
+    function gentypeconvnode(node : ptree;t : pdef) : ptree;
+    function gentypenode(t : pdef) : ptree;
+    function gencallparanode(expr,next : ptree) : ptree;
+    function genrealconstnode(v : bestreal) : ptree;
+    function gencallnode(v : pprocsym;st : psymtable) : ptree;
+    function genmethodcallnode(v : pprocsym;st : psymtable;mp : ptree) : ptree;
+
+    { allow pchar or string for defining a pchar node }
+    function genstringconstnode(const s : string) : ptree;
+    { length is required for ansistrings }
+    function genpcharconstnode(s : pchar;length : longint) : ptree;
+    { helper routine for conststring node }
+    function getpcharcopy(p : ptree) : pchar;
+
+    function genzeronode(t : ttreetyp) : ptree;
+    function geninlinenode(number : byte;is_const:boolean;l : ptree) : ptree;
+    function genprocinlinenode(callp,code : ptree) : ptree;
+    function gentypedconstloadnode(sym : ptypedconstsym;st : psymtable) : ptree;
+    function genenumnode(v : penumsym) : ptree;
+    function genselfnode(_class : pdef) : ptree;
+    function gensetconstnode(s : pconstset;settype : psetdef) : ptree;
+    function genloopnode(t : ttreetyp;l,r,n1: ptree;back : boolean) : ptree;
+    function genasmnode(p_asm : paasmoutput) : ptree;
+    function gencasenode(l,r : ptree;nodes : pcaserecord) : ptree;
+    function genwithnode(symtable : psymtable;l,r : ptree;count : longint) : ptree;
+
+    function getcopy(p : ptree) : ptree;
+
+    function equal_trees(t1,t2 : ptree) : boolean;
+
+    procedure swaptree(p:Ptree);
+    procedure disposetree(p : ptree);
+    procedure putnode(p : ptree);
+    function getnode : ptree;
+    procedure set_file_line(from,_to : ptree);
+    procedure set_tree_filepos(p : ptree;const filepos : tfileposinfo);
+{$ifdef extdebug}
+    procedure compare_trees(oldp,p : ptree);
+    const
+       maxfirstpasscount : longint = 0;
+{$endif extdebug}
+
+    { sets the callunique flag, if the node is a vecn, }
+    { takes care of type casts etc.                    }
+    procedure set_unique(p : ptree);
+
+    { gibt den ordinalen Werten der Node zurueck oder falls sie }
+    { keinen ordinalen Wert hat, wird ein Fehler erzeugt        }
+    function get_ordinal_value(p : ptree) : longint;
+
+    function is_constnode(p : ptree) : boolean;
+    { true, if p is a pointer to a const int value }
+    function is_constintnode(p : ptree) : boolean;
+    function is_constboolnode(p : ptree) : boolean;
+    function is_constrealnode(p : ptree) : boolean;
+    function is_constcharnode(p : ptree) : boolean;
+    function str_length(p : ptree) : longint;
+    function is_emptyset(p : ptree):boolean;
+
+{$I innr.inc}
+
+  implementation
+
+    uses
+       systems,
+       globals,verbose,files,types;
+
+{****************************************************************************
+                                 TNODE
+ ****************************************************************************}
+
+    constructor tnode.init;
+
+      begin
+         treetype:=nothingn;
+         { this allows easier error tracing }
+         location.loc:=LOC_INVALID;
+         { save local info }
+         fileinfo:=aktfilepos;
+         localswitches:=aktlocalswitches;
+         resulttype:=nil;
+         registersint:=0;
+         registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         registersmmx:=0;
+{$endif SUPPORT_MMX}
+      end;
+
+    destructor tnode.done;
+
+      begin
+         { reference info }
+         if (location.loc in [LOC_MEM,LOC_REFERENCE]) and
+            assigned(location.reference.symbol) then
+           stringdispose(location.reference.symbol);
+{$ifdef extdebug}
+         if firstpasscount>maxfirstpasscount then
+            maxfirstpasscount:=firstpasscount;
+{$endif extdebug}
+      end;
+
+{****************************************************************************
+                                 TLOADNODE
+ ****************************************************************************}
+
+    constructor tloadnode.init(v : pvarsym;st : psymtable) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         inherited init;
+         p^.treetype:=loadn;
+         resulttype:=v^.definition;
+         symtableentry:=v;
+         symtable:=st;
+         p^.is_first := False;
+         p^.is_methodpointer:=false;
+
+         { method pointer load nodes can use the left subtree }
+         { !!!!! p^.left:=nil; }
+      end;
+
+    destructor tloadnode.done;
+
+      begin
+         inherited done;
+         { method pointer load nodes can use the left subtree }
+         { !!!!! dispose(left,done); }
+      end;
+
+{$ifdef dummy}
+
+         { clean up the contents of a node }
+         case p^.treetype of
+          asmn : if assigned(p^.p_asm) then
+                  dispose(p^.p_asm,done);
+  stringconstn : begin
+                   ansistringdispose(p^.value_str,p^.length);
+                 end;
+     setconstn : begin
+                   if assigned(p^.value_set) then
+                     dispose(p^.value_set);
+                 end;
+         end;
+
+
+    procedure deletecaselabels(p : pcaserecord);
+
+      begin
+         if assigned(p^.greater) then
+           deletecaselabels(p^.greater);
+         if assigned(p^.less) then
+           deletecaselabels(p^.less);
+         freelabel(p^._at);
+         if p^.firstlabel then
+          freelabel(p^.statement);
+         dispose(p);
+      end;
+
+    procedure swaptree(p:Ptree);
+
+    var swapp:Ptree;
+
+    begin
+        swapp:=p^.right;
+        p^.right:=p^.left;
+        p^.left:=swapp;
+        p^.swaped:=not(p^.swaped);
+    end;
+
+
+    procedure disposetree(p : ptree);
+
+      var
+         symt : psymtable;
+         i : longint;
+
+      begin
+         if not(assigned(p)) then
+           exit;
+         case p^.disposetyp of
+            dt_leftright :
+              begin
+                 if assigned(p^.left) then
+                   disposetree(p^.left);
+                 if assigned(p^.right) then
+                   disposetree(p^.right);
+              end;
+            dt_case :
+              begin
+                 if assigned(p^.left) then
+                   disposetree(p^.left);
+                 if assigned(p^.right) then
+                   disposetree(p^.right);
+                 if assigned(p^.nodes) then
+                   deletecaselabels(p^.nodes);
+                 if assigned(p^.elseblock) then
+                   disposetree(p^.elseblock);
+              end;
+            dt_nothing : ;
+            dt_left    :
+              if assigned(p^.left) then
+                disposetree(p^.left);
+            dt_mbleft :
+              if assigned(p^.left) then
+                disposetree(p^.left);
+            dt_mbleft_and_method :
+              begin
+                 if assigned(p^.left) then disposetree(p^.left);
+                 disposetree(p^.methodpointer);
+              end;
+            dt_typeconv : disposetree(p^.left);
+            dt_inlinen :
+              if assigned(p^.left) then
+                disposetree(p^.left);
+            dt_loop :
+              begin
+                 if assigned(p^.left) then
+                   disposetree(p^.left);
+                 if assigned(p^.right) then
+                   disposetree(p^.right);
+                 if assigned(p^.t1) then
+                   disposetree(p^.t1);
+                 if assigned(p^.t2) then
+                   disposetree(p^.t2);
+              end;
+            dt_onn:
+              begin
+                 if assigned(p^.left) then
+                   disposetree(p^.left);
+                 if assigned(p^.right) then
+                   disposetree(p^.right);
+                 if assigned(p^.exceptsymtable) then
+                   dispose(p^.exceptsymtable,done);
+              end;
+            dt_with :
+              begin
+                 if assigned(p^.left) then
+                   disposetree(p^.left);
+                 if assigned(p^.right) then
+                   disposetree(p^.right);
+                 symt:=p^.withsymtable;
+                 for i:=1 to p^.tablecount do
+                   begin
+                      if assigned(symt) then
+                        begin
+                           p^.withsymtable:=symt^.next;
+                           dispose(symt,done);
+                        end;
+                      symt:=p^.withsymtable;
+                   end;
+              end;
+            else internalerror(12);
+         end;
+         putnode(p);
+      end;
+
+    procedure set_file_line(from,_to : ptree);
+
+      begin
+         if assigned(from) then
+           _to^.fileinfo:=from^.fileinfo;
+      end;
+
+   procedure set_tree_filepos(p : ptree;const filepos : tfileposinfo);
+     begin
+        p^.fileinfo:=filepos;
+     end;
+
+   function genwithnode(symtable : psymtable;l,r : ptree;count : longint) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_with;
+         p^.treetype:=withn;
+         p^.left:=l;
+         p^.right:=r;
+         p^.registers32:=0;
+         { p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         p^.withsymtable:=symtable;
+         p^.tablecount:=count;
+         set_file_line(l,p);
+         genwithnode:=p;
+      end;
+
+    function genfixconstnode(v : longint;def : pdef) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=fixconstn;
+         p^.registers32:=0;
+         { p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=def;
+         p^.value:=v;
+         genfixconstnode:=p;
+      end;
+
+    function gencallparanode(expr,next : ptree) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_leftright;
+         p^.treetype:=callparan;
+         p^.left:=expr;
+         p^.right:=next;
+         p^.registers32:=0;
+         { p^.registers16:=0;
+         p^.registers8:=0; }
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.registersfpu:=0;
+         p^.resulttype:=nil;
+         p^.exact_match_found:=false;
+         p^.is_colon_para:=false;
+         set_file_line(expr,p);
+         gencallparanode:=p;
+      end;
+
+    function gennode(t : ttreetyp;l,r : ptree) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_leftright;
+         p^.treetype:=t;
+         p^.left:=l;
+         p^.right:=r;
+         p^.registers32:=0;
+         { p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         gennode:=p;
+      end;
+
+    function gencasenode(l,r : ptree;nodes : pcaserecord) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_case;
+         p^.treetype:=casen;
+         p^.left:=l;
+         p^.right:=r;
+         p^.nodes:=nodes;
+         p^.registers32:=0;
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         set_file_line(l,p);
+         gencasenode:=p;
+      end;
+
+    function genloopnode(t : ttreetyp;l,r,n1 : ptree;back : boolean) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_loop;
+         p^.treetype:=t;
+         p^.left:=l;
+         p^.right:=r;
+         p^.t1:=n1;
+         p^.t2:=nil;
+         p^.registers32:=0;
+         p^.backward:=back;
+         { p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         set_file_line(l,p);
+         genloopnode:=p;
+      end;
+
+    function genordinalconstnode(v : longint;def : pdef) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=ordconstn;
+         p^.registers32:=0;
+         { p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=def;
+         p^.value:=v;
+         if p^.resulttype^.deftype=orddef then
+          testrange(p^.resulttype,p^.value);
+         genordinalconstnode:=p;
+      end;
+
+    function genenumnode(v : penumsym) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=ordconstn;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=v^.definition;
+         p^.value:=v^.value;
+         testrange(p^.resulttype,p^.value);
+         genenumnode:=p;
+      end;
+
+
+    function genrealconstnode(v : bestreal) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=realconstn;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+{$ifdef i386}
+         p^.resulttype:=c64floatdef;
+         p^.value_real:=v;
+         { default value is double }
+         p^.realtyp:=ait_real_64bit;
+{$endif}
+{$ifdef m68k}
+         p^.resulttype:=new(pfloatdef,init(s32real));
+         p^.value_real:=v;
+         { default value is double }
+         p^.realtyp:=ait_real_32bit;
+{$endif}
+         p^.lab_real:=nil;
+         genrealconstnode:=p;
+      end;
+
+    function genstringconstnode(const s : string) : ptree;
+
+      var
+         p : ptree;
+         l : longint;
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=stringconstn;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         l:=length(s);
+         p^.length:=l;
+         { stringdup write even past a #0 }
+         getmem(p^.value_str,l+1);
+         move(s[1],p^.value_str^,l);
+         p^.value_str[l]:=#0;
+         p^.lab_str:=nil;
+         if cs_ansistrings in aktlocalswitches then
+          begin
+            p^.stringtype:=st_ansistring;
+            p^.resulttype:=cansistringdef;
+          end
+         else
+          begin
+            p^.stringtype:=st_shortstring;
+            p^.resulttype:=cshortstringdef;
+          end;
+
+         genstringconstnode:=p;
+      end;
+
+    function getpcharcopy(p : ptree) : pchar;
+      var
+         pc : pchar;
+      begin
+         pc:=nil;
+         getmem(pc,p^.length+1);
+         if pc=nil then
+           Message(general_f_no_memory_left);
+         move(p^.value_str^,pc^,p^.length+1);
+         getpcharcopy:=pc;
+      end;
+
+
+    function genpcharconstnode(s : pchar;length : longint) : ptree;
+      var
+         p : ptree;
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=stringconstn;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=cshortstringdef;
+         p^.length:=length;
+         p^.value_str:=s;
+         p^.lab_str:=nil;
+         genpcharconstnode:=p;
+      end;
+
+
+    function gensinglenode(t : ttreetyp;l : ptree) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_left;
+         p^.treetype:=t;
+         p^.left:=l;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         gensinglenode:=p;
+      end;
+
+    function genasmnode(p_asm : paasmoutput) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=asmn;
+         p^.registers32:=4;
+         p^.p_asm:=p_asm;
+         p^.object_preserved:=false;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=8;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=8;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         genasmnode:=p;
+      end;
+
+    function genloadcallnode(v: pprocsym;st: psymtable): ptree;
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.treetype:=loadn;
+         p^.resulttype:=v^.definition;
+         p^.symtableentry:=v;
+         p^.symtable:=st;
+         p^.is_first := False;
+         p^.disposetyp:=dt_nothing;
+         genloadcallnode:=p;
+      end;
+
+
+    function gentypedconstloadnode(sym : ptypedconstsym;st : psymtable) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.treetype:=loadn;
+         p^.resulttype:=sym^.definition;
+         p^.symtableentry:=pvarsym(sym);
+         p^.symtable:=st;
+         p^.disposetyp:=dt_nothing;
+         gentypedconstloadnode:=p;
+      end;
+
+    function gentypeconvnode(node : ptree;t : pdef) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_typeconv;
+         p^.treetype:=typeconvn;
+         p^.left:=node;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.convtyp:=tc_equal;
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=t;
+         p^.explizit:=false;
+         set_file_line(node,p);
+         gentypeconvnode:=p;
+      end;
+
+    function gentypenode(t : pdef) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=typen;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=generrordef;
+         p^.typenodetype:=t;
+         gentypenode:=p;
+      end;
+
+    function gencallnode(v : pprocsym;st : psymtable) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.treetype:=calln;
+         p^.symtableprocentry:=v;
+         p^.symtableproc:=st;
+         p^.unit_specific:=false;
+         p^.no_check:=false;
+         p^.return_value_used:=true;
+         p^.disposetyp := dt_leftright;
+         p^.methodpointer:=nil;
+         p^.left:=nil;
+         p^.right:=nil;
+         p^.procdefinition:=nil;
+         gencallnode:=p;
+      end;
+
+    function genmethodcallnode(v : pprocsym;st : psymtable;mp : ptree) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.treetype:=calln;
+         p^.return_value_used:=true;
+         p^.symtableprocentry:=v;
+         p^.symtableproc:=st;
+         p^.disposetyp:=dt_mbleft_and_method;
+         p^.left:=nil;
+         p^.right:=nil;
+         p^.methodpointer:=mp;
+         p^.procdefinition:=nil;
+         genmethodcallnode:=p;
+      end;
+
+    function gensubscriptnode(varsym : pvarsym;l : ptree) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_left;
+         p^.treetype:=subscriptn;
+         p^.left:=l;
+         p^.registers32:=0;
+         p^.vs:=varsym;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         gensubscriptnode:=p;
+      end;
+
+   function genzeronode(t : ttreetyp) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=t;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         genzeronode:=p;
+      end;
+
+   function genlabelnode(t : ttreetyp;nr : plabel) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=t;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         { for security }
+         { nr^.is_used:=true;}
+         p^.labelnr:=nr;
+         genlabelnode:=p;
+      end;
+
+    function genselfnode(_class : pdef) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_nothing;
+         p^.treetype:=selfn;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=_class;
+         genselfnode:=p;
+      end;
+
+   function geninlinenode(number : byte;is_const:boolean;l : ptree) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_inlinen;
+         p^.treetype:=inlinen;
+         p^.left:=l;
+         p^.inlinenumber:=number;
+         p^.inlineconst:=is_const;
+         p^.registers32:=0;
+{         p^.registers16:=0;
+         p^.registers8:=0; }
+         p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=nil;
+         geninlinenode:=p;
+      end;
+
+
+      { uses the callnode to create the new procinline node }
+    function genprocinlinenode(callp,code : ptree) : ptree;
+
+      var
+         p : ptree;
+
+      begin
+         p:=getnode;
+         p^.disposetyp:=dt_left;
+         p^.treetype:=procinlinen;
+         p^.inlineprocdef:=callp^.procdefinition;
+         p^.retoffset:=-4; { less dangerous as zero (PM) }
+         p^.para_offset:=0;
+         p^.para_size:=p^.inlineprocdef^.para_size;
+         if ret_in_param(p^.inlineprocdef^.retdef) then
+           p^.para_size:=p^.para_size+target_os.size_of_pointer;
+         { copy args }
+         p^.left:=getcopy(code);
+         p^.registers32:=code^.registers32;
+         p^.registersfpu:=code^.registersfpu;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=p^.inlineprocdef^.retdef;
+         genprocinlinenode:=p;
+      end;
+
+   function gensetconstnode(s : pconstset;settype : psetdef) : ptree;
+
+     var
+        p : ptree;
+
+     begin
+        p:=getnode;
+        p^.disposetyp:=dt_nothing;
+        p^.treetype:=setconstn;
+        p^.registers32:=0;
+        p^.registersfpu:=0;
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=0;
+{$endif SUPPORT_MMX}
+         p^.resulttype:=settype;
+         p^.left:=nil;
+         new(p^.value_set);
+         p^.value_set^:=s^;
+         gensetconstnode:=p;
+      end;
+
+{$ifdef extdebug}
+    procedure compare_trees(oldp,p : ptree);
+
+      var
+         error_found : boolean;
+
+      begin
+          if oldp^.resulttype<>p^.resulttype then
+            begin
+               error_found:=true;
+               if is_equal(oldp^.resulttype,p^.resulttype) then
+                 comment(v_debug,'resulttype fields are different but equal')
+               else
+                 comment(v_warning,'resulttype fields are really different');
+            end;
+         if oldp^.treetype<>p^.treetype then
+           begin
+              comment(v_warning,'treetype field different');
+              error_found:=true;
+           end
+         else
+           comment(v_debug,' treetype '+tostr(longint(oldp^.treetype)));
+         if oldp^.error<>p^.error then
+           begin
+              comment(v_warning,'error field different');
+              error_found:=true;
+           end;
+         if oldp^.disposetyp<>p^.disposetyp then
+           begin
+              comment(v_warning,'disposetyp field different');
+              error_found:=true;
+           end;
+         { is true, if the right and left operand are swaped }
+         if oldp^.swaped<>p^.swaped then
+           begin
+              comment(v_warning,'swaped field different');
+              error_found:=true;
+           end;
+
+         { the location of the result of this node }
+         if oldp^.location.loc<>p^.location.loc then
+           begin
+              comment(v_warning,'location.loc field different');
+              error_found:=true;
+           end;
+
+          { the number of registers needed to evalute the node }
+          if oldp^.registers32<>p^.registers32 then
+           begin
+              comment(v_warning,'registers32 field different');
+              comment(v_warning,' old '+tostr(oldp^.registers32)+'<> new '+tostr(p^.registers32));
+              error_found:=true;
+           end;
+          if oldp^.registersfpu<>p^.registersfpu then
+           begin
+              comment(v_warning,'registersfpu field different');
+              error_found:=true;
+           end;
+{$ifdef SUPPORT_MMX}
+          if oldp^.registersmmx<>p^.registersmmx then
+           begin
+              comment(v_warning,'registersmmx field different');
+              error_found:=true;
+           end;
+{$endif SUPPORT_MMX}
+          if oldp^.left<>p^.left then
+           begin
+              comment(v_warning,'left field different');
+              error_found:=true;
+           end;
+          if oldp^.right<>p^.right then
+           begin
+              comment(v_warning,'right field different');
+              error_found:=true;
+           end;
+          if oldp^.fileinfo.line<>p^.fileinfo.line then
+            begin
+               comment(v_warning,'fileinfo.line field different');
+               error_found:=true;
+            end;
+          if oldp^.fileinfo.column<>p^.fileinfo.column then
+            begin
+               comment(v_warning,'fileinfo.column field different');
+               error_found:=true;
+            end;
+          if oldp^.fileinfo.fileindex<>p^.fileinfo.fileindex then
+            begin
+               comment(v_warning,'fileinfo.fileindex field different');
+               error_found:=true;
+            end;
+          if oldp^.localswitches<>p^.localswitches then
+            begin
+               comment(v_warning,'localswitches field different');
+               error_found:=true;
+            end;
+{$ifdef extdebug}
+          if oldp^.firstpasscount<>p^.firstpasscount then
+            begin
+               comment(v_warning,'firstpasscount field different');
+               error_found:=true;
+            end;
+{$endif extdebug}
+          if oldp^.treetype=p^.treetype then
+          case oldp^.treetype of
+             addn :
+             begin
+                if oldp^.use_strconcat<>p^.use_strconcat then
+                  begin
+                     comment(v_warning,'use_strconcat field different');
+                     error_found:=true;
+                  end;
+                if oldp^.string_typ<>p^.string_typ then
+                  begin
+                     comment(v_warning,'stringtyp field different');
+                     error_found:=true;
+                  end;
+             end;
+             callparan :
+             {(is_colon_para : boolean;exact_match_found : boolean);}
+             begin
+                if oldp^.is_colon_para<>p^.is_colon_para then
+                  begin
+                     comment(v_warning,'use_strconcat field different');
+                     error_found:=true;
+                  end;
+                if oldp^.exact_match_found<>p^.exact_match_found then
+                  begin
+                     comment(v_warning,'exact_match_found field different');
+                     error_found:=true;
+                  end;
+             end;
+             assignn :
+             {(assigntyp : tassigntyp;concat_string : boolean);}
+             begin
+                if oldp^.assigntyp<>p^.assigntyp then
+                  begin
+                     comment(v_warning,'assigntyp field different');
+                     error_found:=true;
+                  end;
+                if oldp^.concat_string<>p^.concat_string then
+                  begin
+                     comment(v_warning,'concat_string field different');
+                     error_found:=true;
+                  end;
+             end;
+             loadn :
+             {(symtableentry : psym;symtable : psymtable;
+                      is_absolute,is_first : boolean);}
+             begin
+                if oldp^.symtableentry<>p^.symtableentry then
+                  begin
+                     comment(v_warning,'symtableentry field different');
+                     error_found:=true;
+                  end;
+                if oldp^.symtable<>p^.symtable then
+                  begin
+                     comment(v_warning,'symtable field different');
+                     error_found:=true;
+                  end;
+                if oldp^.is_absolute<>p^.is_absolute then
+                  begin
+                     comment(v_warning,'is_absolute field different');
+                     error_found:=true;
+                  end;
+                if oldp^.is_first<>p^.is_first then
+                  begin
+                     comment(v_warning,'is_first field different');
+                     error_found:=true;
+                  end;
+             end;
+             calln :
+             {(symtableprocentry : pprocsym;
+                      symtableproc : psymtable;procdefinition : pprocdef;
+                      methodpointer : ptree;
+                      no_check,unit_specific : boolean);}
+             begin
+                if oldp^.symtableprocentry<>p^.symtableprocentry then
+                  begin
+                     comment(v_warning,'symtableprocentry field different');
+                     error_found:=true;
+                  end;
+                if oldp^.symtableproc<>p^.symtableproc then
+                  begin
+                     comment(v_warning,'symtableproc field different');
+                     error_found:=true;
+                  end;
+                if oldp^.procdefinition<>p^.procdefinition then
+                  begin
+                     comment(v_warning,'procdefinition field different');
+                     error_found:=true;
+                  end;
+                if oldp^.methodpointer<>p^.methodpointer then
+                  begin
+                     comment(v_warning,'methodpointer field different');
+                     error_found:=true;
+                  end;
+                if oldp^.no_check<>p^.no_check then
+                  begin
+                     comment(v_warning,'no_check field different');
+                     error_found:=true;
+                  end;
+                if oldp^.unit_specific<>p^.unit_specific then
+                  begin
+                     error_found:=true;
+                     comment(v_warning,'unit_specific field different');
+                  end;
+             end;
+             ordconstn :
+               begin
+                  if oldp^.value<>p^.value then
+                  begin
+                     comment(v_warning,'value field different');
+                     error_found:=true;
+                  end;
+               end;
+             realconstn :
+               begin
+                  if oldp^.value_real<>p^.value_real then
+                  begin
+                     comment(v_warning,'valued field different');
+                     error_found:=true;
+                  end;
+                  if oldp^.lab_real<>p^.lab_real then
+                  begin
+                     comment(v_warning,'labnumber field different');
+                     error_found:=true;
+                  end;
+                  if oldp^.realtyp<>p^.realtyp then
+                  begin
+                     comment(v_warning,'realtyp field different');
+                     error_found:=true;
+                  end;
+               end;
+           end;
+         if not error_found then
+           comment(v_warning,'did not find difference in trees');
+
+      end;
+{$endif extdebug}
+
+    function equal_trees(t1,t2 : ptree) : boolean;
+
+      begin
+         if t1^.treetype=t2^.treetype then
+           begin
+              case t1^.treetype of
+                 addn,
+                 muln,
+                 equaln,
+                 orn,
+                 xorn,
+                 andn,
+                 unequaln:
+                   begin
+                      equal_trees:=(equal_trees(t1^.left,t2^.left) and
+                                    equal_trees(t1^.right,t2^.right)) or
+                                   (equal_trees(t1^.right,t2^.left) and
+                                    equal_trees(t1^.left,t2^.right));
+                   end;
+                 subn,
+                 divn,
+                 modn,
+                 assignn,
+                 ltn,
+                 lten,
+                 gtn,
+                 gten,
+                 inn,
+                 shrn,
+                 shln,
+                 slashn,
+                 rangen:
+                   begin
+                      equal_trees:=(equal_trees(t1^.left,t2^.left) and
+                                    equal_trees(t1^.right,t2^.right));
+                   end;
+                 umminusn,
+                 notn,
+                 derefn,
+                 addrn:
+                   begin
+                      equal_trees:=(equal_trees(t1^.left,t2^.left));
+                   end;
+                loadn:
+                   begin
+                      equal_trees:=(t1^.symtableentry=t2^.symtableentry)
+                        { not necessary
+                                     and (t1^.symtable=t2^.symtable)};
+                   end;
+                {
+
+                   subscriptn,
+                   ordconstn,typeconvn,calln,callparan,
+                   realconstn,asmn,vecn,
+                   stringconstn,funcretn,selfn,
+                   inlinen,niln,errorn,
+                   typen,hnewn,hdisposen,newn,
+                   disposen,setelen,setconstrn
+                }
+                else equal_trees:=false;
+             end;
+          end
+        else
+          equal_trees:=false;
+     end;
+
+    procedure set_unique(p : ptree);
+
+      begin
+         if assigned(p) then
+           begin
+              case p^.treetype of
+                 vecn:
+                    p^.callunique:=true;
+                 typeconvn:
+                    set_unique(p^.left);
+              end;
+           end;
+      end;
+
+    function get_ordinal_value(p : ptree) : longint;
+      begin
+         if p^.treetype=ordconstn then
+           get_ordinal_value:=p^.value
+         else
+           Message(type_e_ordinal_expr_expected);
+      end;
+
+
+    function is_constnode(p : ptree) : boolean;
+      begin
+        is_constnode:=(p^.treetype in [ordconstn,realconstn,stringconstn,fixconstn,setconstn]);
+      end;
+
+
+    function is_constintnode(p : ptree) : boolean;
+      begin
+         is_constintnode:=(p^.treetype=ordconstn) and is_integer(p^.resulttype);
+      end;
+
+
+    function is_constcharnode(p : ptree) : boolean;
+
+      begin
+         is_constcharnode:=((p^.treetype=ordconstn) and
+           (p^.resulttype^.deftype=orddef) and
+           (porddef(p^.resulttype)^.typ=uchar));
+      end;
+
+    function is_constrealnode(p : ptree) : boolean;
+
+      begin
+         is_constrealnode:=(p^.treetype=realconstn);
+      end;
+
+    function is_constboolnode(p : ptree) : boolean;
+
+      begin
+         is_constboolnode:=((p^.treetype=ordconstn) and
+           (p^.resulttype^.deftype=orddef) and
+           (porddef(p^.resulttype)^.typ in [bool8bit,bool16bit,bool32bit]));
+      end;
+
+    function str_length(p : ptree) : longint;
+
+      begin
+         str_length:=p^.length;
+      end;
+
+
+    function is_emptyset(p : ptree):boolean;
+    {
+      return true if set s is empty
+    }
+      var
+        i : longint;
+      begin
+        i:=0;
+        if p^.treetype=setconstn then
+         begin
+           while (i<32) and (p^.value_set^[i]=0) do
+            inc(i);
+         end;
+        is_emptyset:=(i=32);
+      end;
+
+    function getcopy(p : ptree) : ptree;
+
+      var
+         hp : ptree;
+
+      begin
+         hp:=getnode;
+         hp^:=p^;
+         if assigned(p^.location.reference.symbol) then
+           hp^.location.reference.symbol:=stringdup(p^.location.reference.symbol^);
+         case p^.disposetyp of
+            dt_leftright :
+              begin
+                 if assigned(p^.left) then
+                   hp^.left:=getcopy(p^.left);
+                 if assigned(p^.right) then
+                   hp^.right:=getcopy(p^.right);
+              end;
+            dt_nothing : ;
+            dt_left    :
+              if assigned(p^.left) then
+                hp^.left:=getcopy(p^.left);
+            dt_mbleft :
+              if assigned(p^.left) then
+                hp^.left:=getcopy(p^.left);
+            dt_mbleft_and_method :
+              begin
+                 if assigned(p^.left) then
+                   hp^.left:=getcopy(p^.left);
+                 hp^.methodpointer:=getcopy(p^.methodpointer);
+              end;
+            dt_loop :
+              begin
+                 if assigned(p^.left) then
+                   hp^.left:=getcopy(p^.left);
+                 if assigned(p^.right) then
+                   hp^.right:=getcopy(p^.right);
+                 if assigned(p^.t1) then
+                   hp^.t1:=getcopy(p^.t1);
+                 if assigned(p^.t2) then
+                   hp^.t2:=getcopy(p^.t2);
+              end;
+            dt_typeconv : hp^.left:=getcopy(p^.left);
+            dt_inlinen :
+              if assigned(p^.left) then
+                hp^.left:=getcopy(p^.left);
+            else internalerror(11);
+         end;
+       { now check treetype }
+         case p^.treetype of
+  stringconstn : begin
+                   hp^.value_str:=getpcharcopy(p);
+                   hp^.length:=p^.length;
+                 end;
+     setconstn : begin
+                   new(hp^.value_set);
+                   hp^.value_set:=p^.value_set;
+                 end;
+         end;
+         getcopy:=hp;
+      end;
+
+{$endif dummy}
+
+end.
+{
+  $Log$
+  Revision 1.1  1998-12-15 22:21:53  florian
+    * first rough conversion
+
+}
+