1 ------------------------------------------------------------------------------
4 -- GNAT COMPILER COMPONENTS --
10 -- Copyright (C) 2001-2007, Free Software Foundation, Inc. --
12 -- GNAT is free software; you can redistribute it and/or modify it under --
13 -- terms of the GNU General Public License as published by the Free Soft- --
14 -- ware Foundation; either version 3, or (at your option) any later ver- --
15 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
18 -- for more details. You should have received a copy of the GNU General --
19 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
20 -- http://www.gnu.org/licenses for a complete copy of the license. --
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 Err_Vars; use Err_Vars;
29 with Osint; use Osint;
30 with Output; use Output;
31 with Prj.Attr; use Prj.Attr;
32 with Prj.Err; use Prj.Err;
33 with Prj.Ext; use Prj.Ext;
34 with Prj.Nmsc; use Prj.Nmsc;
35 with Sinput; use Sinput;
38 with GNAT.Case_Util; use GNAT.Case_Util;
41 package body Prj.Proc is
43 Error_Report : Put_Line_Access := null;
45 package Processed_Projects is new GNAT.HTable.Simple_HTable
46 (Header_Num => Header_Num,
47 Element => Project_Id,
48 No_Element => No_Project,
52 -- This hash table contains all processed projects
54 package Unit_Htable is new GNAT.HTable.Simple_HTable
55 (Header_Num => Header_Num,
57 No_Element => No_Source,
61 -- This hash table contains all processed projects
63 procedure Add (To_Exp : in out Name_Id; Str : Name_Id);
64 -- Concatenate two strings and returns another string if both
65 -- arguments are not null string.
67 procedure Add_Attributes
68 (Project : Project_Id;
69 Project_Name : Name_Id;
70 In_Tree : Project_Tree_Ref;
71 Decl : in out Declarations;
72 First : Attribute_Node_Id;
73 Project_Level : Boolean);
74 -- Add all attributes, starting with First, with their default
75 -- values to the package or project with declarations Decl.
78 (In_Tree : Project_Tree_Ref;
81 When_No_Sources : Error_Warning);
82 -- Set all projects to not checked, then call Recursive_Check for the
83 -- main project Project. Project is set to No_Project if errors occurred.
84 -- Current_Dir is for optimization purposes, avoiding extra system calls.
86 procedure Copy_Package_Declarations
88 To : in out Declarations;
90 In_Tree : Project_Tree_Ref);
91 -- Copy a package declaration From to To for a renamed package. Change the
92 -- locations of all the attributes to New_Loc.
95 (Project : Project_Id;
96 In_Tree : Project_Tree_Ref;
97 From_Project_Node : Project_Node_Id;
98 From_Project_Node_Tree : Project_Node_Tree_Ref;
100 First_Term : Project_Node_Id;
101 Kind : Variable_Kind) return Variable_Value;
102 -- From N_Expression project node From_Project_Node, compute the value
103 -- of an expression and return it as a Variable_Value.
105 function Imported_Or_Extended_Project_From
106 (Project : Project_Id;
107 In_Tree : Project_Tree_Ref;
108 With_Name : Name_Id) return Project_Id;
109 -- Find an imported or extended project of Project whose name is With_Name
111 function Package_From
112 (Project : Project_Id;
113 In_Tree : Project_Tree_Ref;
114 With_Name : Name_Id) return Package_Id;
115 -- Find the package of Project whose name is With_Name
117 procedure Process_Declarative_Items
118 (Project : Project_Id;
119 In_Tree : Project_Tree_Ref;
120 From_Project_Node : Project_Node_Id;
121 From_Project_Node_Tree : Project_Node_Tree_Ref;
123 Item : Project_Node_Id);
124 -- Process declarative items starting with From_Project_Node, and put them
125 -- in declarations Decl. This is a recursive procedure; it calls itself for
126 -- a package declaration or a case construction.
128 procedure Recursive_Process
129 (In_Tree : Project_Tree_Ref;
130 Project : out Project_Id;
131 From_Project_Node : Project_Node_Id;
132 From_Project_Node_Tree : Project_Node_Tree_Ref;
133 Extended_By : Project_Id);
134 -- Process project with node From_Project_Node in the tree.
135 -- Do nothing if From_Project_Node is Empty_Node.
136 -- If project has already been processed, simply return its project id.
137 -- Otherwise create a new project id, mark it as processed, call itself
138 -- recursively for all imported projects and a extended project, if any.
139 -- Then process the declarative items of the project.
141 procedure Recursive_Check
142 (Project : Project_Id;
143 In_Tree : Project_Tree_Ref;
144 Current_Dir : String;
145 When_No_Sources : Error_Warning);
146 -- If Project is not marked as checked, mark it as checked, call
147 -- Check_Naming_Scheme for the project, then call itself for a
148 -- possible extended project and all the imported projects of Project.
149 -- Current_Dir is for optimization purposes, avoiding extra system calls.
155 procedure Add (To_Exp : in out Name_Id; Str : Name_Id) is
157 if To_Exp = No_Name or else To_Exp = Empty_String then
159 -- To_Exp is nil or empty. The result is Str
163 -- If Str is nil, then do not change To_Ext
165 elsif Str /= No_Name and then Str /= Empty_String then
167 S : constant String := Get_Name_String (Str);
170 Get_Name_String (To_Exp);
171 Add_Str_To_Name_Buffer (S);
181 procedure Add_Attributes
182 (Project : Project_Id;
183 Project_Name : Name_Id;
184 In_Tree : Project_Tree_Ref;
185 Decl : in out Declarations;
186 First : Attribute_Node_Id;
187 Project_Level : Boolean)
189 The_Attribute : Attribute_Node_Id := First;
192 while The_Attribute /= Empty_Attribute loop
193 if Attribute_Kind_Of (The_Attribute) = Single then
195 New_Attribute : Variable_Value;
198 case Variable_Kind_Of (The_Attribute) is
200 -- Undefined should not happen
204 (False, "attribute with an undefined kind");
207 -- Single attributes have a default value of empty string
213 Location => No_Location,
215 Value => Empty_String,
218 -- Special case of <project>'Name
221 and then Attribute_Name_Of (The_Attribute) =
224 New_Attribute.Value := Project_Name;
227 -- List attributes have a default value of nil list
233 Location => No_Location,
235 Values => Nil_String);
239 Variable_Element_Table.Increment_Last
240 (In_Tree.Variable_Elements);
241 In_Tree.Variable_Elements.Table
242 (Variable_Element_Table.Last
243 (In_Tree.Variable_Elements)) :=
244 (Next => Decl.Attributes,
245 Name => Attribute_Name_Of (The_Attribute),
246 Value => New_Attribute);
247 Decl.Attributes := Variable_Element_Table.Last
248 (In_Tree.Variable_Elements);
252 The_Attribute := Next_Attribute (After => The_Attribute);
261 (In_Tree : Project_Tree_Ref;
262 Project : Project_Id;
263 Current_Dir : String;
264 When_No_Sources : Error_Warning)
267 -- Make sure that all projects are marked as not checked
269 for Index in Project_Table.First ..
270 Project_Table.Last (In_Tree.Projects)
272 In_Tree.Projects.Table (Index).Checked := False;
275 Recursive_Check (Project, In_Tree, Current_Dir, When_No_Sources);
277 -- Set the Other_Part field for the units
287 Source1 := In_Tree.First_Source;
288 while Source1 /= No_Source loop
289 Name := In_Tree.Sources.Table (Source1).Unit;
291 if Name /= No_Name then
292 Source2 := Unit_Htable.Get (Name);
294 if Source2 = No_Source then
295 Unit_Htable.Set (K => Name, E => Source1);
298 Unit_Htable.Remove (Name);
299 In_Tree.Sources.Table (Source1).Other_Part := Source2;
300 In_Tree.Sources.Table (Source2).Other_Part := Source1;
304 Source1 := In_Tree.Sources.Table (Source1).Next_In_Sources;
309 -------------------------------
310 -- Copy_Package_Declarations --
311 -------------------------------
313 procedure Copy_Package_Declarations
314 (From : Declarations;
315 To : in out Declarations;
316 New_Loc : Source_Ptr;
317 In_Tree : Project_Tree_Ref)
319 V1 : Variable_Id := From.Attributes;
320 V2 : Variable_Id := No_Variable;
322 A1 : Array_Id := From.Arrays;
323 A2 : Array_Id := No_Array;
325 E1 : Array_Element_Id;
326 E2 : Array_Element_Id := No_Array_Element;
330 -- To avoid references in error messages to attribute declarations in
331 -- an original package that has been renamed, copy all the attribute
332 -- declarations of the package and change all locations to New_Loc,
333 -- the location of the renamed package.
335 -- First single attributes
337 while V1 /= No_Variable loop
339 -- Copy the attribute
341 Var := In_Tree.Variable_Elements.Table (V1);
344 -- Remove the Next component
346 Var.Next := No_Variable;
348 -- Change the location to New_Loc
350 Var.Value.Location := New_Loc;
351 Variable_Element_Table.Increment_Last (In_Tree.Variable_Elements);
353 -- Put in new declaration
355 if To.Attributes = No_Variable then
357 Variable_Element_Table.Last (In_Tree.Variable_Elements);
360 In_Tree.Variable_Elements.Table (V2).Next :=
361 Variable_Element_Table.Last (In_Tree.Variable_Elements);
364 V2 := Variable_Element_Table.Last (In_Tree.Variable_Elements);
365 In_Tree.Variable_Elements.Table (V2) := Var;
368 -- Then the associated array attributes
370 while A1 /= No_Array loop
374 Arr := In_Tree.Arrays.Table (A1);
377 -- Remove the Next component
379 Arr.Next := No_Array;
381 Array_Table.Increment_Last (In_Tree.Arrays);
383 -- Create new Array declaration
384 if To.Arrays = No_Array then
385 To.Arrays := Array_Table.Last (In_Tree.Arrays);
388 In_Tree.Arrays.Table (A2).Next :=
389 Array_Table.Last (In_Tree.Arrays);
392 A2 := Array_Table.Last (In_Tree.Arrays);
394 -- Don't store the array, as its first element has not been set yet
396 -- Copy the array elements of the array
399 Arr.Value := No_Array_Element;
401 while E1 /= No_Array_Element loop
403 -- Copy the array element
405 Elm := In_Tree.Array_Elements.Table (E1);
408 -- Remove the Next component
410 Elm.Next := No_Array_Element;
412 -- Change the location
414 Elm.Value.Location := New_Loc;
415 Array_Element_Table.Increment_Last (In_Tree.Array_Elements);
417 -- Create new array element
419 if Arr.Value = No_Array_Element then
420 Arr.Value := Array_Element_Table.Last (In_Tree.Array_Elements);
422 In_Tree.Array_Elements.Table (E2).Next :=
423 Array_Element_Table.Last (In_Tree.Array_Elements);
426 E2 := Array_Element_Table.Last (In_Tree.Array_Elements);
427 In_Tree.Array_Elements.Table (E2) := Elm;
430 -- Finally, store the new array
432 In_Tree.Arrays.Table (A2) := Arr;
434 end Copy_Package_Declarations;
441 (Project : Project_Id;
442 In_Tree : Project_Tree_Ref;
443 From_Project_Node : Project_Node_Id;
444 From_Project_Node_Tree : Project_Node_Tree_Ref;
446 First_Term : Project_Node_Id;
447 Kind : Variable_Kind) return Variable_Value
449 The_Term : Project_Node_Id := First_Term;
450 -- The term in the expression list
452 The_Current_Term : Project_Node_Id := Empty_Node;
453 -- The current term node id
455 Result : Variable_Value (Kind => Kind);
456 -- The returned result
458 Last : String_List_Id := Nil_String;
459 -- Reference to the last string elements in Result, when Kind is List
462 Result.Project := Project;
463 Result.Location := Location_Of (First_Term, From_Project_Node_Tree);
465 -- Process each term of the expression, starting with First_Term
467 while The_Term /= Empty_Node loop
468 The_Current_Term := Current_Term (The_Term, From_Project_Node_Tree);
470 case Kind_Of (The_Current_Term, From_Project_Node_Tree) is
472 when N_Literal_String =>
478 -- Should never happen
480 pragma Assert (False, "Undefined expression kind");
486 (The_Current_Term, From_Project_Node_Tree));
489 (The_Current_Term, From_Project_Node_Tree);
493 String_Element_Table.Increment_Last
494 (In_Tree.String_Elements);
496 if Last = Nil_String then
498 -- This can happen in an expression like () & "toto"
500 Result.Values := String_Element_Table.Last
501 (In_Tree.String_Elements);
504 In_Tree.String_Elements.Table
505 (Last).Next := String_Element_Table.Last
506 (In_Tree.String_Elements);
509 Last := String_Element_Table.Last
510 (In_Tree.String_Elements);
511 In_Tree.String_Elements.Table (Last) :=
515 From_Project_Node_Tree),
518 (The_Current_Term, From_Project_Node_Tree),
519 Display_Value => No_Name,
523 From_Project_Node_Tree),
528 when N_Literal_String_List =>
531 String_Node : Project_Node_Id :=
532 First_Expression_In_List
534 From_Project_Node_Tree);
536 Value : Variable_Value;
539 if String_Node /= Empty_Node then
541 -- If String_Node is nil, it is an empty list,
542 -- there is nothing to do
547 From_Project_Node => From_Project_Node,
548 From_Project_Node_Tree => From_Project_Node_Tree,
552 (String_Node, From_Project_Node_Tree),
554 String_Element_Table.Increment_Last
555 (In_Tree.String_Elements);
557 if Result.Values = Nil_String then
559 -- This literal string list is the first term
560 -- in a string list expression
563 String_Element_Table.Last (In_Tree.String_Elements);
566 In_Tree.String_Elements.Table
568 String_Element_Table.Last (In_Tree.String_Elements);
572 String_Element_Table.Last (In_Tree.String_Elements);
574 In_Tree.String_Elements.Table (Last) :=
575 (Value => Value.Value,
576 Display_Value => No_Name,
577 Location => Value.Location,
580 Index => Value.Index);
583 -- Add the other element of the literal string list
584 -- one after the other
587 Next_Expression_In_List
588 (String_Node, From_Project_Node_Tree);
590 exit when String_Node = Empty_Node;
596 From_Project_Node => From_Project_Node,
597 From_Project_Node_Tree => From_Project_Node_Tree,
601 (String_Node, From_Project_Node_Tree),
604 String_Element_Table.Increment_Last
605 (In_Tree.String_Elements);
606 In_Tree.String_Elements.Table
607 (Last).Next := String_Element_Table.Last
608 (In_Tree.String_Elements);
609 Last := String_Element_Table.Last
610 (In_Tree.String_Elements);
611 In_Tree.String_Elements.Table (Last) :=
612 (Value => Value.Value,
613 Display_Value => No_Name,
614 Location => Value.Location,
617 Index => Value.Index);
622 when N_Variable_Reference | N_Attribute_Reference =>
625 The_Project : Project_Id := Project;
626 The_Package : Package_Id := Pkg;
627 The_Name : Name_Id := No_Name;
628 The_Variable_Id : Variable_Id := No_Variable;
629 The_Variable : Variable_Value;
630 Term_Project : constant Project_Node_Id :=
633 From_Project_Node_Tree);
634 Term_Package : constant Project_Node_Id :=
637 From_Project_Node_Tree);
638 Index : Name_Id := No_Name;
641 if Term_Project /= Empty_Node and then
642 Term_Project /= From_Project_Node
644 -- This variable or attribute comes from another project
647 Name_Of (Term_Project, From_Project_Node_Tree);
648 The_Project := Imported_Or_Extended_Project_From
651 With_Name => The_Name);
654 if Term_Package /= Empty_Node then
656 -- This is an attribute of a package
659 Name_Of (Term_Package, From_Project_Node_Tree);
660 The_Package := In_Tree.Projects.Table
661 (The_Project).Decl.Packages;
663 while The_Package /= No_Package
664 and then In_Tree.Packages.Table
665 (The_Package).Name /= The_Name
668 In_Tree.Packages.Table
673 (The_Package /= No_Package,
674 "package not found.");
676 elsif Kind_Of (The_Current_Term, From_Project_Node_Tree) =
677 N_Attribute_Reference
679 The_Package := No_Package;
683 Name_Of (The_Current_Term, From_Project_Node_Tree);
685 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
686 N_Attribute_Reference
689 Associative_Array_Index_Of
690 (The_Current_Term, From_Project_Node_Tree);
693 -- If it is not an associative array attribute
695 if Index = No_Name then
697 -- It is not an associative array attribute
699 if The_Package /= No_Package then
701 -- First, if there is a package, look into the package
703 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
707 In_Tree.Packages.Table
708 (The_Package).Decl.Variables;
711 In_Tree.Packages.Table
712 (The_Package).Decl.Attributes;
715 while The_Variable_Id /= No_Variable
717 In_Tree.Variable_Elements.Table
718 (The_Variable_Id).Name /= The_Name
721 In_Tree.Variable_Elements.Table
722 (The_Variable_Id).Next;
727 if The_Variable_Id = No_Variable then
729 -- If we have not found it, look into the project
731 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
735 In_Tree.Projects.Table
736 (The_Project).Decl.Variables;
739 In_Tree.Projects.Table
740 (The_Project).Decl.Attributes;
743 while The_Variable_Id /= No_Variable
745 In_Tree.Variable_Elements.Table
746 (The_Variable_Id).Name /= The_Name
749 In_Tree.Variable_Elements.Table
750 (The_Variable_Id).Next;
755 pragma Assert (The_Variable_Id /= No_Variable,
756 "variable or attribute not found");
759 In_Tree.Variable_Elements.Table
760 (The_Variable_Id).Value;
764 -- It is an associative array attribute
767 The_Array : Array_Id := No_Array;
768 The_Element : Array_Element_Id := No_Array_Element;
769 Array_Index : Name_Id := No_Name;
773 if The_Package /= No_Package then
775 In_Tree.Packages.Table
776 (The_Package).Decl.Arrays;
779 In_Tree.Projects.Table
780 (The_Project).Decl.Arrays;
783 while The_Array /= No_Array
784 and then In_Tree.Arrays.Table
785 (The_Array).Name /= The_Name
787 The_Array := In_Tree.Arrays.Table
791 if The_Array /= No_Array then
792 The_Element := In_Tree.Arrays.Table
795 Get_Name_String (Index);
799 (The_Current_Term, From_Project_Node_Tree);
801 -- In multi-language mode (gprbuild), the index is
802 -- always case insensitive if it does not include
805 if Get_Mode = Multi_Language and then not Lower then
808 for J in 1 .. Name_Len loop
809 if Name_Buffer (J) = '.' then
817 To_Lower (Name_Buffer (1 .. Name_Len));
820 Array_Index := Name_Find;
822 while The_Element /= No_Array_Element
824 In_Tree.Array_Elements.Table
825 (The_Element).Index /= Array_Index
828 In_Tree.Array_Elements.Table
834 if The_Element /= No_Array_Element then
836 In_Tree.Array_Elements.Table
840 if Expression_Kind_Of
841 (The_Current_Term, From_Project_Node_Tree) =
847 Location => No_Location,
849 Values => Nil_String);
854 Location => No_Location,
856 Value => Empty_String,
867 -- Should never happen
869 pragma Assert (False, "undefined expression kind");
874 case The_Variable.Kind is
880 Add (Result.Value, The_Variable.Value);
884 -- Should never happen
888 "list cannot appear in single " &
889 "string expression");
894 case The_Variable.Kind is
900 String_Element_Table.Increment_Last
901 (In_Tree.String_Elements);
903 if Last = Nil_String then
905 -- This can happen in an expression such as
909 String_Element_Table.Last
910 (In_Tree.String_Elements);
913 In_Tree.String_Elements.Table
915 String_Element_Table.Last
916 (In_Tree.String_Elements);
920 String_Element_Table.Last
921 (In_Tree.String_Elements);
923 In_Tree.String_Elements.Table (Last) :=
924 (Value => The_Variable.Value,
925 Display_Value => No_Name,
926 Location => Location_Of
928 From_Project_Node_Tree),
936 The_List : String_List_Id :=
940 while The_List /= Nil_String loop
941 String_Element_Table.Increment_Last
942 (In_Tree.String_Elements);
944 if Last = Nil_String then
946 String_Element_Table.Last
952 String_Elements.Table (Last).Next :=
953 String_Element_Table.Last
960 String_Element_Table.Last
961 (In_Tree.String_Elements);
963 In_Tree.String_Elements.Table (Last) :=
965 In_Tree.String_Elements.Table
967 Display_Value => No_Name,
971 From_Project_Node_Tree),
977 In_Tree. String_Elements.Table
985 when N_External_Value =>
988 (External_Reference_Of
989 (The_Current_Term, From_Project_Node_Tree),
990 From_Project_Node_Tree));
993 Name : constant Name_Id := Name_Find;
994 Default : Name_Id := No_Name;
995 Value : Name_Id := No_Name;
997 Def_Var : Variable_Value;
999 Default_Node : constant Project_Node_Id :=
1001 (The_Current_Term, From_Project_Node_Tree);
1004 -- If there is a default value for the external reference,
1007 if Default_Node /= Empty_Node then
1008 Def_Var := Expression
1009 (Project => Project,
1011 From_Project_Node => Default_Node,
1012 From_Project_Node_Tree => From_Project_Node_Tree,
1016 (Default_Node, From_Project_Node_Tree),
1019 if Def_Var /= Nil_Variable_Value then
1020 Default := Def_Var.Value;
1024 Value := Prj.Ext.Value_Of (Name, Default);
1026 if Value = No_Name then
1027 if not Quiet_Output then
1028 if Error_Report = null then
1030 ("?undefined external reference",
1032 (The_Current_Term, From_Project_Node_Tree));
1035 ("warning: """ & Get_Name_String (Name) &
1036 """ is an undefined external reference",
1041 Value := Empty_String;
1050 Add (Result.Value, Value);
1053 String_Element_Table.Increment_Last
1054 (In_Tree.String_Elements);
1056 if Last = Nil_String then
1057 Result.Values := String_Element_Table.Last
1058 (In_Tree.String_Elements);
1061 In_Tree.String_Elements.Table
1062 (Last).Next := String_Element_Table.Last
1063 (In_Tree.String_Elements);
1066 Last := String_Element_Table.Last
1067 (In_Tree.String_Elements);
1068 In_Tree.String_Elements.Table (Last) :=
1070 Display_Value => No_Name,
1073 (The_Current_Term, From_Project_Node_Tree),
1083 -- Should never happen
1087 "illegal node kind in an expression");
1088 raise Program_Error;
1092 The_Term := Next_Term (The_Term, From_Project_Node_Tree);
1098 ---------------------------------------
1099 -- Imported_Or_Extended_Project_From --
1100 ---------------------------------------
1102 function Imported_Or_Extended_Project_From
1103 (Project : Project_Id;
1104 In_Tree : Project_Tree_Ref;
1105 With_Name : Name_Id) return Project_Id
1107 Data : constant Project_Data :=
1108 In_Tree.Projects.Table (Project);
1109 List : Project_List := Data.Imported_Projects;
1110 Result : Project_Id := No_Project;
1111 Temp_Result : Project_Id := No_Project;
1114 -- First check if it is the name of an extended project
1116 if Data.Extends /= No_Project
1117 and then In_Tree.Projects.Table (Data.Extends).Name =
1120 return Data.Extends;
1123 -- Then check the name of each imported project
1125 while List /= Empty_Project_List loop
1126 Result := In_Tree.Project_Lists.Table (List).Project;
1128 -- If the project is directly imported, then returns its ID
1131 In_Tree.Projects.Table (Result).Name = With_Name
1136 -- If a project extending the project is imported, then keep
1137 -- this extending project as a possibility. It will be the
1138 -- returned ID if the project is not imported directly.
1141 Proj : Project_Id :=
1142 In_Tree.Projects.Table (Result).Extends;
1144 while Proj /= No_Project loop
1145 if In_Tree.Projects.Table (Proj).Name =
1148 Temp_Result := Result;
1152 Proj := In_Tree.Projects.Table (Proj).Extends;
1156 List := In_Tree.Project_Lists.Table (List).Next;
1160 (Temp_Result /= No_Project,
1161 "project not found");
1165 end Imported_Or_Extended_Project_From;
1171 function Package_From
1172 (Project : Project_Id;
1173 In_Tree : Project_Tree_Ref;
1174 With_Name : Name_Id) return Package_Id
1176 Data : constant Project_Data :=
1177 In_Tree.Projects.Table (Project);
1178 Result : Package_Id := Data.Decl.Packages;
1181 -- Check the name of each existing package of Project
1183 while Result /= No_Package
1184 and then In_Tree.Packages.Table (Result).Name /= With_Name
1186 Result := In_Tree.Packages.Table (Result).Next;
1189 if Result = No_Package then
1191 -- Should never happen
1193 Write_Line ("package """ & Get_Name_String (With_Name) &
1195 raise Program_Error;
1207 (In_Tree : Project_Tree_Ref;
1208 Project : out Project_Id;
1209 Success : out Boolean;
1210 From_Project_Node : Project_Node_Id;
1211 From_Project_Node_Tree : Project_Node_Tree_Ref;
1212 Report_Error : Put_Line_Access;
1213 When_No_Sources : Error_Warning := Error;
1214 Reset_Tree : Boolean := True;
1215 Current_Dir : String := "")
1218 Process_Project_Tree_Phase_1
1219 (In_Tree => In_Tree,
1222 From_Project_Node => From_Project_Node,
1223 From_Project_Node_Tree => From_Project_Node_Tree,
1224 Report_Error => Report_Error,
1225 Reset_Tree => Reset_Tree);
1227 if not In_Configuration then
1228 Process_Project_Tree_Phase_2
1229 (In_Tree => In_Tree,
1232 From_Project_Node => From_Project_Node,
1233 From_Project_Node_Tree => From_Project_Node_Tree,
1234 Report_Error => Report_Error,
1235 When_No_Sources => When_No_Sources,
1236 Current_Dir => Current_Dir);
1240 -------------------------------
1241 -- Process_Declarative_Items --
1242 -------------------------------
1244 procedure Process_Declarative_Items
1245 (Project : Project_Id;
1246 In_Tree : Project_Tree_Ref;
1247 From_Project_Node : Project_Node_Id;
1248 From_Project_Node_Tree : Project_Node_Tree_Ref;
1250 Item : Project_Node_Id)
1252 Current_Declarative_Item : Project_Node_Id;
1253 Current_Item : Project_Node_Id;
1256 -- Loop through declarative items
1258 Current_Item := Empty_Node;
1260 Current_Declarative_Item := Item;
1261 while Current_Declarative_Item /= Empty_Node loop
1267 (Current_Declarative_Item, From_Project_Node_Tree);
1269 -- And set Current_Declarative_Item to the next declarative item
1270 -- ready for the next iteration.
1272 Current_Declarative_Item :=
1273 Next_Declarative_Item
1274 (Current_Declarative_Item, From_Project_Node_Tree);
1276 case Kind_Of (Current_Item, From_Project_Node_Tree) is
1278 when N_Package_Declaration =>
1280 -- Do not process a package declaration that should be ignored
1282 if Expression_Kind_Of
1283 (Current_Item, From_Project_Node_Tree) /= Ignored
1285 -- Create the new package
1287 Package_Table.Increment_Last (In_Tree.Packages);
1290 New_Pkg : constant Package_Id :=
1291 Package_Table.Last (In_Tree.Packages);
1292 The_New_Package : Package_Element;
1294 Project_Of_Renamed_Package :
1295 constant Project_Node_Id :=
1296 Project_Of_Renamed_Package_Of
1297 (Current_Item, From_Project_Node_Tree);
1300 -- Set the name of the new package
1302 The_New_Package.Name :=
1303 Name_Of (Current_Item, From_Project_Node_Tree);
1305 -- Insert the new package in the appropriate list
1307 if Pkg /= No_Package then
1308 The_New_Package.Next :=
1309 In_Tree.Packages.Table (Pkg).Decl.Packages;
1310 In_Tree.Packages.Table (Pkg).Decl.Packages :=
1314 The_New_Package.Next :=
1315 In_Tree.Projects.Table (Project).Decl.Packages;
1316 In_Tree.Projects.Table (Project).Decl.Packages :=
1320 In_Tree.Packages.Table (New_Pkg) :=
1323 if Project_Of_Renamed_Package /= Empty_Node then
1328 Project_Name : constant Name_Id :=
1330 (Project_Of_Renamed_Package,
1331 From_Project_Node_Tree);
1334 constant Project_Id :=
1335 Imported_Or_Extended_Project_From
1336 (Project, In_Tree, Project_Name);
1338 Renamed_Package : constant Package_Id :=
1340 (Renamed_Project, In_Tree,
1343 From_Project_Node_Tree));
1346 -- For a renamed package, copy the declarations of
1347 -- the renamed package, but set all the locations
1348 -- to the location of the package name in the
1349 -- renaming declaration.
1351 Copy_Package_Declarations
1353 In_Tree.Packages.Table (Renamed_Package).Decl,
1355 In_Tree.Packages.Table (New_Pkg).Decl,
1358 (Current_Item, From_Project_Node_Tree),
1359 In_Tree => In_Tree);
1362 -- Standard package declaration, not renaming
1365 -- Set the default values of the attributes
1369 In_Tree.Projects.Table (Project).Name,
1371 In_Tree.Packages.Table (New_Pkg).Decl,
1374 (Current_Item, From_Project_Node_Tree)),
1375 Project_Level => False);
1377 -- And process declarative items of the new package
1379 Process_Declarative_Items
1380 (Project => Project,
1382 From_Project_Node => From_Project_Node,
1383 From_Project_Node_Tree => From_Project_Node_Tree,
1386 First_Declarative_Item_Of
1387 (Current_Item, From_Project_Node_Tree));
1392 when N_String_Type_Declaration =>
1394 -- There is nothing to process
1398 when N_Attribute_Declaration |
1399 N_Typed_Variable_Declaration |
1400 N_Variable_Declaration =>
1402 if Expression_Of (Current_Item, From_Project_Node_Tree) =
1406 -- It must be a full associative array attribute declaration
1409 Current_Item_Name : constant Name_Id :=
1412 From_Project_Node_Tree);
1413 -- The name of the attribute
1415 New_Array : Array_Id;
1416 -- The new associative array created
1418 Orig_Array : Array_Id;
1419 -- The associative array value
1421 Orig_Project_Name : Name_Id := No_Name;
1422 -- The name of the project where the associative array
1425 Orig_Project : Project_Id := No_Project;
1426 -- The id of the project where the associative array
1429 Orig_Package_Name : Name_Id := No_Name;
1430 -- The name of the package, if any, where the associative
1433 Orig_Package : Package_Id := No_Package;
1434 -- The id of the package, if any, where the associative
1437 New_Element : Array_Element_Id := No_Array_Element;
1438 -- Id of a new array element created
1440 Prev_Element : Array_Element_Id := No_Array_Element;
1441 -- Last new element id created
1443 Orig_Element : Array_Element_Id := No_Array_Element;
1444 -- Current array element in original associative array
1446 Next_Element : Array_Element_Id := No_Array_Element;
1447 -- Id of the array element that follows the new element.
1448 -- This is not always nil, because values for the
1449 -- associative array attribute may already have been
1450 -- declared, and the array elements declared are reused.
1453 -- First find if the associative array attribute already
1454 -- has elements declared.
1456 if Pkg /= No_Package then
1457 New_Array := In_Tree.Packages.Table
1461 New_Array := In_Tree.Projects.Table
1462 (Project).Decl.Arrays;
1465 while New_Array /= No_Array
1466 and then In_Tree.Arrays.Table (New_Array).Name /=
1469 New_Array := In_Tree.Arrays.Table (New_Array).Next;
1472 -- If the attribute has never been declared add new entry
1473 -- in the arrays of the project/package and link it.
1475 if New_Array = No_Array then
1476 Array_Table.Increment_Last (In_Tree.Arrays);
1477 New_Array := Array_Table.Last (In_Tree.Arrays);
1479 if Pkg /= No_Package then
1480 In_Tree.Arrays.Table (New_Array) :=
1481 (Name => Current_Item_Name,
1482 Value => No_Array_Element,
1484 In_Tree.Packages.Table (Pkg).Decl.Arrays);
1486 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1490 In_Tree.Arrays.Table (New_Array) :=
1491 (Name => Current_Item_Name,
1492 Value => No_Array_Element,
1494 In_Tree.Projects.Table (Project).Decl.Arrays);
1496 In_Tree.Projects.Table (Project).Decl.Arrays :=
1501 -- Find the project where the value is declared
1503 Orig_Project_Name :=
1505 (Associative_Project_Of
1506 (Current_Item, From_Project_Node_Tree),
1507 From_Project_Node_Tree);
1509 for Index in Project_Table.First ..
1513 if In_Tree.Projects.Table (Index).Name =
1516 Orig_Project := Index;
1521 pragma Assert (Orig_Project /= No_Project,
1522 "original project not found");
1524 if Associative_Package_Of
1525 (Current_Item, From_Project_Node_Tree) = Empty_Node
1528 In_Tree.Projects.Table
1529 (Orig_Project).Decl.Arrays;
1532 -- If in a package, find the package where the value
1535 Orig_Package_Name :=
1537 (Associative_Package_Of
1538 (Current_Item, From_Project_Node_Tree),
1539 From_Project_Node_Tree);
1542 In_Tree.Projects.Table
1543 (Orig_Project).Decl.Packages;
1544 pragma Assert (Orig_Package /= No_Package,
1545 "original package not found");
1547 while In_Tree.Packages.Table
1548 (Orig_Package).Name /= Orig_Package_Name
1550 Orig_Package := In_Tree.Packages.Table
1551 (Orig_Package).Next;
1552 pragma Assert (Orig_Package /= No_Package,
1553 "original package not found");
1557 In_Tree.Packages.Table
1558 (Orig_Package).Decl.Arrays;
1561 -- Now look for the array
1563 while Orig_Array /= No_Array
1564 and then In_Tree.Arrays.Table (Orig_Array).Name /=
1567 Orig_Array := In_Tree.Arrays.Table
1571 if Orig_Array = No_Array then
1572 if Error_Report = null then
1574 ("associative array value cannot be found",
1576 (Current_Item, From_Project_Node_Tree));
1579 ("associative array value cannot be found",
1585 In_Tree.Arrays.Table (Orig_Array).Value;
1587 -- Copy each array element
1589 while Orig_Element /= No_Array_Element loop
1591 -- Case of first element
1593 if Prev_Element = No_Array_Element then
1595 -- And there is no array element declared yet,
1596 -- create a new first array element.
1598 if In_Tree.Arrays.Table (New_Array).Value =
1601 Array_Element_Table.Increment_Last
1602 (In_Tree.Array_Elements);
1603 New_Element := Array_Element_Table.Last
1604 (In_Tree.Array_Elements);
1605 In_Tree.Arrays.Table
1606 (New_Array).Value := New_Element;
1607 Next_Element := No_Array_Element;
1609 -- Otherwise, the new element is the first
1612 New_Element := In_Tree.Arrays.
1613 Table (New_Array).Value;
1615 In_Tree.Array_Elements.Table
1619 -- Otherwise, reuse an existing element, or create
1620 -- one if necessary.
1624 In_Tree.Array_Elements.Table
1625 (Prev_Element).Next;
1627 if Next_Element = No_Array_Element then
1628 Array_Element_Table.Increment_Last
1629 (In_Tree.Array_Elements);
1630 New_Element := Array_Element_Table.Last
1631 (In_Tree.Array_Elements);
1634 New_Element := Next_Element;
1636 In_Tree.Array_Elements.Table
1641 -- Copy the value of the element
1643 In_Tree.Array_Elements.Table
1645 In_Tree.Array_Elements.Table
1647 In_Tree.Array_Elements.Table
1648 (New_Element).Value.Project := Project;
1650 -- Adjust the Next link
1652 In_Tree.Array_Elements.Table
1653 (New_Element).Next := Next_Element;
1655 -- Adjust the previous id for the next element
1657 Prev_Element := New_Element;
1659 -- Go to the next element in the original array
1662 In_Tree.Array_Elements.Table
1663 (Orig_Element).Next;
1666 -- Make sure that the array ends here, in case there
1667 -- previously a greater number of elements.
1669 In_Tree.Array_Elements.Table
1670 (New_Element).Next := No_Array_Element;
1674 -- Declarations other that full associative arrays
1678 New_Value : constant Variable_Value :=
1680 (Project => Project,
1682 From_Project_Node => From_Project_Node,
1683 From_Project_Node_Tree => From_Project_Node_Tree,
1688 (Current_Item, From_Project_Node_Tree),
1689 From_Project_Node_Tree),
1692 (Current_Item, From_Project_Node_Tree));
1693 -- The expression value
1695 The_Variable : Variable_Id := No_Variable;
1697 Current_Item_Name : constant Name_Id :=
1700 From_Project_Node_Tree);
1703 -- Process a typed variable declaration
1705 if Kind_Of (Current_Item, From_Project_Node_Tree) =
1706 N_Typed_Variable_Declaration
1708 -- Report an error for an empty string
1710 if New_Value.Value = Empty_String then
1712 Name_Of (Current_Item, From_Project_Node_Tree);
1714 if Error_Report = null then
1716 ("no value defined for %%",
1718 (Current_Item, From_Project_Node_Tree));
1721 ("no value defined for " &
1722 Get_Name_String (Error_Msg_Name_1),
1728 Current_String : Project_Node_Id;
1731 -- Loop through all the valid strings for the
1732 -- string type and compare to the string value.
1735 First_Literal_String
1736 (String_Type_Of (Current_Item,
1737 From_Project_Node_Tree),
1738 From_Project_Node_Tree);
1739 while Current_String /= Empty_Node
1742 (Current_String, From_Project_Node_Tree) /=
1747 (Current_String, From_Project_Node_Tree);
1750 -- Report an error if the string value is not
1751 -- one for the string type.
1753 if Current_String = Empty_Node then
1754 Error_Msg_Name_1 := New_Value.Value;
1757 (Current_Item, From_Project_Node_Tree);
1759 if Error_Report = null then
1761 ("value %% is illegal " &
1762 "for typed string %%",
1765 From_Project_Node_Tree));
1770 Get_Name_String (Error_Msg_Name_1) &
1771 """ is illegal for typed string """ &
1772 Get_Name_String (Error_Msg_Name_2) &
1783 if Kind_Of (Current_Item, From_Project_Node_Tree) /=
1784 N_Attribute_Declaration
1786 Associative_Array_Index_Of
1787 (Current_Item, From_Project_Node_Tree) = No_Name
1789 -- Case of a variable declaration or of a not
1790 -- associative array attribute.
1792 -- First, find the list where to find the variable
1795 if Kind_Of (Current_Item, From_Project_Node_Tree) =
1796 N_Attribute_Declaration
1798 if Pkg /= No_Package then
1800 In_Tree.Packages.Table
1801 (Pkg).Decl.Attributes;
1804 In_Tree.Projects.Table
1805 (Project).Decl.Attributes;
1809 if Pkg /= No_Package then
1811 In_Tree.Packages.Table
1812 (Pkg).Decl.Variables;
1815 In_Tree.Projects.Table
1816 (Project).Decl.Variables;
1821 -- Loop through the list, to find if it has already
1824 while The_Variable /= No_Variable
1826 In_Tree.Variable_Elements.Table
1827 (The_Variable).Name /= Current_Item_Name
1830 In_Tree.Variable_Elements.Table
1831 (The_Variable).Next;
1834 -- If it has not been declared, create a new entry
1837 if The_Variable = No_Variable then
1839 -- All single string attribute should already have
1840 -- been declared with a default empty string value.
1843 (Kind_Of (Current_Item, From_Project_Node_Tree) /=
1844 N_Attribute_Declaration,
1845 "illegal attribute declaration");
1847 Variable_Element_Table.Increment_Last
1848 (In_Tree.Variable_Elements);
1849 The_Variable := Variable_Element_Table.Last
1850 (In_Tree.Variable_Elements);
1852 -- Put the new variable in the appropriate list
1854 if Pkg /= No_Package then
1855 In_Tree.Variable_Elements.Table (The_Variable) :=
1857 In_Tree.Packages.Table
1858 (Pkg).Decl.Variables,
1859 Name => Current_Item_Name,
1860 Value => New_Value);
1861 In_Tree.Packages.Table
1862 (Pkg).Decl.Variables := The_Variable;
1865 In_Tree.Variable_Elements.Table (The_Variable) :=
1867 In_Tree.Projects.Table
1868 (Project).Decl.Variables,
1869 Name => Current_Item_Name,
1870 Value => New_Value);
1871 In_Tree.Projects.Table
1872 (Project).Decl.Variables :=
1876 -- If the variable/attribute has already been
1877 -- declared, just change the value.
1880 In_Tree.Variable_Elements.Table
1881 (The_Variable).Value :=
1886 -- Associative array attribute
1889 -- Get the string index
1892 (Associative_Array_Index_Of
1893 (Current_Item, From_Project_Node_Tree));
1895 -- Put in lower case, if necessary
1903 (Current_Item, From_Project_Node_Tree);
1905 -- In multi-language mode (gprbuild), the index is
1906 -- always case insensitive if it does not include
1909 if Get_Mode = Multi_Language and then not Lower then
1910 for J in 1 .. Name_Len loop
1911 if Name_Buffer (J) = '.' then
1919 GNAT.Case_Util.To_Lower
1920 (Name_Buffer (1 .. Name_Len));
1925 The_Array : Array_Id;
1927 The_Array_Element : Array_Element_Id :=
1930 Index_Name : constant Name_Id := Name_Find;
1931 -- The name id of the index
1934 -- Look for the array in the appropriate list
1936 if Pkg /= No_Package then
1938 In_Tree.Packages.Table (Pkg).Decl.Arrays;
1942 In_Tree.Projects.Table (Project).Decl.Arrays;
1946 The_Array /= No_Array
1948 In_Tree.Arrays.Table (The_Array).Name /=
1951 The_Array := In_Tree.Arrays.Table
1955 -- If the array cannot be found, create a new entry
1956 -- in the list. As The_Array_Element is initialized
1957 -- to No_Array_Element, a new element will be
1958 -- created automatically later
1960 if The_Array = No_Array then
1961 Array_Table.Increment_Last (In_Tree.Arrays);
1962 The_Array := Array_Table.Last (In_Tree.Arrays);
1964 if Pkg /= No_Package then
1965 In_Tree.Arrays.Table (The_Array) :=
1966 (Name => Current_Item_Name,
1967 Value => No_Array_Element,
1969 In_Tree.Packages.Table
1972 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1976 In_Tree.Arrays.Table (The_Array) :=
1977 (Name => Current_Item_Name,
1978 Value => No_Array_Element,
1980 In_Tree.Projects.Table
1981 (Project).Decl.Arrays);
1983 In_Tree.Projects.Table
1984 (Project).Decl.Arrays := The_Array;
1987 -- Otherwise initialize The_Array_Element as the
1988 -- head of the element list.
1991 The_Array_Element :=
1992 In_Tree.Arrays.Table (The_Array).Value;
1995 -- Look in the list, if any, to find an element
1996 -- with the same index.
1998 while The_Array_Element /= No_Array_Element
2000 In_Tree.Array_Elements.Table
2001 (The_Array_Element).Index /= Index_Name
2003 The_Array_Element :=
2004 In_Tree.Array_Elements.Table
2005 (The_Array_Element).Next;
2008 -- If no such element were found, create a new one
2009 -- and insert it in the element list, with the
2012 if The_Array_Element = No_Array_Element then
2013 Array_Element_Table.Increment_Last
2014 (In_Tree.Array_Elements);
2015 The_Array_Element := Array_Element_Table.Last
2016 (In_Tree.Array_Elements);
2018 In_Tree.Array_Elements.Table
2019 (The_Array_Element) :=
2020 (Index => Index_Name,
2023 (Current_Item, From_Project_Node_Tree),
2024 Index_Case_Sensitive =>
2025 not Case_Insensitive
2026 (Current_Item, From_Project_Node_Tree),
2028 Next => In_Tree.Arrays.Table
2030 In_Tree.Arrays.Table
2031 (The_Array).Value := The_Array_Element;
2033 -- An element with the same index already exists,
2034 -- just replace its value with the new one.
2037 In_Tree.Array_Elements.Table
2038 (The_Array_Element).Value := New_Value;
2045 when N_Case_Construction =>
2047 The_Project : Project_Id := Project;
2048 -- The id of the project of the case variable
2050 The_Package : Package_Id := Pkg;
2051 -- The id of the package, if any, of the case variable
2053 The_Variable : Variable_Value := Nil_Variable_Value;
2054 -- The case variable
2056 Case_Value : Name_Id := No_Name;
2057 -- The case variable value
2059 Case_Item : Project_Node_Id := Empty_Node;
2060 Choice_String : Project_Node_Id := Empty_Node;
2061 Decl_Item : Project_Node_Id := Empty_Node;
2065 Variable_Node : constant Project_Node_Id :=
2066 Case_Variable_Reference_Of
2068 From_Project_Node_Tree);
2070 Var_Id : Variable_Id := No_Variable;
2071 Name : Name_Id := No_Name;
2074 -- If a project was specified for the case variable,
2078 (Variable_Node, From_Project_Node_Tree) /= Empty_Node
2083 (Variable_Node, From_Project_Node_Tree),
2084 From_Project_Node_Tree);
2086 Imported_Or_Extended_Project_From
2087 (Project, In_Tree, Name);
2090 -- If a package were specified for the case variable,
2094 (Variable_Node, From_Project_Node_Tree) /= Empty_Node
2099 (Variable_Node, From_Project_Node_Tree),
2100 From_Project_Node_Tree);
2102 Package_From (The_Project, In_Tree, Name);
2105 Name := Name_Of (Variable_Node, From_Project_Node_Tree);
2107 -- First, look for the case variable into the package,
2110 if The_Package /= No_Package then
2111 Var_Id := In_Tree.Packages.Table
2112 (The_Package).Decl.Variables;
2114 Name_Of (Variable_Node, From_Project_Node_Tree);
2115 while Var_Id /= No_Variable
2117 In_Tree.Variable_Elements.Table
2118 (Var_Id).Name /= Name
2120 Var_Id := In_Tree.Variable_Elements.
2121 Table (Var_Id).Next;
2125 -- If not found in the package, or if there is no
2126 -- package, look at the project level.
2128 if Var_Id = No_Variable
2131 (Variable_Node, From_Project_Node_Tree) = Empty_Node
2133 Var_Id := In_Tree.Projects.Table
2134 (The_Project).Decl.Variables;
2135 while Var_Id /= No_Variable
2137 In_Tree.Variable_Elements.Table
2138 (Var_Id).Name /= Name
2140 Var_Id := In_Tree.Variable_Elements.
2141 Table (Var_Id).Next;
2145 if Var_Id = No_Variable then
2147 -- Should never happen, because this has already been
2148 -- checked during parsing.
2150 Write_Line ("variable """ &
2151 Get_Name_String (Name) &
2153 raise Program_Error;
2156 -- Get the case variable
2158 The_Variable := In_Tree.Variable_Elements.
2159 Table (Var_Id).Value;
2161 if The_Variable.Kind /= Single then
2163 -- Should never happen, because this has already been
2164 -- checked during parsing.
2166 Write_Line ("variable""" &
2167 Get_Name_String (Name) &
2168 """ is not a single string variable");
2169 raise Program_Error;
2172 -- Get the case variable value
2173 Case_Value := The_Variable.Value;
2176 -- Now look into all the case items of the case construction
2179 First_Case_Item_Of (Current_Item, From_Project_Node_Tree);
2181 while Case_Item /= Empty_Node loop
2183 First_Choice_Of (Case_Item, From_Project_Node_Tree);
2185 -- When Choice_String is nil, it means that it is
2186 -- the "when others =>" alternative.
2188 if Choice_String = Empty_Node then
2190 First_Declarative_Item_Of
2191 (Case_Item, From_Project_Node_Tree);
2192 exit Case_Item_Loop;
2195 -- Look into all the alternative of this case item
2198 while Choice_String /= Empty_Node loop
2201 (Choice_String, From_Project_Node_Tree)
2204 First_Declarative_Item_Of
2205 (Case_Item, From_Project_Node_Tree);
2206 exit Case_Item_Loop;
2211 (Choice_String, From_Project_Node_Tree);
2212 end loop Choice_Loop;
2215 Next_Case_Item (Case_Item, From_Project_Node_Tree);
2216 end loop Case_Item_Loop;
2218 -- If there is an alternative, then we process it
2220 if Decl_Item /= Empty_Node then
2221 Process_Declarative_Items
2222 (Project => Project,
2224 From_Project_Node => From_Project_Node,
2225 From_Project_Node_Tree => From_Project_Node_Tree,
2233 -- Should never happen
2235 Write_Line ("Illegal declarative item: " &
2236 Project_Node_Kind'Image
2238 (Current_Item, From_Project_Node_Tree)));
2239 raise Program_Error;
2242 end Process_Declarative_Items;
2244 ----------------------------------
2245 -- Process_Project_Tree_Phase_1 --
2246 ----------------------------------
2248 procedure Process_Project_Tree_Phase_1
2249 (In_Tree : Project_Tree_Ref;
2250 Project : out Project_Id;
2251 Success : out Boolean;
2252 From_Project_Node : Project_Node_Id;
2253 From_Project_Node_Tree : Project_Node_Tree_Ref;
2254 Report_Error : Put_Line_Access;
2255 Reset_Tree : Boolean := True)
2258 Error_Report := Report_Error;
2262 -- Make sure there are no projects in the data structure
2264 Project_Table.Set_Last (In_Tree.Projects, No_Project);
2267 Processed_Projects.Reset;
2269 -- And process the main project and all of the projects it depends on,
2273 (Project => Project,
2275 From_Project_Node => From_Project_Node,
2276 From_Project_Node_Tree => From_Project_Node_Tree,
2277 Extended_By => No_Project);
2280 Total_Errors_Detected = 0
2282 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2283 end Process_Project_Tree_Phase_1;
2285 ----------------------------------
2286 -- Process_Project_Tree_Phase_2 --
2287 ----------------------------------
2289 procedure Process_Project_Tree_Phase_2
2290 (In_Tree : Project_Tree_Ref;
2291 Project : Project_Id;
2292 Success : out Boolean;
2293 From_Project_Node : Project_Node_Id;
2294 From_Project_Node_Tree : Project_Node_Tree_Ref;
2295 Report_Error : Put_Line_Access;
2296 When_No_Sources : Error_Warning := Error;
2297 Current_Dir : String)
2299 Obj_Dir : Path_Name_Type;
2300 Extending : Project_Id;
2301 Extending2 : Project_Id;
2303 -- Start of processing for Process_Project_Tree_Phase_2
2306 Error_Report := Report_Error;
2309 if Project /= No_Project then
2310 Check (In_Tree, Project, Current_Dir, When_No_Sources);
2313 -- If main project is an extending all project, set the object
2314 -- directory of all virtual extending projects to the object
2315 -- directory of the main project.
2317 if Project /= No_Project
2319 Is_Extending_All (From_Project_Node, From_Project_Node_Tree)
2322 Object_Dir : constant Path_Name_Type :=
2323 In_Tree.Projects.Table
2324 (Project).Object_Directory;
2327 Project_Table.First .. Project_Table.Last (In_Tree.Projects)
2329 if In_Tree.Projects.Table (Index).Virtual then
2330 In_Tree.Projects.Table (Index).Object_Directory :=
2337 -- Check that no extending project shares its object directory with
2338 -- the project(s) it extends.
2340 if Project /= No_Project then
2342 Project_Table.First .. Project_Table.Last (In_Tree.Projects)
2344 Extending := In_Tree.Projects.Table (Proj).Extended_By;
2346 if Extending /= No_Project then
2347 Obj_Dir := In_Tree.Projects.Table (Proj).Object_Directory;
2349 -- Check that a project being extended does not share its
2350 -- object directory with any project that extends it, directly
2351 -- or indirectly, including a virtual extending project.
2353 -- Start with the project directly extending it
2355 Extending2 := Extending;
2356 while Extending2 /= No_Project loop
2357 if In_Tree.Projects.Table (Extending2).Ada_Sources /=
2360 In_Tree.Projects.Table (Extending2).Object_Directory =
2363 if In_Tree.Projects.Table (Extending2).Virtual then
2365 In_Tree.Projects.Table (Proj).Display_Name;
2367 if Error_Report = null then
2369 ("project %% cannot be extended by a virtual" &
2370 " project with the same object directory",
2371 In_Tree.Projects.Table (Proj).Location);
2375 Get_Name_String (Error_Msg_Name_1) &
2376 """ cannot be extended by a virtual " &
2377 "project with the same object directory",
2383 In_Tree.Projects.Table (Extending2).Display_Name;
2385 In_Tree.Projects.Table (Proj).Display_Name;
2387 if Error_Report = null then
2389 ("project %% cannot extend project %%",
2390 In_Tree.Projects.Table (Extending2).Location);
2392 ("\they share the same object directory",
2393 In_Tree.Projects.Table (Extending2).Location);
2398 Get_Name_String (Error_Msg_Name_1) &
2399 """ cannot extend project """ &
2400 Get_Name_String (Error_Msg_Name_2) & """",
2403 ("they share the same object directory",
2409 -- Continue with the next extending project, if any
2412 In_Tree.Projects.Table (Extending2).Extended_By;
2419 Total_Errors_Detected = 0
2421 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2422 end Process_Project_Tree_Phase_2;
2424 ---------------------
2425 -- Recursive_Check --
2426 ---------------------
2428 procedure Recursive_Check
2429 (Project : Project_Id;
2430 In_Tree : Project_Tree_Ref;
2431 Current_Dir : String;
2432 When_No_Sources : Error_Warning)
2434 Data : Project_Data;
2435 Imported_Project_List : Project_List := Empty_Project_List;
2438 -- Do nothing if Project is No_Project, or Project has already
2439 -- been marked as checked.
2441 if Project /= No_Project
2442 and then not In_Tree.Projects.Table (Project).Checked
2444 -- Mark project as checked, to avoid infinite recursion in
2445 -- ill-formed trees, where a project imports itself.
2447 In_Tree.Projects.Table (Project).Checked := True;
2449 Data := In_Tree.Projects.Table (Project);
2451 -- Call itself for a possible extended project.
2452 -- (if there is no extended project, then nothing happens).
2454 Recursive_Check (Data.Extends, In_Tree, Current_Dir, When_No_Sources);
2456 -- Call itself for all imported projects
2458 Imported_Project_List := Data.Imported_Projects;
2459 while Imported_Project_List /= Empty_Project_List loop
2461 (In_Tree.Project_Lists.Table
2462 (Imported_Project_List).Project,
2463 In_Tree, Current_Dir, When_No_Sources);
2464 Imported_Project_List :=
2465 In_Tree.Project_Lists.Table
2466 (Imported_Project_List).Next;
2469 if Verbose_Mode then
2470 Write_Str ("Checking project file """);
2471 Write_Str (Get_Name_String (Data.Name));
2476 (Project, In_Tree, Error_Report, When_No_Sources,
2479 end Recursive_Check;
2481 -----------------------
2482 -- Recursive_Process --
2483 -----------------------
2485 procedure Recursive_Process
2486 (In_Tree : Project_Tree_Ref;
2487 Project : out Project_Id;
2488 From_Project_Node : Project_Node_Id;
2489 From_Project_Node_Tree : Project_Node_Tree_Ref;
2490 Extended_By : Project_Id)
2492 With_Clause : Project_Node_Id;
2495 if From_Project_Node = Empty_Node then
2496 Project := No_Project;
2500 Processed_Data : Project_Data := Empty_Project (In_Tree);
2501 Imported : Project_List := Empty_Project_List;
2502 Declaration_Node : Project_Node_Id := Empty_Node;
2503 Tref : Source_Buffer_Ptr;
2504 Name : constant Name_Id :=
2506 (From_Project_Node, From_Project_Node_Tree);
2507 Location : Source_Ptr :=
2509 (From_Project_Node, From_Project_Node_Tree);
2512 Project := Processed_Projects.Get (Name);
2514 if Project /= No_Project then
2516 -- Make sure that, when a project is extended, the project id
2517 -- of the project extending it is recorded in its data, even
2518 -- when it has already been processed as an imported project.
2519 -- This is for virtually extended projects.
2521 if Extended_By /= No_Project then
2522 In_Tree.Projects.Table (Project).Extended_By := Extended_By;
2528 Project_Table.Increment_Last (In_Tree.Projects);
2529 Project := Project_Table.Last (In_Tree.Projects);
2530 Processed_Projects.Set (Name, Project);
2532 Processed_Data.Name := Name;
2534 Get_Name_String (Name);
2536 -- If name starts with the virtual prefix, flag the project as
2537 -- being a virtual extending project.
2539 if Name_Len > Virtual_Prefix'Length
2540 and then Name_Buffer (1 .. Virtual_Prefix'Length) =
2543 Processed_Data.Virtual := True;
2544 Processed_Data.Display_Name := Name;
2546 -- If there is no file, for example when the project node tree is
2547 -- built in memory by GPS, the Display_Name cannot be found in
2548 -- the source, so its value is the same as Name.
2550 elsif Location = No_Location then
2551 Processed_Data.Display_Name := Name;
2553 -- Get the spelling of the project name from the project file
2556 Tref := Source_Text (Get_Source_File_Index (Location));
2558 for J in 1 .. Name_Len loop
2559 Name_Buffer (J) := Tref (Location);
2560 Location := Location + 1;
2563 Processed_Data.Display_Name := Name_Find;
2566 Processed_Data.Display_Path_Name :=
2567 Path_Name_Of (From_Project_Node, From_Project_Node_Tree);
2568 Get_Name_String (Processed_Data.Display_Path_Name);
2569 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2570 Processed_Data.Path_Name := Name_Find;
2572 Processed_Data.Location :=
2573 Location_Of (From_Project_Node, From_Project_Node_Tree);
2575 Processed_Data.Display_Directory :=
2576 Directory_Of (From_Project_Node, From_Project_Node_Tree);
2577 Get_Name_String (Processed_Data.Display_Directory);
2578 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2579 Processed_Data.Directory := Name_Find;
2581 Processed_Data.Extended_By := Extended_By;
2587 Processed_Data.Decl,
2588 Prj.Attr.Attribute_First,
2589 Project_Level => True);
2592 First_With_Clause_Of (From_Project_Node, From_Project_Node_Tree);
2593 while With_Clause /= Empty_Node loop
2595 New_Project : Project_Id;
2596 New_Data : Project_Data;
2600 (In_Tree => In_Tree,
2601 Project => New_Project,
2602 From_Project_Node =>
2603 Project_Node_Of (With_Clause, From_Project_Node_Tree),
2604 From_Project_Node_Tree => From_Project_Node_Tree,
2605 Extended_By => No_Project);
2607 In_Tree.Projects.Table (New_Project);
2609 -- If we were the first project to import it,
2610 -- set First_Referred_By to us.
2612 if New_Data.First_Referred_By = No_Project then
2613 New_Data.First_Referred_By := Project;
2614 In_Tree.Projects.Table (New_Project) :=
2618 -- Add this project to our list of imported projects
2620 Project_List_Table.Increment_Last
2621 (In_Tree.Project_Lists);
2622 In_Tree.Project_Lists.Table
2623 (Project_List_Table.Last
2624 (In_Tree.Project_Lists)) :=
2625 (Project => New_Project, Next => Empty_Project_List);
2627 -- Imported is the id of the last imported project.
2628 -- If it is nil, then this imported project is our first.
2630 if Imported = Empty_Project_List then
2631 Processed_Data.Imported_Projects :=
2632 Project_List_Table.Last
2633 (In_Tree.Project_Lists);
2636 In_Tree.Project_Lists.Table
2637 (Imported).Next := Project_List_Table.Last
2638 (In_Tree.Project_Lists);
2641 Imported := Project_List_Table.Last
2642 (In_Tree.Project_Lists);
2645 Next_With_Clause_Of (With_Clause, From_Project_Node_Tree);
2650 Project_Declaration_Of
2651 (From_Project_Node, From_Project_Node_Tree);
2654 (In_Tree => In_Tree,
2655 Project => Processed_Data.Extends,
2656 From_Project_Node => Extended_Project_Of
2658 From_Project_Node_Tree),
2659 From_Project_Node_Tree => From_Project_Node_Tree,
2660 Extended_By => Project);
2662 In_Tree.Projects.Table (Project) := Processed_Data;
2664 Process_Declarative_Items
2665 (Project => Project,
2667 From_Project_Node => From_Project_Node,
2668 From_Project_Node_Tree => From_Project_Node_Tree,
2670 Item => First_Declarative_Item_Of
2672 From_Project_Node_Tree));
2674 -- If it is an extending project, inherit all packages
2675 -- from the extended project that are not explicitely defined
2676 -- or renamed. Also inherit the languages, if attribute Languages
2677 -- is not explicitely defined.
2679 if Processed_Data.Extends /= No_Project then
2680 Processed_Data := In_Tree.Projects.Table (Project);
2683 Extended_Pkg : Package_Id;
2684 Current_Pkg : Package_Id;
2685 Element : Package_Element;
2686 First : constant Package_Id :=
2687 Processed_Data.Decl.Packages;
2688 Attribute1 : Variable_Id;
2689 Attribute2 : Variable_Id;
2690 Attr_Value1 : Variable;
2691 Attr_Value2 : Variable;
2695 In_Tree.Projects.Table
2696 (Processed_Data.Extends).Decl.Packages;
2697 while Extended_Pkg /= No_Package loop
2699 In_Tree.Packages.Table (Extended_Pkg);
2701 Current_Pkg := First;
2702 while Current_Pkg /= No_Package
2703 and then In_Tree.Packages.Table (Current_Pkg).Name /=
2707 In_Tree.Packages.Table (Current_Pkg).Next;
2710 if Current_Pkg = No_Package then
2711 Package_Table.Increment_Last
2713 Current_Pkg := Package_Table.Last (In_Tree.Packages);
2714 In_Tree.Packages.Table (Current_Pkg) :=
2715 (Name => Element.Name,
2716 Decl => No_Declarations,
2717 Parent => No_Package,
2718 Next => Processed_Data.Decl.Packages);
2719 Processed_Data.Decl.Packages := Current_Pkg;
2720 Copy_Package_Declarations
2721 (From => Element.Decl,
2722 To => In_Tree.Packages.Table (Current_Pkg).Decl,
2723 New_Loc => No_Location,
2724 In_Tree => In_Tree);
2727 Extended_Pkg := Element.Next;
2730 -- Check if attribute Languages is declared in the
2731 -- extending project.
2733 Attribute1 := Processed_Data.Decl.Attributes;
2734 while Attribute1 /= No_Variable loop
2735 Attr_Value1 := In_Tree.Variable_Elements.
2737 exit when Attr_Value1.Name = Snames.Name_Languages;
2738 Attribute1 := Attr_Value1.Next;
2741 if Attribute1 = No_Variable or else
2742 Attr_Value1.Value.Default
2744 -- Attribute Languages is not declared in the extending
2745 -- project. Check if it is declared in the project being
2749 In_Tree.Projects.Table
2750 (Processed_Data.Extends).Decl.Attributes;
2751 while Attribute2 /= No_Variable loop
2752 Attr_Value2 := In_Tree.Variable_Elements.
2754 exit when Attr_Value2.Name = Snames.Name_Languages;
2755 Attribute2 := Attr_Value2.Next;
2758 if Attribute2 /= No_Variable and then
2759 not Attr_Value2.Value.Default
2761 -- As attribute Languages is declared in the project
2762 -- being extended, copy its value for the extending
2765 if Attribute1 = No_Variable then
2766 Variable_Element_Table.Increment_Last
2767 (In_Tree.Variable_Elements);
2768 Attribute1 := Variable_Element_Table.Last
2769 (In_Tree.Variable_Elements);
2770 Attr_Value1.Next := Processed_Data.Decl.Attributes;
2771 Processed_Data.Decl.Attributes := Attribute1;
2774 Attr_Value1.Name := Snames.Name_Languages;
2775 Attr_Value1.Value := Attr_Value2.Value;
2776 In_Tree.Variable_Elements.Table
2777 (Attribute1) := Attr_Value1;
2782 In_Tree.Projects.Table (Project) := Processed_Data;
2786 end Recursive_Process;