X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Fada%2Ftreepr.adb;fp=gcc%2Fada%2Ftreepr.adb;h=0000000000000000000000000000000000000000;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=44797bb0634f8a39e85bc4c44d7e6746b42ac77d;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb deleted file mode 100644 index 44797bb0..00000000 --- a/gcc/ada/treepr.adb +++ /dev/null @@ -1,1873 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- T R E E P R -- --- -- --- B o d y -- --- -- --- $Revision: 1.1.16.1 $ --- -- --- Copyright (C) 1992-2001 Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, -- --- MA 02111-1307, USA. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Atree; use Atree; -with Csets; use Csets; -with Debug; use Debug; -with Einfo; use Einfo; -with Elists; use Elists; -with Lib; use Lib; -with Namet; use Namet; -with Nlists; use Nlists; -with Output; use Output; -with Sem_Mech; use Sem_Mech; -with Sinfo; use Sinfo; -with Snames; use Snames; -with Sinput; use Sinput; -with Stand; use Stand; -with Stringt; use Stringt; -with Treeprs; use Treeprs; -with Uintp; use Uintp; -with Urealp; use Urealp; -with Uname; use Uname; -with Unchecked_Deallocation; - -package body Treepr is - - use Atree.Unchecked_Access; - -- This module uses the unchecked access functions in package Atree - -- since it does an untyped traversal of the tree (we do not want to - -- count on the structure of the tree being correct in this routine!) - - ---------------------------------- - -- Approach Used for Tree Print -- - ---------------------------------- - - -- When a complete subtree is being printed, a trace phase first marks - -- the nodes and lists to be printed. This trace phase allocates logical - -- numbers corresponding to the order in which the nodes and lists will - -- be printed. The Node_Id, List_Id and Elist_Id values are mapped to - -- logical node numbers using a hash table. Output is done using a set - -- of Print_xxx routines, which are similar to the Write_xxx routines - -- with the same name, except that they do not generate any output in - -- the marking phase. This allows identical logic to be used in the - -- two phases. - - -- Note that the hash table not only holds the serial numbers, but also - -- acts as a record of which nodes have already been visited. In the - -- marking phase, a node has been visited if it is already in the hash - -- table, and in the printing phase, we can tell whether a node has - -- already been printed by looking at the value of the serial number. - - ---------------------- - -- Global Variables -- - ---------------------- - - type Hash_Record is record - Serial : Nat; - -- Serial number for hash table entry. A value of zero means that - -- the entry is currently unused. - - Id : Int; - -- If serial number field is non-zero, contains corresponding Id value - end record; - - type Hash_Table_Type is array (Nat range <>) of Hash_Record; - type Access_Hash_Table_Type is access Hash_Table_Type; - Hash_Table : Access_Hash_Table_Type; - -- The hash table itself, see Serial_Number function for details of use - - Hash_Table_Len : Nat; - -- Range of Hash_Table is from 0 .. Hash_Table_Len - 1 so that dividing - -- by Hash_Table_Len gives a remainder that is in Hash_Table'Range. - - Next_Serial_Number : Nat; - -- Number of last visited node or list. Used during the marking phase to - -- set proper node numbers in the hash table, and during the printing - -- phase to make sure that a given node is not printed more than once. - -- (nodes are printed in order during the printing phase, that's the - -- point of numbering them in the first place!) - - Printing_Descendants : Boolean; - -- True if descendants are being printed, False if not. In the false case, - -- only node Id's are printed. In the true case, node numbers as well as - -- node Id's are printed, as described above. - - type Phase_Type is (Marking, Printing); - -- Type for Phase variable - - Phase : Phase_Type; - -- When an entire tree is being printed, the traversal operates in two - -- phases. The first phase marks the nodes in use by installing node - -- numbers in the node number table. The second phase prints the nodes. - -- This variable indicates the current phase. - - ---------------------- - -- Local Procedures -- - ---------------------- - - procedure Print_End_Span (N : Node_Id); - -- Special routine to print contents of End_Span field of node N. - -- The format includes the implicit source location as well as the - -- value of the field. - - procedure Print_Init; - -- Initialize for printing of tree with descendents - - procedure Print_Term; - -- Clean up after printing of tree with descendents - - procedure Print_Char (C : Character); - -- Print character C if currently in print phase, noop if in marking phase - - procedure Print_Name (N : Name_Id); - -- Print name from names table if currently in print phase, noop if in - -- marking phase. Note that the name is output in mixed case mode. - - procedure Print_Node_Kind (N : Node_Id); - -- Print node kind name in mixed case if in print phase, noop if in - -- marking phase. - - procedure Print_Str (S : String); - -- Print string S if currently in print phase, noop if in marking phase - - procedure Print_Str_Mixed_Case (S : String); - -- Like Print_Str, except that the string is printed in mixed case mode - - procedure Print_Int (I : Int); - -- Print integer I if currently in print phase, noop if in marking phase - - procedure Print_Eol; - -- Print end of line if currently in print phase, noop if in marking phase - - procedure Print_Node_Ref (N : Node_Id); - -- Print "", "" or "Node #nnn" with additional information - -- in the latter case, including the Id and the Nkind of the node. - - procedure Print_List_Ref (L : List_Id); - -- Print "", or "" or "Node list #nnn" - - procedure Print_Elist_Ref (E : Elist_Id); - -- Print "", or "" or "Element list #nnn" - - procedure Print_Entity_Info (Ent : Entity_Id; Prefix : String); - -- Called if the node being printed is an entity. Prints fields from the - -- extension, using routines in Einfo to get the field names and flags. - - procedure Print_Field (Val : Union_Id; Format : UI_Format := Auto); - -- Print representation of Field value (name, tree, string, uint, charcode) - -- The format parameter controls the format of printing in the case of an - -- integer value (see UI_Write for details). - - procedure Print_Flag (F : Boolean); - -- Print True or False - - procedure Print_Node - (N : Node_Id; - Prefix_Str : String; - Prefix_Char : Character); - -- This is the internal routine used to print a single node. Each line of - -- output is preceded by Prefix_Str (which is used to set the indentation - -- level and the bars used to link list elements). In addition, for lines - -- other than the first, an additional character Prefix_Char is output. - - function Serial_Number (Id : Int) return Nat; - -- Given a Node_Id, List_Id or Elist_Id, returns the previously assigned - -- serial number, or zero if no serial number has yet been assigned. - - procedure Set_Serial_Number; - -- Can be called only immediately following a call to Serial_Number that - -- returned a value of zero. Causes the value of Next_Serial_Number to be - -- placed in the hash table (corresponding to the Id argument used in the - -- Serial_Number call), and increments Next_Serial_Number. - - procedure Visit_Node - (N : Node_Id; - Prefix_Str : String; - Prefix_Char : Character); - -- Called to process a single node in the case where descendents are to - -- be printed before every line, and Prefix_Char added to all lines - -- except the header line for the node. - - procedure Visit_List (L : List_Id; Prefix_Str : String); - -- Visit_List is called to process a list in the case where descendents - -- are to be printed. Prefix_Str is to be added to all printed lines. - - procedure Visit_Elist (E : Elist_Id; Prefix_Str : String); - -- Visit_Elist is called to process an element list in the case where - -- descendents are to be printed. Prefix_Str is to be added to all - -- printed lines. - - -------- - -- PE -- - -------- - - procedure PE (E : Elist_Id) is - begin - Print_Tree_Elist (E); - end PE; - - -------- - -- PL -- - -------- - - procedure PL (L : List_Id) is - begin - Print_Tree_List (L); - end PL; - - -------- - -- PN -- - -------- - - procedure PN (N : Node_Id) is - begin - Print_Tree_Node (N); - end PN; - - ---------------- - -- Print_Char -- - ---------------- - - procedure Print_Char (C : Character) is - begin - if Phase = Printing then - Write_Char (C); - end if; - end Print_Char; - - --------------------- - -- Print_Elist_Ref -- - --------------------- - - procedure Print_Elist_Ref (E : Elist_Id) is - begin - if Phase /= Printing then - return; - end if; - - if E = No_Elist then - Write_Str (""); - - elsif Is_Empty_Elmt_List (E) then - Write_Str ("Empty elist, (Elist_Id="); - Write_Int (Int (E)); - Write_Char (')'); - - else - Write_Str ("(Elist_Id="); - Write_Int (Int (E)); - Write_Char (')'); - - if Printing_Descendants then - Write_Str (" #"); - Write_Int (Serial_Number (Int (E))); - end if; - end if; - end Print_Elist_Ref; - - ------------------------- - -- Print_Elist_Subtree -- - ------------------------- - - procedure Print_Elist_Subtree (E : Elist_Id) is - begin - Print_Init; - - Next_Serial_Number := 1; - Phase := Marking; - Visit_Elist (E, ""); - - Next_Serial_Number := 1; - Phase := Printing; - Visit_Elist (E, ""); - - Print_Term; - end Print_Elist_Subtree; - - -------------------- - -- Print_End_Span -- - -------------------- - - procedure Print_End_Span (N : Node_Id) is - Val : constant Uint := End_Span (N); - - begin - UI_Write (Val); - Write_Str (" (Uint = "); - Write_Int (Int (Field5 (N))); - Write_Str (") "); - - if Val /= No_Uint then - Write_Location (End_Location (N)); - end if; - end Print_End_Span; - - ----------------------- - -- Print_Entity_Info -- - ----------------------- - - procedure Print_Entity_Info (Ent : Entity_Id; Prefix : String) is - function Field_Present (U : Union_Id) return Boolean; - -- Returns False unless the value U represents a missing value - -- (Empty, No_Uint, No_Ureal or No_String) - - function Field_Present (U : Union_Id) return Boolean is - begin - return - U /= Union_Id (Empty) and then - U /= To_Union (No_Uint) and then - U /= To_Union (No_Ureal) and then - U /= Union_Id (No_String); - end Field_Present; - - -- Start of processing for Print_Entity_Info - - begin - Print_Str (Prefix); - Print_Str ("Ekind = "); - Print_Str_Mixed_Case (Entity_Kind'Image (Ekind (Ent))); - Print_Eol; - - Print_Str (Prefix); - Print_Str ("Etype = "); - Print_Node_Ref (Etype (Ent)); - Print_Eol; - - if Convention (Ent) /= Convention_Ada then - Print_Str (Prefix); - Print_Str ("Convention = "); - - -- Print convention name skipping the Convention_ at the start - - declare - S : constant String := Convention_Id'Image (Convention (Ent)); - - begin - Print_Str_Mixed_Case (S (12 .. S'Last)); - Print_Eol; - end; - end if; - - if Field_Present (Field6 (Ent)) then - Print_Str (Prefix); - Write_Field6_Name (Ent); - Write_Str (" = "); - Print_Field (Field6 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field7 (Ent)) then - Print_Str (Prefix); - Write_Field7_Name (Ent); - Write_Str (" = "); - Print_Field (Field7 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field8 (Ent)) then - Print_Str (Prefix); - Write_Field8_Name (Ent); - Write_Str (" = "); - Print_Field (Field8 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field9 (Ent)) then - Print_Str (Prefix); - Write_Field9_Name (Ent); - Write_Str (" = "); - Print_Field (Field9 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field10 (Ent)) then - Print_Str (Prefix); - Write_Field10_Name (Ent); - Write_Str (" = "); - Print_Field (Field10 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field11 (Ent)) then - Print_Str (Prefix); - Write_Field11_Name (Ent); - Write_Str (" = "); - Print_Field (Field11 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field12 (Ent)) then - Print_Str (Prefix); - Write_Field12_Name (Ent); - Write_Str (" = "); - Print_Field (Field12 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field13 (Ent)) then - Print_Str (Prefix); - Write_Field13_Name (Ent); - Write_Str (" = "); - Print_Field (Field13 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field14 (Ent)) then - Print_Str (Prefix); - Write_Field14_Name (Ent); - Write_Str (" = "); - Print_Field (Field14 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field15 (Ent)) then - Print_Str (Prefix); - Write_Field15_Name (Ent); - Write_Str (" = "); - Print_Field (Field15 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field16 (Ent)) then - Print_Str (Prefix); - Write_Field16_Name (Ent); - Write_Str (" = "); - Print_Field (Field16 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field17 (Ent)) then - Print_Str (Prefix); - Write_Field17_Name (Ent); - Write_Str (" = "); - Print_Field (Field17 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field18 (Ent)) then - Print_Str (Prefix); - Write_Field18_Name (Ent); - Write_Str (" = "); - Print_Field (Field18 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field19 (Ent)) then - Print_Str (Prefix); - Write_Field19_Name (Ent); - Write_Str (" = "); - Print_Field (Field19 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field20 (Ent)) then - Print_Str (Prefix); - Write_Field20_Name (Ent); - Write_Str (" = "); - Print_Field (Field20 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field21 (Ent)) then - Print_Str (Prefix); - Write_Field21_Name (Ent); - Write_Str (" = "); - Print_Field (Field21 (Ent)); - Print_Eol; - end if; - - if Field_Present (Field22 (Ent)) then - Print_Str (Prefix); - Write_Field22_Name (Ent); - Write_Str (" = "); - - -- Mechanism case has to be handled specially - - if Ekind (Ent) = E_Function or else Is_Formal (Ent) then - declare - M : constant Mechanism_Type := Mechanism (Ent); - - begin - case M is - when Default_Mechanism => Write_Str ("Default"); - when By_Copy => Write_Str ("By_Copy"); - when By_Reference => Write_Str ("By_Reference"); - when By_Descriptor => Write_Str ("By_Descriptor"); - when By_Descriptor_UBS => Write_Str ("By_Descriptor_UBS"); - when By_Descriptor_UBSB => Write_Str ("By_Descriptor_UBSB"); - when By_Descriptor_UBA => Write_Str ("By_Descriptor_UBA"); - when By_Descriptor_S => Write_Str ("By_Descriptor_S"); - when By_Descriptor_SB => Write_Str ("By_Descriptor_SB"); - when By_Descriptor_A => Write_Str ("By_Descriptor_A"); - when By_Descriptor_NCA => Write_Str ("By_Descriptor_NCA"); - - when 1 .. Mechanism_Type'Last => - Write_Str ("By_Copy if size <= "); - Write_Int (Int (M)); - - end case; - end; - - -- Normal case (not Mechanism) - - else - Print_Field (Field22 (Ent)); - end if; - - Print_Eol; - end if; - - if Field_Present (Field23 (Ent)) then - Print_Str (Prefix); - Write_Field23_Name (Ent); - Write_Str (" = "); - Print_Field (Field23 (Ent)); - Print_Eol; - end if; - - Write_Entity_Flags (Ent, Prefix); - - end Print_Entity_Info; - - --------------- - -- Print_Eol -- - --------------- - - procedure Print_Eol is - begin - if Phase = Printing then - Write_Eol; - end if; - end Print_Eol; - - ----------------- - -- Print_Field -- - ----------------- - - procedure Print_Field (Val : Union_Id; Format : UI_Format := Auto) is - begin - if Phase /= Printing then - return; - end if; - - if Val in Node_Range then - Print_Node_Ref (Node_Id (Val)); - - elsif Val in List_Range then - Print_List_Ref (List_Id (Val)); - - elsif Val in Elist_Range then - Print_Elist_Ref (Elist_Id (Val)); - - elsif Val in Names_Range then - Print_Name (Name_Id (Val)); - Write_Str (" (Name_Id="); - Write_Int (Int (Val)); - Write_Char (')'); - - elsif Val in Strings_Range then - Write_String_Table_Entry (String_Id (Val)); - Write_Str (" (String_Id="); - Write_Int (Int (Val)); - Write_Char (')'); - - elsif Val in Uint_Range then - UI_Write (From_Union (Val), Format); - Write_Str (" (Uint = "); - Write_Int (Int (Val)); - Write_Char (')'); - - elsif Val in Ureal_Range then - UR_Write (From_Union (Val)); - Write_Str (" (Ureal = "); - Write_Int (Int (Val)); - Write_Char (')'); - - elsif Val in Char_Code_Range then - Write_Str ("Character code = "); - - declare - C : Char_Code := Char_Code (Val - Char_Code_Bias); - - begin - Write_Int (Int (C)); - Write_Str (" ('"); - Write_Char_Code (C); - Write_Str ("')"); - end; - - else - Print_Str ("****** Incorrect value = "); - Print_Int (Int (Val)); - end if; - end Print_Field; - - ---------------- - -- Print_Flag -- - ---------------- - - procedure Print_Flag (F : Boolean) is - begin - if F then - Print_Str ("True"); - else - Print_Str ("False"); - end if; - end Print_Flag; - - ---------------- - -- Print_Init -- - ---------------- - - procedure Print_Init is - begin - Printing_Descendants := True; - Write_Eol; - - -- Allocate and clear serial number hash table. The size is 150% of - -- the maximum possible number of entries, so that the hash table - -- cannot get significantly overloaded. - - Hash_Table_Len := (150 * (Num_Nodes + Num_Lists + Num_Elists)) / 100; - Hash_Table := new Hash_Table_Type (0 .. Hash_Table_Len - 1); - - for J in Hash_Table'Range loop - Hash_Table (J).Serial := 0; - end loop; - - end Print_Init; - - --------------- - -- Print_Int -- - --------------- - - procedure Print_Int (I : Int) is - begin - if Phase = Printing then - Write_Int (I); - end if; - end Print_Int; - - -------------------- - -- Print_List_Ref -- - -------------------- - - procedure Print_List_Ref (L : List_Id) is - begin - if Phase /= Printing then - return; - end if; - - if No (L) then - Write_Str (""); - - elsif Is_Empty_List (L) then - Write_Str (" (List_Id="); - Write_Int (Int (L)); - Write_Char (')'); - - else - Write_Str ("List"); - - if Printing_Descendants then - Write_Str (" #"); - Write_Int (Serial_Number (Int (L))); - end if; - - Write_Str (" (List_Id="); - Write_Int (Int (L)); - Write_Char (')'); - end if; - end Print_List_Ref; - - ------------------------ - -- Print_List_Subtree -- - ------------------------ - - procedure Print_List_Subtree (L : List_Id) is - begin - Print_Init; - - Next_Serial_Number := 1; - Phase := Marking; - Visit_List (L, ""); - - Next_Serial_Number := 1; - Phase := Printing; - Visit_List (L, ""); - - Print_Term; - end Print_List_Subtree; - - ---------------- - -- Print_Name -- - ---------------- - - procedure Print_Name (N : Name_Id) is - begin - if Phase = Printing then - if N = No_Name then - Print_Str (""); - - elsif N = Error_Name then - Print_Str (""); - - else - Get_Name_String (N); - Print_Char ('"'); - Write_Name (N); - Print_Char ('"'); - end if; - end if; - end Print_Name; - - ---------------- - -- Print_Node -- - ---------------- - - procedure Print_Node - (N : Node_Id; - Prefix_Str : String; - Prefix_Char : Character) - is - F : Fchar; - P : Natural := Pchar_Pos (Nkind (N)); - - Field_To_Be_Printed : Boolean; - Prefix_Str_Char : String (Prefix_Str'First .. Prefix_Str'Last + 1); - - Sfile : Source_File_Index; - Notes : Boolean; - Fmt : UI_Format; - - begin - if Phase /= Printing then - return; - end if; - - if Nkind (N) = N_Integer_Literal and then Print_In_Hex (N) then - Fmt := Hex; - else - Fmt := Auto; - end if; - - Prefix_Str_Char (Prefix_Str'Range) := Prefix_Str; - Prefix_Str_Char (Prefix_Str'Last + 1) := Prefix_Char; - - -- Print header line - - Print_Str (Prefix_Str); - Print_Node_Ref (N); - - Notes := False; - - if Comes_From_Source (N) then - Notes := True; - Print_Str (" (source"); - end if; - - if Analyzed (N) then - if not Notes then - Notes := True; - Print_Str (" ("); - else - Print_Str (","); - end if; - - Print_Str ("analyzed"); - end if; - - if Error_Posted (N) then - if not Notes then - Notes := True; - Print_Str (" ("); - else - Print_Str (","); - end if; - - Print_Str ("posted"); - end if; - - if Notes then - Print_Char (')'); - end if; - - Print_Eol; - - if Is_Rewrite_Substitution (N) then - Print_Str (Prefix_Str); - Print_Str (" Rewritten: original node = "); - Print_Node_Ref (Original_Node (N)); - Print_Eol; - end if; - - if N = Empty then - return; - end if; - - if not Is_List_Member (N) then - Print_Str (Prefix_Str); - Print_Str (" Parent = "); - Print_Node_Ref (Parent (N)); - Print_Eol; - end if; - - -- Print Sloc field if it is set - - if Sloc (N) /= No_Location then - Print_Str (Prefix_Str_Char); - Print_Str ("Sloc = "); - - if Sloc (N) = Standard_Location then - Print_Str ("Standard_Location"); - - elsif Sloc (N) = Standard_ASCII_Location then - Print_Str ("Standard_ASCII_Location"); - - else - Sfile := Get_Source_File_Index (Sloc (N)); - Print_Int (Int (Sloc (N)) - Int (Source_Text (Sfile)'First)); - Write_Str (" "); - Write_Location (Sloc (N)); - end if; - - Print_Eol; - end if; - - -- Print Chars field if present - - if Nkind (N) in N_Has_Chars and then Chars (N) /= No_Name then - Print_Str (Prefix_Str_Char); - Print_Str ("Chars = "); - Print_Name (Chars (N)); - Write_Str (" (Name_Id="); - Write_Int (Int (Chars (N))); - Write_Char (')'); - Print_Eol; - end if; - - -- Special field print operations for non-entity nodes - - if Nkind (N) not in N_Entity then - - -- Deal with Left_Opnd and Right_Opnd fields - - if Nkind (N) in N_Op - or else Nkind (N) = N_And_Then - or else Nkind (N) = N_In - or else Nkind (N) = N_Not_In - or else Nkind (N) = N_Or_Else - then - -- Print Left_Opnd if present - - if Nkind (N) not in N_Unary_Op then - Print_Str (Prefix_Str_Char); - Print_Str ("Left_Opnd = "); - Print_Node_Ref (Left_Opnd (N)); - Print_Eol; - end if; - - -- Print Right_Opnd - - Print_Str (Prefix_Str_Char); - Print_Str ("Right_Opnd = "); - Print_Node_Ref (Right_Opnd (N)); - Print_Eol; - end if; - - -- Print Entity field if operator (other cases of Entity - -- are in the table, so are handled in the normal circuit) - - if Nkind (N) in N_Op and then Present (Entity (N)) then - Print_Str (Prefix_Str_Char); - Print_Str ("Entity = "); - Print_Node_Ref (Entity (N)); - Print_Eol; - end if; - - -- Print special fields if we have a subexpression - - if Nkind (N) in N_Subexpr then - - if Assignment_OK (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Assignment_OK = True"); - Print_Eol; - end if; - - if Do_Range_Check (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Do_Range_Check = True"); - Print_Eol; - end if; - - if Has_Dynamic_Length_Check (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Has_Dynamic_Length_Check = True"); - Print_Eol; - end if; - - if Has_Dynamic_Range_Check (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Has_Dynamic_Range_Check = True"); - Print_Eol; - end if; - - if Is_Controlling_Actual (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Is_Controlling_Actual = True"); - Print_Eol; - end if; - - if Is_Overloaded (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Is_Overloaded = True"); - Print_Eol; - end if; - - if Is_Static_Expression (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Is_Static_Expression = True"); - Print_Eol; - end if; - - if Must_Not_Freeze (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Must_Not_Freeze = True"); - Print_Eol; - end if; - - if Paren_Count (N) /= 0 then - Print_Str (Prefix_Str_Char); - Print_Str ("Paren_Count = "); - Print_Int (Int (Paren_Count (N))); - Print_Eol; - end if; - - if Raises_Constraint_Error (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Raise_Constraint_Error = True"); - Print_Eol; - end if; - - end if; - - -- Print Do_Overflow_Check field if present - - if Nkind (N) in N_Op and then Do_Overflow_Check (N) then - Print_Str (Prefix_Str_Char); - Print_Str ("Do_Overflow_Check = True"); - Print_Eol; - end if; - - -- Print Etype field if present (printing of this field for entities - -- is handled by the Print_Entity_Info procedure). - - if Nkind (N) in N_Has_Etype - and then Present (Etype (N)) - then - Print_Str (Prefix_Str_Char); - Print_Str ("Etype = "); - Print_Node_Ref (Etype (N)); - Print_Eol; - end if; - end if; - - -- Loop to print fields included in Pchars array - - while P < Pchar_Pos (Node_Kind'Succ (Nkind (N))) loop - F := Pchars (P); - P := P + 1; - - -- Check for case of False flag, which we never print, or - -- an Empty field, which is also never printed - - case F is - when F_Field1 => - Field_To_Be_Printed := Field1 (N) /= Union_Id (Empty); - - when F_Field2 => - Field_To_Be_Printed := Field2 (N) /= Union_Id (Empty); - - when F_Field3 => - Field_To_Be_Printed := Field3 (N) /= Union_Id (Empty); - - when F_Field4 => - Field_To_Be_Printed := Field4 (N) /= Union_Id (Empty); - - when F_Field5 => - Field_To_Be_Printed := Field5 (N) /= Union_Id (Empty); - - when F_Flag4 => Field_To_Be_Printed := Flag4 (N); - when F_Flag5 => Field_To_Be_Printed := Flag5 (N); - when F_Flag6 => Field_To_Be_Printed := Flag6 (N); - when F_Flag7 => Field_To_Be_Printed := Flag7 (N); - when F_Flag8 => Field_To_Be_Printed := Flag8 (N); - when F_Flag9 => Field_To_Be_Printed := Flag9 (N); - when F_Flag10 => Field_To_Be_Printed := Flag10 (N); - when F_Flag11 => Field_To_Be_Printed := Flag11 (N); - when F_Flag12 => Field_To_Be_Printed := Flag12 (N); - when F_Flag13 => Field_To_Be_Printed := Flag13 (N); - when F_Flag14 => Field_To_Be_Printed := Flag14 (N); - when F_Flag15 => Field_To_Be_Printed := Flag15 (N); - when F_Flag16 => Field_To_Be_Printed := Flag16 (N); - when F_Flag17 => Field_To_Be_Printed := Flag17 (N); - when F_Flag18 => Field_To_Be_Printed := Flag18 (N); - - -- Flag1,2,3 are no longer used - - when F_Flag1 => raise Program_Error; - when F_Flag2 => raise Program_Error; - when F_Flag3 => raise Program_Error; - - end case; - - -- Print field if it is to be printed - - if Field_To_Be_Printed then - Print_Str (Prefix_Str_Char); - - while P < Pchar_Pos (Node_Kind'Succ (Nkind (N))) - and then Pchars (P) not in Fchar - loop - Print_Char (Pchars (P)); - P := P + 1; - end loop; - - Print_Str (" = "); - - case F is - when F_Field1 => Print_Field (Field1 (N), Fmt); - when F_Field2 => Print_Field (Field2 (N), Fmt); - when F_Field3 => Print_Field (Field3 (N), Fmt); - when F_Field4 => Print_Field (Field4 (N), Fmt); - - -- Special case End_Span = Uint5 - - when F_Field5 => - if Nkind (N) = N_Case_Statement - or else Nkind (N) = N_If_Statement - then - Print_End_Span (N); - else - Print_Field (Field5 (N), Fmt); - end if; - - when F_Flag4 => Print_Flag (Flag4 (N)); - when F_Flag5 => Print_Flag (Flag5 (N)); - when F_Flag6 => Print_Flag (Flag6 (N)); - when F_Flag7 => Print_Flag (Flag7 (N)); - when F_Flag8 => Print_Flag (Flag8 (N)); - when F_Flag9 => Print_Flag (Flag9 (N)); - when F_Flag10 => Print_Flag (Flag10 (N)); - when F_Flag11 => Print_Flag (Flag11 (N)); - when F_Flag12 => Print_Flag (Flag12 (N)); - when F_Flag13 => Print_Flag (Flag13 (N)); - when F_Flag14 => Print_Flag (Flag14 (N)); - when F_Flag15 => Print_Flag (Flag15 (N)); - when F_Flag16 => Print_Flag (Flag16 (N)); - when F_Flag17 => Print_Flag (Flag17 (N)); - when F_Flag18 => Print_Flag (Flag18 (N)); - - -- Flag1,2,3 are no longer used - - when F_Flag1 => raise Program_Error; - when F_Flag2 => raise Program_Error; - when F_Flag3 => raise Program_Error; - end case; - - Print_Eol; - - -- Field is not to be printed (False flag field) - - else - while P < Pchar_Pos (Node_Kind'Succ (Nkind (N))) - and then Pchars (P) not in Fchar - loop - P := P + 1; - end loop; - end if; - - end loop; - - -- Print entity information for entities - - if Nkind (N) in N_Entity then - Print_Entity_Info (N, Prefix_Str_Char); - end if; - - end Print_Node; - - --------------------- - -- Print_Node_Kind -- - --------------------- - - procedure Print_Node_Kind (N : Node_Id) is - Ucase : Boolean; - S : constant String := Node_Kind'Image (Nkind (N)); - - begin - if Phase = Printing then - Ucase := True; - - -- Note: the call to Fold_Upper in this loop is to get past the GNAT - -- bug of 'Image returning lower case instead of upper case. - - for J in S'Range loop - if Ucase then - Write_Char (Fold_Upper (S (J))); - else - Write_Char (Fold_Lower (S (J))); - end if; - - Ucase := (S (J) = '_'); - end loop; - end if; - end Print_Node_Kind; - - -------------------- - -- Print_Node_Ref -- - -------------------- - - procedure Print_Node_Ref (N : Node_Id) is - S : Nat; - - begin - if Phase /= Printing then - return; - end if; - - if N = Empty then - Write_Str (""); - - elsif N = Error then - Write_Str (""); - - else - if Printing_Descendants then - S := Serial_Number (Int (N)); - - if S /= 0 then - Write_Str ("Node"); - Write_Str (" #"); - Write_Int (S); - Write_Char (' '); - end if; - end if; - - Print_Node_Kind (N); - - if Nkind (N) in N_Has_Chars then - Write_Char (' '); - Print_Name (Chars (N)); - end if; - - if Nkind (N) in N_Entity then - Write_Str (" (Entity_Id="); - else - Write_Str (" (Node_Id="); - end if; - - Write_Int (Int (N)); - - if Sloc (N) <= Standard_Location then - Write_Char ('s'); - end if; - - Write_Char (')'); - - end if; - end Print_Node_Ref; - - ------------------------ - -- Print_Node_Subtree -- - ------------------------ - - procedure Print_Node_Subtree (N : Node_Id) is - begin - Print_Init; - - Next_Serial_Number := 1; - Phase := Marking; - Visit_Node (N, "", ' '); - - Next_Serial_Number := 1; - Phase := Printing; - Visit_Node (N, "", ' '); - - Print_Term; - end Print_Node_Subtree; - - --------------- - -- Print_Str -- - --------------- - - procedure Print_Str (S : String) is - begin - if Phase = Printing then - Write_Str (S); - end if; - end Print_Str; - - -------------------------- - -- Print_Str_Mixed_Case -- - -------------------------- - - procedure Print_Str_Mixed_Case (S : String) is - Ucase : Boolean; - - begin - if Phase = Printing then - Ucase := True; - - for J in S'Range loop - if Ucase then - Write_Char (S (J)); - else - Write_Char (Fold_Lower (S (J))); - end if; - - Ucase := (S (J) = '_'); - end loop; - end if; - end Print_Str_Mixed_Case; - - ---------------- - -- Print_Term -- - ---------------- - - procedure Print_Term is - procedure Free is new Unchecked_Deallocation - (Hash_Table_Type, Access_Hash_Table_Type); - - begin - Free (Hash_Table); - end Print_Term; - - --------------------- - -- Print_Tree_Elist -- - --------------------- - - procedure Print_Tree_Elist (E : Elist_Id) is - M : Elmt_Id; - - begin - Printing_Descendants := False; - Phase := Printing; - - Print_Elist_Ref (E); - Print_Eol; - - M := First_Elmt (E); - - if No (M) then - Print_Str (""); - Print_Eol; - - else - loop - Print_Char ('|'); - Print_Eol; - exit when No (Next_Elmt (M)); - Print_Node (Node (M), "", '|'); - Next_Elmt (M); - end loop; - - Print_Node (Node (M), "", ' '); - Print_Eol; - end if; - end Print_Tree_Elist; - - --------------------- - -- Print_Tree_List -- - --------------------- - - procedure Print_Tree_List (L : List_Id) is - N : Node_Id; - - begin - Printing_Descendants := False; - Phase := Printing; - - Print_List_Ref (L); - Print_Str (" List_Id="); - Print_Int (Int (L)); - Print_Eol; - - N := First (L); - - if N = Empty then - Print_Str (""); - Print_Eol; - - else - loop - Print_Char ('|'); - Print_Eol; - exit when Next (N) = Empty; - Print_Node (N, "", '|'); - Next (N); - end loop; - - Print_Node (N, "", ' '); - Print_Eol; - end if; - end Print_Tree_List; - - --------------------- - -- Print_Tree_Node -- - --------------------- - - procedure Print_Tree_Node (N : Node_Id; Label : String := "") is - begin - Printing_Descendants := False; - Phase := Printing; - Print_Node (N, Label, ' '); - end Print_Tree_Node; - - -------- - -- PT -- - -------- - - procedure PT (N : Node_Id) is - begin - Print_Node_Subtree (N); - end PT; - - ------------------- - -- Serial_Number -- - ------------------- - - -- The hashing algorithm is to use the remainder of the ID value divided - -- by the hash table length as the starting point in the table, and then - -- handle collisions by serial searching wrapping at the end of the table. - - Hash_Slot : Nat; - -- Set by an unsuccessful call to Serial_Number (one which returns zero) - -- to save the slot that should be used if Set_Serial_Number is called. - - function Serial_Number (Id : Int) return Nat is - H : Int := Id mod Hash_Table_Len; - - begin - while Hash_Table (H).Serial /= 0 loop - - if Id = Hash_Table (H).Id then - return Hash_Table (H).Serial; - end if; - - H := H + 1; - - if H > Hash_Table'Last then - H := 0; - end if; - end loop; - - -- Entry was not found, save slot number for possible subsequent call - -- to Set_Serial_Number, and unconditionally save the Id in this slot - -- in case of such a call (the Id field is never read if the serial - -- number of the slot is zero, so this is harmless in the case where - -- Set_Serial_Number is not subsequently called). - - Hash_Slot := H; - Hash_Table (H).Id := Id; - return 0; - - end Serial_Number; - - ----------------------- - -- Set_Serial_Number -- - ----------------------- - - procedure Set_Serial_Number is - begin - Hash_Table (Hash_Slot).Serial := Next_Serial_Number; - Next_Serial_Number := Next_Serial_Number + 1; - end Set_Serial_Number; - - --------------- - -- Tree_Dump -- - --------------- - - procedure Tree_Dump is - procedure Underline; - -- Put underline under string we just printed - - procedure Underline is - Col : constant Int := Column; - - begin - Write_Eol; - - while Col > Column loop - Write_Char ('-'); - end loop; - - Write_Eol; - end Underline; - - -- Start of processing for Tree_Dump. Note that we turn off the tree dump - -- flags immediately, before starting the dump. This avoids generating two - -- copies of the dump if an abort occurs after printing the dump, and more - -- importantly, avoids an infinite loop if an abort occurs during the dump. - - -- Note: unlike in the source print case (in Sprint), we do not output - -- separate trees for each unit. Instead the -df debug switch causes the - -- tree that is output from the main unit to trace references into other - -- units (normally such references are not traced). Since all other units - -- are linked to the main unit by at least one reference, this causes all - -- tree nodes to be included in the output tree. - - begin - if Debug_Flag_Y then - Debug_Flag_Y := False; - Write_Eol; - Write_Str ("Tree created for Standard (spec) "); - Underline; - Print_Node_Subtree (Standard_Package_Node); - Write_Eol; - end if; - - if Debug_Flag_T then - Debug_Flag_T := False; - - Write_Eol; - Write_Str ("Tree created for "); - Write_Unit_Name (Unit_Name (Main_Unit)); - Underline; - Print_Node_Subtree (Cunit (Main_Unit)); - Write_Eol; - end if; - - end Tree_Dump; - - ----------------- - -- Visit_Elist -- - ----------------- - - procedure Visit_Elist (E : Elist_Id; Prefix_Str : String) is - M : Elmt_Id; - N : Node_Id; - S : constant Nat := Serial_Number (Int (E)); - - begin - -- In marking phase, return if already marked, otherwise set next - -- serial number in hash table for later reference. - - if Phase = Marking then - if S /= 0 then - return; -- already visited - else - Set_Serial_Number; - end if; - - -- In printing phase, if already printed, then return, otherwise we - -- are printing the next item, so increment the serial number. - - else - if S < Next_Serial_Number then - return; -- already printed - else - Next_Serial_Number := Next_Serial_Number + 1; - end if; - end if; - - -- Now process the list (Print calls have no effect in marking phase) - - Print_Str (Prefix_Str); - Print_Elist_Ref (E); - Print_Eol; - - if Is_Empty_Elmt_List (E) then - Print_Str (Prefix_Str); - Print_Str ("(Empty element list)"); - Print_Eol; - Print_Eol; - - else - if Phase = Printing then - M := First_Elmt (E); - while Present (M) loop - N := Node (M); - Print_Str (Prefix_Str); - Print_Str (" "); - Print_Node_Ref (N); - Print_Eol; - Next_Elmt (M); - end loop; - - Print_Str (Prefix_Str); - Print_Eol; - end if; - - M := First_Elmt (E); - while Present (M) loop - Visit_Node (Node (M), Prefix_Str, ' '); - Next_Elmt (M); - end loop; - end if; - end Visit_Elist; - - ---------------- - -- Visit_List -- - ---------------- - - procedure Visit_List (L : List_Id; Prefix_Str : String) is - N : Node_Id; - S : constant Nat := Serial_Number (Int (L)); - - begin - -- In marking phase, return if already marked, otherwise set next - -- serial number in hash table for later reference. - - if Phase = Marking then - if S /= 0 then - return; - else - Set_Serial_Number; - end if; - - -- In printing phase, if already printed, then return, otherwise we - -- are printing the next item, so increment the serial number. - - else - if S < Next_Serial_Number then - return; -- already printed - else - Next_Serial_Number := Next_Serial_Number + 1; - end if; - end if; - - -- Now process the list (Print calls have no effect in marking phase) - - Print_Str (Prefix_Str); - Print_List_Ref (L); - Print_Eol; - - Print_Str (Prefix_Str); - Print_Str ("|Parent = "); - Print_Node_Ref (Parent (L)); - Print_Eol; - - N := First (L); - - if N = Empty then - Print_Str (Prefix_Str); - Print_Str ("(Empty list)"); - Print_Eol; - Print_Eol; - - else - Print_Str (Prefix_Str); - Print_Char ('|'); - Print_Eol; - - while Next (N) /= Empty loop - Visit_Node (N, Prefix_Str, '|'); - Next (N); - end loop; - end if; - - Visit_Node (N, Prefix_Str, ' '); - end Visit_List; - - ---------------- - -- Visit_Node -- - ---------------- - - procedure Visit_Node - (N : Node_Id; - Prefix_Str : String; - Prefix_Char : Character) - is - New_Prefix : String (Prefix_Str'First .. Prefix_Str'Last + 2); - -- Prefix string for printing referenced fields - - procedure Visit_Descendent - (D : Union_Id; - No_Indent : Boolean := False); - -- This procedure tests the given value of one of the Fields referenced - -- by the current node to determine whether to visit it recursively. - -- Normally No_Indent is false, which means tha the visited node will - -- be indented using New_Prefix. If No_Indent is set to True, then - -- this indentation is skipped, and Prefix_Str is used for the call - -- to print the descendent. No_Indent is effective only if the - -- referenced descendent is a node. - - ---------------------- - -- Visit_Descendent -- - ---------------------- - - procedure Visit_Descendent - (D : Union_Id; - No_Indent : Boolean := False) - is - begin - -- Case of descendent is a node - - if D in Node_Range then - - -- Don't bother about Empty or Error descendents - - if D <= Union_Id (Empty_Or_Error) then - return; - end if; - - declare - Nod : constant Node_Or_Entity_Id := Node_Or_Entity_Id (D); - - begin - -- Descendents in one of the standardly compiled internal - -- packages are normally ignored, unless the parent is also - -- in such a package (happens when Standard itself is output) - -- or if the -df switch is set which causes all links to be - -- followed, even into package standard. - - if Sloc (Nod) <= Standard_Location then - if Sloc (N) > Standard_Location - and then not Debug_Flag_F - then - return; - end if; - - -- Don't bother about a descendent in a different unit than - -- the node we came from unless the -df switch is set. Note - -- that we know at this point that Sloc (D) > Standard_Location - - -- Note: the tests for No_Location here just make sure that we - -- don't blow up on a node which is missing an Sloc value. This - -- should not normally happen. - - else - if (Sloc (N) <= Standard_Location - or else Sloc (N) = No_Location - or else Sloc (Nod) = No_Location - or else not In_Same_Source_Unit (Nod, N)) - and then not Debug_Flag_F - then - return; - end if; - end if; - - -- Don't bother visiting a source node that has a parent which - -- is not the node we came from. We prefer to trace such nodes - -- from their real parents. This causes the tree to be printed - -- in a more coherent order, e.g. a defining identifier listed - -- next to its corresponding declaration, instead of next to - -- some semantic reference. - - -- This test is skipped for nodes in standard packages unless - -- the -dy option is set (which outputs the tree for standard) - - -- Also, always follow pointers to Is_Itype entities, - -- since we want to list these when they are first referenced. - - if Parent (Nod) /= Empty - and then Comes_From_Source (Nod) - and then Parent (Nod) /= N - and then (Sloc (N) > Standard_Location or else Debug_Flag_Y) - then - return; - end if; - - -- If we successfully fall through all the above tests (which - -- execute a return if the node is not to be visited), we can - -- go ahead and visit the node! - - if No_Indent then - Visit_Node (Nod, Prefix_Str, Prefix_Char); - else - Visit_Node (Nod, New_Prefix, ' '); - end if; - end; - - -- Case of descendent is a list - - elsif D in List_Range then - - -- Don't bother with a missing list, empty list or error list - - if D = Union_Id (No_List) - or else D = Union_Id (Error_List) - or else Is_Empty_List (List_Id (D)) - then - return; - - -- Otherwise we can visit the list. Note that we don't bother - -- to do the parent test that we did for the node case, because - -- it just does not happen that lists are referenced more than - -- one place in the tree. We aren't counting on this being the - -- case to generate valid output, it is just that we don't need - -- in practice to worry about listing the list at a place that - -- is inconvenient. - - else - Visit_List (List_Id (D), New_Prefix); - end if; - - -- Case of descendent is an element list - - elsif D in Elist_Range then - - -- Don't bother with a missing list, or an empty list - - if D = Union_Id (No_Elist) - or else Is_Empty_Elmt_List (Elist_Id (D)) - then - return; - - -- Otherwise, visit the referenced element list - - else - Visit_Elist (Elist_Id (D), New_Prefix); - end if; - - -- For all other kinds of descendents (strings, names, uints etc), - -- there is nothing to visit (the contents of the field will be - -- printed when we print the containing node, but what concerns - -- us now is looking for descendents in the tree. - - else - null; - end if; - end Visit_Descendent; - - -- Start of processing for Visit_Node - - begin - if N = Empty then - return; - end if; - - -- Set fatal error node in case we get a blow up during the trace - - Current_Error_Node := N; - - New_Prefix (Prefix_Str'Range) := Prefix_Str; - New_Prefix (Prefix_Str'Last + 1) := Prefix_Char; - New_Prefix (Prefix_Str'Last + 2) := ' '; - - -- In the marking phase, all we do is to set the serial number - - if Phase = Marking then - if Serial_Number (Int (N)) /= 0 then - return; -- already visited - else - Set_Serial_Number; - end if; - - -- In the printing phase, we print the node - - else - if Serial_Number (Int (N)) < Next_Serial_Number then - - -- Here we have already visited the node, but if it is in - -- a list, we still want to print the reference, so that - -- it is clear that it belongs to the list. - - if Is_List_Member (N) then - Print_Str (Prefix_Str); - Print_Node_Ref (N); - Print_Eol; - Print_Str (Prefix_Str); - Print_Char (Prefix_Char); - Print_Str ("(already output)"); - Print_Eol; - Print_Str (Prefix_Str); - Print_Char (Prefix_Char); - Print_Eol; - end if; - - return; - - else - Print_Node (N, Prefix_Str, Prefix_Char); - Print_Str (Prefix_Str); - Print_Char (Prefix_Char); - Print_Eol; - Next_Serial_Number := Next_Serial_Number + 1; - end if; - end if; - - -- Visit all descendents of this node - - if Nkind (N) not in N_Entity then - Visit_Descendent (Field1 (N)); - Visit_Descendent (Field2 (N)); - Visit_Descendent (Field3 (N)); - Visit_Descendent (Field4 (N)); - Visit_Descendent (Field5 (N)); - - -- Entity case - - else - Visit_Descendent (Field1 (N)); - Visit_Descendent (Field3 (N)); - Visit_Descendent (Field4 (N)); - Visit_Descendent (Field5 (N)); - Visit_Descendent (Field6 (N)); - Visit_Descendent (Field7 (N)); - Visit_Descendent (Field8 (N)); - Visit_Descendent (Field9 (N)); - Visit_Descendent (Field10 (N)); - Visit_Descendent (Field11 (N)); - Visit_Descendent (Field12 (N)); - Visit_Descendent (Field13 (N)); - Visit_Descendent (Field14 (N)); - Visit_Descendent (Field15 (N)); - Visit_Descendent (Field16 (N)); - Visit_Descendent (Field17 (N)); - Visit_Descendent (Field18 (N)); - Visit_Descendent (Field19 (N)); - Visit_Descendent (Field20 (N)); - Visit_Descendent (Field21 (N)); - Visit_Descendent (Field22 (N)); - Visit_Descendent (Field23 (N)); - - -- You may be wondering why we omitted Field2 above. The answer - -- is that this is the Next_Entity field, and we want to treat - -- it rather specially. Why? Because a Next_Entity link does not - -- correspond to a level deeper in the tree, and we do not want - -- the tree to march off to the right of the page due to bogus - -- indentations coming from this effect. - - -- To prevent this, what we do is to control references via - -- Next_Entity only from the first entity on a given scope - -- chain, and we keep them all at the same level. Of course - -- if an entity has already been referenced it is not printed. - - if Present (Next_Entity (N)) - and then Present (Scope (N)) - and then First_Entity (Scope (N)) = N - then - declare - Nod : Node_Id; - - begin - Nod := N; - while Present (Nod) loop - Visit_Descendent (Union_Id (Next_Entity (Nod))); - Nod := Next_Entity (Nod); - end loop; - end; - end if; - end if; - end Visit_Node; - -end Treepr;