OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ada/] [treepr.adb] - Blame information for rev 16

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.