1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2008, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, 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 COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Err_Vars; use Err_Vars;
28 with Osint; use Osint;
29 with Output; use Output;
30 with Prj.Attr; use Prj.Attr;
31 with Prj.Err; use Prj.Err;
32 with Prj.Ext; use Prj.Ext;
33 with Prj.Nmsc; use Prj.Nmsc;
34 with Sinput; use Sinput;
37 with GNAT.Case_Util; use GNAT.Case_Util;
40 package body Prj.Proc is
42 Error_Report : Put_Line_Access := null;
44 package Processed_Projects is new GNAT.HTable.Simple_HTable
45 (Header_Num => Header_Num,
46 Element => Project_Id,
47 No_Element => No_Project,
51 -- This hash table contains all processed projects
53 package Unit_Htable is new GNAT.HTable.Simple_HTable
54 (Header_Num => Header_Num,
56 No_Element => No_Source,
60 -- This hash table contains all processed projects
62 procedure Add (To_Exp : in out Name_Id; Str : Name_Id);
63 -- Concatenate two strings and returns another string if both
64 -- arguments are not null string.
66 procedure Add_Attributes
67 (Project : Project_Id;
68 Project_Name : Name_Id;
69 In_Tree : Project_Tree_Ref;
70 Decl : in out Declarations;
71 First : Attribute_Node_Id;
72 Project_Level : Boolean);
73 -- Add all attributes, starting with First, with their default
74 -- values to the package or project with declarations Decl.
77 (In_Tree : Project_Tree_Ref;
80 When_No_Sources : Error_Warning);
81 -- Set all projects to not checked, then call Recursive_Check for the
82 -- main project Project. Project is set to No_Project if errors occurred.
83 -- Current_Dir is for optimization purposes, avoiding extra system calls.
85 procedure Copy_Package_Declarations
87 To : in out Declarations;
89 Naming_Restricted : Boolean;
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. When Naming_Restricted is
93 -- True, do not copy attributes Body, Spec, Implementation and
97 (Project : Project_Id;
98 In_Tree : Project_Tree_Ref;
99 From_Project_Node : Project_Node_Id;
100 From_Project_Node_Tree : Project_Node_Tree_Ref;
102 First_Term : Project_Node_Id;
103 Kind : Variable_Kind) return Variable_Value;
104 -- From N_Expression project node From_Project_Node, compute the value
105 -- of an expression and return it as a Variable_Value.
107 function Imported_Or_Extended_Project_From
108 (Project : Project_Id;
109 In_Tree : Project_Tree_Ref;
110 With_Name : Name_Id) return Project_Id;
111 -- Find an imported or extended project of Project whose name is With_Name
113 function Package_From
114 (Project : Project_Id;
115 In_Tree : Project_Tree_Ref;
116 With_Name : Name_Id) return Package_Id;
117 -- Find the package of Project whose name is With_Name
119 procedure Process_Declarative_Items
120 (Project : Project_Id;
121 In_Tree : Project_Tree_Ref;
122 From_Project_Node : Project_Node_Id;
123 From_Project_Node_Tree : Project_Node_Tree_Ref;
125 Item : Project_Node_Id);
126 -- Process declarative items starting with From_Project_Node, and put them
127 -- in declarations Decl. This is a recursive procedure; it calls itself for
128 -- a package declaration or a case construction.
130 procedure Recursive_Process
131 (In_Tree : Project_Tree_Ref;
132 Project : out Project_Id;
133 From_Project_Node : Project_Node_Id;
134 From_Project_Node_Tree : Project_Node_Tree_Ref;
135 Extended_By : Project_Id);
136 -- Process project with node From_Project_Node in the tree.
137 -- Do nothing if From_Project_Node is Empty_Node.
138 -- If project has already been processed, simply return its project id.
139 -- Otherwise create a new project id, mark it as processed, call itself
140 -- recursively for all imported projects and a extended project, if any.
141 -- Then process the declarative items of the project.
143 procedure Recursive_Check
144 (Project : Project_Id;
145 In_Tree : Project_Tree_Ref;
146 Current_Dir : String;
147 When_No_Sources : Error_Warning);
148 -- If Project is not marked as checked, mark it as checked, call
149 -- Check_Naming_Scheme for the project, then call itself for a
150 -- possible extended project and all the imported projects of Project.
151 -- Current_Dir is for optimization purposes, avoiding extra system calls.
157 procedure Add (To_Exp : in out Name_Id; Str : Name_Id) is
159 if To_Exp = No_Name or else To_Exp = Empty_String then
161 -- To_Exp is nil or empty. The result is Str
165 -- If Str is nil, then do not change To_Ext
167 elsif Str /= No_Name and then Str /= Empty_String then
169 S : constant String := Get_Name_String (Str);
172 Get_Name_String (To_Exp);
173 Add_Str_To_Name_Buffer (S);
183 procedure Add_Attributes
184 (Project : Project_Id;
185 Project_Name : Name_Id;
186 In_Tree : Project_Tree_Ref;
187 Decl : in out Declarations;
188 First : Attribute_Node_Id;
189 Project_Level : Boolean)
191 The_Attribute : Attribute_Node_Id := First;
194 while The_Attribute /= Empty_Attribute loop
195 if Attribute_Kind_Of (The_Attribute) = Single then
197 New_Attribute : Variable_Value;
200 case Variable_Kind_Of (The_Attribute) is
202 -- Undefined should not happen
206 (False, "attribute with an undefined kind");
209 -- Single attributes have a default value of empty string
215 Location => No_Location,
217 Value => Empty_String,
220 -- Special case of <project>'Name
223 and then Attribute_Name_Of (The_Attribute) =
226 New_Attribute.Value := Project_Name;
229 -- List attributes have a default value of nil list
235 Location => No_Location,
237 Values => Nil_String);
241 Variable_Element_Table.Increment_Last
242 (In_Tree.Variable_Elements);
243 In_Tree.Variable_Elements.Table
244 (Variable_Element_Table.Last
245 (In_Tree.Variable_Elements)) :=
246 (Next => Decl.Attributes,
247 Name => Attribute_Name_Of (The_Attribute),
248 Value => New_Attribute);
249 Decl.Attributes := Variable_Element_Table.Last
250 (In_Tree.Variable_Elements);
254 The_Attribute := Next_Attribute (After => The_Attribute);
263 (In_Tree : Project_Tree_Ref;
264 Project : Project_Id;
265 Current_Dir : String;
266 When_No_Sources : Error_Warning)
269 -- Make sure that all projects are marked as not checked
271 for Index in Project_Table.First ..
272 Project_Table.Last (In_Tree.Projects)
274 In_Tree.Projects.Table (Index).Checked := False;
277 Recursive_Check (Project, In_Tree, Current_Dir, When_No_Sources);
279 -- Set the Other_Part field for the units
289 Source1 := In_Tree.First_Source;
290 while Source1 /= No_Source loop
291 Name := In_Tree.Sources.Table (Source1).Unit;
293 if Name /= No_Name then
294 Source2 := Unit_Htable.Get (Name);
296 if Source2 = No_Source then
297 Unit_Htable.Set (K => Name, E => Source1);
300 Unit_Htable.Remove (Name);
301 In_Tree.Sources.Table (Source1).Other_Part := Source2;
302 In_Tree.Sources.Table (Source2).Other_Part := Source1;
306 Source1 := In_Tree.Sources.Table (Source1).Next_In_Sources;
311 -------------------------------
312 -- Copy_Package_Declarations --
313 -------------------------------
315 procedure Copy_Package_Declarations
316 (From : Declarations;
317 To : in out Declarations;
318 New_Loc : Source_Ptr;
319 Naming_Restricted : Boolean;
320 In_Tree : Project_Tree_Ref)
322 V1 : Variable_Id := From.Attributes;
323 V2 : Variable_Id := No_Variable;
325 A1 : Array_Id := From.Arrays;
326 A2 : Array_Id := No_Array;
328 E1 : Array_Element_Id;
329 E2 : Array_Element_Id := No_Array_Element;
333 -- To avoid references in error messages to attribute declarations in
334 -- an original package that has been renamed, copy all the attribute
335 -- declarations of the package and change all locations to New_Loc,
336 -- the location of the renamed package.
338 -- First single attributes
340 while V1 /= No_Variable loop
342 -- Copy the attribute
344 Var := In_Tree.Variable_Elements.Table (V1);
347 -- Remove the Next component
349 Var.Next := No_Variable;
351 -- Change the location to New_Loc
353 Var.Value.Location := New_Loc;
354 Variable_Element_Table.Increment_Last (In_Tree.Variable_Elements);
356 -- Put in new declaration
358 if To.Attributes = No_Variable then
360 Variable_Element_Table.Last (In_Tree.Variable_Elements);
363 In_Tree.Variable_Elements.Table (V2).Next :=
364 Variable_Element_Table.Last (In_Tree.Variable_Elements);
367 V2 := Variable_Element_Table.Last (In_Tree.Variable_Elements);
368 In_Tree.Variable_Elements.Table (V2) := Var;
371 -- Then the associated array attributes
373 while A1 /= No_Array loop
375 Arr := In_Tree.Arrays.Table (A1);
378 if not Naming_Restricted or else
379 (Arr.Name /= Snames.Name_Body
380 and then Arr.Name /= Snames.Name_Spec
381 and then Arr.Name /= Snames.Name_Implementation
382 and then Arr.Name /= Snames.Name_Specification)
384 -- Remove the Next component
386 Arr.Next := No_Array;
388 Array_Table.Increment_Last (In_Tree.Arrays);
390 -- Create new Array declaration
392 if To.Arrays = No_Array then
393 To.Arrays := Array_Table.Last (In_Tree.Arrays);
396 In_Tree.Arrays.Table (A2).Next :=
397 Array_Table.Last (In_Tree.Arrays);
400 A2 := Array_Table.Last (In_Tree.Arrays);
402 -- Don't store the array as its first element has not been set yet
404 -- Copy the array elements of the array
407 Arr.Value := No_Array_Element;
408 while E1 /= No_Array_Element loop
410 -- Copy the array element
412 Elm := In_Tree.Array_Elements.Table (E1);
415 -- Remove the Next component
417 Elm.Next := No_Array_Element;
419 -- Change the location
421 Elm.Value.Location := New_Loc;
422 Array_Element_Table.Increment_Last (In_Tree.Array_Elements);
424 -- Create new array element
426 if Arr.Value = No_Array_Element then
428 Array_Element_Table.Last (In_Tree.Array_Elements);
430 In_Tree.Array_Elements.Table (E2).Next :=
431 Array_Element_Table.Last (In_Tree.Array_Elements);
434 E2 := Array_Element_Table.Last (In_Tree.Array_Elements);
435 In_Tree.Array_Elements.Table (E2) := Elm;
438 -- Finally, store the new array
440 In_Tree.Arrays.Table (A2) := Arr;
443 end Copy_Package_Declarations;
450 (Project : Project_Id;
451 In_Tree : Project_Tree_Ref;
452 From_Project_Node : Project_Node_Id;
453 From_Project_Node_Tree : Project_Node_Tree_Ref;
455 First_Term : Project_Node_Id;
456 Kind : Variable_Kind) return Variable_Value
458 The_Term : Project_Node_Id := First_Term;
459 -- The term in the expression list
461 The_Current_Term : Project_Node_Id := Empty_Node;
462 -- The current term node id
464 Result : Variable_Value (Kind => Kind);
465 -- The returned result
467 Last : String_List_Id := Nil_String;
468 -- Reference to the last string elements in Result, when Kind is List
471 Result.Project := Project;
472 Result.Location := Location_Of (First_Term, From_Project_Node_Tree);
474 -- Process each term of the expression, starting with First_Term
476 while Present (The_Term) loop
477 The_Current_Term := Current_Term (The_Term, From_Project_Node_Tree);
479 case Kind_Of (The_Current_Term, From_Project_Node_Tree) is
481 when N_Literal_String =>
487 -- Should never happen
489 pragma Assert (False, "Undefined expression kind");
495 (The_Current_Term, From_Project_Node_Tree));
498 (The_Current_Term, From_Project_Node_Tree);
502 String_Element_Table.Increment_Last
503 (In_Tree.String_Elements);
505 if Last = Nil_String then
507 -- This can happen in an expression like () & "toto"
509 Result.Values := String_Element_Table.Last
510 (In_Tree.String_Elements);
513 In_Tree.String_Elements.Table
514 (Last).Next := String_Element_Table.Last
515 (In_Tree.String_Elements);
518 Last := String_Element_Table.Last
519 (In_Tree.String_Elements);
520 In_Tree.String_Elements.Table (Last) :=
524 From_Project_Node_Tree),
527 (The_Current_Term, From_Project_Node_Tree),
528 Display_Value => No_Name,
532 From_Project_Node_Tree),
537 when N_Literal_String_List =>
540 String_Node : Project_Node_Id :=
541 First_Expression_In_List
543 From_Project_Node_Tree);
545 Value : Variable_Value;
548 if Present (String_Node) then
550 -- If String_Node is nil, it is an empty list,
551 -- there is nothing to do
556 From_Project_Node => From_Project_Node,
557 From_Project_Node_Tree => From_Project_Node_Tree,
561 (String_Node, From_Project_Node_Tree),
563 String_Element_Table.Increment_Last
564 (In_Tree.String_Elements);
566 if Result.Values = Nil_String then
568 -- This literal string list is the first term
569 -- in a string list expression
572 String_Element_Table.Last (In_Tree.String_Elements);
575 In_Tree.String_Elements.Table
577 String_Element_Table.Last (In_Tree.String_Elements);
581 String_Element_Table.Last (In_Tree.String_Elements);
583 In_Tree.String_Elements.Table (Last) :=
584 (Value => Value.Value,
585 Display_Value => No_Name,
586 Location => Value.Location,
589 Index => Value.Index);
592 -- Add the other element of the literal string list
593 -- one after the other
596 Next_Expression_In_List
597 (String_Node, From_Project_Node_Tree);
599 exit when No (String_Node);
605 From_Project_Node => From_Project_Node,
606 From_Project_Node_Tree => From_Project_Node_Tree,
610 (String_Node, From_Project_Node_Tree),
613 String_Element_Table.Increment_Last
614 (In_Tree.String_Elements);
615 In_Tree.String_Elements.Table
616 (Last).Next := String_Element_Table.Last
617 (In_Tree.String_Elements);
618 Last := String_Element_Table.Last
619 (In_Tree.String_Elements);
620 In_Tree.String_Elements.Table (Last) :=
621 (Value => Value.Value,
622 Display_Value => No_Name,
623 Location => Value.Location,
626 Index => Value.Index);
631 when N_Variable_Reference | N_Attribute_Reference =>
634 The_Project : Project_Id := Project;
635 The_Package : Package_Id := Pkg;
636 The_Name : Name_Id := No_Name;
637 The_Variable_Id : Variable_Id := No_Variable;
638 The_Variable : Variable_Value;
639 Term_Project : constant Project_Node_Id :=
642 From_Project_Node_Tree);
643 Term_Package : constant Project_Node_Id :=
646 From_Project_Node_Tree);
647 Index : Name_Id := No_Name;
650 if Present (Term_Project) and then
651 Term_Project /= From_Project_Node
653 -- This variable or attribute comes from another project
656 Name_Of (Term_Project, From_Project_Node_Tree);
657 The_Project := Imported_Or_Extended_Project_From
660 With_Name => The_Name);
663 if Present (Term_Package) then
665 -- This is an attribute of a package
668 Name_Of (Term_Package, From_Project_Node_Tree);
669 The_Package := In_Tree.Projects.Table
670 (The_Project).Decl.Packages;
672 while The_Package /= No_Package
673 and then In_Tree.Packages.Table
674 (The_Package).Name /= The_Name
677 In_Tree.Packages.Table
682 (The_Package /= No_Package,
683 "package not found.");
685 elsif Kind_Of (The_Current_Term, From_Project_Node_Tree) =
686 N_Attribute_Reference
688 The_Package := No_Package;
692 Name_Of (The_Current_Term, From_Project_Node_Tree);
694 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
695 N_Attribute_Reference
698 Associative_Array_Index_Of
699 (The_Current_Term, From_Project_Node_Tree);
702 -- If it is not an associative array attribute
704 if Index = No_Name then
706 -- It is not an associative array attribute
708 if The_Package /= No_Package then
710 -- First, if there is a package, look into the package
712 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
716 In_Tree.Packages.Table
717 (The_Package).Decl.Variables;
720 In_Tree.Packages.Table
721 (The_Package).Decl.Attributes;
724 while The_Variable_Id /= No_Variable
726 In_Tree.Variable_Elements.Table
727 (The_Variable_Id).Name /= The_Name
730 In_Tree.Variable_Elements.Table
731 (The_Variable_Id).Next;
736 if The_Variable_Id = No_Variable then
738 -- If we have not found it, look into the project
740 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
744 In_Tree.Projects.Table
745 (The_Project).Decl.Variables;
748 In_Tree.Projects.Table
749 (The_Project).Decl.Attributes;
752 while The_Variable_Id /= No_Variable
754 In_Tree.Variable_Elements.Table
755 (The_Variable_Id).Name /= The_Name
758 In_Tree.Variable_Elements.Table
759 (The_Variable_Id).Next;
764 pragma Assert (The_Variable_Id /= No_Variable,
765 "variable or attribute not found");
768 In_Tree.Variable_Elements.Table
769 (The_Variable_Id).Value;
773 -- It is an associative array attribute
776 The_Array : Array_Id := No_Array;
777 The_Element : Array_Element_Id := No_Array_Element;
778 Array_Index : Name_Id := No_Name;
782 if The_Package /= No_Package then
784 In_Tree.Packages.Table
785 (The_Package).Decl.Arrays;
788 In_Tree.Projects.Table
789 (The_Project).Decl.Arrays;
792 while The_Array /= No_Array
793 and then In_Tree.Arrays.Table
794 (The_Array).Name /= The_Name
796 The_Array := In_Tree.Arrays.Table
800 if The_Array /= No_Array then
801 The_Element := In_Tree.Arrays.Table
804 Get_Name_String (Index);
808 (The_Current_Term, From_Project_Node_Tree);
810 -- In multi-language mode (gprbuild), the index is
811 -- always case insensitive if it does not include
814 if Get_Mode = Multi_Language and then not Lower then
817 for J in 1 .. Name_Len loop
818 if Name_Buffer (J) = '.' then
826 To_Lower (Name_Buffer (1 .. Name_Len));
829 Array_Index := Name_Find;
831 while The_Element /= No_Array_Element
833 In_Tree.Array_Elements.Table
834 (The_Element).Index /= Array_Index
837 In_Tree.Array_Elements.Table
843 if The_Element /= No_Array_Element then
845 In_Tree.Array_Elements.Table
849 if Expression_Kind_Of
850 (The_Current_Term, From_Project_Node_Tree) =
856 Location => No_Location,
858 Values => Nil_String);
863 Location => No_Location,
865 Value => Empty_String,
876 -- Should never happen
878 pragma Assert (False, "undefined expression kind");
883 case The_Variable.Kind is
889 Add (Result.Value, The_Variable.Value);
893 -- Should never happen
897 "list cannot appear in single " &
898 "string expression");
903 case The_Variable.Kind is
909 String_Element_Table.Increment_Last
910 (In_Tree.String_Elements);
912 if Last = Nil_String then
914 -- This can happen in an expression such as
918 String_Element_Table.Last
919 (In_Tree.String_Elements);
922 In_Tree.String_Elements.Table
924 String_Element_Table.Last
925 (In_Tree.String_Elements);
929 String_Element_Table.Last
930 (In_Tree.String_Elements);
932 In_Tree.String_Elements.Table (Last) :=
933 (Value => The_Variable.Value,
934 Display_Value => No_Name,
935 Location => Location_Of
937 From_Project_Node_Tree),
945 The_List : String_List_Id :=
949 while The_List /= Nil_String loop
950 String_Element_Table.Increment_Last
951 (In_Tree.String_Elements);
953 if Last = Nil_String then
955 String_Element_Table.Last
961 String_Elements.Table (Last).Next :=
962 String_Element_Table.Last
969 String_Element_Table.Last
970 (In_Tree.String_Elements);
972 In_Tree.String_Elements.Table (Last) :=
974 In_Tree.String_Elements.Table
976 Display_Value => No_Name,
980 From_Project_Node_Tree),
986 In_Tree. String_Elements.Table
994 when N_External_Value =>
997 (External_Reference_Of
998 (The_Current_Term, From_Project_Node_Tree),
999 From_Project_Node_Tree));
1002 Name : constant Name_Id := Name_Find;
1003 Default : Name_Id := No_Name;
1004 Value : Name_Id := No_Name;
1006 Def_Var : Variable_Value;
1008 Default_Node : constant Project_Node_Id :=
1010 (The_Current_Term, From_Project_Node_Tree);
1013 -- If there is a default value for the external reference,
1016 if Present (Default_Node) then
1017 Def_Var := Expression
1018 (Project => Project,
1020 From_Project_Node => From_Project_Node,
1021 From_Project_Node_Tree => From_Project_Node_Tree,
1025 (Default_Node, From_Project_Node_Tree),
1028 if Def_Var /= Nil_Variable_Value then
1029 Default := Def_Var.Value;
1033 Value := Prj.Ext.Value_Of (Name, Default);
1035 if Value = No_Name then
1036 if not Quiet_Output then
1037 if Error_Report = null then
1039 ("?undefined external reference",
1041 (The_Current_Term, From_Project_Node_Tree));
1044 ("warning: """ & Get_Name_String (Name) &
1045 """ is an undefined external reference",
1050 Value := Empty_String;
1059 Add (Result.Value, Value);
1062 String_Element_Table.Increment_Last
1063 (In_Tree.String_Elements);
1065 if Last = Nil_String then
1066 Result.Values := String_Element_Table.Last
1067 (In_Tree.String_Elements);
1070 In_Tree.String_Elements.Table
1071 (Last).Next := String_Element_Table.Last
1072 (In_Tree.String_Elements);
1075 Last := String_Element_Table.Last
1076 (In_Tree.String_Elements);
1077 In_Tree.String_Elements.Table (Last) :=
1079 Display_Value => No_Name,
1082 (The_Current_Term, From_Project_Node_Tree),
1092 -- Should never happen
1096 "illegal node kind in an expression");
1097 raise Program_Error;
1101 The_Term := Next_Term (The_Term, From_Project_Node_Tree);
1107 ---------------------------------------
1108 -- Imported_Or_Extended_Project_From --
1109 ---------------------------------------
1111 function Imported_Or_Extended_Project_From
1112 (Project : Project_Id;
1113 In_Tree : Project_Tree_Ref;
1114 With_Name : Name_Id) return Project_Id
1116 Data : constant Project_Data := In_Tree.Projects.Table (Project);
1117 List : Project_List;
1118 Result : Project_Id;
1119 Temp_Result : Project_Id;
1122 -- First check if it is the name of an extended project
1124 Result := Data.Extends;
1125 while Result /= No_Project loop
1126 if In_Tree.Projects.Table (Result).Name = With_Name then
1129 Result := In_Tree.Projects.Table (Result).Extends;
1133 -- Then check the name of each imported project
1135 Temp_Result := No_Project;
1136 List := Data.Imported_Projects;
1137 while List /= Empty_Project_List loop
1138 Result := In_Tree.Project_Lists.Table (List).Project;
1140 -- If the project is directly imported, then returns its ID
1142 if In_Tree.Projects.Table (Result).Name = With_Name then
1146 -- If a project extending the project is imported, then keep this
1147 -- extending project as a possibility. It will be the returned ID
1148 -- if the project is not imported directly.
1151 Proj : Project_Id := In_Tree.Projects.Table (Result).Extends;
1154 while Proj /= No_Project loop
1155 if In_Tree.Projects.Table (Proj).Name = With_Name then
1156 Temp_Result := Result;
1160 Proj := In_Tree.Projects.Table (Proj).Extends;
1164 List := In_Tree.Project_Lists.Table (List).Next;
1167 pragma Assert (Temp_Result /= No_Project, "project not found");
1169 end Imported_Or_Extended_Project_From;
1175 function Package_From
1176 (Project : Project_Id;
1177 In_Tree : Project_Tree_Ref;
1178 With_Name : Name_Id) return Package_Id
1180 Data : constant Project_Data :=
1181 In_Tree.Projects.Table (Project);
1182 Result : Package_Id := Data.Decl.Packages;
1185 -- Check the name of each existing package of Project
1187 while Result /= No_Package
1188 and then In_Tree.Packages.Table (Result).Name /= With_Name
1190 Result := In_Tree.Packages.Table (Result).Next;
1193 if Result = No_Package then
1195 -- Should never happen
1197 Write_Line ("package """ & Get_Name_String (With_Name) &
1199 raise Program_Error;
1211 (In_Tree : Project_Tree_Ref;
1212 Project : out Project_Id;
1213 Success : out Boolean;
1214 From_Project_Node : Project_Node_Id;
1215 From_Project_Node_Tree : Project_Node_Tree_Ref;
1216 Report_Error : Put_Line_Access;
1217 When_No_Sources : Error_Warning := Error;
1218 Reset_Tree : Boolean := True;
1219 Current_Dir : String := "")
1222 Process_Project_Tree_Phase_1
1223 (In_Tree => In_Tree,
1226 From_Project_Node => From_Project_Node,
1227 From_Project_Node_Tree => From_Project_Node_Tree,
1228 Report_Error => Report_Error,
1229 Reset_Tree => Reset_Tree);
1231 if not In_Configuration then
1232 Process_Project_Tree_Phase_2
1233 (In_Tree => In_Tree,
1236 From_Project_Node => From_Project_Node,
1237 From_Project_Node_Tree => From_Project_Node_Tree,
1238 Report_Error => Report_Error,
1239 When_No_Sources => When_No_Sources,
1240 Current_Dir => Current_Dir);
1244 -------------------------------
1245 -- Process_Declarative_Items --
1246 -------------------------------
1248 procedure Process_Declarative_Items
1249 (Project : Project_Id;
1250 In_Tree : Project_Tree_Ref;
1251 From_Project_Node : Project_Node_Id;
1252 From_Project_Node_Tree : Project_Node_Tree_Ref;
1254 Item : Project_Node_Id)
1256 Current_Declarative_Item : Project_Node_Id;
1257 Current_Item : Project_Node_Id;
1260 -- Loop through declarative items
1262 Current_Item := Empty_Node;
1264 Current_Declarative_Item := Item;
1265 while Present (Current_Declarative_Item) loop
1271 (Current_Declarative_Item, From_Project_Node_Tree);
1273 -- And set Current_Declarative_Item to the next declarative item
1274 -- ready for the next iteration.
1276 Current_Declarative_Item :=
1277 Next_Declarative_Item
1278 (Current_Declarative_Item, From_Project_Node_Tree);
1280 case Kind_Of (Current_Item, From_Project_Node_Tree) is
1282 when N_Package_Declaration =>
1284 -- Do not process a package declaration that should be ignored
1286 if Expression_Kind_Of
1287 (Current_Item, From_Project_Node_Tree) /= Ignored
1289 -- Create the new package
1291 Package_Table.Increment_Last (In_Tree.Packages);
1294 New_Pkg : constant Package_Id :=
1295 Package_Table.Last (In_Tree.Packages);
1296 The_New_Package : Package_Element;
1298 Project_Of_Renamed_Package :
1299 constant Project_Node_Id :=
1300 Project_Of_Renamed_Package_Of
1301 (Current_Item, From_Project_Node_Tree);
1304 -- Set the name of the new package
1306 The_New_Package.Name :=
1307 Name_Of (Current_Item, From_Project_Node_Tree);
1309 -- Insert the new package in the appropriate list
1311 if Pkg /= No_Package then
1312 The_New_Package.Next :=
1313 In_Tree.Packages.Table (Pkg).Decl.Packages;
1314 In_Tree.Packages.Table (Pkg).Decl.Packages :=
1318 The_New_Package.Next :=
1319 In_Tree.Projects.Table (Project).Decl.Packages;
1320 In_Tree.Projects.Table (Project).Decl.Packages :=
1324 In_Tree.Packages.Table (New_Pkg) :=
1327 if Present (Project_Of_Renamed_Package) then
1332 Project_Name : constant Name_Id :=
1334 (Project_Of_Renamed_Package,
1335 From_Project_Node_Tree);
1338 constant Project_Id :=
1339 Imported_Or_Extended_Project_From
1340 (Project, In_Tree, Project_Name);
1342 Renamed_Package : constant Package_Id :=
1344 (Renamed_Project, In_Tree,
1347 From_Project_Node_Tree));
1350 -- For a renamed package, copy the declarations of
1351 -- the renamed package, but set all the locations
1352 -- to the location of the package name in the
1353 -- renaming declaration.
1355 Copy_Package_Declarations
1357 In_Tree.Packages.Table (Renamed_Package).Decl,
1359 In_Tree.Packages.Table (New_Pkg).Decl,
1362 (Current_Item, From_Project_Node_Tree),
1363 Naming_Restricted => False,
1364 In_Tree => In_Tree);
1367 -- Standard package declaration, not renaming
1370 -- Set the default values of the attributes
1374 In_Tree.Projects.Table (Project).Name,
1376 In_Tree.Packages.Table (New_Pkg).Decl,
1379 (Current_Item, From_Project_Node_Tree)),
1380 Project_Level => False);
1382 -- And process declarative items of the new package
1384 Process_Declarative_Items
1385 (Project => Project,
1387 From_Project_Node => From_Project_Node,
1388 From_Project_Node_Tree => From_Project_Node_Tree,
1391 First_Declarative_Item_Of
1392 (Current_Item, From_Project_Node_Tree));
1397 when N_String_Type_Declaration =>
1399 -- There is nothing to process
1403 when N_Attribute_Declaration |
1404 N_Typed_Variable_Declaration |
1405 N_Variable_Declaration =>
1407 if Expression_Of (Current_Item, From_Project_Node_Tree) =
1411 -- It must be a full associative array attribute declaration
1414 Current_Item_Name : constant Name_Id :=
1417 From_Project_Node_Tree);
1418 -- The name of the attribute
1420 Current_Location : constant Source_Ptr :=
1423 From_Project_Node_Tree);
1425 New_Array : Array_Id;
1426 -- The new associative array created
1428 Orig_Array : Array_Id;
1429 -- The associative array value
1431 Orig_Project_Name : Name_Id := No_Name;
1432 -- The name of the project where the associative array
1435 Orig_Project : Project_Id := No_Project;
1436 -- The id of the project where the associative array
1439 Orig_Package_Name : Name_Id := No_Name;
1440 -- The name of the package, if any, where the associative
1443 Orig_Package : Package_Id := No_Package;
1444 -- The id of the package, if any, where the associative
1447 New_Element : Array_Element_Id := No_Array_Element;
1448 -- Id of a new array element created
1450 Prev_Element : Array_Element_Id := No_Array_Element;
1451 -- Last new element id created
1453 Orig_Element : Array_Element_Id := No_Array_Element;
1454 -- Current array element in original associative array
1456 Next_Element : Array_Element_Id := No_Array_Element;
1457 -- Id of the array element that follows the new element.
1458 -- This is not always nil, because values for the
1459 -- associative array attribute may already have been
1460 -- declared, and the array elements declared are reused.
1463 -- First find if the associative array attribute already
1464 -- has elements declared.
1466 if Pkg /= No_Package then
1467 New_Array := In_Tree.Packages.Table
1471 New_Array := In_Tree.Projects.Table
1472 (Project).Decl.Arrays;
1475 while New_Array /= No_Array
1476 and then In_Tree.Arrays.Table (New_Array).Name /=
1479 New_Array := In_Tree.Arrays.Table (New_Array).Next;
1482 -- If the attribute has never been declared add new entry
1483 -- in the arrays of the project/package and link it.
1485 if New_Array = No_Array then
1486 Array_Table.Increment_Last (In_Tree.Arrays);
1487 New_Array := Array_Table.Last (In_Tree.Arrays);
1489 if Pkg /= No_Package then
1490 In_Tree.Arrays.Table (New_Array) :=
1491 (Name => Current_Item_Name,
1492 Location => Current_Location,
1493 Value => No_Array_Element,
1494 Next => In_Tree.Packages.Table
1497 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1501 In_Tree.Arrays.Table (New_Array) :=
1502 (Name => Current_Item_Name,
1503 Location => Current_Location,
1504 Value => No_Array_Element,
1505 Next => In_Tree.Projects.Table
1506 (Project).Decl.Arrays);
1508 In_Tree.Projects.Table (Project).Decl.Arrays :=
1513 -- Find the project where the value is declared
1515 Orig_Project_Name :=
1517 (Associative_Project_Of
1518 (Current_Item, From_Project_Node_Tree),
1519 From_Project_Node_Tree);
1521 for Index in Project_Table.First ..
1525 if In_Tree.Projects.Table (Index).Name =
1528 Orig_Project := Index;
1533 pragma Assert (Orig_Project /= No_Project,
1534 "original project not found");
1536 if No (Associative_Package_Of
1537 (Current_Item, From_Project_Node_Tree))
1540 In_Tree.Projects.Table
1541 (Orig_Project).Decl.Arrays;
1544 -- If in a package, find the package where the value
1547 Orig_Package_Name :=
1549 (Associative_Package_Of
1550 (Current_Item, From_Project_Node_Tree),
1551 From_Project_Node_Tree);
1554 In_Tree.Projects.Table
1555 (Orig_Project).Decl.Packages;
1556 pragma Assert (Orig_Package /= No_Package,
1557 "original package not found");
1559 while In_Tree.Packages.Table
1560 (Orig_Package).Name /= Orig_Package_Name
1562 Orig_Package := In_Tree.Packages.Table
1563 (Orig_Package).Next;
1564 pragma Assert (Orig_Package /= No_Package,
1565 "original package not found");
1569 In_Tree.Packages.Table
1570 (Orig_Package).Decl.Arrays;
1573 -- Now look for the array
1575 while Orig_Array /= No_Array
1576 and then In_Tree.Arrays.Table (Orig_Array).Name /=
1579 Orig_Array := In_Tree.Arrays.Table
1583 if Orig_Array = No_Array then
1584 if Error_Report = null then
1586 ("associative array value cannot be found",
1588 (Current_Item, From_Project_Node_Tree));
1591 ("associative array value cannot be found",
1597 In_Tree.Arrays.Table (Orig_Array).Value;
1599 -- Copy each array element
1601 while Orig_Element /= No_Array_Element loop
1603 -- Case of first element
1605 if Prev_Element = No_Array_Element then
1607 -- And there is no array element declared yet,
1608 -- create a new first array element.
1610 if In_Tree.Arrays.Table (New_Array).Value =
1613 Array_Element_Table.Increment_Last
1614 (In_Tree.Array_Elements);
1615 New_Element := Array_Element_Table.Last
1616 (In_Tree.Array_Elements);
1617 In_Tree.Arrays.Table
1618 (New_Array).Value := New_Element;
1619 Next_Element := No_Array_Element;
1621 -- Otherwise, the new element is the first
1624 New_Element := In_Tree.Arrays.
1625 Table (New_Array).Value;
1627 In_Tree.Array_Elements.Table
1631 -- Otherwise, reuse an existing element, or create
1632 -- one if necessary.
1636 In_Tree.Array_Elements.Table
1637 (Prev_Element).Next;
1639 if Next_Element = No_Array_Element then
1640 Array_Element_Table.Increment_Last
1641 (In_Tree.Array_Elements);
1643 Array_Element_Table.Last
1644 (In_Tree.Array_Elements);
1645 In_Tree.Array_Elements.Table
1646 (Prev_Element).Next := New_Element;
1649 New_Element := Next_Element;
1651 In_Tree.Array_Elements.Table
1656 -- Copy the value of the element
1658 In_Tree.Array_Elements.Table
1660 In_Tree.Array_Elements.Table (Orig_Element);
1661 In_Tree.Array_Elements.Table
1662 (New_Element).Value.Project := Project;
1664 -- Adjust the Next link
1666 In_Tree.Array_Elements.Table
1667 (New_Element).Next := Next_Element;
1669 -- Adjust the previous id for the next element
1671 Prev_Element := New_Element;
1673 -- Go to the next element in the original array
1676 In_Tree.Array_Elements.Table
1677 (Orig_Element).Next;
1680 -- Make sure that the array ends here, in case there
1681 -- previously a greater number of elements.
1683 In_Tree.Array_Elements.Table
1684 (New_Element).Next := No_Array_Element;
1688 -- Declarations other that full associative arrays
1692 New_Value : constant Variable_Value :=
1694 (Project => Project,
1696 From_Project_Node => From_Project_Node,
1697 From_Project_Node_Tree => From_Project_Node_Tree,
1702 (Current_Item, From_Project_Node_Tree),
1703 From_Project_Node_Tree),
1706 (Current_Item, From_Project_Node_Tree));
1707 -- The expression value
1709 The_Variable : Variable_Id := No_Variable;
1711 Current_Item_Name : constant Name_Id :=
1714 From_Project_Node_Tree);
1716 Current_Location : constant Source_Ptr :=
1719 From_Project_Node_Tree);
1722 -- Process a typed variable declaration
1724 if Kind_Of (Current_Item, From_Project_Node_Tree) =
1725 N_Typed_Variable_Declaration
1727 -- Report an error for an empty string
1729 if New_Value.Value = Empty_String then
1731 Name_Of (Current_Item, From_Project_Node_Tree);
1733 if Error_Report = null then
1735 ("no value defined for %%",
1737 (Current_Item, From_Project_Node_Tree));
1740 ("no value defined for " &
1741 Get_Name_String (Error_Msg_Name_1),
1747 Current_String : Project_Node_Id;
1750 -- Loop through all the valid strings for the
1751 -- string type and compare to the string value.
1754 First_Literal_String
1755 (String_Type_Of (Current_Item,
1756 From_Project_Node_Tree),
1757 From_Project_Node_Tree);
1758 while Present (Current_String)
1761 (Current_String, From_Project_Node_Tree) /=
1766 (Current_String, From_Project_Node_Tree);
1769 -- Report an error if the string value is not
1770 -- one for the string type.
1772 if No (Current_String) then
1773 Error_Msg_Name_1 := New_Value.Value;
1776 (Current_Item, From_Project_Node_Tree);
1778 if Error_Report = null then
1780 ("value %% is illegal " &
1781 "for typed string %%",
1784 From_Project_Node_Tree));
1789 Get_Name_String (Error_Msg_Name_1) &
1790 """ is illegal for typed string """ &
1791 Get_Name_String (Error_Msg_Name_2) &
1802 if Kind_Of (Current_Item, From_Project_Node_Tree) /=
1803 N_Attribute_Declaration
1805 Associative_Array_Index_Of
1806 (Current_Item, From_Project_Node_Tree) = No_Name
1808 -- Case of a variable declaration or of a not
1809 -- associative array attribute.
1811 -- First, find the list where to find the variable
1814 if Kind_Of (Current_Item, From_Project_Node_Tree) =
1815 N_Attribute_Declaration
1817 if Pkg /= No_Package then
1819 In_Tree.Packages.Table
1820 (Pkg).Decl.Attributes;
1823 In_Tree.Projects.Table
1824 (Project).Decl.Attributes;
1828 if Pkg /= No_Package then
1830 In_Tree.Packages.Table
1831 (Pkg).Decl.Variables;
1834 In_Tree.Projects.Table
1835 (Project).Decl.Variables;
1840 -- Loop through the list, to find if it has already
1843 while The_Variable /= No_Variable
1845 In_Tree.Variable_Elements.Table
1846 (The_Variable).Name /= Current_Item_Name
1849 In_Tree.Variable_Elements.Table
1850 (The_Variable).Next;
1853 -- If it has not been declared, create a new entry
1856 if The_Variable = No_Variable then
1858 -- All single string attribute should already have
1859 -- been declared with a default empty string value.
1862 (Kind_Of (Current_Item, From_Project_Node_Tree) /=
1863 N_Attribute_Declaration,
1864 "illegal attribute declaration");
1866 Variable_Element_Table.Increment_Last
1867 (In_Tree.Variable_Elements);
1868 The_Variable := Variable_Element_Table.Last
1869 (In_Tree.Variable_Elements);
1871 -- Put the new variable in the appropriate list
1873 if Pkg /= No_Package then
1874 In_Tree.Variable_Elements.Table (The_Variable) :=
1876 In_Tree.Packages.Table
1877 (Pkg).Decl.Variables,
1878 Name => Current_Item_Name,
1879 Value => New_Value);
1880 In_Tree.Packages.Table
1881 (Pkg).Decl.Variables := The_Variable;
1884 In_Tree.Variable_Elements.Table (The_Variable) :=
1886 In_Tree.Projects.Table
1887 (Project).Decl.Variables,
1888 Name => Current_Item_Name,
1889 Value => New_Value);
1890 In_Tree.Projects.Table
1891 (Project).Decl.Variables :=
1895 -- If the variable/attribute has already been
1896 -- declared, just change the value.
1899 In_Tree.Variable_Elements.Table
1900 (The_Variable).Value := New_Value;
1903 -- Associative array attribute
1907 Index_Name : Name_Id :=
1908 Associative_Array_Index_Of
1909 (Current_Item, From_Project_Node_Tree);
1911 The_Array : Array_Id;
1913 The_Array_Element : Array_Element_Id :=
1917 if Index_Name /= All_Other_Names then
1918 -- Get the string index
1921 (Associative_Array_Index_Of
1922 (Current_Item, From_Project_Node_Tree));
1924 -- Put in lower case, if necessary
1928 (Current_Item, From_Project_Node_Tree);
1930 -- In multi-language mode (gprbuild), the index
1931 -- is always case insensitive if it does not
1934 if Get_Mode = Multi_Language
1937 for J in 1 .. Name_Len loop
1938 if Name_Buffer (J) = '.' then
1946 GNAT.Case_Util.To_Lower
1947 (Name_Buffer (1 .. Name_Len));
1950 Index_Name := Name_Find;
1953 -- Look for the array in the appropriate list
1955 if Pkg /= No_Package then
1957 In_Tree.Packages.Table (Pkg).Decl.Arrays;
1961 In_Tree.Projects.Table (Project).Decl.Arrays;
1965 The_Array /= No_Array
1967 In_Tree.Arrays.Table (The_Array).Name /=
1970 The_Array := In_Tree.Arrays.Table
1974 -- If the array cannot be found, create a new entry
1975 -- in the list. As The_Array_Element is initialized
1976 -- to No_Array_Element, a new element will be
1977 -- created automatically later
1979 if The_Array = No_Array then
1980 Array_Table.Increment_Last (In_Tree.Arrays);
1981 The_Array := Array_Table.Last (In_Tree.Arrays);
1983 if Pkg /= No_Package then
1984 In_Tree.Arrays.Table (The_Array) :=
1985 (Name => Current_Item_Name,
1986 Location => Current_Location,
1987 Value => No_Array_Element,
1988 Next => In_Tree.Packages.Table
1991 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1995 In_Tree.Arrays.Table (The_Array) :=
1996 (Name => Current_Item_Name,
1997 Location => Current_Location,
1998 Value => No_Array_Element,
1999 Next => In_Tree.Projects.Table
2000 (Project).Decl.Arrays);
2002 In_Tree.Projects.Table
2003 (Project).Decl.Arrays := The_Array;
2006 -- Otherwise initialize The_Array_Element as the
2007 -- head of the element list.
2010 The_Array_Element :=
2011 In_Tree.Arrays.Table (The_Array).Value;
2014 -- Look in the list, if any, to find an element
2015 -- with the same index.
2017 while The_Array_Element /= No_Array_Element
2019 In_Tree.Array_Elements.Table
2020 (The_Array_Element).Index /= Index_Name
2022 The_Array_Element :=
2023 In_Tree.Array_Elements.Table
2024 (The_Array_Element).Next;
2027 -- If no such element were found, create a new one
2028 -- and insert it in the element list, with the
2031 if The_Array_Element = No_Array_Element then
2032 Array_Element_Table.Increment_Last
2033 (In_Tree.Array_Elements);
2034 The_Array_Element := Array_Element_Table.Last
2035 (In_Tree.Array_Elements);
2037 In_Tree.Array_Elements.Table
2038 (The_Array_Element) :=
2039 (Index => Index_Name,
2042 (Current_Item, From_Project_Node_Tree),
2043 Index_Case_Sensitive =>
2044 not Case_Insensitive
2045 (Current_Item, From_Project_Node_Tree),
2047 Next => In_Tree.Arrays.Table
2049 In_Tree.Arrays.Table
2050 (The_Array).Value := The_Array_Element;
2052 -- An element with the same index already exists,
2053 -- just replace its value with the new one.
2056 In_Tree.Array_Elements.Table
2057 (The_Array_Element).Value := New_Value;
2064 when N_Case_Construction =>
2066 The_Project : Project_Id := Project;
2067 -- The id of the project of the case variable
2069 The_Package : Package_Id := Pkg;
2070 -- The id of the package, if any, of the case variable
2072 The_Variable : Variable_Value := Nil_Variable_Value;
2073 -- The case variable
2075 Case_Value : Name_Id := No_Name;
2076 -- The case variable value
2078 Case_Item : Project_Node_Id := Empty_Node;
2079 Choice_String : Project_Node_Id := Empty_Node;
2080 Decl_Item : Project_Node_Id := Empty_Node;
2084 Variable_Node : constant Project_Node_Id :=
2085 Case_Variable_Reference_Of
2087 From_Project_Node_Tree);
2089 Var_Id : Variable_Id := No_Variable;
2090 Name : Name_Id := No_Name;
2093 -- If a project was specified for the case variable,
2096 if Present (Project_Node_Of
2097 (Variable_Node, From_Project_Node_Tree))
2102 (Variable_Node, From_Project_Node_Tree),
2103 From_Project_Node_Tree);
2105 Imported_Or_Extended_Project_From
2106 (Project, In_Tree, Name);
2109 -- If a package were specified for the case variable,
2112 if Present (Package_Node_Of
2113 (Variable_Node, From_Project_Node_Tree))
2118 (Variable_Node, From_Project_Node_Tree),
2119 From_Project_Node_Tree);
2121 Package_From (The_Project, In_Tree, Name);
2124 Name := Name_Of (Variable_Node, From_Project_Node_Tree);
2126 -- First, look for the case variable into the package,
2129 if The_Package /= No_Package then
2130 Var_Id := In_Tree.Packages.Table
2131 (The_Package).Decl.Variables;
2133 Name_Of (Variable_Node, From_Project_Node_Tree);
2134 while Var_Id /= No_Variable
2136 In_Tree.Variable_Elements.Table
2137 (Var_Id).Name /= Name
2139 Var_Id := In_Tree.Variable_Elements.
2140 Table (Var_Id).Next;
2144 -- If not found in the package, or if there is no
2145 -- package, look at the project level.
2147 if Var_Id = No_Variable
2150 (Variable_Node, From_Project_Node_Tree))
2152 Var_Id := In_Tree.Projects.Table
2153 (The_Project).Decl.Variables;
2154 while Var_Id /= No_Variable
2156 In_Tree.Variable_Elements.Table
2157 (Var_Id).Name /= Name
2159 Var_Id := In_Tree.Variable_Elements.
2160 Table (Var_Id).Next;
2164 if Var_Id = No_Variable then
2166 -- Should never happen, because this has already been
2167 -- checked during parsing.
2169 Write_Line ("variable """ &
2170 Get_Name_String (Name) &
2172 raise Program_Error;
2175 -- Get the case variable
2177 The_Variable := In_Tree.Variable_Elements.
2178 Table (Var_Id).Value;
2180 if The_Variable.Kind /= Single then
2182 -- Should never happen, because this has already been
2183 -- checked during parsing.
2185 Write_Line ("variable""" &
2186 Get_Name_String (Name) &
2187 """ is not a single string variable");
2188 raise Program_Error;
2191 -- Get the case variable value
2192 Case_Value := The_Variable.Value;
2195 -- Now look into all the case items of the case construction
2198 First_Case_Item_Of (Current_Item, From_Project_Node_Tree);
2200 while Present (Case_Item) loop
2202 First_Choice_Of (Case_Item, From_Project_Node_Tree);
2204 -- When Choice_String is nil, it means that it is
2205 -- the "when others =>" alternative.
2207 if No (Choice_String) then
2209 First_Declarative_Item_Of
2210 (Case_Item, From_Project_Node_Tree);
2211 exit Case_Item_Loop;
2214 -- Look into all the alternative of this case item
2217 while Present (Choice_String) loop
2220 (Choice_String, From_Project_Node_Tree)
2223 First_Declarative_Item_Of
2224 (Case_Item, From_Project_Node_Tree);
2225 exit Case_Item_Loop;
2230 (Choice_String, From_Project_Node_Tree);
2231 end loop Choice_Loop;
2234 Next_Case_Item (Case_Item, From_Project_Node_Tree);
2235 end loop Case_Item_Loop;
2237 -- If there is an alternative, then we process it
2239 if Present (Decl_Item) then
2240 Process_Declarative_Items
2241 (Project => Project,
2243 From_Project_Node => From_Project_Node,
2244 From_Project_Node_Tree => From_Project_Node_Tree,
2252 -- Should never happen
2254 Write_Line ("Illegal declarative item: " &
2255 Project_Node_Kind'Image
2257 (Current_Item, From_Project_Node_Tree)));
2258 raise Program_Error;
2261 end Process_Declarative_Items;
2263 ----------------------------------
2264 -- Process_Project_Tree_Phase_1 --
2265 ----------------------------------
2267 procedure Process_Project_Tree_Phase_1
2268 (In_Tree : Project_Tree_Ref;
2269 Project : out Project_Id;
2270 Success : out Boolean;
2271 From_Project_Node : Project_Node_Id;
2272 From_Project_Node_Tree : Project_Node_Tree_Ref;
2273 Report_Error : Put_Line_Access;
2274 Reset_Tree : Boolean := True)
2277 Error_Report := Report_Error;
2281 -- Make sure there are no projects in the data structure
2283 Project_Table.Set_Last (In_Tree.Projects, No_Project);
2286 Processed_Projects.Reset;
2288 -- And process the main project and all of the projects it depends on,
2292 (Project => Project,
2294 From_Project_Node => From_Project_Node,
2295 From_Project_Node_Tree => From_Project_Node_Tree,
2296 Extended_By => No_Project);
2299 Total_Errors_Detected = 0
2301 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2302 end Process_Project_Tree_Phase_1;
2304 ----------------------------------
2305 -- Process_Project_Tree_Phase_2 --
2306 ----------------------------------
2308 procedure Process_Project_Tree_Phase_2
2309 (In_Tree : Project_Tree_Ref;
2310 Project : Project_Id;
2311 Success : out Boolean;
2312 From_Project_Node : Project_Node_Id;
2313 From_Project_Node_Tree : Project_Node_Tree_Ref;
2314 Report_Error : Put_Line_Access;
2315 When_No_Sources : Error_Warning := Error;
2316 Current_Dir : String)
2318 Obj_Dir : Path_Name_Type;
2319 Extending : Project_Id;
2320 Extending2 : Project_Id;
2322 -- Start of processing for Process_Project_Tree_Phase_2
2325 Error_Report := Report_Error;
2328 if Project /= No_Project then
2329 Check (In_Tree, Project, Current_Dir, When_No_Sources);
2332 -- If main project is an extending all project, set the object
2333 -- directory of all virtual extending projects to the object
2334 -- directory of the main project.
2336 if Project /= No_Project
2338 Is_Extending_All (From_Project_Node, From_Project_Node_Tree)
2341 Object_Dir : constant Path_Name_Type :=
2342 In_Tree.Projects.Table
2343 (Project).Object_Directory.Name;
2346 Project_Table.First .. Project_Table.Last (In_Tree.Projects)
2348 if In_Tree.Projects.Table (Index).Virtual then
2349 In_Tree.Projects.Table (Index).Object_Directory.Name :=
2356 -- Check that no extending project shares its object directory with
2357 -- the project(s) it extends.
2359 if Project /= No_Project then
2361 Project_Table.First .. Project_Table.Last (In_Tree.Projects)
2363 Extending := In_Tree.Projects.Table (Proj).Extended_By;
2365 if Extending /= No_Project then
2366 Obj_Dir := In_Tree.Projects.Table (Proj).Object_Directory.Name;
2368 -- Check that a project being extended does not share its
2369 -- object directory with any project that extends it, directly
2370 -- or indirectly, including a virtual extending project.
2372 -- Start with the project directly extending it
2374 Extending2 := Extending;
2375 while Extending2 /= No_Project loop
2376 if In_Tree.Projects.Table (Extending2).Ada_Sources /=
2379 In_Tree.Projects.Table
2380 (Extending2).Object_Directory.Name = Obj_Dir
2382 if In_Tree.Projects.Table (Extending2).Virtual then
2384 In_Tree.Projects.Table (Proj).Display_Name;
2386 if Error_Report = null then
2388 ("project %% cannot be extended by a virtual" &
2389 " project with the same object directory",
2390 In_Tree.Projects.Table (Proj).Location);
2394 Get_Name_String (Error_Msg_Name_1) &
2395 """ cannot be extended by a virtual " &
2396 "project with the same object directory",
2402 In_Tree.Projects.Table (Extending2).Display_Name;
2404 In_Tree.Projects.Table (Proj).Display_Name;
2406 if Error_Report = null then
2408 ("project %% cannot extend project %%",
2409 In_Tree.Projects.Table (Extending2).Location);
2411 ("\they share the same object directory",
2412 In_Tree.Projects.Table (Extending2).Location);
2417 Get_Name_String (Error_Msg_Name_1) &
2418 """ cannot extend project """ &
2419 Get_Name_String (Error_Msg_Name_2) & """",
2422 ("they share the same object directory",
2428 -- Continue with the next extending project, if any
2431 In_Tree.Projects.Table (Extending2).Extended_By;
2438 Total_Errors_Detected = 0
2440 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2441 end Process_Project_Tree_Phase_2;
2443 ---------------------
2444 -- Recursive_Check --
2445 ---------------------
2447 procedure Recursive_Check
2448 (Project : Project_Id;
2449 In_Tree : Project_Tree_Ref;
2450 Current_Dir : String;
2451 When_No_Sources : Error_Warning)
2453 Data : Project_Data;
2454 Imported_Project_List : Project_List := Empty_Project_List;
2457 -- Do nothing if Project is No_Project, or Project has already
2458 -- been marked as checked.
2460 if Project /= No_Project
2461 and then not In_Tree.Projects.Table (Project).Checked
2463 -- Mark project as checked, to avoid infinite recursion in
2464 -- ill-formed trees, where a project imports itself.
2466 In_Tree.Projects.Table (Project).Checked := True;
2468 Data := In_Tree.Projects.Table (Project);
2470 -- Call itself for a possible extended project.
2471 -- (if there is no extended project, then nothing happens).
2473 Recursive_Check (Data.Extends, In_Tree, Current_Dir, When_No_Sources);
2475 -- Call itself for all imported projects
2477 Imported_Project_List := Data.Imported_Projects;
2478 while Imported_Project_List /= Empty_Project_List loop
2480 (In_Tree.Project_Lists.Table
2481 (Imported_Project_List).Project,
2482 In_Tree, Current_Dir, When_No_Sources);
2483 Imported_Project_List :=
2484 In_Tree.Project_Lists.Table
2485 (Imported_Project_List).Next;
2488 if Verbose_Mode then
2489 Write_Str ("Checking project file """);
2490 Write_Str (Get_Name_String (Data.Name));
2495 (Project, In_Tree, Error_Report, When_No_Sources,
2498 end Recursive_Check;
2500 -----------------------
2501 -- Recursive_Process --
2502 -----------------------
2504 procedure Recursive_Process
2505 (In_Tree : Project_Tree_Ref;
2506 Project : out Project_Id;
2507 From_Project_Node : Project_Node_Id;
2508 From_Project_Node_Tree : Project_Node_Tree_Ref;
2509 Extended_By : Project_Id)
2511 With_Clause : Project_Node_Id;
2514 if No (From_Project_Node) then
2515 Project := No_Project;
2519 Processed_Data : Project_Data := Empty_Project (In_Tree);
2520 Imported : Project_List := Empty_Project_List;
2521 Declaration_Node : Project_Node_Id := Empty_Node;
2522 Tref : Source_Buffer_Ptr;
2523 Name : constant Name_Id :=
2525 (From_Project_Node, From_Project_Node_Tree);
2526 Location : Source_Ptr :=
2528 (From_Project_Node, From_Project_Node_Tree);
2531 Project := Processed_Projects.Get (Name);
2533 if Project /= No_Project then
2535 -- Make sure that, when a project is extended, the project id
2536 -- of the project extending it is recorded in its data, even
2537 -- when it has already been processed as an imported project.
2538 -- This is for virtually extended projects.
2540 if Extended_By /= No_Project then
2541 In_Tree.Projects.Table (Project).Extended_By := Extended_By;
2547 Project_Table.Increment_Last (In_Tree.Projects);
2548 Project := Project_Table.Last (In_Tree.Projects);
2549 Processed_Projects.Set (Name, Project);
2551 Processed_Data.Name := Name;
2552 Processed_Data.Qualifier :=
2553 Project_Qualifier_Of (From_Project_Node, From_Project_Node_Tree);
2554 In_Tree.Projects.Table (Project).Name := Name;
2555 In_Tree.Projects.Table (Project).Qualifier :=
2556 Processed_Data.Qualifier;
2558 Get_Name_String (Name);
2560 -- If name starts with the virtual prefix, flag the project as
2561 -- being a virtual extending project.
2563 if Name_Len > Virtual_Prefix'Length
2564 and then Name_Buffer (1 .. Virtual_Prefix'Length) =
2567 Processed_Data.Virtual := True;
2568 Processed_Data.Display_Name := Name;
2570 -- If there is no file, for example when the project node tree is
2571 -- built in memory by GPS, the Display_Name cannot be found in
2572 -- the source, so its value is the same as Name.
2574 elsif Location = No_Location then
2575 Processed_Data.Display_Name := Name;
2577 -- Get the spelling of the project name from the project file
2580 Tref := Source_Text (Get_Source_File_Index (Location));
2582 for J in 1 .. Name_Len loop
2583 Name_Buffer (J) := Tref (Location);
2584 Location := Location + 1;
2587 Processed_Data.Display_Name := Name_Find;
2590 Processed_Data.Path.Display_Name :=
2591 Path_Name_Of (From_Project_Node, From_Project_Node_Tree);
2592 Get_Name_String (Processed_Data.Path.Display_Name);
2593 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2594 Processed_Data.Path.Name := Name_Find;
2596 Processed_Data.Location :=
2597 Location_Of (From_Project_Node, From_Project_Node_Tree);
2599 Processed_Data.Directory.Display_Name :=
2600 Directory_Of (From_Project_Node, From_Project_Node_Tree);
2601 Get_Name_String (Processed_Data.Directory.Display_Name);
2602 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2603 Processed_Data.Directory.Name := Name_Find;
2605 Processed_Data.Extended_By := Extended_By;
2611 Processed_Data.Decl,
2612 Prj.Attr.Attribute_First,
2613 Project_Level => True);
2615 -- Process non limited withed projects
2618 First_With_Clause_Of (From_Project_Node, From_Project_Node_Tree);
2619 while Present (With_Clause) loop
2621 New_Project : Project_Id;
2622 New_Data : Project_Data;
2623 Proj_Node : Project_Node_Id;
2627 Non_Limited_Project_Node_Of
2628 (With_Clause, From_Project_Node_Tree);
2630 if Present (Proj_Node) then
2632 (In_Tree => In_Tree,
2633 Project => New_Project,
2634 From_Project_Node =>
2636 (With_Clause, From_Project_Node_Tree),
2637 From_Project_Node_Tree => From_Project_Node_Tree,
2638 Extended_By => No_Project);
2641 In_Tree.Projects.Table (New_Project);
2643 -- If we were the first project to import it,
2644 -- set First_Referred_By to us.
2646 if New_Data.First_Referred_By = No_Project then
2647 New_Data.First_Referred_By := Project;
2648 In_Tree.Projects.Table (New_Project) :=
2652 -- Add this project to our list of imported projects
2654 Project_List_Table.Increment_Last
2655 (In_Tree.Project_Lists);
2657 In_Tree.Project_Lists.Table
2658 (Project_List_Table.Last
2659 (In_Tree.Project_Lists)) :=
2660 (Project => New_Project, Next => Empty_Project_List);
2662 -- Imported is the id of the last imported project. If it
2663 -- is nil, then this imported project is our first.
2665 if Imported = Empty_Project_List then
2666 Processed_Data.Imported_Projects :=
2667 Project_List_Table.Last
2668 (In_Tree.Project_Lists);
2671 In_Tree.Project_Lists.Table
2672 (Imported).Next := Project_List_Table.Last
2673 (In_Tree.Project_Lists);
2676 Imported := Project_List_Table.Last
2677 (In_Tree.Project_Lists);
2682 (With_Clause, From_Project_Node_Tree);
2687 Project_Declaration_Of
2688 (From_Project_Node, From_Project_Node_Tree);
2691 (In_Tree => In_Tree,
2692 Project => Processed_Data.Extends,
2693 From_Project_Node => Extended_Project_Of
2695 From_Project_Node_Tree),
2696 From_Project_Node_Tree => From_Project_Node_Tree,
2697 Extended_By => Project);
2699 In_Tree.Projects.Table (Project) := Processed_Data;
2701 Process_Declarative_Items
2702 (Project => Project,
2704 From_Project_Node => From_Project_Node,
2705 From_Project_Node_Tree => From_Project_Node_Tree,
2707 Item => First_Declarative_Item_Of
2709 From_Project_Node_Tree));
2711 -- If it is an extending project, inherit all packages
2712 -- from the extended project that are not explicitly defined
2713 -- or renamed. Also inherit the languages, if attribute Languages
2714 -- is not explicitly defined.
2716 Processed_Data := In_Tree.Projects.Table (Project);
2718 if Processed_Data.Extends /= No_Project then
2720 Extended_Pkg : Package_Id;
2721 Current_Pkg : Package_Id;
2722 Element : Package_Element;
2723 First : constant Package_Id :=
2724 Processed_Data.Decl.Packages;
2725 Attribute1 : Variable_Id;
2726 Attribute2 : Variable_Id;
2727 Attr_Value1 : Variable;
2728 Attr_Value2 : Variable;
2732 In_Tree.Projects.Table
2733 (Processed_Data.Extends).Decl.Packages;
2734 while Extended_Pkg /= No_Package loop
2736 In_Tree.Packages.Table (Extended_Pkg);
2738 Current_Pkg := First;
2739 while Current_Pkg /= No_Package
2740 and then In_Tree.Packages.Table (Current_Pkg).Name /=
2744 In_Tree.Packages.Table (Current_Pkg).Next;
2747 if Current_Pkg = No_Package then
2748 Package_Table.Increment_Last
2750 Current_Pkg := Package_Table.Last (In_Tree.Packages);
2751 In_Tree.Packages.Table (Current_Pkg) :=
2752 (Name => Element.Name,
2753 Decl => No_Declarations,
2754 Parent => No_Package,
2755 Next => Processed_Data.Decl.Packages);
2756 Processed_Data.Decl.Packages := Current_Pkg;
2757 Copy_Package_Declarations
2758 (From => Element.Decl,
2760 In_Tree.Packages.Table (Current_Pkg).Decl,
2761 New_Loc => No_Location,
2762 Naming_Restricted =>
2763 Element.Name = Snames.Name_Naming,
2764 In_Tree => In_Tree);
2767 Extended_Pkg := Element.Next;
2770 -- Check if attribute Languages is declared in the
2771 -- extending project.
2773 Attribute1 := Processed_Data.Decl.Attributes;
2774 while Attribute1 /= No_Variable loop
2775 Attr_Value1 := In_Tree.Variable_Elements.
2777 exit when Attr_Value1.Name = Snames.Name_Languages;
2778 Attribute1 := Attr_Value1.Next;
2781 if Attribute1 = No_Variable or else
2782 Attr_Value1.Value.Default
2784 -- Attribute Languages is not declared in the extending
2785 -- project. Check if it is declared in the project being
2789 In_Tree.Projects.Table
2790 (Processed_Data.Extends).Decl.Attributes;
2791 while Attribute2 /= No_Variable loop
2792 Attr_Value2 := In_Tree.Variable_Elements.
2794 exit when Attr_Value2.Name = Snames.Name_Languages;
2795 Attribute2 := Attr_Value2.Next;
2798 if Attribute2 /= No_Variable and then
2799 not Attr_Value2.Value.Default
2801 -- As attribute Languages is declared in the project
2802 -- being extended, copy its value for the extending
2805 if Attribute1 = No_Variable then
2806 Variable_Element_Table.Increment_Last
2807 (In_Tree.Variable_Elements);
2808 Attribute1 := Variable_Element_Table.Last
2809 (In_Tree.Variable_Elements);
2810 Attr_Value1.Next := Processed_Data.Decl.Attributes;
2811 Processed_Data.Decl.Attributes := Attribute1;
2814 Attr_Value1.Name := Snames.Name_Languages;
2815 Attr_Value1.Value := Attr_Value2.Value;
2816 In_Tree.Variable_Elements.Table
2817 (Attribute1) := Attr_Value1;
2822 In_Tree.Projects.Table (Project) := Processed_Data;
2825 -- Process limited withed projects
2828 First_With_Clause_Of
2829 (From_Project_Node, From_Project_Node_Tree);
2830 while Present (With_Clause) loop
2832 New_Project : Project_Id;
2833 New_Data : Project_Data;
2834 Proj_Node : Project_Node_Id;
2838 Non_Limited_Project_Node_Of
2839 (With_Clause, From_Project_Node_Tree);
2841 if No (Proj_Node) then
2843 (In_Tree => In_Tree,
2844 Project => New_Project,
2845 From_Project_Node =>
2847 (With_Clause, From_Project_Node_Tree),
2848 From_Project_Node_Tree => From_Project_Node_Tree,
2849 Extended_By => No_Project);
2852 In_Tree.Projects.Table (New_Project);
2854 -- If we were the first project to import it, set
2855 -- First_Referred_By to us.
2857 if New_Data.First_Referred_By = No_Project then
2858 New_Data.First_Referred_By := Project;
2859 In_Tree.Projects.Table (New_Project) :=
2863 -- Add this project to our list of imported projects
2865 Project_List_Table.Increment_Last
2866 (In_Tree.Project_Lists);
2868 In_Tree.Project_Lists.Table
2869 (Project_List_Table.Last
2870 (In_Tree.Project_Lists)) :=
2871 (Project => New_Project, Next => Empty_Project_List);
2873 -- Imported is the id of the last imported project. If
2874 -- it is nil, then this imported project is our first.
2876 if Imported = Empty_Project_List then
2877 In_Tree.Projects.Table (Project).Imported_Projects :=
2878 Project_List_Table.Last
2879 (In_Tree.Project_Lists);
2881 In_Tree.Project_Lists.Table
2882 (Imported).Next := Project_List_Table.Last
2883 (In_Tree.Project_Lists);
2886 Imported := Project_List_Table.Last
2887 (In_Tree.Project_Lists);
2892 (With_Clause, From_Project_Node_Tree);
2897 end Recursive_Process;