1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2009, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Err_Vars; use Err_Vars;
28 with Osint; use Osint;
29 with Output; use Output;
30 with Prj.Attr; use Prj.Attr;
31 with Prj.Err; use Prj.Err;
32 with Prj.Ext; use Prj.Ext;
33 with Prj.Nmsc; use Prj.Nmsc;
34 with Sinput; use Sinput;
37 with GNAT.Case_Util; use GNAT.Case_Util;
40 package body Prj.Proc is
42 package Processed_Projects is new GNAT.HTable.Simple_HTable
43 (Header_Num => Header_Num,
44 Element => Project_Id,
45 No_Element => No_Project,
49 -- This hash table contains all processed projects
51 package Unit_Htable is new GNAT.HTable.Simple_HTable
52 (Header_Num => Header_Num,
54 No_Element => No_Source,
58 -- This hash table contains all processed projects
60 procedure Add (To_Exp : in out Name_Id; Str : Name_Id);
61 -- Concatenate two strings and returns another string if both
62 -- arguments are not null string.
64 -- In the following procedures, we are expected to guess the meaning of
65 -- the parameters from their names, this is never a good idea, comments
66 -- should be added precisely defining every formal ???
68 procedure Add_Attributes
69 (Project : Project_Id;
70 Project_Name : Name_Id;
71 Project_Dir : Name_Id;
72 In_Tree : Project_Tree_Ref;
73 Decl : in out Declarations;
74 First : Attribute_Node_Id;
75 Project_Level : Boolean);
76 -- Add all attributes, starting with First, with their default values to
77 -- the package or project with declarations Decl.
80 (In_Tree : Project_Tree_Ref;
82 Flags : Processing_Flags);
83 -- Set all projects to not checked, then call Recursive_Check for the
84 -- main project Project. Project is set to No_Project if errors occurred.
85 -- Current_Dir is for optimization purposes, avoiding extra system calls.
86 -- If Allow_Duplicate_Basenames, then files with the same base names are
87 -- authorized within a project for source-based languages (never for unit
90 procedure Copy_Package_Declarations
92 To : in out Declarations;
94 Naming_Restricted : Boolean;
95 In_Tree : Project_Tree_Ref);
96 -- Copy a package declaration From to To for a renamed package. Change the
97 -- locations of all the attributes to New_Loc. When Naming_Restricted is
98 -- True, do not copy attributes Body, Spec, Implementation and
102 (Project : Project_Id;
103 In_Tree : Project_Tree_Ref;
104 Flags : Processing_Flags;
105 From_Project_Node : Project_Node_Id;
106 From_Project_Node_Tree : Project_Node_Tree_Ref;
108 First_Term : Project_Node_Id;
109 Kind : Variable_Kind) return Variable_Value;
110 -- From N_Expression project node From_Project_Node, compute the value
111 -- of an expression and return it as a Variable_Value.
113 function Imported_Or_Extended_Project_From
114 (Project : Project_Id;
115 With_Name : Name_Id) return Project_Id;
116 -- Find an imported or extended project of Project whose name is With_Name
118 function Package_From
119 (Project : Project_Id;
120 In_Tree : Project_Tree_Ref;
121 With_Name : Name_Id) return Package_Id;
122 -- Find the package of Project whose name is With_Name
124 procedure Process_Declarative_Items
125 (Project : Project_Id;
126 In_Tree : Project_Tree_Ref;
127 Flags : Processing_Flags;
128 From_Project_Node : Project_Node_Id;
129 From_Project_Node_Tree : Project_Node_Tree_Ref;
131 Item : Project_Node_Id);
132 -- Process declarative items starting with From_Project_Node, and put them
133 -- in declarations Decl. This is a recursive procedure; it calls itself for
134 -- a package declaration or a case construction.
136 procedure Recursive_Process
137 (In_Tree : Project_Tree_Ref;
138 Project : out Project_Id;
139 Flags : Processing_Flags;
140 From_Project_Node : Project_Node_Id;
141 From_Project_Node_Tree : Project_Node_Tree_Ref;
142 Extended_By : Project_Id);
143 -- Process project with node From_Project_Node in the tree. Do nothing if
144 -- From_Project_Node is Empty_Node. If project has already been processed,
145 -- simply return its project id. Otherwise create a new project id, mark it
146 -- as processed, call itself recursively for all imported projects and a
147 -- extended project, if any. Then process the declarative items of the
150 function Get_Attribute_Index
151 (Tree : Project_Node_Tree_Ref;
152 Attr : Project_Node_Id;
153 Index : Name_Id) return Name_Id;
154 -- Copy the index of the attribute into Name_Buffer, converting to lower
155 -- case if the attribute is case-insensitive.
161 procedure Add (To_Exp : in out Name_Id; Str : Name_Id) is
163 if To_Exp = No_Name or else To_Exp = Empty_String then
165 -- To_Exp is nil or empty. The result is Str
169 -- If Str is nil, then do not change To_Ext
171 elsif Str /= No_Name and then Str /= Empty_String then
173 S : constant String := Get_Name_String (Str);
175 Get_Name_String (To_Exp);
176 Add_Str_To_Name_Buffer (S);
186 procedure Add_Attributes
187 (Project : Project_Id;
188 Project_Name : Name_Id;
189 Project_Dir : Name_Id;
190 In_Tree : Project_Tree_Ref;
191 Decl : in out Declarations;
192 First : Attribute_Node_Id;
193 Project_Level : Boolean)
195 The_Attribute : Attribute_Node_Id := First;
198 while The_Attribute /= Empty_Attribute loop
199 if Attribute_Kind_Of (The_Attribute) = Single then
201 New_Attribute : Variable_Value;
204 case Variable_Kind_Of (The_Attribute) is
206 -- Undefined should not happen
210 (False, "attribute with an undefined kind");
213 -- Single attributes have a default value of empty string
219 Location => No_Location,
221 Value => Empty_String,
224 -- Special cases of <project>'Name and
225 -- <project>'Project_Dir.
227 if Project_Level then
228 if Attribute_Name_Of (The_Attribute) =
231 New_Attribute.Value := Project_Name;
233 elsif Attribute_Name_Of (The_Attribute) =
234 Snames.Name_Project_Dir
236 New_Attribute.Value := Project_Dir;
240 -- List attributes have a default value of nil list
246 Location => No_Location,
248 Values => Nil_String);
252 Variable_Element_Table.Increment_Last
253 (In_Tree.Variable_Elements);
254 In_Tree.Variable_Elements.Table
255 (Variable_Element_Table.Last
256 (In_Tree.Variable_Elements)) :=
257 (Next => Decl.Attributes,
258 Name => Attribute_Name_Of (The_Attribute),
259 Value => New_Attribute);
260 Decl.Attributes := Variable_Element_Table.Last
261 (In_Tree.Variable_Elements);
265 The_Attribute := Next_Attribute (After => The_Attribute);
274 (In_Tree : Project_Tree_Ref;
275 Project : Project_Id;
276 Flags : Processing_Flags)
279 Process_Naming_Scheme (In_Tree, Project, Flags);
281 -- Set the Other_Part field for the units
287 Iter : Source_Iterator;
292 Iter := For_Each_Source (In_Tree);
294 Source1 := Prj.Element (Iter);
295 exit when Source1 = No_Source;
297 if Source1.Unit /= No_Unit_Index then
298 Name := Source1.Unit.Name;
299 Source2 := Unit_Htable.Get (Name);
301 if Source2 = No_Source then
302 Unit_Htable.Set (K => Name, E => Source1);
304 Unit_Htable.Remove (Name);
313 -------------------------------
314 -- Copy_Package_Declarations --
315 -------------------------------
317 procedure Copy_Package_Declarations
318 (From : Declarations;
319 To : in out Declarations;
320 New_Loc : Source_Ptr;
321 Naming_Restricted : Boolean;
322 In_Tree : Project_Tree_Ref)
325 V2 : Variable_Id := No_Variable;
328 A2 : Array_Id := No_Array;
330 E1 : Array_Element_Id;
331 E2 : Array_Element_Id := No_Array_Element;
335 -- To avoid references in error messages to attribute declarations in
336 -- an original package that has been renamed, copy all the attribute
337 -- declarations of the package and change all locations to New_Loc,
338 -- the location of the renamed package.
340 -- First single attributes
342 V1 := From.Attributes;
343 while V1 /= No_Variable loop
345 -- Copy the attribute
347 Var := In_Tree.Variable_Elements.Table (V1);
350 -- Remove the Next component
352 Var.Next := No_Variable;
354 -- Change the location to New_Loc
356 Var.Value.Location := New_Loc;
357 Variable_Element_Table.Increment_Last (In_Tree.Variable_Elements);
359 -- Put in new declaration
361 if To.Attributes = No_Variable then
363 Variable_Element_Table.Last (In_Tree.Variable_Elements);
365 In_Tree.Variable_Elements.Table (V2).Next :=
366 Variable_Element_Table.Last (In_Tree.Variable_Elements);
369 V2 := Variable_Element_Table.Last (In_Tree.Variable_Elements);
370 In_Tree.Variable_Elements.Table (V2) := Var;
373 -- Then the associated array attributes
376 while A1 /= No_Array loop
377 Arr := In_Tree.Arrays.Table (A1);
380 if not Naming_Restricted or else
381 (Arr.Name /= Snames.Name_Body
382 and then Arr.Name /= Snames.Name_Spec
383 and then Arr.Name /= Snames.Name_Implementation
384 and then Arr.Name /= Snames.Name_Specification)
386 -- Remove the Next component
388 Arr.Next := No_Array;
390 Array_Table.Increment_Last (In_Tree.Arrays);
392 -- Create new Array declaration
394 if To.Arrays = No_Array then
395 To.Arrays := Array_Table.Last (In_Tree.Arrays);
397 In_Tree.Arrays.Table (A2).Next :=
398 Array_Table.Last (In_Tree.Arrays);
401 A2 := Array_Table.Last (In_Tree.Arrays);
403 -- Don't store the array as its first element has not been set yet
405 -- Copy the array elements of the array
408 Arr.Value := No_Array_Element;
409 while E1 /= No_Array_Element loop
411 -- Copy the array element
413 Elm := In_Tree.Array_Elements.Table (E1);
416 -- Remove the Next component
418 Elm.Next := No_Array_Element;
420 -- Change the location
422 Elm.Value.Location := New_Loc;
423 Array_Element_Table.Increment_Last (In_Tree.Array_Elements);
425 -- Create new array element
427 if Arr.Value = No_Array_Element then
429 Array_Element_Table.Last (In_Tree.Array_Elements);
431 In_Tree.Array_Elements.Table (E2).Next :=
432 Array_Element_Table.Last (In_Tree.Array_Elements);
435 E2 := Array_Element_Table.Last (In_Tree.Array_Elements);
436 In_Tree.Array_Elements.Table (E2) := Elm;
439 -- Finally, store the new array
441 In_Tree.Arrays.Table (A2) := Arr;
444 end Copy_Package_Declarations;
446 -------------------------
447 -- Get_Attribute_Index --
448 -------------------------
450 function Get_Attribute_Index
451 (Tree : Project_Node_Tree_Ref;
452 Attr : Project_Node_Id;
453 Index : Name_Id) return Name_Id
458 Get_Name_String (Index);
459 Lower := Case_Insensitive (Attr, Tree);
461 -- The index is always case insensitive if it does not include any dot.
462 -- ??? Why not use the properties from prj-attr, simply, maybe because
463 -- we don't know whether we have a file as an index?
468 for J in 1 .. Name_Len loop
469 if Name_Buffer (J) = '.' then
477 To_Lower (Name_Buffer (1 .. Name_Len));
482 end Get_Attribute_Index;
489 (Project : Project_Id;
490 In_Tree : Project_Tree_Ref;
491 Flags : Processing_Flags;
492 From_Project_Node : Project_Node_Id;
493 From_Project_Node_Tree : Project_Node_Tree_Ref;
495 First_Term : Project_Node_Id;
496 Kind : Variable_Kind) return Variable_Value
498 The_Term : Project_Node_Id;
499 -- The term in the expression list
501 The_Current_Term : Project_Node_Id := Empty_Node;
502 -- The current term node id
504 Result : Variable_Value (Kind => Kind);
505 -- The returned result
507 Last : String_List_Id := Nil_String;
508 -- Reference to the last string elements in Result, when Kind is List
511 Result.Project := Project;
512 Result.Location := Location_Of (First_Term, From_Project_Node_Tree);
514 -- Process each term of the expression, starting with First_Term
516 The_Term := First_Term;
517 while Present (The_Term) loop
518 The_Current_Term := Current_Term (The_Term, From_Project_Node_Tree);
520 case Kind_Of (The_Current_Term, From_Project_Node_Tree) is
522 when N_Literal_String =>
528 -- Should never happen
530 pragma Assert (False, "Undefined expression kind");
536 (The_Current_Term, From_Project_Node_Tree));
539 (The_Current_Term, From_Project_Node_Tree);
543 String_Element_Table.Increment_Last
544 (In_Tree.String_Elements);
546 if Last = Nil_String then
548 -- This can happen in an expression like () & "toto"
550 Result.Values := String_Element_Table.Last
551 (In_Tree.String_Elements);
554 In_Tree.String_Elements.Table
555 (Last).Next := String_Element_Table.Last
556 (In_Tree.String_Elements);
559 Last := String_Element_Table.Last
560 (In_Tree.String_Elements);
562 In_Tree.String_Elements.Table (Last) :=
563 (Value => String_Value_Of
565 From_Project_Node_Tree),
566 Index => Source_Index_Of
568 From_Project_Node_Tree),
569 Display_Value => No_Name,
570 Location => Location_Of
572 From_Project_Node_Tree),
577 when N_Literal_String_List =>
580 String_Node : Project_Node_Id :=
581 First_Expression_In_List
583 From_Project_Node_Tree);
585 Value : Variable_Value;
588 if Present (String_Node) then
590 -- If String_Node is nil, it is an empty list, there is
597 From_Project_Node => From_Project_Node,
598 From_Project_Node_Tree => From_Project_Node_Tree,
602 (String_Node, From_Project_Node_Tree),
604 String_Element_Table.Increment_Last
605 (In_Tree.String_Elements);
607 if Result.Values = Nil_String then
609 -- This literal string list is the first term in a
610 -- string list expression
613 String_Element_Table.Last (In_Tree.String_Elements);
616 In_Tree.String_Elements.Table
618 String_Element_Table.Last (In_Tree.String_Elements);
622 String_Element_Table.Last (In_Tree.String_Elements);
624 In_Tree.String_Elements.Table (Last) :=
625 (Value => Value.Value,
626 Display_Value => No_Name,
627 Location => Value.Location,
630 Index => Value.Index);
633 -- Add the other element of the literal string list
634 -- one after the other
637 Next_Expression_In_List
638 (String_Node, From_Project_Node_Tree);
640 exit when No (String_Node);
647 From_Project_Node => From_Project_Node,
648 From_Project_Node_Tree => From_Project_Node_Tree,
652 (String_Node, From_Project_Node_Tree),
655 String_Element_Table.Increment_Last
656 (In_Tree.String_Elements);
657 In_Tree.String_Elements.Table
658 (Last).Next := String_Element_Table.Last
659 (In_Tree.String_Elements);
660 Last := String_Element_Table.Last
661 (In_Tree.String_Elements);
662 In_Tree.String_Elements.Table (Last) :=
663 (Value => Value.Value,
664 Display_Value => No_Name,
665 Location => Value.Location,
668 Index => Value.Index);
673 when N_Variable_Reference | N_Attribute_Reference =>
676 The_Project : Project_Id := Project;
677 The_Package : Package_Id := Pkg;
678 The_Name : Name_Id := No_Name;
679 The_Variable_Id : Variable_Id := No_Variable;
680 The_Variable : Variable_Value;
681 Term_Project : constant Project_Node_Id :=
684 From_Project_Node_Tree);
685 Term_Package : constant Project_Node_Id :=
688 From_Project_Node_Tree);
689 Index : Name_Id := No_Name;
692 if Present (Term_Project) and then
693 Term_Project /= From_Project_Node
695 -- This variable or attribute comes from another project
698 Name_Of (Term_Project, From_Project_Node_Tree);
699 The_Project := Imported_Or_Extended_Project_From
701 With_Name => The_Name);
704 if Present (Term_Package) then
706 -- This is an attribute of a package
709 Name_Of (Term_Package, From_Project_Node_Tree);
710 The_Package := The_Project.Decl.Packages;
712 while The_Package /= No_Package
713 and then In_Tree.Packages.Table
714 (The_Package).Name /= The_Name
717 In_Tree.Packages.Table
722 (The_Package /= No_Package,
723 "package not found.");
725 elsif Kind_Of (The_Current_Term, From_Project_Node_Tree) =
726 N_Attribute_Reference
728 The_Package := No_Package;
732 Name_Of (The_Current_Term, From_Project_Node_Tree);
734 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
735 N_Attribute_Reference
738 Associative_Array_Index_Of
739 (The_Current_Term, From_Project_Node_Tree);
742 -- If it is not an associative array attribute
744 if Index = No_Name then
746 -- It is not an associative array attribute
748 if The_Package /= No_Package then
750 -- First, if there is a package, look into the package
752 if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
756 In_Tree.Packages.Table
757 (The_Package).Decl.Variables;
760 In_Tree.Packages.Table
761 (The_Package).Decl.Attributes;
764 while The_Variable_Id /= No_Variable
766 In_Tree.Variable_Elements.Table
767 (The_Variable_Id).Name /= The_Name
770 In_Tree.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
790 In_Tree.Variable_Elements.Table
791 (The_Variable_Id).Name /= The_Name
794 In_Tree.Variable_Elements.Table
795 (The_Variable_Id).Next;
800 pragma Assert (The_Variable_Id /= No_Variable,
801 "variable or attribute not found");
804 In_Tree.Variable_Elements.Table
805 (The_Variable_Id).Value;
809 -- It is an associative array attribute
812 The_Array : Array_Id := No_Array;
813 The_Element : Array_Element_Id := No_Array_Element;
814 Array_Index : Name_Id := No_Name;
817 if The_Package /= No_Package then
819 In_Tree.Packages.Table
820 (The_Package).Decl.Arrays;
822 The_Array := The_Project.Decl.Arrays;
825 while The_Array /= No_Array
826 and then In_Tree.Arrays.Table
827 (The_Array).Name /= The_Name
829 The_Array := In_Tree.Arrays.Table
833 if The_Array /= No_Array then
834 The_Element := In_Tree.Arrays.Table
838 (From_Project_Node_Tree,
842 while The_Element /= No_Array_Element
844 In_Tree.Array_Elements.Table
845 (The_Element).Index /= Array_Index
848 In_Tree.Array_Elements.Table
854 if The_Element /= No_Array_Element then
856 In_Tree.Array_Elements.Table
860 if Expression_Kind_Of
861 (The_Current_Term, From_Project_Node_Tree) =
867 Location => No_Location,
869 Values => Nil_String);
874 Location => No_Location,
876 Value => Empty_String,
887 -- Should never happen
889 pragma Assert (False, "undefined expression kind");
894 case The_Variable.Kind is
900 Add (Result.Value, The_Variable.Value);
904 -- Should never happen
908 "list cannot appear in single " &
909 "string expression");
914 case The_Variable.Kind is
920 String_Element_Table.Increment_Last
921 (In_Tree.String_Elements);
923 if Last = Nil_String then
925 -- This can happen in an expression such as
929 String_Element_Table.Last
930 (In_Tree.String_Elements);
933 In_Tree.String_Elements.Table
935 String_Element_Table.Last
936 (In_Tree.String_Elements);
940 String_Element_Table.Last
941 (In_Tree.String_Elements);
943 In_Tree.String_Elements.Table (Last) :=
944 (Value => The_Variable.Value,
945 Display_Value => No_Name,
946 Location => Location_Of
948 From_Project_Node_Tree),
956 The_List : String_List_Id :=
960 while The_List /= Nil_String loop
961 String_Element_Table.Increment_Last
962 (In_Tree.String_Elements);
964 if Last = Nil_String then
966 String_Element_Table.Last
972 String_Elements.Table (Last).Next :=
973 String_Element_Table.Last
980 String_Element_Table.Last
981 (In_Tree.String_Elements);
983 In_Tree.String_Elements.Table (Last) :=
985 In_Tree.String_Elements.Table
987 Display_Value => No_Name,
991 From_Project_Node_Tree),
997 In_Tree. String_Elements.Table
1005 when N_External_Value =>
1008 (External_Reference_Of
1009 (The_Current_Term, From_Project_Node_Tree),
1010 From_Project_Node_Tree));
1013 Name : constant Name_Id := Name_Find;
1014 Default : Name_Id := No_Name;
1015 Value : Name_Id := No_Name;
1017 Def_Var : Variable_Value;
1019 Default_Node : constant Project_Node_Id :=
1021 (The_Current_Term, From_Project_Node_Tree);
1024 -- If there is a default value for the external reference,
1027 if Present (Default_Node) then
1028 Def_Var := Expression
1029 (Project => Project,
1032 From_Project_Node => From_Project_Node,
1033 From_Project_Node_Tree => From_Project_Node_Tree,
1037 (Default_Node, From_Project_Node_Tree),
1040 if Def_Var /= Nil_Variable_Value then
1041 Default := Def_Var.Value;
1045 Value := Prj.Ext.Value_Of (Name, Default);
1047 if Value = No_Name then
1048 if not Quiet_Output then
1050 (Flags, "?undefined external reference",
1052 (The_Current_Term, From_Project_Node_Tree),
1056 Value := Empty_String;
1065 Add (Result.Value, Value);
1068 String_Element_Table.Increment_Last
1069 (In_Tree.String_Elements);
1071 if Last = Nil_String then
1072 Result.Values := String_Element_Table.Last
1073 (In_Tree.String_Elements);
1076 In_Tree.String_Elements.Table
1077 (Last).Next := String_Element_Table.Last
1078 (In_Tree.String_Elements);
1081 Last := String_Element_Table.Last
1082 (In_Tree.String_Elements);
1083 In_Tree.String_Elements.Table (Last) :=
1085 Display_Value => No_Name,
1088 (The_Current_Term, From_Project_Node_Tree),
1098 -- Should never happen
1102 "illegal node kind in an expression");
1103 raise Program_Error;
1107 The_Term := Next_Term (The_Term, From_Project_Node_Tree);
1113 ---------------------------------------
1114 -- Imported_Or_Extended_Project_From --
1115 ---------------------------------------
1117 function Imported_Or_Extended_Project_From
1118 (Project : Project_Id;
1119 With_Name : Name_Id) return Project_Id
1121 List : Project_List;
1122 Result : Project_Id;
1123 Temp_Result : Project_Id;
1126 -- First check if it is the name of an extended project
1128 Result := Project.Extends;
1129 while Result /= No_Project loop
1130 if Result.Name = With_Name then
1133 Result := Result.Extends;
1137 -- Then check the name of each imported project
1139 Temp_Result := No_Project;
1140 List := Project.Imported_Projects;
1141 while List /= null loop
1142 Result := List.Project;
1144 -- If the project is directly imported, then returns its ID
1146 if Result.Name = With_Name then
1150 -- If a project extending the project is imported, then keep this
1151 -- extending project as a possibility. It will be the returned ID
1152 -- if the project is not imported directly.
1158 Proj := Result.Extends;
1159 while Proj /= No_Project loop
1160 if Proj.Name = With_Name then
1161 Temp_Result := Result;
1165 Proj := Proj.Extends;
1172 pragma Assert (Temp_Result /= No_Project, "project not found");
1174 end Imported_Or_Extended_Project_From;
1180 function Package_From
1181 (Project : Project_Id;
1182 In_Tree : Project_Tree_Ref;
1183 With_Name : Name_Id) return Package_Id
1185 Result : Package_Id := Project.Decl.Packages;
1188 -- Check the name of each existing package of Project
1190 while Result /= No_Package
1191 and then In_Tree.Packages.Table (Result).Name /= With_Name
1193 Result := In_Tree.Packages.Table (Result).Next;
1196 if Result = No_Package then
1198 -- Should never happen
1200 Write_Line ("package """ & Get_Name_String (With_Name) &
1202 raise Program_Error;
1214 (In_Tree : Project_Tree_Ref;
1215 Project : out Project_Id;
1216 Success : out Boolean;
1217 From_Project_Node : Project_Node_Id;
1218 From_Project_Node_Tree : Project_Node_Tree_Ref;
1219 Flags : Processing_Flags;
1220 Reset_Tree : Boolean := True)
1223 Process_Project_Tree_Phase_1
1224 (In_Tree => In_Tree,
1227 From_Project_Node => From_Project_Node,
1228 From_Project_Node_Tree => From_Project_Node_Tree,
1230 Reset_Tree => Reset_Tree);
1232 if Project_Qualifier_Of (From_Project_Node, From_Project_Node_Tree) /=
1235 Process_Project_Tree_Phase_2
1236 (In_Tree => In_Tree,
1239 From_Project_Node => From_Project_Node,
1240 From_Project_Node_Tree => From_Project_Node_Tree,
1245 -------------------------------
1246 -- Process_Declarative_Items --
1247 -------------------------------
1249 procedure Process_Declarative_Items
1250 (Project : Project_Id;
1251 In_Tree : Project_Tree_Ref;
1252 Flags : Processing_Flags;
1253 From_Project_Node : Project_Node_Id;
1254 From_Project_Node_Tree : Project_Node_Tree_Ref;
1256 Item : Project_Node_Id)
1258 Current_Declarative_Item : Project_Node_Id;
1259 Current_Item : Project_Node_Id;
1262 -- Loop through declarative items
1264 Current_Item := Empty_Node;
1266 Current_Declarative_Item := Item;
1267 while Present (Current_Declarative_Item) loop
1273 (Current_Declarative_Item, From_Project_Node_Tree);
1275 -- And set Current_Declarative_Item to the next declarative item
1276 -- ready for the next iteration.
1278 Current_Declarative_Item :=
1279 Next_Declarative_Item
1280 (Current_Declarative_Item, From_Project_Node_Tree);
1282 case Kind_Of (Current_Item, From_Project_Node_Tree) is
1284 when N_Package_Declaration =>
1286 -- Do not process a package declaration that should be ignored
1288 if Expression_Kind_Of
1289 (Current_Item, From_Project_Node_Tree) /= Ignored
1291 -- Create the new package
1293 Package_Table.Increment_Last (In_Tree.Packages);
1296 New_Pkg : constant Package_Id :=
1297 Package_Table.Last (In_Tree.Packages);
1298 The_New_Package : Package_Element;
1300 Project_Of_Renamed_Package :
1301 constant Project_Node_Id :=
1302 Project_Of_Renamed_Package_Of
1303 (Current_Item, From_Project_Node_Tree);
1306 -- Set the name of the new package
1308 The_New_Package.Name :=
1309 Name_Of (Current_Item, From_Project_Node_Tree);
1311 -- Insert the new package in the appropriate list
1313 if Pkg /= No_Package then
1314 The_New_Package.Next :=
1315 In_Tree.Packages.Table (Pkg).Decl.Packages;
1316 In_Tree.Packages.Table (Pkg).Decl.Packages :=
1320 The_New_Package.Next := Project.Decl.Packages;
1321 Project.Decl.Packages := New_Pkg;
1324 In_Tree.Packages.Table (New_Pkg) :=
1327 if Present (Project_Of_Renamed_Package) then
1332 Project_Name : constant Name_Id :=
1334 (Project_Of_Renamed_Package,
1335 From_Project_Node_Tree);
1338 constant Project_Id :=
1339 Imported_Or_Extended_Project_From
1340 (Project, Project_Name);
1342 Renamed_Package : constant Package_Id :=
1344 (Renamed_Project, In_Tree,
1347 From_Project_Node_Tree));
1350 -- For a renamed package, copy the declarations of
1351 -- the renamed package, but set all the locations
1352 -- to the location of the package name in the
1353 -- renaming declaration.
1355 Copy_Package_Declarations
1357 In_Tree.Packages.Table (Renamed_Package).Decl,
1359 In_Tree.Packages.Table (New_Pkg).Decl,
1362 (Current_Item, From_Project_Node_Tree),
1363 Naming_Restricted => False,
1364 In_Tree => In_Tree);
1367 -- Standard package declaration, not renaming
1370 -- Set the default values of the attributes
1375 Name_Id (Project.Directory.Name),
1377 In_Tree.Packages.Table (New_Pkg).Decl,
1380 (Current_Item, From_Project_Node_Tree)),
1381 Project_Level => False);
1383 -- And process declarative items of the new package
1385 Process_Declarative_Items
1386 (Project => Project,
1389 From_Project_Node => From_Project_Node,
1390 From_Project_Node_Tree => From_Project_Node_Tree,
1393 First_Declarative_Item_Of
1394 (Current_Item, From_Project_Node_Tree));
1399 when N_String_Type_Declaration =>
1401 -- There is nothing to process
1405 when N_Attribute_Declaration |
1406 N_Typed_Variable_Declaration |
1407 N_Variable_Declaration =>
1409 if Expression_Of (Current_Item, From_Project_Node_Tree) =
1413 -- It must be a full associative array attribute declaration
1416 Current_Item_Name : constant Name_Id :=
1419 From_Project_Node_Tree);
1420 -- The name of the attribute
1422 Current_Location : constant Source_Ptr :=
1425 From_Project_Node_Tree);
1427 New_Array : Array_Id;
1428 -- The new associative array created
1430 Orig_Array : Array_Id;
1431 -- The associative array value
1433 Orig_Project_Name : Name_Id := No_Name;
1434 -- The name of the project where the associative array
1437 Orig_Project : Project_Id := No_Project;
1438 -- The id of the project where the associative array
1441 Orig_Package_Name : Name_Id := No_Name;
1442 -- The name of the package, if any, where the associative
1445 Orig_Package : Package_Id := No_Package;
1446 -- The id of the package, if any, where the associative
1449 New_Element : Array_Element_Id := No_Array_Element;
1450 -- Id of a new array element created
1452 Prev_Element : Array_Element_Id := No_Array_Element;
1453 -- Last new element id created
1455 Orig_Element : Array_Element_Id := No_Array_Element;
1456 -- Current array element in original associative array
1458 Next_Element : Array_Element_Id := No_Array_Element;
1459 -- Id of the array element that follows the new element.
1460 -- This is not always nil, because values for the
1461 -- associative array attribute may already have been
1462 -- declared, and the array elements declared are reused.
1467 -- First find if the associative array attribute already
1468 -- has elements declared.
1470 if Pkg /= No_Package then
1471 New_Array := In_Tree.Packages.Table
1475 New_Array := Project.Decl.Arrays;
1478 while New_Array /= No_Array
1479 and then In_Tree.Arrays.Table (New_Array).Name /=
1482 New_Array := In_Tree.Arrays.Table (New_Array).Next;
1485 -- If the attribute has never been declared add new entry
1486 -- in the arrays of the project/package and link it.
1488 if New_Array = No_Array then
1489 Array_Table.Increment_Last (In_Tree.Arrays);
1490 New_Array := Array_Table.Last (In_Tree.Arrays);
1492 if Pkg /= No_Package then
1493 In_Tree.Arrays.Table (New_Array) :=
1494 (Name => Current_Item_Name,
1495 Location => Current_Location,
1496 Value => No_Array_Element,
1497 Next => In_Tree.Packages.Table
1500 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1504 In_Tree.Arrays.Table (New_Array) :=
1505 (Name => Current_Item_Name,
1506 Location => Current_Location,
1507 Value => No_Array_Element,
1508 Next => Project.Decl.Arrays);
1510 Project.Decl.Arrays := New_Array;
1514 -- Find the project where the value is declared
1516 Orig_Project_Name :=
1518 (Associative_Project_Of
1519 (Current_Item, From_Project_Node_Tree),
1520 From_Project_Node_Tree);
1522 Prj := In_Tree.Projects;
1523 while Prj /= null loop
1524 if Prj.Project.Name = Orig_Project_Name then
1525 Orig_Project := Prj.Project;
1531 pragma Assert (Orig_Project /= No_Project,
1532 "original project not found");
1534 if No (Associative_Package_Of
1535 (Current_Item, From_Project_Node_Tree))
1537 Orig_Array := Orig_Project.Decl.Arrays;
1540 -- If in a package, find the package where the value
1543 Orig_Package_Name :=
1545 (Associative_Package_Of
1546 (Current_Item, From_Project_Node_Tree),
1547 From_Project_Node_Tree);
1549 Orig_Package := Orig_Project.Decl.Packages;
1550 pragma Assert (Orig_Package /= No_Package,
1551 "original package not found");
1553 while In_Tree.Packages.Table
1554 (Orig_Package).Name /= Orig_Package_Name
1556 Orig_Package := In_Tree.Packages.Table
1557 (Orig_Package).Next;
1558 pragma Assert (Orig_Package /= No_Package,
1559 "original package not found");
1563 In_Tree.Packages.Table (Orig_Package).Decl.Arrays;
1566 -- Now look for the array
1568 while Orig_Array /= No_Array
1569 and then In_Tree.Arrays.Table (Orig_Array).Name /=
1572 Orig_Array := In_Tree.Arrays.Table
1576 if Orig_Array = No_Array then
1579 "associative array value not found",
1580 Location_Of (Current_Item, From_Project_Node_Tree),
1585 In_Tree.Arrays.Table (Orig_Array).Value;
1587 -- Copy each array element
1589 while Orig_Element /= No_Array_Element loop
1591 -- Case of first element
1593 if Prev_Element = No_Array_Element then
1595 -- And there is no array element declared yet,
1596 -- create a new first array element.
1598 if In_Tree.Arrays.Table (New_Array).Value =
1601 Array_Element_Table.Increment_Last
1602 (In_Tree.Array_Elements);
1603 New_Element := Array_Element_Table.Last
1604 (In_Tree.Array_Elements);
1605 In_Tree.Arrays.Table
1606 (New_Array).Value := New_Element;
1607 Next_Element := No_Array_Element;
1609 -- Otherwise, the new element is the first
1612 New_Element := In_Tree.Arrays.
1613 Table (New_Array).Value;
1615 In_Tree.Array_Elements.Table
1619 -- Otherwise, reuse an existing element, or create
1620 -- one if necessary.
1624 In_Tree.Array_Elements.Table
1625 (Prev_Element).Next;
1627 if Next_Element = No_Array_Element then
1628 Array_Element_Table.Increment_Last
1629 (In_Tree.Array_Elements);
1631 Array_Element_Table.Last
1632 (In_Tree.Array_Elements);
1633 In_Tree.Array_Elements.Table
1634 (Prev_Element).Next := New_Element;
1637 New_Element := Next_Element;
1639 In_Tree.Array_Elements.Table
1644 -- Copy the value of the element
1646 In_Tree.Array_Elements.Table
1648 In_Tree.Array_Elements.Table (Orig_Element);
1649 In_Tree.Array_Elements.Table
1650 (New_Element).Value.Project := Project;
1652 -- Adjust the Next link
1654 In_Tree.Array_Elements.Table
1655 (New_Element).Next := Next_Element;
1657 -- Adjust the previous id for the next element
1659 Prev_Element := New_Element;
1661 -- Go to the next element in the original array
1664 In_Tree.Array_Elements.Table
1665 (Orig_Element).Next;
1668 -- Make sure that the array ends here, in case there
1669 -- previously a greater number of elements.
1671 In_Tree.Array_Elements.Table
1672 (New_Element).Next := No_Array_Element;
1676 -- Declarations other that full associative arrays
1680 New_Value : constant Variable_Value :=
1682 (Project => Project,
1685 From_Project_Node => From_Project_Node,
1686 From_Project_Node_Tree => From_Project_Node_Tree,
1691 (Current_Item, From_Project_Node_Tree),
1692 From_Project_Node_Tree),
1695 (Current_Item, From_Project_Node_Tree));
1696 -- The expression value
1698 The_Variable : Variable_Id := No_Variable;
1700 Current_Item_Name : constant Name_Id :=
1703 From_Project_Node_Tree);
1705 Current_Location : constant Source_Ptr :=
1708 From_Project_Node_Tree);
1711 -- Process a typed variable declaration
1713 if Kind_Of (Current_Item, From_Project_Node_Tree) =
1714 N_Typed_Variable_Declaration
1716 -- Report an error for an empty string
1718 if New_Value.Value = Empty_String then
1720 Name_Of (Current_Item, From_Project_Node_Tree);
1723 "no value defined for %%",
1725 (Current_Item, From_Project_Node_Tree),
1730 Current_String : Project_Node_Id;
1733 -- Loop through all the valid strings for the
1734 -- string type and compare to the string value.
1737 First_Literal_String
1738 (String_Type_Of (Current_Item,
1739 From_Project_Node_Tree),
1740 From_Project_Node_Tree);
1741 while Present (Current_String)
1744 (Current_String, From_Project_Node_Tree) /=
1749 (Current_String, From_Project_Node_Tree);
1752 -- Report an error if the string value is not
1753 -- one for the string type.
1755 if No (Current_String) then
1756 Error_Msg_Name_1 := New_Value.Value;
1759 (Current_Item, From_Project_Node_Tree);
1762 "value %% is illegal for typed string %%",
1764 (Current_Item, From_Project_Node_Tree),
1773 if Kind_Of (Current_Item, From_Project_Node_Tree) /=
1774 N_Attribute_Declaration
1776 Associative_Array_Index_Of
1777 (Current_Item, From_Project_Node_Tree) = No_Name
1779 -- Case of a variable declaration or of a not
1780 -- associative array attribute.
1782 -- First, find the list where to find the variable
1785 if Kind_Of (Current_Item, From_Project_Node_Tree) =
1786 N_Attribute_Declaration
1788 if Pkg /= No_Package then
1790 In_Tree.Packages.Table
1791 (Pkg).Decl.Attributes;
1793 The_Variable := Project.Decl.Attributes;
1797 if Pkg /= No_Package then
1799 In_Tree.Packages.Table
1800 (Pkg).Decl.Variables;
1802 The_Variable := Project.Decl.Variables;
1807 -- Loop through the list, to find if it has already
1810 while The_Variable /= No_Variable
1812 In_Tree.Variable_Elements.Table
1813 (The_Variable).Name /= Current_Item_Name
1816 In_Tree.Variable_Elements.Table
1817 (The_Variable).Next;
1820 -- If it has not been declared, create a new entry
1823 if The_Variable = No_Variable then
1825 -- All single string attribute should already have
1826 -- been declared with a default empty string value.
1829 (Kind_Of (Current_Item, From_Project_Node_Tree) /=
1830 N_Attribute_Declaration,
1831 "illegal attribute declaration for "
1832 & Get_Name_String (Current_Item_Name));
1834 Variable_Element_Table.Increment_Last
1835 (In_Tree.Variable_Elements);
1836 The_Variable := Variable_Element_Table.Last
1837 (In_Tree.Variable_Elements);
1839 -- Put the new variable in the appropriate list
1841 if Pkg /= No_Package then
1842 In_Tree.Variable_Elements.Table (The_Variable) :=
1844 In_Tree.Packages.Table
1845 (Pkg).Decl.Variables,
1846 Name => Current_Item_Name,
1847 Value => New_Value);
1848 In_Tree.Packages.Table
1849 (Pkg).Decl.Variables := The_Variable;
1852 In_Tree.Variable_Elements.Table (The_Variable) :=
1853 (Next => Project.Decl.Variables,
1854 Name => Current_Item_Name,
1855 Value => New_Value);
1856 Project.Decl.Variables := The_Variable;
1859 -- If the variable/attribute has already been
1860 -- declared, just change the value.
1863 In_Tree.Variable_Elements.Table
1864 (The_Variable).Value := New_Value;
1867 -- Associative array attribute
1871 Index_Name : Name_Id :=
1872 Associative_Array_Index_Of
1873 (Current_Item, From_Project_Node_Tree);
1874 The_Array : Array_Id;
1875 The_Array_Element : Array_Element_Id :=
1879 if Index_Name /= All_Other_Names then
1880 Index_Name := Get_Attribute_Index
1881 (From_Project_Node_Tree,
1883 Associative_Array_Index_Of
1884 (Current_Item, From_Project_Node_Tree));
1887 -- Look for the array in the appropriate list
1889 if Pkg /= No_Package then
1891 In_Tree.Packages.Table (Pkg).Decl.Arrays;
1894 The_Array := Project.Decl.Arrays;
1898 The_Array /= No_Array
1900 In_Tree.Arrays.Table (The_Array).Name /=
1903 The_Array := In_Tree.Arrays.Table
1907 -- If the array cannot be found, create a new entry
1908 -- in the list. As The_Array_Element is initialized
1909 -- to No_Array_Element, a new element will be
1910 -- created automatically later
1912 if The_Array = No_Array then
1913 Array_Table.Increment_Last (In_Tree.Arrays);
1914 The_Array := Array_Table.Last (In_Tree.Arrays);
1916 if Pkg /= No_Package then
1917 In_Tree.Arrays.Table (The_Array) :=
1918 (Name => Current_Item_Name,
1919 Location => Current_Location,
1920 Value => No_Array_Element,
1921 Next => In_Tree.Packages.Table
1924 In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1928 In_Tree.Arrays.Table (The_Array) :=
1929 (Name => Current_Item_Name,
1930 Location => Current_Location,
1931 Value => No_Array_Element,
1932 Next => Project.Decl.Arrays);
1934 Project.Decl.Arrays := The_Array;
1937 -- Otherwise initialize The_Array_Element as the
1938 -- head of the element list.
1941 The_Array_Element :=
1942 In_Tree.Arrays.Table (The_Array).Value;
1945 -- Look in the list, if any, to find an element
1946 -- with the same index.
1948 while The_Array_Element /= No_Array_Element
1950 In_Tree.Array_Elements.Table
1951 (The_Array_Element).Index /= Index_Name
1953 The_Array_Element :=
1954 In_Tree.Array_Elements.Table
1955 (The_Array_Element).Next;
1958 -- If no such element were found, create a new one
1959 -- and insert it in the element list, with the
1962 if The_Array_Element = No_Array_Element then
1963 Array_Element_Table.Increment_Last
1964 (In_Tree.Array_Elements);
1965 The_Array_Element := Array_Element_Table.Last
1966 (In_Tree.Array_Elements);
1968 In_Tree.Array_Elements.Table
1969 (The_Array_Element) :=
1970 (Index => Index_Name,
1973 (Current_Item, From_Project_Node_Tree),
1974 Index_Case_Sensitive =>
1975 not Case_Insensitive
1976 (Current_Item, From_Project_Node_Tree),
1978 Next => In_Tree.Arrays.Table
1980 In_Tree.Arrays.Table
1981 (The_Array).Value := The_Array_Element;
1983 -- An element with the same index already exists,
1984 -- just replace its value with the new one.
1987 In_Tree.Array_Elements.Table
1988 (The_Array_Element).Value := New_Value;
1995 when N_Case_Construction =>
1997 The_Project : Project_Id := Project;
1998 -- The id of the project of the case variable
2000 The_Package : Package_Id := Pkg;
2001 -- The id of the package, if any, of the case variable
2003 The_Variable : Variable_Value := Nil_Variable_Value;
2004 -- The case variable
2006 Case_Value : Name_Id := No_Name;
2007 -- The case variable value
2009 Case_Item : Project_Node_Id := Empty_Node;
2010 Choice_String : Project_Node_Id := Empty_Node;
2011 Decl_Item : Project_Node_Id := Empty_Node;
2015 Variable_Node : constant Project_Node_Id :=
2016 Case_Variable_Reference_Of
2018 From_Project_Node_Tree);
2020 Var_Id : Variable_Id := No_Variable;
2021 Name : Name_Id := No_Name;
2024 -- If a project was specified for the case variable,
2027 if Present (Project_Node_Of
2028 (Variable_Node, From_Project_Node_Tree))
2033 (Variable_Node, From_Project_Node_Tree),
2034 From_Project_Node_Tree);
2036 Imported_Or_Extended_Project_From (Project, Name);
2039 -- If a package were specified for the case variable,
2042 if Present (Package_Node_Of
2043 (Variable_Node, From_Project_Node_Tree))
2048 (Variable_Node, From_Project_Node_Tree),
2049 From_Project_Node_Tree);
2051 Package_From (The_Project, In_Tree, Name);
2054 Name := Name_Of (Variable_Node, From_Project_Node_Tree);
2056 -- First, look for the case variable into the package,
2059 if The_Package /= No_Package then
2060 Var_Id := In_Tree.Packages.Table
2061 (The_Package).Decl.Variables;
2063 Name_Of (Variable_Node, From_Project_Node_Tree);
2064 while Var_Id /= No_Variable
2066 In_Tree.Variable_Elements.Table
2067 (Var_Id).Name /= Name
2069 Var_Id := In_Tree.Variable_Elements.
2070 Table (Var_Id).Next;
2074 -- If not found in the package, or if there is no
2075 -- package, look at the project level.
2077 if Var_Id = No_Variable
2080 (Variable_Node, From_Project_Node_Tree))
2082 Var_Id := The_Project.Decl.Variables;
2083 while Var_Id /= No_Variable
2085 In_Tree.Variable_Elements.Table
2086 (Var_Id).Name /= Name
2088 Var_Id := In_Tree.Variable_Elements.
2089 Table (Var_Id).Next;
2093 if Var_Id = No_Variable then
2095 -- Should never happen, because this has already been
2096 -- checked during parsing.
2098 Write_Line ("variable """ &
2099 Get_Name_String (Name) &
2101 raise Program_Error;
2104 -- Get the case variable
2106 The_Variable := In_Tree.Variable_Elements.
2107 Table (Var_Id).Value;
2109 if The_Variable.Kind /= Single then
2111 -- Should never happen, because this has already been
2112 -- checked during parsing.
2114 Write_Line ("variable""" &
2115 Get_Name_String (Name) &
2116 """ is not a single string variable");
2117 raise Program_Error;
2120 -- Get the case variable value
2121 Case_Value := The_Variable.Value;
2124 -- Now look into all the case items of the case construction
2127 First_Case_Item_Of (Current_Item, From_Project_Node_Tree);
2129 while Present (Case_Item) loop
2131 First_Choice_Of (Case_Item, From_Project_Node_Tree);
2133 -- When Choice_String is nil, it means that it is
2134 -- the "when others =>" alternative.
2136 if No (Choice_String) then
2138 First_Declarative_Item_Of
2139 (Case_Item, From_Project_Node_Tree);
2140 exit Case_Item_Loop;
2143 -- Look into all the alternative of this case item
2146 while Present (Choice_String) loop
2149 (Choice_String, From_Project_Node_Tree)
2152 First_Declarative_Item_Of
2153 (Case_Item, From_Project_Node_Tree);
2154 exit Case_Item_Loop;
2159 (Choice_String, From_Project_Node_Tree);
2160 end loop Choice_Loop;
2163 Next_Case_Item (Case_Item, From_Project_Node_Tree);
2164 end loop Case_Item_Loop;
2166 -- If there is an alternative, then we process it
2168 if Present (Decl_Item) then
2169 Process_Declarative_Items
2170 (Project => Project,
2173 From_Project_Node => From_Project_Node,
2174 From_Project_Node_Tree => From_Project_Node_Tree,
2182 -- Should never happen
2184 Write_Line ("Illegal declarative item: " &
2185 Project_Node_Kind'Image
2187 (Current_Item, From_Project_Node_Tree)));
2188 raise Program_Error;
2191 end Process_Declarative_Items;
2193 ----------------------------------
2194 -- Process_Project_Tree_Phase_1 --
2195 ----------------------------------
2197 procedure Process_Project_Tree_Phase_1
2198 (In_Tree : Project_Tree_Ref;
2199 Project : out Project_Id;
2200 Success : out Boolean;
2201 From_Project_Node : Project_Node_Id;
2202 From_Project_Node_Tree : Project_Node_Tree_Ref;
2203 Flags : Processing_Flags;
2204 Reset_Tree : Boolean := True)
2209 -- Make sure there are no projects in the data structure
2211 Free_List (In_Tree.Projects, Free_Project => True);
2214 Processed_Projects.Reset;
2216 -- And process the main project and all of the projects it depends on,
2220 (Project => Project,
2223 From_Project_Node => From_Project_Node,
2224 From_Project_Node_Tree => From_Project_Node_Tree,
2225 Extended_By => No_Project);
2228 Total_Errors_Detected = 0
2230 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2231 end Process_Project_Tree_Phase_1;
2233 ----------------------------------
2234 -- Process_Project_Tree_Phase_2 --
2235 ----------------------------------
2237 procedure Process_Project_Tree_Phase_2
2238 (In_Tree : Project_Tree_Ref;
2239 Project : Project_Id;
2240 Success : out Boolean;
2241 From_Project_Node : Project_Node_Id;
2242 From_Project_Node_Tree : Project_Node_Tree_Ref;
2243 Flags : Processing_Flags)
2245 Obj_Dir : Path_Name_Type;
2246 Extending : Project_Id;
2247 Extending2 : Project_Id;
2250 -- Start of processing for Process_Project_Tree_Phase_2
2255 if Project /= No_Project then
2256 Check (In_Tree, Project, Flags);
2259 -- If main project is an extending all project, set the object
2260 -- directory of all virtual extending projects to the object
2261 -- directory of the main project.
2263 if Project /= No_Project
2265 Is_Extending_All (From_Project_Node, From_Project_Node_Tree)
2268 Object_Dir : constant Path_Name_Type :=
2269 Project.Object_Directory.Name;
2271 Prj := In_Tree.Projects;
2272 while Prj /= null loop
2273 if Prj.Project.Virtual then
2274 Prj.Project.Object_Directory.Name := Object_Dir;
2281 -- Check that no extending project shares its object directory with
2282 -- the project(s) it extends.
2284 if Project /= No_Project then
2285 Prj := In_Tree.Projects;
2286 while Prj /= null loop
2287 Extending := Prj.Project.Extended_By;
2289 if Extending /= No_Project then
2290 Obj_Dir := Prj.Project.Object_Directory.Name;
2292 -- Check that a project being extended does not share its
2293 -- object directory with any project that extends it, directly
2294 -- or indirectly, including a virtual extending project.
2296 -- Start with the project directly extending it
2298 Extending2 := Extending;
2299 while Extending2 /= No_Project loop
2300 if Has_Ada_Sources (Extending2)
2301 and then Extending2.Object_Directory.Name = Obj_Dir
2303 if Extending2.Virtual then
2304 Error_Msg_Name_1 := Prj.Project.Display_Name;
2307 "project %% cannot be extended by a virtual" &
2308 " project with the same object directory",
2309 Prj.Project.Location, Project);
2312 Error_Msg_Name_1 := Extending2.Display_Name;
2313 Error_Msg_Name_2 := Prj.Project.Display_Name;
2316 "project %% cannot extend project %%",
2317 Extending2.Location, Project);
2320 "\they share the same object directory",
2321 Extending2.Location, Project);
2325 -- Continue with the next extending project, if any
2327 Extending2 := Extending2.Extended_By;
2336 Total_Errors_Detected = 0
2338 (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
2339 end Process_Project_Tree_Phase_2;
2341 -----------------------
2342 -- Recursive_Process --
2343 -----------------------
2345 procedure Recursive_Process
2346 (In_Tree : Project_Tree_Ref;
2347 Project : out Project_Id;
2348 Flags : Processing_Flags;
2349 From_Project_Node : Project_Node_Id;
2350 From_Project_Node_Tree : Project_Node_Tree_Ref;
2351 Extended_By : Project_Id)
2353 procedure Process_Imported_Projects
2354 (Imported : in out Project_List;
2355 Limited_With : Boolean);
2356 -- Process imported projects. If Limited_With is True, then only
2357 -- projects processed through a "limited with" are processed, otherwise
2358 -- only projects imported through a standard "with" are processed.
2359 -- Imported is the id of the last imported project.
2361 -------------------------------
2362 -- Process_Imported_Projects --
2363 -------------------------------
2365 procedure Process_Imported_Projects
2366 (Imported : in out Project_List;
2367 Limited_With : Boolean)
2369 With_Clause : Project_Node_Id;
2370 New_Project : Project_Id;
2371 Proj_Node : Project_Node_Id;
2375 First_With_Clause_Of
2376 (From_Project_Node, From_Project_Node_Tree);
2377 while Present (With_Clause) loop
2379 Non_Limited_Project_Node_Of
2380 (With_Clause, From_Project_Node_Tree);
2381 New_Project := No_Project;
2383 if (Limited_With and No (Proj_Node))
2384 or (not Limited_With and Present (Proj_Node))
2387 (In_Tree => In_Tree,
2388 Project => New_Project,
2390 From_Project_Node =>
2392 (With_Clause, From_Project_Node_Tree),
2393 From_Project_Node_Tree => From_Project_Node_Tree,
2394 Extended_By => No_Project);
2396 -- Imported is the id of the last imported project. If
2397 -- it is nil, then this imported project is our first.
2399 if Imported = null then
2400 Project.Imported_Projects :=
2401 new Project_List_Element'
2402 (Project => New_Project,
2404 Imported := Project.Imported_Projects;
2406 Imported.Next := new Project_List_Element'
2407 (Project => New_Project,
2409 Imported := Imported.Next;
2414 Next_With_Clause_Of (With_Clause, From_Project_Node_Tree);
2416 end Process_Imported_Projects;
2418 -- Start of processing for Recursive_Process
2421 if No (From_Project_Node) then
2422 Project := No_Project;
2426 Imported : Project_List;
2427 Declaration_Node : Project_Node_Id := Empty_Node;
2428 Tref : Source_Buffer_Ptr;
2429 Name : constant Name_Id :=
2431 (From_Project_Node, From_Project_Node_Tree);
2432 Location : Source_Ptr :=
2434 (From_Project_Node, From_Project_Node_Tree);
2437 Project := Processed_Projects.Get (Name);
2439 if Project /= No_Project then
2441 -- Make sure that, when a project is extended, the project id
2442 -- of the project extending it is recorded in its data, even
2443 -- when it has already been processed as an imported project.
2444 -- This is for virtually extended projects.
2446 if Extended_By /= No_Project then
2447 Project.Extended_By := Extended_By;
2453 Project := new Project_Data'(Empty_Project);
2454 In_Tree.Projects := new Project_List_Element'
2455 (Project => Project,
2456 Next => In_Tree.Projects);
2458 Processed_Projects.Set (Name, Project);
2460 Project.Name := Name;
2461 Project.Qualifier :=
2462 Project_Qualifier_Of (From_Project_Node, From_Project_Node_Tree);
2464 Get_Name_String (Name);
2466 -- If name starts with the virtual prefix, flag the project as
2467 -- being a virtual extending project.
2469 if Name_Len > Virtual_Prefix'Length
2470 and then Name_Buffer (1 .. Virtual_Prefix'Length) =
2473 Project.Virtual := True;
2474 Project.Display_Name := Name;
2476 -- If there is no file, for example when the project node tree is
2477 -- built in memory by GPS, the Display_Name cannot be found in
2478 -- the source, so its value is the same as Name.
2480 elsif Location = No_Location then
2481 Project.Display_Name := Name;
2483 -- Get the spelling of the project name from the project file
2486 Tref := Source_Text (Get_Source_File_Index (Location));
2488 for J in 1 .. Name_Len loop
2489 Name_Buffer (J) := Tref (Location);
2490 Location := Location + 1;
2493 Project.Display_Name := Name_Find;
2496 Project.Path.Display_Name :=
2497 Path_Name_Of (From_Project_Node, From_Project_Node_Tree);
2498 Get_Name_String (Project.Path.Display_Name);
2499 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2500 Project.Path.Name := Name_Find;
2503 Location_Of (From_Project_Node, From_Project_Node_Tree);
2505 Project.Directory.Display_Name :=
2506 Directory_Of (From_Project_Node, From_Project_Node_Tree);
2507 Get_Name_String (Project.Directory.Display_Name);
2508 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2509 Project.Directory.Name := Name_Find;
2511 Project.Extended_By := Extended_By;
2516 Name_Id (Project.Directory.Name),
2519 Prj.Attr.Attribute_First,
2520 Project_Level => True);
2522 Process_Imported_Projects (Imported, Limited_With => False);
2525 Project_Declaration_Of
2526 (From_Project_Node, From_Project_Node_Tree);
2529 (In_Tree => In_Tree,
2530 Project => Project.Extends,
2532 From_Project_Node => Extended_Project_Of
2534 From_Project_Node_Tree),
2535 From_Project_Node_Tree => From_Project_Node_Tree,
2536 Extended_By => Project);
2538 Process_Declarative_Items
2539 (Project => Project,
2542 From_Project_Node => From_Project_Node,
2543 From_Project_Node_Tree => From_Project_Node_Tree,
2545 Item => First_Declarative_Item_Of
2547 From_Project_Node_Tree));
2549 -- If it is an extending project, inherit all packages
2550 -- from the extended project that are not explicitly defined
2551 -- or renamed. Also inherit the languages, if attribute Languages
2552 -- is not explicitly defined.
2554 if Project.Extends /= No_Project then
2556 Extended_Pkg : Package_Id;
2557 Current_Pkg : Package_Id;
2558 Element : Package_Element;
2559 First : constant Package_Id :=
2560 Project.Decl.Packages;
2561 Attribute1 : Variable_Id;
2562 Attribute2 : Variable_Id;
2563 Attr_Value1 : Variable;
2564 Attr_Value2 : Variable;
2567 Extended_Pkg := Project.Extends.Decl.Packages;
2568 while Extended_Pkg /= No_Package loop
2569 Element := In_Tree.Packages.Table (Extended_Pkg);
2571 Current_Pkg := First;
2572 while Current_Pkg /= No_Package
2573 and then In_Tree.Packages.Table (Current_Pkg).Name /=
2577 In_Tree.Packages.Table (Current_Pkg).Next;
2580 if Current_Pkg = No_Package then
2581 Package_Table.Increment_Last
2583 Current_Pkg := Package_Table.Last (In_Tree.Packages);
2584 In_Tree.Packages.Table (Current_Pkg) :=
2585 (Name => Element.Name,
2586 Decl => No_Declarations,
2587 Parent => No_Package,
2588 Next => Project.Decl.Packages);
2589 Project.Decl.Packages := Current_Pkg;
2590 Copy_Package_Declarations
2591 (From => Element.Decl,
2593 In_Tree.Packages.Table (Current_Pkg).Decl,
2594 New_Loc => No_Location,
2595 Naming_Restricted =>
2596 Element.Name = Snames.Name_Naming,
2597 In_Tree => In_Tree);
2600 Extended_Pkg := Element.Next;
2603 -- Check if attribute Languages is declared in the
2604 -- extending project.
2606 Attribute1 := Project.Decl.Attributes;
2607 while Attribute1 /= No_Variable loop
2608 Attr_Value1 := In_Tree.Variable_Elements.
2610 exit when Attr_Value1.Name = Snames.Name_Languages;
2611 Attribute1 := Attr_Value1.Next;
2614 if Attribute1 = No_Variable or else
2615 Attr_Value1.Value.Default
2617 -- Attribute Languages is not declared in the extending
2618 -- project. Check if it is declared in the project being
2621 Attribute2 := Project.Extends.Decl.Attributes;
2622 while Attribute2 /= No_Variable loop
2623 Attr_Value2 := In_Tree.Variable_Elements.
2625 exit when Attr_Value2.Name = Snames.Name_Languages;
2626 Attribute2 := Attr_Value2.Next;
2629 if Attribute2 /= No_Variable and then
2630 not Attr_Value2.Value.Default
2632 -- As attribute Languages is declared in the project
2633 -- being extended, copy its value for the extending
2636 if Attribute1 = No_Variable then
2637 Variable_Element_Table.Increment_Last
2638 (In_Tree.Variable_Elements);
2639 Attribute1 := Variable_Element_Table.Last
2640 (In_Tree.Variable_Elements);
2641 Attr_Value1.Next := Project.Decl.Attributes;
2642 Project.Decl.Attributes := Attribute1;
2645 Attr_Value1.Name := Snames.Name_Languages;
2646 Attr_Value1.Value := Attr_Value2.Value;
2647 In_Tree.Variable_Elements.Table
2648 (Attribute1) := Attr_Value1;
2654 Process_Imported_Projects (Imported, Limited_With => True);
2657 end Recursive_Process;