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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [treepr.adb] - Blame information for rev 300

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

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

powered by: WebSVN 2.1.0

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