* Make-lang.in (nmake.ads): Add dependency on ada/nmake.adb
[official-gcc.git] / gcc / ada / prj-pp.adb
blob8bbc265efc8fe3273cc6e28c0fa0961a5685e63d
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.
52 ---------------------
53 -- Indicate_Tested --
54 ---------------------
56 procedure Indicate_Tested (Kind : Project_Node_Kind) is
57 begin
58 Not_Tested (Kind) := False;
59 end Indicate_Tested;
61 ------------------
62 -- Pretty_Print --
63 ------------------
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;
73 Backward_Compatibility : Boolean)
75 procedure Print (Node : Project_Node_Id; Indent : Natural);
76 -- A recursive procedure that traverses a project file tree and outputs
77 -- its source. Current_Prj is the project that we are printing. This
78 -- is used when printing attributes, since in nested packages they
79 -- need to use a fully qualified name.
81 procedure Output_Attribute_Name (Name : Name_Id);
82 -- Outputs an attribute name, taking into account the value of
83 -- Backward_Compatibility.
85 procedure Output_Name (Name : Name_Id; Capitalize : Boolean := True);
86 -- Outputs a name
88 procedure Start_Line (Indent : Natural);
89 -- Outputs the indentation at the beginning of the line.
91 procedure Output_String (S : Name_Id);
92 -- Outputs a string using the default output procedures
94 procedure Write_Empty_Line (Always : Boolean := False);
95 -- Outputs an empty line, only if the previous line was not empty
96 -- already and either Always is True or Minimize_Empty_Lines is False.
98 procedure Write_Line (S : String);
99 -- Outputs S followed by a new line
101 procedure Write_String (S : String);
102 -- Outputs S using Write_Str, starting a new line if line would
103 -- become too long.
105 Write_Char : Write_Char_Ap := Output.Write_Char'Access;
106 Write_Eol : Write_Eol_Ap := Output.Write_Eol'Access;
107 Write_Str : Write_Str_Ap := Output.Write_Str'Access;
108 -- These three access to procedure values are used for the output.
110 Last_Line_Is_Empty : Boolean := False;
111 -- Used to avoid two consecutive empty lines.
113 ---------------------------
114 -- Output_Attribute_Name --
115 ---------------------------
117 procedure Output_Attribute_Name (Name : Name_Id) is
118 begin
119 if Backward_Compatibility then
120 case Name is
121 when Snames.Name_Spec =>
122 Output_Name (Snames.Name_Specification);
124 when Snames.Name_Spec_Suffix =>
125 Output_Name (Snames.Name_Specification_Suffix);
127 when Snames.Name_Body =>
128 Output_Name (Snames.Name_Implementation);
130 when Snames.Name_Body_Suffix =>
131 Output_Name (Snames.Name_Implementation_Suffix);
133 when others =>
134 Output_Name (Name);
135 end case;
137 else
138 Output_Name (Name);
139 end if;
140 end Output_Attribute_Name;
142 -----------------
143 -- Output_Name --
144 -----------------
146 procedure Output_Name (Name : Name_Id; Capitalize : Boolean := True) is
147 Capital : Boolean := Capitalize;
149 begin
150 Get_Name_String (Name);
152 -- If line would become too long, create new line
154 if Column + Name_Len > Max_Line_Length then
155 Write_Eol.all;
156 Column := 0;
157 end if;
159 for J in 1 .. Name_Len loop
160 if Capital then
161 Write_Char (To_Upper (Name_Buffer (J)));
162 else
163 Write_Char (Name_Buffer (J));
164 end if;
166 if Capitalize then
167 Capital :=
168 Name_Buffer (J) = '_'
169 or else Is_Digit (Name_Buffer (J));
170 end if;
171 end loop;
173 Column := Column + Name_Len;
174 end Output_Name;
176 -------------------
177 -- Output_String --
178 -------------------
180 procedure Output_String (S : Name_Id) is
181 begin
182 Get_Name_String (S);
184 -- If line could become too long, create new line.
185 -- Note that the number of characters on the line could be
186 -- twice the number of character in the string (if every
187 -- character is a '"') plus two (the initial and final '"').
189 if Column + Name_Len + Name_Len + 2 > Max_Line_Length then
190 Write_Eol.all;
191 Column := 0;
192 end if;
194 Write_Char ('"');
195 Column := Column + 1;
196 Get_Name_String (S);
198 for J in 1 .. Name_Len loop
199 if Name_Buffer (J) = '"' then
200 Write_Char ('"');
201 Write_Char ('"');
202 Column := Column + 2;
203 else
204 Write_Char (Name_Buffer (J));
205 Column := Column + 1;
206 end if;
208 -- If the string does not fit on one line, cut it in parts
209 -- and concatenate.
211 if J < Name_Len and then Column >= Max_Line_Length then
212 Write_Str (""" &");
213 Write_Eol.all;
214 Write_Char ('"');
215 Column := 1;
216 end if;
217 end loop;
219 Write_Char ('"');
220 Column := Column + 1;
221 end Output_String;
223 ----------------
224 -- Start_Line --
225 ----------------
227 procedure Start_Line (Indent : Natural) is
228 begin
229 if not Minimize_Empty_Lines then
230 Write_Str ((1 .. Indent => ' '));
231 Column := Column + Indent;
232 end if;
233 end Start_Line;
235 ----------------------
236 -- Write_Empty_Line --
237 ----------------------
239 procedure Write_Empty_Line (Always : Boolean := False) is
240 begin
241 if (Always or else not Minimize_Empty_Lines)
242 and then not Last_Line_Is_Empty then
243 Write_Eol.all;
244 Column := 0;
245 Last_Line_Is_Empty := True;
246 end if;
247 end Write_Empty_Line;
249 ----------------
250 -- Write_Line --
251 ----------------
253 procedure Write_Line (S : String) is
254 begin
255 Write_String (S);
256 Last_Line_Is_Empty := False;
257 Write_Eol.all;
258 Column := 0;
259 end Write_Line;
261 ------------------
262 -- Write_String --
263 ------------------
265 procedure Write_String (S : String) is
266 begin
267 -- If the string would not fit on the line,
268 -- start a new line.
270 if Column + S'Length > Max_Line_Length then
271 Write_Eol.all;
272 Column := 0;
273 end if;
275 Write_Str (S);
276 Column := Column + S'Length;
277 end Write_String;
279 -----------
280 -- Print --
281 -----------
283 procedure Print (Node : Project_Node_Id; Indent : Natural) is
284 begin
285 if Node /= Empty_Node then
287 case Kind_Of (Node) is
289 when N_Project =>
290 pragma Debug (Indicate_Tested (N_Project));
291 if First_With_Clause_Of (Node) /= Empty_Node then
293 -- with clause(s)
295 Print (First_With_Clause_Of (Node), Indent);
296 Write_Empty_Line (Always => True);
297 end if;
299 Start_Line (Indent);
300 Write_String ("project ");
301 Output_Name (Name_Of (Node));
303 -- Check if this project extends another project
305 if Extended_Project_Path_Of (Node) /= No_Name then
306 Write_String (" extends ");
307 Output_String (Extended_Project_Path_Of (Node));
308 end if;
310 Write_Line (" is");
311 Write_Empty_Line (Always => True);
313 -- Output all of the declarations in the project
315 Print (Project_Declaration_Of (Node), Indent);
316 Start_Line (Indent);
317 Write_String ("end ");
318 Output_Name (Name_Of (Node));
319 Write_Line (";");
321 when N_With_Clause =>
322 pragma Debug (Indicate_Tested (N_With_Clause));
324 if Name_Of (Node) /= No_Name then
325 Start_Line (Indent);
327 if Non_Limited_Project_Node_Of (Node) = Empty_Node then
328 Write_String ("limited ");
329 end if;
331 Write_String ("with ");
332 Output_String (String_Value_Of (Node));
333 Write_Line (";");
334 end if;
336 Print (Next_With_Clause_Of (Node), Indent);
338 when N_Project_Declaration =>
339 pragma Debug (Indicate_Tested (N_Project_Declaration));
341 if First_Declarative_Item_Of (Node) /= Empty_Node then
342 Print
343 (First_Declarative_Item_Of (Node), Indent + Increment);
344 Write_Empty_Line (Always => True);
345 end if;
347 when N_Declarative_Item =>
348 pragma Debug (Indicate_Tested (N_Declarative_Item));
349 Print (Current_Item_Node (Node), Indent);
350 Print (Next_Declarative_Item (Node), Indent);
352 when N_Package_Declaration =>
353 pragma Debug (Indicate_Tested (N_Package_Declaration));
354 Write_Empty_Line (Always => True);
355 Start_Line (Indent);
356 Write_String ("package ");
357 Output_Name (Name_Of (Node));
359 if Project_Of_Renamed_Package_Of (Node) /= Empty_Node then
360 Write_String (" renames ");
361 Output_Name
362 (Name_Of (Project_Of_Renamed_Package_Of (Node)));
363 Write_String (".");
364 Output_Name (Name_Of (Node));
365 Write_Line (";");
367 else
368 Write_Line (" is");
370 if First_Declarative_Item_Of (Node) /= Empty_Node then
371 Print
372 (First_Declarative_Item_Of (Node),
373 Indent + Increment);
374 end if;
376 Start_Line (Indent);
377 Write_String ("end ");
378 Output_Name (Name_Of (Node));
379 Write_Line (";");
380 Write_Empty_Line;
381 end if;
383 when N_String_Type_Declaration =>
384 pragma Debug (Indicate_Tested (N_String_Type_Declaration));
385 Start_Line (Indent);
386 Write_String ("type ");
387 Output_Name (Name_Of (Node));
388 Write_Line (" is");
389 Start_Line (Indent + Increment);
390 Write_String ("(");
392 declare
393 String_Node : Project_Node_Id :=
394 First_Literal_String (Node);
396 begin
397 while String_Node /= Empty_Node loop
398 Output_String (String_Value_Of (String_Node));
399 String_Node := Next_Literal_String (String_Node);
401 if String_Node /= Empty_Node then
402 Write_String (", ");
403 end if;
404 end loop;
405 end;
407 Write_Line (");");
409 when N_Literal_String =>
410 pragma Debug (Indicate_Tested (N_Literal_String));
411 Output_String (String_Value_Of (Node));
413 when N_Attribute_Declaration =>
414 pragma Debug (Indicate_Tested (N_Attribute_Declaration));
415 Start_Line (Indent);
416 Write_String ("for ");
417 Output_Attribute_Name (Name_Of (Node));
419 if Associative_Array_Index_Of (Node) /= No_Name then
420 Write_String (" (");
421 Output_String (Associative_Array_Index_Of (Node));
422 Write_String (")");
423 end if;
425 Write_String (" use ");
426 Print (Expression_Of (Node), Indent);
427 Write_Line (";");
429 when N_Typed_Variable_Declaration =>
430 pragma Debug
431 (Indicate_Tested (N_Typed_Variable_Declaration));
432 Start_Line (Indent);
433 Output_Name (Name_Of (Node));
434 Write_String (" : ");
435 Output_Name (Name_Of (String_Type_Of (Node)));
436 Write_String (" := ");
437 Print (Expression_Of (Node), Indent);
438 Write_Line (";");
440 when N_Variable_Declaration =>
441 pragma Debug (Indicate_Tested (N_Variable_Declaration));
442 Start_Line (Indent);
443 Output_Name (Name_Of (Node));
444 Write_String (" := ");
445 Print (Expression_Of (Node), Indent);
446 Write_Line (";");
448 when N_Expression =>
449 pragma Debug (Indicate_Tested (N_Expression));
450 declare
451 Term : Project_Node_Id := First_Term (Node);
453 begin
454 while Term /= Empty_Node loop
455 Print (Term, Indent);
456 Term := Next_Term (Term);
458 if Term /= Empty_Node then
459 Write_String (" & ");
460 end if;
461 end loop;
462 end;
464 when N_Term =>
465 pragma Debug (Indicate_Tested (N_Term));
466 Print (Current_Term (Node), Indent);
468 when N_Literal_String_List =>
469 pragma Debug (Indicate_Tested (N_Literal_String_List));
470 Write_String ("(");
472 declare
473 Expression : Project_Node_Id :=
474 First_Expression_In_List (Node);
476 begin
477 while Expression /= Empty_Node loop
478 Print (Expression, Indent);
479 Expression := Next_Expression_In_List (Expression);
481 if Expression /= Empty_Node then
482 Write_String (", ");
483 end if;
484 end loop;
485 end;
487 Write_String (")");
489 when N_Variable_Reference =>
490 pragma Debug (Indicate_Tested (N_Variable_Reference));
491 if Project_Node_Of (Node) /= Empty_Node then
492 Output_Name (Name_Of (Project_Node_Of (Node)));
493 Write_String (".");
494 end if;
496 if Package_Node_Of (Node) /= Empty_Node then
497 Output_Name (Name_Of (Package_Node_Of (Node)));
498 Write_String (".");
499 end if;
501 Output_Name (Name_Of (Node));
503 when N_External_Value =>
504 pragma Debug (Indicate_Tested (N_External_Value));
505 Write_String ("external (");
506 Print (External_Reference_Of (Node), Indent);
508 if External_Default_Of (Node) /= Empty_Node then
509 Write_String (", ");
510 Print (External_Default_Of (Node), Indent);
511 end if;
513 Write_String (")");
515 when N_Attribute_Reference =>
516 pragma Debug (Indicate_Tested (N_Attribute_Reference));
518 if Project_Node_Of (Node) /= Empty_Node
519 and then Project_Node_Of (Node) /= Project
520 then
521 Output_Name (Name_Of (Project_Node_Of (Node)));
523 if Package_Node_Of (Node) /= Empty_Node then
524 Write_String (".");
525 Output_Name (Name_Of (Package_Node_Of (Node)));
526 end if;
528 elsif Package_Node_Of (Node) /= Empty_Node then
529 Output_Name (Name_Of (Package_Node_Of (Node)));
531 else
532 Write_String ("project");
533 end if;
535 Write_String ("'");
536 Output_Attribute_Name (Name_Of (Node));
538 declare
539 Index : constant Name_Id :=
540 Associative_Array_Index_Of (Node);
542 begin
543 if Index /= No_Name then
544 Write_String (" (");
545 Output_String (Index);
546 Write_String (")");
547 end if;
548 end;
550 when N_Case_Construction =>
551 pragma Debug (Indicate_Tested (N_Case_Construction));
553 declare
554 Case_Item : Project_Node_Id := First_Case_Item_Of (Node);
555 Is_Non_Empty : Boolean := False;
556 begin
557 while Case_Item /= Empty_Node loop
558 if First_Declarative_Item_Of (Case_Item) /= Empty_Node
559 or else not Eliminate_Empty_Case_Constructions
560 then
561 Is_Non_Empty := True;
562 exit;
563 end if;
564 Case_Item := Next_Case_Item (Case_Item);
565 end loop;
567 if Is_Non_Empty then
568 Write_Empty_Line;
569 Start_Line (Indent);
570 Write_String ("case ");
571 Print (Case_Variable_Reference_Of (Node), Indent);
572 Write_Line (" is");
574 declare
575 Case_Item : Project_Node_Id :=
576 First_Case_Item_Of (Node);
578 begin
579 while Case_Item /= Empty_Node loop
580 pragma Assert
581 (Kind_Of (Case_Item) = N_Case_Item);
582 Print (Case_Item, Indent + Increment);
583 Case_Item := Next_Case_Item (Case_Item);
584 end loop;
585 end;
587 Start_Line (Indent);
588 Write_Line ("end case;");
589 end if;
590 end;
592 when N_Case_Item =>
593 pragma Debug (Indicate_Tested (N_Case_Item));
595 if First_Declarative_Item_Of (Node) /= Empty_Node
596 or else not Eliminate_Empty_Case_Constructions
597 then
598 Write_Empty_Line;
599 Start_Line (Indent);
600 Write_String ("when ");
602 if First_Choice_Of (Node) = Empty_Node then
603 Write_String ("others");
605 else
606 declare
607 Label : Project_Node_Id := First_Choice_Of (Node);
609 begin
610 while Label /= Empty_Node loop
611 Print (Label, Indent);
612 Label := Next_Literal_String (Label);
614 if Label /= Empty_Node then
615 Write_String (" | ");
616 end if;
617 end loop;
618 end;
619 end if;
621 Write_Line (" =>");
623 declare
624 First : constant Project_Node_Id :=
625 First_Declarative_Item_Of (Node);
627 begin
628 if First = Empty_Node then
629 Write_Eol.all;
631 else
632 Print (First, Indent + Increment);
633 end if;
634 end;
635 end if;
636 end case;
637 end if;
638 end Print;
640 -- Start of processing for Pretty_Print
642 begin
643 if W_Char = null then
644 Write_Char := Output.Write_Char'Access;
645 else
646 Write_Char := W_Char;
647 end if;
649 if W_Eol = null then
650 Write_Eol := Output.Write_Eol'Access;
651 else
652 Write_Eol := W_Eol;
653 end if;
655 if W_Str = null then
656 Write_Str := Output.Write_Str'Access;
657 else
658 Write_Str := W_Str;
659 end if;
661 Print (Project, 0);
663 if W_Char = null or else W_Str = null then
664 Output.Write_Eol;
665 end if;
666 end Pretty_Print;
668 -----------------------
669 -- Output_Statistics --
670 -----------------------
672 procedure Output_Statistics is
673 begin
674 Output.Write_Line ("Project_Node_Kinds not tested:");
676 for Kind in Project_Node_Kind loop
677 if Not_Tested (Kind) then
678 Output.Write_Str (" ");
679 Output.Write_Line (Project_Node_Kind'Image (Kind));
680 end if;
681 end loop;
683 Output.Write_Eol;
684 end Output_Statistics;
686 end Prj.PP;