File : treepr.adb


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                         GNAT COMPILER COMPONENTS                         --
   4 --                                                                          --
   5 --                               T R E E P R                                --
   6 --                                                                          --
   7 --                                 B o d y                                  --
   8 --                                                                          --
   9 --          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
  10 --                                                                          --
  11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  12 -- terms of the  GNU General Public License as published  by the Free Soft- --
  13 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
  14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  17 -- for  more details.  You should have  received  a copy of the GNU General --
  18 -- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
  19 -- http://www.gnu.org/licenses for a complete copy of the license.          --
  20 --                                                                          --
  21 -- GNAT was originally developed  by the GNAT team at  New York University. --
  22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
  23 --                                                                          --
  24 ------------------------------------------------------------------------------
  25 
  26 with Aspects;  use Aspects;
  27 with Atree;    use Atree;
  28 with Csets;    use Csets;
  29 with Debug;    use Debug;
  30 with Einfo;    use Einfo;
  31 with Elists;   use Elists;
  32 with Lib;      use Lib;
  33 with Namet;    use Namet;
  34 with Nlists;   use Nlists;
  35 with Output;   use Output;
  36 with Sem_Mech; use Sem_Mech;
  37 with Sinfo;    use Sinfo;
  38 with Snames;   use Snames;
  39 with Sinput;   use Sinput;
  40 with Stand;    use Stand;
  41 with Stringt;  use Stringt;
  42 with SCIL_LL;  use SCIL_LL;
  43 with Treeprs;  use Treeprs;
  44 with Uintp;    use Uintp;
  45 with Urealp;   use Urealp;
  46 with Uname;    use Uname;
  47 with Unchecked_Deallocation;
  48 
  49 package body Treepr is
  50 
  51    use Atree.Unchecked_Access;
  52    --  This module uses the unchecked access functions in package Atree
  53    --  since it does an untyped traversal of the tree (we do not want to
  54    --  count on the structure of the tree being correct in this routine).
  55 
  56    ----------------------------------
  57    -- Approach Used for Tree Print --
  58    ----------------------------------
  59 
  60    --  When a complete subtree is being printed, a trace phase first marks
  61    --  the nodes and lists to be printed. This trace phase allocates logical
  62    --  numbers corresponding to the order in which the nodes and lists will
  63    --  be printed. The Node_Id, List_Id and Elist_Id values are mapped to
  64    --  logical node numbers using a hash table. Output is done using a set
  65    --  of Print_xxx routines, which are similar to the Write_xxx routines
  66    --  with the same name, except that they do not generate any output in
  67    --  the marking phase. This allows identical logic to be used in the
  68    --  two phases.
  69 
  70    --  Note that the hash table not only holds the serial numbers, but also
  71    --  acts as a record of which nodes have already been visited. In the
  72    --  marking phase, a node has been visited if it is already in the hash
  73    --  table, and in the printing phase, we can tell whether a node has
  74    --  already been printed by looking at the value of the serial number.
  75 
  76    ----------------------
  77    -- Global Variables --
  78    ----------------------
  79 
  80    type Hash_Record is record
  81       Serial : Nat;
  82       --  Serial number for hash table entry. A value of zero means that
  83       --  the entry is currently unused.
  84 
  85       Id : Int;
  86       --  If serial number field is non-zero, contains corresponding Id value
  87    end record;
  88 
  89    type Hash_Table_Type is array (Nat range <>) of Hash_Record;
  90    type Access_Hash_Table_Type is access Hash_Table_Type;
  91    Hash_Table : Access_Hash_Table_Type;
  92    --  The hash table itself, see Serial_Number function for details of use
  93 
  94    Hash_Table_Len : Nat;
  95    --  Range of Hash_Table is from 0 .. Hash_Table_Len - 1 so that dividing
  96    --  by Hash_Table_Len gives a remainder that is in Hash_Table'Range.
  97 
  98    Next_Serial_Number : Nat;
  99    --  Number of last visited node or list. Used during the marking phase to
 100    --  set proper node numbers in the hash table, and during the printing
 101    --  phase to make sure that a given node is not printed more than once.
 102    --  (nodes are printed in order during the printing phase, that's the
 103    --  point of numbering them in the first place).
 104 
 105    Printing_Descendants : Boolean;
 106    --  True if descendants are being printed, False if not. In the false case,
 107    --  only node Id's are printed. In the true case, node numbers as well as
 108    --  node Id's are printed, as described above.
 109 
 110    type Phase_Type is (Marking, Printing);
 111    --  Type for Phase variable
 112 
 113    Phase : Phase_Type;
 114    --  When an entire tree is being printed, the traversal operates in two
 115    --  phases. The first phase marks the nodes in use by installing node
 116    --  numbers in the node number table. The second phase prints the nodes.
 117    --  This variable indicates the current phase.
 118 
 119    ----------------------
 120    -- Local Procedures --
 121    ----------------------
 122 
 123    procedure Print_End_Span (N : Node_Id);
 124    --  Special routine to print contents of End_Span field of node N.
 125    --  The format includes the implicit source location as well as the
 126    --  value of the field.
 127 
 128    procedure Print_Init;
 129    --  Initialize for printing of tree with descendants
 130 
 131    procedure Print_Term;
 132    --  Clean up after printing of tree with descendants
 133 
 134    procedure Print_Char (C : Character);
 135    --  Print character C if currently in print phase, noop if in marking phase
 136 
 137    procedure Print_Name (N : Name_Id);
 138    --  Print name from names table if currently in print phase, noop if in
 139    --  marking phase. Note that the name is output in mixed case mode.
 140 
 141    procedure Print_Node_Header (N : Node_Id);
 142    --  Print header line used by Print_Node and Print_Node_Briefly
 143 
 144    procedure Print_Node_Kind (N : Node_Id);
 145    --  Print node kind name in mixed case if in print phase, noop if in
 146    --  marking phase.
 147 
 148    procedure Print_Str (S : String);
 149    --  Print string S if currently in print phase, noop if in marking phase
 150 
 151    procedure Print_Str_Mixed_Case (S : String);
 152    --  Like Print_Str, except that the string is printed in mixed case mode
 153 
 154    procedure Print_Int (I : Int);
 155    --  Print integer I if currently in print phase, noop if in marking phase
 156 
 157    procedure Print_Eol;
 158    --  Print end of line if currently in print phase, noop if in marking phase
 159 
 160    procedure Print_Node_Ref (N : Node_Id);
 161    --  Print "<empty>", "<error>" or "Node #nnn" with additional information
 162    --  in the latter case, including the Id and the Nkind of the node.
 163 
 164    procedure Print_List_Ref (L : List_Id);
 165    --  Print "<no list>", or "<empty node list>" or "Node list #nnn"
 166 
 167    procedure Print_Elist_Ref (E : Elist_Id);
 168    --  Print "<no elist>", or "<empty element list>" or "Element list #nnn"
 169 
 170    procedure Print_Entity_Info (Ent : Entity_Id; Prefix : String);
 171    --  Called if the node being printed is an entity. Prints fields from the
 172    --  extension, using routines in Einfo to get the field names and flags.
 173 
 174    procedure Print_Field (Val : Union_Id; Format : UI_Format := Auto);
 175    --  Print representation of Field value (name, tree, string, uint, charcode)
 176    --  The format parameter controls the format of printing in the case of an
 177    --  integer value (see UI_Write for details).
 178 
 179    procedure Print_Flag (F : Boolean);
 180    --  Print True or False
 181 
 182    procedure Print_Node
 183      (N           : Node_Id;
 184       Prefix_Str  : String;
 185       Prefix_Char : Character);
 186    --  This is the internal routine used to print a single node. Each line of
 187    --  output is preceded by Prefix_Str (which is used to set the indentation
 188    --  level and the bars used to link list elements). In addition, for lines
 189    --  other than the first, an additional character Prefix_Char is output.
 190 
 191    function Serial_Number (Id : Int) return Nat;
 192    --  Given a Node_Id, List_Id or Elist_Id, returns the previously assigned
 193    --  serial number, or zero if no serial number has yet been assigned.
 194 
 195    procedure Set_Serial_Number;
 196    --  Can be called only immediately following a call to Serial_Number that
 197    --  returned a value of zero. Causes the value of Next_Serial_Number to be
 198    --  placed in the hash table (corresponding to the Id argument used in the
 199    --  Serial_Number call), and increments Next_Serial_Number.
 200 
 201    procedure Visit_Node
 202      (N           : Node_Id;
 203       Prefix_Str  : String;
 204       Prefix_Char : Character);
 205    --  Called to process a single node in the case where descendants are to
 206    --  be printed before every line, and Prefix_Char added to all lines
 207    --  except the header line for the node.
 208 
 209    procedure Visit_List (L : List_Id; Prefix_Str : String);
 210    --  Visit_List is called to process a list in the case where descendants
 211    --  are to be printed. Prefix_Str is to be added to all printed lines.
 212 
 213    procedure Visit_Elist (E : Elist_Id; Prefix_Str : String);
 214    --  Visit_Elist is called to process an element list in the case where
 215    --  descendants are to be printed. Prefix_Str is to be added to all
 216    --  printed lines.
 217 
 218    -------
 219    -- p --
 220    -------
 221 
 222    function p (N : Union_Id) return Node_Or_Entity_Id is
 223    begin
 224       case N is
 225          when List_Low_Bound .. List_High_Bound - 1 =>
 226             return Nlists.Parent (List_Id (N));
 227 
 228          when Node_Range =>
 229             return Atree.Parent (Node_Or_Entity_Id (N));
 230 
 231          when others =>
 232             Write_Int (Int (N));
 233             Write_Str (" is not a Node_Id or List_Id value");
 234             Write_Eol;
 235             return Empty;
 236       end case;
 237    end p;
 238 
 239    ---------
 240    -- par --
 241    ---------
 242 
 243    function par (N : Union_Id) return Node_Or_Entity_Id renames p;
 244 
 245    --------
 246    -- pe --
 247    --------
 248 
 249    procedure pe (N : Union_Id) renames pn;
 250 
 251    --------
 252    -- pl --
 253    --------
 254 
 255    procedure pl (L : Int) is
 256       Lid : Int;
 257 
 258    begin
 259       if L < 0 then
 260          Lid := L;
 261 
 262       --  This is the case where we transform e.g. +36 to -99999936
 263 
 264       else
 265          if L <= 9 then
 266             Lid := -(99999990 + L);
 267          elsif L <= 99 then
 268             Lid := -(99999900 + L);
 269          elsif L <= 999 then
 270             Lid := -(99999000 + L);
 271          elsif L <= 9999 then
 272             Lid := -(99990000 + L);
 273          elsif L <= 99999 then
 274             Lid := -(99900000 + L);
 275          elsif L <= 999999 then
 276             Lid := -(99000000 + L);
 277          elsif L <= 9999999 then
 278             Lid := -(90000000 + L);
 279          else
 280             Lid := -L;
 281          end if;
 282       end if;
 283 
 284       --  Now output the list
 285 
 286       Print_Tree_List (List_Id (Lid));
 287    end pl;
 288 
 289    --------
 290    -- pn --
 291    --------
 292 
 293    procedure pn (N : Union_Id) is
 294    begin
 295       case N is
 296          when List_Low_Bound .. List_High_Bound - 1 =>
 297             pl (Int (N));
 298          when Node_Range =>
 299             Print_Tree_Node (Node_Id (N));
 300          when Elist_Range =>
 301             Print_Tree_Elist (Elist_Id (N));
 302          when Elmt_Range =>
 303             declare
 304                Id : constant Elmt_Id := Elmt_Id (N);
 305             begin
 306                if No (Id) then
 307                   Write_Str ("No_Elmt");
 308                   Write_Eol;
 309                else
 310                   Write_Str ("Elmt_Id --> ");
 311                   Print_Tree_Node (Node (Id));
 312                end if;
 313             end;
 314          when Names_Range =>
 315             Namet.wn (Name_Id (N));
 316          when Strings_Range =>
 317             Write_String_Table_Entry (String_Id (N));
 318          when Uint_Range =>
 319             Uintp.pid (From_Union (N));
 320          when Ureal_Range =>
 321             Urealp.pr (From_Union (N));
 322          when others =>
 323             Write_Str ("Invalid Union_Id: ");
 324             Write_Int (Int (N));
 325             Write_Eol;
 326       end case;
 327    end pn;
 328 
 329    --------
 330    -- pp --
 331    --------
 332 
 333    procedure pp (N : Union_Id) renames pn;
 334 
 335    ---------
 336    -- ppp --
 337    ---------
 338 
 339    procedure ppp (N : Union_Id) renames pt;
 340 
 341    ----------------
 342    -- Print_Char --
 343    ----------------
 344 
 345    procedure Print_Char (C : Character) is
 346    begin
 347       if Phase = Printing then
 348          Write_Char (C);
 349       end if;
 350    end Print_Char;
 351 
 352    ---------------------
 353    -- Print_Elist_Ref --
 354    ---------------------
 355 
 356    procedure Print_Elist_Ref (E : Elist_Id) is
 357    begin
 358       if Phase /= Printing then
 359          return;
 360       end if;
 361 
 362       if E = No_Elist then
 363          Write_Str ("<no elist>");
 364 
 365       elsif Is_Empty_Elmt_List (E) then
 366          Write_Str ("Empty elist, (Elist_Id=");
 367          Write_Int (Int (E));
 368          Write_Char (')');
 369 
 370       else
 371          Write_Str ("(Elist_Id=");
 372          Write_Int (Int (E));
 373          Write_Char (')');
 374 
 375          if Printing_Descendants then
 376             Write_Str (" #");
 377             Write_Int (Serial_Number (Int (E)));
 378          end if;
 379       end if;
 380    end Print_Elist_Ref;
 381 
 382    -------------------------
 383    -- Print_Elist_Subtree --
 384    -------------------------
 385 
 386    procedure Print_Elist_Subtree (E : Elist_Id) is
 387    begin
 388       Print_Init;
 389 
 390       Next_Serial_Number := 1;
 391       Phase := Marking;
 392       Visit_Elist (E, "");
 393 
 394       Next_Serial_Number := 1;
 395       Phase := Printing;
 396       Visit_Elist (E, "");
 397 
 398       Print_Term;
 399    end Print_Elist_Subtree;
 400 
 401    --------------------
 402    -- Print_End_Span --
 403    --------------------
 404 
 405    procedure Print_End_Span (N : Node_Id) is
 406       Val : constant Uint := End_Span (N);
 407 
 408    begin
 409       UI_Write (Val);
 410       Write_Str (" (Uint = ");
 411       Write_Int (Int (Field5 (N)));
 412       Write_Str (")  ");
 413 
 414       if Val /= No_Uint then
 415          Write_Location (End_Location (N));
 416       end if;
 417    end Print_End_Span;
 418 
 419    -----------------------
 420    -- Print_Entity_Info --
 421    -----------------------
 422 
 423    procedure Print_Entity_Info (Ent : Entity_Id; Prefix : String) is
 424       function Field_Present (U : Union_Id) return Boolean;
 425       --  Returns False unless the value U represents a missing value
 426       --  (Empty, No_Uint, No_Ureal or No_String)
 427 
 428       function Field_Present (U : Union_Id) return Boolean is
 429       begin
 430          return
 431             U /= Union_Id (Empty)    and then
 432             U /= To_Union (No_Uint)  and then
 433             U /= To_Union (No_Ureal) and then
 434             U /= Union_Id (No_String);
 435       end Field_Present;
 436 
 437    --  Start of processing for Print_Entity_Info
 438 
 439    begin
 440       Print_Str (Prefix);
 441       Print_Str ("Ekind = ");
 442       Print_Str_Mixed_Case (Entity_Kind'Image (Ekind (Ent)));
 443       Print_Eol;
 444 
 445       Print_Str (Prefix);
 446       Print_Str ("Etype = ");
 447       Print_Node_Ref (Etype (Ent));
 448       Print_Eol;
 449 
 450       if Convention (Ent) /= Convention_Ada then
 451          Print_Str (Prefix);
 452          Print_Str ("Convention = ");
 453 
 454          --  Print convention name skipping the Convention_ at the start
 455 
 456          declare
 457             S : constant String := Convention_Id'Image (Convention (Ent));
 458 
 459          begin
 460             Print_Str_Mixed_Case (S (12 .. S'Last));
 461             Print_Eol;
 462          end;
 463       end if;
 464 
 465       if Field_Present (Field6 (Ent)) then
 466          Print_Str (Prefix);
 467          Write_Field6_Name (Ent);
 468          Write_Str (" = ");
 469          Print_Field (Field6 (Ent));
 470          Print_Eol;
 471       end if;
 472 
 473       if Field_Present (Field7 (Ent)) then
 474          Print_Str (Prefix);
 475          Write_Field7_Name (Ent);
 476          Write_Str (" = ");
 477          Print_Field (Field7 (Ent));
 478          Print_Eol;
 479       end if;
 480 
 481       if Field_Present (Field8 (Ent)) then
 482          Print_Str (Prefix);
 483          Write_Field8_Name (Ent);
 484          Write_Str (" = ");
 485          Print_Field (Field8 (Ent));
 486          Print_Eol;
 487       end if;
 488 
 489       if Field_Present (Field9 (Ent)) then
 490          Print_Str (Prefix);
 491          Write_Field9_Name (Ent);
 492          Write_Str (" = ");
 493          Print_Field (Field9 (Ent));
 494          Print_Eol;
 495       end if;
 496 
 497       if Field_Present (Field10 (Ent)) then
 498          Print_Str (Prefix);
 499          Write_Field10_Name (Ent);
 500          Write_Str (" = ");
 501          Print_Field (Field10 (Ent));
 502          Print_Eol;
 503       end if;
 504 
 505       if Field_Present (Field11 (Ent)) then
 506          Print_Str (Prefix);
 507          Write_Field11_Name (Ent);
 508          Write_Str (" = ");
 509          Print_Field (Field11 (Ent));
 510          Print_Eol;
 511       end if;
 512 
 513       if Field_Present (Field12 (Ent)) then
 514          Print_Str (Prefix);
 515          Write_Field12_Name (Ent);
 516          Write_Str (" = ");
 517          Print_Field (Field12 (Ent));
 518          Print_Eol;
 519       end if;
 520 
 521       if Field_Present (Field13 (Ent)) then
 522          Print_Str (Prefix);
 523          Write_Field13_Name (Ent);
 524          Write_Str (" = ");
 525          Print_Field (Field13 (Ent));
 526          Print_Eol;
 527       end if;
 528 
 529       if Field_Present (Field14 (Ent)) then
 530          Print_Str (Prefix);
 531          Write_Field14_Name (Ent);
 532          Write_Str (" = ");
 533          Print_Field (Field14 (Ent));
 534          Print_Eol;
 535       end if;
 536 
 537       if Field_Present (Field15 (Ent)) then
 538          Print_Str (Prefix);
 539          Write_Field15_Name (Ent);
 540          Write_Str (" = ");
 541          Print_Field (Field15 (Ent));
 542          Print_Eol;
 543       end if;
 544 
 545       if Field_Present (Field16 (Ent)) then
 546          Print_Str (Prefix);
 547          Write_Field16_Name (Ent);
 548          Write_Str (" = ");
 549          Print_Field (Field16 (Ent));
 550          Print_Eol;
 551       end if;
 552 
 553       if Field_Present (Field17 (Ent)) then
 554          Print_Str (Prefix);
 555          Write_Field17_Name (Ent);
 556          Write_Str (" = ");
 557          Print_Field (Field17 (Ent));
 558          Print_Eol;
 559       end if;
 560 
 561       if Field_Present (Field18 (Ent)) then
 562          Print_Str (Prefix);
 563          Write_Field18_Name (Ent);
 564          Write_Str (" = ");
 565          Print_Field (Field18 (Ent));
 566          Print_Eol;
 567       end if;
 568 
 569       if Field_Present (Field19 (Ent)) then
 570          Print_Str (Prefix);
 571          Write_Field19_Name (Ent);
 572          Write_Str (" = ");
 573          Print_Field (Field19 (Ent));
 574          Print_Eol;
 575       end if;
 576 
 577       if Field_Present (Field20 (Ent)) then
 578          Print_Str (Prefix);
 579          Write_Field20_Name (Ent);
 580          Write_Str (" = ");
 581          Print_Field (Field20 (Ent));
 582          Print_Eol;
 583       end if;
 584 
 585       if Field_Present (Field21 (Ent)) then
 586          Print_Str (Prefix);
 587          Write_Field21_Name (Ent);
 588          Write_Str (" = ");
 589          Print_Field (Field21 (Ent));
 590          Print_Eol;
 591       end if;
 592 
 593       if Field_Present (Field22 (Ent)) then
 594          Print_Str (Prefix);
 595          Write_Field22_Name (Ent);
 596          Write_Str (" = ");
 597 
 598          --  Mechanism case has to be handled specially
 599 
 600          if Ekind (Ent) = E_Function or else Is_Formal (Ent) then
 601             declare
 602                M : constant Mechanism_Type := Mechanism (Ent);
 603 
 604             begin
 605                case M is
 606                   when Default_Mechanism        =>
 607                      Write_Str ("Default");
 608 
 609                   when By_Copy                  =>
 610                      Write_Str ("By_Copy");
 611 
 612                   when By_Reference             =>
 613                      Write_Str ("By_Reference");
 614 
 615                   when 1 .. Mechanism_Type'Last =>
 616                      Write_Str ("By_Copy if size <= ");
 617                      Write_Int (Int (M));
 618                end case;
 619             end;
 620 
 621          --  Normal case (not Mechanism)
 622 
 623          else
 624             Print_Field (Field22 (Ent));
 625          end if;
 626 
 627          Print_Eol;
 628       end if;
 629 
 630       if Field_Present (Field23 (Ent)) then
 631          Print_Str (Prefix);
 632          Write_Field23_Name (Ent);
 633          Write_Str (" = ");
 634          Print_Field (Field23 (Ent));
 635          Print_Eol;
 636       end if;
 637 
 638       if Field_Present (Field24 (Ent)) then
 639          Print_Str (Prefix);
 640          Write_Field24_Name (Ent);
 641          Write_Str (" = ");
 642          Print_Field (Field24 (Ent));
 643          Print_Eol;
 644       end if;
 645 
 646       if Field_Present (Field25 (Ent)) then
 647          Print_Str (Prefix);
 648          Write_Field25_Name (Ent);
 649          Write_Str (" = ");
 650          Print_Field (Field25 (Ent));
 651          Print_Eol;
 652       end if;
 653 
 654       if Field_Present (Field26 (Ent)) then
 655          Print_Str (Prefix);
 656          Write_Field26_Name (Ent);
 657          Write_Str (" = ");
 658          Print_Field (Field26 (Ent));
 659          Print_Eol;
 660       end if;
 661 
 662       if Field_Present (Field27 (Ent)) then
 663          Print_Str (Prefix);
 664          Write_Field27_Name (Ent);
 665          Write_Str (" = ");
 666          Print_Field (Field27 (Ent));
 667          Print_Eol;
 668       end if;
 669 
 670       if Field_Present (Field28 (Ent)) then
 671          Print_Str (Prefix);
 672          Write_Field28_Name (Ent);
 673          Write_Str (" = ");
 674          Print_Field (Field28 (Ent));
 675          Print_Eol;
 676       end if;
 677 
 678       if Field_Present (Field29 (Ent)) then
 679          Print_Str (Prefix);
 680          Write_Field29_Name (Ent);
 681          Write_Str (" = ");
 682          Print_Field (Field29 (Ent));
 683          Print_Eol;
 684       end if;
 685 
 686       if Field_Present (Field30 (Ent)) then
 687          Print_Str (Prefix);
 688          Write_Field30_Name (Ent);
 689          Write_Str (" = ");
 690          Print_Field (Field30 (Ent));
 691          Print_Eol;
 692       end if;
 693 
 694       if Field_Present (Field31 (Ent)) then
 695          Print_Str (Prefix);
 696          Write_Field31_Name (Ent);
 697          Write_Str (" = ");
 698          Print_Field (Field31 (Ent));
 699          Print_Eol;
 700       end if;
 701 
 702       if Field_Present (Field32 (Ent)) then
 703          Print_Str (Prefix);
 704          Write_Field32_Name (Ent);
 705          Write_Str (" = ");
 706          Print_Field (Field32 (Ent));
 707          Print_Eol;
 708       end if;
 709 
 710       if Field_Present (Field33 (Ent)) then
 711          Print_Str (Prefix);
 712          Write_Field33_Name (Ent);
 713          Write_Str (" = ");
 714          Print_Field (Field33 (Ent));
 715          Print_Eol;
 716       end if;
 717 
 718       if Field_Present (Field34 (Ent)) then
 719          Print_Str (Prefix);
 720          Write_Field34_Name (Ent);
 721          Write_Str (" = ");
 722          Print_Field (Field34 (Ent));
 723          Print_Eol;
 724       end if;
 725 
 726       if Field_Present (Field35 (Ent)) then
 727          Print_Str (Prefix);
 728          Write_Field35_Name (Ent);
 729          Write_Str (" = ");
 730          Print_Field (Field35 (Ent));
 731          Print_Eol;
 732       end if;
 733 
 734       if Field_Present (Field36 (Ent)) then
 735          Print_Str (Prefix);
 736          Write_Field36_Name (Ent);
 737          Write_Str (" = ");
 738          Print_Field (Field36 (Ent));
 739          Print_Eol;
 740       end if;
 741 
 742       if Field_Present (Field37 (Ent)) then
 743          Print_Str (Prefix);
 744          Write_Field37_Name (Ent);
 745          Write_Str (" = ");
 746          Print_Field (Field37 (Ent));
 747          Print_Eol;
 748       end if;
 749 
 750       if Field_Present (Field38 (Ent)) then
 751          Print_Str (Prefix);
 752          Write_Field38_Name (Ent);
 753          Write_Str (" = ");
 754          Print_Field (Field38 (Ent));
 755          Print_Eol;
 756       end if;
 757 
 758       if Field_Present (Field39 (Ent)) then
 759          Print_Str (Prefix);
 760          Write_Field39_Name (Ent);
 761          Write_Str (" = ");
 762          Print_Field (Field39 (Ent));
 763          Print_Eol;
 764       end if;
 765 
 766       if Field_Present (Field40 (Ent)) then
 767          Print_Str (Prefix);
 768          Write_Field40_Name (Ent);
 769          Write_Str (" = ");
 770          Print_Field (Field40 (Ent));
 771          Print_Eol;
 772       end if;
 773 
 774       if Field_Present (Field41 (Ent)) then
 775          Print_Str (Prefix);
 776          Write_Field41_Name (Ent);
 777          Write_Str (" = ");
 778          Print_Field (Field41 (Ent));
 779          Print_Eol;
 780       end if;
 781 
 782       Write_Entity_Flags (Ent, Prefix);
 783    end Print_Entity_Info;
 784 
 785    ---------------
 786    -- Print_Eol --
 787    ---------------
 788 
 789    procedure Print_Eol is
 790    begin
 791       if Phase = Printing then
 792          Write_Eol;
 793       end if;
 794    end Print_Eol;
 795 
 796    -----------------
 797    -- Print_Field --
 798    -----------------
 799 
 800    procedure Print_Field (Val : Union_Id; Format : UI_Format := Auto) is
 801    begin
 802       if Phase /= Printing then
 803          return;
 804       end if;
 805 
 806       if Val in Node_Range then
 807          Print_Node_Ref (Node_Id (Val));
 808 
 809       elsif Val in List_Range then
 810          Print_List_Ref (List_Id (Val));
 811 
 812       elsif Val in Elist_Range then
 813          Print_Elist_Ref (Elist_Id (Val));
 814 
 815       elsif Val in Names_Range then
 816          Print_Name (Name_Id (Val));
 817          Write_Str (" (Name_Id=");
 818          Write_Int (Int (Val));
 819          Write_Char (')');
 820 
 821       elsif Val in Strings_Range then
 822          Write_String_Table_Entry (String_Id (Val));
 823          Write_Str (" (String_Id=");
 824          Write_Int (Int (Val));
 825          Write_Char (')');
 826 
 827       elsif Val in Uint_Range then
 828          UI_Write (From_Union (Val), Format);
 829          Write_Str (" (Uint = ");
 830          Write_Int (Int (Val));
 831          Write_Char (')');
 832 
 833       elsif Val in Ureal_Range then
 834          UR_Write (From_Union (Val));
 835          Write_Str (" (Ureal = ");
 836          Write_Int (Int (Val));
 837          Write_Char (')');
 838 
 839       else
 840          Print_Str ("****** Incorrect value = ");
 841          Print_Int (Int (Val));
 842       end if;
 843    end Print_Field;
 844 
 845    ----------------
 846    -- Print_Flag --
 847    ----------------
 848 
 849    procedure Print_Flag (F : Boolean) is
 850    begin
 851       if F then
 852          Print_Str ("True");
 853       else
 854          Print_Str ("False");
 855       end if;
 856    end Print_Flag;
 857 
 858    ----------------
 859    -- Print_Init --
 860    ----------------
 861 
 862    procedure Print_Init is
 863    begin
 864       Printing_Descendants := True;
 865       Write_Eol;
 866 
 867       --  Allocate and clear serial number hash table. The size is 150% of
 868       --  the maximum possible number of entries, so that the hash table
 869       --  cannot get significantly overloaded.
 870 
 871       Hash_Table_Len := (150 * (Num_Nodes + Num_Lists + Num_Elists)) / 100;
 872       Hash_Table := new Hash_Table_Type  (0 .. Hash_Table_Len - 1);
 873 
 874       for J in Hash_Table'Range loop
 875          Hash_Table (J).Serial := 0;
 876       end loop;
 877 
 878    end Print_Init;
 879 
 880    ---------------
 881    -- Print_Int --
 882    ---------------
 883 
 884    procedure Print_Int (I : Int) is
 885    begin
 886       if Phase = Printing then
 887          Write_Int (I);
 888       end if;
 889    end Print_Int;
 890 
 891    --------------------
 892    -- Print_List_Ref --
 893    --------------------
 894 
 895    procedure Print_List_Ref (L : List_Id) is
 896    begin
 897       if Phase /= Printing then
 898          return;
 899       end if;
 900 
 901       if No (L) then
 902          Write_Str ("<no list>");
 903 
 904       elsif Is_Empty_List (L) then
 905          Write_Str ("<empty list> (List_Id=");
 906          Write_Int (Int (L));
 907          Write_Char (')');
 908 
 909       else
 910          Write_Str ("List");
 911 
 912          if Printing_Descendants then
 913             Write_Str (" #");
 914             Write_Int (Serial_Number (Int (L)));
 915          end if;
 916 
 917          Write_Str (" (List_Id=");
 918          Write_Int (Int (L));
 919          Write_Char (')');
 920       end if;
 921    end Print_List_Ref;
 922 
 923    ------------------------
 924    -- Print_List_Subtree --
 925    ------------------------
 926 
 927    procedure Print_List_Subtree (L : List_Id) is
 928    begin
 929       Print_Init;
 930 
 931       Next_Serial_Number := 1;
 932       Phase := Marking;
 933       Visit_List (L, "");
 934 
 935       Next_Serial_Number := 1;
 936       Phase := Printing;
 937       Visit_List (L, "");
 938 
 939       Print_Term;
 940    end Print_List_Subtree;
 941 
 942    ----------------
 943    -- Print_Name --
 944    ----------------
 945 
 946    procedure Print_Name (N : Name_Id) is
 947    begin
 948       if Phase = Printing then
 949          if N = No_Name then
 950             Print_Str ("<No_Name>");
 951 
 952          elsif N = Error_Name then
 953             Print_Str ("<Error_Name>");
 954 
 955          elsif Is_Valid_Name (N) then
 956             Get_Name_String (N);
 957             Print_Char ('"');
 958             Write_Name (N);
 959             Print_Char ('"');
 960 
 961          else
 962             Print_Str ("<invalid name ???>");
 963          end if;
 964       end if;
 965    end Print_Name;
 966 
 967    ----------------
 968    -- Print_Node --
 969    ----------------
 970 
 971    procedure Print_Node
 972      (N           : Node_Id;
 973       Prefix_Str  : String;
 974       Prefix_Char : Character)
 975    is
 976       F : Fchar;
 977       P : Natural;
 978 
 979       Field_To_Be_Printed : Boolean;
 980       Prefix_Str_Char     : String (Prefix_Str'First .. Prefix_Str'Last + 1);
 981 
 982       Sfile : Source_File_Index;
 983       Fmt   : UI_Format;
 984 
 985    begin
 986       if Phase /= Printing then
 987          return;
 988       end if;
 989 
 990       --  If there is no such node, indicate that. Skip the rest, so we don't
 991       --  crash getting fields of the nonexistent node.
 992 
 993       if N > Atree_Private_Part.Nodes.Last then
 994          Print_Str ("No such node: ");
 995          Print_Int (Int (N));
 996          Print_Eol;
 997          return;
 998       end if;
 999 
1000       Prefix_Str_Char (Prefix_Str'Range)    := Prefix_Str;
1001       Prefix_Str_Char (Prefix_Str'Last + 1) := Prefix_Char;
1002 
1003       --  Print header line
1004 
1005       Print_Str (Prefix_Str);
1006       Print_Node_Header (N);
1007 
1008       if Is_Rewrite_Substitution (N) then
1009          Print_Str (Prefix_Str);
1010          Print_Str (" Rewritten: original node = ");
1011          Print_Node_Ref (Original_Node (N));
1012          Print_Eol;
1013       end if;
1014 
1015       if N = Empty then
1016          return;
1017       end if;
1018 
1019       if not Is_List_Member (N) then
1020          Print_Str (Prefix_Str);
1021          Print_Str (" Parent = ");
1022          Print_Node_Ref (Parent (N));
1023          Print_Eol;
1024       end if;
1025 
1026       --  Print Sloc field if it is set
1027 
1028       if Sloc (N) /= No_Location then
1029          Print_Str (Prefix_Str_Char);
1030          Print_Str ("Sloc = ");
1031 
1032          if Sloc (N) = Standard_Location then
1033             Print_Str ("Standard_Location");
1034 
1035          elsif Sloc (N) = Standard_ASCII_Location then
1036             Print_Str ("Standard_ASCII_Location");
1037 
1038          else
1039             Sfile := Get_Source_File_Index (Sloc (N));
1040             Print_Int (Int (Sloc (N)) - Int (Source_Text (Sfile)'First));
1041             Write_Str ("  ");
1042             Write_Location (Sloc (N));
1043          end if;
1044 
1045          Print_Eol;
1046       end if;
1047 
1048       --  Print Chars field if present
1049 
1050       if Nkind (N) in N_Has_Chars and then Chars (N) /= No_Name then
1051          Print_Str (Prefix_Str_Char);
1052          Print_Str ("Chars = ");
1053          Print_Name (Chars (N));
1054          Write_Str (" (Name_Id=");
1055          Write_Int (Int (Chars (N)));
1056          Write_Char (')');
1057          Print_Eol;
1058       end if;
1059 
1060       --  Special field print operations for non-entity nodes
1061 
1062       if Nkind (N) not in N_Entity then
1063 
1064          --  Deal with Left_Opnd and Right_Opnd fields
1065 
1066          if Nkind (N) in N_Op
1067            or else Nkind (N) in N_Short_Circuit
1068            or else Nkind (N) in N_Membership_Test
1069          then
1070             --  Print Left_Opnd if present
1071 
1072             if Nkind (N) not in N_Unary_Op then
1073                Print_Str (Prefix_Str_Char);
1074                Print_Str ("Left_Opnd = ");
1075                Print_Node_Ref (Left_Opnd (N));
1076                Print_Eol;
1077             end if;
1078 
1079             --  Print Right_Opnd
1080 
1081             Print_Str (Prefix_Str_Char);
1082             Print_Str ("Right_Opnd = ");
1083             Print_Node_Ref (Right_Opnd (N));
1084             Print_Eol;
1085          end if;
1086 
1087          --  Print Entity field if operator (other cases of Entity
1088          --  are in the table, so are handled in the normal circuit)
1089 
1090          if Nkind (N) in N_Op and then Present (Entity (N)) then
1091             Print_Str (Prefix_Str_Char);
1092             Print_Str ("Entity = ");
1093             Print_Node_Ref (Entity (N));
1094             Print_Eol;
1095          end if;
1096 
1097          --  Print special fields if we have a subexpression
1098 
1099          if Nkind (N) in N_Subexpr then
1100 
1101             if Assignment_OK (N) then
1102                Print_Str (Prefix_Str_Char);
1103                Print_Str ("Assignment_OK = True");
1104                Print_Eol;
1105             end if;
1106 
1107             if Do_Range_Check (N) then
1108                Print_Str (Prefix_Str_Char);
1109                Print_Str ("Do_Range_Check = True");
1110                Print_Eol;
1111             end if;
1112 
1113             if Has_Dynamic_Length_Check (N) then
1114                Print_Str (Prefix_Str_Char);
1115                Print_Str ("Has_Dynamic_Length_Check = True");
1116                Print_Eol;
1117             end if;
1118 
1119             if Has_Aspects (N) then
1120                Print_Str (Prefix_Str_Char);
1121                Print_Str ("Has_Aspects = True");
1122                Print_Eol;
1123             end if;
1124 
1125             if Has_Dynamic_Range_Check (N) then
1126                Print_Str (Prefix_Str_Char);
1127                Print_Str ("Has_Dynamic_Range_Check = True");
1128                Print_Eol;
1129             end if;
1130 
1131             if Is_Controlling_Actual (N) then
1132                Print_Str (Prefix_Str_Char);
1133                Print_Str ("Is_Controlling_Actual = True");
1134                Print_Eol;
1135             end if;
1136 
1137             if Is_Overloaded (N) then
1138                Print_Str (Prefix_Str_Char);
1139                Print_Str ("Is_Overloaded = True");
1140                Print_Eol;
1141             end if;
1142 
1143             if Is_Static_Expression (N) then
1144                Print_Str (Prefix_Str_Char);
1145                Print_Str ("Is_Static_Expression = True");
1146                Print_Eol;
1147             end if;
1148 
1149             if Must_Not_Freeze (N) then
1150                Print_Str (Prefix_Str_Char);
1151                Print_Str ("Must_Not_Freeze = True");
1152                Print_Eol;
1153             end if;
1154 
1155             if Paren_Count (N) /= 0 then
1156                Print_Str (Prefix_Str_Char);
1157                Print_Str ("Paren_Count = ");
1158                Print_Int (Int (Paren_Count (N)));
1159                Print_Eol;
1160             end if;
1161 
1162             if Raises_Constraint_Error (N) then
1163                Print_Str (Prefix_Str_Char);
1164                Print_Str ("Raise_Constraint_Error = True");
1165                Print_Eol;
1166             end if;
1167 
1168          end if;
1169 
1170          --  Print Do_Overflow_Check field if present
1171 
1172          if Nkind (N) in N_Op and then Do_Overflow_Check (N) then
1173             Print_Str (Prefix_Str_Char);
1174             Print_Str ("Do_Overflow_Check = True");
1175             Print_Eol;
1176          end if;
1177 
1178          --  Print Etype field if present (printing of this field for entities
1179          --  is handled by the Print_Entity_Info procedure).
1180 
1181          if Nkind (N) in N_Has_Etype and then Present (Etype (N)) then
1182             Print_Str (Prefix_Str_Char);
1183             Print_Str ("Etype = ");
1184             Print_Node_Ref (Etype (N));
1185             Print_Eol;
1186          end if;
1187       end if;
1188 
1189       --  Loop to print fields included in Pchars array
1190 
1191       P := Pchar_Pos (Nkind (N));
1192 
1193       if Nkind (N) = N_Integer_Literal and then Print_In_Hex (N) then
1194          Fmt := Hex;
1195       else
1196          Fmt := Auto;
1197       end if;
1198 
1199       while P < Pchar_Pos (Node_Kind'Succ (Nkind (N))) loop
1200          F := Pchars (P);
1201          P := P + 1;
1202 
1203          --  Check for case of False flag, which we never print, or
1204          --  an Empty field, which is also never printed
1205 
1206          case F is
1207             when F_Field1 =>
1208                Field_To_Be_Printed := Field1 (N) /= Union_Id (Empty);
1209 
1210             when F_Field2 =>
1211                Field_To_Be_Printed := Field2 (N) /= Union_Id (Empty);
1212 
1213             when F_Field3 =>
1214                Field_To_Be_Printed := Field3 (N) /= Union_Id (Empty);
1215 
1216             when F_Field4 =>
1217                Field_To_Be_Printed := Field4 (N) /= Union_Id (Empty);
1218 
1219             when F_Field5 =>
1220                Field_To_Be_Printed := Field5 (N) /= Union_Id (Empty);
1221 
1222             when F_Flag1  => Field_To_Be_Printed := Flag1  (N);
1223             when F_Flag2  => Field_To_Be_Printed := Flag2  (N);
1224             when F_Flag3  => Field_To_Be_Printed := Flag3  (N);
1225             when F_Flag4  => Field_To_Be_Printed := Flag4  (N);
1226             when F_Flag5  => Field_To_Be_Printed := Flag5  (N);
1227             when F_Flag6  => Field_To_Be_Printed := Flag6  (N);
1228             when F_Flag7  => Field_To_Be_Printed := Flag7  (N);
1229             when F_Flag8  => Field_To_Be_Printed := Flag8  (N);
1230             when F_Flag9  => Field_To_Be_Printed := Flag9  (N);
1231             when F_Flag10 => Field_To_Be_Printed := Flag10 (N);
1232             when F_Flag11 => Field_To_Be_Printed := Flag11 (N);
1233             when F_Flag12 => Field_To_Be_Printed := Flag12 (N);
1234             when F_Flag13 => Field_To_Be_Printed := Flag13 (N);
1235             when F_Flag14 => Field_To_Be_Printed := Flag14 (N);
1236             when F_Flag15 => Field_To_Be_Printed := Flag15 (N);
1237             when F_Flag16 => Field_To_Be_Printed := Flag16 (N);
1238             when F_Flag17 => Field_To_Be_Printed := Flag17 (N);
1239             when F_Flag18 => Field_To_Be_Printed := Flag18 (N);
1240          end case;
1241 
1242          --  Print field if it is to be printed
1243 
1244          if Field_To_Be_Printed then
1245             Print_Str (Prefix_Str_Char);
1246 
1247             while P < Pchar_Pos (Node_Kind'Succ (Nkind (N)))
1248               and then Pchars (P) not in Fchar
1249             loop
1250                Print_Char (Pchars (P));
1251                P := P + 1;
1252             end loop;
1253 
1254             Print_Str (" = ");
1255 
1256             case F is
1257                when F_Field1 => Print_Field (Field1 (N), Fmt);
1258                when F_Field2 => Print_Field (Field2 (N), Fmt);
1259                when F_Field3 => Print_Field (Field3 (N), Fmt);
1260                when F_Field4 => Print_Field (Field4 (N), Fmt);
1261 
1262                --  Special case End_Span = Uint5
1263 
1264                when F_Field5 =>
1265                   if Nkind_In (N, N_Case_Statement, N_If_Statement) then
1266                      Print_End_Span (N);
1267                   else
1268                      Print_Field (Field5 (N), Fmt);
1269                   end if;
1270 
1271                when F_Flag1  => Print_Flag  (Flag1 (N));
1272                when F_Flag2  => Print_Flag  (Flag2 (N));
1273                when F_Flag3  => Print_Flag  (Flag3 (N));
1274                when F_Flag4  => Print_Flag  (Flag4 (N));
1275                when F_Flag5  => Print_Flag  (Flag5 (N));
1276                when F_Flag6  => Print_Flag  (Flag6 (N));
1277                when F_Flag7  => Print_Flag  (Flag7 (N));
1278                when F_Flag8  => Print_Flag  (Flag8 (N));
1279                when F_Flag9  => Print_Flag  (Flag9 (N));
1280                when F_Flag10 => Print_Flag  (Flag10 (N));
1281                when F_Flag11 => Print_Flag  (Flag11 (N));
1282                when F_Flag12 => Print_Flag  (Flag12 (N));
1283                when F_Flag13 => Print_Flag  (Flag13 (N));
1284                when F_Flag14 => Print_Flag  (Flag14 (N));
1285                when F_Flag15 => Print_Flag  (Flag15 (N));
1286                when F_Flag16 => Print_Flag  (Flag16 (N));
1287                when F_Flag17 => Print_Flag  (Flag17 (N));
1288                when F_Flag18 => Print_Flag  (Flag18 (N));
1289             end case;
1290 
1291             Print_Eol;
1292 
1293          --  Field is not to be printed (False flag field)
1294 
1295          else
1296             while P < Pchar_Pos (Node_Kind'Succ (Nkind (N)))
1297               and then Pchars (P) not in Fchar
1298             loop
1299                P := P + 1;
1300             end loop;
1301          end if;
1302       end loop;
1303 
1304       --  Print aspects if present
1305 
1306       if Has_Aspects (N) then
1307          Print_Str (Prefix_Str_Char);
1308          Print_Str ("Aspect_Specifications = ");
1309          Print_Field (Union_Id (Aspect_Specifications (N)));
1310          Print_Eol;
1311       end if;
1312 
1313       --  Print entity information for entities
1314 
1315       if Nkind (N) in N_Entity then
1316          Print_Entity_Info (N, Prefix_Str_Char);
1317       end if;
1318 
1319       --  Print the SCIL node (if available)
1320 
1321       if Present (Get_SCIL_Node (N)) then
1322          Print_Str (Prefix_Str_Char);
1323          Print_Str ("SCIL_Node = ");
1324          Print_Node_Ref (Get_SCIL_Node (N));
1325          Print_Eol;
1326       end if;
1327    end Print_Node;
1328 
1329    ------------------------
1330    -- Print_Node_Briefly --
1331    ------------------------
1332 
1333    procedure Print_Node_Briefly (N : Node_Id) is
1334    begin
1335       Printing_Descendants := False;
1336       Phase := Printing;
1337       Print_Node_Header (N);
1338    end Print_Node_Briefly;
1339 
1340    -----------------------
1341    -- Print_Node_Header --
1342    -----------------------
1343 
1344    procedure Print_Node_Header (N : Node_Id) is
1345       Enumerate : Boolean := False;
1346       --  Flag set when enumerating multiple header flags
1347 
1348       procedure Print_Header_Flag (Flag : String);
1349       --  Output one of the flags that appears in a node header. The routine
1350       --  automatically handles enumeration of multiple flags.
1351 
1352       -----------------------
1353       -- Print_Header_Flag --
1354       -----------------------
1355 
1356       procedure Print_Header_Flag (Flag : String) is
1357       begin
1358          if Enumerate then
1359             Print_Char (',');
1360          else
1361             Enumerate := True;
1362             Print_Char ('(');
1363          end if;
1364 
1365          Print_Str (Flag);
1366       end Print_Header_Flag;
1367 
1368    --  Start of processing for Print_Node_Header
1369 
1370    begin
1371       Print_Node_Ref (N);
1372 
1373       if N > Atree_Private_Part.Nodes.Last then
1374          Print_Str (" (no such node)");
1375          Print_Eol;
1376          return;
1377       end if;
1378 
1379       Print_Char (' ');
1380 
1381       if Comes_From_Source (N) then
1382          Print_Header_Flag ("source");
1383       end if;
1384 
1385       if Analyzed (N) then
1386          Print_Header_Flag ("analyzed");
1387       end if;
1388 
1389       if Error_Posted (N) then
1390          Print_Header_Flag ("posted");
1391       end if;
1392 
1393       if Is_Ignored_Ghost_Node (N) then
1394          Print_Header_Flag ("ignored ghost");
1395       end if;
1396 
1397       if Check_Actuals (N) then
1398          Print_Header_Flag ("check actuals");
1399       end if;
1400 
1401       if Enumerate then
1402          Print_Char (')');
1403       end if;
1404 
1405       Print_Eol;
1406    end Print_Node_Header;
1407 
1408    ---------------------
1409    -- Print_Node_Kind --
1410    ---------------------
1411 
1412    procedure Print_Node_Kind (N : Node_Id) is
1413       Ucase : Boolean;
1414       S     : constant String := Node_Kind'Image (Nkind (N));
1415 
1416    begin
1417       if Phase = Printing then
1418          Ucase := True;
1419 
1420          --  Note: the call to Fold_Upper in this loop is to get past the GNAT
1421          --  bug of 'Image returning lower case instead of upper case.
1422 
1423          for J in S'Range loop
1424             if Ucase then
1425                Write_Char (Fold_Upper (S (J)));
1426             else
1427                Write_Char (Fold_Lower (S (J)));
1428             end if;
1429 
1430             Ucase := (S (J) = '_');
1431          end loop;
1432       end if;
1433    end Print_Node_Kind;
1434 
1435    --------------------
1436    -- Print_Node_Ref --
1437    --------------------
1438 
1439    procedure Print_Node_Ref (N : Node_Id) is
1440       S : Nat;
1441 
1442    begin
1443       if Phase /= Printing then
1444          return;
1445       end if;
1446 
1447       if N = Empty then
1448          Write_Str ("<empty>");
1449 
1450       elsif N = Error then
1451          Write_Str ("<error>");
1452 
1453       else
1454          if Printing_Descendants then
1455             S := Serial_Number (Int (N));
1456 
1457             if S /= 0 then
1458                Write_Str ("Node");
1459                Write_Str (" #");
1460                Write_Int (S);
1461                Write_Char (' ');
1462             end if;
1463          end if;
1464 
1465          Print_Node_Kind (N);
1466 
1467          if Nkind (N) in N_Has_Chars then
1468             Write_Char (' ');
1469             Print_Name (Chars (N));
1470          end if;
1471 
1472          if Nkind (N) in N_Entity then
1473             Write_Str (" (Entity_Id=");
1474          else
1475             Write_Str (" (Node_Id=");
1476          end if;
1477 
1478          Write_Int (Int (N));
1479 
1480          if Sloc (N) <= Standard_Location then
1481             Write_Char ('s');
1482          end if;
1483 
1484          Write_Char (')');
1485 
1486       end if;
1487    end Print_Node_Ref;
1488 
1489    ------------------------
1490    -- Print_Node_Subtree --
1491    ------------------------
1492 
1493    procedure Print_Node_Subtree (N : Node_Id) is
1494    begin
1495       Print_Init;
1496 
1497       Next_Serial_Number := 1;
1498       Phase := Marking;
1499       Visit_Node (N, "", ' ');
1500 
1501       Next_Serial_Number := 1;
1502       Phase := Printing;
1503       Visit_Node (N, "", ' ');
1504 
1505       Print_Term;
1506    end Print_Node_Subtree;
1507 
1508    ---------------
1509    -- Print_Str --
1510    ---------------
1511 
1512    procedure Print_Str (S : String) is
1513    begin
1514       if Phase = Printing then
1515          Write_Str (S);
1516       end if;
1517    end Print_Str;
1518 
1519    --------------------------
1520    -- Print_Str_Mixed_Case --
1521    --------------------------
1522 
1523    procedure Print_Str_Mixed_Case (S : String) is
1524       Ucase : Boolean;
1525 
1526    begin
1527       if Phase = Printing then
1528          Ucase := True;
1529 
1530          for J in S'Range loop
1531             if Ucase then
1532                Write_Char (S (J));
1533             else
1534                Write_Char (Fold_Lower (S (J)));
1535             end if;
1536 
1537             Ucase := (S (J) = '_');
1538          end loop;
1539       end if;
1540    end Print_Str_Mixed_Case;
1541 
1542    ----------------
1543    -- Print_Term --
1544    ----------------
1545 
1546    procedure Print_Term is
1547       procedure Free is new Unchecked_Deallocation
1548         (Hash_Table_Type, Access_Hash_Table_Type);
1549 
1550    begin
1551       Free (Hash_Table);
1552    end Print_Term;
1553 
1554    ---------------------
1555    -- Print_Tree_Elist --
1556    ---------------------
1557 
1558    procedure Print_Tree_Elist (E : Elist_Id) is
1559       M : Elmt_Id;
1560 
1561    begin
1562       Printing_Descendants := False;
1563       Phase := Printing;
1564 
1565       Print_Elist_Ref (E);
1566       Print_Eol;
1567 
1568       if Present (E) and then not Is_Empty_Elmt_List (E) then
1569          M := First_Elmt (E);
1570 
1571          loop
1572             Print_Char ('|');
1573             Print_Eol;
1574             exit when No (Next_Elmt (M));
1575             Print_Node (Node (M), "", '|');
1576             Next_Elmt (M);
1577          end loop;
1578 
1579          Print_Node (Node (M), "", ' ');
1580          Print_Eol;
1581       end if;
1582    end Print_Tree_Elist;
1583 
1584    ---------------------
1585    -- Print_Tree_List --
1586    ---------------------
1587 
1588    procedure Print_Tree_List (L : List_Id) is
1589       N : Node_Id;
1590 
1591    begin
1592       Printing_Descendants := False;
1593       Phase := Printing;
1594 
1595       Print_List_Ref (L);
1596       Print_Str (" List_Id=");
1597       Print_Int (Int (L));
1598       Print_Eol;
1599 
1600       N := First (L);
1601 
1602       if N = Empty then
1603          Print_Str ("<empty node list>");
1604          Print_Eol;
1605 
1606       else
1607          loop
1608             Print_Char ('|');
1609             Print_Eol;
1610             exit when Next (N) = Empty;
1611             Print_Node (N, "", '|');
1612             Next (N);
1613          end loop;
1614 
1615          Print_Node (N, "", ' ');
1616          Print_Eol;
1617       end if;
1618    end Print_Tree_List;
1619 
1620    ---------------------
1621    -- Print_Tree_Node --
1622    ---------------------
1623 
1624    procedure Print_Tree_Node (N : Node_Id; Label : String := "") is
1625    begin
1626       Printing_Descendants := False;
1627       Phase := Printing;
1628       Print_Node (N, Label, ' ');
1629    end Print_Tree_Node;
1630 
1631    --------
1632    -- pt --
1633    --------
1634 
1635    procedure pt (N : Union_Id) is
1636    begin
1637       case N is
1638          when List_Low_Bound .. List_High_Bound - 1 =>
1639             Print_List_Subtree (List_Id (N));
1640          when Node_Range =>
1641             Print_Node_Subtree (Node_Id (N));
1642          when Elist_Range =>
1643             Print_Elist_Subtree (Elist_Id (N));
1644          when others =>
1645             pp (N);
1646       end case;
1647    end pt;
1648 
1649    -------------------
1650    -- Serial_Number --
1651    -------------------
1652 
1653    --  The hashing algorithm is to use the remainder of the ID value divided
1654    --  by the hash table length as the starting point in the table, and then
1655    --  handle collisions by serial searching wrapping at the end of the table.
1656 
1657    Hash_Slot : Nat;
1658    --  Set by an unsuccessful call to Serial_Number (one which returns zero)
1659    --  to save the slot that should be used if Set_Serial_Number is called.
1660 
1661    function Serial_Number (Id : Int) return Nat is
1662       H : Int := Id mod Hash_Table_Len;
1663 
1664    begin
1665       while Hash_Table (H).Serial /= 0 loop
1666 
1667          if Id = Hash_Table (H).Id then
1668             return Hash_Table (H).Serial;
1669          end if;
1670 
1671          H := H + 1;
1672 
1673          if H > Hash_Table'Last then
1674             H := 0;
1675          end if;
1676       end loop;
1677 
1678       --  Entry was not found, save slot number for possible subsequent call
1679       --  to Set_Serial_Number, and unconditionally save the Id in this slot
1680       --  in case of such a call (the Id field is never read if the serial
1681       --  number of the slot is zero, so this is harmless in the case where
1682       --  Set_Serial_Number is not subsequently called).
1683 
1684       Hash_Slot := H;
1685       Hash_Table (H).Id := Id;
1686       return 0;
1687 
1688    end Serial_Number;
1689 
1690    -----------------------
1691    -- Set_Serial_Number --
1692    -----------------------
1693 
1694    procedure Set_Serial_Number is
1695    begin
1696       Hash_Table (Hash_Slot).Serial := Next_Serial_Number;
1697       Next_Serial_Number := Next_Serial_Number + 1;
1698    end Set_Serial_Number;
1699 
1700    ---------------
1701    -- Tree_Dump --
1702    ---------------
1703 
1704    procedure Tree_Dump is
1705       procedure Underline;
1706       --  Put underline under string we just printed
1707 
1708       procedure Underline is
1709          Col : constant Int := Column;
1710 
1711       begin
1712          Write_Eol;
1713 
1714          while Col > Column loop
1715             Write_Char ('-');
1716          end loop;
1717 
1718          Write_Eol;
1719       end Underline;
1720 
1721    --  Start of processing for Tree_Dump. Note that we turn off the tree dump
1722    --  flags immediately, before starting the dump. This avoids generating two
1723    --  copies of the dump if an abort occurs after printing the dump, and more
1724    --  importantly, avoids an infinite loop if an abort occurs during the dump.
1725 
1726    --  Note: unlike in the source print case (in Sprint), we do not output
1727    --  separate trees for each unit. Instead the -df debug switch causes the
1728    --  tree that is output from the main unit to trace references into other
1729    --  units (normally such references are not traced). Since all other units
1730    --  are linked to the main unit by at least one reference, this causes all
1731    --  tree nodes to be included in the output tree.
1732 
1733    begin
1734       if Debug_Flag_Y then
1735          Debug_Flag_Y := False;
1736          Write_Eol;
1737          Write_Str ("Tree created for Standard (spec) ");
1738          Underline;
1739          Print_Node_Subtree (Standard_Package_Node);
1740          Write_Eol;
1741       end if;
1742 
1743       if Debug_Flag_T then
1744          Debug_Flag_T := False;
1745 
1746          Write_Eol;
1747          Write_Str ("Tree created for ");
1748          Write_Unit_Name (Unit_Name (Main_Unit));
1749          Underline;
1750          Print_Node_Subtree (Cunit (Main_Unit));
1751          Write_Eol;
1752       end if;
1753    end Tree_Dump;
1754 
1755    -----------------
1756    -- Visit_Elist --
1757    -----------------
1758 
1759    procedure Visit_Elist (E : Elist_Id; Prefix_Str : String) is
1760       M : Elmt_Id;
1761       N : Node_Id;
1762       S : constant Nat := Serial_Number (Int (E));
1763 
1764    begin
1765       --  In marking phase, return if already marked, otherwise set next
1766       --  serial number in hash table for later reference.
1767 
1768       if Phase = Marking then
1769          if S /= 0 then
1770             return; -- already visited
1771          else
1772             Set_Serial_Number;
1773          end if;
1774 
1775       --  In printing phase, if already printed, then return, otherwise we
1776       --  are printing the next item, so increment the serial number.
1777 
1778       else
1779          if S < Next_Serial_Number then
1780             return; -- already printed
1781          else
1782             Next_Serial_Number := Next_Serial_Number + 1;
1783          end if;
1784       end if;
1785 
1786       --  Now process the list (Print calls have no effect in marking phase)
1787 
1788       Print_Str (Prefix_Str);
1789       Print_Elist_Ref (E);
1790       Print_Eol;
1791 
1792       if Is_Empty_Elmt_List (E) then
1793          Print_Str (Prefix_Str);
1794          Print_Str ("(Empty element list)");
1795          Print_Eol;
1796          Print_Eol;
1797 
1798       else
1799          if Phase = Printing then
1800             M := First_Elmt (E);
1801             while Present (M) loop
1802                N := Node (M);
1803                Print_Str (Prefix_Str);
1804                Print_Str (" ");
1805                Print_Node_Ref (N);
1806                Print_Eol;
1807                Next_Elmt (M);
1808             end loop;
1809 
1810             Print_Str (Prefix_Str);
1811             Print_Eol;
1812          end if;
1813 
1814          M := First_Elmt (E);
1815          while Present (M) loop
1816             Visit_Node (Node (M), Prefix_Str, ' ');
1817             Next_Elmt (M);
1818          end loop;
1819       end if;
1820    end Visit_Elist;
1821 
1822    ----------------
1823    -- Visit_List --
1824    ----------------
1825 
1826    procedure Visit_List (L : List_Id; Prefix_Str : String) is
1827       N : Node_Id;
1828       S : constant Nat := Serial_Number (Int (L));
1829 
1830    begin
1831       --  In marking phase, return if already marked, otherwise set next
1832       --  serial number in hash table for later reference.
1833 
1834       if Phase = Marking then
1835          if S /= 0 then
1836             return;
1837          else
1838             Set_Serial_Number;
1839          end if;
1840 
1841       --  In printing phase, if already printed, then return, otherwise we
1842       --  are printing the next item, so increment the serial number.
1843 
1844       else
1845          if S < Next_Serial_Number then
1846             return; -- already printed
1847          else
1848             Next_Serial_Number := Next_Serial_Number + 1;
1849          end if;
1850       end if;
1851 
1852       --  Now process the list (Print calls have no effect in marking phase)
1853 
1854       Print_Str (Prefix_Str);
1855       Print_List_Ref (L);
1856       Print_Eol;
1857 
1858       Print_Str (Prefix_Str);
1859       Print_Str ("|Parent = ");
1860       Print_Node_Ref (Parent (L));
1861       Print_Eol;
1862 
1863       N := First (L);
1864 
1865       if N = Empty then
1866          Print_Str (Prefix_Str);
1867          Print_Str ("(Empty list)");
1868          Print_Eol;
1869          Print_Eol;
1870 
1871       else
1872          Print_Str (Prefix_Str);
1873          Print_Char ('|');
1874          Print_Eol;
1875 
1876          while Next (N) /= Empty loop
1877             Visit_Node (N, Prefix_Str, '|');
1878             Next (N);
1879          end loop;
1880       end if;
1881 
1882       Visit_Node (N, Prefix_Str, ' ');
1883    end Visit_List;
1884 
1885    ----------------
1886    -- Visit_Node --
1887    ----------------
1888 
1889    procedure Visit_Node
1890      (N           : Node_Id;
1891       Prefix_Str  : String;
1892       Prefix_Char : Character)
1893    is
1894       New_Prefix : String (Prefix_Str'First .. Prefix_Str'Last + 2);
1895       --  Prefix string for printing referenced fields
1896 
1897       procedure Visit_Descendant
1898         (D         : Union_Id;
1899          No_Indent : Boolean := False);
1900       --  This procedure tests the given value of one of the Fields referenced
1901       --  by the current node to determine whether to visit it recursively.
1902       --  Normally No_Indent is false, which means that the visited node will
1903       --  be indented using New_Prefix. If No_Indent is set to True, then
1904       --  this indentation is skipped, and Prefix_Str is used for the call
1905       --  to print the descendant. No_Indent is effective only if the
1906       --  referenced descendant is a node.
1907 
1908       ----------------------
1909       -- Visit_Descendant --
1910       ----------------------
1911 
1912       procedure Visit_Descendant
1913         (D         : Union_Id;
1914          No_Indent : Boolean := False)
1915       is
1916       begin
1917          --  Case of descendant is a node
1918 
1919          if D in Node_Range then
1920 
1921             --  Don't bother about Empty or Error descendants
1922 
1923             if D <= Union_Id (Empty_Or_Error) then
1924                return;
1925             end if;
1926 
1927             declare
1928                Nod : constant Node_Or_Entity_Id := Node_Or_Entity_Id (D);
1929 
1930             begin
1931                --  Descendants in one of the standardly compiled internal
1932                --  packages are normally ignored, unless the parent is also
1933                --  in such a package (happens when Standard itself is output)
1934                --  or if the -df switch is set which causes all links to be
1935                --  followed, even into package standard.
1936 
1937                if Sloc (Nod) <= Standard_Location then
1938                   if Sloc (N) > Standard_Location
1939                     and then not Debug_Flag_F
1940                   then
1941                      return;
1942                   end if;
1943 
1944                --  Don't bother about a descendant in a different unit than
1945                --  the node we came from unless the -df switch is set. Note
1946                --  that we know at this point that Sloc (D) > Standard_Location
1947 
1948                --  Note: the tests for No_Location here just make sure that we
1949                --  don't blow up on a node which is missing an Sloc value. This
1950                --  should not normally happen.
1951 
1952                else
1953                   if (Sloc (N) <= Standard_Location
1954                         or else Sloc (N) = No_Location
1955                         or else Sloc (Nod) = No_Location
1956                         or else not In_Same_Source_Unit (Nod, N))
1957                     and then not Debug_Flag_F
1958                   then
1959                      return;
1960                   end if;
1961                end if;
1962 
1963                --  Don't bother visiting a source node that has a parent which
1964                --  is not the node we came from. We prefer to trace such nodes
1965                --  from their real parents. This causes the tree to be printed
1966                --  in a more coherent order, e.g. a defining identifier listed
1967                --  next to its corresponding declaration, instead of next to
1968                --  some semantic reference.
1969 
1970                --  This test is skipped for nodes in standard packages unless
1971                --  the -dy option is set (which outputs the tree for standard)
1972 
1973                --  Also, always follow pointers to Is_Itype entities,
1974                --  since we want to list these when they are first referenced.
1975 
1976                if Parent (Nod) /= Empty
1977                  and then Comes_From_Source (Nod)
1978                  and then Parent (Nod) /= N
1979                  and then (Sloc (N) > Standard_Location or else Debug_Flag_Y)
1980                then
1981                   return;
1982                end if;
1983 
1984                --  If we successfully fall through all the above tests (which
1985                --  execute a return if the node is not to be visited), we can
1986                --  go ahead and visit the node.
1987 
1988                if No_Indent then
1989                   Visit_Node (Nod, Prefix_Str, Prefix_Char);
1990                else
1991                   Visit_Node (Nod, New_Prefix, ' ');
1992                end if;
1993             end;
1994 
1995          --  Case of descendant is a list
1996 
1997          elsif D in List_Range then
1998 
1999             --  Don't bother with a missing list, empty list or error list
2000 
2001             pragma Assert (D /= Union_Id (No_List));
2002             --  Because No_List = Empty, which is in Node_Range above
2003 
2004             if D = Union_Id (Error_List)
2005               or else Is_Empty_List (List_Id (D))
2006             then
2007                return;
2008 
2009             --  Otherwise we can visit the list. Note that we don't bother to
2010             --  do the parent test that we did for the node case, because it
2011             --  just does not happen that lists are referenced more than one
2012             --  place in the tree. We aren't counting on this being the case
2013             --  to generate valid output, it is just that we don't need in
2014             --  practice to worry about listing the list at a place that is
2015             --  inconvenient.
2016 
2017             else
2018                Visit_List (List_Id (D), New_Prefix);
2019             end if;
2020 
2021          --  Case of descendant is an element list
2022 
2023          elsif D in Elist_Range then
2024 
2025             --  Don't bother with a missing list, or an empty list
2026 
2027             if D = Union_Id (No_Elist)
2028               or else Is_Empty_Elmt_List (Elist_Id (D))
2029             then
2030                return;
2031 
2032             --  Otherwise, visit the referenced element list
2033 
2034             else
2035                Visit_Elist (Elist_Id (D), New_Prefix);
2036             end if;
2037 
2038          --  For all other kinds of descendants (strings, names, uints etc),
2039          --  there is nothing to visit (the contents of the field will be
2040          --  printed when we print the containing node, but what concerns
2041          --  us now is looking for descendants in the tree.
2042 
2043          else
2044             null;
2045          end if;
2046       end Visit_Descendant;
2047 
2048    --  Start of processing for Visit_Node
2049 
2050    begin
2051       if N = Empty then
2052          return;
2053       end if;
2054 
2055       --  Set fatal error node in case we get a blow up during the trace
2056 
2057       Current_Error_Node := N;
2058 
2059       New_Prefix (Prefix_Str'Range)    := Prefix_Str;
2060       New_Prefix (Prefix_Str'Last + 1) := Prefix_Char;
2061       New_Prefix (Prefix_Str'Last + 2) := ' ';
2062 
2063       --  In the marking phase, all we do is to set the serial number
2064 
2065       if Phase = Marking then
2066          if Serial_Number (Int (N)) /= 0 then
2067             return; -- already visited
2068          else
2069             Set_Serial_Number;
2070          end if;
2071 
2072       --  In the printing phase, we print the node
2073 
2074       else
2075          if Serial_Number (Int (N)) < Next_Serial_Number then
2076 
2077             --  Here we have already visited the node, but if it is in a list,
2078             --  we still want to print the reference, so that it is clear that
2079             --  it belongs to the list.
2080 
2081             if Is_List_Member (N) then
2082                Print_Str (Prefix_Str);
2083                Print_Node_Ref (N);
2084                Print_Eol;
2085                Print_Str (Prefix_Str);
2086                Print_Char (Prefix_Char);
2087                Print_Str ("(already output)");
2088                Print_Eol;
2089                Print_Str (Prefix_Str);
2090                Print_Char (Prefix_Char);
2091                Print_Eol;
2092             end if;
2093 
2094             return;
2095 
2096          else
2097             Print_Node (N, Prefix_Str, Prefix_Char);
2098             Print_Str (Prefix_Str);
2099             Print_Char (Prefix_Char);
2100             Print_Eol;
2101             Next_Serial_Number := Next_Serial_Number + 1;
2102          end if;
2103       end if;
2104 
2105       --  Visit all descendants of this node
2106 
2107       if Nkind (N) not in N_Entity then
2108          Visit_Descendant (Field1 (N));
2109          Visit_Descendant (Field2 (N));
2110          Visit_Descendant (Field3 (N));
2111          Visit_Descendant (Field4 (N));
2112          Visit_Descendant (Field5 (N));
2113 
2114          if Has_Aspects (N) then
2115             Visit_Descendant (Union_Id (Aspect_Specifications (N)));
2116          end if;
2117 
2118       --  Entity case
2119 
2120       else
2121          Visit_Descendant (Field1 (N));
2122          Visit_Descendant (Field3 (N));
2123          Visit_Descendant (Field4 (N));
2124          Visit_Descendant (Field5 (N));
2125          Visit_Descendant (Field6 (N));
2126          Visit_Descendant (Field7 (N));
2127          Visit_Descendant (Field8 (N));
2128          Visit_Descendant (Field9 (N));
2129          Visit_Descendant (Field10 (N));
2130          Visit_Descendant (Field11 (N));
2131          Visit_Descendant (Field12 (N));
2132          Visit_Descendant (Field13 (N));
2133          Visit_Descendant (Field14 (N));
2134          Visit_Descendant (Field15 (N));
2135          Visit_Descendant (Field16 (N));
2136          Visit_Descendant (Field17 (N));
2137          Visit_Descendant (Field18 (N));
2138          Visit_Descendant (Field19 (N));
2139          Visit_Descendant (Field20 (N));
2140          Visit_Descendant (Field21 (N));
2141          Visit_Descendant (Field22 (N));
2142          Visit_Descendant (Field23 (N));
2143 
2144          --  Now an interesting special case. Normally parents are always
2145          --  printed since we traverse the tree in a downwards direction.
2146          --  However, there is an exception to this rule, which is the
2147          --  case where a parent is constructed by the compiler and is not
2148          --  referenced elsewhere in the tree. The following catches this case.
2149 
2150          if not Comes_From_Source (N) then
2151             Visit_Descendant (Union_Id (Parent (N)));
2152          end if;
2153 
2154          --  You may be wondering why we omitted Field2 above. The answer
2155          --  is that this is the Next_Entity field, and we want to treat
2156          --  it rather specially. Why? Because a Next_Entity link does not
2157          --  correspond to a level deeper in the tree, and we do not want
2158          --  the tree to march off to the right of the page due to bogus
2159          --  indentations coming from this effect.
2160 
2161          --  To prevent this, what we do is to control references via
2162          --  Next_Entity only from the first entity on a given scope chain,
2163          --  and we keep them all at the same level. Of course if an entity
2164          --  has already been referenced it is not printed.
2165 
2166          if Present (Next_Entity (N))
2167            and then Present (Scope (N))
2168            and then First_Entity (Scope (N)) = N
2169          then
2170             declare
2171                Nod : Node_Id;
2172 
2173             begin
2174                Nod := N;
2175                while Present (Nod) loop
2176                   Visit_Descendant (Union_Id (Next_Entity (Nod)));
2177                   Nod := Next_Entity (Nod);
2178                end loop;
2179             end;
2180          end if;
2181       end if;
2182    end Visit_Node;
2183 
2184 end Treepr;