1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2009, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Err_Vars; use Err_Vars;
27 with Prj.Attr; use Prj.Attr;
28 with Prj.Err; use Prj.Err;
31 with Uintp; use Uintp;
33 package body Prj.Strt is
35 Buffer : String_Access;
36 Buffer_Last : Natural := 0;
38 type Choice_String is record
40 Already_Used : Boolean := False;
42 -- The string of a case label, and an indication that it has already
43 -- been used (to avoid duplicate case labels).
45 Choices_Initial : constant := 10;
46 Choices_Increment : constant := 100;
47 -- These should be in alloc.ads
49 Choice_Node_Low_Bound : constant := 0;
50 Choice_Node_High_Bound : constant := 099_999_999;
51 -- In practice, infinite
53 type Choice_Node_Id is
54 range Choice_Node_Low_Bound .. Choice_Node_High_Bound;
56 First_Choice_Node_Id : constant Choice_Node_Id :=
57 Choice_Node_Low_Bound;
61 (Table_Component_Type => Choice_String,
62 Table_Index_Type => Choice_Node_Id'Base,
63 Table_Low_Bound => First_Choice_Node_Id,
64 Table_Initial => Choices_Initial,
65 Table_Increment => Choices_Increment,
66 Table_Name => "Prj.Strt.Choices");
67 -- Used to store the case labels and check that there is no duplicate
69 package Choice_Lasts is
71 (Table_Component_Type => Choice_Node_Id,
72 Table_Index_Type => Nat,
75 Table_Increment => 100,
76 Table_Name => "Prj.Strt.Choice_Lasts");
77 -- Used to store the indices of the choices in table Choices,
78 -- to distinguish nested case constructions.
80 Choice_First : Choice_Node_Id := 0;
81 -- Index in table Choices of the first case label of the current
82 -- case construction. Zero means no current case construction.
84 type Name_Location is record
85 Name : Name_Id := No_Name;
86 Location : Source_Ptr := No_Location;
88 -- Store the identifier and the location of a simple name
92 (Table_Component_Type => Name_Location,
93 Table_Index_Type => Nat,
96 Table_Increment => 100,
97 Table_Name => "Prj.Strt.Names");
98 -- Used to accumulate the single names of a name
100 procedure Add (This_String : Name_Id);
101 -- Add a string to the case label list, indicating that it has not
104 procedure Add_To_Names (NL : Name_Location);
105 -- Add one single names to table Names
107 procedure External_Reference
108 (In_Tree : Project_Node_Tree_Ref;
109 Current_Project : Project_Node_Id;
110 Current_Package : Project_Node_Id;
111 External_Value : out Project_Node_Id;
112 Flags : Processing_Flags);
113 -- Parse an external reference. Current token is "external"
115 procedure Attribute_Reference
116 (In_Tree : Project_Node_Tree_Ref;
117 Reference : out Project_Node_Id;
118 First_Attribute : Attribute_Node_Id;
119 Current_Project : Project_Node_Id;
120 Current_Package : Project_Node_Id;
121 Flags : Processing_Flags);
122 -- Parse an attribute reference. Current token is an apostrophe
125 (In_Tree : Project_Node_Tree_Ref;
126 Term : out Project_Node_Id;
127 Expr_Kind : in out Variable_Kind;
128 Current_Project : Project_Node_Id;
129 Current_Package : Project_Node_Id;
130 Optional_Index : Boolean;
131 Flags : Processing_Flags);
132 -- Recursive procedure to parse one term or several terms concatenated
139 procedure Add (This_String : Name_Id) is
141 Choices.Increment_Last;
142 Choices.Table (Choices.Last) :=
143 (The_String => This_String,
144 Already_Used => False);
151 procedure Add_To_Names (NL : Name_Location) is
153 Names.Increment_Last;
154 Names.Table (Names.Last) := NL;
157 -------------------------
158 -- Attribute_Reference --
159 -------------------------
161 procedure Attribute_Reference
162 (In_Tree : Project_Node_Tree_Ref;
163 Reference : out Project_Node_Id;
164 First_Attribute : Attribute_Node_Id;
165 Current_Project : Project_Node_Id;
166 Current_Package : Project_Node_Id;
167 Flags : Processing_Flags)
169 Current_Attribute : Attribute_Node_Id := First_Attribute;
172 -- Declare the node of the attribute reference
176 (Of_Kind => N_Attribute_Reference, In_Tree => In_Tree);
177 Set_Location_Of (Reference, In_Tree, To => Token_Ptr);
178 Scan (In_Tree); -- past apostrophe
180 -- Body may be an attribute name
182 if Token = Tok_Body then
183 Token := Tok_Identifier;
184 Token_Name := Snames.Name_Body;
187 Expect (Tok_Identifier, "identifier");
189 if Token = Tok_Identifier then
190 Set_Name_Of (Reference, In_Tree, To => Token_Name);
192 -- Check if the identifier is one of the attribute identifiers in the
193 -- context (package or project level attributes).
196 Attribute_Node_Id_Of (Token_Name, Starting_At => First_Attribute);
198 -- If the identifier is not allowed, report an error
200 if Current_Attribute = Empty_Attribute then
201 Error_Msg_Name_1 := Token_Name;
202 Error_Msg (Flags, "unknown attribute %%", Token_Ptr);
203 Reference := Empty_Node;
205 -- Scan past the attribute name
210 -- Give its characteristics to this attribute reference
212 Set_Project_Node_Of (Reference, In_Tree, To => Current_Project);
213 Set_Package_Node_Of (Reference, In_Tree, To => Current_Package);
214 Set_Expression_Kind_Of
215 (Reference, In_Tree, To => Variable_Kind_Of (Current_Attribute));
218 To => Attribute_Kind_Of (Current_Attribute) in
219 Case_Insensitive_Associative_Array ..
220 Optional_Index_Case_Insensitive_Associative_Array);
222 -- Scan past the attribute name
226 -- If the attribute is an associative array, get the index
228 if Attribute_Kind_Of (Current_Attribute) /= Single then
229 Expect (Tok_Left_Paren, "`(`");
231 if Token = Tok_Left_Paren then
233 Expect (Tok_String_Literal, "literal string");
235 if Token = Tok_String_Literal then
236 Set_Associative_Array_Index_Of
237 (Reference, In_Tree, To => Token_Name);
239 Expect (Tok_Right_Paren, "`)`");
241 if Token = Tok_Right_Paren then
249 -- Change name of obsolete attributes
251 if Present (Reference) then
252 case Name_Of (Reference, In_Tree) is
253 when Snames.Name_Specification =>
254 Set_Name_Of (Reference, In_Tree, To => Snames.Name_Spec);
256 when Snames.Name_Specification_Suffix =>
258 (Reference, In_Tree, To => Snames.Name_Spec_Suffix);
260 when Snames.Name_Implementation =>
261 Set_Name_Of (Reference, In_Tree, To => Snames.Name_Body);
263 when Snames.Name_Implementation_Suffix =>
265 (Reference, In_Tree, To => Snames.Name_Body_Suffix);
272 end Attribute_Reference;
274 ---------------------------
275 -- End_Case_Construction --
276 ---------------------------
278 procedure End_Case_Construction
279 (Check_All_Labels : Boolean;
280 Case_Location : Source_Ptr;
281 Flags : Processing_Flags)
283 Non_Used : Natural := 0;
284 First_Non_Used : Choice_Node_Id := First_Choice_Node_Id;
286 -- First, if Check_All_Labels is True, check if all values
287 -- of the string type have been used.
289 if Check_All_Labels then
290 for Choice in Choice_First .. Choices.Last loop
291 if not Choices.Table (Choice).Already_Used then
292 Non_Used := Non_Used + 1;
295 First_Non_Used := Choice;
300 -- If only one is not used, report a single warning for this value
303 Error_Msg_Name_1 := Choices.Table (First_Non_Used).The_String;
304 Error_Msg (Flags, "?value %% is not used as label", Case_Location);
306 -- If several are not used, report a warning for each one of them
308 elsif Non_Used > 1 then
310 (Flags, "?the following values are not used as labels:",
313 for Choice in First_Non_Used .. Choices.Last loop
314 if not Choices.Table (Choice).Already_Used then
315 Error_Msg_Name_1 := Choices.Table (Choice).The_String;
316 Error_Msg (Flags, "\?%%", Case_Location);
322 -- If this is the only case construction, empty the tables
324 if Choice_Lasts.Last = 1 then
325 Choice_Lasts.Set_Last (0);
326 Choices.Set_Last (First_Choice_Node_Id);
329 elsif Choice_Lasts.Last = 2 then
331 -- This is the second case construction, set the tables to the first
333 Choice_Lasts.Set_Last (1);
334 Choices.Set_Last (Choice_Lasts.Table (1));
338 -- This is the 3rd or more case construction, set the tables to the
341 Choice_Lasts.Decrement_Last;
342 Choices.Set_Last (Choice_Lasts.Table (Choice_Lasts.Last));
343 Choice_First := Choice_Lasts.Table (Choice_Lasts.Last - 1) + 1;
345 end End_Case_Construction;
347 ------------------------
348 -- External_Reference --
349 ------------------------
351 procedure External_Reference
352 (In_Tree : Project_Node_Tree_Ref;
353 Current_Project : Project_Node_Id;
354 Current_Package : Project_Node_Id;
355 External_Value : out Project_Node_Id;
356 Flags : Processing_Flags)
358 Field_Id : Project_Node_Id := Empty_Node;
363 (Of_Kind => N_External_Value,
365 And_Expr_Kind => Single);
366 Set_Location_Of (External_Value, In_Tree, To => Token_Ptr);
368 -- The current token is External
370 -- Get the left parenthesis
373 Expect (Tok_Left_Paren, "`(`");
375 -- Scan past the left parenthesis
377 if Token = Tok_Left_Paren then
381 -- Get the name of the external reference
383 Expect (Tok_String_Literal, "literal string");
385 if Token = Tok_String_Literal then
388 (Of_Kind => N_Literal_String,
390 And_Expr_Kind => Single);
391 Set_String_Value_Of (Field_Id, In_Tree, To => Token_Name);
392 Set_External_Reference_Of (External_Value, In_Tree, To => Field_Id);
394 -- Scan past the first argument
400 when Tok_Right_Paren =>
401 Scan (In_Tree); -- scan past right paren
404 Scan (In_Tree); -- scan past comma
406 -- Get the string expression for the default
409 Loc : constant Source_Ptr := Token_Ptr;
414 Expression => Field_Id,
416 Current_Project => Current_Project,
417 Current_Package => Current_Package,
418 Optional_Index => False);
420 if Expression_Kind_Of (Field_Id, In_Tree) = List then
422 (Flags, "expression must be a single string", Loc);
424 Set_External_Default_Of
425 (External_Value, In_Tree, To => Field_Id);
429 Expect (Tok_Right_Paren, "`)`");
431 if Token = Tok_Right_Paren then
432 Scan (In_Tree); -- scan past right paren
436 Error_Msg (Flags, "`,` or `)` expected", Token_Ptr);
439 end External_Reference;
441 -----------------------
442 -- Parse_Choice_List --
443 -----------------------
445 procedure Parse_Choice_List
446 (In_Tree : Project_Node_Tree_Ref;
447 First_Choice : out Project_Node_Id;
448 Flags : Processing_Flags)
450 Current_Choice : Project_Node_Id := Empty_Node;
451 Next_Choice : Project_Node_Id := Empty_Node;
452 Choice_String : Name_Id := No_Name;
453 Found : Boolean := False;
456 -- Declare the node of the first choice
460 (Of_Kind => N_Literal_String,
462 And_Expr_Kind => Single);
464 -- Initially Current_Choice is the same as First_Choice
466 Current_Choice := First_Choice;
469 Expect (Tok_String_Literal, "literal string");
470 exit when Token /= Tok_String_Literal;
471 Set_Location_Of (Current_Choice, In_Tree, To => Token_Ptr);
472 Choice_String := Token_Name;
474 -- Give the string value to the current choice
476 Set_String_Value_Of (Current_Choice, In_Tree, To => Choice_String);
478 -- Check if the label is part of the string type and if it has not
479 -- been already used.
482 for Choice in Choice_First .. Choices.Last loop
483 if Choices.Table (Choice).The_String = Choice_String then
485 -- This label is part of the string type
489 if Choices.Table (Choice).Already_Used then
491 -- But it has already appeared in a choice list for this
492 -- case construction so report an error.
494 Error_Msg_Name_1 := Choice_String;
495 Error_Msg (Flags, "duplicate case label %%", Token_Ptr);
498 Choices.Table (Choice).Already_Used := True;
505 -- If the label is not part of the string list, report an error
508 Error_Msg_Name_1 := Choice_String;
509 Error_Msg (Flags, "illegal case label %%", Token_Ptr);
512 -- Scan past the label
516 -- If there is no '|', we are done
518 if Token = Tok_Vertical_Bar then
520 -- Otherwise, declare the node of the next choice, link it to
521 -- Current_Choice and set Current_Choice to this new node.
525 (Of_Kind => N_Literal_String,
527 And_Expr_Kind => Single);
528 Set_Next_Literal_String
529 (Current_Choice, In_Tree, To => Next_Choice);
530 Current_Choice := Next_Choice;
536 end Parse_Choice_List;
538 ----------------------
539 -- Parse_Expression --
540 ----------------------
542 procedure Parse_Expression
543 (In_Tree : Project_Node_Tree_Ref;
544 Expression : out Project_Node_Id;
545 Current_Project : Project_Node_Id;
546 Current_Package : Project_Node_Id;
547 Optional_Index : Boolean;
548 Flags : Processing_Flags)
550 First_Term : Project_Node_Id := Empty_Node;
551 Expression_Kind : Variable_Kind := Undefined;
554 -- Declare the node of the expression
557 Default_Project_Node (Of_Kind => N_Expression, In_Tree => In_Tree);
558 Set_Location_Of (Expression, In_Tree, To => Token_Ptr);
560 -- Parse the term or terms of the expression
562 Terms (In_Tree => In_Tree,
564 Expr_Kind => Expression_Kind,
566 Current_Project => Current_Project,
567 Current_Package => Current_Package,
568 Optional_Index => Optional_Index);
570 -- Set the first term and the expression kind
572 Set_First_Term (Expression, In_Tree, To => First_Term);
573 Set_Expression_Kind_Of (Expression, In_Tree, To => Expression_Kind);
574 end Parse_Expression;
576 ----------------------------
577 -- Parse_String_Type_List --
578 ----------------------------
580 procedure Parse_String_Type_List
581 (In_Tree : Project_Node_Tree_Ref;
582 First_String : out Project_Node_Id;
583 Flags : Processing_Flags)
585 Last_String : Project_Node_Id := Empty_Node;
586 Next_String : Project_Node_Id := Empty_Node;
587 String_Value : Name_Id := No_Name;
590 -- Declare the node of the first string
594 (Of_Kind => N_Literal_String,
596 And_Expr_Kind => Single);
598 -- Initially, Last_String is the same as First_String
600 Last_String := First_String;
603 Expect (Tok_String_Literal, "literal string");
604 exit when Token /= Tok_String_Literal;
605 String_Value := Token_Name;
607 -- Give its string value to Last_String
609 Set_String_Value_Of (Last_String, In_Tree, To => String_Value);
610 Set_Location_Of (Last_String, In_Tree, To => Token_Ptr);
612 -- Now, check if the string is already part of the string type
615 Current : Project_Node_Id := First_String;
618 while Current /= Last_String loop
619 if String_Value_Of (Current, In_Tree) = String_Value then
621 -- This is a repetition, report an error
623 Error_Msg_Name_1 := String_Value;
624 Error_Msg (Flags, "duplicate value %% in type", Token_Ptr);
628 Current := Next_Literal_String (Current, In_Tree);
632 -- Scan past the literal string
636 -- If there is no comma following the literal string, we are done
638 if Token /= Tok_Comma then
642 -- Declare the next string, link it to Last_String and set
643 -- Last_String to its node.
647 (Of_Kind => N_Literal_String,
649 And_Expr_Kind => Single);
650 Set_Next_Literal_String (Last_String, In_Tree, To => Next_String);
651 Last_String := Next_String;
655 end Parse_String_Type_List;
657 ------------------------------
658 -- Parse_Variable_Reference --
659 ------------------------------
661 procedure Parse_Variable_Reference
662 (In_Tree : Project_Node_Tree_Ref;
663 Variable : out Project_Node_Id;
664 Current_Project : Project_Node_Id;
665 Current_Package : Project_Node_Id;
666 Flags : Processing_Flags)
668 Current_Variable : Project_Node_Id := Empty_Node;
670 The_Package : Project_Node_Id := Current_Package;
671 The_Project : Project_Node_Id := Current_Project;
673 Specified_Project : Project_Node_Id := Empty_Node;
674 Specified_Package : Project_Node_Id := Empty_Node;
675 Look_For_Variable : Boolean := True;
676 First_Attribute : Attribute_Node_Id := Empty_Attribute;
677 Variable_Name : Name_Id;
683 Expect (Tok_Identifier, "identifier");
685 if Token /= Tok_Identifier then
686 Look_For_Variable := False;
690 Add_To_Names (NL => (Name => Token_Name, Location => Token_Ptr));
692 exit when Token /= Tok_Dot;
696 if Look_For_Variable then
698 if Token = Tok_Apostrophe then
700 -- Attribute reference
710 -- This may be a project name or a package name.
711 -- Project name have precedence.
713 -- First, look if it can be a package name
717 (Package_Node_Id_Of (Names.Table (1).Name));
719 -- Now, look if it can be a project name
721 if Names.Table (1).Name =
722 Name_Of (Current_Project, In_Tree)
724 The_Project := Current_Project;
728 Imported_Or_Extended_Project_Of
729 (Current_Project, In_Tree, Names.Table (1).Name);
732 if No (The_Project) then
734 -- If it is neither a project name nor a package name,
737 if First_Attribute = Empty_Attribute then
738 Error_Msg_Name_1 := Names.Table (1).Name;
739 Error_Msg (Flags, "unknown project %",
740 Names.Table (1).Location);
741 First_Attribute := Attribute_First;
744 -- If it is a package name, check if the package has
745 -- already been declared in the current project.
748 First_Package_Of (Current_Project, In_Tree);
750 while Present (The_Package)
751 and then Name_Of (The_Package, In_Tree) /=
755 Next_Package_In_Project (The_Package, In_Tree);
758 -- If it has not been already declared, report an
761 if No (The_Package) then
762 Error_Msg_Name_1 := Names.Table (1).Name;
763 Error_Msg (Flags, "package % not yet defined",
764 Names.Table (1).Location);
769 -- It is a project name
771 First_Attribute := Attribute_First;
772 The_Package := Empty_Node;
777 -- We have either a project name made of several simple
778 -- names (long project), or a project name (short project)
779 -- followed by a package name. The long project name has
783 Short_Project : Name_Id;
784 Long_Project : Name_Id;
791 -- Get the name of the short project
793 for Index in 1 .. Names.Last - 1 loop
795 (Get_Name_String (Names.Table (Index).Name),
796 Buffer, Buffer_Last);
798 if Index /= Names.Last - 1 then
799 Add_To_Buffer (".", Buffer, Buffer_Last);
803 Name_Len := Buffer_Last;
804 Name_Buffer (1 .. Buffer_Last) :=
805 Buffer (1 .. Buffer_Last);
806 Short_Project := Name_Find;
808 -- Now, add the last simple name to get the name of the
811 Add_To_Buffer (".", Buffer, Buffer_Last);
813 (Get_Name_String (Names.Table (Names.Last).Name),
814 Buffer, Buffer_Last);
815 Name_Len := Buffer_Last;
816 Name_Buffer (1 .. Buffer_Last) :=
817 Buffer (1 .. Buffer_Last);
818 Long_Project := Name_Find;
820 -- Check if the long project is imported or extended
822 if Long_Project = Name_Of (Current_Project, In_Tree) then
823 The_Project := Current_Project;
827 Imported_Or_Extended_Project_Of
833 -- If the long project exists, then this is the prefix
836 if Present (The_Project) then
837 First_Attribute := Attribute_First;
838 The_Package := Empty_Node;
841 -- Otherwise, check if the short project is imported
845 Name_Of (Current_Project, In_Tree)
847 The_Project := Current_Project;
850 The_Project := Imported_Or_Extended_Project_Of
851 (Current_Project, In_Tree,
855 -- If short project does not exist, report an error
857 if No (The_Project) then
858 Error_Msg_Name_1 := Long_Project;
859 Error_Msg_Name_2 := Short_Project;
860 Error_Msg (Flags, "unknown projects % or %",
861 Names.Table (1).Location);
862 The_Package := Empty_Node;
863 First_Attribute := Attribute_First;
866 -- Now, we check if the package has been declared
870 First_Package_Of (The_Project, In_Tree);
871 while Present (The_Package)
872 and then Name_Of (The_Package, In_Tree) /=
873 Names.Table (Names.Last).Name
876 Next_Package_In_Project (The_Package, In_Tree);
879 -- If it has not, then we report an error
881 if No (The_Package) then
883 Names.Table (Names.Last).Name;
884 Error_Msg_Name_2 := Short_Project;
886 "package % not declared in project %",
887 Names.Table (Names.Last).Location);
888 First_Attribute := Attribute_First;
891 -- Otherwise, we have the correct project and
896 (Package_Id_Of (The_Package, In_Tree));
907 Current_Project => The_Project,
908 Current_Package => The_Package,
909 First_Attribute => First_Attribute);
916 (Of_Kind => N_Variable_Reference, In_Tree => In_Tree);
918 if Look_For_Variable then
922 -- Cannot happen (so why null instead of raise PE???)
928 -- Simple variable name
930 Set_Name_Of (Variable, In_Tree, To => Names.Table (1).Name);
934 -- Variable name with a simple name prefix that can be
935 -- a project name or a package name. Project names have
936 -- priority over package names.
938 Set_Name_Of (Variable, In_Tree, To => Names.Table (2).Name);
940 -- Check if it can be a package name
942 The_Package := First_Package_Of (Current_Project, In_Tree);
944 while Present (The_Package)
945 and then Name_Of (The_Package, In_Tree) /=
949 Next_Package_In_Project (The_Package, In_Tree);
952 -- Now look for a possible project name
954 The_Project := Imported_Or_Extended_Project_Of
955 (Current_Project, In_Tree, Names.Table (1).Name);
957 if Present (The_Project) then
958 Specified_Project := The_Project;
960 elsif No (The_Package) then
961 Error_Msg_Name_1 := Names.Table (1).Name;
962 Error_Msg (Flags, "unknown package or project %",
963 Names.Table (1).Location);
964 Look_For_Variable := False;
967 Specified_Package := The_Package;
972 -- Variable name with a prefix that is either a project name
973 -- made of several simple names, or a project name followed
974 -- by a package name.
977 (Variable, In_Tree, To => Names.Table (Names.Last).Name);
980 Short_Project : Name_Id;
981 Long_Project : Name_Id;
984 -- First, we get the two possible project names
990 -- Add all the simple names, except the last two
992 for Index in 1 .. Names.Last - 2 loop
994 (Get_Name_String (Names.Table (Index).Name),
995 Buffer, Buffer_Last);
997 if Index /= Names.Last - 2 then
998 Add_To_Buffer (".", Buffer, Buffer_Last);
1002 Name_Len := Buffer_Last;
1003 Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last);
1004 Short_Project := Name_Find;
1006 -- Add the simple name before the name of the variable
1008 Add_To_Buffer (".", Buffer, Buffer_Last);
1010 (Get_Name_String (Names.Table (Names.Last - 1).Name),
1011 Buffer, Buffer_Last);
1012 Name_Len := Buffer_Last;
1013 Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last);
1014 Long_Project := Name_Find;
1016 -- Check if the prefix is the name of an imported or
1017 -- extended project.
1019 The_Project := Imported_Or_Extended_Project_Of
1020 (Current_Project, In_Tree, Long_Project);
1022 if Present (The_Project) then
1023 Specified_Project := The_Project;
1026 -- Now check if the prefix may be a project name followed
1027 -- by a package name.
1029 -- First check for a possible project name
1032 Imported_Or_Extended_Project_Of
1033 (Current_Project, In_Tree, Short_Project);
1035 if No (The_Project) then
1036 -- Unknown prefix, report an error
1038 Error_Msg_Name_1 := Long_Project;
1039 Error_Msg_Name_2 := Short_Project;
1041 (Flags, "unknown projects % or %",
1042 Names.Table (1).Location);
1043 Look_For_Variable := False;
1046 Specified_Project := The_Project;
1048 -- Now look for the package in this project
1050 The_Package := First_Package_Of (The_Project, In_Tree);
1052 while Present (The_Package)
1053 and then Name_Of (The_Package, In_Tree) /=
1054 Names.Table (Names.Last - 1).Name
1057 Next_Package_In_Project (The_Package, In_Tree);
1060 if No (The_Package) then
1062 -- The package does not exist, report an error
1064 Error_Msg_Name_1 := Names.Table (2).Name;
1065 Error_Msg (Flags, "unknown package %",
1066 Names.Table (Names.Last - 1).Location);
1067 Look_For_Variable := False;
1070 Specified_Package := The_Package;
1078 if Look_For_Variable then
1079 Variable_Name := Name_Of (Variable, In_Tree);
1080 Set_Project_Node_Of (Variable, In_Tree, To => Specified_Project);
1081 Set_Package_Node_Of (Variable, In_Tree, To => Specified_Package);
1083 if Present (Specified_Project) then
1084 The_Project := Specified_Project;
1086 The_Project := Current_Project;
1089 Current_Variable := Empty_Node;
1091 -- Look for this variable
1093 -- If a package was specified, check if the variable has been
1094 -- declared in this package.
1096 if Present (Specified_Package) then
1098 First_Variable_Of (Specified_Package, In_Tree);
1099 while Present (Current_Variable)
1101 Name_Of (Current_Variable, In_Tree) /= Variable_Name
1103 Current_Variable := Next_Variable (Current_Variable, In_Tree);
1107 -- Otherwise, if no project has been specified and we are in
1108 -- a package, first check if the variable has been declared in
1111 if No (Specified_Project)
1112 and then Present (Current_Package)
1115 First_Variable_Of (Current_Package, In_Tree);
1116 while Present (Current_Variable)
1117 and then Name_Of (Current_Variable, In_Tree) /= Variable_Name
1120 Next_Variable (Current_Variable, In_Tree);
1124 -- If we have not found the variable in the package, check if the
1125 -- variable has been declared in the project, or in any of its
1128 if No (Current_Variable) then
1130 Proj : Project_Node_Id := The_Project;
1134 Current_Variable := First_Variable_Of (Proj, In_Tree);
1136 Present (Current_Variable)
1138 Name_Of (Current_Variable, In_Tree) /= Variable_Name
1141 Next_Variable (Current_Variable, In_Tree);
1144 exit when Present (Current_Variable);
1146 Proj := Parent_Project_Of (Proj, In_Tree);
1148 Set_Project_Node_Of (Variable, In_Tree, To => Proj);
1150 exit when No (Proj);
1156 -- If the variable was not found, report an error
1158 if No (Current_Variable) then
1159 Error_Msg_Name_1 := Variable_Name;
1161 (Flags, "unknown variable %", Names.Table (Names.Last).Location);
1165 if Present (Current_Variable) then
1166 Set_Expression_Kind_Of
1168 To => Expression_Kind_Of (Current_Variable, In_Tree));
1170 if Kind_Of (Current_Variable, In_Tree) =
1171 N_Typed_Variable_Declaration
1175 To => String_Type_Of (Current_Variable, In_Tree));
1179 -- If the variable is followed by a left parenthesis, report an error
1180 -- but attempt to scan the index.
1182 if Token = Tok_Left_Paren then
1184 (Flags, "\variables cannot be associative arrays", Token_Ptr);
1186 Expect (Tok_String_Literal, "literal string");
1188 if Token = Tok_String_Literal then
1190 Expect (Tok_Right_Paren, "`)`");
1192 if Token = Tok_Right_Paren then
1197 end Parse_Variable_Reference;
1199 ---------------------------------
1200 -- Start_New_Case_Construction --
1201 ---------------------------------
1203 procedure Start_New_Case_Construction
1204 (In_Tree : Project_Node_Tree_Ref;
1205 String_Type : Project_Node_Id)
1207 Current_String : Project_Node_Id;
1210 -- Set Choice_First, depending on whether this is the first case
1211 -- construction or not.
1213 if Choice_First = 0 then
1215 Choices.Set_Last (First_Choice_Node_Id);
1217 Choice_First := Choices.Last + 1;
1220 -- Add the literal of the string type to the Choices table
1222 if Present (String_Type) then
1223 Current_String := First_Literal_String (String_Type, In_Tree);
1224 while Present (Current_String) loop
1225 Add (This_String => String_Value_Of (Current_String, In_Tree));
1226 Current_String := Next_Literal_String (Current_String, In_Tree);
1230 -- Set the value of the last choice in table Choice_Lasts
1232 Choice_Lasts.Increment_Last;
1233 Choice_Lasts.Table (Choice_Lasts.Last) := Choices.Last;
1234 end Start_New_Case_Construction;
1241 (In_Tree : Project_Node_Tree_Ref;
1242 Term : out Project_Node_Id;
1243 Expr_Kind : in out Variable_Kind;
1244 Current_Project : Project_Node_Id;
1245 Current_Package : Project_Node_Id;
1246 Optional_Index : Boolean;
1247 Flags : Processing_Flags)
1249 Next_Term : Project_Node_Id := Empty_Node;
1250 Term_Id : Project_Node_Id := Empty_Node;
1251 Current_Expression : Project_Node_Id := Empty_Node;
1252 Next_Expression : Project_Node_Id := Empty_Node;
1253 Current_Location : Source_Ptr := No_Location;
1254 Reference : Project_Node_Id := Empty_Node;
1257 -- Declare a new node for the term
1259 Term := Default_Project_Node (Of_Kind => N_Term, In_Tree => In_Tree);
1260 Set_Location_Of (Term, In_Tree, To => Token_Ptr);
1263 when Tok_Left_Paren =>
1265 -- If we have a left parenthesis and we don't know the expression
1266 -- kind, then this is a string list.
1277 -- If we already know that this is a single string, report
1278 -- an error, but set the expression kind to string list to
1279 -- avoid several errors.
1283 (Flags, "literal string list cannot appear in a string",
1287 -- Declare a new node for this literal string list
1289 Term_Id := Default_Project_Node
1290 (Of_Kind => N_Literal_String_List,
1292 And_Expr_Kind => List);
1293 Set_Current_Term (Term, In_Tree, To => Term_Id);
1294 Set_Location_Of (Term, In_Tree, To => Token_Ptr);
1296 -- Scan past the left parenthesis
1300 -- If the left parenthesis is immediately followed by a right
1301 -- parenthesis, the literal string list is empty.
1303 if Token = Tok_Right_Paren then
1307 -- Otherwise parse the expression(s) in the literal string list
1310 Current_Location := Token_Ptr;
1312 (In_Tree => In_Tree,
1313 Expression => Next_Expression,
1315 Current_Project => Current_Project,
1316 Current_Package => Current_Package,
1317 Optional_Index => Optional_Index);
1319 -- The expression kind is String list, report an error
1321 if Expression_Kind_Of (Next_Expression, In_Tree) = List then
1322 Error_Msg (Flags, "single expression expected",
1326 -- If Current_Expression is empty, it means that the
1327 -- expression is the first in the string list.
1329 if No (Current_Expression) then
1330 Set_First_Expression_In_List
1331 (Term_Id, In_Tree, To => Next_Expression);
1333 Set_Next_Expression_In_List
1334 (Current_Expression, In_Tree, To => Next_Expression);
1337 Current_Expression := Next_Expression;
1339 -- If there is a comma, continue with the next expression
1341 exit when Token /= Tok_Comma;
1342 Scan (In_Tree); -- past the comma
1345 -- We expect a closing right parenthesis
1347 Expect (Tok_Right_Paren, "`)`");
1349 if Token = Tok_Right_Paren then
1354 when Tok_String_Literal =>
1356 -- If we don't know the expression kind (first term), then it is
1359 if Expr_Kind = Undefined then
1360 Expr_Kind := Single;
1363 -- Declare a new node for the string literal
1366 Default_Project_Node
1367 (Of_Kind => N_Literal_String, In_Tree => In_Tree);
1368 Set_Current_Term (Term, In_Tree, To => Term_Id);
1369 Set_String_Value_Of (Term_Id, In_Tree, To => Token_Name);
1371 -- Scan past the string literal
1375 -- Check for possible index expression
1377 if Token = Tok_At then
1378 if not Optional_Index then
1379 Error_Msg (Flags, "index not allowed here", Token_Ptr);
1382 if Token = Tok_Integer_Literal then
1386 -- Set the index value
1390 Expect (Tok_Integer_Literal, "integer literal");
1392 if Token = Tok_Integer_Literal then
1394 Index : constant Int := UI_To_Int (Int_Literal_Value);
1398 (Flags, "index cannot be zero", Token_Ptr);
1401 (Term_Id, In_Tree, To => Index);
1410 when Tok_Identifier =>
1411 Current_Location := Token_Ptr;
1413 -- Get the variable or attribute reference
1415 Parse_Variable_Reference
1416 (In_Tree => In_Tree,
1417 Variable => Reference,
1419 Current_Project => Current_Project,
1420 Current_Package => Current_Package);
1421 Set_Current_Term (Term, In_Tree, To => Reference);
1423 if Present (Reference) then
1425 -- If we don't know the expression kind (first term), then it
1426 -- has the kind of the variable or attribute reference.
1428 if Expr_Kind = Undefined then
1429 Expr_Kind := Expression_Kind_Of (Reference, In_Tree);
1431 elsif Expr_Kind = Single
1432 and then Expression_Kind_Of (Reference, In_Tree) = List
1434 -- If the expression is a single list, and the reference is
1435 -- a string list, report an error, and set the expression
1436 -- kind to string list to avoid multiple errors.
1441 "list variable cannot appear in single string expression",
1448 -- Project can appear in an expression as the prefix of an
1449 -- attribute reference of the current project.
1451 Current_Location := Token_Ptr;
1453 Expect (Tok_Apostrophe, "`'`");
1455 if Token = Tok_Apostrophe then
1457 (In_Tree => In_Tree,
1458 Reference => Reference,
1460 First_Attribute => Prj.Attr.Attribute_First,
1461 Current_Project => Current_Project,
1462 Current_Package => Empty_Node);
1463 Set_Current_Term (Term, In_Tree, To => Reference);
1466 -- Same checks as above for the expression kind
1468 if Present (Reference) then
1469 if Expr_Kind = Undefined then
1470 Expr_Kind := Expression_Kind_Of (Reference, In_Tree);
1472 elsif Expr_Kind = Single
1473 and then Expression_Kind_Of (Reference, In_Tree) = List
1476 (Flags, "lists cannot appear in single string expression",
1481 when Tok_External =>
1483 -- An external reference is always a single string
1485 if Expr_Kind = Undefined then
1486 Expr_Kind := Single;
1490 (In_Tree => In_Tree,
1492 Current_Project => Current_Project,
1493 Current_Package => Current_Package,
1494 External_Value => Reference);
1495 Set_Current_Term (Term, In_Tree, To => Reference);
1498 Error_Msg (Flags, "cannot be part of an expression", Token_Ptr);
1503 -- If there is an '&', call Terms recursively
1505 if Token = Tok_Ampersand then
1506 Scan (In_Tree); -- scan past ampersand
1509 (In_Tree => In_Tree,
1511 Expr_Kind => Expr_Kind,
1513 Current_Project => Current_Project,
1514 Current_Package => Current_Package,
1515 Optional_Index => Optional_Index);
1517 -- And link the next term to this term
1519 Set_Next_Term (Term, In_Tree, To => Next_Term);