1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2010, 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;
36 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
38 with GNAT.Case_Util; use GNAT.Case_Util;
41 package body Prj.Proc is
43 package Processed_Projects is new GNAT.HTable.Simple_HTable
44 (Header_Num => Header_Num,
45 Element => Project_Id,
46 No_Element => No_Project,
50 -- This hash table contains all processed projects
52 package Unit_Htable is new GNAT.HTable.Simple_HTable
53 (Header_Num => Header_Num,
55 No_Element => No_Source,
59 -- This hash table contains all processed projects
61 procedure Add (To_Exp : in out Name_Id; Str : Name_Id);
62 -- Concatenate two strings and returns another string if both
63 -- arguments are not null string.
65 -- In the following procedures, we are expected to guess the meaning of
66 -- the parameters from their names, this is never a good idea, comments
67 -- should be added precisely defining every formal ???
69 procedure Add_Attributes
70 (Project : Project_Id;
71 Project_Name : Name_Id;
72 Project_Dir : Name_Id;
73 In_Tree : Project_Tree_Ref;
74 Decl : in out Declarations;
75 First : Attribute_Node_Id;
76 Project_Level : Boolean);
77 -- Add all attributes, starting with First, with their default values to
78 -- the package or project with declarations Decl.
81 (In_Tree : Project_Tree_Ref;
83 Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
84 Flags : Processing_Flags);
85 -- Set all projects to not checked, then call Recursive_Check for the
86 -- main project Project. Project is set to No_Project if errors occurred.
87 -- Current_Dir is for optimization purposes, avoiding extra system calls.
88 -- If Allow_Duplicate_Basenames, then files with the same base names are
89 -- authorized within a project for source-based languages (never for unit
92 procedure Copy_Package_Declarations
94 To : in out Declarations;
97 In_Tree : Project_Tree_Ref);
98 -- Copy a package declaration From to To for a renamed package. Change the
99 -- locations of all the attributes to New_Loc. When Restricted is
100 -- True, do not copy attributes Body, Spec, Implementation, Specification
101 -- and Linker_Options.
104 (Project : Project_Id;
105 In_Tree : Project_Tree_Ref;
106 Flags : Processing_Flags;
107 From_Project_Node : Project_Node_Id;
108 From_Project_Node_Tree : Project_Node_Tree_Ref;
110 First_Term : Project_Node_Id;
111 Kind : Variable_Kind) return Variable_Value;
112 -- From N_Expression project node From_Project_Node, compute the value
113 -- of an expression and return it as a Variable_Value.
115 function Imported_Or_Extended_Project_From
116 (Project : Project_Id;
117 With_Name : Name_Id) return Project_Id;
118 -- Find an imported or extended project of Project whose name is With_Name
120 function Package_From
121 (Project : Project_Id;
122 In_Tree : Project_Tree_Ref;
123 With_Name : Name_Id) return Package_Id;
124 -- Find the package of Project whose name is With_Name
126 procedure Process_Declarative_Items
127 (Project : Project_Id;
128 In_Tree : Project_Tree_Ref;
129 Flags : Processing_Flags;
130 From_Project_Node : Project_Node_Id;
131 From_Project_Node_Tree : Project_Node_Tree_Ref;
133 Item : Project_Node_Id);
134 -- Process declarative items starting with From_Project_Node, and put them
135 -- in declarations Decl. This is a recursive procedure; it calls itself for
136 -- a package declaration or a case construction.
138 procedure Recursive_Process
139 (In_Tree : Project_Tree_Ref;
140 Project : out Project_Id;
141 Flags : Processing_Flags;
142 From_Project_Node : Project_Node_Id;
143 From_Project_Node_Tree : Project_Node_Tree_Ref;
144 Extended_By : Project_Id);
145 -- Process project with node From_Project_Node in the tree. Do nothing if
146 -- From_Project_Node is Empty_Node. If project has already been processed,
147 -- simply return its project id. Otherwise create a new project id, mark it
148 -- as processed, call itself recursively for all imported projects and a
149 -- extended project, if any. Then process the declarative items of the
152 function Get_Attribute_Index
153 (Tree : Project_Node_Tree_Ref;
154 Attr : Project_Node_Id;
155 Index : Name_Id) return Name_Id;
156 -- Copy the index of the attribute into Name_Buffer, converting to lower
157 -- case if the attribute is case-insensitive.
163 procedure Add (To_Exp : in out Name_Id; Str : Name_Id) is
165 if To_Exp = No_Name or else To_Exp = Empty_String then
167 -- To_Exp is nil or empty. The result is Str
171 -- If Str is nil, then do not change To_Ext
173 elsif Str /= No_Name and then Str /= Empty_String then
175 S : constant String := Get_Name_String (Str);
177 Get_Name_String (To_Exp);
178 Add_Str_To_Name_Buffer (S);
188 procedure Add_Attributes
189 (Project : Project_Id;
190 Project_Name : Name_Id;
191 Project_Dir : Name_Id;
192 In_Tree : Project_Tree_Ref;
193 Decl : in out Declarations;
194 First : Attribute_Node_Id;
195 Project_Level : Boolean)
197 The_Attribute : Attribute_Node_Id := First;
200 while The_Attribute /= Empty_Attribute loop
201 if Attribute_Kind_Of (The_Attribute) = Single then
203 New_Attribute : Variable_Value;
206 case Variable_Kind_Of (The_Attribute) is
208 -- Undefined should not happen
212 (False, "attribute with an undefined kind");
215 -- Single attributes have a default value of empty string
221 Location => No_Location,
223 Value => Empty_String,
226 -- Special cases of <project>'Name and
227 -- <project>'Project_Dir.
229 if Project_Level then
230 if Attribute_Name_Of (The_Attribute) =
233 New_Attribute.Value := Project_Name;
235 elsif Attribute_Name_Of (The_Attribute) =
236 Snames.Name_Project_Dir
238 New_Attribute.Value := Project_Dir;
242 -- List attributes have a default value of nil list
248 Location => No_Location,
250 Values => Nil_String);
254 Variable_Element_Table.Increment_Last
255 (In_Tree.Variable_Elements);
256 In_Tree.Variable_Elements.Table
257 (Variable_Element_Table.Last
258 (In_Tree.Variable_Elements)) :=
259 (Next => Decl.Attributes,
260 Name => Attribute_Name_Of (The_Attribute),
261 Value => New_Attribute);
262 Decl.Attributes := Variable_Element_Table.Last
263 (In_Tree.Variable_Elements);
267 The_Attribute := Next_Attribute (After => The_Attribute);
276 (In_Tree : Project_Tree_Ref;
277 Project : Project_Id;
278 Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
279 Flags : Processing_Flags)
282 Process_Naming_Scheme (In_Tree, Project, Node_Tree, Flags);
284 -- Set the Other_Part field for the units
290 Iter : Source_Iterator;
295 Iter := For_Each_Source (In_Tree);
297 Source1 := Prj.Element (Iter);
298 exit when Source1 = No_Source;
300 if Source1.Unit /= No_Unit_Index then
301 Name := Source1.Unit.Name;
302 Source2 := Unit_Htable.Get (Name);
304 if Source2 = No_Source then
305 Unit_Htable.Set (K => Name, E => Source1);
307 Unit_Htable.Remove (Name);
316 -------------------------------
317 -- Copy_Package_Declarations --
318 -------------------------------
320 procedure Copy_Package_Declarations
321 (From : Declarations;
322 To : in out Declarations;
323 New_Loc : Source_Ptr;
324 Restricted : Boolean;
325 In_Tree : Project_Tree_Ref)
328 V2 : Variable_Id := No_Variable;
331 A2 : Array_Id := No_Array;
333 E1 : Array_Element_Id;
334 E2 : Array_Element_Id := No_Array_Element;
338 -- To avoid references in error messages to attribute declarations in
339 -- an original package that has been renamed, copy all the attribute
340 -- declarations of the package and change all locations to New_Loc,
341 -- the location of the renamed package.
343 -- First single attributes
345 V1 := From.Attributes;
346 while V1 /= No_Variable loop
348 -- Copy the attribute
350 Var := In_Tree.Variable_Elements.Table (V1);
353 -- Do not copy the value of attribute Linker_Options if Restricted
355 if Restricted and then Var.Name = Snames.Name_Linker_Options then
356 Var.Value.Values := Nil_String;
359 -- Remove the Next component
361 Var.Next := No_Variable;
363 -- Change the location to New_Loc
365 Var.Value.Location := New_Loc;
366 Variable_Element_Table.Increment_Last (In_Tree.Variable_Elements);
368 -- Put in new declaration
370 if To.Attributes = No_Variable then
372 Variable_Element_Table.Last (In_Tree.Variable_Elements);
374 In_Tree.Variable_Elements.Table (V2).Next :=
375 Variable_Element_Table.Last (In_Tree.Variable_Elements);
378 V2 := Variable_Element_Table.Last (In_Tree.Variable_Elements);
379 In_Tree.Variable_Elements.Table (V2) := Var;
382 -- Then the associated array attributes
385 while A1 /= No_Array loop
386 Arr := In_Tree.Arrays.Table (A1);
391 (Arr.Name /= Snames.Name_Body and then
392 Arr.Name /= Snames.Name_Spec and then
393 Arr.Name /= Snames.Name_Implementation and then
394 Arr.Name /= Snames.Name_Specification)
396 -- Remove the Next component
398 Arr.Next := No_Array;
399 Array_Table.Increment_Last (In_Tree.Arrays);
401 -- Create new Array declaration
403 if To.Arrays = No_Array then
404 To.Arrays := Array_Table.Last (In_Tree.Arrays);
406 In_Tree.Arrays.Table (A2).Next :=
407 Array_Table.Last (In_Tree.Arrays);
410 A2 := Array_Table.Last (In_Tree.Arrays);
412 -- Don't store the array as its first element has not been set yet
414 -- Copy the array elements of the array
417 Arr.Value := No_Array_Element;
418 while E1 /= No_Array_Element loop
420 -- Copy the array element
422 Elm := In_Tree.Array_Elements.Table (E1);
425 -- Remove the Next component
427 Elm.Next := No_Array_Element;
429 -- Change the location
431 Elm.Value.Location := New_Loc;
432 Array_Element_Table.Increment_Last (In_Tree.Array_Elements);
434 -- Create new array element
436 if Arr.Value = No_Array_Element then
438 Array_Element_Table.Last (In_Tree.Array_Elements);
440 In_Tree.Array_Elements.Table (E2).Next :=
441 Array_Element_Table.Last (In_Tree.Array_Elements);
444 E2 := Array_Element_Table.Last (In_Tree.Array_Elements);
445 In_Tree.Array_Elements.Table (E2) := Elm;
448 -- Finally, store the new array
450 In_Tree.Arrays.Table (A2) := Arr;
453 end Copy_Package_Declarations;
455 -------------------------
456 -- Get_Attribute_Index --
457 -------------------------
459 function Get_Attribute_Index
460 (Tree : Project_Node_Tree_Ref;
461 Attr : Project_Node_Id;
462 Index : Name_Id) return Name_Id
467 if Index = All_Other_Names then
471 Get_Name_String (Index);
472 Lower := Case_Insensitive (Attr, Tree);
474 -- The index is always case insensitive if it does not include any dot.
475 -- ??? Why not use the properties from prj-attr, simply, maybe because
476 -- we don't know whether we have a file as an index?
481 for J in 1 .. Name_Len loop
482 if Name_Buffer (J) = '.' then
490 To_Lower (Name_Buffer (1 .. Name_Len));
495 end Get_Attribute_Index;
502 (Project : Project_Id;
503 In_Tree : Project_Tree_Ref;
504 Flags : Processing_Flags;
505 From_Project_Node : Project_Node_Id;
506 From_Project_Node_Tree : Project_Node_Tree_Ref;
508 First_Term : Project_Node_Id;
509 Kind : Variable_Kind) return Variable_Value
511 The_Term : Project_Node_Id;
512 -- The term in the expression list
514 The_Current_Term : Project_Node_Id := Empty_Node;
515 -- The current term node id
517 Result : Variable_Value (Kind => Kind);
518 -- The returned result
520 Last : String_List_Id := Nil_String;
521 -- Reference to the last string elements in Result, when Kind is List
524 Result.Project := Project;
525 Result.Location := Location_Of (First_Term, From_Project_Node_Tree);
527 -- Process each term of the expression, starting with First_Term
529 The_Term := First_Term;
530 while Present (The_Term) loop
531 The_Current_Term := Current_Term (The_Term, From_Project_Node_Tree);
533 case Kind_Of (The_Current_Term, From_Project_Node_Tree) is
535 when N_Literal_String =>
541 -- Should never happen
543 pragma Assert (False, "Undefined expression kind");
549 (The_Current_Term, From_Project_Node_Tree));
552 (The_Current_Term, From_Project_Node_Tree);
556 String_Element_Table.Increment_Last
557 (In_Tree.String_Elements);
559 if Last = Nil_String then
561 -- This can happen in an expression like () & "toto"
563 Result.Values := String_Element_Table.Last
564 (In_Tree.String_Elements);
567 In_Tree.String_Elements.Table
568 (Last).Next := String_Element_Table.Last
569 (In_Tree.String_Elements);
572 Last := String_Element_Table.Last
573 (In_Tree.String_Elements);
575 In_Tree.String_Elements.Table (Last) :=
576 (Value => String_Value_Of
578 From_Project_Node_Tree),
579 Index => Source_Index_Of
581 From_Project_Node_Tree),
582 Display_Value => No_Name,
583 Location => Location_Of
585 From_Project_Node_Tree),
590 when N_Literal_String_List =>
593 String_Node : Project_Node_Id :=
594 First_Expression_In_List
596 From_Project_Node_Tree);
598 Value : Variable_Value;
601 if Present (String_Node) then
603 -- If String_Node is nil, it is an empty list, there is
610 From_Project_Node => From_Project_Node,
611 From_Project_Node_Tree => From_Project_Node_Tree,
615 (String_Node, From_Project_Node_Tree),
617 String_Element_Table.Increment_Last
618 (In_Tree.String_Elements);
620 if Result.Values = Nil_String then
622 -- This literal string list is the first term in a
623 -- string list expression
626 String_Element_Table.Last (In_Tree.String_Elements);
629 In_Tree.String_Elements.Table
631 String_Element_Table.Last (In_Tree.String_Elements);
635 String_Element_Table.Last (In_Tree.String_Elements);
637 In_Tree.String_Elements.Table (Last) :=
638 (Value => Value.Value,
639 Display_Value => No_Name,
640 Location => Value.Location,
643 Index => Value.Index);
646 -- Add the other element of the literal string list
647 -- one after the other
650 Next_Expression_In_List
651 (String_Node, From_Project_Node_Tree);
653 exit when No (String_Node);
660 From_Project_Node => From_Project_Node,
661 From_Project_Node_Tree => From_Project_Node_Tree,
665 (String_Node, From_Project_Node_Tree),
668 String_Element_Table.Increment_Last
669 (In_Tree.String_Elements);
670 In_Tree.String_Elements.Table
671 (Last).Next := String_Element_Table.Last
672 (In_Tree.String_Elements);
673 Last := String_Element_Table.Last
674 (In_Tree.String_Elements);
675 In_Tree.String_Elements.Table (Last) :=
676 (Value => Value.Value,
677 Display_Value => No_Name,
678 Location => Value.Location,
681 Index => Value.Index);
686 when N_Variable_Reference | N_Attribute_Reference =>
689 The_Project : Project_Id := Project;
690 The_Package : Package_Id := Pkg;
691 The_Name : Name_Id := No_Name;
692 The_Variable_Id : Variable_Id := No_Variable;
693 The_Variable : Variable_Value;
694 Term_Project : constant Project_Node_Id :=
697 From_Project_Node_Tree);
698 Term_Package : constant Project_Node_Id :=
701 From_Project_Node_Tree);
702 Index : Name_Id := No_Name;
705 if Present (Term_Project) and then
706 Term_Project /= From_Project_Node
708 -- This variable or attribute comes from another project
711 Name_Of (Term_Project, From_Project_Node_Tree);
712 The_Project := Imported_Or_Extended_Project_From
714 With_Name => The_Name);
717 if Present (Term_Package) then
719 -- This is an attribute of a package
722 Name_Of (Term_Package, From_Project_Node_Tree);
723 The_Package := The_Project.Decl.Packages;
725 while The_Package /= No_Package
726 and then In_Tree.Packages.Table
727 (The_Package).Name /= The_Name
730 In_Tree.Packages.Table
735 (The_Package /= No_Package,
736 "package not found.");
738 elsif Kind_Of (The_Current_Term, From_Project_Node_Tree) =
739 N_Attribute_Reference
741 The_Package := No_Package;
745 Name_Of (The_Current_Term, From_Project_Node_Tree);
747 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
748 N_Attribute_Reference
751 Associative_Array_Index_Of
752 (The_Current_Term, From_Project_Node_Tree);
755 -- If it is not an associative array attribute
757 if Index = No_Name then
759 -- It is not an associative array attribute
761 if The_Package /= No_Package then
763 -- First, if there is a package, look into the package
765 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
769 In_Tree.Packages.Table
770 (The_Package).Decl.Variables;
773 In_Tree.Packages.Table
774 (The_Package).Decl.Attributes;
777 while The_Variable_Id /= No_Variable
779 In_Tree.Variable_Elements.Table
780 (The_Variable_Id).Name /= The_Name
783 In_Tree.Variable_Elements.Table
784 (The_Variable_Id).Next;
789 if The_Variable_Id = No_Variable then
791 -- If we have not found it, look into the project
793 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
796 The_Variable_Id := The_Project.Decl.Variables;
798 The_Variable_Id := The_Project.Decl.Attributes;
801 while The_Variable_Id /= No_Variable
803 In_Tree.Variable_Elements.Table
804 (The_Variable_Id).Name /= The_Name
807 In_Tree.Variable_Elements.Table
808 (The_Variable_Id).Next;
813 pragma Assert (The_Variable_Id /= No_Variable,
814 "variable or attribute not found");
817 In_Tree.Variable_Elements.Table
818 (The_Variable_Id).Value;
822 -- It is an associative array attribute
825 The_Array : Array_Id := No_Array;
826 The_Element : Array_Element_Id := No_Array_Element;
827 Array_Index : Name_Id := No_Name;
830 if The_Package /= No_Package then
832 In_Tree.Packages.Table
833 (The_Package).Decl.Arrays;
835 The_Array := The_Project.Decl.Arrays;
838 while The_Array /= No_Array
839 and then In_Tree.Arrays.Table
840 (The_Array).Name /= The_Name
842 The_Array := In_Tree.Arrays.Table
846 if The_Array /= No_Array then
847 The_Element := In_Tree.Arrays.Table
851 (From_Project_Node_Tree,
855 while The_Element /= No_Array_Element
857 In_Tree.Array_Elements.Table
858 (The_Element).Index /= Array_Index
861 In_Tree.Array_Elements.Table
867 if The_Element /= No_Array_Element then
869 In_Tree.Array_Elements.Table
873 if Expression_Kind_Of
874 (The_Current_Term, From_Project_Node_Tree) =
880 Location => No_Location,
882 Values => Nil_String);
887 Location => No_Location,
889 Value => Empty_String,
900 -- Should never happen
902 pragma Assert (False, "undefined expression kind");
907 case The_Variable.Kind is
913 Add (Result.Value, The_Variable.Value);
917 -- Should never happen
921 "list cannot appear in single " &
922 "string expression");
927 case The_Variable.Kind is
933 String_Element_Table.Increment_Last
934 (In_Tree.String_Elements);
936 if Last = Nil_String then
938 -- This can happen in an expression such as
942 String_Element_Table.Last
943 (In_Tree.String_Elements);
946 In_Tree.String_Elements.Table
948 String_Element_Table.Last
949 (In_Tree.String_Elements);
953 String_Element_Table.Last
954 (In_Tree.String_Elements);
956 In_Tree.String_Elements.Table (Last) :=
957 (Value => The_Variable.Value,
958 Display_Value => No_Name,
959 Location => Location_Of
961 From_Project_Node_Tree),
969 The_List : String_List_Id :=
973 while The_List /= Nil_String loop
974 String_Element_Table.Increment_Last
975 (In_Tree.String_Elements);
977 if Last = Nil_String then
979 String_Element_Table.Last
985 String_Elements.Table (Last).Next :=
986 String_Element_Table.Last
993 String_Element_Table.Last
994 (In_Tree.String_Elements);
996 In_Tree.String_Elements.Table (Last) :=
998 In_Tree.String_Elements.Table
1000 Display_Value => No_Name,
1004 From_Project_Node_Tree),
1010 In_Tree. String_Elements.Table
1018 when N_External_Value =>
1021 (External_Reference_Of
1022 (The_Current_Term, From_Project_Node_Tree),
1023 From_Project_Node_Tree));
1026 Name : constant Name_Id := Name_Find;
1027 Default : Name_Id := No_Name;
1028 Value : Name_Id := No_Name;
1029 Ext_List : Boolean := False;
1030 Str_List : String_List_Access := null;
1031 Def_Var : Variable_Value;
1033 Default_Node : constant Project_Node_Id :=
1036 From_Project_Node_Tree);
1039 -- If there is a default value for the external reference,
1042 if Present (Default_Node) then
1043 Def_Var := Expression
1044 (Project => Project,
1047 From_Project_Node => From_Project_Node,
1048 From_Project_Node_Tree => From_Project_Node_Tree,
1052 (Default_Node, From_Project_Node_Tree),
1055 if Def_Var /= Nil_Variable_Value then
1056 Default := Def_Var.Value;
1060 Ext_List := Expression_Kind_Of
1062 From_Project_Node_Tree) = List;
1067 (From_Project_Node_Tree, Name, No_Name);
1069 if Value /= No_Name then
1071 Sep : constant String :=
1072 Get_Name_String (Default);
1073 First : Positive := 1;
1075 Done : Boolean := False;
1079 Get_Name_String (Value);
1082 or else Sep'Length = 0
1083 or else Name_Buffer (1 .. Name_Len) = Sep
1088 if not Done and then Name_Len < Sep'Length then
1092 (Name_Buffer (1 .. Name_Len)));
1097 if Name_Buffer (1 .. Sep'Length) = Sep then
1098 First := Sep'Length + 1;
1101 if Name_Len - First + 1 >= Sep'Length
1103 Name_Buffer (Name_Len - Sep'Length + 1 ..
1106 Name_Len := Name_Len - Sep'Length;
1109 if Name_Len = 0 then
1111 new String_List'(1 => new String'(""));
1117 -- Count the number of string
1120 Saved : constant Positive := First;
1128 Name_Buffer (First .. Name_Len),
1132 First := Lst + Sep'Length;
1138 Str_List := new String_List (1 .. Nmb);
1140 -- Populate the string list
1147 Name_Buffer (First .. Name_Len),
1153 (Name_Buffer (First .. Name_Len));
1159 (Name_Buffer (First .. Lst - 1));
1161 First := Lst + Sep'Length;
1173 (From_Project_Node_Tree, Name, Default);
1175 if Value = No_Name then
1176 if not Quiet_Output then
1178 (Flags, "?undefined external reference",
1180 (The_Current_Term, From_Project_Node_Tree),
1184 Value := Empty_String;
1198 Add (Result.Value, Value);
1202 if not Ext_List or else Str_List /= null then
1203 String_Element_Table.Increment_Last
1204 (In_Tree.String_Elements);
1206 if Last = Nil_String then
1208 String_Element_Table.Last
1209 (In_Tree.String_Elements);
1212 In_Tree.String_Elements.Table (Last).Next :=
1213 String_Element_Table.Last
1214 (In_Tree.String_Elements);
1218 String_Element_Table.Last
1219 (In_Tree.String_Elements);
1222 for Ind in Str_List'Range loop
1224 Add_Str_To_Name_Buffer (Str_List (Ind).all);
1226 In_Tree.String_Elements.Table (Last) :=
1228 Display_Value => No_Name,
1232 From_Project_Node_Tree),
1237 if Ind /= Str_List'Last then
1238 String_Element_Table.Increment_Last
1239 (In_Tree.String_Elements);
1240 In_Tree.String_Elements.Table
1242 String_Element_Table.Last
1243 (In_Tree.String_Elements);
1245 String_Element_Table.Last
1246 (In_Tree.String_Elements);
1251 In_Tree.String_Elements.Table (Last) :=
1253 Display_Value => No_Name,
1257 From_Project_Node_Tree),
1268 -- Should never happen
1272 "illegal node kind in an expression");
1273 raise Program_Error;
1277 The_Term := Next_Term (The_Term, From_Project_Node_Tree);
1283 ---------------------------------------
1284 -- Imported_Or_Extended_Project_From --
1285 ---------------------------------------
1287 function Imported_Or_Extended_Project_From
1288 (Project : Project_Id;
1289 With_Name : Name_Id) return Project_Id
1291 List : Project_List;
1292 Result : Project_Id;
1293 Temp_Result : Project_Id;
1296 -- First check if it is the name of an extended project
1298 Result := Project.Extends;
1299 while Result /= No_Project loop
1300 if Result.Name = With_Name then
1303 Result := Result.Extends;
1307 -- Then check the name of each imported project
1309 Temp_Result := No_Project;
1310 List := Project.Imported_Projects;
1311 while List /= null loop
1312 Result := List.Project;
1314 -- If the project is directly imported, then returns its ID
1316 if Result.Name = With_Name then
1320 -- If a project extending the project is imported, then keep this
1321 -- extending project as a possibility. It will be the returned ID
1322 -- if the project is not imported directly.
1328 Proj := Result.Extends;
1329 while Proj /= No_Project loop
1330 if Proj.Name = With_Name then
1331 Temp_Result := Result;
1335 Proj := Proj.Extends;
1342 pragma Assert (Temp_Result /= No_Project, "project not found");
1344 end Imported_Or_Extended_Project_From;
1350 function Package_From
1351 (Project : Project_Id;
1352 In_Tree : Project_Tree_Ref;
1353 With_Name : Name_Id) return Package_Id
1355 Result : Package_Id := Project.Decl.Packages;
1358 -- Check the name of each existing package of Project
1360 while Result /= No_Package
1361 and then In_Tree.Packages.Table (Result).Name /= With_Name
1363 Result := In_Tree.Packages.Table (Result).Next;
1366 if Result = No_Package then
1368 -- Should never happen
1370 Write_Line ("package """ & Get_Name_String (With_Name) &
1372 raise Program_Error;
1384 (In_Tree : Project_Tree_Ref;
1385 Project : out Project_Id;
1386 Success : out Boolean;
1387 From_Project_Node : Project_Node_Id;
1388 From_Project_Node_Tree : Project_Node_Tree_Ref;
1389 Flags : Processing_Flags;
1390 Reset_Tree : Boolean := True)
1393 Process_Project_Tree_Phase_1
1394 (In_Tree => In_Tree,
1397 From_Project_Node => From_Project_Node,
1398 From_Project_Node_Tree => From_Project_Node_Tree,
1400 Reset_Tree => Reset_Tree);
1402 if Project_Qualifier_Of (From_Project_Node, From_Project_Node_Tree) /=
1405 Process_Project_Tree_Phase_2
1406 (In_Tree => In_Tree,
1409 From_Project_Node => From_Project_Node,
1410 From_Project_Node_Tree => From_Project_Node_Tree,
1415 -------------------------------
1416 -- Process_Declarative_Items --
1417 -------------------------------
1419 procedure Process_Declarative_Items
1420 (Project : Project_Id;
1421 In_Tree : Project_Tree_Ref;
1422 Flags : Processing_Flags;
1423 From_Project_Node : Project_Node_Id;
1424 From_Project_Node_Tree : Project_Node_Tree_Ref;
1426 Item : Project_Node_Id)
1428 procedure Check_Or_Set_Typed_Variable
1429 (Value : in out Variable_Value;
1430 Declaration : Project_Node_Id);
1431 -- Check whether Value is valid for this typed variable declaration. If
1432 -- it is an error, the behavior depends on the flags: either an error is
1433 -- reported, or a warning, or nothing. In the last two cases, the value
1434 -- of the variable is set to a valid value, replacing Value.
1436 ---------------------------------
1437 -- Check_Or_Set_Typed_Variable --
1438 ---------------------------------
1440 procedure Check_Or_Set_Typed_Variable
1441 (Value : in out Variable_Value;
1442 Declaration : Project_Node_Id)
1444 Loc : constant Source_Ptr :=
1445 Location_Of (Declaration, From_Project_Node_Tree);
1447 Reset_Value : Boolean := False;
1448 Current_String : Project_Node_Id;
1451 -- Report an error for an empty string
1453 if Value.Value = Empty_String then
1454 Error_Msg_Name_1 := Name_Of (Declaration, From_Project_Node_Tree);
1456 case Flags.Allow_Invalid_External is
1458 Error_Msg (Flags, "no value defined for %%", Loc, Project);
1460 Reset_Value := True;
1461 Error_Msg (Flags, "?no value defined for %%", Loc, Project);
1463 Reset_Value := True;
1467 -- Loop through all the valid strings for the
1468 -- string type and compare to the string value.
1471 First_Literal_String
1472 (String_Type_Of (Declaration, From_Project_Node_Tree),
1473 From_Project_Node_Tree);
1474 while Present (Current_String)
1475 and then String_Value_Of
1476 (Current_String, From_Project_Node_Tree) /= Value.Value
1479 Next_Literal_String (Current_String, From_Project_Node_Tree);
1482 -- Report error if string value is not one for the string type
1484 if No (Current_String) then
1485 Error_Msg_Name_1 := Value.Value;
1487 Name_Of (Declaration, From_Project_Node_Tree);
1489 case Flags.Allow_Invalid_External is
1492 (Flags, "value %% is illegal for typed string %%",
1496 (Flags, "?value %% is illegal for typed string %%",
1498 Reset_Value := True;
1500 Reset_Value := True;
1507 First_Literal_String
1508 (String_Type_Of (Declaration, From_Project_Node_Tree),
1509 From_Project_Node_Tree);
1511 Value.Value := String_Value_Of
1512 (Current_String, From_Project_Node_Tree);
1514 end Check_Or_Set_Typed_Variable;
1518 Current_Declarative_Item : Project_Node_Id;
1519 Current_Item : Project_Node_Id;
1521 -- Start of processing for Process_Declarative_Items
1524 -- Loop through declarative items
1526 Current_Item := Empty_Node;
1528 Current_Declarative_Item := Item;
1529 while Present (Current_Declarative_Item) loop
1535 (Current_Declarative_Item, From_Project_Node_Tree);
1537 -- And set Current_Declarative_Item to the next declarative item
1538 -- ready for the next iteration.
1540 Current_Declarative_Item :=
1541 Next_Declarative_Item
1542 (Current_Declarative_Item, From_Project_Node_Tree);
1544 case Kind_Of (Current_Item, From_Project_Node_Tree) is
1546 when N_Package_Declaration =>
1548 -- Do not process a package declaration that should be ignored
1550 if Expression_Kind_Of
1551 (Current_Item, From_Project_Node_Tree) /= Ignored
1553 -- Create the new package
1555 Package_Table.Increment_Last (In_Tree.Packages);
1558 New_Pkg : constant Package_Id :=
1559 Package_Table.Last (In_Tree.Packages);
1560 The_New_Package : Package_Element;
1562 Project_Of_Renamed_Package :
1563 constant Project_Node_Id :=
1564 Project_Of_Renamed_Package_Of
1565 (Current_Item, From_Project_Node_Tree);
1568 -- Set the name of the new package
1570 The_New_Package.Name :=
1571 Name_Of (Current_Item, From_Project_Node_Tree);
1573 -- Insert the new package in the appropriate list
1575 if Pkg /= No_Package then
1576 The_New_Package.Next :=
1577 In_Tree.Packages.Table (Pkg).Decl.Packages;
1578 In_Tree.Packages.Table (Pkg).Decl.Packages :=
1582 The_New_Package.Next := Project.Decl.Packages;
1583 Project.Decl.Packages := New_Pkg;
1586 In_Tree.Packages.Table (New_Pkg) :=
1589 if Present (Project_Of_Renamed_Package) then
1591 -- Renamed or extending package
1594 Project_Name : constant Name_Id :=
1596 (Project_Of_Renamed_Package,
1597 From_Project_Node_Tree);
1600 constant Project_Id :=
1601 Imported_Or_Extended_Project_From
1602 (Project, Project_Name);
1604 Renamed_Package : constant Package_Id :=
1606 (Renamed_Project, In_Tree,
1609 From_Project_Node_Tree));
1612 -- For a renamed package, copy the declarations of
1613 -- the renamed package, but set all the locations
1614 -- to the location of the package name in the
1615 -- renaming declaration.
1617 Copy_Package_Declarations
1619 In_Tree.Packages.Table (Renamed_Package).Decl,
1621 In_Tree.Packages.Table (New_Pkg).Decl,
1624 (Current_Item, From_Project_Node_Tree),
1625 Restricted => False,
1626 In_Tree => In_Tree);
1630 -- Set the default values of the attributes
1635 Name_Id (Project.Directory.Name),
1637 In_Tree.Packages.Table (New_Pkg).Decl,
1640 (Current_Item, From_Project_Node_Tree)),
1641 Project_Level => False);
1645 -- Process declarative items (nothing to do when the
1646 -- package is renaming, as the first declarative item is
1649 Process_Declarative_Items
1650 (Project => Project,
1653 From_Project_Node => From_Project_Node,
1654 From_Project_Node_Tree => From_Project_Node_Tree,
1657 First_Declarative_Item_Of
1658 (Current_Item, From_Project_Node_Tree));
1662 when N_String_Type_Declaration =>
1664 -- There is nothing to process
1668 when N_Attribute_Declaration |
1669 N_Typed_Variable_Declaration |
1670 N_Variable_Declaration =>
1672 if Expression_Of (Current_Item, From_Project_Node_Tree) =
1676 -- It must be a full associative array attribute declaration
1679 Current_Item_Name : constant Name_Id :=
1682 From_Project_Node_Tree);
1683 -- The name of the attribute
1685 Current_Location : constant Source_Ptr :=
1688 From_Project_Node_Tree);
1690 New_Array : Array_Id;
1691 -- The new associative array created
1693 Orig_Array : Array_Id;
1694 -- The associative array value
1696 Orig_Project_Name : Name_Id := No_Name;
1697 -- The name of the project where the associative array
1700 Orig_Project : Project_Id := No_Project;
1701 -- The id of the project where the associative array
1704 Orig_Package_Name : Name_Id := No_Name;
1705 -- The name of the package, if any, where the associative
1708 Orig_Package : Package_Id := No_Package;
1709 -- The id of the package, if any, where the associative
1712 New_Element : Array_Element_Id := No_Array_Element;
1713 -- Id of a new array element created
1715 Prev_Element : Array_Element_Id := No_Array_Element;
1716 -- Last new element id created
1718 Orig_Element : Array_Element_Id := No_Array_Element;
1719 -- Current array element in original associative array
1721 Next_Element : Array_Element_Id := No_Array_Element;
1722 -- Id of the array element that follows the new element.
1723 -- This is not always nil, because values for the
1724 -- associative array attribute may already have been
1725 -- declared, and the array elements declared are reused.
1730 -- First find if the associative array attribute already
1731 -- has elements declared.
1733 if Pkg /= No_Package then
1734 New_Array := In_Tree.Packages.Table
1738 New_Array := Project.Decl.Arrays;
1741 while New_Array /= No_Array
1742 and then In_Tree.Arrays.Table (New_Array).Name /=
1745 New_Array := In_Tree.Arrays.Table (New_Array).Next;
1748 -- If the attribute has never been declared add new entry
1749 -- in the arrays of the project/package and link it.
1751 if New_Array = No_Array then
1752 Array_Table.Increment_Last (In_Tree.Arrays);
1753 New_Array := Array_Table.Last (In_Tree.Arrays);
1755 if Pkg /= No_Package then
1756 In_Tree.Arrays.Table (New_Array) :=
1757 (Name => Current_Item_Name,
1758 Location => Current_Location,
1759 Value => No_Array_Element,
1760 Next => In_Tree.Packages.Table
1763 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1767 In_Tree.Arrays.Table (New_Array) :=
1768 (Name => Current_Item_Name,
1769 Location => Current_Location,
1770 Value => No_Array_Element,
1771 Next => Project.Decl.Arrays);
1773 Project.Decl.Arrays := New_Array;
1777 -- Find the project where the value is declared
1779 Orig_Project_Name :=
1781 (Associative_Project_Of
1782 (Current_Item, From_Project_Node_Tree),
1783 From_Project_Node_Tree);
1785 Prj := In_Tree.Projects;
1786 while Prj /= null loop
1787 if Prj.Project.Name = Orig_Project_Name then
1788 Orig_Project := Prj.Project;
1794 pragma Assert (Orig_Project /= No_Project,
1795 "original project not found");
1797 if No (Associative_Package_Of
1798 (Current_Item, From_Project_Node_Tree))
1800 Orig_Array := Orig_Project.Decl.Arrays;
1803 -- If in a package, find the package where the value
1806 Orig_Package_Name :=
1808 (Associative_Package_Of
1809 (Current_Item, From_Project_Node_Tree),
1810 From_Project_Node_Tree);
1812 Orig_Package := Orig_Project.Decl.Packages;
1813 pragma Assert (Orig_Package /= No_Package,
1814 "original package not found");
1816 while In_Tree.Packages.Table
1817 (Orig_Package).Name /= Orig_Package_Name
1819 Orig_Package := In_Tree.Packages.Table
1820 (Orig_Package).Next;
1821 pragma Assert (Orig_Package /= No_Package,
1822 "original package not found");
1826 In_Tree.Packages.Table (Orig_Package).Decl.Arrays;
1829 -- Now look for the array
1831 while Orig_Array /= No_Array
1832 and then In_Tree.Arrays.Table (Orig_Array).Name /=
1835 Orig_Array := In_Tree.Arrays.Table
1839 if Orig_Array = No_Array then
1842 "associative array value not found",
1843 Location_Of (Current_Item, From_Project_Node_Tree),
1848 In_Tree.Arrays.Table (Orig_Array).Value;
1850 -- Copy each array element
1852 while Orig_Element /= No_Array_Element loop
1854 -- Case of first element
1856 if Prev_Element = No_Array_Element then
1858 -- And there is no array element declared yet,
1859 -- create a new first array element.
1861 if In_Tree.Arrays.Table (New_Array).Value =
1864 Array_Element_Table.Increment_Last
1865 (In_Tree.Array_Elements);
1866 New_Element := Array_Element_Table.Last
1867 (In_Tree.Array_Elements);
1868 In_Tree.Arrays.Table
1869 (New_Array).Value := New_Element;
1870 Next_Element := No_Array_Element;
1872 -- Otherwise, the new element is the first
1875 New_Element := In_Tree.Arrays.
1876 Table (New_Array).Value;
1878 In_Tree.Array_Elements.Table
1882 -- Otherwise, reuse an existing element, or create
1883 -- one if necessary.
1887 In_Tree.Array_Elements.Table
1888 (Prev_Element).Next;
1890 if Next_Element = No_Array_Element then
1891 Array_Element_Table.Increment_Last
1892 (In_Tree.Array_Elements);
1894 Array_Element_Table.Last
1895 (In_Tree.Array_Elements);
1896 In_Tree.Array_Elements.Table
1897 (Prev_Element).Next := New_Element;
1900 New_Element := Next_Element;
1902 In_Tree.Array_Elements.Table
1907 -- Copy the value of the element
1909 In_Tree.Array_Elements.Table
1911 In_Tree.Array_Elements.Table (Orig_Element);
1912 In_Tree.Array_Elements.Table
1913 (New_Element).Value.Project := Project;
1915 -- Adjust the Next link
1917 In_Tree.Array_Elements.Table
1918 (New_Element).Next := Next_Element;
1920 -- Adjust the previous id for the next element
1922 Prev_Element := New_Element;
1924 -- Go to the next element in the original array
1927 In_Tree.Array_Elements.Table
1928 (Orig_Element).Next;
1931 -- Make sure that the array ends here, in case there
1932 -- previously a greater number of elements.
1934 In_Tree.Array_Elements.Table
1935 (New_Element).Next := No_Array_Element;
1939 -- Declarations other that full associative arrays
1943 New_Value : Variable_Value :=
1945 (Project => Project,
1948 From_Project_Node => From_Project_Node,
1949 From_Project_Node_Tree => From_Project_Node_Tree,
1954 (Current_Item, From_Project_Node_Tree),
1955 From_Project_Node_Tree),
1958 (Current_Item, From_Project_Node_Tree));
1959 -- The expression value
1961 The_Variable : Variable_Id := No_Variable;
1963 Current_Item_Name : constant Name_Id :=
1966 From_Project_Node_Tree);
1968 Current_Location : constant Source_Ptr :=
1971 From_Project_Node_Tree);
1974 -- Process a typed variable declaration
1976 if Kind_Of (Current_Item, From_Project_Node_Tree) =
1977 N_Typed_Variable_Declaration
1979 Check_Or_Set_Typed_Variable
1980 (Value => New_Value,
1981 Declaration => Current_Item);
1986 if Kind_Of (Current_Item, From_Project_Node_Tree) /=
1987 N_Attribute_Declaration
1989 Associative_Array_Index_Of
1990 (Current_Item, From_Project_Node_Tree) = No_Name
1992 -- Case of a variable declaration or of a not
1993 -- associative array attribute.
1995 -- First, find the list where to find the variable
1998 if Kind_Of (Current_Item, From_Project_Node_Tree) =
1999 N_Attribute_Declaration
2001 if Pkg /= No_Package then
2003 In_Tree.Packages.Table
2004 (Pkg).Decl.Attributes;
2006 The_Variable := Project.Decl.Attributes;
2010 if Pkg /= No_Package then
2012 In_Tree.Packages.Table
2013 (Pkg).Decl.Variables;
2015 The_Variable := Project.Decl.Variables;
2020 -- Loop through the list, to find if it has already
2023 while The_Variable /= No_Variable
2025 In_Tree.Variable_Elements.Table
2026 (The_Variable).Name /= Current_Item_Name
2029 In_Tree.Variable_Elements.Table
2030 (The_Variable).Next;
2033 -- If it has not been declared, create a new entry
2036 if The_Variable = No_Variable then
2038 -- All single string attribute should already have
2039 -- been declared with a default empty string value.
2042 (Kind_Of (Current_Item, From_Project_Node_Tree) /=
2043 N_Attribute_Declaration,
2044 "illegal attribute declaration for "
2045 & Get_Name_String (Current_Item_Name));
2047 Variable_Element_Table.Increment_Last
2048 (In_Tree.Variable_Elements);
2049 The_Variable := Variable_Element_Table.Last
2050 (In_Tree.Variable_Elements);
2052 -- Put the new variable in the appropriate list
2054 if Pkg /= No_Package then
2055 In_Tree.Variable_Elements.Table (The_Variable) :=
2057 In_Tree.Packages.Table
2058 (Pkg).Decl.Variables,
2059 Name => Current_Item_Name,
2060 Value => New_Value);
2061 In_Tree.Packages.Table
2062 (Pkg).Decl.Variables := The_Variable;
2065 In_Tree.Variable_Elements.Table (The_Variable) :=
2066 (Next => Project.Decl.Variables,
2067 Name => Current_Item_Name,
2068 Value => New_Value);
2069 Project.Decl.Variables := The_Variable;
2072 -- If the variable/attribute has already been
2073 -- declared, just change the value.
2076 In_Tree.Variable_Elements.Table
2077 (The_Variable).Value := New_Value;
2080 -- Associative array attribute
2084 Index_Name : Name_Id :=
2085 Associative_Array_Index_Of
2087 From_Project_Node_Tree);
2089 Source_Index : constant Int :=
2092 From_Project_Node_Tree);
2094 The_Array : Array_Id;
2095 The_Array_Element : Array_Element_Id :=
2099 if Index_Name /= All_Other_Names then
2100 Index_Name := Get_Attribute_Index
2101 (From_Project_Node_Tree,
2103 Associative_Array_Index_Of
2104 (Current_Item, From_Project_Node_Tree));
2107 -- Look for the array in the appropriate list
2109 if Pkg /= No_Package then
2111 In_Tree.Packages.Table (Pkg).Decl.Arrays;
2114 Project.Decl.Arrays;
2118 The_Array /= No_Array
2120 In_Tree.Arrays.Table (The_Array).Name /=
2124 In_Tree.Arrays.Table (The_Array).Next;
2127 -- If the array cannot be found, create a new entry
2128 -- in the list. As The_Array_Element is initialized
2129 -- to No_Array_Element, a new element will be
2130 -- created automatically later
2132 if The_Array = No_Array then
2133 Array_Table.Increment_Last (In_Tree.Arrays);
2134 The_Array := Array_Table.Last (In_Tree.Arrays);
2136 if Pkg /= No_Package then
2137 In_Tree.Arrays.Table (The_Array) :=
2138 (Name => Current_Item_Name,
2139 Location => Current_Location,
2140 Value => No_Array_Element,
2141 Next => In_Tree.Packages.Table
2144 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
2148 In_Tree.Arrays.Table (The_Array) :=
2149 (Name => Current_Item_Name,
2150 Location => Current_Location,
2151 Value => No_Array_Element,
2152 Next => Project.Decl.Arrays);
2154 Project.Decl.Arrays := The_Array;
2157 -- Otherwise initialize The_Array_Element as the
2158 -- head of the element list.
2161 The_Array_Element :=
2162 In_Tree.Arrays.Table (The_Array).Value;
2165 -- Look in the list, if any, to find an element
2166 -- with the same index and same source index.
2168 while The_Array_Element /= No_Array_Element
2170 (In_Tree.Array_Elements.Table
2171 (The_Array_Element).Index /= Index_Name
2173 In_Tree.Array_Elements.Table
2174 (The_Array_Element).Src_Index /= Source_Index)
2176 The_Array_Element :=
2177 In_Tree.Array_Elements.Table
2178 (The_Array_Element).Next;
2181 -- If no such element were found, create a new one
2182 -- and insert it in the element list, with the
2185 if The_Array_Element = No_Array_Element then
2186 Array_Element_Table.Increment_Last
2187 (In_Tree.Array_Elements);
2188 The_Array_Element :=
2189 Array_Element_Table.Last
2190 (In_Tree.Array_Elements);
2192 In_Tree.Array_Elements.Table
2193 (The_Array_Element) :=
2194 (Index => Index_Name,
2195 Src_Index => Source_Index,
2196 Index_Case_Sensitive =>
2197 not Case_Insensitive
2198 (Current_Item, From_Project_Node_Tree),
2201 In_Tree.Arrays.Table (The_Array).Value);
2203 In_Tree.Arrays.Table (The_Array).Value :=
2206 -- An element with the same index already exists,
2207 -- just replace its value with the new one.
2210 In_Tree.Array_Elements.Table
2211 (The_Array_Element).Value := New_Value;
2218 when N_Case_Construction =>
2220 The_Project : Project_Id := Project;
2221 -- The id of the project of the case variable
2223 The_Package : Package_Id := Pkg;
2224 -- The id of the package, if any, of the case variable
2226 The_Variable : Variable_Value := Nil_Variable_Value;
2227 -- The case variable
2229 Case_Value : Name_Id := No_Name;
2230 -- The case variable value
2232 Case_Item : Project_Node_Id := Empty_Node;
2233 Choice_String : Project_Node_Id := Empty_Node;
2234 Decl_Item : Project_Node_Id := Empty_Node;
2238 Variable_Node : constant Project_Node_Id :=
2239 Case_Variable_Reference_Of
2241 From_Project_Node_Tree);
2243 Var_Id : Variable_Id := No_Variable;
2244 Name : Name_Id := No_Name;
2247 -- If a project was specified for the case variable,
2250 if Present (Project_Node_Of
2251 (Variable_Node, From_Project_Node_Tree))
2256 (Variable_Node, From_Project_Node_Tree),
2257 From_Project_Node_Tree);
2259 Imported_Or_Extended_Project_From (Project, Name);
2262 -- If a package were specified for the case variable,
2265 if Present (Package_Node_Of
2266 (Variable_Node, From_Project_Node_Tree))
2271 (Variable_Node, From_Project_Node_Tree),
2272 From_Project_Node_Tree);
2274 Package_From (The_Project, In_Tree, Name);
2277 Name := Name_Of (Variable_Node, From_Project_Node_Tree);
2279 -- First, look for the case variable into the package,
2282 if The_Package /= No_Package then
2283 Var_Id := In_Tree.Packages.Table
2284 (The_Package).Decl.Variables;
2286 Name_Of (Variable_Node, From_Project_Node_Tree);
2287 while Var_Id /= No_Variable
2289 In_Tree.Variable_Elements.Table
2290 (Var_Id).Name /= Name
2292 Var_Id := In_Tree.Variable_Elements.
2293 Table (Var_Id).Next;
2297 -- If not found in the package, or if there is no
2298 -- package, look at the project level.
2300 if Var_Id = No_Variable
2303 (Variable_Node, From_Project_Node_Tree))
2305 Var_Id := The_Project.Decl.Variables;
2306 while Var_Id /= No_Variable
2308 In_Tree.Variable_Elements.Table
2309 (Var_Id).Name /= Name
2311 Var_Id := In_Tree.Variable_Elements.
2312 Table (Var_Id).Next;
2316 if Var_Id = No_Variable then
2318 -- Should never happen, because this has already been
2319 -- checked during parsing.
2321 Write_Line ("variable """ &
2322 Get_Name_String (Name) &
2324 raise Program_Error;
2327 -- Get the case variable
2329 The_Variable := In_Tree.Variable_Elements.
2330 Table (Var_Id).Value;
2332 if The_Variable.Kind /= Single then
2334 -- Should never happen, because this has already been
2335 -- checked during parsing.
2337 Write_Line ("variable""" &
2338 Get_Name_String (Name) &
2339 """ is not a single string variable");
2340 raise Program_Error;
2343 -- Get the case variable value
2344 Case_Value := The_Variable.Value;
2347 -- Now look into all the case items of the case construction
2350 First_Case_Item_Of (Current_Item, From_Project_Node_Tree);
2352 while Present (Case_Item) loop
2354 First_Choice_Of (Case_Item, From_Project_Node_Tree);
2356 -- When Choice_String is nil, it means that it is
2357 -- the "when others =>" alternative.
2359 if No (Choice_String) then
2361 First_Declarative_Item_Of
2362 (Case_Item, From_Project_Node_Tree);
2363 exit Case_Item_Loop;
2366 -- Look into all the alternative of this case item
2369 while Present (Choice_String) loop
2372 (Choice_String, From_Project_Node_Tree)
2375 First_Declarative_Item_Of
2376 (Case_Item, From_Project_Node_Tree);
2377 exit Case_Item_Loop;
2382 (Choice_String, From_Project_Node_Tree);
2383 end loop Choice_Loop;
2386 Next_Case_Item (Case_Item, From_Project_Node_Tree);
2387 end loop Case_Item_Loop;
2389 -- If there is an alternative, then we process it
2391 if Present (Decl_Item) then
2392 Process_Declarative_Items
2393 (Project => Project,
2396 From_Project_Node => From_Project_Node,
2397 From_Project_Node_Tree => From_Project_Node_Tree,
2405 -- Should never happen
2407 Write_Line ("Illegal declarative item: " &
2408 Project_Node_Kind'Image
2410 (Current_Item, From_Project_Node_Tree)));
2411 raise Program_Error;
2414 end Process_Declarative_Items;
2416 ----------------------------------
2417 -- Process_Project_Tree_Phase_1 --
2418 ----------------------------------
2420 procedure Process_Project_Tree_Phase_1
2421 (In_Tree : Project_Tree_Ref;
2422 Project : out Project_Id;
2423 Success : out Boolean;
2424 From_Project_Node : Project_Node_Id;
2425 From_Project_Node_Tree : Project_Node_Tree_Ref;
2426 Flags : Processing_Flags;
2427 Reset_Tree : Boolean := True)
2432 -- Make sure there are no projects in the data structure
2434 Free_List (In_Tree.Projects, Free_Project => True);
2437 Processed_Projects.Reset;
2439 -- And process the main project and all of the projects it depends on,
2443 (Project => Project,
2446 From_Project_Node => From_Project_Node,
2447 From_Project_Node_Tree => From_Project_Node_Tree,
2448 Extended_By => No_Project);
2451 Total_Errors_Detected = 0
2453 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2454 end Process_Project_Tree_Phase_1;
2456 ----------------------------------
2457 -- Process_Project_Tree_Phase_2 --
2458 ----------------------------------
2460 procedure Process_Project_Tree_Phase_2
2461 (In_Tree : Project_Tree_Ref;
2462 Project : Project_Id;
2463 Success : out Boolean;
2464 From_Project_Node : Project_Node_Id;
2465 From_Project_Node_Tree : Project_Node_Tree_Ref;
2466 Flags : Processing_Flags)
2468 Obj_Dir : Path_Name_Type;
2469 Extending : Project_Id;
2470 Extending2 : Project_Id;
2473 -- Start of processing for Process_Project_Tree_Phase_2
2478 if Project /= No_Project then
2479 Check (In_Tree, Project, From_Project_Node_Tree, Flags);
2482 -- If main project is an extending all project, set object directory of
2483 -- all virtual extending projects to object directory of main project.
2485 if Project /= No_Project
2487 Is_Extending_All (From_Project_Node, From_Project_Node_Tree)
2490 Object_Dir : constant Path_Information :=
2491 Project.Object_Directory;
2493 Prj := In_Tree.Projects;
2494 while Prj /= null loop
2495 if Prj.Project.Virtual then
2496 Prj.Project.Object_Directory := Object_Dir;
2503 -- Check that no extending project shares its object directory with
2504 -- the project(s) it extends.
2506 if Project /= No_Project then
2507 Prj := In_Tree.Projects;
2508 while Prj /= null loop
2509 Extending := Prj.Project.Extended_By;
2511 if Extending /= No_Project then
2512 Obj_Dir := Prj.Project.Object_Directory.Name;
2514 -- Check that a project being extended does not share its
2515 -- object directory with any project that extends it, directly
2516 -- or indirectly, including a virtual extending project.
2518 -- Start with the project directly extending it
2520 Extending2 := Extending;
2521 while Extending2 /= No_Project loop
2522 if Has_Ada_Sources (Extending2)
2523 and then Extending2.Object_Directory.Name = Obj_Dir
2525 if Extending2.Virtual then
2526 Error_Msg_Name_1 := Prj.Project.Display_Name;
2529 "project %% cannot be extended by a virtual" &
2530 " project with the same object directory",
2531 Prj.Project.Location, Project);
2534 Error_Msg_Name_1 := Extending2.Display_Name;
2535 Error_Msg_Name_2 := Prj.Project.Display_Name;
2538 "project %% cannot extend project %%",
2539 Extending2.Location, Project);
2542 "\they share the same object directory",
2543 Extending2.Location, Project);
2547 -- Continue with the next extending project, if any
2549 Extending2 := Extending2.Extended_By;
2558 Total_Errors_Detected = 0
2560 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2561 end Process_Project_Tree_Phase_2;
2563 -----------------------
2564 -- Recursive_Process --
2565 -----------------------
2567 procedure Recursive_Process
2568 (In_Tree : Project_Tree_Ref;
2569 Project : out Project_Id;
2570 Flags : Processing_Flags;
2571 From_Project_Node : Project_Node_Id;
2572 From_Project_Node_Tree : Project_Node_Tree_Ref;
2573 Extended_By : Project_Id)
2575 procedure Process_Imported_Projects
2576 (Imported : in out Project_List;
2577 Limited_With : Boolean);
2578 -- Process imported projects. If Limited_With is True, then only
2579 -- projects processed through a "limited with" are processed, otherwise
2580 -- only projects imported through a standard "with" are processed.
2581 -- Imported is the id of the last imported project.
2583 -------------------------------
2584 -- Process_Imported_Projects --
2585 -------------------------------
2587 procedure Process_Imported_Projects
2588 (Imported : in out Project_List;
2589 Limited_With : Boolean)
2591 With_Clause : Project_Node_Id;
2592 New_Project : Project_Id;
2593 Proj_Node : Project_Node_Id;
2597 First_With_Clause_Of
2598 (From_Project_Node, From_Project_Node_Tree);
2599 while Present (With_Clause) loop
2601 Non_Limited_Project_Node_Of
2602 (With_Clause, From_Project_Node_Tree);
2603 New_Project := No_Project;
2605 if (Limited_With and then No (Proj_Node))
2606 or else (not Limited_With and then Present (Proj_Node))
2609 (In_Tree => In_Tree,
2610 Project => New_Project,
2612 From_Project_Node =>
2614 (With_Clause, From_Project_Node_Tree),
2615 From_Project_Node_Tree => From_Project_Node_Tree,
2616 Extended_By => No_Project);
2618 -- Imported is the id of the last imported project. If
2619 -- it is nil, then this imported project is our first.
2621 if Imported = null then
2622 Project.Imported_Projects :=
2623 new Project_List_Element'
2624 (Project => New_Project,
2626 Imported := Project.Imported_Projects;
2628 Imported.Next := new Project_List_Element'
2629 (Project => New_Project,
2631 Imported := Imported.Next;
2636 Next_With_Clause_Of (With_Clause, From_Project_Node_Tree);
2638 end Process_Imported_Projects;
2640 -- Start of processing for Recursive_Process
2643 if No (From_Project_Node) then
2644 Project := No_Project;
2648 Imported : Project_List;
2649 Declaration_Node : Project_Node_Id := Empty_Node;
2651 Name : constant Name_Id :=
2652 Name_Of (From_Project_Node, From_Project_Node_Tree);
2654 Name_Node : constant Tree_Private_Part.Project_Name_And_Node :=
2655 Tree_Private_Part.Projects_Htable.Get
2656 (From_Project_Node_Tree.Projects_HT, Name);
2659 Project := Processed_Projects.Get (Name);
2661 if Project /= No_Project then
2663 -- Make sure that, when a project is extended, the project id
2664 -- of the project extending it is recorded in its data, even
2665 -- when it has already been processed as an imported project.
2666 -- This is for virtually extended projects.
2668 if Extended_By /= No_Project then
2669 Project.Extended_By := Extended_By;
2675 Project := new Project_Data'(Empty_Project);
2676 In_Tree.Projects := new Project_List_Element'
2677 (Project => Project,
2678 Next => In_Tree.Projects);
2680 Processed_Projects.Set (Name, Project);
2682 Project.Name := Name;
2683 Project.Display_Name := Name_Node.Display_Name;
2684 Project.Qualifier :=
2685 Project_Qualifier_Of (From_Project_Node, From_Project_Node_Tree);
2687 Get_Name_String (Name);
2689 -- If name starts with the virtual prefix, flag the project as
2690 -- being a virtual extending project.
2692 if Name_Len > Virtual_Prefix'Length
2693 and then Name_Buffer (1 .. Virtual_Prefix'Length) =
2696 Project.Virtual := True;
2699 Project.Path.Display_Name :=
2700 Path_Name_Of (From_Project_Node, From_Project_Node_Tree);
2701 Get_Name_String (Project.Path.Display_Name);
2702 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2703 Project.Path.Name := Name_Find;
2706 Location_Of (From_Project_Node, From_Project_Node_Tree);
2708 Project.Directory.Display_Name :=
2709 Directory_Of (From_Project_Node, From_Project_Node_Tree);
2710 Get_Name_String (Project.Directory.Display_Name);
2711 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2712 Project.Directory.Name := Name_Find;
2714 Project.Extended_By := Extended_By;
2719 Name_Id (Project.Directory.Name),
2722 Prj.Attr.Attribute_First,
2723 Project_Level => True);
2725 Process_Imported_Projects (Imported, Limited_With => False);
2728 Project_Declaration_Of
2729 (From_Project_Node, From_Project_Node_Tree);
2732 (In_Tree => In_Tree,
2733 Project => Project.Extends,
2735 From_Project_Node => Extended_Project_Of
2737 From_Project_Node_Tree),
2738 From_Project_Node_Tree => From_Project_Node_Tree,
2739 Extended_By => Project);
2741 Process_Declarative_Items
2742 (Project => Project,
2745 From_Project_Node => From_Project_Node,
2746 From_Project_Node_Tree => From_Project_Node_Tree,
2748 Item => First_Declarative_Item_Of
2750 From_Project_Node_Tree));
2752 -- If it is an extending project, inherit all packages
2753 -- from the extended project that are not explicitly defined
2754 -- or renamed. Also inherit the languages, if attribute Languages
2755 -- is not explicitly defined.
2757 if Project.Extends /= No_Project then
2759 Extended_Pkg : Package_Id;
2760 Current_Pkg : Package_Id;
2761 Element : Package_Element;
2762 First : constant Package_Id :=
2763 Project.Decl.Packages;
2764 Attribute1 : Variable_Id;
2765 Attribute2 : Variable_Id;
2766 Attr_Value1 : Variable;
2767 Attr_Value2 : Variable;
2770 Extended_Pkg := Project.Extends.Decl.Packages;
2771 while Extended_Pkg /= No_Package loop
2772 Element := In_Tree.Packages.Table (Extended_Pkg);
2774 Current_Pkg := First;
2775 while Current_Pkg /= No_Package
2776 and then In_Tree.Packages.Table (Current_Pkg).Name /=
2780 In_Tree.Packages.Table (Current_Pkg).Next;
2783 if Current_Pkg = No_Package then
2784 Package_Table.Increment_Last
2786 Current_Pkg := Package_Table.Last (In_Tree.Packages);
2787 In_Tree.Packages.Table (Current_Pkg) :=
2788 (Name => Element.Name,
2789 Decl => No_Declarations,
2790 Parent => No_Package,
2791 Next => Project.Decl.Packages);
2792 Project.Decl.Packages := Current_Pkg;
2793 Copy_Package_Declarations
2794 (From => Element.Decl,
2796 In_Tree.Packages.Table (Current_Pkg).Decl,
2797 New_Loc => No_Location,
2799 In_Tree => In_Tree);
2802 Extended_Pkg := Element.Next;
2805 -- Check if attribute Languages is declared in the
2806 -- extending project.
2808 Attribute1 := Project.Decl.Attributes;
2809 while Attribute1 /= No_Variable loop
2810 Attr_Value1 := In_Tree.Variable_Elements.
2812 exit when Attr_Value1.Name = Snames.Name_Languages;
2813 Attribute1 := Attr_Value1.Next;
2816 if Attribute1 = No_Variable or else
2817 Attr_Value1.Value.Default
2819 -- Attribute Languages is not declared in the extending
2820 -- project. Check if it is declared in the project being
2823 Attribute2 := Project.Extends.Decl.Attributes;
2824 while Attribute2 /= No_Variable loop
2825 Attr_Value2 := In_Tree.Variable_Elements.
2827 exit when Attr_Value2.Name = Snames.Name_Languages;
2828 Attribute2 := Attr_Value2.Next;
2831 if Attribute2 /= No_Variable and then
2832 not Attr_Value2.Value.Default
2834 -- As attribute Languages is declared in the project
2835 -- being extended, copy its value for the extending
2838 if Attribute1 = No_Variable then
2839 Variable_Element_Table.Increment_Last
2840 (In_Tree.Variable_Elements);
2841 Attribute1 := Variable_Element_Table.Last
2842 (In_Tree.Variable_Elements);
2843 Attr_Value1.Next := Project.Decl.Attributes;
2844 Project.Decl.Attributes := Attribute1;
2847 Attr_Value1.Name := Snames.Name_Languages;
2848 Attr_Value1.Value := Attr_Value2.Value;
2849 In_Tree.Variable_Elements.Table
2850 (Attribute1) := Attr_Value1;
2856 Process_Imported_Projects (Imported, Limited_With => True);
2859 end Recursive_Process;