OSDN Git Service

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