1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2007, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with 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 Prj.Util; use Prj.Util;
36 with Sinput; use Sinput;
39 with GNAT.Case_Util; use GNAT.Case_Util;
42 package body Prj.Proc is
44 Error_Report : Put_Line_Access := null;
46 package Processed_Projects is new GNAT.HTable.Simple_HTable
47 (Header_Num => Header_Num,
48 Element => Project_Id,
49 No_Element => No_Project,
53 -- This hash table contains all processed projects
55 package Unit_Htable is new GNAT.HTable.Simple_HTable
56 (Header_Num => Header_Num,
58 No_Element => No_Source,
62 -- This hash table contains all processed projects
64 procedure Add (To_Exp : in out Name_Id; Str : Name_Id);
65 -- Concatenate two strings and returns another string if both
66 -- arguments are not null string.
68 procedure Add_Attributes
69 (Project : Project_Id;
70 Project_Name : Name_Id;
71 In_Tree : Project_Tree_Ref;
72 Decl : in out Declarations;
73 First : Attribute_Node_Id;
74 Project_Level : Boolean);
75 -- Add all attributes, starting with First, with their default
76 -- values to the package or project with declarations Decl.
79 (In_Tree : Project_Tree_Ref;
81 Follow_Links : Boolean;
82 When_No_Sources : Error_Warning);
83 -- Set all projects to not checked, then call Recursive_Check for the
84 -- main project Project. Project is set to No_Project if errors occurred.
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 Follow_Links : Boolean;
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.
154 procedure Add (To_Exp : in out Name_Id; Str : Name_Id) is
156 if To_Exp = No_Name or else To_Exp = Empty_String then
158 -- To_Exp is nil or empty. The result is Str
162 -- If Str is nil, then do not change To_Ext
164 elsif Str /= No_Name and then Str /= Empty_String then
166 S : constant String := Get_Name_String (Str);
169 Get_Name_String (To_Exp);
170 Add_Str_To_Name_Buffer (S);
180 procedure Add_Attributes
181 (Project : Project_Id;
182 Project_Name : Name_Id;
183 In_Tree : Project_Tree_Ref;
184 Decl : in out Declarations;
185 First : Attribute_Node_Id;
186 Project_Level : Boolean)
188 The_Attribute : Attribute_Node_Id := First;
191 while The_Attribute /= Empty_Attribute loop
192 if Attribute_Kind_Of (The_Attribute) = Single then
194 New_Attribute : Variable_Value;
197 case Variable_Kind_Of (The_Attribute) is
199 -- Undefined should not happen
203 (False, "attribute with an undefined kind");
206 -- Single attributes have a default value of empty string
212 Location => No_Location,
214 Value => Empty_String,
217 -- Special case of <project>'Name
220 and then Attribute_Name_Of (The_Attribute) =
223 New_Attribute.Value := Project_Name;
226 -- List attributes have a default value of nil list
232 Location => No_Location,
234 Values => Nil_String);
238 Variable_Element_Table.Increment_Last
239 (In_Tree.Variable_Elements);
240 In_Tree.Variable_Elements.Table
241 (Variable_Element_Table.Last
242 (In_Tree.Variable_Elements)) :=
243 (Next => Decl.Attributes,
244 Name => Attribute_Name_Of (The_Attribute),
245 Value => New_Attribute);
246 Decl.Attributes := Variable_Element_Table.Last
247 (In_Tree.Variable_Elements);
251 The_Attribute := Next_Attribute (After => The_Attribute);
260 (In_Tree : Project_Tree_Ref;
261 Project : Project_Id;
262 Follow_Links : Boolean;
263 When_No_Sources : Error_Warning)
266 -- Make sure that all projects are marked as not checked
268 for Index in Project_Table.First ..
269 Project_Table.Last (In_Tree.Projects)
271 In_Tree.Projects.Table (Index).Checked := False;
275 (Project, In_Tree, Follow_Links, 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;
772 if The_Package /= No_Package then
774 In_Tree.Packages.Table
775 (The_Package).Decl.Arrays;
778 In_Tree.Projects.Table
779 (The_Project).Decl.Arrays;
782 while The_Array /= No_Array
783 and then In_Tree.Arrays.Table
784 (The_Array).Name /= The_Name
786 The_Array := In_Tree.Arrays.Table
790 if The_Array /= No_Array then
791 The_Element := In_Tree.Arrays.Table
794 Get_Name_String (Index);
797 (The_Current_Term, From_Project_Node_Tree)
799 To_Lower (Name_Buffer (1 .. Name_Len));
802 Array_Index := Name_Find;
804 while The_Element /= No_Array_Element
806 In_Tree.Array_Elements.Table
807 (The_Element).Index /= Array_Index
810 In_Tree.Array_Elements.Table
816 if The_Element /= No_Array_Element then
818 In_Tree.Array_Elements.Table
822 if Expression_Kind_Of
823 (The_Current_Term, From_Project_Node_Tree) =
829 Location => No_Location,
831 Values => Nil_String);
836 Location => No_Location,
838 Value => Empty_String,
849 -- Should never happen
851 pragma Assert (False, "undefined expression kind");
856 case The_Variable.Kind is
862 Add (Result.Value, The_Variable.Value);
866 -- Should never happen
870 "list cannot appear in single " &
871 "string expression");
876 case The_Variable.Kind is
882 String_Element_Table.Increment_Last
883 (In_Tree.String_Elements);
885 if Last = Nil_String then
887 -- This can happen in an expression such as
891 String_Element_Table.Last
892 (In_Tree.String_Elements);
895 In_Tree.String_Elements.Table
897 String_Element_Table.Last
898 (In_Tree.String_Elements);
902 String_Element_Table.Last
903 (In_Tree.String_Elements);
905 In_Tree.String_Elements.Table (Last) :=
906 (Value => The_Variable.Value,
907 Display_Value => No_Name,
908 Location => Location_Of
910 From_Project_Node_Tree),
918 The_List : String_List_Id :=
922 while The_List /= Nil_String loop
923 String_Element_Table.Increment_Last
924 (In_Tree.String_Elements);
926 if Last = Nil_String then
928 String_Element_Table.Last
934 String_Elements.Table (Last).Next :=
935 String_Element_Table.Last
942 String_Element_Table.Last
943 (In_Tree.String_Elements);
945 In_Tree.String_Elements.Table (Last) :=
947 In_Tree.String_Elements.Table
949 Display_Value => No_Name,
953 From_Project_Node_Tree),
959 In_Tree. String_Elements.Table
967 when N_External_Value =>
970 (External_Reference_Of
971 (The_Current_Term, From_Project_Node_Tree),
972 From_Project_Node_Tree));
975 Name : constant Name_Id := Name_Find;
976 Default : Name_Id := No_Name;
977 Value : Name_Id := No_Name;
979 Def_Var : Variable_Value;
981 Default_Node : constant Project_Node_Id :=
983 (The_Current_Term, From_Project_Node_Tree);
986 -- If there is a default value for the external reference,
989 if Default_Node /= Empty_Node then
990 Def_Var := Expression
993 From_Project_Node => Default_Node,
994 From_Project_Node_Tree => From_Project_Node_Tree,
998 (Default_Node, From_Project_Node_Tree),
1001 if Def_Var /= Nil_Variable_Value then
1002 Default := Def_Var.Value;
1006 Value := Prj.Ext.Value_Of (Name, Default);
1008 if Value = No_Name then
1009 if not Quiet_Output then
1010 if Error_Report = null then
1012 ("?undefined external reference",
1014 (The_Current_Term, From_Project_Node_Tree));
1017 ("warning: """ & Get_Name_String (Name) &
1018 """ is an undefined external reference",
1023 Value := Empty_String;
1032 Add (Result.Value, Value);
1035 String_Element_Table.Increment_Last
1036 (In_Tree.String_Elements);
1038 if Last = Nil_String then
1039 Result.Values := String_Element_Table.Last
1040 (In_Tree.String_Elements);
1043 In_Tree.String_Elements.Table
1044 (Last).Next := String_Element_Table.Last
1045 (In_Tree.String_Elements);
1048 Last := String_Element_Table.Last
1049 (In_Tree.String_Elements);
1050 In_Tree.String_Elements.Table (Last) :=
1052 Display_Value => No_Name,
1055 (The_Current_Term, From_Project_Node_Tree),
1065 -- Should never happen
1069 "illegal node kind in an expression");
1070 raise Program_Error;
1074 The_Term := Next_Term (The_Term, From_Project_Node_Tree);
1080 ---------------------------------------
1081 -- Imported_Or_Extended_Project_From --
1082 ---------------------------------------
1084 function Imported_Or_Extended_Project_From
1085 (Project : Project_Id;
1086 In_Tree : Project_Tree_Ref;
1087 With_Name : Name_Id) return Project_Id
1089 Data : constant Project_Data :=
1090 In_Tree.Projects.Table (Project);
1091 List : Project_List := Data.Imported_Projects;
1092 Result : Project_Id := No_Project;
1093 Temp_Result : Project_Id := No_Project;
1096 -- First check if it is the name of an extended project
1098 if Data.Extends /= No_Project
1099 and then In_Tree.Projects.Table (Data.Extends).Name =
1102 return Data.Extends;
1105 -- Then check the name of each imported project
1107 while List /= Empty_Project_List loop
1108 Result := In_Tree.Project_Lists.Table (List).Project;
1110 -- If the project is directly imported, then returns its ID
1113 In_Tree.Projects.Table (Result).Name = With_Name
1118 -- If a project extending the project is imported, then keep
1119 -- this extending project as a possibility. It will be the
1120 -- returned ID if the project is not imported directly.
1123 Proj : Project_Id :=
1124 In_Tree.Projects.Table (Result).Extends;
1126 while Proj /= No_Project loop
1127 if In_Tree.Projects.Table (Proj).Name =
1130 Temp_Result := Result;
1134 Proj := In_Tree.Projects.Table (Proj).Extends;
1138 List := In_Tree.Project_Lists.Table (List).Next;
1142 (Temp_Result /= No_Project,
1143 "project not found");
1147 end Imported_Or_Extended_Project_From;
1153 function Package_From
1154 (Project : Project_Id;
1155 In_Tree : Project_Tree_Ref;
1156 With_Name : Name_Id) return Package_Id
1158 Data : constant Project_Data :=
1159 In_Tree.Projects.Table (Project);
1160 Result : Package_Id := Data.Decl.Packages;
1163 -- Check the name of each existing package of Project
1165 while Result /= No_Package
1166 and then In_Tree.Packages.Table (Result).Name /= With_Name
1168 Result := In_Tree.Packages.Table (Result).Next;
1171 if Result = No_Package then
1173 -- Should never happen
1175 Write_Line ("package """ & Get_Name_String (With_Name) &
1177 raise Program_Error;
1189 (In_Tree : Project_Tree_Ref;
1190 Project : out Project_Id;
1191 Success : out Boolean;
1192 From_Project_Node : Project_Node_Id;
1193 From_Project_Node_Tree : Project_Node_Tree_Ref;
1194 Report_Error : Put_Line_Access;
1195 Follow_Links : Boolean := True;
1196 When_No_Sources : Error_Warning := Error;
1197 Reset_Tree : Boolean := True)
1199 Obj_Dir : Path_Name_Type;
1200 Extending : Project_Id;
1201 Extending2 : Project_Id;
1202 Packages : Package_Id;
1203 Element : Package_Element;
1205 procedure Process_Attributes (Attrs : Variable_Id);
1207 ------------------------
1208 -- Process_Attributes --
1209 ------------------------
1211 procedure Process_Attributes (Attrs : Variable_Id) is
1212 Attribute_Id : Variable_Id;
1213 Attribute : Variable;
1214 List : String_List_Id;
1217 -- Loop through attributes
1219 Attribute_Id := Attrs;
1220 while Attribute_Id /= No_Variable loop
1222 In_Tree.Variable_Elements.Table (Attribute_Id);
1224 if not Attribute.Value.Default then
1225 case Attribute.Name is
1226 when Snames.Name_Driver =>
1228 -- Attribute Linker'Driver: the default linker to use
1230 In_Tree.Config.Linker :=
1231 Path_Name_Type (Attribute.Value.Value);
1233 when Snames.Name_Required_Switches =>
1235 -- Attribute Linker'Required_Switches: the minimum
1236 -- options to use when invoking the linker
1239 In_Tree.Config.Minimum_Linker_Options,
1240 From_List => Attribute.Value.Values,
1241 In_Tree => In_Tree);
1243 when Snames.Name_Executable_Suffix =>
1245 -- Attribute Executable_Suffix: the suffix of the
1248 In_Tree.Config.Executable_Suffix :=
1249 Attribute.Value.Value;
1251 when Snames.Name_Library_Builder =>
1253 -- Attribute Library_Builder: the application to invoke
1254 -- to build libraries.
1256 In_Tree.Config.Library_Builder :=
1257 Path_Name_Type (Attribute.Value.Value);
1259 when Snames.Name_Archive_Builder =>
1261 -- Attribute Archive_Builder: the archive builder
1262 -- (usually "ar") and its minimum options (usually "cr").
1264 List := Attribute.Value.Values;
1266 if List = Nil_String then
1268 ("archive builder cannot be null",
1269 Attribute.Value.Location);
1272 Put (Into_List => In_Tree.Config.Archive_Builder,
1274 In_Tree => In_Tree);
1276 when Snames.Name_Archive_Indexer =>
1278 -- Attribute Archive_Indexer: the optional archive
1279 -- indexer (usually "ranlib") with its minimum options
1282 List := Attribute.Value.Values;
1284 if List = Nil_String then
1286 ("archive indexer cannot be null",
1287 Attribute.Value.Location);
1290 Put (Into_List => In_Tree.Config.Archive_Indexer,
1292 In_Tree => In_Tree);
1294 when Snames.Name_Library_Partial_Linker =>
1296 -- Attribute Library_Partial_Linker: the optional linker
1297 -- driver with its minimum options, to partially link
1300 List := Attribute.Value.Values;
1302 if List = Nil_String then
1304 ("partial linker cannot be null",
1305 Attribute.Value.Location);
1308 Put (Into_List => In_Tree.Config.Lib_Partial_Linker,
1310 In_Tree => In_Tree);
1312 when Snames.Name_Archive_Suffix =>
1313 In_Tree.Config.Archive_Suffix :=
1314 File_Name_Type (Attribute.Value.Value);
1316 when Snames.Name_Linker_Executable_Option =>
1318 -- Attribute Linker_Executable_Option: optional options
1319 -- to specify an executable name. Defaults to "-o".
1321 List := Attribute.Value.Values;
1323 if List = Nil_String then
1325 ("linker executable option cannot be null",
1326 Attribute.Value.Location);
1330 In_Tree.Config.Linker_Executable_Option,
1332 In_Tree => In_Tree);
1334 when Snames.Name_Linker_Lib_Dir_Option =>
1336 -- Attribute Linker_Lib_Dir_Option: optional options
1337 -- to specify a library search directory. Defaults to
1340 Get_Name_String (Attribute.Value.Value);
1342 if Name_Len = 0 then
1344 ("linker library directory option cannot be empty",
1345 Attribute.Value.Location);
1348 In_Tree.Config.Linker_Lib_Dir_Option :=
1349 Attribute.Value.Value;
1351 when Snames.Name_Linker_Lib_Name_Option =>
1353 -- Attribute Linker_Lib_Name_Option: optional options
1354 -- to specify the name of a library to be linked in.
1355 -- Defaults to "-l".
1357 Get_Name_String (Attribute.Value.Value);
1359 if Name_Len = 0 then
1361 ("linker library name option cannot be empty",
1362 Attribute.Value.Location);
1365 In_Tree.Config.Linker_Lib_Name_Option :=
1366 Attribute.Value.Value;
1368 when Snames.Name_Run_Path_Option =>
1370 -- Attribute Run_Path_Option: optional options to
1371 -- specify a path for libraries.
1373 List := Attribute.Value.Values;
1375 if List /= Nil_String then
1376 Put (Into_List => In_Tree.Config.Run_Path_Option,
1378 In_Tree => In_Tree);
1381 when Snames.Name_Library_Support =>
1383 pragma Unsuppress (All_Checks);
1385 In_Tree.Config.Lib_Support :=
1386 Library_Support'Value (Get_Name_String
1387 (Attribute.Value.Value));
1389 when Constraint_Error =>
1391 ("invalid value """ &
1392 Get_Name_String (Attribute.Value.Value) &
1393 """ for Library_Support",
1394 Attribute.Value.Location);
1397 when Snames.Name_Shared_Library_Prefix =>
1398 In_Tree.Config.Shared_Lib_Prefix :=
1399 File_Name_Type (Attribute.Value.Value);
1401 when Snames.Name_Shared_Library_Suffix =>
1402 In_Tree.Config.Shared_Lib_Suffix :=
1403 File_Name_Type (Attribute.Value.Value);
1405 when Snames.Name_Symbolic_Link_Supported =>
1407 pragma Unsuppress (All_Checks);
1409 In_Tree.Config.Symbolic_Link_Supported :=
1410 Boolean'Value (Get_Name_String
1411 (Attribute.Value.Value));
1413 when Constraint_Error =>
1415 ("invalid value """ &
1416 Get_Name_String (Attribute.Value.Value) &
1417 """ for Symbolic_Link_Supported",
1418 Attribute.Value.Location);
1421 when Snames.Name_Library_Major_Minor_Id_Supported =>
1423 pragma Unsuppress (All_Checks);
1425 In_Tree.Config.Lib_Maj_Min_Id_Supported :=
1426 Boolean'Value (Get_Name_String
1427 (Attribute.Value.Value));
1429 when Constraint_Error =>
1431 ("invalid value """ &
1432 Get_Name_String (Attribute.Value.Value) &
1433 """ for Library_Major_Minor_Id_Supported",
1434 Attribute.Value.Location);
1437 when Snames.Name_Library_Auto_Init_Supported =>
1439 pragma Unsuppress (All_Checks);
1441 In_Tree.Config.Auto_Init_Supported :=
1442 Boolean'Value (Get_Name_String
1443 (Attribute.Value.Value));
1445 when Constraint_Error =>
1447 ("invalid value """ &
1448 Get_Name_String (Attribute.Value.Value) &
1449 """ for Library_Auto_Init_Supported",
1450 Attribute.Value.Location);
1453 when Snames.Name_Shared_Library_Minimum_Switches =>
1454 List := Attribute.Value.Values;
1456 if List /= Nil_String then
1458 In_Tree.Config.Shared_Lib_Min_Options,
1460 In_Tree => In_Tree);
1463 when Snames.Name_Library_Version_Switches =>
1464 List := Attribute.Value.Values;
1466 if List /= Nil_String then
1468 In_Tree.Config.Lib_Version_Options,
1470 In_Tree => In_Tree);
1478 Attribute_Id := Attribute.Next;
1480 end Process_Attributes;
1483 Error_Report := Report_Error;
1488 -- Make sure there are no projects in the data structure
1490 Project_Table.Set_Last (In_Tree.Projects, No_Project);
1493 Processed_Projects.Reset;
1495 -- And process the main project and all of the projects it depends on,
1499 (Project => Project,
1501 From_Project_Node => From_Project_Node,
1502 From_Project_Node_Tree => From_Project_Node_Tree,
1503 Extended_By => No_Project);
1505 if not In_Configuration then
1507 if Project /= No_Project then
1509 (In_Tree, Project, Follow_Links, When_No_Sources);
1512 -- If main project is an extending all project, set the object
1513 -- directory of all virtual extending projects to the object
1514 -- directory of the main project.
1516 if Project /= No_Project
1518 Is_Extending_All (From_Project_Node, From_Project_Node_Tree)
1521 Object_Dir : constant Path_Name_Type :=
1522 In_Tree.Projects.Table
1523 (Project).Object_Directory;
1526 Project_Table.First .. Project_Table.Last (In_Tree.Projects)
1528 if In_Tree.Projects.Table (Index).Virtual then
1529 In_Tree.Projects.Table (Index).Object_Directory :=
1536 -- Check that no extending project shares its object directory with
1537 -- the project(s) it extends.
1539 if Project /= No_Project then
1541 Project_Table.First .. Project_Table.Last (In_Tree.Projects)
1543 Extending := In_Tree.Projects.Table (Proj).Extended_By;
1545 if Extending /= No_Project then
1546 Obj_Dir := In_Tree.Projects.Table (Proj).Object_Directory;
1548 -- Check that a project being extended does not share its
1549 -- object directory with any project that extends it,
1550 -- directly or indirectly, including a virtual extending
1553 -- Start with the project directly extending it
1555 Extending2 := Extending;
1556 while Extending2 /= No_Project loop
1557 if In_Tree.Projects.Table (Extending2).Ada_Sources /=
1560 In_Tree.Projects.Table (Extending2).Object_Directory =
1563 if In_Tree.Projects.Table (Extending2).Virtual then
1565 In_Tree.Projects.Table (Proj).Display_Name;
1567 if Error_Report = null then
1569 ("project %% cannot be extended by a virtual" &
1570 " project with the same object directory",
1571 In_Tree.Projects.Table (Proj).Location);
1575 Get_Name_String (Error_Msg_Name_1) &
1576 """ cannot be extended by a virtual " &
1577 "project with the same object directory",
1583 In_Tree.Projects.Table (Extending2).Display_Name;
1585 In_Tree.Projects.Table (Proj).Display_Name;
1587 if Error_Report = null then
1589 ("project %% cannot extend project %%",
1590 In_Tree.Projects.Table (Extending2).Location);
1592 ("\they share the same object directory",
1593 In_Tree.Projects.Table (Extending2).Location);
1598 Get_Name_String (Error_Msg_Name_1) &
1599 """ cannot extend project """ &
1600 Get_Name_String (Error_Msg_Name_2) & """",
1603 ("they share the same object directory",
1609 -- Continue with the next extending project, if any
1612 In_Tree.Projects.Table (Extending2).Extended_By;
1618 -- Get the global configuration
1620 if Project /= No_Project then
1623 (In_Tree.Projects.Table (Project).Decl.Attributes);
1625 -- Loop through packages ???
1627 Packages := In_Tree.Projects.Table (Project).Decl.Packages;
1628 while Packages /= No_Package loop
1629 Element := In_Tree.Packages.Table (Packages);
1631 case Element.Name is
1632 when Snames.Name_Builder =>
1634 -- Process attributes of package Builder
1636 Process_Attributes (Element.Decl.Attributes);
1638 when Snames.Name_Linker =>
1640 -- Process attributes of package Linker
1642 Process_Attributes (Element.Decl.Attributes);
1648 Packages := Element.Next;
1654 Total_Errors_Detected = 0
1656 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
1659 -------------------------------
1660 -- Process_Declarative_Items --
1661 -------------------------------
1663 procedure Process_Declarative_Items
1664 (Project : Project_Id;
1665 In_Tree : Project_Tree_Ref;
1666 From_Project_Node : Project_Node_Id;
1667 From_Project_Node_Tree : Project_Node_Tree_Ref;
1669 Item : Project_Node_Id)
1671 Current_Declarative_Item : Project_Node_Id;
1672 Current_Item : Project_Node_Id;
1675 -- Loop through declarative items
1677 Current_Item := Empty_Node;
1679 Current_Declarative_Item := Item;
1680 while Current_Declarative_Item /= Empty_Node loop
1686 (Current_Declarative_Item, From_Project_Node_Tree);
1688 -- And set Current_Declarative_Item to the next declarative item
1689 -- ready for the next iteration.
1691 Current_Declarative_Item :=
1692 Next_Declarative_Item
1693 (Current_Declarative_Item, From_Project_Node_Tree);
1695 case Kind_Of (Current_Item, From_Project_Node_Tree) is
1697 when N_Package_Declaration =>
1699 -- Do not process a package declaration that should be ignored
1701 if Expression_Kind_Of
1702 (Current_Item, From_Project_Node_Tree) /= Ignored
1704 -- Create the new package
1706 Package_Table.Increment_Last (In_Tree.Packages);
1709 New_Pkg : constant Package_Id :=
1710 Package_Table.Last (In_Tree.Packages);
1711 The_New_Package : Package_Element;
1713 Project_Of_Renamed_Package :
1714 constant Project_Node_Id :=
1715 Project_Of_Renamed_Package_Of
1716 (Current_Item, From_Project_Node_Tree);
1719 -- Set the name of the new package
1721 The_New_Package.Name :=
1722 Name_Of (Current_Item, From_Project_Node_Tree);
1724 -- Insert the new package in the appropriate list
1726 if Pkg /= No_Package then
1727 The_New_Package.Next :=
1728 In_Tree.Packages.Table (Pkg).Decl.Packages;
1729 In_Tree.Packages.Table (Pkg).Decl.Packages :=
1732 The_New_Package.Next :=
1733 In_Tree.Projects.Table (Project).Decl.Packages;
1734 In_Tree.Projects.Table (Project).Decl.Packages :=
1738 In_Tree.Packages.Table (New_Pkg) :=
1741 if Project_Of_Renamed_Package /= Empty_Node then
1746 Project_Name : constant Name_Id :=
1748 (Project_Of_Renamed_Package,
1749 From_Project_Node_Tree);
1752 constant Project_Id :=
1753 Imported_Or_Extended_Project_From
1754 (Project, In_Tree, Project_Name);
1756 Renamed_Package : constant Package_Id :=
1758 (Renamed_Project, In_Tree,
1761 From_Project_Node_Tree));
1764 -- For a renamed package, copy the declarations of
1765 -- the renamed package, but set all the locations
1766 -- to the location of the package name in the
1767 -- renaming declaration.
1769 Copy_Package_Declarations
1771 In_Tree.Packages.Table (Renamed_Package).Decl,
1773 In_Tree.Packages.Table (New_Pkg).Decl,
1776 (Current_Item, From_Project_Node_Tree),
1777 In_Tree => In_Tree);
1780 -- Standard package declaration, not renaming
1783 -- Set the default values of the attributes
1787 In_Tree.Projects.Table (Project).Name,
1789 In_Tree.Packages.Table (New_Pkg).Decl,
1792 (Current_Item, From_Project_Node_Tree)),
1793 Project_Level => False);
1795 -- And process declarative items of the new package
1797 Process_Declarative_Items
1798 (Project => Project,
1800 From_Project_Node => From_Project_Node,
1801 From_Project_Node_Tree => From_Project_Node_Tree,
1804 First_Declarative_Item_Of
1805 (Current_Item, From_Project_Node_Tree));
1810 when N_String_Type_Declaration =>
1812 -- There is nothing to process
1816 when N_Attribute_Declaration |
1817 N_Typed_Variable_Declaration |
1818 N_Variable_Declaration =>
1820 if Expression_Of (Current_Item, From_Project_Node_Tree) =
1824 -- It must be a full associative array attribute declaration
1827 Current_Item_Name : constant Name_Id :=
1830 From_Project_Node_Tree);
1831 -- The name of the attribute
1833 New_Array : Array_Id;
1834 -- The new associative array created
1836 Orig_Array : Array_Id;
1837 -- The associative array value
1839 Orig_Project_Name : Name_Id := No_Name;
1840 -- The name of the project where the associative array
1843 Orig_Project : Project_Id := No_Project;
1844 -- The id of the project where the associative array
1847 Orig_Package_Name : Name_Id := No_Name;
1848 -- The name of the package, if any, where the associative
1851 Orig_Package : Package_Id := No_Package;
1852 -- The id of the package, if any, where the associative
1855 New_Element : Array_Element_Id := No_Array_Element;
1856 -- Id of a new array element created
1858 Prev_Element : Array_Element_Id := No_Array_Element;
1859 -- Last new element id created
1861 Orig_Element : Array_Element_Id := No_Array_Element;
1862 -- Current array element in the original associative
1865 Next_Element : Array_Element_Id := No_Array_Element;
1866 -- Id of the array element that follows the new element.
1867 -- This is not always nil, because values for the
1868 -- associative array attribute may already have been
1869 -- declared, and the array elements declared are reused.
1872 -- First, find if the associative array attribute already
1873 -- has elements declared.
1875 if Pkg /= No_Package then
1876 New_Array := In_Tree.Packages.Table
1880 New_Array := In_Tree.Projects.Table
1881 (Project).Decl.Arrays;
1884 while New_Array /= No_Array
1885 and then In_Tree.Arrays.Table (New_Array).Name /=
1888 New_Array := In_Tree.Arrays.Table (New_Array).Next;
1891 -- If the attribute has never been declared add new entry
1892 -- in the arrays of the project/package and link it.
1894 if New_Array = No_Array then
1895 Array_Table.Increment_Last (In_Tree.Arrays);
1896 New_Array := Array_Table.Last (In_Tree.Arrays);
1898 if Pkg /= No_Package then
1899 In_Tree.Arrays.Table (New_Array) :=
1900 (Name => Current_Item_Name,
1901 Value => No_Array_Element,
1903 In_Tree.Packages.Table (Pkg).Decl.Arrays);
1905 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1909 In_Tree.Arrays.Table (New_Array) :=
1910 (Name => Current_Item_Name,
1911 Value => No_Array_Element,
1913 In_Tree.Projects.Table (Project).Decl.Arrays);
1915 In_Tree.Projects.Table (Project).Decl.Arrays :=
1920 -- Find the project where the value is declared
1922 Orig_Project_Name :=
1924 (Associative_Project_Of
1925 (Current_Item, From_Project_Node_Tree),
1926 From_Project_Node_Tree);
1928 for Index in Project_Table.First ..
1932 if In_Tree.Projects.Table (Index).Name =
1935 Orig_Project := Index;
1940 pragma Assert (Orig_Project /= No_Project,
1941 "original project not found");
1943 if Associative_Package_Of
1944 (Current_Item, From_Project_Node_Tree) = Empty_Node
1947 In_Tree.Projects.Table
1948 (Orig_Project).Decl.Arrays;
1951 -- If in a package, find the package where the
1952 -- value is declared.
1954 Orig_Package_Name :=
1956 (Associative_Package_Of
1957 (Current_Item, From_Project_Node_Tree),
1958 From_Project_Node_Tree);
1961 In_Tree.Projects.Table
1962 (Orig_Project).Decl.Packages;
1963 pragma Assert (Orig_Package /= No_Package,
1964 "original package not found");
1966 while In_Tree.Packages.Table
1967 (Orig_Package).Name /= Orig_Package_Name
1969 Orig_Package := In_Tree.Packages.Table
1970 (Orig_Package).Next;
1971 pragma Assert (Orig_Package /= No_Package,
1972 "original package not found");
1976 In_Tree.Packages.Table
1977 (Orig_Package).Decl.Arrays;
1980 -- Now look for the array
1982 while Orig_Array /= No_Array and then
1983 In_Tree.Arrays.Table (Orig_Array).Name /=
1986 Orig_Array := In_Tree.Arrays.Table
1990 if Orig_Array = No_Array then
1991 if Error_Report = null then
1993 ("associative array value cannot be found",
1995 (Current_Item, From_Project_Node_Tree));
1999 ("associative array value cannot be found",
2005 In_Tree.Arrays.Table (Orig_Array).Value;
2007 -- Copy each array element
2009 while Orig_Element /= No_Array_Element loop
2011 -- Case of first element
2013 if Prev_Element = No_Array_Element then
2015 -- And there is no array element declared yet,
2016 -- create a new first array element.
2018 if In_Tree.Arrays.Table (New_Array).Value =
2021 Array_Element_Table.Increment_Last
2022 (In_Tree.Array_Elements);
2023 New_Element := Array_Element_Table.Last
2024 (In_Tree.Array_Elements);
2025 In_Tree.Arrays.Table
2026 (New_Array).Value := New_Element;
2027 Next_Element := No_Array_Element;
2029 -- Otherwise, the new element is the first
2032 New_Element := In_Tree.Arrays.
2033 Table (New_Array).Value;
2035 In_Tree.Array_Elements.Table
2039 -- Otherwise, reuse an existing element, or create
2040 -- one if necessary.
2044 In_Tree.Array_Elements.Table
2045 (Prev_Element).Next;
2047 if Next_Element = No_Array_Element then
2048 Array_Element_Table.Increment_Last
2049 (In_Tree.Array_Elements);
2050 New_Element := Array_Element_Table.Last
2051 (In_Tree.Array_Elements);
2054 New_Element := Next_Element;
2056 In_Tree.Array_Elements.Table
2061 -- Copy the value of the element
2063 In_Tree.Array_Elements.Table
2065 In_Tree.Array_Elements.Table
2067 In_Tree.Array_Elements.Table
2068 (New_Element).Value.Project := Project;
2070 -- Adjust the Next link
2072 In_Tree.Array_Elements.Table
2073 (New_Element).Next := Next_Element;
2075 -- Adjust the previous id for the next element
2077 Prev_Element := New_Element;
2079 -- Go to the next element in the original array
2082 In_Tree.Array_Elements.Table
2083 (Orig_Element).Next;
2086 -- Make sure that the array ends here, in case there
2087 -- previously a greater number of elements.
2089 In_Tree.Array_Elements.Table
2090 (New_Element).Next := No_Array_Element;
2094 -- Declarations other that full associative arrays
2098 New_Value : constant Variable_Value :=
2100 (Project => Project,
2102 From_Project_Node => From_Project_Node,
2103 From_Project_Node_Tree => From_Project_Node_Tree,
2108 (Current_Item, From_Project_Node_Tree),
2109 From_Project_Node_Tree),
2112 (Current_Item, From_Project_Node_Tree));
2113 -- The expression value
2115 The_Variable : Variable_Id := No_Variable;
2117 Current_Item_Name : constant Name_Id :=
2118 Name_Of (Current_Item, From_Project_Node_Tree);
2121 -- Process a typed variable declaration
2123 if Kind_Of (Current_Item, From_Project_Node_Tree) =
2124 N_Typed_Variable_Declaration
2126 -- Report an error for an empty string
2128 if New_Value.Value = Empty_String then
2130 Name_Of (Current_Item, From_Project_Node_Tree);
2132 if Error_Report = null then
2134 ("no value defined for %%",
2136 (Current_Item, From_Project_Node_Tree));
2140 ("no value defined for " &
2141 Get_Name_String (Error_Msg_Name_1),
2147 Current_String : Project_Node_Id :=
2148 First_Literal_String
2151 From_Project_Node_Tree),
2152 From_Project_Node_Tree);
2155 -- Loop through all the valid strings for the
2156 -- string type and compare to the string value.
2158 while Current_String /= Empty_Node
2161 (Current_String, From_Project_Node_Tree) /=
2166 (Current_String, From_Project_Node_Tree);
2169 -- Report an error if the string value is not
2170 -- one for the string type.
2172 if Current_String = Empty_Node then
2173 Error_Msg_Name_1 := New_Value.Value;
2176 (Current_Item, From_Project_Node_Tree);
2178 if Error_Report = null then
2180 ("value %% is illegal " &
2181 "for typed string %%",
2184 From_Project_Node_Tree));
2189 Get_Name_String (Error_Msg_Name_1) &
2190 """ is illegal for typed string """ &
2191 Get_Name_String (Error_Msg_Name_2) &
2200 if Kind_Of (Current_Item, From_Project_Node_Tree) /=
2201 N_Attribute_Declaration
2203 Associative_Array_Index_Of
2204 (Current_Item, From_Project_Node_Tree) = No_Name
2206 -- Case of a variable declaration or of a not
2207 -- associative array attribute.
2209 -- First, find the list where to find the variable
2212 if Kind_Of (Current_Item, From_Project_Node_Tree) =
2213 N_Attribute_Declaration
2215 if Pkg /= No_Package then
2217 In_Tree.Packages.Table
2218 (Pkg).Decl.Attributes;
2221 In_Tree.Projects.Table
2222 (Project).Decl.Attributes;
2226 if Pkg /= No_Package then
2228 In_Tree.Packages.Table
2229 (Pkg).Decl.Variables;
2232 In_Tree.Projects.Table
2233 (Project).Decl.Variables;
2238 -- Loop through the list, to find if it has already
2241 while The_Variable /= No_Variable
2243 In_Tree.Variable_Elements.Table
2244 (The_Variable).Name /= Current_Item_Name
2247 In_Tree.Variable_Elements.Table
2248 (The_Variable).Next;
2251 -- If it has not been declared, create a new entry
2254 if The_Variable = No_Variable then
2256 -- All single string attribute should already have
2257 -- been declared with a default empty string value.
2260 (Kind_Of (Current_Item, From_Project_Node_Tree) /=
2261 N_Attribute_Declaration,
2262 "illegal attribute declaration");
2264 Variable_Element_Table.Increment_Last
2265 (In_Tree.Variable_Elements);
2266 The_Variable := Variable_Element_Table.Last
2267 (In_Tree.Variable_Elements);
2269 -- Put the new variable in the appropriate list
2271 if Pkg /= No_Package then
2272 In_Tree.Variable_Elements.Table (The_Variable) :=
2274 In_Tree.Packages.Table
2275 (Pkg).Decl.Variables,
2276 Name => Current_Item_Name,
2277 Value => New_Value);
2278 In_Tree.Packages.Table
2279 (Pkg).Decl.Variables := The_Variable;
2282 In_Tree.Variable_Elements.Table (The_Variable) :=
2284 In_Tree.Projects.Table
2285 (Project).Decl.Variables,
2286 Name => Current_Item_Name,
2287 Value => New_Value);
2288 In_Tree.Projects.Table
2289 (Project).Decl.Variables :=
2293 -- If the variable/attribute has already been
2294 -- declared, just change the value.
2297 In_Tree.Variable_Elements.Table
2298 (The_Variable).Value :=
2304 -- Associative array attribute
2306 -- Get the string index
2309 (Associative_Array_Index_Of
2310 (Current_Item, From_Project_Node_Tree));
2312 -- Put in lower case, if necessary
2315 (Current_Item, From_Project_Node_Tree)
2317 GNAT.Case_Util.To_Lower
2318 (Name_Buffer (1 .. Name_Len));
2322 The_Array : Array_Id;
2324 The_Array_Element : Array_Element_Id :=
2327 Index_Name : constant Name_Id := Name_Find;
2328 -- The name id of the index
2331 -- Look for the array in the appropriate list
2333 if Pkg /= No_Package then
2334 The_Array := In_Tree.Packages.Table
2338 The_Array := In_Tree.Projects.Table
2339 (Project).Decl.Arrays;
2343 The_Array /= No_Array
2344 and then In_Tree.Arrays.Table
2345 (The_Array).Name /= Current_Item_Name
2347 The_Array := In_Tree.Arrays.Table
2351 -- If the array cannot be found, create a new
2352 -- entry in the list. As The_Array_Element is
2353 -- initialized to No_Array_Element, a new element
2354 -- will be created automatically later.
2356 if The_Array = No_Array then
2357 Array_Table.Increment_Last
2359 The_Array := Array_Table.Last
2362 if Pkg /= No_Package then
2363 In_Tree.Arrays.Table
2365 (Name => Current_Item_Name,
2366 Value => No_Array_Element,
2368 In_Tree.Packages.Table
2371 In_Tree.Packages.Table
2372 (Pkg).Decl.Arrays :=
2376 In_Tree.Arrays.Table
2378 (Name => Current_Item_Name,
2379 Value => No_Array_Element,
2381 In_Tree.Projects.Table
2382 (Project).Decl.Arrays);
2384 In_Tree.Projects.Table
2385 (Project).Decl.Arrays :=
2389 -- Otherwise, initialize The_Array_Element as the
2390 -- head of the element list.
2393 The_Array_Element :=
2394 In_Tree.Arrays.Table
2398 -- Look in the list, if any, to find an element
2399 -- with the same index.
2401 while The_Array_Element /= No_Array_Element
2403 In_Tree.Array_Elements.Table
2404 (The_Array_Element).Index /= Index_Name
2406 The_Array_Element :=
2407 In_Tree.Array_Elements.Table
2408 (The_Array_Element).Next;
2411 -- If no such element were found, create a new
2412 -- one and insert it in the element list, with
2413 -- the propoer value.
2415 if The_Array_Element = No_Array_Element then
2416 Array_Element_Table.Increment_Last
2417 (In_Tree.Array_Elements);
2418 The_Array_Element := Array_Element_Table.Last
2419 (In_Tree.Array_Elements);
2421 In_Tree.Array_Elements.Table
2422 (The_Array_Element) :=
2423 (Index => Index_Name,
2426 (Current_Item, From_Project_Node_Tree),
2427 Index_Case_Sensitive =>
2428 not Case_Insensitive
2429 (Current_Item, From_Project_Node_Tree),
2431 Next => In_Tree.Arrays.Table
2433 In_Tree.Arrays.Table
2434 (The_Array).Value := The_Array_Element;
2436 -- An element with the same index already exists,
2437 -- just replace its value with the new one.
2440 In_Tree.Array_Elements.Table
2441 (The_Array_Element).Value := New_Value;
2448 when N_Case_Construction =>
2450 The_Project : Project_Id := Project;
2451 -- The id of the project of the case variable
2453 The_Package : Package_Id := Pkg;
2454 -- The id of the package, if any, of the case variable
2456 The_Variable : Variable_Value := Nil_Variable_Value;
2457 -- The case variable
2459 Case_Value : Name_Id := No_Name;
2460 -- The case variable value
2462 Case_Item : Project_Node_Id := Empty_Node;
2463 Choice_String : Project_Node_Id := Empty_Node;
2464 Decl_Item : Project_Node_Id := Empty_Node;
2468 Variable_Node : constant Project_Node_Id :=
2469 Case_Variable_Reference_Of
2471 From_Project_Node_Tree);
2473 Var_Id : Variable_Id := No_Variable;
2474 Name : Name_Id := No_Name;
2477 -- If a project were specified for the case variable,
2481 (Variable_Node, From_Project_Node_Tree) /= Empty_Node
2486 (Variable_Node, From_Project_Node_Tree),
2487 From_Project_Node_Tree);
2489 Imported_Or_Extended_Project_From
2490 (Project, In_Tree, Name);
2493 -- If a package were specified for the case variable,
2497 (Variable_Node, From_Project_Node_Tree) /= Empty_Node
2502 (Variable_Node, From_Project_Node_Tree),
2503 From_Project_Node_Tree);
2505 Package_From (The_Project, In_Tree, Name);
2508 Name := Name_Of (Variable_Node, From_Project_Node_Tree);
2510 -- First, look for the case variable into the package,
2513 if The_Package /= No_Package then
2514 Var_Id := In_Tree.Packages.Table
2515 (The_Package).Decl.Variables;
2517 Name_Of (Variable_Node, From_Project_Node_Tree);
2518 while Var_Id /= No_Variable
2520 In_Tree.Variable_Elements.Table
2521 (Var_Id).Name /= Name
2523 Var_Id := In_Tree.Variable_Elements.
2524 Table (Var_Id).Next;
2528 -- If not found in the package, or if there is no
2529 -- package, look at the project level.
2531 if Var_Id = No_Variable
2534 (Variable_Node, From_Project_Node_Tree) = Empty_Node
2536 Var_Id := In_Tree.Projects.Table
2537 (The_Project).Decl.Variables;
2538 while Var_Id /= No_Variable
2540 In_Tree.Variable_Elements.Table
2541 (Var_Id).Name /= Name
2543 Var_Id := In_Tree.Variable_Elements.
2544 Table (Var_Id).Next;
2548 if Var_Id = No_Variable then
2550 -- Should never happen, because this has already been
2551 -- checked during parsing.
2553 Write_Line ("variable """ &
2554 Get_Name_String (Name) &
2556 raise Program_Error;
2559 -- Get the case variable
2561 The_Variable := In_Tree.Variable_Elements.
2562 Table (Var_Id).Value;
2564 if The_Variable.Kind /= Single then
2566 -- Should never happen, because this has already been
2567 -- checked during parsing.
2569 Write_Line ("variable""" &
2570 Get_Name_String (Name) &
2571 """ is not a single string variable");
2572 raise Program_Error;
2575 -- Get the case variable value
2576 Case_Value := The_Variable.Value;
2579 -- Now look into all the case items of the case construction
2582 First_Case_Item_Of (Current_Item, From_Project_Node_Tree);
2584 while Case_Item /= Empty_Node loop
2586 First_Choice_Of (Case_Item, From_Project_Node_Tree);
2588 -- When Choice_String is nil, it means that it is
2589 -- the "when others =>" alternative.
2591 if Choice_String = Empty_Node then
2593 First_Declarative_Item_Of
2594 (Case_Item, From_Project_Node_Tree);
2595 exit Case_Item_Loop;
2598 -- Look into all the alternative of this case item
2601 while Choice_String /= Empty_Node loop
2604 (Choice_String, From_Project_Node_Tree)
2607 First_Declarative_Item_Of
2608 (Case_Item, From_Project_Node_Tree);
2609 exit Case_Item_Loop;
2614 (Choice_String, From_Project_Node_Tree);
2615 end loop Choice_Loop;
2618 Next_Case_Item (Case_Item, From_Project_Node_Tree);
2619 end loop Case_Item_Loop;
2621 -- If there is an alternative, then we process it
2623 if Decl_Item /= Empty_Node then
2624 Process_Declarative_Items
2625 (Project => Project,
2627 From_Project_Node => From_Project_Node,
2628 From_Project_Node_Tree => From_Project_Node_Tree,
2636 -- Should never happen
2638 Write_Line ("Illegal declarative item: " &
2639 Project_Node_Kind'Image
2641 (Current_Item, From_Project_Node_Tree)));
2642 raise Program_Error;
2645 end Process_Declarative_Items;
2647 ---------------------
2648 -- Recursive_Check --
2649 ---------------------
2651 procedure Recursive_Check
2652 (Project : Project_Id;
2653 In_Tree : Project_Tree_Ref;
2654 Follow_Links : Boolean;
2655 When_No_Sources : Error_Warning)
2657 Data : Project_Data;
2658 Imported_Project_List : Project_List := Empty_Project_List;
2661 -- Do nothing if Project is No_Project, or Project has already
2662 -- been marked as checked.
2664 if Project /= No_Project
2665 and then not In_Tree.Projects.Table (Project).Checked
2667 -- Mark project as checked, to avoid infinite recursion in
2668 -- ill-formed trees, where a project imports itself.
2670 In_Tree.Projects.Table (Project).Checked := True;
2672 Data := In_Tree.Projects.Table (Project);
2674 -- Call itself for a possible extended project.
2675 -- (if there is no extended project, then nothing happens).
2678 (Data.Extends, In_Tree, Follow_Links, When_No_Sources);
2680 -- Call itself for all imported projects
2682 Imported_Project_List := Data.Imported_Projects;
2683 while Imported_Project_List /= Empty_Project_List loop
2685 (In_Tree.Project_Lists.Table
2686 (Imported_Project_List).Project,
2687 In_Tree, Follow_Links, When_No_Sources);
2688 Imported_Project_List :=
2689 In_Tree.Project_Lists.Table
2690 (Imported_Project_List).Next;
2693 if Verbose_Mode then
2694 Write_Str ("Checking project file """);
2695 Write_Str (Get_Name_String (Data.Name));
2700 (Project, In_Tree, Error_Report, Follow_Links, When_No_Sources);
2702 end Recursive_Check;
2704 -----------------------
2705 -- Recursive_Process --
2706 -----------------------
2708 procedure Recursive_Process
2709 (In_Tree : Project_Tree_Ref;
2710 Project : out Project_Id;
2711 From_Project_Node : Project_Node_Id;
2712 From_Project_Node_Tree : Project_Node_Tree_Ref;
2713 Extended_By : Project_Id)
2715 With_Clause : Project_Node_Id;
2718 if From_Project_Node = Empty_Node then
2719 Project := No_Project;
2723 Processed_Data : Project_Data := Empty_Project (In_Tree);
2724 Imported : Project_List := Empty_Project_List;
2725 Declaration_Node : Project_Node_Id := Empty_Node;
2726 Tref : Source_Buffer_Ptr;
2727 Name : constant Name_Id :=
2729 (From_Project_Node, From_Project_Node_Tree);
2730 Location : Source_Ptr :=
2732 (From_Project_Node, From_Project_Node_Tree);
2735 Project := Processed_Projects.Get (Name);
2737 if Project /= No_Project then
2739 -- Make sure that, when a project is extended, the project id
2740 -- of the project extending it is recorded in its data, even
2741 -- when it has already been processed as an imported project.
2742 -- This is for virtually extended projects.
2744 if Extended_By /= No_Project then
2745 In_Tree.Projects.Table (Project).Extended_By := Extended_By;
2751 Project_Table.Increment_Last (In_Tree.Projects);
2752 Project := Project_Table.Last (In_Tree.Projects);
2753 Processed_Projects.Set (Name, Project);
2755 Processed_Data.Name := Name;
2757 Get_Name_String (Name);
2759 -- If name starts with the virtual prefix, flag the project as
2760 -- being a virtual extending project.
2762 if Name_Len > Virtual_Prefix'Length
2763 and then Name_Buffer (1 .. Virtual_Prefix'Length) =
2766 Processed_Data.Virtual := True;
2767 Processed_Data.Display_Name := Name;
2769 -- If there is no file, for example when the project node tree is
2770 -- built in memory by GPS, the Display_Name cannot be found in
2771 -- the source, so its value is the same as Name.
2773 elsif Location = No_Location then
2774 Processed_Data.Display_Name := Name;
2776 -- Get the spelling of the project name from the project file
2779 Tref := Source_Text (Get_Source_File_Index (Location));
2781 for J in 1 .. Name_Len loop
2782 Name_Buffer (J) := Tref (Location);
2783 Location := Location + 1;
2786 Processed_Data.Display_Name := Name_Find;
2789 Processed_Data.Display_Path_Name :=
2790 Path_Name_Of (From_Project_Node, From_Project_Node_Tree);
2791 Get_Name_String (Processed_Data.Display_Path_Name);
2792 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2793 Processed_Data.Path_Name := Name_Find;
2795 Processed_Data.Location :=
2796 Location_Of (From_Project_Node, From_Project_Node_Tree);
2798 Processed_Data.Display_Directory :=
2799 Directory_Of (From_Project_Node, From_Project_Node_Tree);
2800 Get_Name_String (Processed_Data.Display_Directory);
2801 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2802 Processed_Data.Directory := Name_Find;
2804 Processed_Data.Extended_By := Extended_By;
2810 Processed_Data.Decl,
2811 Prj.Attr.Attribute_First,
2812 Project_Level => True);
2815 First_With_Clause_Of (From_Project_Node, From_Project_Node_Tree);
2816 while With_Clause /= Empty_Node loop
2818 New_Project : Project_Id;
2819 New_Data : Project_Data;
2823 (In_Tree => In_Tree,
2824 Project => New_Project,
2825 From_Project_Node =>
2826 Project_Node_Of (With_Clause, From_Project_Node_Tree),
2827 From_Project_Node_Tree => From_Project_Node_Tree,
2828 Extended_By => No_Project);
2830 In_Tree.Projects.Table (New_Project);
2832 -- If we were the first project to import it,
2833 -- set First_Referred_By to us.
2835 if New_Data.First_Referred_By = No_Project then
2836 New_Data.First_Referred_By := Project;
2837 In_Tree.Projects.Table (New_Project) :=
2841 -- Add this project to our list of imported projects
2843 Project_List_Table.Increment_Last
2844 (In_Tree.Project_Lists);
2845 In_Tree.Project_Lists.Table
2846 (Project_List_Table.Last
2847 (In_Tree.Project_Lists)) :=
2848 (Project => New_Project, Next => Empty_Project_List);
2850 -- Imported is the id of the last imported project.
2851 -- If it is nil, then this imported project is our first.
2853 if Imported = Empty_Project_List then
2854 Processed_Data.Imported_Projects :=
2855 Project_List_Table.Last
2856 (In_Tree.Project_Lists);
2859 In_Tree.Project_Lists.Table
2860 (Imported).Next := Project_List_Table.Last
2861 (In_Tree.Project_Lists);
2864 Imported := Project_List_Table.Last
2865 (In_Tree.Project_Lists);
2868 Next_With_Clause_Of (With_Clause, From_Project_Node_Tree);
2873 Project_Declaration_Of
2874 (From_Project_Node, From_Project_Node_Tree);
2877 (In_Tree => In_Tree,
2878 Project => Processed_Data.Extends,
2879 From_Project_Node =>
2881 (Declaration_Node, From_Project_Node_Tree),
2882 From_Project_Node_Tree => From_Project_Node_Tree,
2883 Extended_By => Project);
2885 In_Tree.Projects.Table (Project) := Processed_Data;
2887 Process_Declarative_Items
2888 (Project => Project,
2890 From_Project_Node => From_Project_Node,
2891 From_Project_Node_Tree => From_Project_Node_Tree,
2894 First_Declarative_Item_Of
2895 (Declaration_Node, From_Project_Node_Tree));
2897 -- If it is an extending project, inherit all packages
2898 -- from the extended project that are not explicitely defined
2899 -- or renamed. Also inherit the languages, if attribute Languages
2900 -- is not explicitely defined.
2902 if Processed_Data.Extends /= No_Project then
2903 Processed_Data := In_Tree.Projects.Table (Project);
2906 Extended_Pkg : Package_Id :=
2907 In_Tree.Projects.Table
2908 (Processed_Data.Extends).Decl.Packages;
2909 Current_Pkg : Package_Id;
2910 Element : Package_Element;
2911 First : constant Package_Id :=
2912 Processed_Data.Decl.Packages;
2913 Attribute1 : Variable_Id;
2914 Attribute2 : Variable_Id;
2915 Attr_Value1 : Variable;
2916 Attr_Value2 : Variable;
2919 while Extended_Pkg /= No_Package loop
2921 In_Tree.Packages.Table (Extended_Pkg);
2923 Current_Pkg := First;
2926 exit when Current_Pkg = No_Package
2927 or else In_Tree.Packages.Table
2928 (Current_Pkg).Name = Element.Name;
2929 Current_Pkg := In_Tree.Packages.Table
2933 if Current_Pkg = No_Package then
2934 Package_Table.Increment_Last
2936 Current_Pkg := Package_Table.Last
2938 In_Tree.Packages.Table (Current_Pkg) :=
2939 (Name => Element.Name,
2940 Decl => Element.Decl,
2941 Parent => No_Package,
2942 Next => Processed_Data.Decl.Packages);
2943 Processed_Data.Decl.Packages := Current_Pkg;
2946 Extended_Pkg := Element.Next;
2949 -- Check if attribute Languages is declared in the
2950 -- extending project.
2952 Attribute1 := Processed_Data.Decl.Attributes;
2953 while Attribute1 /= No_Variable loop
2954 Attr_Value1 := In_Tree.Variable_Elements.
2956 exit when Attr_Value1.Name = Snames.Name_Languages;
2957 Attribute1 := Attr_Value1.Next;
2960 if Attribute1 = No_Variable or else
2961 Attr_Value1.Value.Default
2963 -- Attribute Languages is not declared in the extending
2964 -- project. Check if it is declared in the project being
2968 In_Tree.Projects.Table
2969 (Processed_Data.Extends).Decl.Attributes;
2971 while Attribute2 /= No_Variable loop
2972 Attr_Value2 := In_Tree.Variable_Elements.
2974 exit when Attr_Value2.Name = Snames.Name_Languages;
2975 Attribute2 := Attr_Value2.Next;
2978 if Attribute2 /= No_Variable and then
2979 not Attr_Value2.Value.Default
2981 -- As attribute Languages is declared in the project
2982 -- being extended, copy its value for the extending
2985 if Attribute1 = No_Variable then
2986 Variable_Element_Table.Increment_Last
2987 (In_Tree.Variable_Elements);
2988 Attribute1 := Variable_Element_Table.Last
2989 (In_Tree.Variable_Elements);
2990 Attr_Value1.Next := Processed_Data.Decl.Attributes;
2991 Processed_Data.Decl.Attributes := Attribute1;
2994 Attr_Value1.Name := Snames.Name_Languages;
2995 Attr_Value1.Value := Attr_Value2.Value;
2996 In_Tree.Variable_Elements.Table
2997 (Attribute1) := Attr_Value1;
3002 In_Tree.Projects.Table (Project) := Processed_Data;
3006 end Recursive_Process;