OSDN Git Service

2007-09-26 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / prj-proc.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                              P R J . P R O C                             --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 2001-2007, Free Software Foundation, Inc.         --
10 --                                                                          --
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.          --
20 --                                                                          --
21 -- GNAT was originally developed  by the GNAT team at  New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
23 --                                                                          --
24 ------------------------------------------------------------------------------
25
26 with Err_Vars; use Err_Vars;
27 with Opt;      use Opt;
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 Prj.Util; use Prj.Util;
35 with Sinput;   use Sinput;
36 with Snames;
37
38 with GNAT.Case_Util; use GNAT.Case_Util;
39 with GNAT.HTable;
40
41 package body Prj.Proc is
42
43    Error_Report : Put_Line_Access := null;
44
45    package Processed_Projects is new GNAT.HTable.Simple_HTable
46      (Header_Num => Header_Num,
47       Element    => Project_Id,
48       No_Element => No_Project,
49       Key        => Name_Id,
50       Hash       => Hash,
51       Equal      => "=");
52    --  This hash table contains all processed projects
53
54    package Unit_Htable is new GNAT.HTable.Simple_HTable
55      (Header_Num => Header_Num,
56       Element    => Source_Id,
57       No_Element => No_Source,
58       Key        => Name_Id,
59       Hash       => Hash,
60       Equal      => "=");
61    --  This hash table contains all processed projects
62
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.
66
67    procedure Add_Attributes
68      (Project       : Project_Id;
69       Project_Name  : Name_Id;
70       In_Tree       : Project_Tree_Ref;
71       Decl          : in out Declarations;
72       First         : Attribute_Node_Id;
73       Project_Level : Boolean);
74    --  Add all attributes, starting with First, with their default
75    --  values to the package or project with declarations Decl.
76
77    procedure Check
78      (In_Tree         : Project_Tree_Ref;
79       Project         : Project_Id;
80       Follow_Links    : Boolean;
81       When_No_Sources : Error_Warning);
82    --  Set all projects to not checked, then call Recursive_Check for the
83    --  main project Project. Project is set to No_Project if errors occurred.
84
85    procedure Copy_Package_Declarations
86      (From    : Declarations;
87       To      : in out Declarations;
88       New_Loc : Source_Ptr;
89       In_Tree : Project_Tree_Ref);
90    --  Copy a package declaration From to To for a renamed package. Change the
91    --  locations of all the attributes to New_Loc.
92
93    function Expression
94      (Project                : Project_Id;
95       In_Tree                : Project_Tree_Ref;
96       From_Project_Node      : Project_Node_Id;
97       From_Project_Node_Tree : Project_Node_Tree_Ref;
98       Pkg                    : Package_Id;
99       First_Term             : Project_Node_Id;
100       Kind                   : Variable_Kind) return Variable_Value;
101    --  From N_Expression project node From_Project_Node, compute the value
102    --  of an expression and return it as a Variable_Value.
103
104    function Imported_Or_Extended_Project_From
105      (Project   : Project_Id;
106       In_Tree   : Project_Tree_Ref;
107       With_Name : Name_Id) return Project_Id;
108    --  Find an imported or extended project of Project whose name is With_Name
109
110    function Package_From
111      (Project   : Project_Id;
112       In_Tree   : Project_Tree_Ref;
113       With_Name : Name_Id) return Package_Id;
114    --  Find the package of Project whose name is With_Name
115
116    procedure Process_Declarative_Items
117      (Project                : Project_Id;
118       In_Tree                : Project_Tree_Ref;
119       From_Project_Node      : Project_Node_Id;
120       From_Project_Node_Tree : Project_Node_Tree_Ref;
121       Pkg                    : Package_Id;
122       Item                   : Project_Node_Id);
123    --  Process declarative items starting with From_Project_Node, and put them
124    --  in declarations Decl. This is a recursive procedure; it calls itself for
125    --  a package declaration or a case construction.
126
127    procedure Recursive_Process
128      (In_Tree                : Project_Tree_Ref;
129       Project                : out Project_Id;
130       From_Project_Node      : Project_Node_Id;
131       From_Project_Node_Tree : Project_Node_Tree_Ref;
132       Extended_By            : Project_Id);
133    --  Process project with node From_Project_Node in the tree.
134    --  Do nothing if From_Project_Node is Empty_Node.
135    --  If project has already been processed, simply return its project id.
136    --  Otherwise create a new project id, mark it as processed, call itself
137    --  recursively for all imported projects and a extended project, if any.
138    --  Then process the declarative items of the project.
139
140    procedure Recursive_Check
141      (Project         : Project_Id;
142       In_Tree         : Project_Tree_Ref;
143       Follow_Links    : Boolean;
144       When_No_Sources : Error_Warning);
145    --  If Project is not marked as checked, mark it as checked, call
146    --  Check_Naming_Scheme for the project, then call itself for a
147    --  possible extended project and all the imported projects of Project.
148
149    ---------
150    -- Add --
151    ---------
152
153    procedure Add (To_Exp : in out Name_Id; Str : Name_Id) is
154    begin
155       if To_Exp = No_Name or else To_Exp = Empty_String then
156
157          --  To_Exp is nil or empty. The result is Str
158
159          To_Exp := Str;
160
161       --  If Str is nil, then do not change To_Ext
162
163       elsif Str /= No_Name and then Str /= Empty_String then
164          declare
165             S : constant String := Get_Name_String (Str);
166
167          begin
168             Get_Name_String (To_Exp);
169             Add_Str_To_Name_Buffer (S);
170             To_Exp := Name_Find;
171          end;
172       end if;
173    end Add;
174
175    --------------------
176    -- Add_Attributes --
177    --------------------
178
179    procedure Add_Attributes
180      (Project       : Project_Id;
181       Project_Name  : Name_Id;
182       In_Tree       : Project_Tree_Ref;
183       Decl          : in out Declarations;
184       First         : Attribute_Node_Id;
185       Project_Level : Boolean)
186    is
187       The_Attribute  : Attribute_Node_Id := First;
188
189    begin
190       while The_Attribute /= Empty_Attribute loop
191          if Attribute_Kind_Of (The_Attribute) = Single then
192             declare
193                New_Attribute : Variable_Value;
194
195             begin
196                case Variable_Kind_Of (The_Attribute) is
197
198                   --  Undefined should not happen
199
200                   when Undefined =>
201                      pragma Assert
202                        (False, "attribute with an undefined kind");
203                      raise Program_Error;
204
205                   --  Single attributes have a default value of empty string
206
207                   when Single =>
208                      New_Attribute :=
209                        (Project  => Project,
210                         Kind     => Single,
211                         Location => No_Location,
212                         Default  => True,
213                         Value    => Empty_String,
214                         Index    => 0);
215
216                      --  Special case of <project>'Name
217
218                      if Project_Level
219                        and then Attribute_Name_Of (The_Attribute) =
220                                   Snames.Name_Name
221                      then
222                         New_Attribute.Value := Project_Name;
223                      end if;
224
225                   --  List attributes have a default value of nil list
226
227                   when List =>
228                      New_Attribute :=
229                        (Project  => Project,
230                         Kind     => List,
231                         Location => No_Location,
232                         Default  => True,
233                         Values   => Nil_String);
234
235                end case;
236
237                Variable_Element_Table.Increment_Last
238                  (In_Tree.Variable_Elements);
239                In_Tree.Variable_Elements.Table
240                  (Variable_Element_Table.Last
241                    (In_Tree.Variable_Elements)) :=
242                  (Next  => Decl.Attributes,
243                   Name  => Attribute_Name_Of (The_Attribute),
244                   Value => New_Attribute);
245                Decl.Attributes := Variable_Element_Table.Last
246                  (In_Tree.Variable_Elements);
247             end;
248          end if;
249
250          The_Attribute := Next_Attribute (After => The_Attribute);
251       end loop;
252    end Add_Attributes;
253
254    -----------
255    -- Check --
256    -----------
257
258    procedure Check
259      (In_Tree         : Project_Tree_Ref;
260       Project         : Project_Id;
261       Follow_Links    : Boolean;
262       When_No_Sources : Error_Warning)
263    is
264    begin
265       --  Make sure that all projects are marked as not checked
266
267       for Index in Project_Table.First ..
268                    Project_Table.Last (In_Tree.Projects)
269       loop
270          In_Tree.Projects.Table (Index).Checked := False;
271       end loop;
272
273       Recursive_Check
274         (Project, In_Tree, Follow_Links, When_No_Sources);
275
276       --  Set the Other_Part field for the units
277
278       declare
279          Source1 : Source_Id;
280          Name    : Name_Id;
281          Source2 : Source_Id;
282
283       begin
284          Unit_Htable.Reset;
285
286          Source1 := In_Tree.First_Source;
287          while Source1 /= No_Source loop
288             Name := In_Tree.Sources.Table (Source1).Unit;
289
290             if Name /= No_Name then
291                Source2 := Unit_Htable.Get (Name);
292
293                if Source2 = No_Source then
294                   Unit_Htable.Set (K => Name, E => Source1);
295
296                else
297                   Unit_Htable.Remove (Name);
298                   In_Tree.Sources.Table (Source1).Other_Part := Source2;
299                   In_Tree.Sources.Table (Source2).Other_Part := Source1;
300                end if;
301             end if;
302
303             Source1 := In_Tree.Sources.Table (Source1).Next_In_Sources;
304          end loop;
305       end;
306    end Check;
307
308    -------------------------------
309    -- Copy_Package_Declarations --
310    -------------------------------
311
312    procedure Copy_Package_Declarations
313      (From    : Declarations;
314       To      : in out Declarations;
315       New_Loc : Source_Ptr;
316       In_Tree : Project_Tree_Ref)
317    is
318       V1  : Variable_Id := From.Attributes;
319       V2  : Variable_Id := No_Variable;
320       Var : Variable;
321       A1  : Array_Id := From.Arrays;
322       A2  : Array_Id := No_Array;
323       Arr : Array_Data;
324       E1  : Array_Element_Id;
325       E2  : Array_Element_Id := No_Array_Element;
326       Elm : Array_Element;
327
328    begin
329       --  To avoid references in error messages to attribute declarations in
330       --  an original package that has been renamed, copy all the attribute
331       --  declarations of the package and change all locations to New_Loc,
332       --  the location of the renamed package.
333
334       --  First single attributes
335
336       while V1 /= No_Variable loop
337
338          --  Copy the attribute
339
340          Var := In_Tree.Variable_Elements.Table (V1);
341          V1  := Var.Next;
342
343          --  Remove the Next component
344
345          Var.Next := No_Variable;
346
347          --  Change the location to New_Loc
348
349          Var.Value.Location := New_Loc;
350          Variable_Element_Table.Increment_Last (In_Tree.Variable_Elements);
351
352          --  Put in new declaration
353
354          if To.Attributes = No_Variable then
355             To.Attributes :=
356               Variable_Element_Table.Last (In_Tree.Variable_Elements);
357
358          else
359             In_Tree.Variable_Elements.Table (V2).Next :=
360               Variable_Element_Table.Last (In_Tree.Variable_Elements);
361          end if;
362
363          V2 := Variable_Element_Table.Last (In_Tree.Variable_Elements);
364          In_Tree.Variable_Elements.Table (V2) := Var;
365       end loop;
366
367       --  Then the associated array attributes
368
369       while A1 /= No_Array loop
370
371          --  Copy the array
372
373          Arr := In_Tree.Arrays.Table (A1);
374          A1  := Arr.Next;
375
376          --  Remove the Next component
377
378          Arr.Next := No_Array;
379
380          Array_Table.Increment_Last (In_Tree.Arrays);
381
382          --  Create new Array declaration
383          if To.Arrays = No_Array then
384             To.Arrays := Array_Table.Last (In_Tree.Arrays);
385
386          else
387             In_Tree.Arrays.Table (A2).Next :=
388               Array_Table.Last (In_Tree.Arrays);
389          end if;
390
391          A2 := Array_Table.Last (In_Tree.Arrays);
392
393          --  Don't store the array, as its first element has not been set yet
394
395          --  Copy the array elements of the array
396
397          E1 := Arr.Value;
398          Arr.Value := No_Array_Element;
399
400          while E1 /= No_Array_Element loop
401
402             --  Copy the array element
403
404             Elm := In_Tree.Array_Elements.Table (E1);
405             E1 := Elm.Next;
406
407             --  Remove the Next component
408
409             Elm.Next := No_Array_Element;
410
411             --  Change the location
412
413             Elm.Value.Location := New_Loc;
414             Array_Element_Table.Increment_Last (In_Tree.Array_Elements);
415
416             --  Create new array element
417
418             if Arr.Value = No_Array_Element then
419                Arr.Value := Array_Element_Table.Last (In_Tree.Array_Elements);
420             else
421                In_Tree.Array_Elements.Table (E2).Next :=
422                  Array_Element_Table.Last (In_Tree.Array_Elements);
423             end if;
424
425             E2 := Array_Element_Table.Last (In_Tree.Array_Elements);
426             In_Tree.Array_Elements.Table (E2) := Elm;
427          end loop;
428
429          --  Finally, store the new array
430
431          In_Tree.Arrays.Table (A2) := Arr;
432       end loop;
433    end Copy_Package_Declarations;
434
435    ----------------
436    -- Expression --
437    ----------------
438
439    function Expression
440      (Project                : Project_Id;
441       In_Tree                : Project_Tree_Ref;
442       From_Project_Node      : Project_Node_Id;
443       From_Project_Node_Tree : Project_Node_Tree_Ref;
444       Pkg                    : Package_Id;
445       First_Term             : Project_Node_Id;
446       Kind                   : Variable_Kind) return Variable_Value
447    is
448       The_Term : Project_Node_Id := First_Term;
449       --  The term in the expression list
450
451       The_Current_Term : Project_Node_Id := Empty_Node;
452       --  The current term node id
453
454       Result : Variable_Value (Kind => Kind);
455       --  The returned result
456
457       Last : String_List_Id := Nil_String;
458       --  Reference to the last string elements in Result, when Kind is List
459
460    begin
461       Result.Project := Project;
462       Result.Location := Location_Of (First_Term, From_Project_Node_Tree);
463
464       --  Process each term of the expression, starting with First_Term
465
466       while The_Term /= Empty_Node loop
467          The_Current_Term := Current_Term (The_Term, From_Project_Node_Tree);
468
469          case Kind_Of (The_Current_Term, From_Project_Node_Tree) is
470
471             when N_Literal_String =>
472
473                case Kind is
474
475                   when Undefined =>
476
477                      --  Should never happen
478
479                      pragma Assert (False, "Undefined expression kind");
480                      raise Program_Error;
481
482                   when Single =>
483                      Add (Result.Value,
484                           String_Value_Of
485                             (The_Current_Term, From_Project_Node_Tree));
486                      Result.Index :=
487                        Source_Index_Of
488                          (The_Current_Term, From_Project_Node_Tree);
489
490                   when List =>
491
492                      String_Element_Table.Increment_Last
493                        (In_Tree.String_Elements);
494
495                      if Last = Nil_String then
496
497                         --  This can happen in an expression like () & "toto"
498
499                         Result.Values := String_Element_Table.Last
500                           (In_Tree.String_Elements);
501
502                      else
503                         In_Tree.String_Elements.Table
504                           (Last).Next := String_Element_Table.Last
505                                        (In_Tree.String_Elements);
506                      end if;
507
508                      Last := String_Element_Table.Last
509                        (In_Tree.String_Elements);
510                      In_Tree.String_Elements.Table (Last) :=
511                        (Value    =>
512                           String_Value_Of
513                             (The_Current_Term,
514                              From_Project_Node_Tree),
515                         Index    =>
516                           Source_Index_Of
517                             (The_Current_Term, From_Project_Node_Tree),
518                         Display_Value => No_Name,
519                         Location      =>
520                           Location_Of
521                             (The_Current_Term,
522                              From_Project_Node_Tree),
523                         Flag     => False,
524                         Next     => Nil_String);
525                end case;
526
527             when N_Literal_String_List =>
528
529                declare
530                   String_Node : Project_Node_Id :=
531                                   First_Expression_In_List
532                                     (The_Current_Term,
533                                      From_Project_Node_Tree);
534
535                   Value : Variable_Value;
536
537                begin
538                   if String_Node /= Empty_Node then
539
540                      --  If String_Node is nil, it is an empty list,
541                      --  there is nothing to do
542
543                      Value := Expression
544                        (Project                => Project,
545                         In_Tree                => In_Tree,
546                         From_Project_Node      => From_Project_Node,
547                         From_Project_Node_Tree => From_Project_Node_Tree,
548                         Pkg                    => Pkg,
549                         First_Term             =>
550                           Tree.First_Term
551                             (String_Node, From_Project_Node_Tree),
552                         Kind                   => Single);
553                      String_Element_Table.Increment_Last
554                        (In_Tree.String_Elements);
555
556                      if Result.Values = Nil_String then
557
558                         --  This literal string list is the first term
559                         --  in a string list expression
560
561                         Result.Values :=
562                           String_Element_Table.Last (In_Tree.String_Elements);
563
564                      else
565                         In_Tree.String_Elements.Table
566                           (Last).Next :=
567                           String_Element_Table.Last (In_Tree.String_Elements);
568                      end if;
569
570                      Last :=
571                        String_Element_Table.Last (In_Tree.String_Elements);
572
573                      In_Tree.String_Elements.Table (Last) :=
574                        (Value    => Value.Value,
575                         Display_Value => No_Name,
576                         Location => Value.Location,
577                         Flag     => False,
578                         Next     => Nil_String,
579                         Index    => Value.Index);
580
581                      loop
582                         --  Add the other element of the literal string list
583                         --  one after the other
584
585                         String_Node :=
586                           Next_Expression_In_List
587                             (String_Node, From_Project_Node_Tree);
588
589                         exit when String_Node = Empty_Node;
590
591                         Value :=
592                           Expression
593                             (Project                => Project,
594                              In_Tree                => In_Tree,
595                              From_Project_Node      => From_Project_Node,
596                              From_Project_Node_Tree => From_Project_Node_Tree,
597                              Pkg                    => Pkg,
598                              First_Term             =>
599                                Tree.First_Term
600                                  (String_Node, From_Project_Node_Tree),
601                              Kind                   => Single);
602
603                         String_Element_Table.Increment_Last
604                           (In_Tree.String_Elements);
605                         In_Tree.String_Elements.Table
606                           (Last).Next := String_Element_Table.Last
607                                         (In_Tree.String_Elements);
608                         Last := String_Element_Table.Last
609                           (In_Tree.String_Elements);
610                         In_Tree.String_Elements.Table (Last) :=
611                           (Value    => Value.Value,
612                            Display_Value => No_Name,
613                            Location => Value.Location,
614                            Flag     => False,
615                            Next     => Nil_String,
616                            Index    => Value.Index);
617                      end loop;
618                   end if;
619                end;
620
621             when N_Variable_Reference | N_Attribute_Reference =>
622
623                declare
624                   The_Project     : Project_Id  := Project;
625                   The_Package     : Package_Id  := Pkg;
626                   The_Name        : Name_Id     := No_Name;
627                   The_Variable_Id : Variable_Id := No_Variable;
628                   The_Variable    : Variable_Value;
629                   Term_Project    : constant Project_Node_Id :=
630                                       Project_Node_Of
631                                         (The_Current_Term,
632                                          From_Project_Node_Tree);
633                   Term_Package    : constant Project_Node_Id :=
634                                       Package_Node_Of
635                                         (The_Current_Term,
636                                          From_Project_Node_Tree);
637                   Index           : Name_Id := No_Name;
638
639                begin
640                   if Term_Project /= Empty_Node and then
641                      Term_Project /= From_Project_Node
642                   then
643                      --  This variable or attribute comes from another project
644
645                      The_Name :=
646                        Name_Of (Term_Project, From_Project_Node_Tree);
647                      The_Project := Imported_Or_Extended_Project_From
648                                       (Project   => Project,
649                                        In_Tree   => In_Tree,
650                                        With_Name => The_Name);
651                   end if;
652
653                   if Term_Package /= Empty_Node then
654
655                      --  This is an attribute of a package
656
657                      The_Name :=
658                        Name_Of (Term_Package, From_Project_Node_Tree);
659                      The_Package := In_Tree.Projects.Table
660                                       (The_Project).Decl.Packages;
661
662                      while The_Package /= No_Package
663                        and then In_Tree.Packages.Table
664                                   (The_Package).Name /= The_Name
665                      loop
666                         The_Package :=
667                           In_Tree.Packages.Table
668                             (The_Package).Next;
669                      end loop;
670
671                      pragma Assert
672                        (The_Package /= No_Package,
673                         "package not found.");
674
675                   elsif Kind_Of (The_Current_Term, From_Project_Node_Tree) =
676                           N_Attribute_Reference
677                   then
678                      The_Package := No_Package;
679                   end if;
680
681                   The_Name :=
682                     Name_Of (The_Current_Term, From_Project_Node_Tree);
683
684                   if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
685                        N_Attribute_Reference
686                   then
687                      Index :=
688                        Associative_Array_Index_Of
689                          (The_Current_Term, From_Project_Node_Tree);
690                   end if;
691
692                   --  If it is not an associative array attribute
693
694                   if Index = No_Name then
695
696                      --  It is not an associative array attribute
697
698                      if The_Package /= No_Package then
699
700                         --  First, if there is a package, look into the package
701
702                         if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
703                              N_Variable_Reference
704                         then
705                            The_Variable_Id :=
706                              In_Tree.Packages.Table
707                                (The_Package).Decl.Variables;
708                         else
709                            The_Variable_Id :=
710                              In_Tree.Packages.Table
711                                (The_Package).Decl.Attributes;
712                         end if;
713
714                         while The_Variable_Id /= No_Variable
715                           and then
716                             In_Tree.Variable_Elements.Table
717                               (The_Variable_Id).Name /= The_Name
718                         loop
719                            The_Variable_Id :=
720                              In_Tree.Variable_Elements.Table
721                                (The_Variable_Id).Next;
722                         end loop;
723
724                      end if;
725
726                      if The_Variable_Id = No_Variable then
727
728                         --  If we have not found it, look into the project
729
730                         if Kind_Of (The_Current_Term, From_Project_Node_Tree) =
731                              N_Variable_Reference
732                         then
733                            The_Variable_Id :=
734                              In_Tree.Projects.Table
735                                (The_Project).Decl.Variables;
736                         else
737                            The_Variable_Id :=
738                              In_Tree.Projects.Table
739                                (The_Project).Decl.Attributes;
740                         end if;
741
742                         while The_Variable_Id /= No_Variable
743                           and then
744                           In_Tree.Variable_Elements.Table
745                             (The_Variable_Id).Name /= The_Name
746                         loop
747                            The_Variable_Id :=
748                              In_Tree.Variable_Elements.Table
749                                (The_Variable_Id).Next;
750                         end loop;
751
752                      end if;
753
754                      pragma Assert (The_Variable_Id /= No_Variable,
755                                       "variable or attribute not found");
756
757                      The_Variable :=
758                        In_Tree.Variable_Elements.Table
759                                                     (The_Variable_Id).Value;
760
761                   else
762
763                      --  It is an associative array attribute
764
765                      declare
766                         The_Array   : Array_Id := No_Array;
767                         The_Element : Array_Element_Id := No_Array_Element;
768                         Array_Index : Name_Id := No_Name;
769
770                      begin
771                         if The_Package /= No_Package then
772                            The_Array :=
773                              In_Tree.Packages.Table
774                                (The_Package).Decl.Arrays;
775                         else
776                            The_Array :=
777                              In_Tree.Projects.Table
778                                (The_Project).Decl.Arrays;
779                         end if;
780
781                         while The_Array /= No_Array
782                           and then In_Tree.Arrays.Table
783                                      (The_Array).Name /= The_Name
784                         loop
785                            The_Array := In_Tree.Arrays.Table
786                                           (The_Array).Next;
787                         end loop;
788
789                         if The_Array /= No_Array then
790                            The_Element := In_Tree.Arrays.Table
791                                             (The_Array).Value;
792
793                            Get_Name_String (Index);
794
795                            if Case_Insensitive
796                                 (The_Current_Term, From_Project_Node_Tree)
797                            then
798                               To_Lower (Name_Buffer (1 .. Name_Len));
799                            end if;
800
801                            Array_Index := Name_Find;
802
803                            while The_Element /= No_Array_Element
804                              and then
805                              In_Tree.Array_Elements.Table
806                                (The_Element).Index /= Array_Index
807                            loop
808                               The_Element :=
809                                 In_Tree.Array_Elements.Table
810                                   (The_Element).Next;
811                            end loop;
812
813                         end if;
814
815                         if The_Element /= No_Array_Element then
816                            The_Variable :=
817                              In_Tree.Array_Elements.Table
818                                (The_Element).Value;
819
820                         else
821                            if Expression_Kind_Of
822                              (The_Current_Term, From_Project_Node_Tree) =
823                                                                         List
824                            then
825                               The_Variable :=
826                                 (Project  => Project,
827                                  Kind     => List,
828                                  Location => No_Location,
829                                  Default  => True,
830                                  Values   => Nil_String);
831                            else
832                               The_Variable :=
833                                 (Project  => Project,
834                                  Kind     => Single,
835                                  Location => No_Location,
836                                  Default  => True,
837                                  Value    => Empty_String,
838                                  Index    => 0);
839                            end if;
840                         end if;
841                      end;
842                   end if;
843
844                   case Kind is
845
846                      when Undefined =>
847
848                         --  Should never happen
849
850                         pragma Assert (False, "undefined expression kind");
851                         null;
852
853                      when Single =>
854
855                         case The_Variable.Kind is
856
857                            when Undefined =>
858                               null;
859
860                            when Single =>
861                               Add (Result.Value, The_Variable.Value);
862
863                            when List =>
864
865                               --  Should never happen
866
867                               pragma Assert
868                                 (False,
869                                  "list cannot appear in single " &
870                                  "string expression");
871                               null;
872                         end case;
873
874                      when List =>
875                         case The_Variable.Kind is
876
877                            when Undefined =>
878                               null;
879
880                            when Single =>
881                               String_Element_Table.Increment_Last
882                                 (In_Tree.String_Elements);
883
884                               if Last = Nil_String then
885
886                                  --  This can happen in an expression such as
887                                  --  () & Var
888
889                                  Result.Values :=
890                                    String_Element_Table.Last
891                                      (In_Tree.String_Elements);
892
893                               else
894                                  In_Tree.String_Elements.Table
895                                    (Last).Next :=
896                                      String_Element_Table.Last
897                                        (In_Tree.String_Elements);
898                               end if;
899
900                               Last :=
901                                 String_Element_Table.Last
902                                   (In_Tree.String_Elements);
903
904                               In_Tree.String_Elements.Table (Last) :=
905                                 (Value         => The_Variable.Value,
906                                  Display_Value => No_Name,
907                                  Location      => Location_Of
908                                                     (The_Current_Term,
909                                                      From_Project_Node_Tree),
910                                  Flag          => False,
911                                  Next          => Nil_String,
912                                  Index         => 0);
913
914                            when List =>
915
916                               declare
917                                  The_List : String_List_Id :=
918                                               The_Variable.Values;
919
920                               begin
921                                  while The_List /= Nil_String loop
922                                     String_Element_Table.Increment_Last
923                                       (In_Tree.String_Elements);
924
925                                     if Last = Nil_String then
926                                        Result.Values :=
927                                          String_Element_Table.Last
928                                            (In_Tree.
929                                                 String_Elements);
930
931                                     else
932                                        In_Tree.
933                                          String_Elements.Table (Last).Next :=
934                                          String_Element_Table.Last
935                                            (In_Tree.
936                                                 String_Elements);
937
938                                     end if;
939
940                                     Last :=
941                                       String_Element_Table.Last
942                                         (In_Tree.String_Elements);
943
944                                     In_Tree.String_Elements.Table (Last) :=
945                                       (Value         =>
946                                          In_Tree.String_Elements.Table
947                                            (The_List).Value,
948                                        Display_Value => No_Name,
949                                        Location      =>
950                                          Location_Of
951                                            (The_Current_Term,
952                                             From_Project_Node_Tree),
953                                        Flag         => False,
954                                        Next         => Nil_String,
955                                        Index        => 0);
956
957                                     The_List :=
958                                       In_Tree. String_Elements.Table
959                                         (The_List).Next;
960                                  end loop;
961                               end;
962                         end case;
963                   end case;
964                end;
965
966             when N_External_Value =>
967                Get_Name_String
968                  (String_Value_Of
969                     (External_Reference_Of
970                        (The_Current_Term, From_Project_Node_Tree),
971                      From_Project_Node_Tree));
972
973                declare
974                   Name    : constant Name_Id  := Name_Find;
975                   Default : Name_Id           := No_Name;
976                   Value   : Name_Id           := No_Name;
977
978                   Def_Var : Variable_Value;
979
980                   Default_Node : constant Project_Node_Id :=
981                     External_Default_Of
982                       (The_Current_Term, From_Project_Node_Tree);
983
984                begin
985                   --  If there is a default value for the external reference,
986                   --  get its value.
987
988                   if Default_Node /= Empty_Node then
989                      Def_Var := Expression
990                        (Project                => Project,
991                         In_Tree                => In_Tree,
992                         From_Project_Node      => Default_Node,
993                         From_Project_Node_Tree => From_Project_Node_Tree,
994                         Pkg                    => Pkg,
995                         First_Term             =>
996                           Tree.First_Term
997                             (Default_Node, From_Project_Node_Tree),
998                         Kind                   => Single);
999
1000                      if Def_Var /= Nil_Variable_Value then
1001                         Default := Def_Var.Value;
1002                      end if;
1003                   end if;
1004
1005                   Value := Prj.Ext.Value_Of (Name, Default);
1006
1007                   if Value = No_Name then
1008                      if not Quiet_Output then
1009                         if Error_Report = null then
1010                            Error_Msg
1011                              ("?undefined external reference",
1012                               Location_Of
1013                                 (The_Current_Term, From_Project_Node_Tree));
1014                         else
1015                            Error_Report
1016                              ("warning: """ & Get_Name_String (Name) &
1017                               """ is an undefined external reference",
1018                               Project, In_Tree);
1019                         end if;
1020                      end if;
1021
1022                      Value := Empty_String;
1023                   end if;
1024
1025                   case Kind is
1026
1027                      when Undefined =>
1028                         null;
1029
1030                      when Single =>
1031                         Add (Result.Value, Value);
1032
1033                      when List =>
1034                         String_Element_Table.Increment_Last
1035                           (In_Tree.String_Elements);
1036
1037                         if Last = Nil_String then
1038                            Result.Values := String_Element_Table.Last
1039                              (In_Tree.String_Elements);
1040
1041                         else
1042                            In_Tree.String_Elements.Table
1043                              (Last).Next := String_Element_Table.Last
1044                                        (In_Tree.String_Elements);
1045                         end if;
1046
1047                         Last := String_Element_Table.Last
1048                                   (In_Tree.String_Elements);
1049                         In_Tree.String_Elements.Table (Last) :=
1050                           (Value    => Value,
1051                            Display_Value => No_Name,
1052                            Location      =>
1053                              Location_Of
1054                                (The_Current_Term, From_Project_Node_Tree),
1055                            Flag     => False,
1056                            Next     => Nil_String,
1057                            Index    => 0);
1058
1059                   end case;
1060                end;
1061
1062             when others =>
1063
1064                --  Should never happen
1065
1066                pragma Assert
1067                  (False,
1068                   "illegal node kind in an expression");
1069                raise Program_Error;
1070
1071          end case;
1072
1073          The_Term := Next_Term (The_Term, From_Project_Node_Tree);
1074       end loop;
1075
1076       return Result;
1077    end Expression;
1078
1079    ---------------------------------------
1080    -- Imported_Or_Extended_Project_From --
1081    ---------------------------------------
1082
1083    function Imported_Or_Extended_Project_From
1084      (Project   : Project_Id;
1085       In_Tree   : Project_Tree_Ref;
1086       With_Name : Name_Id) return Project_Id
1087    is
1088       Data        : constant Project_Data :=
1089                       In_Tree.Projects.Table (Project);
1090       List        : Project_List          := Data.Imported_Projects;
1091       Result      : Project_Id := No_Project;
1092       Temp_Result : Project_Id := No_Project;
1093
1094    begin
1095       --  First check if it is the name of an extended project
1096
1097       if Data.Extends /= No_Project
1098         and then In_Tree.Projects.Table (Data.Extends).Name =
1099                    With_Name
1100       then
1101          return Data.Extends;
1102
1103       else
1104          --  Then check the name of each imported project
1105
1106          while List /= Empty_Project_List loop
1107             Result := In_Tree.Project_Lists.Table (List).Project;
1108
1109             --  If the project is directly imported, then returns its ID
1110
1111             if
1112               In_Tree.Projects.Table (Result).Name = With_Name
1113             then
1114                return Result;
1115             end if;
1116
1117             --  If a project extending the project is imported, then keep
1118             --  this extending project as a possibility. It will be the
1119             --  returned ID if the project is not imported directly.
1120
1121             declare
1122                Proj : Project_Id :=
1123                  In_Tree.Projects.Table (Result).Extends;
1124             begin
1125                while Proj /= No_Project loop
1126                   if In_Tree.Projects.Table (Proj).Name =
1127                        With_Name
1128                   then
1129                      Temp_Result := Result;
1130                      exit;
1131                   end if;
1132
1133                   Proj := In_Tree.Projects.Table (Proj).Extends;
1134                end loop;
1135             end;
1136
1137             List := In_Tree.Project_Lists.Table (List).Next;
1138          end loop;
1139
1140          pragma Assert
1141            (Temp_Result /= No_Project,
1142            "project not found");
1143
1144          return Temp_Result;
1145       end if;
1146    end Imported_Or_Extended_Project_From;
1147
1148    ------------------
1149    -- Package_From --
1150    ------------------
1151
1152    function Package_From
1153      (Project   : Project_Id;
1154       In_Tree   : Project_Tree_Ref;
1155       With_Name : Name_Id) return Package_Id
1156    is
1157       Data   : constant Project_Data :=
1158         In_Tree.Projects.Table (Project);
1159       Result : Package_Id := Data.Decl.Packages;
1160
1161    begin
1162       --  Check the name of each existing package of Project
1163
1164       while Result /= No_Package
1165         and then In_Tree.Packages.Table (Result).Name /= With_Name
1166       loop
1167          Result := In_Tree.Packages.Table (Result).Next;
1168       end loop;
1169
1170       if Result = No_Package then
1171
1172          --  Should never happen
1173
1174          Write_Line ("package """ & Get_Name_String (With_Name) &
1175                      """ not found");
1176          raise Program_Error;
1177
1178       else
1179          return Result;
1180       end if;
1181    end Package_From;
1182
1183    -------------
1184    -- Process --
1185    -------------
1186
1187    procedure Process
1188      (In_Tree                : Project_Tree_Ref;
1189       Project                : out Project_Id;
1190       Success                : out Boolean;
1191       From_Project_Node      : Project_Node_Id;
1192       From_Project_Node_Tree : Project_Node_Tree_Ref;
1193       Report_Error           : Put_Line_Access;
1194       Follow_Links           : Boolean := True;
1195       When_No_Sources        : Error_Warning := Error;
1196       Reset_Tree             : Boolean := True)
1197    is
1198       Obj_Dir    : Path_Name_Type;
1199       Extending  : Project_Id;
1200       Extending2 : Project_Id;
1201       Packages   : Package_Id;
1202       Element    : Package_Element;
1203
1204       procedure Process_Attributes (Attrs : Variable_Id);
1205
1206       ------------------------
1207       -- Process_Attributes --
1208       ------------------------
1209
1210       procedure Process_Attributes (Attrs : Variable_Id) is
1211          Attribute_Id : Variable_Id;
1212          Attribute    : Variable;
1213          List         : String_List_Id;
1214
1215       begin
1216          --  Loop through attributes
1217
1218          Attribute_Id := Attrs;
1219          while Attribute_Id /= No_Variable loop
1220             Attribute :=
1221               In_Tree.Variable_Elements.Table (Attribute_Id);
1222
1223             if not Attribute.Value.Default then
1224                case Attribute.Name is
1225                   when Snames.Name_Driver =>
1226
1227                      --  Attribute Linker'Driver: the default linker to use
1228
1229                      In_Tree.Config.Linker :=
1230                        Path_Name_Type (Attribute.Value.Value);
1231
1232                   when Snames.Name_Required_Switches =>
1233
1234                      --  Attribute Linker'Required_Switches: the minimum
1235                      --  options to use when invoking the linker
1236
1237                      Put (Into_List =>
1238                           In_Tree.Config.Minimum_Linker_Options,
1239                           From_List => Attribute.Value.Values,
1240                           In_Tree   => In_Tree);
1241
1242                   when Snames.Name_Executable_Suffix =>
1243
1244                      --  Attribute Executable_Suffix: the suffix of the
1245                      --  executables.
1246
1247                      In_Tree.Config.Executable_Suffix :=
1248                        Attribute.Value.Value;
1249
1250                   when Snames.Name_Library_Builder =>
1251
1252                      --  Attribute Library_Builder: the application to invoke
1253                      --  to build libraries.
1254
1255                      In_Tree.Config.Library_Builder :=
1256                        Path_Name_Type (Attribute.Value.Value);
1257
1258                   when Snames.Name_Archive_Builder =>
1259
1260                      --  Attribute Archive_Builder: the archive builder
1261                      --  (usually "ar") and its minimum options (usually "cr").
1262
1263                      List := Attribute.Value.Values;
1264
1265                      if List = Nil_String then
1266                         Error_Msg
1267                           ("archive builder cannot be null",
1268                            Attribute.Value.Location);
1269                      end if;
1270
1271                      Put (Into_List => In_Tree.Config.Archive_Builder,
1272                           From_List => List,
1273                           In_Tree   => In_Tree);
1274
1275                   when Snames.Name_Archive_Indexer =>
1276
1277                      --  Attribute Archive_Indexer: the optional archive
1278                      --  indexer (usually "ranlib") with its minimum options
1279                      --  (usually none).
1280
1281                      List := Attribute.Value.Values;
1282
1283                      if List = Nil_String then
1284                         Error_Msg
1285                           ("archive indexer cannot be null",
1286                            Attribute.Value.Location);
1287                      end if;
1288
1289                      Put (Into_List => In_Tree.Config.Archive_Indexer,
1290                           From_List => List,
1291                           In_Tree   => In_Tree);
1292
1293                   when Snames.Name_Library_Partial_Linker =>
1294
1295                      --  Attribute Library_Partial_Linker: the optional linker
1296                      --  driver with its minimum options, to partially link
1297                      --  archives.
1298
1299                      List := Attribute.Value.Values;
1300
1301                      if List = Nil_String then
1302                         Error_Msg
1303                           ("partial linker cannot be null",
1304                            Attribute.Value.Location);
1305                      end if;
1306
1307                      Put (Into_List => In_Tree.Config.Lib_Partial_Linker,
1308                           From_List => List,
1309                           In_Tree   => In_Tree);
1310
1311                   when Snames.Name_Archive_Suffix =>
1312                      In_Tree.Config.Archive_Suffix :=
1313                        File_Name_Type (Attribute.Value.Value);
1314
1315                   when Snames.Name_Linker_Executable_Option =>
1316
1317                      --  Attribute Linker_Executable_Option: optional options
1318                      --  to specify an executable name. Defaults to "-o".
1319
1320                      List := Attribute.Value.Values;
1321
1322                      if List = Nil_String then
1323                         Error_Msg
1324                           ("linker executable option cannot be null",
1325                            Attribute.Value.Location);
1326                      end if;
1327
1328                      Put (Into_List =>
1329                           In_Tree.Config.Linker_Executable_Option,
1330                           From_List => List,
1331                           In_Tree   => In_Tree);
1332
1333                   when Snames.Name_Linker_Lib_Dir_Option =>
1334
1335                      --  Attribute Linker_Lib_Dir_Option: optional options
1336                      --  to specify a library search directory. Defaults to
1337                      --  "-L".
1338
1339                      Get_Name_String (Attribute.Value.Value);
1340
1341                      if Name_Len = 0 then
1342                         Error_Msg
1343                           ("linker library directory option cannot be empty",
1344                            Attribute.Value.Location);
1345                      end if;
1346
1347                      In_Tree.Config.Linker_Lib_Dir_Option :=
1348                        Attribute.Value.Value;
1349
1350                   when Snames.Name_Linker_Lib_Name_Option =>
1351
1352                      --  Attribute Linker_Lib_Name_Option: optional options
1353                      --  to specify the name of a library to be linked in.
1354                      --  Defaults to "-l".
1355
1356                      Get_Name_String (Attribute.Value.Value);
1357
1358                      if Name_Len = 0 then
1359                         Error_Msg
1360                           ("linker library name option cannot be empty",
1361                            Attribute.Value.Location);
1362                      end if;
1363
1364                      In_Tree.Config.Linker_Lib_Name_Option :=
1365                        Attribute.Value.Value;
1366
1367                   when Snames.Name_Run_Path_Option =>
1368
1369                      --  Attribute Run_Path_Option: optional options to
1370                      --  specify a path for libraries.
1371
1372                      List := Attribute.Value.Values;
1373
1374                      if List /= Nil_String then
1375                         Put (Into_List => In_Tree.Config.Run_Path_Option,
1376                              From_List => List,
1377                              In_Tree   => In_Tree);
1378                      end if;
1379
1380                   when Snames.Name_Library_Support =>
1381                      declare
1382                         pragma Unsuppress (All_Checks);
1383                      begin
1384                         In_Tree.Config.Lib_Support :=
1385                           Library_Support'Value (Get_Name_String
1386                                                  (Attribute.Value.Value));
1387                      exception
1388                         when Constraint_Error =>
1389                            Error_Msg
1390                              ("invalid value """ &
1391                               Get_Name_String (Attribute.Value.Value) &
1392                               """ for Library_Support",
1393                               Attribute.Value.Location);
1394                      end;
1395
1396                   when Snames.Name_Shared_Library_Prefix =>
1397                      In_Tree.Config.Shared_Lib_Prefix :=
1398                        File_Name_Type (Attribute.Value.Value);
1399
1400                   when Snames.Name_Shared_Library_Suffix =>
1401                      In_Tree.Config.Shared_Lib_Suffix :=
1402                        File_Name_Type (Attribute.Value.Value);
1403
1404                   when Snames.Name_Symbolic_Link_Supported =>
1405                      declare
1406                         pragma Unsuppress (All_Checks);
1407                      begin
1408                         In_Tree.Config.Symbolic_Link_Supported :=
1409                           Boolean'Value (Get_Name_String
1410                                          (Attribute.Value.Value));
1411                      exception
1412                         when Constraint_Error =>
1413                            Error_Msg
1414                              ("invalid value """ &
1415                               Get_Name_String (Attribute.Value.Value) &
1416                               """ for Symbolic_Link_Supported",
1417                               Attribute.Value.Location);
1418                      end;
1419
1420                   when Snames.Name_Library_Major_Minor_Id_Supported =>
1421                      declare
1422                         pragma Unsuppress (All_Checks);
1423                      begin
1424                         In_Tree.Config.Lib_Maj_Min_Id_Supported :=
1425                           Boolean'Value (Get_Name_String
1426                                          (Attribute.Value.Value));
1427                      exception
1428                         when Constraint_Error =>
1429                            Error_Msg
1430                              ("invalid value """ &
1431                               Get_Name_String (Attribute.Value.Value) &
1432                               """ for Library_Major_Minor_Id_Supported",
1433                               Attribute.Value.Location);
1434                      end;
1435
1436                   when Snames.Name_Library_Auto_Init_Supported =>
1437                      declare
1438                         pragma Unsuppress (All_Checks);
1439                      begin
1440                         In_Tree.Config.Auto_Init_Supported :=
1441                           Boolean'Value (Get_Name_String
1442                                          (Attribute.Value.Value));
1443                      exception
1444                         when Constraint_Error =>
1445                            Error_Msg
1446                              ("invalid value """ &
1447                               Get_Name_String (Attribute.Value.Value) &
1448                               """ for Library_Auto_Init_Supported",
1449                               Attribute.Value.Location);
1450                      end;
1451
1452                   when Snames.Name_Shared_Library_Minimum_Switches =>
1453                      List := Attribute.Value.Values;
1454
1455                      if List /= Nil_String then
1456                         Put (Into_List =>
1457                                In_Tree.Config.Shared_Lib_Min_Options,
1458                              From_List => List,
1459                              In_Tree   => In_Tree);
1460                      end if;
1461
1462                   when Snames.Name_Library_Version_Switches =>
1463                      List := Attribute.Value.Values;
1464
1465                      if List /= Nil_String then
1466                         Put (Into_List =>
1467                                In_Tree.Config.Lib_Version_Options,
1468                              From_List => List,
1469                              In_Tree   => In_Tree);
1470                      end if;
1471
1472                   when others =>
1473                      null;
1474                end case;
1475             end if;
1476
1477             Attribute_Id := Attribute.Next;
1478          end loop;
1479       end Process_Attributes;
1480
1481    begin
1482       Error_Report := Report_Error;
1483       Success := True;
1484
1485       if Reset_Tree then
1486
1487          --  Make sure there are no projects in the data structure
1488
1489          Project_Table.Set_Last (In_Tree.Projects, No_Project);
1490       end if;
1491
1492       Processed_Projects.Reset;
1493
1494       --  And process the main project and all of the projects it depends on,
1495       --  recursively.
1496
1497       Recursive_Process
1498         (Project                => Project,
1499          In_Tree                => In_Tree,
1500          From_Project_Node      => From_Project_Node,
1501          From_Project_Node_Tree => From_Project_Node_Tree,
1502          Extended_By            => No_Project);
1503
1504       if not In_Configuration then
1505
1506          if Project /= No_Project then
1507             Check
1508               (In_Tree, Project, Follow_Links, When_No_Sources);
1509          end if;
1510
1511          --  If main project is an extending all project, set the object
1512          --  directory of all virtual extending projects to the object
1513          --  directory of the main project.
1514
1515          if Project /= No_Project
1516            and then
1517              Is_Extending_All (From_Project_Node, From_Project_Node_Tree)
1518          then
1519             declare
1520                Object_Dir : constant Path_Name_Type :=
1521                               In_Tree.Projects.Table
1522                                 (Project).Object_Directory;
1523             begin
1524                for Index in
1525                  Project_Table.First .. Project_Table.Last (In_Tree.Projects)
1526                loop
1527                   if In_Tree.Projects.Table (Index).Virtual then
1528                      In_Tree.Projects.Table (Index).Object_Directory :=
1529                        Object_Dir;
1530                   end if;
1531                end loop;
1532             end;
1533          end if;
1534
1535          --  Check that no extending project shares its object directory with
1536          --  the project(s) it extends.
1537
1538          if Project /= No_Project then
1539             for Proj in
1540               Project_Table.First .. Project_Table.Last (In_Tree.Projects)
1541             loop
1542                Extending := In_Tree.Projects.Table (Proj).Extended_By;
1543
1544                if Extending /= No_Project then
1545                   Obj_Dir := In_Tree.Projects.Table (Proj).Object_Directory;
1546
1547                   --  Check that a project being extended does not share its
1548                   --  object directory with any project that extends it,
1549                   --  directly or indirectly, including a virtual extending
1550                   --  project.
1551
1552                   --  Start with the project directly extending it
1553
1554                   Extending2 := Extending;
1555                   while Extending2 /= No_Project loop
1556                      if In_Tree.Projects.Table (Extending2).Ada_Sources /=
1557                        Nil_String
1558                        and then
1559                          In_Tree.Projects.Table (Extending2).Object_Directory =
1560                          Obj_Dir
1561                      then
1562                         if In_Tree.Projects.Table (Extending2).Virtual then
1563                            Error_Msg_Name_1 :=
1564                              In_Tree.Projects.Table (Proj).Display_Name;
1565
1566                            if Error_Report = null then
1567                               Error_Msg
1568                                 ("project %% cannot be extended by a virtual" &
1569                                  " project with the same object directory",
1570                                  In_Tree.Projects.Table (Proj).Location);
1571                            else
1572                               Error_Report
1573                                 ("project """ &
1574                                  Get_Name_String (Error_Msg_Name_1) &
1575                                  """ cannot be extended by a virtual " &
1576                                  "project with the same object directory",
1577                                  Project, In_Tree);
1578                            end if;
1579
1580                         else
1581                            Error_Msg_Name_1 :=
1582                              In_Tree.Projects.Table (Extending2).Display_Name;
1583                            Error_Msg_Name_2 :=
1584                              In_Tree.Projects.Table (Proj).Display_Name;
1585
1586                            if Error_Report = null then
1587                               Error_Msg
1588                                 ("project %% cannot extend project %%",
1589                                  In_Tree.Projects.Table (Extending2).Location);
1590                               Error_Msg
1591                                 ("\they share the same object directory",
1592                                  In_Tree.Projects.Table (Extending2).Location);
1593
1594                            else
1595                               Error_Report
1596                                 ("project """ &
1597                                  Get_Name_String (Error_Msg_Name_1) &
1598                                  """ cannot extend project """ &
1599                                  Get_Name_String (Error_Msg_Name_2) & """",
1600                                  Project, In_Tree);
1601                               Error_Report
1602                                 ("they share the same object directory",
1603                                  Project, In_Tree);
1604                            end if;
1605                         end if;
1606                      end if;
1607
1608                      --  Continue with the next extending project, if any
1609
1610                      Extending2 :=
1611                        In_Tree.Projects.Table (Extending2).Extended_By;
1612                   end loop;
1613                end if;
1614             end loop;
1615          end if;
1616
1617          --  Get the global configuration
1618
1619          if Project /= No_Project then
1620
1621             Process_Attributes
1622               (In_Tree.Projects.Table (Project).Decl.Attributes);
1623
1624             --  Loop through packages ???
1625
1626             Packages := In_Tree.Projects.Table (Project).Decl.Packages;
1627             while Packages /= No_Package loop
1628                Element := In_Tree.Packages.Table (Packages);
1629
1630                case Element.Name is
1631                   when Snames.Name_Builder =>
1632
1633                      --  Process attributes of package Builder
1634
1635                      Process_Attributes (Element.Decl.Attributes);
1636
1637                   when Snames.Name_Linker =>
1638
1639                      --  Process attributes of package Linker
1640
1641                      Process_Attributes (Element.Decl.Attributes);
1642
1643                   when others =>
1644                      null;
1645                end case;
1646
1647                Packages := Element.Next;
1648             end loop;
1649          end if;
1650       end if;
1651
1652       Success :=
1653         Total_Errors_Detected = 0
1654           and then
1655             (Warning_Mode /= Treat_As_Error or else Warnings_Detected = 0);
1656    end Process;
1657
1658    -------------------------------
1659    -- Process_Declarative_Items --
1660    -------------------------------
1661
1662    procedure Process_Declarative_Items
1663      (Project                : Project_Id;
1664       In_Tree                : Project_Tree_Ref;
1665       From_Project_Node      : Project_Node_Id;
1666       From_Project_Node_Tree : Project_Node_Tree_Ref;
1667       Pkg                    : Package_Id;
1668       Item                   : Project_Node_Id)
1669    is
1670       Current_Declarative_Item : Project_Node_Id;
1671       Current_Item             : Project_Node_Id;
1672
1673    begin
1674       --  Loop through declarative items
1675
1676       Current_Item := Empty_Node;
1677
1678       Current_Declarative_Item := Item;
1679       while Current_Declarative_Item /= Empty_Node loop
1680
1681          --  Get its data
1682
1683          Current_Item :=
1684            Current_Item_Node
1685              (Current_Declarative_Item, From_Project_Node_Tree);
1686
1687          --  And set Current_Declarative_Item to the next declarative item
1688          --  ready for the next iteration.
1689
1690          Current_Declarative_Item :=
1691            Next_Declarative_Item
1692              (Current_Declarative_Item, From_Project_Node_Tree);
1693
1694          case Kind_Of (Current_Item, From_Project_Node_Tree) is
1695
1696             when N_Package_Declaration =>
1697
1698                --  Do not process a package declaration that should be ignored
1699
1700                if Expression_Kind_Of
1701                     (Current_Item, From_Project_Node_Tree) /= Ignored
1702                then
1703                   --  Create the new package
1704
1705                   Package_Table.Increment_Last (In_Tree.Packages);
1706
1707                   declare
1708                      New_Pkg         : constant Package_Id :=
1709                                          Package_Table.Last (In_Tree.Packages);
1710                      The_New_Package : Package_Element;
1711
1712                      Project_Of_Renamed_Package :
1713                        constant Project_Node_Id :=
1714                          Project_Of_Renamed_Package_Of
1715                            (Current_Item, From_Project_Node_Tree);
1716
1717                   begin
1718                      --  Set the name of the new package
1719
1720                      The_New_Package.Name :=
1721                        Name_Of (Current_Item, From_Project_Node_Tree);
1722
1723                      --  Insert the new package in the appropriate list
1724
1725                      if Pkg /= No_Package then
1726                         The_New_Package.Next :=
1727                           In_Tree.Packages.Table (Pkg).Decl.Packages;
1728                         In_Tree.Packages.Table (Pkg).Decl.Packages :=
1729                           New_Pkg;
1730                      else
1731                         The_New_Package.Next :=
1732                           In_Tree.Projects.Table (Project).Decl.Packages;
1733                         In_Tree.Projects.Table (Project).Decl.Packages :=
1734                           New_Pkg;
1735                      end if;
1736
1737                      In_Tree.Packages.Table (New_Pkg) :=
1738                        The_New_Package;
1739
1740                      if Project_Of_Renamed_Package /= Empty_Node then
1741
1742                         --  Renamed package
1743
1744                         declare
1745                            Project_Name : constant Name_Id :=
1746                                             Name_Of
1747                                               (Project_Of_Renamed_Package,
1748                                                From_Project_Node_Tree);
1749
1750                            Renamed_Project :
1751                              constant Project_Id :=
1752                                Imported_Or_Extended_Project_From
1753                                (Project, In_Tree, Project_Name);
1754
1755                            Renamed_Package : constant Package_Id :=
1756                                                Package_From
1757                                                  (Renamed_Project, In_Tree,
1758                                                   Name_Of
1759                                                     (Current_Item,
1760                                                      From_Project_Node_Tree));
1761
1762                         begin
1763                            --  For a renamed package, copy the declarations of
1764                            --  the renamed package, but set all the locations
1765                            --  to the location of the package name in the
1766                            --  renaming declaration.
1767
1768                            Copy_Package_Declarations
1769                              (From     =>
1770                                 In_Tree.Packages.Table (Renamed_Package).Decl,
1771                               To      =>
1772                                 In_Tree.Packages.Table (New_Pkg).Decl,
1773                               New_Loc =>
1774                                 Location_Of
1775                                   (Current_Item, From_Project_Node_Tree),
1776                               In_Tree => In_Tree);
1777                         end;
1778
1779                      --  Standard package declaration, not renaming
1780
1781                      else
1782                         --  Set the default values of the attributes
1783
1784                         Add_Attributes
1785                           (Project,
1786                            In_Tree.Projects.Table (Project).Name,
1787                            In_Tree,
1788                            In_Tree.Packages.Table (New_Pkg).Decl,
1789                            First_Attribute_Of
1790                              (Package_Id_Of
1791                                 (Current_Item, From_Project_Node_Tree)),
1792                            Project_Level => False);
1793
1794                         --  And process declarative items of the new package
1795
1796                         Process_Declarative_Items
1797                           (Project                => Project,
1798                            In_Tree                => In_Tree,
1799                            From_Project_Node      => From_Project_Node,
1800                            From_Project_Node_Tree => From_Project_Node_Tree,
1801                            Pkg                    => New_Pkg,
1802                            Item                   =>
1803                              First_Declarative_Item_Of
1804                                (Current_Item, From_Project_Node_Tree));
1805                      end if;
1806                   end;
1807                end if;
1808
1809             when N_String_Type_Declaration =>
1810
1811                --  There is nothing to process
1812
1813                null;
1814
1815             when N_Attribute_Declaration      |
1816                  N_Typed_Variable_Declaration |
1817                  N_Variable_Declaration       =>
1818
1819                if Expression_Of (Current_Item, From_Project_Node_Tree) =
1820                     Empty_Node
1821                then
1822
1823                   --  It must be a full associative array attribute declaration
1824
1825                   declare
1826                      Current_Item_Name : constant Name_Id :=
1827                                            Name_Of
1828                                              (Current_Item,
1829                                               From_Project_Node_Tree);
1830                      --  The name of the attribute
1831
1832                      New_Array : Array_Id;
1833                      --  The new associative array created
1834
1835                      Orig_Array : Array_Id;
1836                      --  The associative array value
1837
1838                      Orig_Project_Name : Name_Id := No_Name;
1839                      --  The name of the project where the associative array
1840                      --  value is.
1841
1842                      Orig_Project : Project_Id := No_Project;
1843                      --  The id of the project where the associative array
1844                      --  value is.
1845
1846                      Orig_Package_Name : Name_Id := No_Name;
1847                      --  The name of the package, if any, where the associative
1848                      --  array value is.
1849
1850                      Orig_Package : Package_Id := No_Package;
1851                      --  The id of the package, if any, where the associative
1852                      --  array value is.
1853
1854                      New_Element : Array_Element_Id := No_Array_Element;
1855                      --  Id of a new array element created
1856
1857                      Prev_Element : Array_Element_Id := No_Array_Element;
1858                      --  Last new element id created
1859
1860                      Orig_Element : Array_Element_Id := No_Array_Element;
1861                      --  Current array element in the original associative
1862                      --  array.
1863
1864                      Next_Element : Array_Element_Id := No_Array_Element;
1865                      --  Id of the array element that follows the new element.
1866                      --  This is not always nil, because values for the
1867                      --  associative array attribute may already have been
1868                      --  declared, and the array elements declared are reused.
1869
1870                   begin
1871                      --  First, find if the associative array attribute already
1872                      --  has elements declared.
1873
1874                      if Pkg /= No_Package then
1875                         New_Array := In_Tree.Packages.Table
1876                                        (Pkg).Decl.Arrays;
1877
1878                      else
1879                         New_Array := In_Tree.Projects.Table
1880                                        (Project).Decl.Arrays;
1881                      end if;
1882
1883                      while New_Array /= No_Array
1884                        and then In_Tree.Arrays.Table (New_Array).Name /=
1885                                                            Current_Item_Name
1886                      loop
1887                         New_Array := In_Tree.Arrays.Table (New_Array).Next;
1888                      end loop;
1889
1890                      --  If the attribute has never been declared add new entry
1891                      --  in the arrays of the project/package and link it.
1892
1893                      if New_Array = No_Array then
1894                         Array_Table.Increment_Last (In_Tree.Arrays);
1895                         New_Array := Array_Table.Last (In_Tree.Arrays);
1896
1897                         if Pkg /= No_Package then
1898                            In_Tree.Arrays.Table (New_Array) :=
1899                              (Name  => Current_Item_Name,
1900                               Value => No_Array_Element,
1901                               Next  =>
1902                                 In_Tree.Packages.Table (Pkg).Decl.Arrays);
1903
1904                            In_Tree.Packages.Table (Pkg).Decl.Arrays :=
1905                              New_Array;
1906
1907                         else
1908                            In_Tree.Arrays.Table (New_Array) :=
1909                              (Name  => Current_Item_Name,
1910                               Value => No_Array_Element,
1911                               Next  =>
1912                                 In_Tree.Projects.Table (Project).Decl.Arrays);
1913
1914                            In_Tree.Projects.Table (Project).Decl.Arrays :=
1915                              New_Array;
1916                         end if;
1917                      end if;
1918
1919                      --  Find the project where the value is declared
1920
1921                      Orig_Project_Name :=
1922                        Name_Of
1923                          (Associative_Project_Of
1924                               (Current_Item, From_Project_Node_Tree),
1925                           From_Project_Node_Tree);
1926
1927                      for Index in Project_Table.First ..
1928                                   Project_Table.Last
1929                                     (In_Tree.Projects)
1930                      loop
1931                         if In_Tree.Projects.Table (Index).Name =
1932                                                            Orig_Project_Name
1933                         then
1934                            Orig_Project := Index;
1935                            exit;
1936                         end if;
1937                      end loop;
1938
1939                      pragma Assert (Orig_Project /= No_Project,
1940                                     "original project not found");
1941
1942                      if Associative_Package_Of
1943                           (Current_Item, From_Project_Node_Tree) = Empty_Node
1944                      then
1945                         Orig_Array :=
1946                           In_Tree.Projects.Table
1947                             (Orig_Project).Decl.Arrays;
1948
1949                      else
1950                         --  If in a package, find the package where the
1951                         --  value is declared.
1952
1953                         Orig_Package_Name :=
1954                           Name_Of
1955                             (Associative_Package_Of
1956                                  (Current_Item, From_Project_Node_Tree),
1957                              From_Project_Node_Tree);
1958
1959                         Orig_Package :=
1960                           In_Tree.Projects.Table
1961                             (Orig_Project).Decl.Packages;
1962                         pragma Assert (Orig_Package /= No_Package,
1963                                        "original package not found");
1964
1965                         while In_Tree.Packages.Table
1966                                 (Orig_Package).Name /= Orig_Package_Name
1967                         loop
1968                            Orig_Package := In_Tree.Packages.Table
1969                                              (Orig_Package).Next;
1970                            pragma Assert (Orig_Package /= No_Package,
1971                                           "original package not found");
1972                         end loop;
1973
1974                         Orig_Array :=
1975                           In_Tree.Packages.Table
1976                             (Orig_Package).Decl.Arrays;
1977                      end if;
1978
1979                      --  Now look for the array
1980
1981                      while Orig_Array /= No_Array and then
1982                      In_Tree.Arrays.Table (Orig_Array).Name /=
1983                                                          Current_Item_Name
1984                      loop
1985                         Orig_Array := In_Tree.Arrays.Table
1986                                         (Orig_Array).Next;
1987                      end loop;
1988
1989                      if Orig_Array = No_Array then
1990                         if Error_Report = null then
1991                            Error_Msg
1992                              ("associative array value cannot be found",
1993                               Location_Of
1994                                 (Current_Item, From_Project_Node_Tree));
1995
1996                         else
1997                            Error_Report
1998                              ("associative array value cannot be found",
1999                               Project, In_Tree);
2000                         end if;
2001
2002                      else
2003                         Orig_Element :=
2004                           In_Tree.Arrays.Table (Orig_Array).Value;
2005
2006                         --  Copy each array element
2007
2008                         while Orig_Element /= No_Array_Element loop
2009
2010                            --  Case of first element
2011
2012                            if Prev_Element = No_Array_Element then
2013
2014                               --  And there is no array element declared yet,
2015                               --  create a new first array element.
2016
2017                               if In_Tree.Arrays.Table (New_Array).Value =
2018                                                               No_Array_Element
2019                               then
2020                                  Array_Element_Table.Increment_Last
2021                                    (In_Tree.Array_Elements);
2022                                  New_Element := Array_Element_Table.Last
2023                                    (In_Tree.Array_Elements);
2024                                  In_Tree.Arrays.Table
2025                                    (New_Array).Value := New_Element;
2026                                  Next_Element := No_Array_Element;
2027
2028                               --  Otherwise, the new element is the first
2029
2030                               else
2031                                  New_Element := In_Tree.Arrays.
2032                                                   Table (New_Array).Value;
2033                                  Next_Element :=
2034                                    In_Tree.Array_Elements.Table
2035                                      (New_Element).Next;
2036                               end if;
2037
2038                            --  Otherwise, reuse an existing element, or create
2039                            --  one if necessary.
2040
2041                            else
2042                               Next_Element :=
2043                                 In_Tree.Array_Elements.Table
2044                                   (Prev_Element).Next;
2045
2046                               if Next_Element = No_Array_Element then
2047                                  Array_Element_Table.Increment_Last
2048                                    (In_Tree.Array_Elements);
2049                                  New_Element := Array_Element_Table.Last
2050                                    (In_Tree.Array_Elements);
2051
2052                               else
2053                                  New_Element := Next_Element;
2054                                  Next_Element :=
2055                                    In_Tree.Array_Elements.Table
2056                                      (New_Element).Next;
2057                               end if;
2058                            end if;
2059
2060                            --  Copy the value of the element
2061
2062                            In_Tree.Array_Elements.Table
2063                              (New_Element) :=
2064                                In_Tree.Array_Elements.Table
2065                                  (Orig_Element);
2066                            In_Tree.Array_Elements.Table
2067                              (New_Element).Value.Project := Project;
2068
2069                            --  Adjust the Next link
2070
2071                            In_Tree.Array_Elements.Table
2072                              (New_Element).Next := Next_Element;
2073
2074                            --  Adjust the previous id for the next element
2075
2076                            Prev_Element := New_Element;
2077
2078                            --  Go to the next element in the original array
2079
2080                            Orig_Element :=
2081                              In_Tree.Array_Elements.Table
2082                                (Orig_Element).Next;
2083                         end loop;
2084
2085                         --  Make sure that the array ends here, in case there
2086                         --  previously a greater number of elements.
2087
2088                         In_Tree.Array_Elements.Table
2089                           (New_Element).Next := No_Array_Element;
2090                      end if;
2091                   end;
2092
2093                --  Declarations other that full associative arrays
2094
2095                else
2096                   declare
2097                      New_Value : constant Variable_Value :=
2098                        Expression
2099                          (Project                => Project,
2100                           In_Tree                => In_Tree,
2101                           From_Project_Node      => From_Project_Node,
2102                           From_Project_Node_Tree => From_Project_Node_Tree,
2103                           Pkg                    => Pkg,
2104                           First_Term             =>
2105                             Tree.First_Term
2106                               (Expression_Of
2107                                    (Current_Item, From_Project_Node_Tree),
2108                                From_Project_Node_Tree),
2109                           Kind                   =>
2110                             Expression_Kind_Of
2111                               (Current_Item, From_Project_Node_Tree));
2112                      --  The expression value
2113
2114                      The_Variable : Variable_Id := No_Variable;
2115
2116                      Current_Item_Name : constant Name_Id :=
2117                        Name_Of (Current_Item, From_Project_Node_Tree);
2118
2119                   begin
2120                      --  Process a typed variable declaration
2121
2122                      if Kind_Of (Current_Item, From_Project_Node_Tree) =
2123                           N_Typed_Variable_Declaration
2124                      then
2125                         --  Report an error for an empty string
2126
2127                         if New_Value.Value = Empty_String then
2128                            Error_Msg_Name_1 :=
2129                              Name_Of (Current_Item, From_Project_Node_Tree);
2130
2131                            if Error_Report = null then
2132                               Error_Msg
2133                                 ("no value defined for %%",
2134                                  Location_Of
2135                                    (Current_Item, From_Project_Node_Tree));
2136
2137                            else
2138                               Error_Report
2139                                 ("no value defined for " &
2140                                  Get_Name_String (Error_Msg_Name_1),
2141                                  Project, In_Tree);
2142                            end if;
2143
2144                         else
2145                            declare
2146                               Current_String : Project_Node_Id :=
2147                                                  First_Literal_String
2148                                                    (String_Type_Of
2149                                                       (Current_Item,
2150                                                        From_Project_Node_Tree),
2151                                                     From_Project_Node_Tree);
2152
2153                            begin
2154                               --  Loop through all the valid strings for the
2155                               --  string type and compare to the string value.
2156
2157                               while Current_String /= Empty_Node
2158                                 and then
2159                                   String_Value_Of
2160                                     (Current_String, From_Project_Node_Tree) /=
2161                                                                New_Value.Value
2162                               loop
2163                                  Current_String :=
2164                                    Next_Literal_String
2165                                      (Current_String, From_Project_Node_Tree);
2166                               end loop;
2167
2168                               --  Report an error if the string value is not
2169                               --  one for the string type.
2170
2171                               if Current_String = Empty_Node then
2172                                  Error_Msg_Name_1 := New_Value.Value;
2173                                  Error_Msg_Name_2 :=
2174                                    Name_Of
2175                                      (Current_Item, From_Project_Node_Tree);
2176
2177                                  if Error_Report = null then
2178                                     Error_Msg
2179                                       ("value %% is illegal " &
2180                                        "for typed string %%",
2181                                        Location_Of
2182                                          (Current_Item,
2183                                           From_Project_Node_Tree));
2184
2185                                  else
2186                                     Error_Report
2187                                       ("value """ &
2188                                        Get_Name_String (Error_Msg_Name_1) &
2189                                        """ is illegal for typed string """ &
2190                                        Get_Name_String (Error_Msg_Name_2) &
2191                                        """",
2192                                        Project, In_Tree);
2193                                  end if;
2194                               end if;
2195                            end;
2196                         end if;
2197                      end if;
2198
2199                      if Kind_Of (Current_Item, From_Project_Node_Tree) /=
2200                           N_Attribute_Declaration
2201                        or else
2202                          Associative_Array_Index_Of
2203                            (Current_Item, From_Project_Node_Tree) = No_Name
2204                      then
2205                         --  Case of a variable declaration or of a not
2206                         --  associative array attribute.
2207
2208                         --  First, find the list where to find the variable
2209                         --  or attribute.
2210
2211                         if Kind_Of (Current_Item, From_Project_Node_Tree) =
2212                              N_Attribute_Declaration
2213                         then
2214                            if Pkg /= No_Package then
2215                               The_Variable :=
2216                                 In_Tree.Packages.Table
2217                                   (Pkg).Decl.Attributes;
2218                            else
2219                               The_Variable :=
2220                                 In_Tree.Projects.Table
2221                                   (Project).Decl.Attributes;
2222                            end if;
2223
2224                         else
2225                            if Pkg /= No_Package then
2226                               The_Variable :=
2227                                 In_Tree.Packages.Table
2228                                   (Pkg).Decl.Variables;
2229                            else
2230                               The_Variable :=
2231                                 In_Tree.Projects.Table
2232                                   (Project).Decl.Variables;
2233                            end if;
2234
2235                         end if;
2236
2237                         --  Loop through the list, to find if it has already
2238                         --  been declared.
2239
2240                         while The_Variable /= No_Variable
2241                           and then
2242                             In_Tree.Variable_Elements.Table
2243                               (The_Variable).Name /= Current_Item_Name
2244                         loop
2245                            The_Variable :=
2246                              In_Tree.Variable_Elements.Table
2247                                (The_Variable).Next;
2248                         end loop;
2249
2250                         --  If it has not been declared, create a new entry
2251                         --  in the list.
2252
2253                         if The_Variable = No_Variable then
2254
2255                            --  All single string attribute should already have
2256                            --  been declared with a default empty string value.
2257
2258                            pragma Assert
2259                              (Kind_Of (Current_Item, From_Project_Node_Tree) /=
2260                                 N_Attribute_Declaration,
2261                               "illegal attribute declaration");
2262
2263                            Variable_Element_Table.Increment_Last
2264                              (In_Tree.Variable_Elements);
2265                            The_Variable := Variable_Element_Table.Last
2266                              (In_Tree.Variable_Elements);
2267
2268                            --  Put the new variable in the appropriate list
2269
2270                            if Pkg /= No_Package then
2271                               In_Tree.Variable_Elements.Table (The_Variable) :=
2272                                 (Next    =>
2273                                    In_Tree.Packages.Table
2274                                      (Pkg).Decl.Variables,
2275                                  Name    => Current_Item_Name,
2276                                  Value   => New_Value);
2277                               In_Tree.Packages.Table
2278                                 (Pkg).Decl.Variables := The_Variable;
2279
2280                            else
2281                               In_Tree.Variable_Elements.Table (The_Variable) :=
2282                                 (Next    =>
2283                                    In_Tree.Projects.Table
2284                                      (Project).Decl.Variables,
2285                                  Name    => Current_Item_Name,
2286                                  Value   => New_Value);
2287                               In_Tree.Projects.Table
2288                                 (Project).Decl.Variables :=
2289                                   The_Variable;
2290                            end if;
2291
2292                         --  If the variable/attribute has already been
2293                         --  declared, just change the value.
2294
2295                         else
2296                            In_Tree.Variable_Elements.Table
2297                              (The_Variable).Value :=
2298                                 New_Value;
2299
2300                         end if;
2301
2302                      else
2303                         --  Associative array attribute
2304
2305                         --  Get the string index
2306
2307                         Get_Name_String
2308                           (Associative_Array_Index_Of
2309                              (Current_Item, From_Project_Node_Tree));
2310
2311                         --  Put in lower case, if necessary
2312
2313                         if Case_Insensitive
2314                              (Current_Item, From_Project_Node_Tree)
2315                         then
2316                            GNAT.Case_Util.To_Lower
2317                                             (Name_Buffer (1 .. Name_Len));
2318                         end if;
2319
2320                         declare
2321                            The_Array : Array_Id;
2322
2323                            The_Array_Element : Array_Element_Id :=
2324                                                  No_Array_Element;
2325
2326                            Index_Name : constant Name_Id := Name_Find;
2327                            --  The name id of the index
2328
2329                         begin
2330                            --  Look for the array in the appropriate list
2331
2332                            if Pkg /= No_Package then
2333                               The_Array := In_Tree.Packages.Table
2334                                              (Pkg).Decl.Arrays;
2335
2336                            else
2337                               The_Array := In_Tree.Projects.Table
2338                                              (Project).Decl.Arrays;
2339                            end if;
2340
2341                            while
2342                              The_Array /= No_Array
2343                              and then In_Tree.Arrays.Table
2344                                         (The_Array).Name /= Current_Item_Name
2345                            loop
2346                               The_Array := In_Tree.Arrays.Table
2347                                              (The_Array).Next;
2348                            end loop;
2349
2350                            --  If the array cannot be found, create a new
2351                            --  entry in the list. As The_Array_Element is
2352                            --  initialized to No_Array_Element, a new element
2353                            --  will be created automatically later.
2354
2355                            if The_Array = No_Array then
2356                               Array_Table.Increment_Last
2357                                 (In_Tree.Arrays);
2358                               The_Array := Array_Table.Last
2359                                 (In_Tree.Arrays);
2360
2361                               if Pkg /= No_Package then
2362                                  In_Tree.Arrays.Table
2363                                    (The_Array) :=
2364                                    (Name  => Current_Item_Name,
2365                                     Value => No_Array_Element,
2366                                     Next  =>
2367                                       In_Tree.Packages.Table
2368                                         (Pkg).Decl.Arrays);
2369
2370                                  In_Tree.Packages.Table
2371                                    (Pkg).Decl.Arrays :=
2372                                      The_Array;
2373
2374                               else
2375                                  In_Tree.Arrays.Table
2376                                    (The_Array) :=
2377                                    (Name  => Current_Item_Name,
2378                                     Value => No_Array_Element,
2379                                     Next  =>
2380                                       In_Tree.Projects.Table
2381                                         (Project).Decl.Arrays);
2382
2383                                  In_Tree.Projects.Table
2384                                    (Project).Decl.Arrays :=
2385                                      The_Array;
2386                               end if;
2387
2388                            --  Otherwise, initialize The_Array_Element as the
2389                            --  head of the element list.
2390
2391                            else
2392                               The_Array_Element :=
2393                                 In_Tree.Arrays.Table
2394                                   (The_Array).Value;
2395                            end if;
2396
2397                            --  Look in the list, if any, to find an element
2398                            --  with the same index.
2399
2400                            while The_Array_Element /= No_Array_Element
2401                              and then
2402                                In_Tree.Array_Elements.Table
2403                                  (The_Array_Element).Index /= Index_Name
2404                            loop
2405                               The_Array_Element :=
2406                                 In_Tree.Array_Elements.Table
2407                                   (The_Array_Element).Next;
2408                            end loop;
2409
2410                            --  If no such element were found, create a new
2411                            --  one and insert it in the element list, with
2412                            --  the propoer value.
2413
2414                            if The_Array_Element = No_Array_Element then
2415                               Array_Element_Table.Increment_Last
2416                                 (In_Tree.Array_Elements);
2417                               The_Array_Element := Array_Element_Table.Last
2418                                 (In_Tree.Array_Elements);
2419
2420                               In_Tree.Array_Elements.Table
2421                                 (The_Array_Element) :=
2422                                 (Index  => Index_Name,
2423                                  Src_Index =>
2424                                    Source_Index_Of
2425                                      (Current_Item, From_Project_Node_Tree),
2426                                  Index_Case_Sensitive =>
2427                                  not Case_Insensitive
2428                                    (Current_Item, From_Project_Node_Tree),
2429                                  Value  => New_Value,
2430                                  Next => In_Tree.Arrays.Table
2431                                            (The_Array).Value);
2432                               In_Tree.Arrays.Table
2433                                 (The_Array).Value := The_Array_Element;
2434
2435                            --  An element with the same index already exists,
2436                            --  just replace its value with the new one.
2437
2438                            else
2439                               In_Tree.Array_Elements.Table
2440                                 (The_Array_Element).Value := New_Value;
2441                            end if;
2442                         end;
2443                      end if;
2444                   end;
2445                end if;
2446
2447             when N_Case_Construction =>
2448                declare
2449                   The_Project   : Project_Id      := Project;
2450                   --  The id of the project of the case variable
2451
2452                   The_Package   : Package_Id      := Pkg;
2453                   --  The id of the package, if any, of the case variable
2454
2455                   The_Variable  : Variable_Value  := Nil_Variable_Value;
2456                   --  The case variable
2457
2458                   Case_Value    : Name_Id         := No_Name;
2459                   --  The case variable value
2460
2461                   Case_Item     : Project_Node_Id := Empty_Node;
2462                   Choice_String : Project_Node_Id := Empty_Node;
2463                   Decl_Item     : Project_Node_Id := Empty_Node;
2464
2465                begin
2466                   declare
2467                      Variable_Node : constant Project_Node_Id :=
2468                                        Case_Variable_Reference_Of
2469                                          (Current_Item,
2470                                           From_Project_Node_Tree);
2471
2472                      Var_Id : Variable_Id := No_Variable;
2473                      Name   : Name_Id     := No_Name;
2474
2475                   begin
2476                      --  If a project were specified for the case variable,
2477                      --  get its id.
2478
2479                      if Project_Node_Of
2480                        (Variable_Node, From_Project_Node_Tree) /= Empty_Node
2481                      then
2482                         Name :=
2483                           Name_Of
2484                             (Project_Node_Of
2485                                (Variable_Node, From_Project_Node_Tree),
2486                              From_Project_Node_Tree);
2487                         The_Project :=
2488                           Imported_Or_Extended_Project_From
2489                             (Project, In_Tree, Name);
2490                      end if;
2491
2492                      --  If a package were specified for the case variable,
2493                      --  get its id.
2494
2495                      if Package_Node_Of
2496                        (Variable_Node, From_Project_Node_Tree) /= Empty_Node
2497                      then
2498                         Name :=
2499                           Name_Of
2500                             (Package_Node_Of
2501                                (Variable_Node, From_Project_Node_Tree),
2502                              From_Project_Node_Tree);
2503                         The_Package :=
2504                           Package_From (The_Project, In_Tree, Name);
2505                      end if;
2506
2507                      Name := Name_Of (Variable_Node, From_Project_Node_Tree);
2508
2509                      --  First, look for the case variable into the package,
2510                      --  if any.
2511
2512                      if The_Package /= No_Package then
2513                         Var_Id := In_Tree.Packages.Table
2514                                     (The_Package).Decl.Variables;
2515                         Name :=
2516                           Name_Of (Variable_Node, From_Project_Node_Tree);
2517                         while Var_Id /= No_Variable
2518                           and then
2519                             In_Tree.Variable_Elements.Table
2520                               (Var_Id).Name /= Name
2521                         loop
2522                            Var_Id := In_Tree.Variable_Elements.
2523                                        Table (Var_Id).Next;
2524                         end loop;
2525                      end if;
2526
2527                      --  If not found in the package, or if there is no
2528                      --  package, look at the project level.
2529
2530                      if Var_Id = No_Variable
2531                         and then
2532                         Package_Node_Of
2533                           (Variable_Node, From_Project_Node_Tree) = Empty_Node
2534                      then
2535                         Var_Id := In_Tree.Projects.Table
2536                                     (The_Project).Decl.Variables;
2537                         while Var_Id /= No_Variable
2538                           and then
2539                             In_Tree.Variable_Elements.Table
2540                               (Var_Id).Name /= Name
2541                         loop
2542                            Var_Id := In_Tree.Variable_Elements.
2543                                        Table (Var_Id).Next;
2544                         end loop;
2545                      end if;
2546
2547                      if Var_Id = No_Variable then
2548
2549                         --  Should never happen, because this has already been
2550                         --  checked during parsing.
2551
2552                         Write_Line ("variable """ &
2553                                     Get_Name_String (Name) &
2554                                     """ not found");
2555                         raise Program_Error;
2556                      end if;
2557
2558                      --  Get the case variable
2559
2560                      The_Variable := In_Tree.Variable_Elements.
2561                                        Table (Var_Id).Value;
2562
2563                      if The_Variable.Kind /= Single then
2564
2565                         --  Should never happen, because this has already been
2566                         --  checked during parsing.
2567
2568                         Write_Line ("variable""" &
2569                                     Get_Name_String (Name) &
2570                                     """ is not a single string variable");
2571                         raise Program_Error;
2572                      end if;
2573
2574                      --  Get the case variable value
2575                      Case_Value := The_Variable.Value;
2576                   end;
2577
2578                   --  Now look into all the case items of the case construction
2579
2580                   Case_Item :=
2581                     First_Case_Item_Of (Current_Item, From_Project_Node_Tree);
2582                   Case_Item_Loop :
2583                      while Case_Item /= Empty_Node loop
2584                         Choice_String :=
2585                           First_Choice_Of (Case_Item, From_Project_Node_Tree);
2586
2587                         --  When Choice_String is nil, it means that it is
2588                         --  the "when others =>" alternative.
2589
2590                         if Choice_String = Empty_Node then
2591                            Decl_Item :=
2592                              First_Declarative_Item_Of
2593                                (Case_Item, From_Project_Node_Tree);
2594                            exit Case_Item_Loop;
2595                         end if;
2596
2597                         --  Look into all the alternative of this case item
2598
2599                         Choice_Loop :
2600                            while Choice_String /= Empty_Node loop
2601                               if Case_Value =
2602                                 String_Value_Of
2603                                   (Choice_String, From_Project_Node_Tree)
2604                               then
2605                                  Decl_Item :=
2606                                    First_Declarative_Item_Of
2607                                      (Case_Item, From_Project_Node_Tree);
2608                                  exit Case_Item_Loop;
2609                               end if;
2610
2611                               Choice_String :=
2612                                 Next_Literal_String
2613                                   (Choice_String, From_Project_Node_Tree);
2614                            end loop Choice_Loop;
2615
2616                         Case_Item :=
2617                           Next_Case_Item (Case_Item, From_Project_Node_Tree);
2618                      end loop Case_Item_Loop;
2619
2620                   --  If there is an alternative, then we process it
2621
2622                   if Decl_Item /= Empty_Node then
2623                      Process_Declarative_Items
2624                        (Project                => Project,
2625                         In_Tree                => In_Tree,
2626                         From_Project_Node      => From_Project_Node,
2627                         From_Project_Node_Tree => From_Project_Node_Tree,
2628                         Pkg                    => Pkg,
2629                         Item                   => Decl_Item);
2630                   end if;
2631                end;
2632
2633             when others =>
2634
2635                --  Should never happen
2636
2637                Write_Line ("Illegal declarative item: " &
2638                            Project_Node_Kind'Image
2639                              (Kind_Of
2640                                 (Current_Item, From_Project_Node_Tree)));
2641                raise Program_Error;
2642          end case;
2643       end loop;
2644    end Process_Declarative_Items;
2645
2646    ---------------------
2647    -- Recursive_Check --
2648    ---------------------
2649
2650    procedure Recursive_Check
2651      (Project         : Project_Id;
2652       In_Tree         : Project_Tree_Ref;
2653       Follow_Links    : Boolean;
2654       When_No_Sources : Error_Warning)
2655    is
2656       Data                  : Project_Data;
2657       Imported_Project_List : Project_List := Empty_Project_List;
2658
2659    begin
2660       --  Do nothing if Project is No_Project, or Project has already
2661       --  been marked as checked.
2662
2663       if Project /= No_Project
2664         and then not In_Tree.Projects.Table (Project).Checked
2665       then
2666          --  Mark project as checked, to avoid infinite recursion in
2667          --  ill-formed trees, where a project imports itself.
2668
2669          In_Tree.Projects.Table (Project).Checked := True;
2670
2671          Data := In_Tree.Projects.Table (Project);
2672
2673          --  Call itself for a possible extended project.
2674          --  (if there is no extended project, then nothing happens).
2675
2676          Recursive_Check
2677            (Data.Extends, In_Tree, Follow_Links, When_No_Sources);
2678
2679          --  Call itself for all imported projects
2680
2681          Imported_Project_List := Data.Imported_Projects;
2682          while Imported_Project_List /= Empty_Project_List loop
2683             Recursive_Check
2684               (In_Tree.Project_Lists.Table
2685                  (Imported_Project_List).Project,
2686                In_Tree, Follow_Links, When_No_Sources);
2687             Imported_Project_List :=
2688               In_Tree.Project_Lists.Table
2689                 (Imported_Project_List).Next;
2690          end loop;
2691
2692          if Verbose_Mode then
2693             Write_Str ("Checking project file """);
2694             Write_Str (Get_Name_String (Data.Name));
2695             Write_Line ("""");
2696          end if;
2697
2698          Prj.Nmsc.Check
2699            (Project, In_Tree, Error_Report, Follow_Links, When_No_Sources);
2700       end if;
2701    end Recursive_Check;
2702
2703    -----------------------
2704    -- Recursive_Process --
2705    -----------------------
2706
2707    procedure Recursive_Process
2708      (In_Tree                : Project_Tree_Ref;
2709       Project                : out Project_Id;
2710       From_Project_Node      : Project_Node_Id;
2711       From_Project_Node_Tree : Project_Node_Tree_Ref;
2712       Extended_By            : Project_Id)
2713    is
2714       With_Clause : Project_Node_Id;
2715
2716    begin
2717       if From_Project_Node = Empty_Node then
2718          Project := No_Project;
2719
2720       else
2721          declare
2722             Processed_Data   : Project_Data     := Empty_Project (In_Tree);
2723             Imported         : Project_List     := Empty_Project_List;
2724             Declaration_Node : Project_Node_Id  := Empty_Node;
2725             Tref             : Source_Buffer_Ptr;
2726             Name             : constant Name_Id :=
2727                                  Name_Of
2728                                    (From_Project_Node, From_Project_Node_Tree);
2729             Location         : Source_Ptr :=
2730                                  Location_Of
2731                                    (From_Project_Node, From_Project_Node_Tree);
2732
2733          begin
2734             Project := Processed_Projects.Get (Name);
2735
2736             if Project /= No_Project then
2737
2738                --  Make sure that, when a project is extended, the project id
2739                --  of the project extending it is recorded in its data, even
2740                --  when it has already been processed as an imported project.
2741                --  This is for virtually extended projects.
2742
2743                if Extended_By /= No_Project then
2744                   In_Tree.Projects.Table (Project).Extended_By := Extended_By;
2745                end if;
2746
2747                return;
2748             end if;
2749
2750             Project_Table.Increment_Last (In_Tree.Projects);
2751             Project := Project_Table.Last (In_Tree.Projects);
2752             Processed_Projects.Set (Name, Project);
2753
2754             Processed_Data.Name := Name;
2755
2756             Get_Name_String (Name);
2757
2758             --  If name starts with the virtual prefix, flag the project as
2759             --  being a virtual extending project.
2760
2761             if Name_Len > Virtual_Prefix'Length
2762               and then Name_Buffer (1 .. Virtual_Prefix'Length) =
2763                          Virtual_Prefix
2764             then
2765                Processed_Data.Virtual := True;
2766                Processed_Data.Display_Name := Name;
2767
2768             --  If there is no file, for example when the project node tree is
2769             --  built in memory by GPS, the Display_Name cannot be found in
2770             --  the source, so its value is the same as Name.
2771
2772             elsif Location = No_Location then
2773                Processed_Data.Display_Name := Name;
2774
2775             --  Get the spelling of the project name from the project file
2776
2777             else
2778                Tref := Source_Text (Get_Source_File_Index (Location));
2779
2780                for J in 1 .. Name_Len loop
2781                   Name_Buffer (J) := Tref (Location);
2782                   Location := Location + 1;
2783                end loop;
2784
2785                Processed_Data.Display_Name := Name_Find;
2786             end if;
2787
2788             Processed_Data.Display_Path_Name :=
2789               Path_Name_Of (From_Project_Node, From_Project_Node_Tree);
2790             Get_Name_String (Processed_Data.Display_Path_Name);
2791             Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2792             Processed_Data.Path_Name := Name_Find;
2793
2794             Processed_Data.Location :=
2795               Location_Of (From_Project_Node, From_Project_Node_Tree);
2796
2797             Processed_Data.Display_Directory :=
2798               Directory_Of (From_Project_Node, From_Project_Node_Tree);
2799             Get_Name_String (Processed_Data.Display_Directory);
2800             Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2801             Processed_Data.Directory := Name_Find;
2802
2803             Processed_Data.Extended_By := Extended_By;
2804
2805             Add_Attributes
2806               (Project,
2807                Name,
2808                In_Tree,
2809                Processed_Data.Decl,
2810                Prj.Attr.Attribute_First,
2811                Project_Level => True);
2812
2813             With_Clause :=
2814               First_With_Clause_Of (From_Project_Node, From_Project_Node_Tree);
2815             while With_Clause /= Empty_Node loop
2816                declare
2817                   New_Project : Project_Id;
2818                   New_Data    : Project_Data;
2819
2820                begin
2821                   Recursive_Process
2822                     (In_Tree                => In_Tree,
2823                      Project                => New_Project,
2824                      From_Project_Node      =>
2825                        Project_Node_Of (With_Clause, From_Project_Node_Tree),
2826                      From_Project_Node_Tree => From_Project_Node_Tree,
2827                      Extended_By            => No_Project);
2828                   New_Data :=
2829                     In_Tree.Projects.Table (New_Project);
2830
2831                   --  If we were the first project to import it,
2832                   --  set First_Referred_By to us.
2833
2834                   if New_Data.First_Referred_By = No_Project then
2835                      New_Data.First_Referred_By := Project;
2836                      In_Tree.Projects.Table (New_Project) :=
2837                        New_Data;
2838                   end if;
2839
2840                   --  Add this project to our list of imported projects
2841
2842                   Project_List_Table.Increment_Last
2843                     (In_Tree.Project_Lists);
2844                   In_Tree.Project_Lists.Table
2845                     (Project_List_Table.Last
2846                        (In_Tree.Project_Lists)) :=
2847                     (Project => New_Project, Next => Empty_Project_List);
2848
2849                   --  Imported is the id of the last imported project.
2850                   --  If it is nil, then this imported project is our first.
2851
2852                   if Imported = Empty_Project_List then
2853                      Processed_Data.Imported_Projects :=
2854                        Project_List_Table.Last
2855                          (In_Tree.Project_Lists);
2856
2857                   else
2858                      In_Tree.Project_Lists.Table
2859                        (Imported).Next := Project_List_Table.Last
2860                           (In_Tree.Project_Lists);
2861                   end if;
2862
2863                   Imported := Project_List_Table.Last
2864                                 (In_Tree.Project_Lists);
2865
2866                   With_Clause :=
2867                     Next_With_Clause_Of (With_Clause, From_Project_Node_Tree);
2868                end;
2869             end loop;
2870
2871             Declaration_Node :=
2872               Project_Declaration_Of
2873                 (From_Project_Node, From_Project_Node_Tree);
2874
2875             Recursive_Process
2876               (In_Tree                => In_Tree,
2877                Project                => Processed_Data.Extends,
2878                From_Project_Node      =>
2879                  Extended_Project_Of
2880                    (Declaration_Node, From_Project_Node_Tree),
2881                From_Project_Node_Tree => From_Project_Node_Tree,
2882                Extended_By            => Project);
2883
2884             In_Tree.Projects.Table (Project) := Processed_Data;
2885
2886             Process_Declarative_Items
2887               (Project                => Project,
2888                In_Tree                => In_Tree,
2889                From_Project_Node      => From_Project_Node,
2890                From_Project_Node_Tree => From_Project_Node_Tree,
2891                Pkg                    => No_Package,
2892                Item                   =>
2893                  First_Declarative_Item_Of
2894                    (Declaration_Node, From_Project_Node_Tree));
2895
2896             --  If it is an extending project, inherit all packages
2897             --  from the extended project that are not explicitely defined
2898             --  or renamed. Also inherit the languages, if attribute Languages
2899             --  is not explicitely defined.
2900
2901             if Processed_Data.Extends /= No_Project then
2902                Processed_Data := In_Tree.Projects.Table (Project);
2903
2904                declare
2905                   Extended_Pkg : Package_Id :=
2906                                    In_Tree.Projects.Table
2907                                      (Processed_Data.Extends).Decl.Packages;
2908                   Current_Pkg : Package_Id;
2909                   Element     : Package_Element;
2910                   First       : constant Package_Id :=
2911                                   Processed_Data.Decl.Packages;
2912                   Attribute1  : Variable_Id;
2913                   Attribute2  : Variable_Id;
2914                   Attr_Value1 : Variable;
2915                   Attr_Value2  : Variable;
2916
2917                begin
2918                   while Extended_Pkg /= No_Package loop
2919                      Element :=
2920                        In_Tree.Packages.Table (Extended_Pkg);
2921
2922                      Current_Pkg := First;
2923
2924                      loop
2925                         exit when Current_Pkg = No_Package
2926                           or else In_Tree.Packages.Table
2927                                     (Current_Pkg).Name = Element.Name;
2928                         Current_Pkg := In_Tree.Packages.Table
2929                                          (Current_Pkg).Next;
2930                      end loop;
2931
2932                      if Current_Pkg = No_Package then
2933                         Package_Table.Increment_Last
2934                           (In_Tree.Packages);
2935                         Current_Pkg := Package_Table.Last
2936                           (In_Tree.Packages);
2937                         In_Tree.Packages.Table (Current_Pkg) :=
2938                           (Name   => Element.Name,
2939                            Decl   => Element.Decl,
2940                            Parent => No_Package,
2941                            Next   => Processed_Data.Decl.Packages);
2942                         Processed_Data.Decl.Packages := Current_Pkg;
2943                      end if;
2944
2945                      Extended_Pkg := Element.Next;
2946                   end loop;
2947
2948                   --  Check if attribute Languages is declared in the
2949                   --  extending project.
2950
2951                   Attribute1 := Processed_Data.Decl.Attributes;
2952                   while Attribute1 /= No_Variable loop
2953                      Attr_Value1 := In_Tree.Variable_Elements.
2954                                       Table (Attribute1);
2955                      exit when Attr_Value1.Name = Snames.Name_Languages;
2956                      Attribute1 := Attr_Value1.Next;
2957                   end loop;
2958
2959                   if Attribute1 = No_Variable or else
2960                      Attr_Value1.Value.Default
2961                   then
2962                      --  Attribute Languages is not declared in the extending
2963                      --  project. Check if it is declared in the project being
2964                      --  extended.
2965
2966                      Attribute2 :=
2967                        In_Tree.Projects.Table
2968                          (Processed_Data.Extends).Decl.Attributes;
2969
2970                      while Attribute2 /= No_Variable loop
2971                         Attr_Value2 := In_Tree.Variable_Elements.
2972                                          Table (Attribute2);
2973                         exit when Attr_Value2.Name = Snames.Name_Languages;
2974                         Attribute2 := Attr_Value2.Next;
2975                      end loop;
2976
2977                      if Attribute2 /= No_Variable and then
2978                         not Attr_Value2.Value.Default
2979                      then
2980                         --  As attribute Languages is declared in the project
2981                         --  being extended, copy its value for the extending
2982                         --  project.
2983
2984                         if Attribute1 = No_Variable then
2985                            Variable_Element_Table.Increment_Last
2986                              (In_Tree.Variable_Elements);
2987                            Attribute1 := Variable_Element_Table.Last
2988                              (In_Tree.Variable_Elements);
2989                            Attr_Value1.Next := Processed_Data.Decl.Attributes;
2990                            Processed_Data.Decl.Attributes := Attribute1;
2991                         end if;
2992
2993                         Attr_Value1.Name := Snames.Name_Languages;
2994                         Attr_Value1.Value := Attr_Value2.Value;
2995                         In_Tree.Variable_Elements.Table
2996                           (Attribute1) := Attr_Value1;
2997                      end if;
2998                   end if;
2999                end;
3000
3001                In_Tree.Projects.Table (Project) := Processed_Data;
3002             end if;
3003          end;
3004       end if;
3005    end Recursive_Process;
3006
3007 end Prj.Proc;