1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2011, 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;
32 with Prj.Err; use Prj.Err;
33 with Prj.Ext; use Prj.Ext;
34 with Prj.Nmsc; use Prj.Nmsc;
38 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
40 with GNAT.Case_Util; use GNAT.Case_Util;
43 package body Prj.Proc is
45 package Processed_Projects is new GNAT.HTable.Simple_HTable
46 (Header_Num => Header_Num,
47 Element => Project_Id,
48 No_Element => No_Project,
52 -- This hash table contains all processed projects
54 package Unit_Htable is new GNAT.HTable.Simple_HTable
55 (Header_Num => Header_Num,
57 No_Element => No_Source,
61 -- This hash table contains all processed projects
63 procedure Add (To_Exp : in out Name_Id; Str : Name_Id);
64 -- Concatenate two strings and returns another string if both
65 -- arguments are not null string.
67 -- In the following procedures, we are expected to guess the meaning of
68 -- the parameters from their names, this is never a good idea, comments
69 -- should be added precisely defining every formal ???
71 procedure Add_Attributes
72 (Project : Project_Id;
73 Project_Name : Name_Id;
74 Project_Dir : Name_Id;
75 Shared : Shared_Project_Tree_Data_Access;
76 Decl : in out Declarations;
77 First : Attribute_Node_Id;
78 Project_Level : Boolean);
79 -- Add all attributes, starting with First, with their default values to
80 -- the package or project with declarations Decl.
83 (In_Tree : Project_Tree_Ref;
85 Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
86 Flags : Processing_Flags);
87 -- Set all projects to not checked, then call Recursive_Check for the
88 -- main project Project. Project is set to No_Project if errors occurred.
89 -- Current_Dir is for optimization purposes, avoiding extra system calls.
90 -- If Allow_Duplicate_Basenames, then files with the same base names are
91 -- authorized within a project for source-based languages (never for unit
94 procedure Copy_Package_Declarations
96 To : in out Declarations;
99 Shared : Shared_Project_Tree_Data_Access);
100 -- Copy a package declaration From to To for a renamed package. Change the
101 -- locations of all the attributes to New_Loc. When Restricted is
102 -- True, do not copy attributes Body, Spec, Implementation, Specification
103 -- and Linker_Options.
106 (Project : Project_Id;
107 Shared : Shared_Project_Tree_Data_Access;
108 From_Project_Node : Project_Node_Id;
109 From_Project_Node_Tree : Project_Node_Tree_Ref;
110 Env : Prj.Tree.Environment;
112 First_Term : Project_Node_Id;
113 Kind : Variable_Kind) return Variable_Value;
114 -- From N_Expression project node From_Project_Node, compute the value
115 -- of an expression and return it as a Variable_Value.
117 function Imported_Or_Extended_Project_From
118 (Project : Project_Id;
119 With_Name : Name_Id) return Project_Id;
120 -- Find an imported or extended project of Project whose name is With_Name
122 function Package_From
123 (Project : Project_Id;
124 Shared : Shared_Project_Tree_Data_Access;
125 With_Name : Name_Id) return Package_Id;
126 -- Find the package of Project whose name is With_Name
128 procedure Process_Declarative_Items
129 (Project : Project_Id;
130 In_Tree : Project_Tree_Ref;
131 From_Project_Node : Project_Node_Id;
132 Node_Tree : Project_Node_Tree_Ref;
133 Env : Prj.Tree.Environment;
135 Item : Project_Node_Id;
136 Child_Env : in out Prj.Tree.Environment);
137 -- Process declarative items starting with From_Project_Node, and put them
138 -- in declarations Decl. This is a recursive procedure; it calls itself for
139 -- a package declaration or a case construction.
141 -- Child_Env is the modified environment after seeing declarations like
142 -- "for External(...) use" or "for Project_Path use" in aggregate projects.
143 -- It should have been initialized first.
145 procedure Recursive_Process
146 (In_Tree : Project_Tree_Ref;
147 Project : out Project_Id;
148 From_Project_Node : Project_Node_Id;
149 From_Project_Node_Tree : Project_Node_Tree_Ref;
150 Env : in out Prj.Tree.Environment;
151 Extended_By : Project_Id);
152 -- Process project with node From_Project_Node in the tree. Do nothing if
153 -- From_Project_Node is Empty_Node. If project has already been processed,
154 -- simply return its project id. Otherwise create a new project id, mark it
155 -- as processed, call itself recursively for all imported projects and a
156 -- extended project, if any. Then process the declarative items of the
159 -- Is_Root_Project should be true only for the project that the user
160 -- explicitly loaded. In the context of aggregate projects, only that
161 -- project is allowed to modify the environment that will be used to load
162 -- projects (Child_Env).
164 function Get_Attribute_Index
165 (Tree : Project_Node_Tree_Ref;
166 Attr : Project_Node_Id;
167 Index : Name_Id) return Name_Id;
168 -- Copy the index of the attribute into Name_Buffer, converting to lower
169 -- case if the attribute is case-insensitive.
175 procedure Add (To_Exp : in out Name_Id; Str : Name_Id) is
177 if To_Exp = No_Name or else To_Exp = Empty_String then
179 -- To_Exp is nil or empty. The result is Str
183 -- If Str is nil, then do not change To_Ext
185 elsif Str /= No_Name and then Str /= Empty_String then
187 S : constant String := Get_Name_String (Str);
189 Get_Name_String (To_Exp);
190 Add_Str_To_Name_Buffer (S);
200 procedure Add_Attributes
201 (Project : Project_Id;
202 Project_Name : Name_Id;
203 Project_Dir : Name_Id;
204 Shared : Shared_Project_Tree_Data_Access;
205 Decl : in out Declarations;
206 First : Attribute_Node_Id;
207 Project_Level : Boolean)
209 The_Attribute : Attribute_Node_Id := First;
212 while The_Attribute /= Empty_Attribute loop
213 if Attribute_Kind_Of (The_Attribute) = Single then
215 New_Attribute : Variable_Value;
218 case Variable_Kind_Of (The_Attribute) is
220 -- Undefined should not happen
224 (False, "attribute with an undefined kind");
227 -- Single attributes have a default value of empty string
233 Location => No_Location,
235 Value => Empty_String,
238 -- Special cases of <project>'Name and
239 -- <project>'Project_Dir.
241 if Project_Level then
242 if Attribute_Name_Of (The_Attribute) =
245 New_Attribute.Value := Project_Name;
247 elsif Attribute_Name_Of (The_Attribute) =
248 Snames.Name_Project_Dir
250 New_Attribute.Value := Project_Dir;
254 -- List attributes have a default value of nil list
260 Location => No_Location,
262 Values => Nil_String);
266 Variable_Element_Table.Increment_Last
267 (Shared.Variable_Elements);
268 Shared.Variable_Elements.Table
269 (Variable_Element_Table.Last (Shared.Variable_Elements)) :=
270 (Next => Decl.Attributes,
271 Name => Attribute_Name_Of (The_Attribute),
272 Value => New_Attribute);
274 Variable_Element_Table.Last
275 (Shared.Variable_Elements);
279 The_Attribute := Next_Attribute (After => The_Attribute);
288 (In_Tree : Project_Tree_Ref;
289 Project : Project_Id;
290 Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
291 Flags : Processing_Flags)
294 Process_Naming_Scheme (In_Tree, Project, Node_Tree, Flags);
296 -- Set the Other_Part field for the units
302 Iter : Source_Iterator;
307 Iter := For_Each_Source (In_Tree);
309 Source1 := Prj.Element (Iter);
310 exit when Source1 = No_Source;
312 if Source1.Unit /= No_Unit_Index then
313 Name := Source1.Unit.Name;
314 Source2 := Unit_Htable.Get (Name);
316 if Source2 = No_Source then
317 Unit_Htable.Set (K => Name, E => Source1);
319 Unit_Htable.Remove (Name);
328 -------------------------------
329 -- Copy_Package_Declarations --
330 -------------------------------
332 procedure Copy_Package_Declarations
333 (From : Declarations;
334 To : in out Declarations;
335 New_Loc : Source_Ptr;
336 Restricted : Boolean;
337 Shared : Shared_Project_Tree_Data_Access)
340 V2 : Variable_Id := No_Variable;
343 A2 : Array_Id := No_Array;
345 E1 : Array_Element_Id;
346 E2 : Array_Element_Id := No_Array_Element;
350 -- To avoid references in error messages to attribute declarations in
351 -- an original package that has been renamed, copy all the attribute
352 -- declarations of the package and change all locations to New_Loc,
353 -- the location of the renamed package.
355 -- First single attributes
357 V1 := From.Attributes;
358 while V1 /= No_Variable loop
360 -- Copy the attribute
362 Var := Shared.Variable_Elements.Table (V1);
365 -- Do not copy the value of attribute Linker_Options if Restricted
367 if Restricted and then Var.Name = Snames.Name_Linker_Options then
368 Var.Value.Values := Nil_String;
371 -- Remove the Next component
373 Var.Next := No_Variable;
375 -- Change the location to New_Loc
377 Var.Value.Location := New_Loc;
378 Variable_Element_Table.Increment_Last (Shared.Variable_Elements);
380 -- Put in new declaration
382 if To.Attributes = No_Variable then
384 Variable_Element_Table.Last (Shared.Variable_Elements);
386 Shared.Variable_Elements.Table (V2).Next :=
387 Variable_Element_Table.Last (Shared.Variable_Elements);
390 V2 := Variable_Element_Table.Last (Shared.Variable_Elements);
391 Shared.Variable_Elements.Table (V2) := Var;
394 -- Then the associated array attributes
397 while A1 /= No_Array loop
398 Arr := Shared.Arrays.Table (A1);
403 (Arr.Name /= Snames.Name_Body and then
404 Arr.Name /= Snames.Name_Spec and then
405 Arr.Name /= Snames.Name_Implementation and then
406 Arr.Name /= Snames.Name_Specification)
408 -- Remove the Next component
410 Arr.Next := No_Array;
411 Array_Table.Increment_Last (Shared.Arrays);
413 -- Create new Array declaration
415 if To.Arrays = No_Array then
416 To.Arrays := Array_Table.Last (Shared.Arrays);
418 Shared.Arrays.Table (A2).Next :=
419 Array_Table.Last (Shared.Arrays);
422 A2 := Array_Table.Last (Shared.Arrays);
424 -- Don't store the array as its first element has not been set yet
426 -- Copy the array elements of the array
429 Arr.Value := No_Array_Element;
430 while E1 /= No_Array_Element loop
432 -- Copy the array element
434 Elm := Shared.Array_Elements.Table (E1);
437 -- Remove the Next component
439 Elm.Next := No_Array_Element;
441 -- Change the location
443 Elm.Value.Location := New_Loc;
444 Array_Element_Table.Increment_Last (Shared.Array_Elements);
446 -- Create new array element
448 if Arr.Value = No_Array_Element then
450 Array_Element_Table.Last (Shared.Array_Elements);
452 Shared.Array_Elements.Table (E2).Next :=
453 Array_Element_Table.Last (Shared.Array_Elements);
456 E2 := Array_Element_Table.Last (Shared.Array_Elements);
457 Shared.Array_Elements.Table (E2) := Elm;
460 -- Finally, store the new array
462 Shared.Arrays.Table (A2) := Arr;
465 end Copy_Package_Declarations;
467 -------------------------
468 -- Get_Attribute_Index --
469 -------------------------
471 function Get_Attribute_Index
472 (Tree : Project_Node_Tree_Ref;
473 Attr : Project_Node_Id;
474 Index : Name_Id) return Name_Id
477 if Index = All_Other_Names
478 or else not Case_Insensitive (Attr, Tree)
483 Get_Name_String (Index);
484 To_Lower (Name_Buffer (1 .. Name_Len));
486 end Get_Attribute_Index;
493 (Project : Project_Id;
494 Shared : Shared_Project_Tree_Data_Access;
495 From_Project_Node : Project_Node_Id;
496 From_Project_Node_Tree : Project_Node_Tree_Ref;
497 Env : Prj.Tree.Environment;
499 First_Term : Project_Node_Id;
500 Kind : Variable_Kind) return Variable_Value
502 The_Term : Project_Node_Id;
503 -- The term in the expression list
505 The_Current_Term : Project_Node_Id := Empty_Node;
506 -- The current term node id
508 Result : Variable_Value (Kind => Kind);
509 -- The returned result
511 Last : String_List_Id := Nil_String;
512 -- Reference to the last string elements in Result, when Kind is List
515 Result.Project := Project;
516 Result.Location := Location_Of (First_Term, From_Project_Node_Tree);
518 -- Process each term of the expression, starting with First_Term
520 The_Term := First_Term;
521 while Present (The_Term) loop
522 The_Current_Term := Current_Term (The_Term, From_Project_Node_Tree);
524 case Kind_Of (The_Current_Term, From_Project_Node_Tree) is
526 when N_Literal_String =>
532 -- Should never happen
534 pragma Assert (False, "Undefined expression kind");
540 (The_Current_Term, From_Project_Node_Tree));
543 (The_Current_Term, From_Project_Node_Tree);
547 String_Element_Table.Increment_Last
548 (Shared.String_Elements);
550 if Last = Nil_String then
552 -- This can happen in an expression like () & "toto"
554 Result.Values := String_Element_Table.Last
555 (Shared.String_Elements);
558 Shared.String_Elements.Table
559 (Last).Next := String_Element_Table.Last
560 (Shared.String_Elements);
563 Last := String_Element_Table.Last
564 (Shared.String_Elements);
566 Shared.String_Elements.Table (Last) :=
567 (Value => String_Value_Of
569 From_Project_Node_Tree),
570 Index => Source_Index_Of
572 From_Project_Node_Tree),
573 Display_Value => No_Name,
574 Location => Location_Of
576 From_Project_Node_Tree),
581 when N_Literal_String_List =>
584 String_Node : Project_Node_Id :=
585 First_Expression_In_List
587 From_Project_Node_Tree);
589 Value : Variable_Value;
592 if Present (String_Node) then
594 -- If String_Node is nil, it is an empty list, there is
600 From_Project_Node => From_Project_Node,
601 From_Project_Node_Tree => From_Project_Node_Tree,
606 (String_Node, From_Project_Node_Tree),
608 String_Element_Table.Increment_Last
609 (Shared.String_Elements);
611 if Result.Values = Nil_String then
613 -- This literal string list is the first term in a
614 -- string list expression
617 String_Element_Table.Last
618 (Shared.String_Elements);
621 Shared.String_Elements.Table (Last).Next :=
622 String_Element_Table.Last (Shared.String_Elements);
626 String_Element_Table.Last (Shared.String_Elements);
628 Shared.String_Elements.Table (Last) :=
629 (Value => Value.Value,
630 Display_Value => No_Name,
631 Location => Value.Location,
634 Index => Value.Index);
637 -- Add the other element of the literal string list
638 -- one after the other.
641 Next_Expression_In_List
642 (String_Node, From_Project_Node_Tree);
644 exit when No (String_Node);
650 From_Project_Node => From_Project_Node,
651 From_Project_Node_Tree => From_Project_Node_Tree,
656 (String_Node, From_Project_Node_Tree),
659 String_Element_Table.Increment_Last
660 (Shared.String_Elements);
661 Shared.String_Elements.Table (Last).Next :=
662 String_Element_Table.Last (Shared.String_Elements);
663 Last := String_Element_Table.Last
664 (Shared.String_Elements);
665 Shared.String_Elements.Table (Last) :=
666 (Value => Value.Value,
667 Display_Value => No_Name,
668 Location => Value.Location,
671 Index => Value.Index);
676 when N_Variable_Reference | N_Attribute_Reference =>
679 The_Project : Project_Id := Project;
680 The_Package : Package_Id := Pkg;
681 The_Name : Name_Id := No_Name;
682 The_Variable_Id : Variable_Id := No_Variable;
683 The_Variable : Variable_Value;
684 Term_Project : constant Project_Node_Id :=
687 From_Project_Node_Tree);
688 Term_Package : constant Project_Node_Id :=
691 From_Project_Node_Tree);
692 Index : Name_Id := No_Name;
695 if Present (Term_Project) and then
696 Term_Project /= From_Project_Node
698 -- This variable or attribute comes from another project
701 Name_Of (Term_Project, From_Project_Node_Tree);
702 The_Project := Imported_Or_Extended_Project_From
704 With_Name => The_Name);
707 if Present (Term_Package) then
709 -- This is an attribute of a package
712 Name_Of (Term_Package, From_Project_Node_Tree);
714 The_Package := The_Project.Decl.Packages;
715 while The_Package /= No_Package
716 and then Shared.Packages.Table (The_Package).Name /=
720 Shared.Packages.Table (The_Package).Next;
724 (The_Package /= No_Package, "package not found.");
726 elsif Kind_Of (The_Current_Term, From_Project_Node_Tree) =
727 N_Attribute_Reference
729 The_Package := No_Package;
733 Name_Of (The_Current_Term, From_Project_Node_Tree);
735 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
736 N_Attribute_Reference
739 Associative_Array_Index_Of
740 (The_Current_Term, From_Project_Node_Tree);
743 -- If it is not an associative array attribute
745 if Index = No_Name then
747 -- It is not an associative array attribute
749 if The_Package /= No_Package then
751 -- First, if there is a package, look into the package
753 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
757 Shared.Packages.Table
758 (The_Package).Decl.Variables;
761 Shared.Packages.Table
762 (The_Package).Decl.Attributes;
765 while The_Variable_Id /= No_Variable
766 and then Shared.Variable_Elements.Table
767 (The_Variable_Id).Name /= The_Name
770 Shared.Variable_Elements.Table
771 (The_Variable_Id).Next;
776 if The_Variable_Id = No_Variable then
778 -- If we have not found it, look into the project
780 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
783 The_Variable_Id := The_Project.Decl.Variables;
785 The_Variable_Id := The_Project.Decl.Attributes;
788 while The_Variable_Id /= No_Variable
789 and then Shared.Variable_Elements.Table
790 (The_Variable_Id).Name /= The_Name
793 Shared.Variable_Elements.Table
794 (The_Variable_Id).Next;
799 pragma Assert (The_Variable_Id /= No_Variable,
800 "variable or attribute not found");
803 Shared.Variable_Elements.Table (The_Variable_Id).Value;
807 -- It is an associative array attribute
810 The_Array : Array_Id := No_Array;
811 The_Element : Array_Element_Id := No_Array_Element;
812 Array_Index : Name_Id := No_Name;
815 if The_Package /= No_Package then
817 Shared.Packages.Table (The_Package).Decl.Arrays;
819 The_Array := The_Project.Decl.Arrays;
822 while The_Array /= No_Array
823 and then Shared.Arrays.Table (The_Array).Name /=
826 The_Array := Shared.Arrays.Table (The_Array).Next;
829 if The_Array /= No_Array then
831 Shared.Arrays.Table (The_Array).Value;
834 (From_Project_Node_Tree,
838 while The_Element /= No_Array_Element
839 and then Shared.Array_Elements.Table
840 (The_Element).Index /= Array_Index
843 Shared.Array_Elements.Table (The_Element).Next;
848 if The_Element /= No_Array_Element then
850 Shared.Array_Elements.Table (The_Element).Value;
853 if Expression_Kind_Of
854 (The_Current_Term, From_Project_Node_Tree) =
860 Location => No_Location,
862 Values => Nil_String);
867 Location => No_Location,
869 Value => Empty_String,
880 -- Should never happen
882 pragma Assert (False, "undefined expression kind");
887 case The_Variable.Kind is
893 Add (Result.Value, The_Variable.Value);
897 -- Should never happen
901 "list cannot appear in single " &
902 "string expression");
907 case The_Variable.Kind is
913 String_Element_Table.Increment_Last
914 (Shared.String_Elements);
916 if Last = Nil_String then
918 -- This can happen in an expression such as
922 String_Element_Table.Last
923 (Shared.String_Elements);
926 Shared.String_Elements.Table (Last).Next :=
927 String_Element_Table.Last
928 (Shared.String_Elements);
932 String_Element_Table.Last
933 (Shared.String_Elements);
935 Shared.String_Elements.Table (Last) :=
936 (Value => The_Variable.Value,
937 Display_Value => No_Name,
938 Location => Location_Of
940 From_Project_Node_Tree),
948 The_List : String_List_Id :=
952 while The_List /= Nil_String loop
953 String_Element_Table.Increment_Last
954 (Shared.String_Elements);
956 if Last = Nil_String then
958 String_Element_Table.Last
959 (Shared.String_Elements);
963 String_Elements.Table (Last).Next :=
964 String_Element_Table.Last
965 (Shared.String_Elements);
970 String_Element_Table.Last
971 (Shared.String_Elements);
973 Shared.String_Elements.Table
976 Shared.String_Elements.Table
978 Display_Value => No_Name,
982 From_Project_Node_Tree),
987 The_List := Shared.String_Elements.Table
995 when N_External_Value =>
998 (External_Reference_Of
999 (The_Current_Term, From_Project_Node_Tree),
1000 From_Project_Node_Tree));
1003 Name : constant Name_Id := Name_Find;
1004 Default : Name_Id := No_Name;
1005 Value : Name_Id := No_Name;
1006 Ext_List : Boolean := False;
1007 Str_List : String_List_Access := null;
1008 Def_Var : Variable_Value;
1010 Default_Node : constant Project_Node_Id :=
1013 From_Project_Node_Tree);
1016 -- If there is a default value for the external reference,
1019 if Present (Default_Node) then
1020 Def_Var := Expression
1021 (Project => Project,
1023 From_Project_Node => From_Project_Node,
1024 From_Project_Node_Tree => From_Project_Node_Tree,
1029 (Default_Node, From_Project_Node_Tree),
1032 if Def_Var /= Nil_Variable_Value then
1033 Default := Def_Var.Value;
1037 Ext_List := Expression_Kind_Of
1039 From_Project_Node_Tree) = List;
1042 Value := Prj.Ext.Value_Of (Env.External, Name, No_Name);
1044 if Value /= No_Name then
1046 Sep : constant String :=
1047 Get_Name_String (Default);
1048 First : Positive := 1;
1050 Done : Boolean := False;
1054 Get_Name_String (Value);
1057 or else Sep'Length = 0
1058 or else Name_Buffer (1 .. Name_Len) = Sep
1063 if not Done and then Name_Len < Sep'Length then
1067 (Name_Buffer (1 .. Name_Len)));
1072 if Name_Buffer (1 .. Sep'Length) = Sep then
1073 First := Sep'Length + 1;
1076 if Name_Len - First + 1 >= Sep'Length
1078 Name_Buffer (Name_Len - Sep'Length + 1 ..
1081 Name_Len := Name_Len - Sep'Length;
1084 if Name_Len = 0 then
1086 new String_List'(1 => new String'(""));
1093 -- Count the number of strings
1096 Saved : constant Positive := First;
1104 Name_Buffer (First .. Name_Len),
1108 First := Lst + Sep'Length;
1114 Str_List := new String_List (1 .. Nmb);
1116 -- Populate the string list
1123 Name_Buffer (First .. Name_Len),
1129 (Name_Buffer (First .. Name_Len));
1135 (Name_Buffer (First .. Lst - 1));
1137 First := Lst + Sep'Length;
1147 Value := Prj.Ext.Value_Of (Env.External, Name, Default);
1149 if Value = No_Name then
1150 if not Quiet_Output then
1152 (Env.Flags, "?undefined external reference",
1154 (The_Current_Term, From_Project_Node_Tree),
1158 Value := Empty_String;
1172 Add (Result.Value, Value);
1176 if not Ext_List or else Str_List /= null then
1177 String_Element_Table.Increment_Last
1178 (Shared.String_Elements);
1180 if Last = Nil_String then
1182 String_Element_Table.Last
1183 (Shared.String_Elements);
1186 Shared.String_Elements.Table (Last).Next
1187 := String_Element_Table.Last
1188 (Shared.String_Elements);
1191 Last := String_Element_Table.Last
1192 (Shared.String_Elements);
1195 for Ind in Str_List'Range loop
1197 Add_Str_To_Name_Buffer (Str_List (Ind).all);
1199 Shared.String_Elements.Table (Last) :=
1201 Display_Value => No_Name,
1205 From_Project_Node_Tree),
1210 if Ind /= Str_List'Last then
1211 String_Element_Table.Increment_Last
1212 (Shared.String_Elements);
1213 Shared.String_Elements.Table (Last).Next :=
1214 String_Element_Table.Last
1215 (Shared.String_Elements);
1216 Last := String_Element_Table.Last
1217 (Shared.String_Elements);
1222 Shared.String_Elements.Table (Last) :=
1224 Display_Value => No_Name,
1228 From_Project_Node_Tree),
1239 -- Should never happen
1243 "illegal node kind in an expression");
1244 raise Program_Error;
1248 The_Term := Next_Term (The_Term, From_Project_Node_Tree);
1254 ---------------------------------------
1255 -- Imported_Or_Extended_Project_From --
1256 ---------------------------------------
1258 function Imported_Or_Extended_Project_From
1259 (Project : Project_Id;
1260 With_Name : Name_Id) return Project_Id
1262 List : Project_List;
1263 Result : Project_Id;
1264 Temp_Result : Project_Id;
1267 -- First check if it is the name of an extended project
1269 Result := Project.Extends;
1270 while Result /= No_Project loop
1271 if Result.Name = With_Name then
1274 Result := Result.Extends;
1278 -- Then check the name of each imported project
1280 Temp_Result := No_Project;
1281 List := Project.Imported_Projects;
1282 while List /= null loop
1283 Result := List.Project;
1285 -- If the project is directly imported, then returns its ID
1287 if Result.Name = With_Name then
1291 -- If a project extending the project is imported, then keep this
1292 -- extending project as a possibility. It will be the returned ID
1293 -- if the project is not imported directly.
1299 Proj := Result.Extends;
1300 while Proj /= No_Project loop
1301 if Proj.Name = With_Name then
1302 Temp_Result := Result;
1306 Proj := Proj.Extends;
1313 pragma Assert (Temp_Result /= No_Project, "project not found");
1315 end Imported_Or_Extended_Project_From;
1321 function Package_From
1322 (Project : Project_Id;
1323 Shared : Shared_Project_Tree_Data_Access;
1324 With_Name : Name_Id) return Package_Id
1326 Result : Package_Id := Project.Decl.Packages;
1329 -- Check the name of each existing package of Project
1331 while Result /= No_Package
1332 and then Shared.Packages.Table (Result).Name /= With_Name
1334 Result := Shared.Packages.Table (Result).Next;
1337 if Result = No_Package then
1339 -- Should never happen
1341 Write_Line ("package """ & Get_Name_String (With_Name) &
1343 raise Program_Error;
1355 (In_Tree : Project_Tree_Ref;
1356 Project : out Project_Id;
1357 Success : out Boolean;
1358 From_Project_Node : Project_Node_Id;
1359 From_Project_Node_Tree : Project_Node_Tree_Ref;
1360 Env : in out Prj.Tree.Environment;
1361 Reset_Tree : Boolean := True)
1364 Process_Project_Tree_Phase_1
1365 (In_Tree => In_Tree,
1368 From_Project_Node => From_Project_Node,
1369 From_Project_Node_Tree => From_Project_Node_Tree,
1371 Reset_Tree => Reset_Tree);
1373 if Project_Qualifier_Of (From_Project_Node, From_Project_Node_Tree) /=
1376 Process_Project_Tree_Phase_2
1377 (In_Tree => In_Tree,
1380 From_Project_Node => From_Project_Node,
1381 From_Project_Node_Tree => From_Project_Node_Tree,
1386 -------------------------------
1387 -- Process_Declarative_Items --
1388 -------------------------------
1390 procedure Process_Declarative_Items
1391 (Project : Project_Id;
1392 In_Tree : Project_Tree_Ref;
1393 From_Project_Node : Project_Node_Id;
1394 Node_Tree : Project_Node_Tree_Ref;
1395 Env : Prj.Tree.Environment;
1397 Item : Project_Node_Id;
1398 Child_Env : in out Prj.Tree.Environment)
1400 Shared : constant Shared_Project_Tree_Data_Access :=
1403 procedure Check_Or_Set_Typed_Variable
1404 (Value : in out Variable_Value;
1405 Declaration : Project_Node_Id);
1406 -- Check whether Value is valid for this typed variable declaration. If
1407 -- it is an error, the behavior depends on the flags: either an error is
1408 -- reported, or a warning, or nothing. In the last two cases, the value
1409 -- of the variable is set to a valid value, replacing Value.
1411 procedure Process_Package_Declaration
1412 (Current_Item : Project_Node_Id);
1413 procedure Process_Attribute_Declaration
1414 (Current : Project_Node_Id);
1415 procedure Process_Case_Construction
1416 (Current_Item : Project_Node_Id);
1417 procedure Process_Associative_Array
1418 (Current_Item : Project_Node_Id);
1419 procedure Process_Expression
1420 (Current : Project_Node_Id);
1421 procedure Process_Expression_For_Associative_Array
1422 (Current : Project_Node_Id;
1423 New_Value : Variable_Value);
1424 procedure Process_Expression_Variable_Decl
1425 (Current_Item : Project_Node_Id;
1426 New_Value : Variable_Value);
1427 -- Process the various declarative items
1429 ---------------------------------
1430 -- Check_Or_Set_Typed_Variable --
1431 ---------------------------------
1433 procedure Check_Or_Set_Typed_Variable
1434 (Value : in out Variable_Value;
1435 Declaration : Project_Node_Id)
1437 Loc : constant Source_Ptr := Location_Of (Declaration, Node_Tree);
1439 Reset_Value : Boolean := False;
1440 Current_String : Project_Node_Id;
1443 -- Report an error for an empty string
1445 if Value.Value = Empty_String then
1446 Error_Msg_Name_1 := Name_Of (Declaration, Node_Tree);
1448 case Env.Flags.Allow_Invalid_External is
1451 (Env.Flags, "no value defined for %%", Loc, Project);
1453 Reset_Value := True;
1455 (Env.Flags, "?no value defined for %%", Loc, Project);
1457 Reset_Value := True;
1461 -- Loop through all the valid strings for the
1462 -- string type and compare to the string value.
1465 First_Literal_String
1466 (String_Type_Of (Declaration, Node_Tree), Node_Tree);
1468 while Present (Current_String)
1469 and then String_Value_Of (Current_String, Node_Tree) /=
1473 Next_Literal_String (Current_String, Node_Tree);
1476 -- Report error if string value is not one for the string type
1478 if No (Current_String) then
1479 Error_Msg_Name_1 := Value.Value;
1480 Error_Msg_Name_2 := Name_Of (Declaration, Node_Tree);
1482 case Env.Flags.Allow_Invalid_External is
1485 (Env.Flags, "value %% is illegal for typed string %%",
1490 (Env.Flags, "?value %% is illegal for typed string %%",
1492 Reset_Value := True;
1495 Reset_Value := True;
1502 First_Literal_String
1503 (String_Type_Of (Declaration, Node_Tree), Node_Tree);
1504 Value.Value := String_Value_Of (Current_String, Node_Tree);
1506 end Check_Or_Set_Typed_Variable;
1508 ---------------------------------
1509 -- Process_Package_Declaration --
1510 ---------------------------------
1512 procedure Process_Package_Declaration
1513 (Current_Item : Project_Node_Id)
1516 -- Do not process a package declaration that should be ignored
1518 if Expression_Kind_Of (Current_Item, Node_Tree) /= Ignored then
1520 -- Create the new package
1522 Package_Table.Increment_Last (Shared.Packages);
1525 New_Pkg : constant Package_Id :=
1526 Package_Table.Last (Shared.Packages);
1527 The_New_Package : Package_Element;
1529 Project_Of_Renamed_Package : constant Project_Node_Id :=
1530 Project_Of_Renamed_Package_Of
1531 (Current_Item, Node_Tree);
1534 -- Set the name of the new package
1536 The_New_Package.Name := Name_Of (Current_Item, Node_Tree);
1538 -- Insert the new package in the appropriate list
1540 if Pkg /= No_Package then
1541 The_New_Package.Next :=
1542 Shared.Packages.Table (Pkg).Decl.Packages;
1543 Shared.Packages.Table (Pkg).Decl.Packages := New_Pkg;
1546 The_New_Package.Next := Project.Decl.Packages;
1547 Project.Decl.Packages := New_Pkg;
1550 Shared.Packages.Table (New_Pkg) := The_New_Package;
1552 if Present (Project_Of_Renamed_Package) then
1554 -- Renamed or extending package
1557 Project_Name : constant Name_Id :=
1558 Name_Of (Project_Of_Renamed_Package, Node_Tree);
1560 Renamed_Project : constant Project_Id :=
1561 Imported_Or_Extended_Project_From
1562 (Project, Project_Name);
1564 Renamed_Package : constant Package_Id :=
1566 (Renamed_Project, Shared,
1567 Name_Of (Current_Item, Node_Tree));
1570 -- For a renamed package, copy the declarations of the
1571 -- renamed package, but set all the locations to the
1572 -- location of the package name in the renaming
1575 Copy_Package_Declarations
1576 (From => Shared.Packages.Table (Renamed_Package).Decl,
1577 To => Shared.Packages.Table (New_Pkg).Decl,
1578 New_Loc => Location_Of (Current_Item, Node_Tree),
1579 Restricted => False,
1584 -- Set the default values of the attributes
1589 Name_Id (Project.Directory.Name),
1591 Shared.Packages.Table (New_Pkg).Decl,
1593 (Package_Id_Of (Current_Item, Node_Tree)),
1594 Project_Level => False);
1597 -- Process declarative items (nothing to do when the package is
1598 -- renaming, as the first declarative item is null).
1600 Process_Declarative_Items
1601 (Project => Project,
1603 From_Project_Node => From_Project_Node,
1604 Node_Tree => Node_Tree,
1608 First_Declarative_Item_Of (Current_Item, Node_Tree),
1609 Child_Env => Child_Env);
1612 end Process_Package_Declaration;
1614 -------------------------------
1615 -- Process_Associative_Array --
1616 -------------------------------
1618 procedure Process_Associative_Array
1619 (Current_Item : Project_Node_Id)
1621 Current_Item_Name : constant Name_Id :=
1622 Name_Of (Current_Item, Node_Tree);
1623 -- The name of the attribute
1625 Current_Location : constant Source_Ptr :=
1626 Location_Of (Current_Item, Node_Tree);
1628 New_Array : Array_Id;
1629 -- The new associative array created
1631 Orig_Array : Array_Id;
1632 -- The associative array value
1634 Orig_Project_Name : Name_Id := No_Name;
1635 -- The name of the project where the associative array
1638 Orig_Project : Project_Id := No_Project;
1639 -- The id of the project where the associative array
1642 Orig_Package_Name : Name_Id := No_Name;
1643 -- The name of the package, if any, where the associative array value
1646 Orig_Package : Package_Id := No_Package;
1647 -- The id of the package, if any, where the associative array value
1650 New_Element : Array_Element_Id := No_Array_Element;
1651 -- Id of a new array element created
1653 Prev_Element : Array_Element_Id := No_Array_Element;
1654 -- Last new element id created
1656 Orig_Element : Array_Element_Id := No_Array_Element;
1657 -- Current array element in original associative array
1659 Next_Element : Array_Element_Id := No_Array_Element;
1660 -- Id of the array element that follows the new element. This is not
1661 -- always nil, because values for the associative array attribute may
1662 -- already have been declared, and the array elements declared are
1668 -- First find if the associative array attribute already has elements
1671 if Pkg /= No_Package then
1672 New_Array := Shared.Packages.Table (Pkg).Decl.Arrays;
1674 New_Array := Project.Decl.Arrays;
1677 while New_Array /= No_Array
1678 and then Shared.Arrays.Table (New_Array).Name /= Current_Item_Name
1680 New_Array := Shared.Arrays.Table (New_Array).Next;
1683 -- If the attribute has never been declared add new entry in the
1684 -- arrays of the project/package and link it.
1686 if New_Array = No_Array then
1687 Array_Table.Increment_Last (Shared.Arrays);
1688 New_Array := Array_Table.Last (Shared.Arrays);
1690 if Pkg /= No_Package then
1691 Shared.Arrays.Table (New_Array) :=
1692 (Name => Current_Item_Name,
1693 Location => Current_Location,
1694 Value => No_Array_Element,
1695 Next => Shared.Packages.Table (Pkg).Decl.Arrays);
1697 Shared.Packages.Table (Pkg).Decl.Arrays := New_Array;
1700 Shared.Arrays.Table (New_Array) :=
1701 (Name => Current_Item_Name,
1702 Location => Current_Location,
1703 Value => No_Array_Element,
1704 Next => Project.Decl.Arrays);
1706 Project.Decl.Arrays := New_Array;
1710 -- Find the project where the value is declared
1712 Orig_Project_Name :=
1714 (Associative_Project_Of (Current_Item, Node_Tree), Node_Tree);
1716 Prj := In_Tree.Projects;
1717 while Prj /= null loop
1718 if Prj.Project.Name = Orig_Project_Name then
1719 Orig_Project := Prj.Project;
1725 pragma Assert (Orig_Project /= No_Project,
1726 "original project not found");
1728 if No (Associative_Package_Of (Current_Item, Node_Tree)) then
1729 Orig_Array := Orig_Project.Decl.Arrays;
1732 -- If in a package, find the package where the value is declared
1734 Orig_Package_Name :=
1736 (Associative_Package_Of (Current_Item, Node_Tree), Node_Tree);
1738 Orig_Package := Orig_Project.Decl.Packages;
1739 pragma Assert (Orig_Package /= No_Package,
1740 "original package not found");
1742 while Shared.Packages.Table
1743 (Orig_Package).Name /= Orig_Package_Name
1745 Orig_Package := Shared.Packages.Table (Orig_Package).Next;
1746 pragma Assert (Orig_Package /= No_Package,
1747 "original package not found");
1750 Orig_Array := Shared.Packages.Table (Orig_Package).Decl.Arrays;
1753 -- Now look for the array
1755 while Orig_Array /= No_Array
1756 and then Shared.Arrays.Table (Orig_Array).Name /= Current_Item_Name
1758 Orig_Array := Shared.Arrays.Table (Orig_Array).Next;
1761 if Orig_Array = No_Array then
1764 "associative array value not found",
1765 Location_Of (Current_Item, Node_Tree),
1769 Orig_Element := Shared.Arrays.Table (Orig_Array).Value;
1771 -- Copy each array element
1773 while Orig_Element /= No_Array_Element loop
1775 -- Case of first element
1777 if Prev_Element = No_Array_Element then
1779 -- And there is no array element declared yet, create a new
1780 -- first array element.
1782 if Shared.Arrays.Table (New_Array).Value =
1785 Array_Element_Table.Increment_Last
1786 (Shared.Array_Elements);
1787 New_Element := Array_Element_Table.Last
1788 (Shared.Array_Elements);
1789 Shared.Arrays.Table (New_Array).Value := New_Element;
1790 Next_Element := No_Array_Element;
1792 -- Otherwise, the new element is the first
1795 New_Element := Shared.Arrays.Table (New_Array).Value;
1797 Shared.Array_Elements.Table (New_Element).Next;
1800 -- Otherwise, reuse an existing element, or create
1801 -- one if necessary.
1805 Shared.Array_Elements.Table (Prev_Element).Next;
1807 if Next_Element = No_Array_Element then
1808 Array_Element_Table.Increment_Last
1809 (Shared.Array_Elements);
1810 New_Element := Array_Element_Table.Last
1811 (Shared.Array_Elements);
1812 Shared.Array_Elements.Table (Prev_Element).Next :=
1816 New_Element := Next_Element;
1818 Shared.Array_Elements.Table (New_Element).Next;
1822 -- Copy the value of the element
1824 Shared.Array_Elements.Table (New_Element) :=
1825 Shared.Array_Elements.Table (Orig_Element);
1826 Shared.Array_Elements.Table (New_Element).Value.Project
1829 -- Adjust the Next link
1831 Shared.Array_Elements.Table (New_Element).Next := Next_Element;
1833 -- Adjust the previous id for the next element
1835 Prev_Element := New_Element;
1837 -- Go to the next element in the original array
1839 Orig_Element := Shared.Array_Elements.Table (Orig_Element).Next;
1842 -- Make sure that the array ends here, in case there previously a
1843 -- greater number of elements.
1845 Shared.Array_Elements.Table (New_Element).Next := No_Array_Element;
1847 end Process_Associative_Array;
1849 ----------------------------------------------
1850 -- Process_Expression_For_Associative_Array --
1851 ----------------------------------------------
1853 procedure Process_Expression_For_Associative_Array
1854 (Current : Project_Node_Id;
1855 New_Value : Variable_Value)
1857 Name : constant Name_Id := Name_Of (Current, Node_Tree);
1858 Current_Location : constant Source_Ptr :=
1859 Location_Of (Current, Node_Tree);
1861 Index_Name : Name_Id :=
1862 Associative_Array_Index_Of (Current, Node_Tree);
1864 Source_Index : constant Int :=
1865 Source_Index_Of (Current, Node_Tree);
1867 The_Array : Array_Id;
1868 Elem : Array_Element_Id := No_Array_Element;
1871 if Index_Name /= All_Other_Names then
1872 Index_Name := Get_Attribute_Index (Node_Tree, Current, Index_Name);
1875 -- Look for the array in the appropriate list
1877 if Pkg /= No_Package then
1878 The_Array := Shared.Packages.Table (Pkg).Decl.Arrays;
1880 The_Array := Project.Decl.Arrays;
1883 while The_Array /= No_Array
1884 and then Shared.Arrays.Table (The_Array).Name /= Name
1886 The_Array := Shared.Arrays.Table (The_Array).Next;
1889 -- If the array cannot be found, create a new entry in the list.
1890 -- As The_Array_Element is initialized to No_Array_Element, a new
1891 -- element will be created automatically later
1893 if The_Array = No_Array then
1894 Array_Table.Increment_Last (Shared.Arrays);
1895 The_Array := Array_Table.Last (Shared.Arrays);
1897 if Pkg /= No_Package then
1898 Shared.Arrays.Table (The_Array) :=
1900 Location => Current_Location,
1901 Value => No_Array_Element,
1902 Next => Shared.Packages.Table (Pkg).Decl.Arrays);
1904 Shared.Packages.Table (Pkg).Decl.Arrays := The_Array;
1907 Shared.Arrays.Table (The_Array) :=
1909 Location => Current_Location,
1910 Value => No_Array_Element,
1911 Next => Project.Decl.Arrays);
1913 Project.Decl.Arrays := The_Array;
1917 Elem := Shared.Arrays.Table (The_Array).Value;
1920 -- Look in the list, if any, to find an element with the same index
1921 -- and same source index.
1923 while Elem /= No_Array_Element
1925 (Shared.Array_Elements.Table (Elem).Index /= Index_Name
1927 Shared.Array_Elements.Table (Elem).Src_Index /= Source_Index)
1929 Elem := Shared.Array_Elements.Table (Elem).Next;
1932 -- If no such element were found, create a new one
1933 -- and insert it in the element list, with the
1936 if Elem = No_Array_Element then
1937 Array_Element_Table.Increment_Last (Shared.Array_Elements);
1938 Elem := Array_Element_Table.Last (Shared.Array_Elements);
1940 Shared.Array_Elements.Table
1942 (Index => Index_Name,
1943 Src_Index => Source_Index,
1944 Index_Case_Sensitive =>
1945 not Case_Insensitive (Current, Node_Tree),
1947 Next => Shared.Arrays.Table (The_Array).Value);
1949 Shared.Arrays.Table (The_Array).Value := Elem;
1952 -- An element with the same index already exists, just replace its
1953 -- value with the new one.
1955 Shared.Array_Elements.Table (Elem).Value := New_Value;
1958 if Name = Snames.Name_External then
1959 if In_Tree.Is_Root_Tree then
1960 Add (Child_Env.External,
1961 External_Name => Get_Name_String (Index_Name),
1962 Value => Get_Name_String (New_Value.Value),
1963 Source => From_External_Attribute);
1965 External_Name => Get_Name_String (Index_Name),
1966 Value => Get_Name_String (New_Value.Value),
1967 Source => From_External_Attribute);
1969 if Current_Verbosity = High then
1971 ("'for External' has no effect except in root aggregate ("
1972 & Get_Name_String (Index_Name) & ")", New_Value.Value);
1976 end Process_Expression_For_Associative_Array;
1978 --------------------------------------
1979 -- Process_Expression_Variable_Decl --
1980 --------------------------------------
1982 procedure Process_Expression_Variable_Decl
1983 (Current_Item : Project_Node_Id;
1984 New_Value : Variable_Value)
1986 Name : constant Name_Id := Name_Of (Current_Item, Node_Tree);
1988 Is_Attribute : constant Boolean :=
1989 Kind_Of (Current_Item, Node_Tree) =
1990 N_Attribute_Declaration;
1992 Var : Variable_Id := No_Variable;
1995 -- First, find the list where to find the variable or attribute
1997 if Is_Attribute then
1998 if Pkg /= No_Package then
1999 Var := Shared.Packages.Table (Pkg).Decl.Attributes;
2001 Var := Project.Decl.Attributes;
2005 if Pkg /= No_Package then
2006 Var := Shared.Packages.Table (Pkg).Decl.Variables;
2008 Var := Project.Decl.Variables;
2012 -- Loop through the list, to find if it has already been declared
2014 while Var /= No_Variable
2015 and then Shared.Variable_Elements.Table (Var).Name /= Name
2017 Var := Shared.Variable_Elements.Table (Var).Next;
2020 -- If it has not been declared, create a new entry in the list
2022 if Var = No_Variable then
2024 -- All single string attribute should already have been declared
2025 -- with a default empty string value.
2029 "illegal attribute declaration for " & Get_Name_String (Name));
2031 Variable_Element_Table.Increment_Last (Shared.Variable_Elements);
2032 Var := Variable_Element_Table.Last (Shared.Variable_Elements);
2034 -- Put the new variable in the appropriate list
2036 if Pkg /= No_Package then
2037 Shared.Variable_Elements.Table (Var) :=
2038 (Next => Shared.Packages.Table (Pkg).Decl.Variables,
2040 Value => New_Value);
2041 Shared.Packages.Table (Pkg).Decl.Variables := Var;
2044 Shared.Variable_Elements.Table (Var) :=
2045 (Next => Project.Decl.Variables,
2047 Value => New_Value);
2048 Project.Decl.Variables := Var;
2051 -- If the variable/attribute has already been declared, just
2052 -- change the value.
2055 Shared.Variable_Elements.Table (Var).Value := New_Value;
2058 if Name = Snames.Name_Project_Path then
2059 if In_Tree.Is_Root_Tree then
2061 Val : String_List_Id := New_Value.Values;
2063 while Val /= Nil_String loop
2064 Prj.Env.Add_Directories
2065 (Child_Env.Project_Path,
2067 (Shared.String_Elements.Table (Val).Value));
2068 Val := Shared.String_Elements.Table (Val).Next;
2073 if Current_Verbosity = High then
2075 ("'for Project_Path' has no effect except in"
2076 & " root aggregate");
2080 end Process_Expression_Variable_Decl;
2082 ------------------------
2083 -- Process_Expression --
2084 ------------------------
2086 procedure Process_Expression (Current : Project_Node_Id) is
2087 New_Value : Variable_Value :=
2089 (Project => Project,
2091 From_Project_Node => From_Project_Node,
2092 From_Project_Node_Tree => Node_Tree,
2097 (Expression_Of (Current, Node_Tree), Node_Tree),
2099 Expression_Kind_Of (Current, Node_Tree));
2102 -- Process a typed variable declaration
2104 if Kind_Of (Current, Node_Tree) = N_Typed_Variable_Declaration then
2105 Check_Or_Set_Typed_Variable (New_Value, Current);
2108 if Kind_Of (Current, Node_Tree) /= N_Attribute_Declaration
2109 or else Associative_Array_Index_Of (Current, Node_Tree) = No_Name
2111 Process_Expression_Variable_Decl (Current, New_Value);
2113 Process_Expression_For_Associative_Array (Current, New_Value);
2115 end Process_Expression;
2117 -----------------------------------
2118 -- Process_Attribute_Declaration --
2119 -----------------------------------
2121 procedure Process_Attribute_Declaration (Current : Project_Node_Id) is
2123 if Expression_Of (Current, Node_Tree) = Empty_Node then
2124 Process_Associative_Array (Current);
2126 Process_Expression (Current);
2128 end Process_Attribute_Declaration;
2130 -------------------------------
2131 -- Process_Case_Construction --
2132 -------------------------------
2134 procedure Process_Case_Construction
2135 (Current_Item : Project_Node_Id)
2137 The_Project : Project_Id := Project;
2138 -- The id of the project of the case variable
2140 The_Package : Package_Id := Pkg;
2141 -- The id of the package, if any, of the case variable
2143 The_Variable : Variable_Value := Nil_Variable_Value;
2144 -- The case variable
2146 Case_Value : Name_Id := No_Name;
2147 -- The case variable value
2149 Case_Item : Project_Node_Id := Empty_Node;
2150 Choice_String : Project_Node_Id := Empty_Node;
2151 Decl_Item : Project_Node_Id := Empty_Node;
2155 Variable_Node : constant Project_Node_Id :=
2156 Case_Variable_Reference_Of
2160 Var_Id : Variable_Id := No_Variable;
2161 Name : Name_Id := No_Name;
2164 -- If a project was specified for the case variable, get its id
2166 if Present (Project_Node_Of (Variable_Node, Node_Tree)) then
2169 (Project_Node_Of (Variable_Node, Node_Tree), Node_Tree);
2171 Imported_Or_Extended_Project_From (Project, Name);
2174 -- If a package was specified for the case variable, get its id
2176 if Present (Package_Node_Of (Variable_Node, Node_Tree)) then
2179 (Package_Node_Of (Variable_Node, Node_Tree), Node_Tree);
2180 The_Package := Package_From (The_Project, Shared, Name);
2183 Name := Name_Of (Variable_Node, Node_Tree);
2185 -- First, look for the case variable into the package, if any
2187 if The_Package /= No_Package then
2188 Name := Name_Of (Variable_Node, Node_Tree);
2190 Var_Id := Shared.Packages.Table (The_Package).Decl.Variables;
2191 while Var_Id /= No_Variable
2192 and then Shared.Variable_Elements.Table (Var_Id).Name /= Name
2194 Var_Id := Shared.Variable_Elements.Table (Var_Id).Next;
2198 -- If not found in the package, or if there is no package, look at
2199 -- the project level.
2201 if Var_Id = No_Variable
2202 and then No (Package_Node_Of (Variable_Node, Node_Tree))
2204 Var_Id := The_Project.Decl.Variables;
2205 while Var_Id /= No_Variable
2206 and then Shared.Variable_Elements.Table (Var_Id).Name /= Name
2208 Var_Id := Shared.Variable_Elements.Table (Var_Id).Next;
2212 if Var_Id = No_Variable then
2214 -- Should never happen, because this has already been checked
2218 ("variable """ & Get_Name_String (Name) & """ not found");
2219 raise Program_Error;
2222 -- Get the case variable
2224 The_Variable := Shared.Variable_Elements. Table (Var_Id).Value;
2226 if The_Variable.Kind /= Single then
2228 -- Should never happen, because this has already been checked
2231 Write_Line ("variable""" & Get_Name_String (Name) &
2232 """ is not a single string variable");
2233 raise Program_Error;
2236 -- Get the case variable value
2238 Case_Value := The_Variable.Value;
2241 -- Now look into all the case items of the case construction
2243 Case_Item := First_Case_Item_Of (Current_Item, Node_Tree);
2246 while Present (Case_Item) loop
2247 Choice_String := First_Choice_Of (Case_Item, Node_Tree);
2249 -- When Choice_String is nil, it means that it is the
2250 -- "when others =>" alternative.
2252 if No (Choice_String) then
2253 Decl_Item := First_Declarative_Item_Of (Case_Item, Node_Tree);
2254 exit Case_Item_Loop;
2257 -- Look into all the alternative of this case item
2260 while Present (Choice_String) loop
2261 if Case_Value = String_Value_Of (Choice_String, Node_Tree) then
2263 First_Declarative_Item_Of (Case_Item, Node_Tree);
2264 exit Case_Item_Loop;
2267 Choice_String := Next_Literal_String (Choice_String, Node_Tree);
2268 end loop Choice_Loop;
2270 Case_Item := Next_Case_Item (Case_Item, Node_Tree);
2271 end loop Case_Item_Loop;
2273 -- If there is an alternative, then we process it
2275 if Present (Decl_Item) then
2276 Process_Declarative_Items
2277 (Project => Project,
2279 From_Project_Node => From_Project_Node,
2280 Node_Tree => Node_Tree,
2284 Child_Env => Child_Env);
2286 end Process_Case_Construction;
2290 Current, Decl : Project_Node_Id;
2291 Kind : Project_Node_Kind;
2293 -- Start of processing for Process_Declarative_Items
2297 while Present (Decl) loop
2298 Current := Current_Item_Node (Decl, Node_Tree);
2299 Decl := Next_Declarative_Item (Decl, Node_Tree);
2300 Kind := Kind_Of (Current, Node_Tree);
2303 when N_Package_Declaration =>
2304 Process_Package_Declaration (Current);
2306 -- Nothing to process for string type declaration
2308 when N_String_Type_Declaration =>
2311 when N_Attribute_Declaration |
2312 N_Typed_Variable_Declaration |
2313 N_Variable_Declaration =>
2314 Process_Attribute_Declaration (Current);
2316 when N_Case_Construction =>
2317 Process_Case_Construction (Current);
2320 Write_Line ("Illegal declarative item: " & Kind'Img);
2321 raise Program_Error;
2324 end Process_Declarative_Items;
2326 ----------------------------------
2327 -- Process_Project_Tree_Phase_1 --
2328 ----------------------------------
2330 procedure Process_Project_Tree_Phase_1
2331 (In_Tree : Project_Tree_Ref;
2332 Project : out Project_Id;
2333 Success : out Boolean;
2334 From_Project_Node : Project_Node_Id;
2335 From_Project_Node_Tree : Project_Node_Tree_Ref;
2336 Env : in out Prj.Tree.Environment;
2337 Reset_Tree : Boolean := True)
2342 -- Make sure there are no projects in the data structure
2344 Free_List (In_Tree.Projects, Free_Project => True);
2347 Processed_Projects.Reset;
2349 -- And process the main project and all of the projects it depends on,
2352 Debug_Increase_Indent ("Process tree, phase 1");
2355 (Project => Project,
2357 From_Project_Node => From_Project_Node,
2358 From_Project_Node_Tree => From_Project_Node_Tree,
2360 Extended_By => No_Project);
2363 Total_Errors_Detected = 0
2365 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2367 if Current_Verbosity = High then
2368 Debug_Decrease_Indent ("Done Process tree, phase 1, Success="
2371 end Process_Project_Tree_Phase_1;
2373 ----------------------------------
2374 -- Process_Project_Tree_Phase_2 --
2375 ----------------------------------
2377 procedure Process_Project_Tree_Phase_2
2378 (In_Tree : Project_Tree_Ref;
2379 Project : Project_Id;
2380 Success : out Boolean;
2381 From_Project_Node : Project_Node_Id;
2382 From_Project_Node_Tree : Project_Node_Tree_Ref;
2385 Obj_Dir : Path_Name_Type;
2386 Extending : Project_Id;
2387 Extending2 : Project_Id;
2390 -- Start of processing for Process_Project_Tree_Phase_2
2395 Debug_Increase_Indent ("Process tree, phase 2", Project.Name);
2397 if Project /= No_Project then
2398 Check (In_Tree, Project, From_Project_Node_Tree, Env.Flags);
2401 -- If main project is an extending all project, set object directory of
2402 -- all virtual extending projects to object directory of main project.
2404 if Project /= No_Project
2406 Is_Extending_All (From_Project_Node, From_Project_Node_Tree)
2409 Object_Dir : constant Path_Information :=
2410 Project.Object_Directory;
2413 Prj := In_Tree.Projects;
2414 while Prj /= null loop
2415 if Prj.Project.Virtual then
2416 Prj.Project.Object_Directory := Object_Dir;
2424 -- Check that no extending project shares its object directory with
2425 -- the project(s) it extends.
2427 if Project /= No_Project then
2428 Prj := In_Tree.Projects;
2429 while Prj /= null loop
2430 Extending := Prj.Project.Extended_By;
2432 if Extending /= No_Project then
2433 Obj_Dir := Prj.Project.Object_Directory.Name;
2435 -- Check that a project being extended does not share its
2436 -- object directory with any project that extends it, directly
2437 -- or indirectly, including a virtual extending project.
2439 -- Start with the project directly extending it
2441 Extending2 := Extending;
2442 while Extending2 /= No_Project loop
2443 if Has_Ada_Sources (Extending2)
2444 and then Extending2.Object_Directory.Name = Obj_Dir
2446 if Extending2.Virtual then
2447 Error_Msg_Name_1 := Prj.Project.Display_Name;
2450 "project %% cannot be extended by a virtual" &
2451 " project with the same object directory",
2452 Prj.Project.Location, Project);
2455 Error_Msg_Name_1 := Extending2.Display_Name;
2456 Error_Msg_Name_2 := Prj.Project.Display_Name;
2459 "project %% cannot extend project %%",
2460 Extending2.Location, Project);
2463 "\they share the same object directory",
2464 Extending2.Location, Project);
2468 -- Continue with the next extending project, if any
2470 Extending2 := Extending2.Extended_By;
2478 Debug_Decrease_Indent ("Done Process tree, phase 2");
2481 Total_Errors_Detected = 0
2483 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2484 end Process_Project_Tree_Phase_2;
2486 -----------------------
2487 -- Recursive_Process --
2488 -----------------------
2490 procedure Recursive_Process
2491 (In_Tree : Project_Tree_Ref;
2492 Project : out Project_Id;
2493 From_Project_Node : Project_Node_Id;
2494 From_Project_Node_Tree : Project_Node_Tree_Ref;
2495 Env : in out Prj.Tree.Environment;
2496 Extended_By : Project_Id)
2498 Shared : constant Shared_Project_Tree_Data_Access :=
2501 Child_Env : Prj.Tree.Environment;
2502 -- Only used for the root aggregate project (if any). This is left
2503 -- uninitialized otherwise.
2505 procedure Process_Imported_Projects
2506 (Imported : in out Project_List;
2507 Limited_With : Boolean);
2508 -- Process imported projects. If Limited_With is True, then only
2509 -- projects processed through a "limited with" are processed, otherwise
2510 -- only projects imported through a standard "with" are processed.
2511 -- Imported is the id of the last imported project.
2513 procedure Process_Aggregated_Projects;
2514 -- Process all the projects aggregated in List. This does nothing if the
2515 -- project is not an aggregate project.
2517 procedure Process_Extended_Project;
2518 -- Process the extended project: inherit all packages from the extended
2519 -- project that are not explicitly defined or renamed. Also inherit the
2520 -- languages, if attribute Languages is not explicitly defined.
2522 -------------------------------
2523 -- Process_Imported_Projects --
2524 -------------------------------
2526 procedure Process_Imported_Projects
2527 (Imported : in out Project_List;
2528 Limited_With : Boolean)
2530 With_Clause : Project_Node_Id;
2531 New_Project : Project_Id;
2532 Proj_Node : Project_Node_Id;
2536 First_With_Clause_Of
2537 (From_Project_Node, From_Project_Node_Tree);
2539 while Present (With_Clause) loop
2541 Non_Limited_Project_Node_Of
2542 (With_Clause, From_Project_Node_Tree);
2543 New_Project := No_Project;
2545 if (Limited_With and then No (Proj_Node))
2546 or else (not Limited_With and then Present (Proj_Node))
2549 (In_Tree => In_Tree,
2550 Project => New_Project,
2551 From_Project_Node =>
2553 (With_Clause, From_Project_Node_Tree),
2554 From_Project_Node_Tree => From_Project_Node_Tree,
2556 Extended_By => No_Project);
2558 -- Imported is the id of the last imported project. If
2559 -- it is nil, then this imported project is our first.
2561 if Imported = null then
2562 Project.Imported_Projects :=
2563 new Project_List_Element'
2564 (Project => New_Project,
2566 Imported := Project.Imported_Projects;
2568 Imported.Next := new Project_List_Element'
2569 (Project => New_Project,
2571 Imported := Imported.Next;
2576 Next_With_Clause_Of (With_Clause, From_Project_Node_Tree);
2578 end Process_Imported_Projects;
2580 ---------------------------------
2581 -- Process_Aggregated_Projects --
2582 ---------------------------------
2584 procedure Process_Aggregated_Projects is
2585 List : Aggregated_Project_List;
2586 Loaded_Project : Prj.Tree.Project_Node_Id;
2587 Success : Boolean := True;
2589 if Project.Qualifier /= Aggregate then
2593 Debug_Increase_Indent ("Process_Aggregated_Projects", Project.Name);
2595 Prj.Nmsc.Process_Aggregated_Projects
2598 Node_Tree => From_Project_Node_Tree,
2599 Flags => Env.Flags);
2601 List := Project.Aggregated_Projects;
2602 while Success and then List /= null loop
2604 (In_Tree => From_Project_Node_Tree,
2605 Project => Loaded_Project,
2606 Project_File_Name => Get_Name_String (List.Path),
2607 Errout_Handling => Prj.Part.Never_Finalize,
2608 Current_Directory => Get_Name_String (Project.Directory.Name),
2609 Is_Config_File => False,
2612 Success := not Prj.Tree.No (Loaded_Project);
2615 List.Tree := new Project_Tree_Data (Is_Root_Tree => False);
2616 Prj.Initialize (List.Tree);
2617 List.Tree.Shared := In_Tree.Shared;
2619 -- We can only do the phase 1 of the processing, since we do
2620 -- not have access to the configuration file yet (this is
2621 -- called when doing phase 1 of the processing for the root
2622 -- aggregate project).
2624 if In_Tree.Is_Root_Tree then
2625 Process_Project_Tree_Phase_1
2626 (In_Tree => List.Tree,
2627 Project => List.Project,
2629 From_Project_Node => Loaded_Project,
2630 From_Project_Node_Tree => From_Project_Node_Tree,
2632 Reset_Tree => False);
2634 -- use the same environment as the rest of the aggregated
2635 -- projects, ie the one that was setup by the root aggregate
2636 Process_Project_Tree_Phase_1
2637 (In_Tree => List.Tree,
2638 Project => List.Project,
2640 From_Project_Node => Loaded_Project,
2641 From_Project_Node_Tree => From_Project_Node_Tree,
2643 Reset_Tree => False);
2646 Debug_Output ("Failed to parse", Name_Id (List.Path));
2652 Debug_Decrease_Indent ("Done Process_Aggregated_Projects");
2653 end Process_Aggregated_Projects;
2655 ------------------------------
2656 -- Process_Extended_Project --
2657 ------------------------------
2659 procedure Process_Extended_Project is
2660 Extended_Pkg : Package_Id;
2661 Current_Pkg : Package_Id;
2662 Element : Package_Element;
2663 First : constant Package_Id := Project.Decl.Packages;
2664 Attribute1 : Variable_Id;
2665 Attribute2 : Variable_Id;
2666 Attr_Value1 : Variable;
2667 Attr_Value2 : Variable;
2670 Extended_Pkg := Project.Extends.Decl.Packages;
2671 while Extended_Pkg /= No_Package loop
2672 Element := Shared.Packages.Table (Extended_Pkg);
2674 Current_Pkg := First;
2675 while Current_Pkg /= No_Package
2676 and then Shared.Packages.Table (Current_Pkg).Name /=
2679 Current_Pkg := Shared.Packages.Table (Current_Pkg).Next;
2682 if Current_Pkg = No_Package then
2683 Package_Table.Increment_Last (Shared.Packages);
2684 Current_Pkg := Package_Table.Last (Shared.Packages);
2685 Shared.Packages.Table (Current_Pkg) :=
2686 (Name => Element.Name,
2687 Decl => No_Declarations,
2688 Parent => No_Package,
2689 Next => Project.Decl.Packages);
2690 Project.Decl.Packages := Current_Pkg;
2691 Copy_Package_Declarations
2692 (From => Element.Decl,
2693 To => Shared.Packages.Table (Current_Pkg).Decl,
2694 New_Loc => No_Location,
2699 Extended_Pkg := Element.Next;
2702 -- Check if attribute Languages is declared in the extending project
2704 Attribute1 := Project.Decl.Attributes;
2705 while Attribute1 /= No_Variable loop
2706 Attr_Value1 := Shared.Variable_Elements. Table (Attribute1);
2707 exit when Attr_Value1.Name = Snames.Name_Languages;
2708 Attribute1 := Attr_Value1.Next;
2711 if Attribute1 = No_Variable
2712 or else Attr_Value1.Value.Default
2714 -- Attribute Languages is not declared in the extending project.
2715 -- Check if it is declared in the project being extended.
2717 Attribute2 := Project.Extends.Decl.Attributes;
2718 while Attribute2 /= No_Variable loop
2719 Attr_Value2 := Shared.Variable_Elements.Table (Attribute2);
2720 exit when Attr_Value2.Name = Snames.Name_Languages;
2721 Attribute2 := Attr_Value2.Next;
2724 if Attribute2 /= No_Variable and then
2725 not Attr_Value2.Value.Default
2727 -- As attribute Languages is declared in the project being
2728 -- extended, copy its value for the extending project.
2730 if Attribute1 = No_Variable then
2731 Variable_Element_Table.Increment_Last
2732 (Shared.Variable_Elements);
2733 Attribute1 := Variable_Element_Table.Last
2734 (Shared.Variable_Elements);
2735 Attr_Value1.Next := Project.Decl.Attributes;
2736 Project.Decl.Attributes := Attribute1;
2739 Attr_Value1.Name := Snames.Name_Languages;
2740 Attr_Value1.Value := Attr_Value2.Value;
2741 Shared.Variable_Elements.Table (Attribute1) := Attr_Value1;
2744 end Process_Extended_Project;
2746 -- Start of processing for Recursive_Process
2749 if No (From_Project_Node) then
2750 Project := No_Project;
2754 Imported : Project_List;
2755 Declaration_Node : Project_Node_Id := Empty_Node;
2757 Name : constant Name_Id :=
2758 Name_Of (From_Project_Node, From_Project_Node_Tree);
2760 Name_Node : constant Tree_Private_Part.Project_Name_And_Node :=
2761 Tree_Private_Part.Projects_Htable.Get
2762 (From_Project_Node_Tree.Projects_HT, Name);
2765 Project := Processed_Projects.Get (Name);
2767 if Project /= No_Project then
2768 -- Make sure that, when a project is extended, the project id
2769 -- of the project extending it is recorded in its data, even
2770 -- when it has already been processed as an imported project.
2771 -- This is for virtually extended projects.
2773 if Extended_By /= No_Project then
2774 Project.Extended_By := Extended_By;
2780 Project := new Project_Data'
2782 (Project_Qualifier_Of
2783 (From_Project_Node, From_Project_Node_Tree)));
2784 In_Tree.Projects := new Project_List_Element'
2785 (Project => Project,
2786 Next => In_Tree.Projects);
2788 Processed_Projects.Set (Name, Project);
2790 Project.Name := Name;
2791 Project.Display_Name := Name_Node.Display_Name;
2792 Get_Name_String (Name);
2794 -- If name starts with the virtual prefix, flag the project as
2795 -- being a virtual extending project.
2797 if Name_Len > Virtual_Prefix'Length
2798 and then Name_Buffer (1 .. Virtual_Prefix'Length) =
2801 Project.Virtual := True;
2804 Project.Path.Display_Name :=
2805 Path_Name_Of (From_Project_Node, From_Project_Node_Tree);
2806 Get_Name_String (Project.Path.Display_Name);
2807 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2808 Project.Path.Name := Name_Find;
2811 Location_Of (From_Project_Node, From_Project_Node_Tree);
2813 Project.Directory.Display_Name :=
2814 Directory_Of (From_Project_Node, From_Project_Node_Tree);
2815 Get_Name_String (Project.Directory.Display_Name);
2816 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2817 Project.Directory.Name := Name_Find;
2819 Project.Extended_By := Extended_By;
2824 Name_Id (Project.Directory.Name),
2827 Prj.Attr.Attribute_First,
2828 Project_Level => True);
2830 Process_Imported_Projects (Imported, Limited_With => False);
2832 if Project.Qualifier = Aggregate
2833 and then In_Tree.Is_Root_Tree
2835 Initialize_And_Copy (Child_Env, Copy_From => Env);
2837 -- No need to initialize Child_Env, since it will not be
2838 -- used anyway by Process_Declarative_Items (only the root
2839 -- aggregate can modify it, and it is never read anyway).
2844 Project_Declaration_Of
2845 (From_Project_Node, From_Project_Node_Tree);
2848 (In_Tree => In_Tree,
2849 Project => Project.Extends,
2850 From_Project_Node => Extended_Project_Of
2851 (Declaration_Node, From_Project_Node_Tree),
2852 From_Project_Node_Tree => From_Project_Node_Tree,
2854 Extended_By => Project);
2856 Process_Declarative_Items
2857 (Project => Project,
2859 From_Project_Node => From_Project_Node,
2860 Node_Tree => From_Project_Node_Tree,
2863 Item => First_Declarative_Item_Of
2864 (Declaration_Node, From_Project_Node_Tree),
2865 Child_Env => Child_Env);
2867 if Project.Extends /= No_Project then
2868 Process_Extended_Project;
2871 Process_Imported_Projects (Imported, Limited_With => True);
2873 if Err_Vars.Total_Errors_Detected = 0 then
2874 Process_Aggregated_Projects;
2877 if Project.Qualifier = Aggregate
2878 and then In_Tree.Is_Root_Tree
2884 end Recursive_Process;