1------------------------------------------------------------------------------
2--                                                                          --
3--                         GNAT COMPILER COMPONENTS                         --
4--                                                                          --
5--                               P R J . P P                                --
6--                                                                          --
7--                                 B o d y                                  --
8--                                                                          --
9--          Copyright (C) 2001-2011, 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
26with Ada.Characters.Handling; use Ada.Characters.Handling;
27
28with Output;   use Output;
29with Snames;
30
31package body Prj.PP is
32
33   use Prj.Tree;
34
35   Not_Tested : array (Project_Node_Kind) of Boolean := (others => True);
36
37   procedure Indicate_Tested (Kind : Project_Node_Kind);
38   --  Set the corresponding component of array Not_Tested to False.
39   --  Only called by pragmas Debug.
40
41   ---------------------
42   -- Indicate_Tested --
43   ---------------------
44
45   procedure Indicate_Tested (Kind : Project_Node_Kind) is
46   begin
47      Not_Tested (Kind) := False;
48   end Indicate_Tested;
49
50   ------------------
51   -- Pretty_Print --
52   ------------------
53
54   procedure Pretty_Print
55     (Project                            : Prj.Tree.Project_Node_Id;
56      In_Tree                            : Prj.Tree.Project_Node_Tree_Ref;
57      Increment                          : Positive       := 3;
58      Eliminate_Empty_Case_Constructions : Boolean        := False;
59      Minimize_Empty_Lines               : Boolean        := False;
60      W_Char                             : Write_Char_Ap  := null;
61      W_Eol                              : Write_Eol_Ap   := null;
62      W_Str                              : Write_Str_Ap   := null;
63      Backward_Compatibility             : Boolean;
64      Id                                 : Prj.Project_Id := Prj.No_Project;
65      Max_Line_Length                    : Max_Length_Of_Line :=
66                                             Max_Length_Of_Line'Last)
67   is
68      procedure Print (Node : Project_Node_Id; Indent : Natural);
69      --  A recursive procedure that traverses a project file tree and outputs
70      --  its source. Current_Prj is the project that we are printing. This
71      --  is used when printing attributes, since in nested packages they
72      --  need to use a fully qualified name.
73
74      procedure Output_Attribute_Name (Name : Name_Id; Indent : Natural);
75      --  Outputs an attribute name, taking into account the value of
76      --  Backward_Compatibility.
77
78      procedure Output_Name
79        (Name       : Name_Id;
80         Indent     : Natural;
81         Capitalize : Boolean := True);
82      --  Outputs a name
83
84      procedure Start_Line (Indent : Natural);
85      --  Outputs the indentation at the beginning of the line
86
87      procedure Output_String (S : Name_Id; Indent : Natural);
88      procedure Output_String (S : Path_Name_Type; Indent : Natural);
89      --  Outputs a string using the default output procedures
90
91      procedure Write_Empty_Line (Always : Boolean := False);
92      --  Outputs an empty line, only if the previous line was not empty
93      --  already and either Always is True or Minimize_Empty_Lines is
94      --  False.
95
96      procedure Write_Line (S : String);
97      --  Outputs S followed by a new line
98
99      procedure Write_String
100        (S         : String;
101         Indent    : Natural;
102         Truncated : Boolean := False);
103      --  Outputs S using Write_Str, starting a new line if line would
104      --  become too long, when Truncated = False.
105      --  When Truncated = True, only the part of the string that can fit on
106      --  the line is output.
107
108      procedure Write_End_Of_Line_Comment (Node : Project_Node_Id);
109
110      Write_Char : Write_Char_Ap := Output.Write_Char'Access;
111      Write_Eol  : Write_Eol_Ap := Output.Write_Eol'Access;
112      Write_Str  : Write_Str_Ap := Output.Write_Str'Access;
113      --  These three access to procedure values are used for the output
114
115      Last_Line_Is_Empty : Boolean := False;
116      --  Used to avoid two consecutive empty lines
117
118      Column : Natural := 0;
119      --  Column number of the last character in the line. Used to avoid
120      --  outputting lines longer than Max_Line_Length.
121
122      First_With_In_List : Boolean := True;
123      --  Indicate that the next with clause is first in a list such as
124      --    with "A", "B";
125      --  First_With_In_List will be True for "A", but not for "B".
126
127      ---------------------------
128      -- Output_Attribute_Name --
129      ---------------------------
130
131      procedure Output_Attribute_Name (Name : Name_Id; Indent : Natural) is
132      begin
133         if Backward_Compatibility then
134            case Name is
135               when Snames.Name_Spec =>
136                  Output_Name (Snames.Name_Specification, Indent);
137
138               when Snames.Name_Spec_Suffix =>
139                  Output_Name (Snames.Name_Specification_Suffix, Indent);
140
141               when Snames.Name_Body =>
142                  Output_Name (Snames.Name_Implementation, Indent);
143
144               when Snames.Name_Body_Suffix =>
145                  Output_Name (Snames.Name_Implementation_Suffix, Indent);
146
147               when others =>
148                  Output_Name (Name, Indent);
149            end case;
150
151         else
152            Output_Name (Name, Indent);
153         end if;
154      end Output_Attribute_Name;
155
156      -----------------
157      -- Output_Name --
158      -----------------
159
160      procedure Output_Name
161        (Name       : Name_Id;
162         Indent     : Natural;
163         Capitalize : Boolean := True)
164      is
165         Capital : Boolean := Capitalize;
166
167      begin
168         if Column = 0 and then Indent /= 0 then
169            Start_Line (Indent + Increment);
170         end if;
171
172         Get_Name_String (Name);
173
174         --  If line would become too long, create new line
175
176         if Column + Name_Len > Max_Line_Length then
177            Write_Eol.all;
178            Column := 0;
179
180            if Indent /= 0 then
181               Start_Line (Indent + Increment);
182            end if;
183         end if;
184
185         for J in 1 .. Name_Len loop
186            if Capital then
187               Write_Char (To_Upper (Name_Buffer (J)));
188            else
189               Write_Char (Name_Buffer (J));
190            end if;
191
192            if Capitalize then
193               Capital :=
194                 Name_Buffer (J) = '_'
195                 or else Is_Digit (Name_Buffer (J));
196            end if;
197         end loop;
198
199         Column := Column + Name_Len;
200      end Output_Name;
201
202      -------------------
203      -- Output_String --
204      -------------------
205
206      procedure Output_String (S : Name_Id; Indent : Natural) is
207      begin
208         if Column = 0 and then Indent /= 0 then
209            Start_Line (Indent + Increment);
210         end if;
211
212         Get_Name_String (S);
213
214         --  If line could become too long, create new line. Note that the
215         --  number of characters on the line could be twice the number of
216         --  character in the string (if every character is a '"') plus two
217         --  (the initial and final '"').
218
219         if Column + Name_Len + Name_Len + 2 > Max_Line_Length then
220            Write_Eol.all;
221            Column := 0;
222
223            if Indent /= 0 then
224               Start_Line (Indent + Increment);
225            end if;
226         end if;
227
228         Write_Char ('"');
229         Column := Column + 1;
230         Get_Name_String (S);
231
232         for J in 1 .. Name_Len loop
233            if Name_Buffer (J) = '"' then
234               Write_Char ('"');
235               Write_Char ('"');
236               Column := Column + 2;
237            else
238               Write_Char (Name_Buffer (J));
239               Column := Column + 1;
240            end if;
241
242            --  If the string does not fit on one line, cut it in parts and
243            --  concatenate.
244
245            if J < Name_Len and then Column >= Max_Line_Length then
246               Write_Str (""" &");
247               Write_Eol.all;
248               Column := 0;
249               Start_Line (Indent + Increment);
250               Write_Char ('"');
251               Column := Column + 1;
252            end if;
253         end loop;
254
255         Write_Char ('"');
256         Column := Column + 1;
257      end Output_String;
258
259      procedure Output_String (S : Path_Name_Type; Indent : Natural) is
260      begin
261         Output_String (Name_Id (S), Indent);
262      end Output_String;
263
264      ----------------
265      -- Start_Line --
266      ----------------
267
268      procedure Start_Line (Indent : Natural) is
269      begin
270         if not Minimize_Empty_Lines then
271            Write_Str ((1 .. Indent => ' '));
272            Column := Column + Indent;
273         end if;
274      end Start_Line;
275
276      ----------------------
277      -- Write_Empty_Line --
278      ----------------------
279
280      procedure Write_Empty_Line (Always : Boolean := False) is
281      begin
282         if (Always or else not Minimize_Empty_Lines)
283           and then not Last_Line_Is_Empty then
284            Write_Eol.all;
285            Column := 0;
286            Last_Line_Is_Empty := True;
287         end if;
288      end Write_Empty_Line;
289
290      -------------------------------
291      -- Write_End_Of_Line_Comment --
292      -------------------------------
293
294      procedure Write_End_Of_Line_Comment (Node : Project_Node_Id) is
295         Value : constant Name_Id := End_Of_Line_Comment (Node, In_Tree);
296
297      begin
298         if Value /= No_Name then
299            Write_String (" --", 0);
300            Write_String (Get_Name_String (Value), 0, Truncated => True);
301         end if;
302
303         Write_Line ("");
304      end Write_End_Of_Line_Comment;
305
306      ----------------
307      -- Write_Line --
308      ----------------
309
310      procedure Write_Line (S : String) is
311      begin
312         Write_String (S, 0);
313         Last_Line_Is_Empty := False;
314         Write_Eol.all;
315         Column := 0;
316      end Write_Line;
317
318      ------------------
319      -- Write_String --
320      ------------------
321
322      procedure Write_String
323        (S         : String;
324         Indent    : Natural;
325         Truncated : Boolean := False) is
326         Length : Natural := S'Length;
327      begin
328         if Column = 0 and then Indent /= 0 then
329            Start_Line (Indent + Increment);
330         end if;
331
332         --  If the string would not fit on the line,
333         --  start a new line.
334
335         if Column + Length > Max_Line_Length then
336            if Truncated then
337               Length := Max_Line_Length - Column;
338
339            else
340               Write_Eol.all;
341               Column := 0;
342
343               if Indent /= 0 then
344                  Start_Line (Indent + Increment);
345               end if;
346            end if;
347         end if;
348
349         Write_Str (S (S'First .. S'First + Length - 1));
350         Column := Column + Length;
351      end Write_String;
352
353      -----------
354      -- Print --
355      -----------
356
357      procedure Print (Node : Project_Node_Id; Indent : Natural) is
358      begin
359         if Present (Node) then
360
361            case Kind_Of (Node, In_Tree) is
362
363               when N_Project  =>
364                  pragma Debug (Indicate_Tested (N_Project));
365                  if Present (First_With_Clause_Of (Node, In_Tree)) then
366
367                     --  with clause(s)
368
369                     First_With_In_List := True;
370                     Print (First_With_Clause_Of (Node, In_Tree), Indent);
371                     Write_Empty_Line (Always => True);
372                  end if;
373
374                  Print (First_Comment_Before (Node, In_Tree), Indent);
375                  Start_Line (Indent);
376
377                  case Project_Qualifier_Of (Node, In_Tree) is
378                     when Unspecified | Standard =>
379                        null;
380                     when Aggregate   =>
381                        Write_String ("aggregate ", Indent);
382                     when Aggregate_Library =>
383                        Write_String ("aggregate library ", Indent);
384                     when Library     =>
385                        Write_String ("library ", Indent);
386                     when Configuration =>
387                        Write_String ("configuration ", Indent);
388                     when Dry =>
389                        Write_String ("abstract ", Indent);
390                  end case;
391
392                  Write_String ("project ", Indent);
393
394                  if Id /= Prj.No_Project then
395                     Output_Name (Id.Display_Name, Indent);
396                  else
397                     Output_Name (Name_Of (Node, In_Tree), Indent);
398                  end if;
399
400                  --  Check if this project extends another project
401
402                  if Extended_Project_Path_Of (Node, In_Tree) /= No_Path then
403                     Write_String (" extends ", Indent);
404
405                     if Is_Extending_All (Node, In_Tree) then
406                        Write_String ("all ", Indent);
407                     end if;
408
409                     Output_String
410                       (Extended_Project_Path_Of (Node, In_Tree),
411                        Indent);
412                  end if;
413
414                  Write_String (" is", Indent);
415                  Write_End_Of_Line_Comment (Node);
416                  Print
417                    (First_Comment_After (Node, In_Tree), Indent + Increment);
418                  Write_Empty_Line (Always => True);
419
420                  --  Output all of the declarations in the project
421
422                  Print (Project_Declaration_Of (Node, In_Tree), Indent);
423                  Print
424                    (First_Comment_Before_End (Node, In_Tree),
425                     Indent + Increment);
426                  Start_Line (Indent);
427                  Write_String ("end ", Indent);
428
429                  if Id /= Prj.No_Project then
430                     Output_Name (Id.Display_Name, Indent);
431                  else
432                     Output_Name (Name_Of (Node, In_Tree), Indent);
433                  end if;
434
435                  Write_Line (";");
436                  Print (First_Comment_After_End (Node, In_Tree), Indent);
437
438               when N_With_Clause =>
439                  pragma Debug (Indicate_Tested (N_With_Clause));
440
441                  --  The with clause will sometimes contain an invalid name
442                  --  when we are importing a virtual project from an
443                  --  extending all project. Do not output anything in this
444                  --  case
445
446                  if Name_Of (Node, In_Tree) /= No_Name
447                    and then String_Value_Of (Node, In_Tree) /= No_Name
448                  then
449                     if First_With_In_List then
450                        Print (First_Comment_Before (Node, In_Tree), Indent);
451                        Start_Line (Indent);
452
453                        if Non_Limited_Project_Node_Of (Node, In_Tree) =
454                             Empty_Node
455                        then
456                           Write_String ("limited ", Indent);
457                        end if;
458
459                        Write_String ("with ", Indent);
460                     end if;
461
462                     Output_String (String_Value_Of (Node, In_Tree), Indent);
463
464                     if Is_Not_Last_In_List (Node, In_Tree) then
465                        Write_String (", ", Indent);
466                        First_With_In_List := False;
467
468                     else
469                        Write_String (";", Indent);
470                        Write_End_Of_Line_Comment (Node);
471                        Print (First_Comment_After (Node, In_Tree), Indent);
472                        First_With_In_List := True;
473                     end if;
474                  end if;
475
476                  Print (Next_With_Clause_Of (Node, In_Tree), Indent);
477
478               when N_Project_Declaration =>
479                  pragma Debug (Indicate_Tested (N_Project_Declaration));
480
481                  if
482                    Present (First_Declarative_Item_Of (Node, In_Tree))
483                  then
484                     Print
485                       (First_Declarative_Item_Of (Node, In_Tree),
486                        Indent + Increment);
487                     Write_Empty_Line (Always => True);
488                  end if;
489
490               when N_Declarative_Item =>
491                  pragma Debug (Indicate_Tested (N_Declarative_Item));
492                  Print (Current_Item_Node (Node, In_Tree), Indent);
493                  Print (Next_Declarative_Item (Node, In_Tree), Indent);
494
495               when N_Package_Declaration =>
496                  pragma Debug (Indicate_Tested (N_Package_Declaration));
497                  Write_Empty_Line (Always => True);
498                  Print (First_Comment_Before (Node, In_Tree), Indent);
499                  Start_Line (Indent);
500                  Write_String ("package ", Indent);
501                  Output_Name (Name_Of (Node, In_Tree), Indent);
502
503                  if Project_Of_Renamed_Package_Of (Node, In_Tree) /=
504                       Empty_Node
505                  then
506                     Write_String (" renames ", Indent);
507                     Output_Name
508                       (Name_Of
509                          (Project_Of_Renamed_Package_Of (Node, In_Tree),
510                           In_Tree),
511                        Indent);
512                     Write_String (".", Indent);
513                     Output_Name (Name_Of (Node, In_Tree), Indent);
514                     Write_String (";", Indent);
515                     Write_End_Of_Line_Comment (Node);
516                     Print (First_Comment_After_End (Node, In_Tree), Indent);
517
518                  else
519                     Write_String (" is", Indent);
520                     Write_End_Of_Line_Comment (Node);
521                     Print (First_Comment_After (Node, In_Tree),
522                            Indent + Increment);
523
524                     if First_Declarative_Item_Of (Node, In_Tree) /=
525                          Empty_Node
526                     then
527                        Print
528                          (First_Declarative_Item_Of (Node, In_Tree),
529                           Indent + Increment);
530                     end if;
531
532                     Print (First_Comment_Before_End (Node, In_Tree),
533                            Indent + Increment);
534                     Start_Line (Indent);
535                     Write_String ("end ", Indent);
536                     Output_Name (Name_Of (Node, In_Tree), Indent);
537                     Write_Line (";");
538                     Print (First_Comment_After_End (Node, In_Tree), Indent);
539                     Write_Empty_Line;
540                  end if;
541
542               when N_String_Type_Declaration =>
543                  pragma Debug (Indicate_Tested (N_String_Type_Declaration));
544                  Print (First_Comment_Before (Node, In_Tree), Indent);
545                  Start_Line (Indent);
546                  Write_String ("type ", Indent);
547                  Output_Name (Name_Of (Node, In_Tree), Indent);
548                  Write_Line (" is");
549                  Start_Line (Indent + Increment);
550                  Write_String ("(", Indent);
551
552                  declare
553                     String_Node : Project_Node_Id :=
554                       First_Literal_String (Node, In_Tree);
555
556                  begin
557                     while Present (String_Node) loop
558                        Output_String
559                          (String_Value_Of (String_Node, In_Tree),
560                           Indent);
561                        String_Node :=
562                          Next_Literal_String (String_Node, In_Tree);
563
564                        if Present (String_Node) then
565                           Write_String (", ", Indent);
566                        end if;
567                     end loop;
568                  end;
569
570                  Write_String (");", Indent);
571                  Write_End_Of_Line_Comment (Node);
572                  Print (First_Comment_After (Node, In_Tree), Indent);
573
574               when N_Literal_String =>
575                  pragma Debug (Indicate_Tested (N_Literal_String));
576                  Output_String (String_Value_Of (Node, In_Tree), Indent);
577
578                  if Source_Index_Of (Node, In_Tree) /= 0 then
579                     Write_String (" at", Indent);
580                     Write_String
581                       (Source_Index_Of (Node, In_Tree)'Img,
582                        Indent);
583                  end if;
584
585               when N_Attribute_Declaration =>
586                  pragma Debug (Indicate_Tested (N_Attribute_Declaration));
587                  Print (First_Comment_Before (Node, In_Tree), Indent);
588                  Start_Line (Indent);
589                  Write_String ("for ", Indent);
590                  Output_Attribute_Name (Name_Of (Node, In_Tree), Indent);
591
592                  if Associative_Array_Index_Of (Node, In_Tree) /= No_Name then
593                     Write_String (" (", Indent);
594                     Output_String
595                       (Associative_Array_Index_Of (Node, In_Tree),
596                        Indent);
597
598                     if Source_Index_Of (Node, In_Tree) /= 0 then
599                        Write_String (" at", Indent);
600                        Write_String
601                          (Source_Index_Of (Node, In_Tree)'Img,
602                           Indent);
603                     end if;
604
605                     Write_String (")", Indent);
606                  end if;
607
608                  Write_String (" use ", Indent);
609
610                  if Present (Expression_Of (Node, In_Tree)) then
611                     Print (Expression_Of (Node, In_Tree), Indent);
612
613                  else
614                     --  Full associative array declaration
615
616                     if
617                       Present (Associative_Project_Of (Node, In_Tree))
618                     then
619                        Output_Name
620                          (Name_Of
621                             (Associative_Project_Of (Node, In_Tree),
622                              In_Tree),
623                           Indent);
624
625                        if
626                          Present (Associative_Package_Of (Node, In_Tree))
627                        then
628                           Write_String (".", Indent);
629                           Output_Name
630                             (Name_Of
631                                (Associative_Package_Of (Node, In_Tree),
632                                 In_Tree),
633                              Indent);
634                        end if;
635
636                     elsif
637                       Present (Associative_Package_Of (Node, In_Tree))
638                     then
639                        Output_Name
640                          (Name_Of
641                             (Associative_Package_Of (Node, In_Tree),
642                              In_Tree),
643                           Indent);
644                     end if;
645
646                     Write_String ("'", Indent);
647                     Output_Attribute_Name (Name_Of (Node, In_Tree), Indent);
648                  end if;
649
650                  Write_String (";", Indent);
651                  Write_End_Of_Line_Comment (Node);
652                  Print (First_Comment_After (Node, In_Tree), Indent);
653
654               when N_Typed_Variable_Declaration =>
655                  pragma Debug
656                    (Indicate_Tested (N_Typed_Variable_Declaration));
657                  Print (First_Comment_Before (Node, In_Tree), Indent);
658                  Start_Line (Indent);
659                  Output_Name (Name_Of (Node, In_Tree), Indent);
660                  Write_String (" : ", Indent);
661                  Output_Name
662                    (Name_Of (String_Type_Of (Node, In_Tree), In_Tree),
663                     Indent);
664                  Write_String (" := ", Indent);
665                  Print (Expression_Of (Node, In_Tree), Indent);
666                  Write_String (";", Indent);
667                  Write_End_Of_Line_Comment (Node);
668                  Print (First_Comment_After (Node, In_Tree), Indent);
669
670               when N_Variable_Declaration =>
671                  pragma Debug (Indicate_Tested (N_Variable_Declaration));
672                  Print (First_Comment_Before (Node, In_Tree), Indent);
673                  Start_Line (Indent);
674                  Output_Name (Name_Of (Node, In_Tree), Indent);
675                  Write_String (" := ", Indent);
676                  Print (Expression_Of (Node, In_Tree), Indent);
677                  Write_String (";", Indent);
678                  Write_End_Of_Line_Comment (Node);
679                  Print (First_Comment_After (Node, In_Tree), Indent);
680
681               when N_Expression =>
682                  pragma Debug (Indicate_Tested (N_Expression));
683                  declare
684                     Term : Project_Node_Id := First_Term (Node, In_Tree);
685
686                  begin
687                     while Present (Term) loop
688                        Print (Term, Indent);
689                        Term := Next_Term (Term, In_Tree);
690
691                        if Present (Term) then
692                           Write_String (" & ", Indent);
693                        end if;
694                     end loop;
695                  end;
696
697               when N_Term =>
698                  pragma Debug (Indicate_Tested (N_Term));
699                  Print (Current_Term (Node, In_Tree), Indent);
700
701               when N_Literal_String_List =>
702                  pragma Debug (Indicate_Tested (N_Literal_String_List));
703                  Write_String ("(", Indent);
704
705                  declare
706                     Expression : Project_Node_Id :=
707                       First_Expression_In_List (Node, In_Tree);
708
709                  begin
710                     while Present (Expression) loop
711                        Print (Expression, Indent);
712                        Expression :=
713                          Next_Expression_In_List (Expression, In_Tree);
714
715                        if Present (Expression) then
716                           Write_String (", ", Indent);
717                        end if;
718                     end loop;
719                  end;
720
721                  Write_String (")", Indent);
722
723               when N_Variable_Reference =>
724                  pragma Debug (Indicate_Tested (N_Variable_Reference));
725                  if Present (Project_Node_Of (Node, In_Tree)) then
726                     Output_Name
727                       (Name_Of (Project_Node_Of (Node, In_Tree), In_Tree),
728                        Indent);
729                     Write_String (".", Indent);
730                  end if;
731
732                  if Present (Package_Node_Of (Node, In_Tree)) then
733                     Output_Name
734                       (Name_Of (Package_Node_Of (Node, In_Tree), In_Tree),
735                        Indent);
736                     Write_String (".", Indent);
737                  end if;
738
739                  Output_Name (Name_Of (Node, In_Tree), Indent);
740
741               when N_External_Value =>
742                  pragma Debug (Indicate_Tested (N_External_Value));
743                  Write_String ("external (", Indent);
744                  Print (External_Reference_Of (Node, In_Tree), Indent);
745
746                  if Present (External_Default_Of (Node, In_Tree)) then
747                     Write_String (", ", Indent);
748                     Print (External_Default_Of (Node, In_Tree), Indent);
749                  end if;
750
751                  Write_String (")", Indent);
752
753               when N_Attribute_Reference =>
754                  pragma Debug (Indicate_Tested (N_Attribute_Reference));
755
756                  if Present (Project_Node_Of (Node, In_Tree))
757                    and then Project_Node_Of (Node, In_Tree) /= Project
758                  then
759                     Output_Name
760                       (Name_Of (Project_Node_Of (Node, In_Tree), In_Tree),
761                        Indent);
762
763                     if Present (Package_Node_Of (Node, In_Tree)) then
764                        Write_String (".", Indent);
765                        Output_Name
766                          (Name_Of (Package_Node_Of (Node, In_Tree), In_Tree),
767                           Indent);
768                     end if;
769
770                  elsif Present (Package_Node_Of (Node, In_Tree)) then
771                     Output_Name
772                       (Name_Of (Package_Node_Of (Node, In_Tree), In_Tree),
773                        Indent);
774
775                  else
776                     Write_String ("project", Indent);
777                  end if;
778
779                  Write_String ("'", Indent);
780                  Output_Attribute_Name (Name_Of (Node, In_Tree), Indent);
781
782                  declare
783                     Index : constant Name_Id :=
784                               Associative_Array_Index_Of (Node, In_Tree);
785
786                  begin
787                     if Index /= No_Name then
788                        Write_String (" (", Indent);
789                        Output_String (Index, Indent);
790                        Write_String (")", Indent);
791                     end if;
792                  end;
793
794               when N_Case_Construction =>
795                  pragma Debug (Indicate_Tested (N_Case_Construction));
796
797                  declare
798                     Case_Item    : Project_Node_Id;
799                     Is_Non_Empty : Boolean := False;
800
801                  begin
802                     Case_Item := First_Case_Item_Of (Node, In_Tree);
803                     while Present (Case_Item) loop
804                        if Present
805                            (First_Declarative_Item_Of (Case_Item, In_Tree))
806                           or else not Eliminate_Empty_Case_Constructions
807                        then
808                           Is_Non_Empty := True;
809                           exit;
810                        end if;
811
812                        Case_Item := Next_Case_Item (Case_Item, In_Tree);
813                     end loop;
814
815                     if Is_Non_Empty then
816                        Write_Empty_Line;
817                        Print (First_Comment_Before (Node, In_Tree), Indent);
818                        Start_Line (Indent);
819                        Write_String ("case ", Indent);
820                        Print
821                          (Case_Variable_Reference_Of (Node, In_Tree),
822                           Indent);
823                        Write_String (" is", Indent);
824                        Write_End_Of_Line_Comment (Node);
825                        Print
826                          (First_Comment_After (Node, In_Tree),
827                           Indent + Increment);
828
829                        declare
830                           Case_Item : Project_Node_Id :=
831                                         First_Case_Item_Of (Node, In_Tree);
832                        begin
833                           while Present (Case_Item) loop
834                              pragma Assert
835                                (Kind_Of (Case_Item, In_Tree) = N_Case_Item);
836                              Print (Case_Item, Indent + Increment);
837                              Case_Item :=
838                                Next_Case_Item (Case_Item, In_Tree);
839                           end loop;
840                        end;
841
842                        Print (First_Comment_Before_End (Node, In_Tree),
843                               Indent + Increment);
844                        Start_Line (Indent);
845                        Write_Line ("end case;");
846                        Print
847                          (First_Comment_After_End (Node, In_Tree), Indent);
848                     end if;
849                  end;
850
851               when N_Case_Item =>
852                  pragma Debug (Indicate_Tested (N_Case_Item));
853
854                  if Present (First_Declarative_Item_Of (Node, In_Tree))
855                    or else not Eliminate_Empty_Case_Constructions
856                  then
857                     Write_Empty_Line;
858                     Print (First_Comment_Before (Node, In_Tree), Indent);
859                     Start_Line (Indent);
860                     Write_String ("when ", Indent);
861
862                     if No (First_Choice_Of (Node, In_Tree)) then
863                        Write_String ("others", Indent);
864
865                     else
866                        declare
867                           Label : Project_Node_Id :=
868                                     First_Choice_Of (Node, In_Tree);
869                        begin
870                           while Present (Label) loop
871                              Print (Label, Indent);
872                              Label := Next_Literal_String (Label, In_Tree);
873
874                              if Present (Label) then
875                                 Write_String (" | ", Indent);
876                              end if;
877                           end loop;
878                        end;
879                     end if;
880
881                     Write_String (" =>", Indent);
882                     Write_End_Of_Line_Comment (Node);
883                     Print
884                       (First_Comment_After (Node, In_Tree),
885                        Indent + Increment);
886
887                     declare
888                        First : constant Project_Node_Id :=
889                                  First_Declarative_Item_Of (Node, In_Tree);
890                     begin
891                        if No (First) then
892                           Write_Empty_Line;
893                        else
894                           Print (First, Indent + Increment);
895                        end if;
896                     end;
897                  end if;
898
899               when N_Comment_Zones =>
900
901               --  Nothing to do, because it will not be processed directly
902
903                  null;
904
905               when N_Comment =>
906                  pragma Debug (Indicate_Tested (N_Comment));
907
908                  if Follows_Empty_Line (Node, In_Tree) then
909                     Write_Empty_Line;
910                  end if;
911
912                  Start_Line (Indent);
913                  Write_String ("--", Indent);
914                  Write_String
915                    (Get_Name_String (String_Value_Of (Node, In_Tree)),
916                     Indent,
917                     Truncated => True);
918                  Write_Line ("");
919
920                  if Is_Followed_By_Empty_Line (Node, In_Tree) then
921                     Write_Empty_Line;
922                  end if;
923
924                  Print (Next_Comment (Node, In_Tree), Indent);
925            end case;
926         end if;
927      end Print;
928
929   --  Start of processing for Pretty_Print
930
931   begin
932      if W_Char = null then
933         Write_Char := Output.Write_Char'Access;
934      else
935         Write_Char := W_Char;
936      end if;
937
938      if W_Eol = null then
939         Write_Eol := Output.Write_Eol'Access;
940      else
941         Write_Eol := W_Eol;
942      end if;
943
944      if W_Str = null then
945         Write_Str := Output.Write_Str'Access;
946      else
947         Write_Str := W_Str;
948      end if;
949
950      Print (Project, 0);
951   end Pretty_Print;
952
953   -----------------------
954   -- Output_Statistics --
955   -----------------------
956
957   procedure Output_Statistics is
958   begin
959      Output.Write_Line ("Project_Node_Kinds not tested:");
960
961      for Kind in Project_Node_Kind loop
962         if Kind /= N_Comment_Zones and then Not_Tested (Kind) then
963            Output.Write_Str ("   ");
964            Output.Write_Line (Project_Node_Kind'Image (Kind));
965         end if;
966      end loop;
967
968      Output.Write_Eol;
969   end Output_Statistics;
970
971   ---------
972   -- wpr --
973   ---------
974
975   procedure wpr
976     (Project : Prj.Tree.Project_Node_Id;
977      In_Tree : Prj.Tree.Project_Node_Tree_Ref) is
978   begin
979      Pretty_Print (Project, In_Tree, Backward_Compatibility => False);
980   end wpr;
981
982end Prj.PP;
983