2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / ada / prj-pp.adb
blob1ac45ed28e3379ba5438618c16238c7039ecf0b3
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J . P P --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2003 Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
21 -- --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 -- --
25 ------------------------------------------------------------------------------
27 with Ada.Characters.Handling; use Ada.Characters.Handling;
29 with Hostparm;
30 with Namet; use Namet;
31 with Output; use Output;
32 with Snames;
34 package body Prj.PP is
36 use Prj.Tree;
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.
51 ---------------------
52 -- Indicate_Tested --
53 ---------------------
55 procedure Indicate_Tested (Kind : Project_Node_Kind) is
56 begin
57 Not_Tested (Kind) := False;
58 end Indicate_Tested;
60 ------------------
61 -- Pretty_Print --
62 ------------------
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);
85 -- Outputs a name
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
121 begin
122 if Backward_Compatibility then
123 case Name is
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);
136 when others =>
137 Output_Name (Name);
138 end case;
140 else
141 Output_Name (Name);
142 end if;
143 end Output_Attribute_Name;
145 -----------------
146 -- Output_Name --
147 -----------------
149 procedure Output_Name (Name : Name_Id; Capitalize : Boolean := True) is
150 Capital : Boolean := Capitalize;
152 begin
153 Get_Name_String (Name);
155 -- If line would become too long, create new line
157 if Column + Name_Len > Max_Line_Length then
158 Write_Eol.all;
159 Column := 0;
160 end if;
162 for J in 1 .. Name_Len loop
163 if Capital then
164 Write_Char (To_Upper (Name_Buffer (J)));
165 else
166 Write_Char (Name_Buffer (J));
167 end if;
169 if Capitalize then
170 Capital :=
171 Name_Buffer (J) = '_'
172 or else Is_Digit (Name_Buffer (J));
173 end if;
174 end loop;
176 Column := Column + Name_Len;
177 end Output_Name;
179 -------------------
180 -- Output_String --
181 -------------------
183 procedure Output_String (S : Name_Id) is
184 begin
185 Get_Name_String (S);
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
193 Write_Eol.all;
194 Column := 0;
195 end if;
197 Write_Char ('"');
198 Column := Column + 1;
199 Get_Name_String (S);
201 for J in 1 .. Name_Len loop
202 if Name_Buffer (J) = '"' then
203 Write_Char ('"');
204 Write_Char ('"');
205 Column := Column + 2;
206 else
207 Write_Char (Name_Buffer (J));
208 Column := Column + 1;
209 end if;
211 -- If the string does not fit on one line, cut it in parts
212 -- and concatenate.
214 if J < Name_Len and then Column >= Max_Line_Length then
215 Write_Str (""" &");
216 Write_Eol.all;
217 Write_Char ('"');
218 Column := 1;
219 end if;
220 end loop;
222 Write_Char ('"');
223 Column := Column + 1;
224 end Output_String;
226 ----------------
227 -- Start_Line --
228 ----------------
230 procedure Start_Line (Indent : Natural) is
231 begin
232 if not Minimize_Empty_Lines then
233 Write_Str ((1 .. Indent => ' '));
234 Column := Column + Indent;
235 end if;
236 end Start_Line;
238 ----------------------
239 -- Write_Empty_Line --
240 ----------------------
242 procedure Write_Empty_Line (Always : Boolean := False) is
243 begin
244 if (Always or else not Minimize_Empty_Lines)
245 and then not Last_Line_Is_Empty then
246 Write_Eol.all;
247 Column := 0;
248 Last_Line_Is_Empty := True;
249 end if;
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);
258 begin
259 if Value /= No_Name then
260 Write_String (" --");
261 Write_String (Get_Name_String (Value), Truncated => True);
262 end if;
264 Write_Line ("");
265 end Write_End_Of_Line_Comment;
267 ----------------
268 -- Write_Line --
269 ----------------
271 procedure Write_Line (S : String) is
272 begin
273 Write_String (S);
274 Last_Line_Is_Empty := False;
275 Write_Eol.all;
276 Column := 0;
277 end Write_Line;
279 ------------------
280 -- Write_String --
281 ------------------
283 procedure Write_String (S : String; Truncated : Boolean := False) is
284 Length : Natural := S'Length;
285 begin
286 -- If the string would not fit on the line,
287 -- start a new line.
289 if Column + Length > Max_Line_Length then
290 if Truncated then
291 Length := Max_Line_Length - Column;
293 else
294 Write_Eol.all;
295 Column := 0;
296 end if;
297 end if;
299 Write_Str (S (S'First .. S'First + Length - 1));
300 Column := Column + Length;
301 end Write_String;
303 -----------
304 -- Print --
305 -----------
307 procedure Print (Node : Project_Node_Id; Indent : Natural) is
308 begin
309 if Node /= Empty_Node then
311 case Kind_Of (Node) is
313 when N_Project =>
314 pragma Debug (Indicate_Tested (N_Project));
315 if First_With_Clause_Of (Node) /= Empty_Node then
317 -- with clause(s)
319 Print (First_With_Clause_Of (Node), Indent);
320 Write_Empty_Line (Always => True);
321 end if;
323 Print (First_Comment_Before (Node), Indent);
324 Start_Line (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));
333 end if;
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);
344 Start_Line (Indent);
345 Write_String ("end ");
346 Output_Name (Name_Of (Node));
347 Write_Line (";");
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);
355 Start_Line (Indent);
357 if Non_Limited_Project_Node_Of (Node) = Empty_Node then
358 Write_String ("limited ");
359 end if;
361 Write_String ("with ");
362 Output_String (String_Value_Of (Node));
363 Write_String (";");
364 Write_End_Of_Line_Comment (Node);
365 Print (First_Comment_After (Node), Indent);
366 end if;
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
374 Print
375 (First_Declarative_Item_Of (Node), Indent + Increment);
376 Write_Empty_Line (Always => True);
377 end if;
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);
388 Start_Line (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 ");
394 Output_Name
395 (Name_Of (Project_Of_Renamed_Package_Of (Node)));
396 Write_String (".");
397 Output_Name (Name_Of (Node));
398 Write_String (";");
399 Write_End_Of_Line_Comment (Node);
400 Print (First_Comment_After_End (Node), Indent);
402 else
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
408 Print
409 (First_Declarative_Item_Of (Node),
410 Indent + Increment);
411 end if;
413 Print (First_Comment_Before_End (Node),
414 Indent + Increment);
415 Start_Line (Indent);
416 Write_String ("end ");
417 Output_Name (Name_Of (Node));
418 Write_Line (";");
419 Print (First_Comment_After_End (Node), Indent);
420 Write_Empty_Line;
421 end if;
423 when N_String_Type_Declaration =>
424 pragma Debug (Indicate_Tested (N_String_Type_Declaration));
425 Print (First_Comment_Before (Node), Indent);
426 Start_Line (Indent);
427 Write_String ("type ");
428 Output_Name (Name_Of (Node));
429 Write_Line (" is");
430 Start_Line (Indent + Increment);
431 Write_String ("(");
433 declare
434 String_Node : Project_Node_Id :=
435 First_Literal_String (Node);
437 begin
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
443 Write_String (", ");
444 end if;
445 end loop;
446 end;
448 Write_String (");");
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);
459 Start_Line (Indent);
460 Write_String ("for ");
461 Output_Attribute_Name (Name_Of (Node));
463 if Associative_Array_Index_Of (Node) /= No_Name then
464 Write_String (" (");
465 Output_String (Associative_Array_Index_Of (Node));
466 Write_String (")");
467 end if;
469 Write_String (" use ");
470 Print (Expression_Of (Node), Indent);
471 Write_String (";");
472 Write_End_Of_Line_Comment (Node);
473 Print (First_Comment_After (Node), Indent);
475 when N_Typed_Variable_Declaration =>
476 pragma Debug
477 (Indicate_Tested (N_Typed_Variable_Declaration));
478 Print (First_Comment_Before (Node), Indent);
479 Start_Line (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);
485 Write_String (";");
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);
492 Start_Line (Indent);
493 Output_Name (Name_Of (Node));
494 Write_String (" := ");
495 Print (Expression_Of (Node), Indent);
496 Write_String (";");
497 Write_End_Of_Line_Comment (Node);
498 Print (First_Comment_After (Node), Indent);
500 when N_Expression =>
501 pragma Debug (Indicate_Tested (N_Expression));
502 declare
503 Term : Project_Node_Id := First_Term (Node);
505 begin
506 while Term /= Empty_Node loop
507 Print (Term, Indent);
508 Term := Next_Term (Term);
510 if Term /= Empty_Node then
511 Write_String (" & ");
512 end if;
513 end loop;
514 end;
516 when N_Term =>
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));
522 Write_String ("(");
524 declare
525 Expression : Project_Node_Id :=
526 First_Expression_In_List (Node);
528 begin
529 while Expression /= Empty_Node loop
530 Print (Expression, Indent);
531 Expression := Next_Expression_In_List (Expression);
533 if Expression /= Empty_Node then
534 Write_String (", ");
535 end if;
536 end loop;
537 end;
539 Write_String (")");
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)));
545 Write_String (".");
546 end if;
548 if Package_Node_Of (Node) /= Empty_Node then
549 Output_Name (Name_Of (Package_Node_Of (Node)));
550 Write_String (".");
551 end if;
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
561 Write_String (", ");
562 Print (External_Default_Of (Node), Indent);
563 end if;
565 Write_String (")");
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
572 then
573 Output_Name (Name_Of (Project_Node_Of (Node)));
575 if Package_Node_Of (Node) /= Empty_Node then
576 Write_String (".");
577 Output_Name (Name_Of (Package_Node_Of (Node)));
578 end if;
580 elsif Package_Node_Of (Node) /= Empty_Node then
581 Output_Name (Name_Of (Package_Node_Of (Node)));
583 else
584 Write_String ("project");
585 end if;
587 Write_String ("'");
588 Output_Attribute_Name (Name_Of (Node));
590 declare
591 Index : constant Name_Id :=
592 Associative_Array_Index_Of (Node);
594 begin
595 if Index /= No_Name then
596 Write_String (" (");
597 Output_String (Index);
598 Write_String (")");
599 end if;
600 end;
602 when N_Case_Construction =>
603 pragma Debug (Indicate_Tested (N_Case_Construction));
605 declare
606 Case_Item : Project_Node_Id := First_Case_Item_Of (Node);
607 Is_Non_Empty : Boolean := False;
608 begin
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
612 then
613 Is_Non_Empty := True;
614 exit;
615 end if;
616 Case_Item := Next_Case_Item (Case_Item);
617 end loop;
619 if Is_Non_Empty then
620 Write_Empty_Line;
621 Print (First_Comment_Before (Node), Indent);
622 Start_Line (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);
629 declare
630 Case_Item : Project_Node_Id :=
631 First_Case_Item_Of (Node);
633 begin
634 while Case_Item /= Empty_Node loop
635 pragma Assert
636 (Kind_Of (Case_Item) = N_Case_Item);
637 Print (Case_Item, Indent + Increment);
638 Case_Item := Next_Case_Item (Case_Item);
639 end loop;
640 end;
642 Print (First_Comment_Before_End (Node),
643 Indent + Increment);
644 Start_Line (Indent);
645 Write_Line ("end case;");
646 Print (First_Comment_After_End (Node), Indent);
647 end if;
648 end;
650 when N_Case_Item =>
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
655 then
656 Write_Empty_Line;
657 Print (First_Comment_Before (Node), Indent);
658 Start_Line (Indent);
659 Write_String ("when ");
661 if First_Choice_Of (Node) = Empty_Node then
662 Write_String ("others");
664 else
665 declare
666 Label : Project_Node_Id := First_Choice_Of (Node);
668 begin
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 (" | ");
675 end if;
676 end loop;
677 end;
678 end if;
680 Write_String (" =>");
681 Write_End_Of_Line_Comment (Node);
682 Print (First_Comment_After (Node), Indent + Increment);
684 declare
685 First : constant Project_Node_Id :=
686 First_Declarative_Item_Of (Node);
688 begin
689 if First = Empty_Node then
690 Write_Empty_Line;
692 else
693 Print (First, Indent + Increment);
694 end if;
695 end;
696 end if;
698 when N_Comment_Zones =>
700 -- Nothing to do, because it will not be processed directly
702 null;
704 when N_Comment =>
705 pragma Debug (Indicate_Tested (N_Comment));
707 if Follows_Empty_Line (Node) then
708 Write_Empty_Line;
709 end if;
711 Start_Line (Indent);
712 Write_String ("--");
713 Write_String
714 (Get_Name_String (String_Value_Of (Node)),
715 Truncated => True);
716 Write_Line ("");
718 if Is_Followed_By_Empty_Line (Node) then
719 Write_Empty_Line;
720 end if;
722 Print (Next_Comment (Node), Indent);
723 end case;
724 end if;
725 end Print;
727 -- Start of processing for Pretty_Print
729 begin
730 if W_Char = null then
731 Write_Char := Output.Write_Char'Access;
732 else
733 Write_Char := W_Char;
734 end if;
736 if W_Eol = null then
737 Write_Eol := Output.Write_Eol'Access;
738 else
739 Write_Eol := W_Eol;
740 end if;
742 if W_Str = null then
743 Write_Str := Output.Write_Str'Access;
744 else
745 Write_Str := W_Str;
746 end if;
748 Print (Project, 0);
750 if W_Char = null or else W_Str = null then
751 Output.Write_Eol;
752 end if;
753 end Pretty_Print;
755 -----------------------
756 -- Output_Statistics --
757 -----------------------
759 procedure Output_Statistics is
760 begin
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));
767 end if;
768 end loop;
770 Output.Write_Eol;
771 end Output_Statistics;
773 end Prj.PP;