1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2002 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
;
32 with Stringt
; use Stringt
;
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 -- outputting 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.
56 procedure Indicate_Tested
(Kind
: Project_Node_Kind
) is
58 Not_Tested
(Kind
) := False;
65 procedure Pretty_Print
66 (Project
: Prj
.Tree
.Project_Node_Id
;
67 Increment
: Positive := 3;
68 Eliminate_Empty_Case_Constructions
: Boolean := False;
69 Minimize_Empty_Lines
: Boolean := False;
70 W_Char
: Write_Char_Ap
:= null;
71 W_Eol
: Write_Eol_Ap
:= null;
72 W_Str
: Write_Str_Ap
:= null) is
74 procedure Print
(Node
: Project_Node_Id
; Indent
: Natural);
75 -- A recursive procedure that traverses a project file tree
76 -- and outputs its source.
77 -- Current_Prj is the project that we are printing. This
78 -- is used when printing attributes, since in nested packages they need
79 -- to use a fully qualified name.
81 procedure Output_Name
(Name
: Name_Id
; Capitalize
: Boolean := True);
84 procedure Start_Line
(Indent
: Natural);
85 -- Outputs the indentation at the beginning of the line.
87 procedure Output_String
(S
: String_Id
);
88 -- Outputs a string using the default output procedures
90 procedure Write_Empty_Line
(Always
: Boolean := False);
91 -- Outputs an empty line, only if the previous line was not
92 -- empty already and either Always is True or Minimize_Empty_Lines
95 procedure Write_Line
(S
: String);
96 -- Outputs S followed by a new line
98 procedure Write_String
(S
: String);
99 -- Outputs S using Write_Str, starting a new line if line would
102 Write_Char
: Write_Char_Ap
:= Output
.Write_Char
'Access;
103 Write_Eol
: Write_Eol_Ap
:= Output
.Write_Eol
'Access;
104 Write_Str
: Write_Str_Ap
:= Output
.Write_Str
'Access;
105 -- These two access to procedure values are used for the output.
107 Last_Line_Is_Empty
: Boolean := False;
108 -- Used to avoid two consecutive empty lines.
114 procedure Output_Name
(Name
: Name_Id
; Capitalize
: Boolean := True) is
115 Capital
: Boolean := Capitalize
;
118 Get_Name_String
(Name
);
120 -- If line would become too long, create new line
122 if Column
+ Name_Len
> Max_Line_Length
then
127 for J
in 1 .. Name_Len
loop
129 Write_Char
(To_Upper
(Name_Buffer
(J
)));
131 Write_Char
(Name_Buffer
(J
));
136 Name_Buffer
(J
) = '_'
137 or else Is_Digit
(Name_Buffer
(J
));
146 procedure Output_String
(S
: String_Id
) is
148 String_To_Name_Buffer
(S
);
150 -- If line could become too long, create new line.
151 -- Note that the number of characters on the line could be
152 -- twice the number of character in the string (if every
153 -- character is a '"') plus two (the initial and final '"').
155 if Column
+ Name_Len
+ Name_Len
+ 2 > Max_Line_Length
then
161 Column
:= Column
+ 1;
162 String_To_Name_Buffer
(S
);
164 for J
in 1 .. Name_Len
loop
165 if Name_Buffer
(J
) = '"' then
168 Column
:= Column
+ 2;
170 Write_Char
(Name_Buffer
(J
));
171 Column
:= Column
+ 1;
174 -- If the string does not fit on one line, cut it in parts
177 if J
< Name_Len
and then Column
>= Max_Line_Length
then
186 Column
:= Column
+ 1;
193 procedure Start_Line
(Indent
: Natural) is
195 if not Minimize_Empty_Lines
then
196 Write_Str
((1 .. Indent
=> ' '));
197 Column
:= Column
+ Indent
;
201 ----------------------
202 -- Write_Empty_Line --
203 ----------------------
205 procedure Write_Empty_Line
(Always
: Boolean := False) is
207 if (Always
or else not Minimize_Empty_Lines
)
208 and then not Last_Line_Is_Empty
then
211 Last_Line_Is_Empty
:= True;
213 end Write_Empty_Line
;
219 procedure Write_Line
(S
: String) is
222 Last_Line_Is_Empty
:= False;
231 procedure Write_String
(S
: String) is
233 -- If the string would not fit on the line,
236 if Column
+ S
'Length > Max_Line_Length
then
242 Column
:= Column
+ S
'Length;
249 procedure Print
(Node
: Project_Node_Id
; Indent
: Natural) is
251 if Node
/= Empty_Node
then
253 case Kind_Of
(Node
) is
256 pragma Debug
(Indicate_Tested
(N_Project
));
257 if First_With_Clause_Of
(Node
) /= Empty_Node
then
261 Print
(First_With_Clause_Of
(Node
), Indent
);
262 Write_Empty_Line
(Always
=> True);
266 Write_String
("project ");
267 Output_Name
(Name_Of
(Node
));
269 -- Check if this project modifies another project
271 if Modified_Project_Path_Of
(Node
) /= No_String
then
272 Write_String
(" extends ");
273 Output_String
(Modified_Project_Path_Of
(Node
));
277 Write_Empty_Line
(Always
=> True);
279 -- Output all of the declarations in the project
281 Print
(Project_Declaration_Of
(Node
), Indent
);
283 Write_String
("end ");
284 Output_Name
(Name_Of
(Node
));
287 when N_With_Clause
=>
288 pragma Debug
(Indicate_Tested
(N_With_Clause
));
290 if Name_Of
(Node
) /= No_Name
then
292 Write_String
("with ");
293 Output_String
(String_Value_Of
(Node
));
297 Print
(Next_With_Clause_Of
(Node
), Indent
);
299 when N_Project_Declaration
=>
300 pragma Debug
(Indicate_Tested
(N_Project_Declaration
));
302 if First_Declarative_Item_Of
(Node
) /= Empty_Node
then
304 (First_Declarative_Item_Of
(Node
), Indent
+ Increment
);
305 Write_Empty_Line
(Always
=> True);
308 when N_Declarative_Item
=>
309 pragma Debug
(Indicate_Tested
(N_Declarative_Item
));
310 Print
(Current_Item_Node
(Node
), Indent
);
311 Print
(Next_Declarative_Item
(Node
), Indent
);
313 when N_Package_Declaration
=>
314 pragma Debug
(Indicate_Tested
(N_Package_Declaration
));
315 Write_Empty_Line
(Always
=> True);
317 Write_String
("package ");
318 Output_Name
(Name_Of
(Node
));
320 if Project_Of_Renamed_Package_Of
(Node
) /= Empty_Node
then
321 Write_String
(" renames ");
323 (Name_Of
(Project_Of_Renamed_Package_Of
(Node
)));
325 Output_Name
(Name_Of
(Node
));
331 if First_Declarative_Item_Of
(Node
) /= Empty_Node
then
333 (First_Declarative_Item_Of
(Node
),
338 Write_String
("end ");
339 Output_Name
(Name_Of
(Node
));
344 when N_String_Type_Declaration
=>
345 pragma Debug
(Indicate_Tested
(N_String_Type_Declaration
));
347 Write_String
("type ");
348 Output_Name
(Name_Of
(Node
));
350 Start_Line
(Indent
+ Increment
);
354 String_Node
: Project_Node_Id
:=
355 First_Literal_String
(Node
);
358 while String_Node
/= Empty_Node
loop
359 Output_String
(String_Value_Of
(String_Node
));
360 String_Node
:= Next_Literal_String
(String_Node
);
362 if String_Node
/= Empty_Node
then
370 when N_Literal_String
=>
371 pragma Debug
(Indicate_Tested
(N_Literal_String
));
372 Output_String
(String_Value_Of
(Node
));
374 when N_Attribute_Declaration
=>
375 pragma Debug
(Indicate_Tested
(N_Attribute_Declaration
));
377 Write_String
("for ");
378 Output_Name
(Name_Of
(Node
));
380 if Associative_Array_Index_Of
(Node
) /= No_String
then
382 Output_String
(Associative_Array_Index_Of
(Node
));
386 Write_String
(" use ");
387 Print
(Expression_Of
(Node
), Indent
);
390 when N_Typed_Variable_Declaration
=>
392 (Indicate_Tested
(N_Typed_Variable_Declaration
));
394 Output_Name
(Name_Of
(Node
));
395 Write_String
(" : ");
396 Output_Name
(Name_Of
(String_Type_Of
(Node
)));
397 Write_String
(" := ");
398 Print
(Expression_Of
(Node
), Indent
);
401 when N_Variable_Declaration
=>
402 pragma Debug
(Indicate_Tested
(N_Variable_Declaration
));
404 Output_Name
(Name_Of
(Node
));
405 Write_String
(" := ");
406 Print
(Expression_Of
(Node
), Indent
);
410 pragma Debug
(Indicate_Tested
(N_Expression
));
412 Term
: Project_Node_Id
:= First_Term
(Node
);
415 while Term
/= Empty_Node
loop
416 Print
(Term
, Indent
);
417 Term
:= Next_Term
(Term
);
419 if Term
/= Empty_Node
then
420 Write_String
(" & ");
426 pragma Debug
(Indicate_Tested
(N_Term
));
427 Print
(Current_Term
(Node
), Indent
);
429 when N_Literal_String_List
=>
430 pragma Debug
(Indicate_Tested
(N_Literal_String_List
));
434 Expression
: Project_Node_Id
:=
435 First_Expression_In_List
(Node
);
438 while Expression
/= Empty_Node
loop
439 Print
(Expression
, Indent
);
440 Expression
:= Next_Expression_In_List
(Expression
);
442 if Expression
/= Empty_Node
then
450 when N_Variable_Reference
=>
451 pragma Debug
(Indicate_Tested
(N_Variable_Reference
));
452 if Project_Node_Of
(Node
) /= Empty_Node
then
453 Output_Name
(Name_Of
(Project_Node_Of
(Node
)));
457 if Package_Node_Of
(Node
) /= Empty_Node
then
458 Output_Name
(Name_Of
(Package_Node_Of
(Node
)));
462 Output_Name
(Name_Of
(Node
));
464 when N_External_Value
=>
465 pragma Debug
(Indicate_Tested
(N_External_Value
));
466 Write_String
("external (");
467 Print
(External_Reference_Of
(Node
), Indent
);
469 if External_Default_Of
(Node
) /= Empty_Node
then
471 Print
(External_Default_Of
(Node
), Indent
);
476 when N_Attribute_Reference
=>
477 pragma Debug
(Indicate_Tested
(N_Attribute_Reference
));
479 if Project_Node_Of
(Node
) /= Empty_Node
480 and then Project_Node_Of
(Node
) /= Project
482 Output_Name
(Name_Of
(Project_Node_Of
(Node
)));
484 if Package_Node_Of
(Node
) /= Empty_Node
then
486 Output_Name
(Name_Of
(Package_Node_Of
(Node
)));
489 elsif Package_Node_Of
(Node
) /= Empty_Node
then
490 Output_Name
(Name_Of
(Package_Node_Of
(Node
)));
493 Write_String
("project");
497 Output_Name
(Name_Of
(Node
));
500 Index
: constant String_Id
:=
501 Associative_Array_Index_Of
(Node
);
504 if Index
/= No_String
then
506 Output_String
(Index
);
511 when N_Case_Construction
=>
512 pragma Debug
(Indicate_Tested
(N_Case_Construction
));
515 Case_Item
: Project_Node_Id
:= First_Case_Item_Of
(Node
);
516 Is_Non_Empty
: Boolean := False;
518 while Case_Item
/= Empty_Node
loop
519 if First_Declarative_Item_Of
(Case_Item
) /= Empty_Node
520 or else not Eliminate_Empty_Case_Constructions
522 Is_Non_Empty
:= True;
525 Case_Item
:= Next_Case_Item
(Case_Item
);
531 Write_String
("case ");
532 Print
(Case_Variable_Reference_Of
(Node
), Indent
);
536 Case_Item
: Project_Node_Id
:=
537 First_Case_Item_Of
(Node
);
540 while Case_Item
/= Empty_Node
loop
542 (Kind_Of
(Case_Item
) = N_Case_Item
);
543 Print
(Case_Item
, Indent
+ Increment
);
544 Case_Item
:= Next_Case_Item
(Case_Item
);
549 Write_Line
("end case;");
554 pragma Debug
(Indicate_Tested
(N_Case_Item
));
556 if First_Declarative_Item_Of
(Node
) /= Empty_Node
557 or else not Eliminate_Empty_Case_Constructions
561 Write_String
("when ");
563 if First_Choice_Of
(Node
) = Empty_Node
then
564 Write_String
("others");
568 Label
: Project_Node_Id
:= First_Choice_Of
(Node
);
571 while Label
/= Empty_Node
loop
572 Print
(Label
, Indent
);
573 Label
:= Next_Literal_String
(Label
);
575 if Label
/= Empty_Node
then
576 Write_String
(" | ");
585 First
: Project_Node_Id
:=
586 First_Declarative_Item_Of
(Node
);
589 if First
= Empty_Node
then
593 Print
(First
, Indent
+ Increment
);
602 if W_Char
= null then
603 Write_Char
:= Output
.Write_Char
'Access;
605 Write_Char
:= W_Char
;
609 Write_Eol
:= Output
.Write_Eol
'Access;
615 Write_Str
:= Output
.Write_Str
'Access;
622 if W_Char
= null or else W_Str
= null then
627 -----------------------
628 -- Output_Statistics --
629 -----------------------
631 procedure Output_Statistics
is
633 Output
.Write_Line
("Project_Node_Kinds not tested:");
635 for Kind
in Project_Node_Kind
loop
636 if Not_Tested
(Kind
) then
637 Output
.Write_Str
(" ");
638 Output
.Write_Line
(Project_Node_Kind
'Image (Kind
));
643 end Output_Statistics
;