1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2011, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with GNAT.Case_Util; use GNAT.Case_Util;
27 with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
30 with Err_Vars; use Err_Vars;
32 with Prj.Attr; use Prj.Attr;
33 with Prj.Attr.PM; use Prj.Attr.PM;
34 with Prj.Err; use Prj.Err;
35 with Prj.Strt; use Prj.Strt;
36 with Prj.Tree; use Prj.Tree;
38 with Uintp; use Uintp;
40 package body Prj.Dect is
44 type Zone is (In_Project, In_Package, In_Case_Construction);
45 -- Used to indicate if we are parsing a package (In_Package),
46 -- a case construction (In_Case_Construction) or none of those two
49 procedure Rename_Obsolescent_Attributes
50 (In_Tree : Project_Node_Tree_Ref;
51 Attribute : Project_Node_Id;
52 Current_Package : Project_Node_Id);
53 -- Rename obsolescent attributes in the tree.
54 -- When the attribute has been renamed since its initial introduction in
55 -- the design of projects, we replace the old name in the tree with the
56 -- new name, so that the code does not have to check both names forever.
58 procedure Check_Attribute_Allowed
59 (In_Tree : Project_Node_Tree_Ref;
60 Project : Project_Node_Id;
61 Attribute : Project_Node_Id;
62 Flags : Processing_Flags);
63 -- Check whether the attribute is valid in this project.
64 -- In particular, depending on the type of project (qualifier), some
65 -- attributes might be disabled.
67 procedure Check_Package_Allowed
68 (In_Tree : Project_Node_Tree_Ref;
69 Project : Project_Node_Id;
70 Current_Package : Project_Node_Id;
71 Flags : Processing_Flags);
72 -- Check whether the package is valid in this project
74 procedure Parse_Attribute_Declaration
75 (In_Tree : Project_Node_Tree_Ref;
76 Attribute : out Project_Node_Id;
77 First_Attribute : Attribute_Node_Id;
78 Current_Project : Project_Node_Id;
79 Current_Package : Project_Node_Id;
80 Packages_To_Check : String_List_Access;
81 Flags : Processing_Flags);
82 -- Parse an attribute declaration
84 procedure Parse_Case_Construction
85 (In_Tree : Project_Node_Tree_Ref;
86 Case_Construction : out Project_Node_Id;
87 First_Attribute : Attribute_Node_Id;
88 Current_Project : Project_Node_Id;
89 Current_Package : Project_Node_Id;
90 Packages_To_Check : String_List_Access;
91 Is_Config_File : Boolean;
92 Flags : Processing_Flags);
93 -- Parse a case construction
95 procedure Parse_Declarative_Items
96 (In_Tree : Project_Node_Tree_Ref;
97 Declarations : out Project_Node_Id;
99 First_Attribute : Attribute_Node_Id;
100 Current_Project : Project_Node_Id;
101 Current_Package : Project_Node_Id;
102 Packages_To_Check : String_List_Access;
103 Is_Config_File : Boolean;
104 Flags : Processing_Flags);
105 -- Parse declarative items. Depending on In_Zone, some declarative items
106 -- may be forbidden. Is_Config_File should be set to True if the project
107 -- represents a config file (.cgpr) since some specific checks apply.
109 procedure Parse_Package_Declaration
110 (In_Tree : Project_Node_Tree_Ref;
111 Package_Declaration : out Project_Node_Id;
112 Current_Project : Project_Node_Id;
113 Packages_To_Check : String_List_Access;
114 Is_Config_File : Boolean;
115 Flags : Processing_Flags);
116 -- Parse a package declaration.
117 -- Is_Config_File should be set to True if the project represents a config
118 -- file (.cgpr) since some specific checks apply.
120 procedure Parse_String_Type_Declaration
121 (In_Tree : Project_Node_Tree_Ref;
122 String_Type : out Project_Node_Id;
123 Current_Project : Project_Node_Id;
124 Flags : Processing_Flags);
125 -- type <name> is ( <literal_string> { , <literal_string> } ) ;
127 procedure Parse_Variable_Declaration
128 (In_Tree : Project_Node_Tree_Ref;
129 Variable : out Project_Node_Id;
130 Current_Project : Project_Node_Id;
131 Current_Package : Project_Node_Id;
132 Flags : Processing_Flags);
133 -- Parse a variable assignment
134 -- <variable_Name> := <expression>; OR
135 -- <variable_Name> : <string_type_Name> := <string_expression>;
142 (In_Tree : Project_Node_Tree_Ref;
143 Declarations : out Project_Node_Id;
144 Current_Project : Project_Node_Id;
145 Extends : Project_Node_Id;
146 Packages_To_Check : String_List_Access;
147 Is_Config_File : Boolean;
148 Flags : Processing_Flags)
150 First_Declarative_Item : Project_Node_Id := Empty_Node;
155 (Of_Kind => N_Project_Declaration, In_Tree => In_Tree);
156 Set_Location_Of (Declarations, In_Tree, To => Token_Ptr);
157 Set_Extended_Project_Of (Declarations, In_Tree, To => Extends);
158 Set_Project_Declaration_Of (Current_Project, In_Tree, Declarations);
159 Parse_Declarative_Items
160 (Declarations => First_Declarative_Item,
162 In_Zone => In_Project,
163 First_Attribute => Prj.Attr.Attribute_First,
164 Current_Project => Current_Project,
165 Current_Package => Empty_Node,
166 Packages_To_Check => Packages_To_Check,
167 Is_Config_File => Is_Config_File,
169 Set_First_Declarative_Item_Of
170 (Declarations, In_Tree, To => First_Declarative_Item);
173 -----------------------------------
174 -- Rename_Obsolescent_Attributes --
175 -----------------------------------
177 procedure Rename_Obsolescent_Attributes
178 (In_Tree : Project_Node_Tree_Ref;
179 Attribute : Project_Node_Id;
180 Current_Package : Project_Node_Id)
183 if Present (Current_Package)
184 and then Expression_Kind_Of (Current_Package, In_Tree) /= Ignored
186 case Name_Of (Attribute, In_Tree) is
187 when Snames.Name_Specification =>
188 Set_Name_Of (Attribute, In_Tree, To => Snames.Name_Spec);
190 when Snames.Name_Specification_Suffix =>
191 Set_Name_Of (Attribute, In_Tree, To => Snames.Name_Spec_Suffix);
193 when Snames.Name_Implementation =>
194 Set_Name_Of (Attribute, In_Tree, To => Snames.Name_Body);
196 when Snames.Name_Implementation_Suffix =>
197 Set_Name_Of (Attribute, In_Tree, To => Snames.Name_Body_Suffix);
203 end Rename_Obsolescent_Attributes;
205 ---------------------------
206 -- Check_Package_Allowed --
207 ---------------------------
209 procedure Check_Package_Allowed
210 (In_Tree : Project_Node_Tree_Ref;
211 Project : Project_Node_Id;
212 Current_Package : Project_Node_Id;
213 Flags : Processing_Flags)
215 Qualif : constant Project_Qualifier :=
216 Project_Qualifier_Of (Project, In_Tree);
217 Name : constant Name_Id := Name_Of (Current_Package, In_Tree);
219 if Qualif = Aggregate
220 and then Name /= Snames.Name_Builder
222 Error_Msg_Name_1 := Name;
225 "package %% is forbidden in aggregate projects",
226 Location_Of (Current_Package, In_Tree));
228 end Check_Package_Allowed;
230 -----------------------------
231 -- Check_Attribute_Allowed --
232 -----------------------------
234 procedure Check_Attribute_Allowed
235 (In_Tree : Project_Node_Tree_Ref;
236 Project : Project_Node_Id;
237 Attribute : Project_Node_Id;
238 Flags : Processing_Flags)
240 Qualif : constant Project_Qualifier :=
241 Project_Qualifier_Of (Project, In_Tree);
242 Name : constant Name_Id := Name_Of (Attribute, In_Tree);
247 if Name = Snames.Name_Languages
248 or else Name = Snames.Name_Source_Files
249 or else Name = Snames.Name_Source_List_File
250 or else Name = Snames.Name_Locally_Removed_Files
251 or else Name = Snames.Name_Excluded_Source_Files
252 or else Name = Snames.Name_Excluded_Source_List_File
253 or else Name = Snames.Name_Interfaces
254 or else Name = Snames.Name_Object_Dir
255 or else Name = Snames.Name_Exec_Dir
256 or else Name = Snames.Name_Source_Dirs
257 or else Name = Snames.Name_Inherit_Source_Path
259 Error_Msg_Name_1 := Name;
262 "%% is not valid in aggregate projects",
263 Location_Of (Attribute, In_Tree));
267 if Name = Snames.Name_Project_Files
268 or else Name = Snames.Name_Project_Path
269 or else Name = Snames.Name_External
271 Error_Msg_Name_1 := Name;
274 "%% is only valid in aggregate projects",
275 Location_Of (Attribute, In_Tree));
278 end Check_Attribute_Allowed;
280 ---------------------------------
281 -- Parse_Attribute_Declaration --
282 ---------------------------------
284 procedure Parse_Attribute_Declaration
285 (In_Tree : Project_Node_Tree_Ref;
286 Attribute : out Project_Node_Id;
287 First_Attribute : Attribute_Node_Id;
288 Current_Project : Project_Node_Id;
289 Current_Package : Project_Node_Id;
290 Packages_To_Check : String_List_Access;
291 Flags : Processing_Flags)
293 Current_Attribute : Attribute_Node_Id := First_Attribute;
294 Full_Associative_Array : Boolean := False;
295 Attribute_Name : Name_Id := No_Name;
296 Optional_Index : Boolean := False;
297 Pkg_Id : Package_Node_Id := Empty_Package;
299 procedure Process_Attribute_Name;
300 -- Read the name of the attribute, and check its type
302 procedure Process_Associative_Array_Index;
303 -- Read the index of the associative array and check its validity
305 ----------------------------
306 -- Process_Attribute_Name --
307 ----------------------------
309 procedure Process_Attribute_Name is
313 Attribute_Name := Token_Name;
314 Set_Name_Of (Attribute, In_Tree, To => Attribute_Name);
315 Set_Location_Of (Attribute, In_Tree, To => Token_Ptr);
317 -- Find the attribute
320 Attribute_Node_Id_Of (Attribute_Name, First_Attribute);
322 -- If the attribute cannot be found, create the attribute if inside
323 -- an unknown package.
325 if Current_Attribute = Empty_Attribute then
326 if Present (Current_Package)
327 and then Expression_Kind_Of (Current_Package, In_Tree) = Ignored
329 Pkg_Id := Package_Id_Of (Current_Package, In_Tree);
330 Add_Attribute (Pkg_Id, Token_Name, Current_Attribute);
333 -- If not a valid attribute name, issue an error if inside
334 -- a package that need to be checked.
336 Ignore := Present (Current_Package) and then
337 Packages_To_Check /= All_Packages;
341 -- Check that we are not in a package to check
343 Get_Name_String (Name_Of (Current_Package, In_Tree));
345 for Index in Packages_To_Check'Range loop
346 if Name_Buffer (1 .. Name_Len) =
347 Packages_To_Check (Index).all
356 Error_Msg_Name_1 := Token_Name;
357 Error_Msg (Flags, "undefined attribute %%", Token_Ptr);
361 -- Set, if appropriate the index case insensitivity flag
364 if Is_Read_Only (Current_Attribute) then
365 Error_Msg_Name_1 := Token_Name;
367 (Flags, "read-only attribute %% cannot be given a value",
371 if Attribute_Kind_Of (Current_Attribute) in
372 All_Case_Insensitive_Associative_Array
374 Set_Case_Insensitive (Attribute, In_Tree, To => True);
378 Scan (In_Tree); -- past the attribute name
380 -- Set the expression kind of the attribute
382 if Current_Attribute /= Empty_Attribute then
383 Set_Expression_Kind_Of
384 (Attribute, In_Tree, To => Variable_Kind_Of (Current_Attribute));
385 Optional_Index := Optional_Index_Of (Current_Attribute);
387 end Process_Attribute_Name;
389 -------------------------------------
390 -- Process_Associative_Array_Index --
391 -------------------------------------
393 procedure Process_Associative_Array_Index is
395 -- If the attribute is not an associative array attribute, report
396 -- an error. If this information is still unknown, set the kind
397 -- to Associative_Array.
399 if Current_Attribute /= Empty_Attribute
400 and then Attribute_Kind_Of (Current_Attribute) = Single
404 Get_Name_String (Attribute_Name_Of (Current_Attribute))
405 & """ cannot be an associative array",
406 Location_Of (Attribute, In_Tree));
408 elsif Attribute_Kind_Of (Current_Attribute) = Unknown then
409 Set_Attribute_Kind_Of (Current_Attribute, To => Associative_Array);
412 Scan (In_Tree); -- past the left parenthesis
414 if Others_Allowed_For (Current_Attribute)
415 and then Token = Tok_Others
417 Set_Associative_Array_Index_Of
418 (Attribute, In_Tree, All_Other_Names);
419 Scan (In_Tree); -- past others
422 if Others_Allowed_For (Current_Attribute) then
423 Expect (Tok_String_Literal, "literal string or others");
425 Expect (Tok_String_Literal, "literal string");
428 if Token = Tok_String_Literal then
429 Get_Name_String (Token_Name);
431 if Case_Insensitive (Attribute, In_Tree) then
432 To_Lower (Name_Buffer (1 .. Name_Len));
435 Set_Associative_Array_Index_Of (Attribute, In_Tree, Name_Find);
436 Scan (In_Tree); -- past the literal string index
438 if Token = Tok_At then
439 case Attribute_Kind_Of (Current_Attribute) is
440 when Optional_Index_Associative_Array |
441 Optional_Index_Case_Insensitive_Associative_Array =>
443 Expect (Tok_Integer_Literal, "integer literal");
445 if Token = Tok_Integer_Literal then
447 -- Set the source index value from given literal
450 Index : constant Int :=
451 UI_To_Int (Int_Literal_Value);
455 (Flags, "index cannot be zero", Token_Ptr);
458 (Attribute, In_Tree, To => Index);
466 Error_Msg (Flags, "index not allowed here", Token_Ptr);
469 if Token = Tok_Integer_Literal then
477 Expect (Tok_Right_Paren, "`)`");
479 if Token = Tok_Right_Paren then
480 Scan (In_Tree); -- past the right parenthesis
482 end Process_Associative_Array_Index;
487 (Of_Kind => N_Attribute_Declaration, In_Tree => In_Tree);
488 Set_Location_Of (Attribute, In_Tree, To => Token_Ptr);
489 Set_Previous_Line_Node (Attribute);
495 -- Body or External may be an attribute name
497 if Token = Tok_Body then
498 Token := Tok_Identifier;
499 Token_Name := Snames.Name_Body;
502 if Token = Tok_External then
503 Token := Tok_Identifier;
504 Token_Name := Snames.Name_External;
507 Expect (Tok_Identifier, "identifier");
508 Process_Attribute_Name;
509 Rename_Obsolescent_Attributes (In_Tree, Attribute, Current_Package);
510 Check_Attribute_Allowed (In_Tree, Current_Project, Attribute, Flags);
512 -- Associative array attributes
514 if Token = Tok_Left_Paren then
515 Process_Associative_Array_Index;
518 -- If it is an associative array attribute and there are no left
519 -- parenthesis, then this is a full associative array declaration.
520 -- Flag it as such for later processing of its value.
522 if Current_Attribute /= Empty_Attribute
524 Attribute_Kind_Of (Current_Attribute) /= Single
526 if Attribute_Kind_Of (Current_Attribute) = Unknown then
527 Set_Attribute_Kind_Of (Current_Attribute, To => Single);
530 Full_Associative_Array := True;
535 Expect (Tok_Use, "USE");
537 if Token = Tok_Use then
540 if Full_Associative_Array then
542 -- Expect <project>'<same_attribute_name>, or
543 -- <project>.<same_package_name>'<same_attribute_name>
546 The_Project : Project_Node_Id := Empty_Node;
547 -- The node of the project where the associative array is
550 The_Package : Project_Node_Id := Empty_Node;
551 -- The node of the package where the associative array is
554 Project_Name : Name_Id := No_Name;
555 -- The name of the project where the associative array is
558 Location : Source_Ptr := No_Location;
559 -- The location of the project name
562 Expect (Tok_Identifier, "identifier");
564 if Token = Tok_Identifier then
565 Location := Token_Ptr;
567 -- Find the project node in the imported project or
568 -- in the project being extended.
570 The_Project := Imported_Or_Extended_Project_Of
571 (Current_Project, In_Tree, Token_Name);
573 if No (The_Project) then
574 Error_Msg (Flags, "unknown project", Location);
575 Scan (In_Tree); -- past the project name
578 Project_Name := Token_Name;
579 Scan (In_Tree); -- past the project name
581 -- If this is inside a package, a dot followed by the
582 -- name of the package must followed the project name.
584 if Present (Current_Package) then
585 Expect (Tok_Dot, "`.`");
587 if Token /= Tok_Dot then
588 The_Project := Empty_Node;
591 Scan (In_Tree); -- past the dot
592 Expect (Tok_Identifier, "identifier");
594 if Token /= Tok_Identifier then
595 The_Project := Empty_Node;
597 -- If it is not the same package name, issue error
600 Token_Name /= Name_Of (Current_Package, In_Tree)
602 The_Project := Empty_Node;
604 (Flags, "not the same package as " &
606 (Name_Of (Current_Package, In_Tree)),
611 First_Package_Of (The_Project, In_Tree);
613 -- Look for the package node
615 while Present (The_Package)
617 Name_Of (The_Package, In_Tree) /= Token_Name
620 Next_Package_In_Project
621 (The_Package, In_Tree);
624 -- If the package cannot be found in the
625 -- project, issue an error.
627 if No (The_Package) then
628 The_Project := Empty_Node;
629 Error_Msg_Name_2 := Project_Name;
630 Error_Msg_Name_1 := Token_Name;
633 "package % not declared in project %",
637 Scan (In_Tree); -- past the package name
644 if Present (The_Project) then
646 -- Looking for '<same attribute name>
648 Expect (Tok_Apostrophe, "`''`");
650 if Token /= Tok_Apostrophe then
651 The_Project := Empty_Node;
654 Scan (In_Tree); -- past the apostrophe
655 Expect (Tok_Identifier, "identifier");
657 if Token /= Tok_Identifier then
658 The_Project := Empty_Node;
661 -- If it is not the same attribute name, issue error
663 if Token_Name /= Attribute_Name then
664 The_Project := Empty_Node;
665 Error_Msg_Name_1 := Attribute_Name;
667 (Flags, "invalid name, should be %", Token_Ptr);
670 Scan (In_Tree); -- past the attribute name
675 if No (The_Project) then
677 -- If there were any problem, set the attribute id to null,
678 -- so that the node will not be recorded.
680 Current_Attribute := Empty_Attribute;
683 -- Set the appropriate field in the node.
684 -- Note that the index and the expression are nil. This
685 -- characterizes full associative array attribute
688 Set_Associative_Project_Of (Attribute, In_Tree, The_Project);
689 Set_Associative_Package_Of (Attribute, In_Tree, The_Package);
693 -- Other attribute declarations (not full associative array)
697 Expression_Location : constant Source_Ptr := Token_Ptr;
698 -- The location of the first token of the expression
700 Expression : Project_Node_Id := Empty_Node;
701 -- The expression, value for the attribute declaration
704 -- Get the expression value and set it in the attribute node
708 Expression => Expression,
710 Current_Project => Current_Project,
711 Current_Package => Current_Package,
712 Optional_Index => Optional_Index);
713 Set_Expression_Of (Attribute, In_Tree, To => Expression);
715 -- If the expression is legal, but not of the right kind
716 -- for the attribute, issue an error.
718 if Current_Attribute /= Empty_Attribute
719 and then Present (Expression)
720 and then Variable_Kind_Of (Current_Attribute) /=
721 Expression_Kind_Of (Expression, In_Tree)
723 if Variable_Kind_Of (Current_Attribute) = Undefined then
726 To => Expression_Kind_Of (Expression, In_Tree));
730 (Flags, "wrong expression kind for attribute """ &
732 (Attribute_Name_Of (Current_Attribute)) &
734 Expression_Location);
741 -- If the attribute was not recognized, return an empty node.
742 -- It may be that it is not in a package to check, and the node will
743 -- not be added to the tree.
745 if Current_Attribute = Empty_Attribute then
746 Attribute := Empty_Node;
749 Set_End_Of_Line (Attribute);
750 Set_Previous_Line_Node (Attribute);
751 end Parse_Attribute_Declaration;
753 -----------------------------
754 -- Parse_Case_Construction --
755 -----------------------------
757 procedure Parse_Case_Construction
758 (In_Tree : Project_Node_Tree_Ref;
759 Case_Construction : out Project_Node_Id;
760 First_Attribute : Attribute_Node_Id;
761 Current_Project : Project_Node_Id;
762 Current_Package : Project_Node_Id;
763 Packages_To_Check : String_List_Access;
764 Is_Config_File : Boolean;
765 Flags : Processing_Flags)
767 Current_Item : Project_Node_Id := Empty_Node;
768 Next_Item : Project_Node_Id := Empty_Node;
769 First_Case_Item : Boolean := True;
771 Variable_Location : Source_Ptr := No_Location;
773 String_Type : Project_Node_Id := Empty_Node;
775 Case_Variable : Project_Node_Id := Empty_Node;
777 First_Declarative_Item : Project_Node_Id := Empty_Node;
779 First_Choice : Project_Node_Id := Empty_Node;
781 When_Others : Boolean := False;
782 -- Set to True when there is a "when others =>" clause
787 (Of_Kind => N_Case_Construction, In_Tree => In_Tree);
788 Set_Location_Of (Case_Construction, In_Tree, To => Token_Ptr);
794 -- Get the switch variable
796 Expect (Tok_Identifier, "identifier");
798 if Token = Tok_Identifier then
799 Variable_Location := Token_Ptr;
800 Parse_Variable_Reference
802 Variable => Case_Variable,
804 Current_Project => Current_Project,
805 Current_Package => Current_Package);
806 Set_Case_Variable_Reference_Of
807 (Case_Construction, In_Tree, To => Case_Variable);
810 if Token /= Tok_Is then
815 if Present (Case_Variable) then
816 String_Type := String_Type_Of (Case_Variable, In_Tree);
818 if No (String_Type) then
821 Get_Name_String (Name_Of (Case_Variable, In_Tree)) &
827 Expect (Tok_Is, "IS");
829 if Token = Tok_Is then
830 Set_End_Of_Line (Case_Construction);
831 Set_Previous_Line_Node (Case_Construction);
832 Set_Next_End_Node (Case_Construction);
839 Start_New_Case_Construction (In_Tree, String_Type);
843 while Token = Tok_When loop
845 if First_Case_Item then
848 (Of_Kind => N_Case_Item, In_Tree => In_Tree);
849 Set_First_Case_Item_Of
850 (Case_Construction, In_Tree, To => Current_Item);
851 First_Case_Item := False;
856 (Of_Kind => N_Case_Item, In_Tree => In_Tree);
857 Set_Next_Case_Item (Current_Item, In_Tree, To => Next_Item);
858 Current_Item := Next_Item;
861 Set_Location_Of (Current_Item, In_Tree, To => Token_Ptr);
867 if Token = Tok_Others then
870 -- Scan past "others"
874 Expect (Tok_Arrow, "`=>`");
875 Set_End_Of_Line (Current_Item);
876 Set_Previous_Line_Node (Current_Item);
878 -- Empty_Node in Field1 of a Case_Item indicates
879 -- the "when others =>" branch.
881 Set_First_Choice_Of (Current_Item, In_Tree, To => Empty_Node);
883 Parse_Declarative_Items
885 Declarations => First_Declarative_Item,
886 In_Zone => In_Case_Construction,
887 First_Attribute => First_Attribute,
888 Current_Project => Current_Project,
889 Current_Package => Current_Package,
890 Packages_To_Check => Packages_To_Check,
891 Is_Config_File => Is_Config_File,
894 -- "when others =>" must be the last branch, so save the
895 -- Case_Item and exit
897 Set_First_Declarative_Item_Of
898 (Current_Item, In_Tree, To => First_Declarative_Item);
904 First_Choice => First_Choice,
906 Set_First_Choice_Of (Current_Item, In_Tree, To => First_Choice);
908 Expect (Tok_Arrow, "`=>`");
909 Set_End_Of_Line (Current_Item);
910 Set_Previous_Line_Node (Current_Item);
912 Parse_Declarative_Items
914 Declarations => First_Declarative_Item,
915 In_Zone => In_Case_Construction,
916 First_Attribute => First_Attribute,
917 Current_Project => Current_Project,
918 Current_Package => Current_Package,
919 Packages_To_Check => Packages_To_Check,
920 Is_Config_File => Is_Config_File,
923 Set_First_Declarative_Item_Of
924 (Current_Item, In_Tree, To => First_Declarative_Item);
929 End_Case_Construction
930 (Check_All_Labels => not When_Others and not Quiet_Output,
931 Case_Location => Location_Of (Case_Construction, In_Tree),
934 Expect (Tok_End, "`END CASE`");
935 Remove_Next_End_Node;
937 if Token = Tok_End then
943 Expect (Tok_Case, "CASE");
951 Expect (Tok_Semicolon, "`;`");
952 Set_Previous_End_Node (Case_Construction);
954 end Parse_Case_Construction;
956 -----------------------------
957 -- Parse_Declarative_Items --
958 -----------------------------
960 procedure Parse_Declarative_Items
961 (In_Tree : Project_Node_Tree_Ref;
962 Declarations : out Project_Node_Id;
964 First_Attribute : Attribute_Node_Id;
965 Current_Project : Project_Node_Id;
966 Current_Package : Project_Node_Id;
967 Packages_To_Check : String_List_Access;
968 Is_Config_File : Boolean;
969 Flags : Processing_Flags)
971 Current_Declarative_Item : Project_Node_Id := Empty_Node;
972 Next_Declarative_Item : Project_Node_Id := Empty_Node;
973 Current_Declaration : Project_Node_Id := Empty_Node;
974 Item_Location : Source_Ptr := No_Location;
977 Declarations := Empty_Node;
980 -- We are always positioned at the token that precedes the first
981 -- token of the declarative element. Scan past it.
985 Item_Location := Token_Ptr;
988 when Tok_Identifier =>
990 if In_Zone = In_Case_Construction then
992 -- Check if the variable has already been declared
995 The_Variable : Project_Node_Id := Empty_Node;
998 if Present (Current_Package) then
1000 First_Variable_Of (Current_Package, In_Tree);
1001 elsif Present (Current_Project) then
1003 First_Variable_Of (Current_Project, In_Tree);
1006 while Present (The_Variable)
1007 and then Name_Of (The_Variable, In_Tree) /=
1010 The_Variable := Next_Variable (The_Variable, In_Tree);
1013 -- It is an error to declare a variable in a case
1014 -- construction for the first time.
1016 if No (The_Variable) then
1019 "a variable cannot be declared " &
1020 "for the first time here",
1026 Parse_Variable_Declaration
1028 Current_Declaration,
1029 Current_Project => Current_Project,
1030 Current_Package => Current_Package,
1033 Set_End_Of_Line (Current_Declaration);
1034 Set_Previous_Line_Node (Current_Declaration);
1038 Parse_Attribute_Declaration
1039 (In_Tree => In_Tree,
1040 Attribute => Current_Declaration,
1041 First_Attribute => First_Attribute,
1042 Current_Project => Current_Project,
1043 Current_Package => Current_Package,
1044 Packages_To_Check => Packages_To_Check,
1047 Set_End_Of_Line (Current_Declaration);
1048 Set_Previous_Line_Node (Current_Declaration);
1052 Scan (In_Tree); -- past "null"
1056 -- Package declaration
1058 if In_Zone /= In_Project then
1060 (Flags, "a package cannot be declared here", Token_Ptr);
1063 Parse_Package_Declaration
1064 (In_Tree => In_Tree,
1065 Package_Declaration => Current_Declaration,
1066 Current_Project => Current_Project,
1067 Packages_To_Check => Packages_To_Check,
1068 Is_Config_File => Is_Config_File,
1071 Set_Previous_End_Node (Current_Declaration);
1075 -- Type String Declaration
1077 if In_Zone /= In_Project then
1079 "a string type cannot be declared here",
1083 Parse_String_Type_Declaration
1084 (In_Tree => In_Tree,
1085 String_Type => Current_Declaration,
1086 Current_Project => Current_Project,
1089 Set_End_Of_Line (Current_Declaration);
1090 Set_Previous_Line_Node (Current_Declaration);
1094 -- Case construction
1096 Parse_Case_Construction
1097 (In_Tree => In_Tree,
1098 Case_Construction => Current_Declaration,
1099 First_Attribute => First_Attribute,
1100 Current_Project => Current_Project,
1101 Current_Package => Current_Package,
1102 Packages_To_Check => Packages_To_Check,
1103 Is_Config_File => Is_Config_File,
1106 Set_Previous_End_Node (Current_Declaration);
1111 -- We are leaving Parse_Declarative_Items positioned
1112 -- at the first token after the list of declarative items.
1113 -- It could be "end" (for a project, a package declaration or
1114 -- a case construction) or "when" (for a case construction)
1118 Expect (Tok_Semicolon, "`;` after declarative items");
1120 -- Insert an N_Declarative_Item in the tree, but only if
1121 -- Current_Declaration is not an empty node.
1123 if Present (Current_Declaration) then
1124 if No (Current_Declarative_Item) then
1125 Current_Declarative_Item :=
1126 Default_Project_Node
1127 (Of_Kind => N_Declarative_Item, In_Tree => In_Tree);
1128 Declarations := Current_Declarative_Item;
1131 Next_Declarative_Item :=
1132 Default_Project_Node
1133 (Of_Kind => N_Declarative_Item, In_Tree => In_Tree);
1134 Set_Next_Declarative_Item
1135 (Current_Declarative_Item, In_Tree,
1136 To => Next_Declarative_Item);
1137 Current_Declarative_Item := Next_Declarative_Item;
1140 Set_Current_Item_Node
1141 (Current_Declarative_Item, In_Tree,
1142 To => Current_Declaration);
1144 (Current_Declarative_Item, In_Tree, To => Item_Location);
1147 end Parse_Declarative_Items;
1149 -------------------------------
1150 -- Parse_Package_Declaration --
1151 -------------------------------
1153 procedure Parse_Package_Declaration
1154 (In_Tree : Project_Node_Tree_Ref;
1155 Package_Declaration : out Project_Node_Id;
1156 Current_Project : Project_Node_Id;
1157 Packages_To_Check : String_List_Access;
1158 Is_Config_File : Boolean;
1159 Flags : Processing_Flags)
1161 First_Attribute : Attribute_Node_Id := Empty_Attribute;
1162 Current_Package : Package_Node_Id := Empty_Package;
1163 First_Declarative_Item : Project_Node_Id := Empty_Node;
1164 Package_Location : constant Source_Ptr := Token_Ptr;
1165 Renaming : Boolean := False;
1166 Extending : Boolean := False;
1169 Package_Declaration :=
1170 Default_Project_Node
1171 (Of_Kind => N_Package_Declaration, In_Tree => In_Tree);
1172 Set_Location_Of (Package_Declaration, In_Tree, To => Package_Location);
1174 -- Scan past "package"
1177 Expect (Tok_Identifier, "identifier");
1179 if Token = Tok_Identifier then
1180 Set_Name_Of (Package_Declaration, In_Tree, To => Token_Name);
1182 Current_Package := Package_Node_Id_Of (Token_Name);
1184 if Current_Package = Empty_Package then
1185 if not Quiet_Output then
1187 List : constant Strings.String_List := Package_Name_List;
1189 Name : constant String := Get_Name_String (Token_Name);
1192 -- Check for possible misspelling of a known package name
1196 if Index >= List'Last then
1203 GNAT.Spelling_Checker.Is_Bad_Spelling_Of
1204 (Name, List (Index).all);
1207 -- Issue warning(s) in verbose mode or when a possible
1208 -- misspelling has been found.
1210 if Verbose_Mode or else Index /= 0 then
1214 (Name_Of (Package_Declaration, In_Tree)) &
1215 """ is not a known package name",
1220 Error_Msg -- CODEFIX
1222 "\?possible misspelling of """ &
1223 List (Index).all & """", Token_Ptr);
1228 -- Set the package declaration to "ignored" so that it is not
1229 -- processed by Prj.Proc.Process.
1231 Set_Expression_Kind_Of (Package_Declaration, In_Tree, Ignored);
1233 -- Add the unknown package in the list of packages
1235 Add_Unknown_Package (Token_Name, Current_Package);
1237 elsif Current_Package = Unknown_Package then
1239 -- Set the package declaration to "ignored" so that it is not
1240 -- processed by Prj.Proc.Process.
1242 Set_Expression_Kind_Of (Package_Declaration, In_Tree, Ignored);
1245 First_Attribute := First_Attribute_Of (Current_Package);
1249 (Package_Declaration, In_Tree, To => Current_Package);
1252 Current : Project_Node_Id :=
1253 First_Package_Of (Current_Project, In_Tree);
1256 while Present (Current)
1257 and then Name_Of (Current, In_Tree) /= Token_Name
1259 Current := Next_Package_In_Project (Current, In_Tree);
1262 if Present (Current) then
1266 Get_Name_String (Name_Of (Package_Declaration, In_Tree)) &
1267 """ is declared twice in the same project",
1271 -- Add the package to the project list
1273 Set_Next_Package_In_Project
1274 (Package_Declaration, In_Tree,
1275 To => First_Package_Of (Current_Project, In_Tree));
1276 Set_First_Package_Of
1277 (Current_Project, In_Tree, To => Package_Declaration);
1281 -- Scan past the package name
1286 Check_Package_Allowed
1287 (In_Tree, Current_Project, Package_Declaration, Flags);
1289 if Token = Tok_Renames then
1291 elsif Token = Tok_Extends then
1295 if Renaming or else Extending then
1296 if Is_Config_File then
1299 "no package rename or extension in configuration projects",
1303 -- Scan past "renames" or "extends"
1307 Expect (Tok_Identifier, "identifier");
1309 if Token = Tok_Identifier then
1311 Project_Name : constant Name_Id := Token_Name;
1313 Clause : Project_Node_Id :=
1314 First_With_Clause_Of (Current_Project, In_Tree);
1315 The_Project : Project_Node_Id := Empty_Node;
1316 Extended : constant Project_Node_Id :=
1318 (Project_Declaration_Of
1319 (Current_Project, In_Tree),
1322 while Present (Clause) loop
1323 -- Only non limited imported projects may be used in a
1324 -- renames declaration.
1327 Non_Limited_Project_Node_Of (Clause, In_Tree);
1328 exit when Present (The_Project)
1329 and then Name_Of (The_Project, In_Tree) = Project_Name;
1330 Clause := Next_With_Clause_Of (Clause, In_Tree);
1334 -- As we have not found the project in the imports, we check
1335 -- if it's the name of an eventual extended project.
1337 if Present (Extended)
1338 and then Name_Of (Extended, In_Tree) = Project_Name
1340 Set_Project_Of_Renamed_Package_Of
1341 (Package_Declaration, In_Tree, To => Extended);
1343 Error_Msg_Name_1 := Project_Name;
1346 "% is not an imported or extended project", Token_Ptr);
1349 Set_Project_Of_Renamed_Package_Of
1350 (Package_Declaration, In_Tree, To => The_Project);
1355 Expect (Tok_Dot, "`.`");
1357 if Token = Tok_Dot then
1359 Expect (Tok_Identifier, "identifier");
1361 if Token = Tok_Identifier then
1362 if Name_Of (Package_Declaration, In_Tree) /= Token_Name then
1363 Error_Msg (Flags, "not the same package name", Token_Ptr);
1365 Present (Project_Of_Renamed_Package_Of
1366 (Package_Declaration, In_Tree))
1369 Current : Project_Node_Id :=
1371 (Project_Of_Renamed_Package_Of
1372 (Package_Declaration, In_Tree),
1376 while Present (Current)
1377 and then Name_Of (Current, In_Tree) /= Token_Name
1380 Next_Package_In_Project (Current, In_Tree);
1383 if No (Current) then
1386 Get_Name_String (Token_Name) &
1387 """ is not a package declared by the project",
1400 Expect (Tok_Semicolon, "`;`");
1401 Set_End_Of_Line (Package_Declaration);
1402 Set_Previous_Line_Node (Package_Declaration);
1404 elsif Token = Tok_Is then
1405 Set_End_Of_Line (Package_Declaration);
1406 Set_Previous_Line_Node (Package_Declaration);
1407 Set_Next_End_Node (Package_Declaration);
1409 Parse_Declarative_Items
1410 (In_Tree => In_Tree,
1411 Declarations => First_Declarative_Item,
1412 In_Zone => In_Package,
1413 First_Attribute => First_Attribute,
1414 Current_Project => Current_Project,
1415 Current_Package => Package_Declaration,
1416 Packages_To_Check => Packages_To_Check,
1417 Is_Config_File => Is_Config_File,
1420 Set_First_Declarative_Item_Of
1421 (Package_Declaration, In_Tree, To => First_Declarative_Item);
1423 Expect (Tok_End, "END");
1425 if Token = Tok_End then
1432 -- We should have the name of the package after "end"
1434 Expect (Tok_Identifier, "identifier");
1436 if Token = Tok_Identifier
1437 and then Name_Of (Package_Declaration, In_Tree) /= No_Name
1438 and then Token_Name /= Name_Of (Package_Declaration, In_Tree)
1440 Error_Msg_Name_1 := Name_Of (Package_Declaration, In_Tree);
1441 Error_Msg (Flags, "expected %%", Token_Ptr);
1444 if Token /= Tok_Semicolon then
1446 -- Scan past the package name
1451 Expect (Tok_Semicolon, "`;`");
1452 Remove_Next_End_Node;
1455 Error_Msg (Flags, "expected IS", Token_Ptr);
1458 end Parse_Package_Declaration;
1460 -----------------------------------
1461 -- Parse_String_Type_Declaration --
1462 -----------------------------------
1464 procedure Parse_String_Type_Declaration
1465 (In_Tree : Project_Node_Tree_Ref;
1466 String_Type : out Project_Node_Id;
1467 Current_Project : Project_Node_Id;
1468 Flags : Processing_Flags)
1470 Current : Project_Node_Id := Empty_Node;
1471 First_String : Project_Node_Id := Empty_Node;
1475 Default_Project_Node
1476 (Of_Kind => N_String_Type_Declaration, In_Tree => In_Tree);
1478 Set_Location_Of (String_Type, In_Tree, To => Token_Ptr);
1484 Expect (Tok_Identifier, "identifier");
1486 if Token = Tok_Identifier then
1487 Set_Name_Of (String_Type, In_Tree, To => Token_Name);
1489 Current := First_String_Type_Of (Current_Project, In_Tree);
1490 while Present (Current)
1492 Name_Of (Current, In_Tree) /= Token_Name
1494 Current := Next_String_Type (Current, In_Tree);
1497 if Present (Current) then
1499 "duplicate string type name """ &
1500 Get_Name_String (Token_Name) &
1504 Current := First_Variable_Of (Current_Project, In_Tree);
1505 while Present (Current)
1506 and then Name_Of (Current, In_Tree) /= Token_Name
1508 Current := Next_Variable (Current, In_Tree);
1511 if Present (Current) then
1514 Get_Name_String (Token_Name) &
1515 """ is already a variable name", Token_Ptr);
1517 Set_Next_String_Type
1518 (String_Type, In_Tree,
1519 To => First_String_Type_Of (Current_Project, In_Tree));
1520 Set_First_String_Type_Of
1521 (Current_Project, In_Tree, To => String_Type);
1525 -- Scan past the name
1530 Expect (Tok_Is, "IS");
1532 if Token = Tok_Is then
1536 Expect (Tok_Left_Paren, "`(`");
1538 if Token = Tok_Left_Paren then
1542 Parse_String_Type_List
1543 (In_Tree => In_Tree, First_String => First_String, Flags => Flags);
1544 Set_First_Literal_String (String_Type, In_Tree, To => First_String);
1546 Expect (Tok_Right_Paren, "`)`");
1548 if Token = Tok_Right_Paren then
1552 end Parse_String_Type_Declaration;
1554 --------------------------------
1555 -- Parse_Variable_Declaration --
1556 --------------------------------
1558 procedure Parse_Variable_Declaration
1559 (In_Tree : Project_Node_Tree_Ref;
1560 Variable : out Project_Node_Id;
1561 Current_Project : Project_Node_Id;
1562 Current_Package : Project_Node_Id;
1563 Flags : Processing_Flags)
1565 Expression_Location : Source_Ptr;
1566 String_Type_Name : Name_Id := No_Name;
1567 Project_String_Type_Name : Name_Id := No_Name;
1568 Type_Location : Source_Ptr := No_Location;
1569 Project_Location : Source_Ptr := No_Location;
1570 Expression : Project_Node_Id := Empty_Node;
1571 Variable_Name : constant Name_Id := Token_Name;
1572 OK : Boolean := True;
1576 Default_Project_Node
1577 (Of_Kind => N_Variable_Declaration, In_Tree => In_Tree);
1578 Set_Name_Of (Variable, In_Tree, To => Variable_Name);
1579 Set_Location_Of (Variable, In_Tree, To => Token_Ptr);
1581 -- Scan past the variable name
1585 if Token = Tok_Colon then
1587 -- Typed string variable declaration
1590 Set_Kind_Of (Variable, In_Tree, N_Typed_Variable_Declaration);
1591 Expect (Tok_Identifier, "identifier");
1593 OK := Token = Tok_Identifier;
1596 String_Type_Name := Token_Name;
1597 Type_Location := Token_Ptr;
1600 if Token = Tok_Dot then
1601 Project_String_Type_Name := String_Type_Name;
1602 Project_Location := Type_Location;
1604 -- Scan past the dot
1607 Expect (Tok_Identifier, "identifier");
1609 if Token = Tok_Identifier then
1610 String_Type_Name := Token_Name;
1611 Type_Location := Token_Ptr;
1620 Proj : Project_Node_Id := Current_Project;
1621 Current : Project_Node_Id := Empty_Node;
1624 if Project_String_Type_Name /= No_Name then
1626 The_Project_Name_And_Node : constant
1627 Tree_Private_Part.Project_Name_And_Node :=
1628 Tree_Private_Part.Projects_Htable.Get
1629 (In_Tree.Projects_HT, Project_String_Type_Name);
1631 use Tree_Private_Part;
1634 if The_Project_Name_And_Node =
1635 Tree_Private_Part.No_Project_Name_And_Node
1638 "unknown project """ &
1640 (Project_String_Type_Name) &
1643 Current := Empty_Node;
1646 First_String_Type_Of
1647 (The_Project_Name_And_Node.Node, In_Tree);
1651 Name_Of (Current, In_Tree) /= String_Type_Name
1653 Current := Next_String_Type (Current, In_Tree);
1659 -- Look for a string type with the correct name in this
1660 -- project or in any of its ancestors.
1664 First_String_Type_Of (Proj, In_Tree);
1668 Name_Of (Current, In_Tree) /= String_Type_Name
1670 Current := Next_String_Type (Current, In_Tree);
1673 exit when Present (Current);
1675 Proj := Parent_Project_Of (Proj, In_Tree);
1676 exit when No (Proj);
1680 if No (Current) then
1682 "unknown string type """ &
1683 Get_Name_String (String_Type_Name) &
1690 (Variable, In_Tree, To => Current);
1697 Expect (Tok_Colon_Equal, "`:=`");
1699 OK := OK and then Token = Tok_Colon_Equal;
1701 if Token = Tok_Colon_Equal then
1705 -- Get the single string or string list value
1707 Expression_Location := Token_Ptr;
1710 (In_Tree => In_Tree,
1711 Expression => Expression,
1713 Current_Project => Current_Project,
1714 Current_Package => Current_Package,
1715 Optional_Index => False);
1716 Set_Expression_Of (Variable, In_Tree, To => Expression);
1718 if Present (Expression) then
1719 -- A typed string must have a single string value, not a list
1721 if Kind_Of (Variable, In_Tree) = N_Typed_Variable_Declaration
1722 and then Expression_Kind_Of (Expression, In_Tree) = List
1726 "expression must be a single string", Expression_Location);
1729 Set_Expression_Kind_Of
1731 To => Expression_Kind_Of (Expression, In_Tree));
1736 The_Variable : Project_Node_Id := Empty_Node;
1739 if Present (Current_Package) then
1740 The_Variable := First_Variable_Of (Current_Package, In_Tree);
1741 elsif Present (Current_Project) then
1742 The_Variable := First_Variable_Of (Current_Project, In_Tree);
1745 while Present (The_Variable)
1746 and then Name_Of (The_Variable, In_Tree) /= Variable_Name
1748 The_Variable := Next_Variable (The_Variable, In_Tree);
1751 if No (The_Variable) then
1752 if Present (Current_Package) then
1755 To => First_Variable_Of (Current_Package, In_Tree));
1756 Set_First_Variable_Of
1757 (Current_Package, In_Tree, To => Variable);
1759 elsif Present (Current_Project) then
1762 To => First_Variable_Of (Current_Project, In_Tree));
1763 Set_First_Variable_Of
1764 (Current_Project, In_Tree, To => Variable);
1768 if Expression_Kind_Of (Variable, In_Tree) /= Undefined then
1769 if Expression_Kind_Of (The_Variable, In_Tree) =
1772 Set_Expression_Kind_Of
1773 (The_Variable, In_Tree,
1774 To => Expression_Kind_Of (Variable, In_Tree));
1777 if Expression_Kind_Of (The_Variable, In_Tree) /=
1778 Expression_Kind_Of (Variable, In_Tree)
1781 "wrong expression kind for variable """ &
1783 (Name_Of (The_Variable, In_Tree)) &
1785 Expression_Location);
1792 end Parse_Variable_Declaration;