OSDN Git Service

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