1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2003 Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Ada
.Characters
.Handling
; use Ada
.Characters
.Handling
;
30 with Namet
; use Namet
;
31 with Output
; use Output
;
34 package body Prj
.PP
is
38 Not_Tested
: array (Project_Node_Kind
) of Boolean := (others => True);
40 Max_Line_Length
: constant := Hostparm
.Max_Line_Length
- 5;
41 -- Maximum length of a line.
43 Column
: Natural := 0;
44 -- Column number of the last character in the line. Used to avoid
45 -- outputing lines longer than Max_Line_Length.
47 procedure Indicate_Tested
(Kind
: Project_Node_Kind
);
48 -- Set the corresponding component of array Not_Tested to False.
49 -- Only called by pragmas Debug.
55 procedure Indicate_Tested
(Kind
: Project_Node_Kind
) is
57 Not_Tested
(Kind
) := False;
64 procedure Pretty_Print
65 (Project
: Prj
.Tree
.Project_Node_Id
;
66 Increment
: Positive := 3;
67 Eliminate_Empty_Case_Constructions
: Boolean := False;
68 Minimize_Empty_Lines
: Boolean := False;
69 W_Char
: Write_Char_Ap
:= null;
70 W_Eol
: Write_Eol_Ap
:= null;
71 W_Str
: Write_Str_Ap
:= null;
72 Backward_Compatibility
: Boolean)
74 procedure Print
(Node
: Project_Node_Id
; Indent
: Natural);
75 -- A recursive procedure that traverses a project file tree and outputs
76 -- its source. Current_Prj is the project that we are printing. This
77 -- is used when printing attributes, since in nested packages they
78 -- need to use a fully qualified name.
80 procedure Output_Attribute_Name
(Name
: Name_Id
);
81 -- Outputs an attribute name, taking into account the value of
82 -- Backward_Compatibility.
84 procedure Output_Name
(Name
: Name_Id
; Capitalize
: Boolean := True);
87 procedure Start_Line
(Indent
: Natural);
88 -- Outputs the indentation at the beginning of the line.
90 procedure Output_String
(S
: Name_Id
);
91 -- Outputs a string using the default output procedures
93 procedure Write_Empty_Line
(Always
: Boolean := False);
94 -- Outputs an empty line, only if the previous line was not empty
95 -- already and either Always is True or Minimize_Empty_Lines is False.
97 procedure Write_Line
(S
: String);
98 -- Outputs S followed by a new line
100 procedure Write_String
(S
: String; Truncated
: Boolean := False);
101 -- Outputs S using Write_Str, starting a new line if line would
102 -- become too long, when Truncated = False.
103 -- When Truncated = True, only the part of the string that can fit on
104 -- the line is output.
106 procedure Write_End_Of_Line_Comment
(Node
: Project_Node_Id
);
108 Write_Char
: Write_Char_Ap
:= Output
.Write_Char
'Access;
109 Write_Eol
: Write_Eol_Ap
:= Output
.Write_Eol
'Access;
110 Write_Str
: Write_Str_Ap
:= Output
.Write_Str
'Access;
111 -- These three access to procedure values are used for the output.
113 Last_Line_Is_Empty
: Boolean := False;
114 -- Used to avoid two consecutive empty lines.
116 ---------------------------
117 -- Output_Attribute_Name --
118 ---------------------------
120 procedure Output_Attribute_Name
(Name
: Name_Id
) is
122 if Backward_Compatibility
then
124 when Snames
.Name_Spec
=>
125 Output_Name
(Snames
.Name_Specification
);
127 when Snames
.Name_Spec_Suffix
=>
128 Output_Name
(Snames
.Name_Specification_Suffix
);
130 when Snames
.Name_Body
=>
131 Output_Name
(Snames
.Name_Implementation
);
133 when Snames
.Name_Body_Suffix
=>
134 Output_Name
(Snames
.Name_Implementation_Suffix
);
143 end Output_Attribute_Name
;
149 procedure Output_Name
(Name
: Name_Id
; Capitalize
: Boolean := True) is
150 Capital
: Boolean := Capitalize
;
153 Get_Name_String
(Name
);
155 -- If line would become too long, create new line
157 if Column
+ Name_Len
> Max_Line_Length
then
162 for J
in 1 .. Name_Len
loop
164 Write_Char
(To_Upper
(Name_Buffer
(J
)));
166 Write_Char
(Name_Buffer
(J
));
171 Name_Buffer
(J
) = '_'
172 or else Is_Digit
(Name_Buffer
(J
));
176 Column
:= Column
+ Name_Len
;
183 procedure Output_String
(S
: Name_Id
) is
187 -- If line could become too long, create new line.
188 -- Note that the number of characters on the line could be
189 -- twice the number of character in the string (if every
190 -- character is a '"') plus two (the initial and final '"').
192 if Column
+ Name_Len
+ Name_Len
+ 2 > Max_Line_Length
then
198 Column
:= Column
+ 1;
201 for J
in 1 .. Name_Len
loop
202 if Name_Buffer
(J
) = '"' then
205 Column
:= Column
+ 2;
207 Write_Char
(Name_Buffer
(J
));
208 Column
:= Column
+ 1;
211 -- If the string does not fit on one line, cut it in parts
214 if J
< Name_Len
and then Column
>= Max_Line_Length
then
223 Column
:= Column
+ 1;
230 procedure Start_Line
(Indent
: Natural) is
232 if not Minimize_Empty_Lines
then
233 Write_Str
((1 .. Indent
=> ' '));
234 Column
:= Column
+ Indent
;
238 ----------------------
239 -- Write_Empty_Line --
240 ----------------------
242 procedure Write_Empty_Line
(Always
: Boolean := False) is
244 if (Always
or else not Minimize_Empty_Lines
)
245 and then not Last_Line_Is_Empty
then
248 Last_Line_Is_Empty
:= True;
250 end Write_Empty_Line
;
252 -------------------------------
253 -- Write_End_Of_Line_Comment --
254 -------------------------------
256 procedure Write_End_Of_Line_Comment
(Node
: Project_Node_Id
) is
257 Value
: Name_Id
:= End_Of_Line_Comment
(Node
);
259 if Value
/= No_Name
then
260 Write_String
(" --");
261 Write_String
(Get_Name_String
(Value
), Truncated
=> True);
265 end Write_End_Of_Line_Comment
;
271 procedure Write_Line
(S
: String) is
274 Last_Line_Is_Empty
:= False;
283 procedure Write_String
(S
: String; Truncated
: Boolean := False) is
284 Length
: Natural := S
'Length;
286 -- If the string would not fit on the line,
289 if Column
+ Length
> Max_Line_Length
then
291 Length
:= Max_Line_Length
- Column
;
299 Write_Str
(S
(S
'First .. S
'First + Length
- 1));
300 Column
:= Column
+ Length
;
307 procedure Print
(Node
: Project_Node_Id
; Indent
: Natural) is
309 if Node
/= Empty_Node
then
311 case Kind_Of
(Node
) is
314 pragma Debug
(Indicate_Tested
(N_Project
));
315 if First_With_Clause_Of
(Node
) /= Empty_Node
then
319 Print
(First_With_Clause_Of
(Node
), Indent
);
320 Write_Empty_Line
(Always
=> True);
323 Print
(First_Comment_Before
(Node
), Indent
);
325 Write_String
("project ");
326 Output_Name
(Name_Of
(Node
));
328 -- Check if this project extends another project
330 if Extended_Project_Path_Of
(Node
) /= No_Name
then
331 Write_String
(" extends ");
332 Output_String
(Extended_Project_Path_Of
(Node
));
335 Write_String
(" is");
336 Write_End_Of_Line_Comment
(Node
);
337 Print
(First_Comment_After
(Node
), Indent
+ Increment
);
338 Write_Empty_Line
(Always
=> True);
340 -- Output all of the declarations in the project
342 Print
(Project_Declaration_Of
(Node
), Indent
);
343 Print
(First_Comment_Before_End
(Node
), Indent
+ Increment
);
345 Write_String
("end ");
346 Output_Name
(Name_Of
(Node
));
348 Print
(First_Comment_After_End
(Node
), Indent
);
350 when N_With_Clause
=>
351 pragma Debug
(Indicate_Tested
(N_With_Clause
));
353 if Name_Of
(Node
) /= No_Name
then
354 Print
(First_Comment_Before
(Node
), Indent
);
357 if Non_Limited_Project_Node_Of
(Node
) = Empty_Node
then
358 Write_String
("limited ");
361 Write_String
("with ");
362 Output_String
(String_Value_Of
(Node
));
364 Write_End_Of_Line_Comment
(Node
);
365 Print
(First_Comment_After
(Node
), Indent
);
368 Print
(Next_With_Clause_Of
(Node
), Indent
);
370 when N_Project_Declaration
=>
371 pragma Debug
(Indicate_Tested
(N_Project_Declaration
));
373 if First_Declarative_Item_Of
(Node
) /= Empty_Node
then
375 (First_Declarative_Item_Of
(Node
), Indent
+ Increment
);
376 Write_Empty_Line
(Always
=> True);
379 when N_Declarative_Item
=>
380 pragma Debug
(Indicate_Tested
(N_Declarative_Item
));
381 Print
(Current_Item_Node
(Node
), Indent
);
382 Print
(Next_Declarative_Item
(Node
), Indent
);
384 when N_Package_Declaration
=>
385 pragma Debug
(Indicate_Tested
(N_Package_Declaration
));
386 Write_Empty_Line
(Always
=> True);
387 Print
(First_Comment_Before
(Node
), Indent
);
389 Write_String
("package ");
390 Output_Name
(Name_Of
(Node
));
392 if Project_Of_Renamed_Package_Of
(Node
) /= Empty_Node
then
393 Write_String
(" renames ");
395 (Name_Of
(Project_Of_Renamed_Package_Of
(Node
)));
397 Output_Name
(Name_Of
(Node
));
399 Write_End_Of_Line_Comment
(Node
);
400 Print
(First_Comment_After_End
(Node
), Indent
);
403 Write_String
(" is");
404 Write_End_Of_Line_Comment
(Node
);
405 Print
(First_Comment_After
(Node
), Indent
+ Increment
);
407 if First_Declarative_Item_Of
(Node
) /= Empty_Node
then
409 (First_Declarative_Item_Of
(Node
),
413 Print
(First_Comment_Before_End
(Node
),
416 Write_String
("end ");
417 Output_Name
(Name_Of
(Node
));
419 Print
(First_Comment_After_End
(Node
), Indent
);
423 when N_String_Type_Declaration
=>
424 pragma Debug
(Indicate_Tested
(N_String_Type_Declaration
));
425 Print
(First_Comment_Before
(Node
), Indent
);
427 Write_String
("type ");
428 Output_Name
(Name_Of
(Node
));
430 Start_Line
(Indent
+ Increment
);
434 String_Node
: Project_Node_Id
:=
435 First_Literal_String
(Node
);
438 while String_Node
/= Empty_Node
loop
439 Output_String
(String_Value_Of
(String_Node
));
440 String_Node
:= Next_Literal_String
(String_Node
);
442 if String_Node
/= Empty_Node
then
449 Write_End_Of_Line_Comment
(Node
);
450 Print
(First_Comment_After
(Node
), Indent
);
452 when N_Literal_String
=>
453 pragma Debug
(Indicate_Tested
(N_Literal_String
));
454 Output_String
(String_Value_Of
(Node
));
456 when N_Attribute_Declaration
=>
457 pragma Debug
(Indicate_Tested
(N_Attribute_Declaration
));
458 Print
(First_Comment_Before
(Node
), Indent
);
460 Write_String
("for ");
461 Output_Attribute_Name
(Name_Of
(Node
));
463 if Associative_Array_Index_Of
(Node
) /= No_Name
then
465 Output_String
(Associative_Array_Index_Of
(Node
));
469 Write_String
(" use ");
470 Print
(Expression_Of
(Node
), Indent
);
472 Write_End_Of_Line_Comment
(Node
);
473 Print
(First_Comment_After
(Node
), Indent
);
475 when N_Typed_Variable_Declaration
=>
477 (Indicate_Tested
(N_Typed_Variable_Declaration
));
478 Print
(First_Comment_Before
(Node
), Indent
);
480 Output_Name
(Name_Of
(Node
));
481 Write_String
(" : ");
482 Output_Name
(Name_Of
(String_Type_Of
(Node
)));
483 Write_String
(" := ");
484 Print
(Expression_Of
(Node
), Indent
);
486 Write_End_Of_Line_Comment
(Node
);
487 Print
(First_Comment_After
(Node
), Indent
);
489 when N_Variable_Declaration
=>
490 pragma Debug
(Indicate_Tested
(N_Variable_Declaration
));
491 Print
(First_Comment_Before
(Node
), Indent
);
493 Output_Name
(Name_Of
(Node
));
494 Write_String
(" := ");
495 Print
(Expression_Of
(Node
), Indent
);
497 Write_End_Of_Line_Comment
(Node
);
498 Print
(First_Comment_After
(Node
), Indent
);
501 pragma Debug
(Indicate_Tested
(N_Expression
));
503 Term
: Project_Node_Id
:= First_Term
(Node
);
506 while Term
/= Empty_Node
loop
507 Print
(Term
, Indent
);
508 Term
:= Next_Term
(Term
);
510 if Term
/= Empty_Node
then
511 Write_String
(" & ");
517 pragma Debug
(Indicate_Tested
(N_Term
));
518 Print
(Current_Term
(Node
), Indent
);
520 when N_Literal_String_List
=>
521 pragma Debug
(Indicate_Tested
(N_Literal_String_List
));
525 Expression
: Project_Node_Id
:=
526 First_Expression_In_List
(Node
);
529 while Expression
/= Empty_Node
loop
530 Print
(Expression
, Indent
);
531 Expression
:= Next_Expression_In_List
(Expression
);
533 if Expression
/= Empty_Node
then
541 when N_Variable_Reference
=>
542 pragma Debug
(Indicate_Tested
(N_Variable_Reference
));
543 if Project_Node_Of
(Node
) /= Empty_Node
then
544 Output_Name
(Name_Of
(Project_Node_Of
(Node
)));
548 if Package_Node_Of
(Node
) /= Empty_Node
then
549 Output_Name
(Name_Of
(Package_Node_Of
(Node
)));
553 Output_Name
(Name_Of
(Node
));
555 when N_External_Value
=>
556 pragma Debug
(Indicate_Tested
(N_External_Value
));
557 Write_String
("external (");
558 Print
(External_Reference_Of
(Node
), Indent
);
560 if External_Default_Of
(Node
) /= Empty_Node
then
562 Print
(External_Default_Of
(Node
), Indent
);
567 when N_Attribute_Reference
=>
568 pragma Debug
(Indicate_Tested
(N_Attribute_Reference
));
570 if Project_Node_Of
(Node
) /= Empty_Node
571 and then Project_Node_Of
(Node
) /= Project
573 Output_Name
(Name_Of
(Project_Node_Of
(Node
)));
575 if Package_Node_Of
(Node
) /= Empty_Node
then
577 Output_Name
(Name_Of
(Package_Node_Of
(Node
)));
580 elsif Package_Node_Of
(Node
) /= Empty_Node
then
581 Output_Name
(Name_Of
(Package_Node_Of
(Node
)));
584 Write_String
("project");
588 Output_Attribute_Name
(Name_Of
(Node
));
591 Index
: constant Name_Id
:=
592 Associative_Array_Index_Of
(Node
);
595 if Index
/= No_Name
then
597 Output_String
(Index
);
602 when N_Case_Construction
=>
603 pragma Debug
(Indicate_Tested
(N_Case_Construction
));
606 Case_Item
: Project_Node_Id
:= First_Case_Item_Of
(Node
);
607 Is_Non_Empty
: Boolean := False;
609 while Case_Item
/= Empty_Node
loop
610 if First_Declarative_Item_Of
(Case_Item
) /= Empty_Node
611 or else not Eliminate_Empty_Case_Constructions
613 Is_Non_Empty
:= True;
616 Case_Item
:= Next_Case_Item
(Case_Item
);
621 Print
(First_Comment_Before
(Node
), Indent
);
623 Write_String
("case ");
624 Print
(Case_Variable_Reference_Of
(Node
), Indent
);
625 Write_String
(" is");
626 Write_End_Of_Line_Comment
(Node
);
627 Print
(First_Comment_After
(Node
), Indent
+ Increment
);
630 Case_Item
: Project_Node_Id
:=
631 First_Case_Item_Of
(Node
);
634 while Case_Item
/= Empty_Node
loop
636 (Kind_Of
(Case_Item
) = N_Case_Item
);
637 Print
(Case_Item
, Indent
+ Increment
);
638 Case_Item
:= Next_Case_Item
(Case_Item
);
642 Print
(First_Comment_Before_End
(Node
),
645 Write_Line
("end case;");
646 Print
(First_Comment_After_End
(Node
), Indent
);
651 pragma Debug
(Indicate_Tested
(N_Case_Item
));
653 if First_Declarative_Item_Of
(Node
) /= Empty_Node
654 or else not Eliminate_Empty_Case_Constructions
657 Print
(First_Comment_Before
(Node
), Indent
);
659 Write_String
("when ");
661 if First_Choice_Of
(Node
) = Empty_Node
then
662 Write_String
("others");
666 Label
: Project_Node_Id
:= First_Choice_Of
(Node
);
669 while Label
/= Empty_Node
loop
670 Print
(Label
, Indent
);
671 Label
:= Next_Literal_String
(Label
);
673 if Label
/= Empty_Node
then
674 Write_String
(" | ");
680 Write_String
(" =>");
681 Write_End_Of_Line_Comment
(Node
);
682 Print
(First_Comment_After
(Node
), Indent
+ Increment
);
685 First
: constant Project_Node_Id
:=
686 First_Declarative_Item_Of
(Node
);
689 if First
= Empty_Node
then
693 Print
(First
, Indent
+ Increment
);
698 when N_Comment_Zones
=>
700 -- Nothing to do, because it will not be processed directly
705 pragma Debug
(Indicate_Tested
(N_Comment
));
707 if Follows_Empty_Line
(Node
) then
714 (Get_Name_String
(String_Value_Of
(Node
)),
718 if Is_Followed_By_Empty_Line
(Node
) then
722 Print
(Next_Comment
(Node
), Indent
);
727 -- Start of processing for Pretty_Print
730 if W_Char
= null then
731 Write_Char
:= Output
.Write_Char
'Access;
733 Write_Char
:= W_Char
;
737 Write_Eol
:= Output
.Write_Eol
'Access;
743 Write_Str
:= Output
.Write_Str
'Access;
750 if W_Char
= null or else W_Str
= null then
755 -----------------------
756 -- Output_Statistics --
757 -----------------------
759 procedure Output_Statistics
is
761 Output
.Write_Line
("Project_Node_Kinds not tested:");
763 for Kind
in Project_Node_Kind
loop
764 if Kind
/= N_Comment_Zones
and then Not_Tested
(Kind
) then
765 Output
.Write_Str
(" ");
766 Output
.Write_Line
(Project_Node_Kind
'Image (Kind
));
771 end Output_Statistics
;