* gcc.dg/compat/struct-layout-1_generate.c (dg_options): New. Moved
[official-gcc.git] / gcc / ada / prj-dect.adb
blob37ae74bfb1008ceccf6738d79ad77755876f04a1
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J . D E C T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2008, 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 ------------------------------------------------------------------------------
26 with Err_Vars; use Err_Vars;
28 with GNAT.Case_Util; use GNAT.Case_Util;
29 with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
31 with Opt; use Opt;
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;
37 with Snames;
38 with Uintp; use Uintp;
40 with GNAT.Strings;
42 package body Prj.Dect is
44 use GNAT;
46 type Zone is (In_Project, In_Package, In_Case_Construction);
47 -- Used to indicate if we are parsing a package (In_Package),
48 -- a case construction (In_Case_Construction) or none of those two
49 -- (In_Project).
51 procedure Parse_Attribute_Declaration
52 (In_Tree : Project_Node_Tree_Ref;
53 Attribute : out Project_Node_Id;
54 First_Attribute : Attribute_Node_Id;
55 Current_Project : Project_Node_Id;
56 Current_Package : Project_Node_Id;
57 Packages_To_Check : String_List_Access);
58 -- Parse an attribute declaration
60 procedure Parse_Case_Construction
61 (In_Tree : Project_Node_Tree_Ref;
62 Case_Construction : out Project_Node_Id;
63 First_Attribute : Attribute_Node_Id;
64 Current_Project : Project_Node_Id;
65 Current_Package : Project_Node_Id;
66 Packages_To_Check : String_List_Access);
67 -- Parse a case construction
69 procedure Parse_Declarative_Items
70 (In_Tree : Project_Node_Tree_Ref;
71 Declarations : out Project_Node_Id;
72 In_Zone : Zone;
73 First_Attribute : Attribute_Node_Id;
74 Current_Project : Project_Node_Id;
75 Current_Package : Project_Node_Id;
76 Packages_To_Check : String_List_Access);
77 -- Parse declarative items. Depending on In_Zone, some declarative
78 -- items may be forbidden.
80 procedure Parse_Package_Declaration
81 (In_Tree : Project_Node_Tree_Ref;
82 Package_Declaration : out Project_Node_Id;
83 Current_Project : Project_Node_Id;
84 Packages_To_Check : String_List_Access);
85 -- Parse a package declaration
87 procedure Parse_String_Type_Declaration
88 (In_Tree : Project_Node_Tree_Ref;
89 String_Type : out Project_Node_Id;
90 Current_Project : Project_Node_Id);
91 -- type <name> is ( <literal_string> { , <literal_string> } ) ;
93 procedure Parse_Variable_Declaration
94 (In_Tree : Project_Node_Tree_Ref;
95 Variable : out Project_Node_Id;
96 Current_Project : Project_Node_Id;
97 Current_Package : Project_Node_Id);
98 -- Parse a variable assignment
99 -- <variable_Name> := <expression>; OR
100 -- <variable_Name> : <string_type_Name> := <string_expression>;
102 -----------
103 -- Parse --
104 -----------
106 procedure Parse
107 (In_Tree : Project_Node_Tree_Ref;
108 Declarations : out Project_Node_Id;
109 Current_Project : Project_Node_Id;
110 Extends : Project_Node_Id;
111 Packages_To_Check : String_List_Access)
113 First_Declarative_Item : Project_Node_Id := Empty_Node;
115 begin
116 Declarations :=
117 Default_Project_Node
118 (Of_Kind => N_Project_Declaration, In_Tree => In_Tree);
119 Set_Location_Of (Declarations, In_Tree, To => Token_Ptr);
120 Set_Extended_Project_Of (Declarations, In_Tree, To => Extends);
121 Set_Project_Declaration_Of (Current_Project, In_Tree, Declarations);
122 Parse_Declarative_Items
123 (Declarations => First_Declarative_Item,
124 In_Tree => In_Tree,
125 In_Zone => In_Project,
126 First_Attribute => Prj.Attr.Attribute_First,
127 Current_Project => Current_Project,
128 Current_Package => Empty_Node,
129 Packages_To_Check => Packages_To_Check);
130 Set_First_Declarative_Item_Of
131 (Declarations, In_Tree, To => First_Declarative_Item);
132 end Parse;
134 ---------------------------------
135 -- Parse_Attribute_Declaration --
136 ---------------------------------
138 procedure Parse_Attribute_Declaration
139 (In_Tree : Project_Node_Tree_Ref;
140 Attribute : out Project_Node_Id;
141 First_Attribute : Attribute_Node_Id;
142 Current_Project : Project_Node_Id;
143 Current_Package : Project_Node_Id;
144 Packages_To_Check : String_List_Access)
146 Current_Attribute : Attribute_Node_Id := First_Attribute;
147 Full_Associative_Array : Boolean := False;
148 Attribute_Name : Name_Id := No_Name;
149 Optional_Index : Boolean := False;
150 Pkg_Id : Package_Node_Id := Empty_Package;
151 Ignore : Boolean := False;
153 begin
154 Attribute :=
155 Default_Project_Node
156 (Of_Kind => N_Attribute_Declaration, In_Tree => In_Tree);
157 Set_Location_Of (Attribute, In_Tree, To => Token_Ptr);
158 Set_Previous_Line_Node (Attribute);
160 -- Scan past "for"
162 Scan (In_Tree);
164 -- Body may be an attribute name
166 if Token = Tok_Body then
167 Token := Tok_Identifier;
168 Token_Name := Snames.Name_Body;
169 end if;
171 Expect (Tok_Identifier, "identifier");
173 if Token = Tok_Identifier then
174 Attribute_Name := Token_Name;
175 Set_Name_Of (Attribute, In_Tree, To => Token_Name);
176 Set_Location_Of (Attribute, In_Tree, To => Token_Ptr);
178 -- Find the attribute
180 Current_Attribute :=
181 Attribute_Node_Id_Of (Token_Name, First_Attribute);
183 -- If the attribute cannot be found, create the attribute if inside
184 -- an unknown package.
186 if Current_Attribute = Empty_Attribute then
187 if Present (Current_Package)
188 and then Expression_Kind_Of (Current_Package, In_Tree) = Ignored
189 then
190 Pkg_Id := Package_Id_Of (Current_Package, In_Tree);
191 Add_Attribute (Pkg_Id, Token_Name, Current_Attribute);
193 else
194 -- If not a valid attribute name, issue an error if inside
195 -- a package that need to be checked.
197 Ignore := Present (Current_Package) and then
198 Packages_To_Check /= All_Packages;
200 if Ignore then
202 -- Check that we are not in a package to check
204 Get_Name_String (Name_Of (Current_Package, In_Tree));
206 for Index in Packages_To_Check'Range loop
207 if Name_Buffer (1 .. Name_Len) =
208 Packages_To_Check (Index).all
209 then
210 Ignore := False;
211 exit;
212 end if;
213 end loop;
214 end if;
216 if not Ignore then
217 Error_Msg_Name_1 := Token_Name;
218 Error_Msg ("undefined attribute %%", Token_Ptr);
219 end if;
220 end if;
222 -- Set, if appropriate the index case insensitivity flag
224 else
225 if Is_Read_Only (Current_Attribute) then
226 Error_Msg_Name_1 := Token_Name;
227 Error_Msg
228 ("read-only attribute %% cannot be given a value",
229 Token_Ptr);
230 end if;
232 if Attribute_Kind_Of (Current_Attribute) in
233 Case_Insensitive_Associative_Array ..
234 Optional_Index_Case_Insensitive_Associative_Array
235 then
236 Set_Case_Insensitive (Attribute, In_Tree, To => True);
237 end if;
238 end if;
240 Scan (In_Tree); -- past the attribute name
241 end if;
243 -- Change obsolete names of attributes to the new names
245 if Present (Current_Package)
246 and then Expression_Kind_Of (Current_Package, In_Tree) /= Ignored
247 then
248 case Name_Of (Attribute, In_Tree) is
249 when Snames.Name_Specification =>
250 Set_Name_Of (Attribute, In_Tree, To => Snames.Name_Spec);
252 when Snames.Name_Specification_Suffix =>
253 Set_Name_Of (Attribute, In_Tree, To => Snames.Name_Spec_Suffix);
255 when Snames.Name_Implementation =>
256 Set_Name_Of (Attribute, In_Tree, To => Snames.Name_Body);
258 when Snames.Name_Implementation_Suffix =>
259 Set_Name_Of (Attribute, In_Tree, To => Snames.Name_Body_Suffix);
261 when others =>
262 null;
263 end case;
264 end if;
266 -- Associative array attributes
268 if Token = Tok_Left_Paren then
270 -- If the attribute is not an associative array attribute, report
271 -- an error. If this information is still unknown, set the kind
272 -- to Associative_Array.
274 if Current_Attribute /= Empty_Attribute
275 and then Attribute_Kind_Of (Current_Attribute) = Single
276 then
277 Error_Msg ("the attribute """ &
278 Get_Name_String
279 (Attribute_Name_Of (Current_Attribute)) &
280 """ cannot be an associative array",
281 Location_Of (Attribute, In_Tree));
283 elsif Attribute_Kind_Of (Current_Attribute) = Unknown then
284 Set_Attribute_Kind_Of (Current_Attribute, To => Associative_Array);
285 end if;
287 Scan (In_Tree); -- past the left parenthesis
289 if Others_Allowed_For (Current_Attribute)
290 and then Token = Tok_Others
291 then
292 Set_Associative_Array_Index_Of
293 (Attribute, In_Tree, All_Other_Names);
294 Scan (In_Tree); -- past others
296 else
297 if Others_Allowed_For (Current_Attribute) then
298 Expect (Tok_String_Literal, "literal string or others");
299 else
300 Expect (Tok_String_Literal, "literal string");
301 end if;
303 if Token = Tok_String_Literal then
304 Get_Name_String (Token_Name);
306 if Case_Insensitive (Attribute, In_Tree) then
307 To_Lower (Name_Buffer (1 .. Name_Len));
308 end if;
310 Set_Associative_Array_Index_Of (Attribute, In_Tree, Name_Find);
311 Scan (In_Tree); -- past the literal string index
313 if Token = Tok_At then
314 case Attribute_Kind_Of (Current_Attribute) is
315 when Optional_Index_Associative_Array |
316 Optional_Index_Case_Insensitive_Associative_Array =>
317 Scan (In_Tree);
318 Expect (Tok_Integer_Literal, "integer literal");
320 if Token = Tok_Integer_Literal then
322 -- Set the source index value from given literal
324 declare
325 Index : constant Int :=
326 UI_To_Int (Int_Literal_Value);
327 begin
328 if Index = 0 then
329 Error_Msg ("index cannot be zero", Token_Ptr);
330 else
331 Set_Source_Index_Of
332 (Attribute, In_Tree, To => Index);
333 end if;
334 end;
336 Scan (In_Tree);
337 end if;
339 when others =>
340 Error_Msg ("index not allowed here", Token_Ptr);
341 Scan (In_Tree);
343 if Token = Tok_Integer_Literal then
344 Scan (In_Tree);
345 end if;
346 end case;
347 end if;
348 end if;
349 end if;
351 Expect (Tok_Right_Paren, "`)`");
353 if Token = Tok_Right_Paren then
354 Scan (In_Tree); -- past the right parenthesis
355 end if;
357 else
358 -- If it is an associative array attribute and there are no left
359 -- parenthesis, then this is a full associative array declaration.
360 -- Flag it as such for later processing of its value.
362 if Current_Attribute /= Empty_Attribute
363 and then
364 Attribute_Kind_Of (Current_Attribute) /= Single
365 then
366 if Attribute_Kind_Of (Current_Attribute) = Unknown then
367 Set_Attribute_Kind_Of (Current_Attribute, To => Single);
369 else
370 Full_Associative_Array := True;
371 end if;
372 end if;
373 end if;
375 -- Set the expression kind of the attribute
377 if Current_Attribute /= Empty_Attribute then
378 Set_Expression_Kind_Of
379 (Attribute, In_Tree, To => Variable_Kind_Of (Current_Attribute));
380 Optional_Index := Optional_Index_Of (Current_Attribute);
381 end if;
383 Expect (Tok_Use, "USE");
385 if Token = Tok_Use then
386 Scan (In_Tree);
388 if Full_Associative_Array then
390 -- Expect <project>'<same_attribute_name>, or
391 -- <project>.<same_package_name>'<same_attribute_name>
393 declare
394 The_Project : Project_Node_Id := Empty_Node;
395 -- The node of the project where the associative array is
396 -- declared.
398 The_Package : Project_Node_Id := Empty_Node;
399 -- The node of the package where the associative array is
400 -- declared, if any.
402 Project_Name : Name_Id := No_Name;
403 -- The name of the project where the associative array is
404 -- declared.
406 Location : Source_Ptr := No_Location;
407 -- The location of the project name
409 begin
410 Expect (Tok_Identifier, "identifier");
412 if Token = Tok_Identifier then
413 Location := Token_Ptr;
415 -- Find the project node in the imported project or
416 -- in the project being extended.
418 The_Project := Imported_Or_Extended_Project_Of
419 (Current_Project, In_Tree, Token_Name);
421 if No (The_Project) then
422 Error_Msg ("unknown project", Location);
423 Scan (In_Tree); -- past the project name
425 else
426 Project_Name := Token_Name;
427 Scan (In_Tree); -- past the project name
429 -- If this is inside a package, a dot followed by the
430 -- name of the package must followed the project name.
432 if Present (Current_Package) then
433 Expect (Tok_Dot, "`.`");
435 if Token /= Tok_Dot then
436 The_Project := Empty_Node;
438 else
439 Scan (In_Tree); -- past the dot
440 Expect (Tok_Identifier, "identifier");
442 if Token /= Tok_Identifier then
443 The_Project := Empty_Node;
445 -- If it is not the same package name, issue error
447 elsif
448 Token_Name /= Name_Of (Current_Package, In_Tree)
449 then
450 The_Project := Empty_Node;
451 Error_Msg
452 ("not the same package as " &
453 Get_Name_String
454 (Name_Of (Current_Package, In_Tree)),
455 Token_Ptr);
457 else
458 The_Package :=
459 First_Package_Of (The_Project, In_Tree);
461 -- Look for the package node
463 while Present (The_Package)
464 and then
465 Name_Of (The_Package, In_Tree) /= Token_Name
466 loop
467 The_Package :=
468 Next_Package_In_Project
469 (The_Package, In_Tree);
470 end loop;
472 -- If the package cannot be found in the
473 -- project, issue an error.
475 if No (The_Package) then
476 The_Project := Empty_Node;
477 Error_Msg_Name_2 := Project_Name;
478 Error_Msg_Name_1 := Token_Name;
479 Error_Msg
480 ("package % not declared in project %",
481 Token_Ptr);
482 end if;
484 Scan (In_Tree); -- past the package name
485 end if;
486 end if;
487 end if;
488 end if;
489 end if;
491 if Present (The_Project) then
493 -- Looking for '<same attribute name>
495 Expect (Tok_Apostrophe, "`''`");
497 if Token /= Tok_Apostrophe then
498 The_Project := Empty_Node;
500 else
501 Scan (In_Tree); -- past the apostrophe
502 Expect (Tok_Identifier, "identifier");
504 if Token /= Tok_Identifier then
505 The_Project := Empty_Node;
507 else
508 -- If it is not the same attribute name, issue error
510 if Token_Name /= Attribute_Name then
511 The_Project := Empty_Node;
512 Error_Msg_Name_1 := Attribute_Name;
513 Error_Msg ("invalid name, should be %", Token_Ptr);
514 end if;
516 Scan (In_Tree); -- past the attribute name
517 end if;
518 end if;
519 end if;
521 if No (The_Project) then
523 -- If there were any problem, set the attribute id to null,
524 -- so that the node will not be recorded.
526 Current_Attribute := Empty_Attribute;
528 else
529 -- Set the appropriate field in the node.
530 -- Note that the index and the expression are nil. This
531 -- characterizes full associative array attribute
532 -- declarations.
534 Set_Associative_Project_Of (Attribute, In_Tree, The_Project);
535 Set_Associative_Package_Of (Attribute, In_Tree, The_Package);
536 end if;
537 end;
539 -- Other attribute declarations (not full associative array)
541 else
542 declare
543 Expression_Location : constant Source_Ptr := Token_Ptr;
544 -- The location of the first token of the expression
546 Expression : Project_Node_Id := Empty_Node;
547 -- The expression, value for the attribute declaration
549 begin
550 -- Get the expression value and set it in the attribute node
552 Parse_Expression
553 (In_Tree => In_Tree,
554 Expression => Expression,
555 Current_Project => Current_Project,
556 Current_Package => Current_Package,
557 Optional_Index => Optional_Index);
558 Set_Expression_Of (Attribute, In_Tree, To => Expression);
560 -- If the expression is legal, but not of the right kind
561 -- for the attribute, issue an error.
563 if Current_Attribute /= Empty_Attribute
564 and then Present (Expression)
565 and then Variable_Kind_Of (Current_Attribute) /=
566 Expression_Kind_Of (Expression, In_Tree)
567 then
568 if Variable_Kind_Of (Current_Attribute) = Undefined then
569 Set_Variable_Kind_Of
570 (Current_Attribute,
571 To => Expression_Kind_Of (Expression, In_Tree));
573 else
574 Error_Msg
575 ("wrong expression kind for attribute """ &
576 Get_Name_String
577 (Attribute_Name_Of (Current_Attribute)) &
578 """",
579 Expression_Location);
580 end if;
581 end if;
582 end;
583 end if;
584 end if;
586 -- If the attribute was not recognized, return an empty node.
587 -- It may be that it is not in a package to check, and the node will
588 -- not be added to the tree.
590 if Current_Attribute = Empty_Attribute then
591 Attribute := Empty_Node;
592 end if;
594 Set_End_Of_Line (Attribute);
595 Set_Previous_Line_Node (Attribute);
596 end Parse_Attribute_Declaration;
598 -----------------------------
599 -- Parse_Case_Construction --
600 -----------------------------
602 procedure Parse_Case_Construction
603 (In_Tree : Project_Node_Tree_Ref;
604 Case_Construction : out Project_Node_Id;
605 First_Attribute : Attribute_Node_Id;
606 Current_Project : Project_Node_Id;
607 Current_Package : Project_Node_Id;
608 Packages_To_Check : String_List_Access)
610 Current_Item : Project_Node_Id := Empty_Node;
611 Next_Item : Project_Node_Id := Empty_Node;
612 First_Case_Item : Boolean := True;
614 Variable_Location : Source_Ptr := No_Location;
616 String_Type : Project_Node_Id := Empty_Node;
618 Case_Variable : Project_Node_Id := Empty_Node;
620 First_Declarative_Item : Project_Node_Id := Empty_Node;
622 First_Choice : Project_Node_Id := Empty_Node;
624 When_Others : Boolean := False;
625 -- Set to True when there is a "when others =>" clause
627 begin
628 Case_Construction :=
629 Default_Project_Node
630 (Of_Kind => N_Case_Construction, In_Tree => In_Tree);
631 Set_Location_Of (Case_Construction, In_Tree, To => Token_Ptr);
633 -- Scan past "case"
635 Scan (In_Tree);
637 -- Get the switch variable
639 Expect (Tok_Identifier, "identifier");
641 if Token = Tok_Identifier then
642 Variable_Location := Token_Ptr;
643 Parse_Variable_Reference
644 (In_Tree => In_Tree,
645 Variable => Case_Variable,
646 Current_Project => Current_Project,
647 Current_Package => Current_Package);
648 Set_Case_Variable_Reference_Of
649 (Case_Construction, In_Tree, To => Case_Variable);
651 else
652 if Token /= Tok_Is then
653 Scan (In_Tree);
654 end if;
655 end if;
657 if Present (Case_Variable) then
658 String_Type := String_Type_Of (Case_Variable, In_Tree);
660 if No (String_Type) then
661 Error_Msg ("variable """ &
662 Get_Name_String (Name_Of (Case_Variable, In_Tree)) &
663 """ is not typed",
664 Variable_Location);
665 end if;
666 end if;
668 Expect (Tok_Is, "IS");
670 if Token = Tok_Is then
671 Set_End_Of_Line (Case_Construction);
672 Set_Previous_Line_Node (Case_Construction);
673 Set_Next_End_Node (Case_Construction);
675 -- Scan past "is"
677 Scan (In_Tree);
678 end if;
680 Start_New_Case_Construction (In_Tree, String_Type);
682 When_Loop :
684 while Token = Tok_When loop
686 if First_Case_Item then
687 Current_Item :=
688 Default_Project_Node
689 (Of_Kind => N_Case_Item, In_Tree => In_Tree);
690 Set_First_Case_Item_Of
691 (Case_Construction, In_Tree, To => Current_Item);
692 First_Case_Item := False;
694 else
695 Next_Item :=
696 Default_Project_Node
697 (Of_Kind => N_Case_Item, In_Tree => In_Tree);
698 Set_Next_Case_Item (Current_Item, In_Tree, To => Next_Item);
699 Current_Item := Next_Item;
700 end if;
702 Set_Location_Of (Current_Item, In_Tree, To => Token_Ptr);
704 -- Scan past "when"
706 Scan (In_Tree);
708 if Token = Tok_Others then
709 When_Others := True;
711 -- Scan past "others"
713 Scan (In_Tree);
715 Expect (Tok_Arrow, "`=>`");
716 Set_End_Of_Line (Current_Item);
717 Set_Previous_Line_Node (Current_Item);
719 -- Empty_Node in Field1 of a Case_Item indicates
720 -- the "when others =>" branch.
722 Set_First_Choice_Of (Current_Item, In_Tree, To => Empty_Node);
724 Parse_Declarative_Items
725 (In_Tree => In_Tree,
726 Declarations => First_Declarative_Item,
727 In_Zone => In_Case_Construction,
728 First_Attribute => First_Attribute,
729 Current_Project => Current_Project,
730 Current_Package => Current_Package,
731 Packages_To_Check => Packages_To_Check);
733 -- "when others =>" must be the last branch, so save the
734 -- Case_Item and exit
736 Set_First_Declarative_Item_Of
737 (Current_Item, In_Tree, To => First_Declarative_Item);
738 exit When_Loop;
740 else
741 Parse_Choice_List
742 (In_Tree => In_Tree,
743 First_Choice => First_Choice);
744 Set_First_Choice_Of (Current_Item, In_Tree, To => First_Choice);
746 Expect (Tok_Arrow, "`=>`");
747 Set_End_Of_Line (Current_Item);
748 Set_Previous_Line_Node (Current_Item);
750 Parse_Declarative_Items
751 (In_Tree => In_Tree,
752 Declarations => First_Declarative_Item,
753 In_Zone => In_Case_Construction,
754 First_Attribute => First_Attribute,
755 Current_Project => Current_Project,
756 Current_Package => Current_Package,
757 Packages_To_Check => Packages_To_Check);
759 Set_First_Declarative_Item_Of
760 (Current_Item, In_Tree, To => First_Declarative_Item);
762 end if;
763 end loop When_Loop;
765 End_Case_Construction
766 (Check_All_Labels => not When_Others and not Quiet_Output,
767 Case_Location => Location_Of (Case_Construction, In_Tree));
769 Expect (Tok_End, "`END CASE`");
770 Remove_Next_End_Node;
772 if Token = Tok_End then
774 -- Scan past "end"
776 Scan (In_Tree);
778 Expect (Tok_Case, "CASE");
780 end if;
782 -- Scan past "case"
784 Scan (In_Tree);
786 Expect (Tok_Semicolon, "`;`");
787 Set_Previous_End_Node (Case_Construction);
789 end Parse_Case_Construction;
791 -----------------------------
792 -- Parse_Declarative_Items --
793 -----------------------------
795 procedure Parse_Declarative_Items
796 (In_Tree : Project_Node_Tree_Ref;
797 Declarations : out Project_Node_Id;
798 In_Zone : Zone;
799 First_Attribute : Attribute_Node_Id;
800 Current_Project : Project_Node_Id;
801 Current_Package : Project_Node_Id;
802 Packages_To_Check : String_List_Access)
804 Current_Declarative_Item : Project_Node_Id := Empty_Node;
805 Next_Declarative_Item : Project_Node_Id := Empty_Node;
806 Current_Declaration : Project_Node_Id := Empty_Node;
807 Item_Location : Source_Ptr := No_Location;
809 begin
810 Declarations := Empty_Node;
812 loop
813 -- We are always positioned at the token that precedes the first
814 -- token of the declarative element. Scan past it.
816 Scan (In_Tree);
818 Item_Location := Token_Ptr;
820 case Token is
821 when Tok_Identifier =>
823 if In_Zone = In_Case_Construction then
825 -- Check if the variable has already been declared
827 declare
828 The_Variable : Project_Node_Id := Empty_Node;
830 begin
831 if Present (Current_Package) then
832 The_Variable :=
833 First_Variable_Of (Current_Package, In_Tree);
834 elsif Present (Current_Project) then
835 The_Variable :=
836 First_Variable_Of (Current_Project, In_Tree);
837 end if;
839 while Present (The_Variable)
840 and then Name_Of (The_Variable, In_Tree) /=
841 Token_Name
842 loop
843 The_Variable := Next_Variable (The_Variable, In_Tree);
844 end loop;
846 -- It is an error to declare a variable in a case
847 -- construction for the first time.
849 if No (The_Variable) then
850 Error_Msg
851 ("a variable cannot be declared " &
852 "for the first time here",
853 Token_Ptr);
854 end if;
855 end;
856 end if;
858 Parse_Variable_Declaration
859 (In_Tree,
860 Current_Declaration,
861 Current_Project => Current_Project,
862 Current_Package => Current_Package);
864 Set_End_Of_Line (Current_Declaration);
865 Set_Previous_Line_Node (Current_Declaration);
867 when Tok_For =>
869 Parse_Attribute_Declaration
870 (In_Tree => In_Tree,
871 Attribute => Current_Declaration,
872 First_Attribute => First_Attribute,
873 Current_Project => Current_Project,
874 Current_Package => Current_Package,
875 Packages_To_Check => Packages_To_Check);
877 Set_End_Of_Line (Current_Declaration);
878 Set_Previous_Line_Node (Current_Declaration);
880 when Tok_Null =>
882 Scan (In_Tree); -- past "null"
884 when Tok_Package =>
886 -- Package declaration
888 if In_Zone /= In_Project then
889 Error_Msg ("a package cannot be declared here", Token_Ptr);
890 end if;
892 Parse_Package_Declaration
893 (In_Tree => In_Tree,
894 Package_Declaration => Current_Declaration,
895 Current_Project => Current_Project,
896 Packages_To_Check => Packages_To_Check);
898 Set_Previous_End_Node (Current_Declaration);
900 when Tok_Type =>
902 -- Type String Declaration
904 if In_Zone /= In_Project then
905 Error_Msg ("a string type cannot be declared here",
906 Token_Ptr);
907 end if;
909 Parse_String_Type_Declaration
910 (In_Tree => In_Tree,
911 String_Type => Current_Declaration,
912 Current_Project => Current_Project);
914 Set_End_Of_Line (Current_Declaration);
915 Set_Previous_Line_Node (Current_Declaration);
917 when Tok_Case =>
919 -- Case construction
921 Parse_Case_Construction
922 (In_Tree => In_Tree,
923 Case_Construction => Current_Declaration,
924 First_Attribute => First_Attribute,
925 Current_Project => Current_Project,
926 Current_Package => Current_Package,
927 Packages_To_Check => Packages_To_Check);
929 Set_Previous_End_Node (Current_Declaration);
931 when others =>
932 exit;
934 -- We are leaving Parse_Declarative_Items positioned
935 -- at the first token after the list of declarative items.
936 -- It could be "end" (for a project, a package declaration or
937 -- a case construction) or "when" (for a case construction)
939 end case;
941 Expect (Tok_Semicolon, "`;` after declarative items");
943 -- Insert an N_Declarative_Item in the tree, but only if
944 -- Current_Declaration is not an empty node.
946 if Present (Current_Declaration) then
947 if No (Current_Declarative_Item) then
948 Current_Declarative_Item :=
949 Default_Project_Node
950 (Of_Kind => N_Declarative_Item, In_Tree => In_Tree);
951 Declarations := Current_Declarative_Item;
953 else
954 Next_Declarative_Item :=
955 Default_Project_Node
956 (Of_Kind => N_Declarative_Item, In_Tree => In_Tree);
957 Set_Next_Declarative_Item
958 (Current_Declarative_Item, In_Tree,
959 To => Next_Declarative_Item);
960 Current_Declarative_Item := Next_Declarative_Item;
961 end if;
963 Set_Current_Item_Node
964 (Current_Declarative_Item, In_Tree,
965 To => Current_Declaration);
966 Set_Location_Of
967 (Current_Declarative_Item, In_Tree, To => Item_Location);
968 end if;
969 end loop;
970 end Parse_Declarative_Items;
972 -------------------------------
973 -- Parse_Package_Declaration --
974 -------------------------------
976 procedure Parse_Package_Declaration
977 (In_Tree : Project_Node_Tree_Ref;
978 Package_Declaration : out Project_Node_Id;
979 Current_Project : Project_Node_Id;
980 Packages_To_Check : String_List_Access)
982 First_Attribute : Attribute_Node_Id := Empty_Attribute;
983 Current_Package : Package_Node_Id := Empty_Package;
984 First_Declarative_Item : Project_Node_Id := Empty_Node;
986 Package_Location : constant Source_Ptr := Token_Ptr;
988 begin
989 Package_Declaration :=
990 Default_Project_Node
991 (Of_Kind => N_Package_Declaration, In_Tree => In_Tree);
992 Set_Location_Of (Package_Declaration, In_Tree, To => Package_Location);
994 -- Scan past "package"
996 Scan (In_Tree);
997 Expect (Tok_Identifier, "identifier");
999 if Token = Tok_Identifier then
1000 Set_Name_Of (Package_Declaration, In_Tree, To => Token_Name);
1002 Current_Package := Package_Node_Id_Of (Token_Name);
1004 if Current_Package = Empty_Package then
1005 if not Quiet_Output then
1006 declare
1007 List : constant Strings.String_List := Package_Name_List;
1008 Index : Natural;
1009 Name : constant String := Get_Name_String (Token_Name);
1011 begin
1012 -- Check for possible misspelling of a known package name
1014 Index := 0;
1015 loop
1016 if Index >= List'Last then
1017 Index := 0;
1018 exit;
1019 end if;
1021 Index := Index + 1;
1022 exit when
1023 GNAT.Spelling_Checker.Is_Bad_Spelling_Of
1024 (Name, List (Index).all);
1025 end loop;
1027 -- Issue warning(s) in verbose mode or when a possible
1028 -- misspelling has been found.
1030 if Verbose_Mode or else Index /= 0 then
1031 Error_Msg ("?""" &
1032 Get_Name_String
1033 (Name_Of (Package_Declaration, In_Tree)) &
1034 """ is not a known package name",
1035 Token_Ptr);
1036 end if;
1038 if Index /= 0 then
1039 Error_Msg ("\?possible misspelling of """ &
1040 List (Index).all & """",
1041 Token_Ptr);
1042 end if;
1043 end;
1044 end if;
1046 -- Set the package declaration to "ignored" so that it is not
1047 -- processed by Prj.Proc.Process.
1049 Set_Expression_Kind_Of (Package_Declaration, In_Tree, Ignored);
1051 -- Add the unknown package in the list of packages
1053 Add_Unknown_Package (Token_Name, Current_Package);
1055 elsif Current_Package = Unknown_Package then
1057 -- Set the package declaration to "ignored" so that it is not
1058 -- processed by Prj.Proc.Process.
1060 Set_Expression_Kind_Of (Package_Declaration, In_Tree, Ignored);
1062 else
1063 First_Attribute := First_Attribute_Of (Current_Package);
1064 end if;
1066 Set_Package_Id_Of
1067 (Package_Declaration, In_Tree, To => Current_Package);
1069 declare
1070 Current : Project_Node_Id :=
1071 First_Package_Of (Current_Project, In_Tree);
1073 begin
1074 while Present (Current)
1075 and then Name_Of (Current, In_Tree) /= Token_Name
1076 loop
1077 Current := Next_Package_In_Project (Current, In_Tree);
1078 end loop;
1080 if Present (Current) then
1081 Error_Msg
1082 ("package """ &
1083 Get_Name_String (Name_Of (Package_Declaration, In_Tree)) &
1084 """ is declared twice in the same project",
1085 Token_Ptr);
1087 else
1088 -- Add the package to the project list
1090 Set_Next_Package_In_Project
1091 (Package_Declaration, In_Tree,
1092 To => First_Package_Of (Current_Project, In_Tree));
1093 Set_First_Package_Of
1094 (Current_Project, In_Tree, To => Package_Declaration);
1095 end if;
1096 end;
1098 -- Scan past the package name
1100 Scan (In_Tree);
1101 end if;
1103 if Token = Tok_Renames then
1104 if In_Configuration then
1105 Error_Msg
1106 ("no package renames in configuration projects", Token_Ptr);
1107 end if;
1109 -- Scan past "renames"
1111 Scan (In_Tree);
1113 Expect (Tok_Identifier, "identifier");
1115 if Token = Tok_Identifier then
1116 declare
1117 Project_Name : constant Name_Id := Token_Name;
1119 Clause : Project_Node_Id :=
1120 First_With_Clause_Of (Current_Project, In_Tree);
1121 The_Project : Project_Node_Id := Empty_Node;
1122 Extended : constant Project_Node_Id :=
1123 Extended_Project_Of
1124 (Project_Declaration_Of
1125 (Current_Project, In_Tree),
1126 In_Tree);
1127 begin
1128 while Present (Clause) loop
1129 -- Only non limited imported projects may be used in a
1130 -- renames declaration.
1132 The_Project :=
1133 Non_Limited_Project_Node_Of (Clause, In_Tree);
1134 exit when Present (The_Project)
1135 and then Name_Of (The_Project, In_Tree) = Project_Name;
1136 Clause := Next_With_Clause_Of (Clause, In_Tree);
1137 end loop;
1139 if No (Clause) then
1140 -- As we have not found the project in the imports, we check
1141 -- if it's the name of an eventual extended project.
1143 if Present (Extended)
1144 and then Name_Of (Extended, In_Tree) = Project_Name
1145 then
1146 Set_Project_Of_Renamed_Package_Of
1147 (Package_Declaration, In_Tree, To => Extended);
1148 else
1149 Error_Msg_Name_1 := Project_Name;
1150 Error_Msg
1151 ("% is not an imported or extended project", Token_Ptr);
1152 end if;
1153 else
1154 Set_Project_Of_Renamed_Package_Of
1155 (Package_Declaration, In_Tree, To => The_Project);
1156 end if;
1157 end;
1159 Scan (In_Tree);
1160 Expect (Tok_Dot, "`.`");
1162 if Token = Tok_Dot then
1163 Scan (In_Tree);
1164 Expect (Tok_Identifier, "identifier");
1166 if Token = Tok_Identifier then
1167 if Name_Of (Package_Declaration, In_Tree) /= Token_Name then
1168 Error_Msg ("not the same package name", Token_Ptr);
1169 elsif
1170 Present (Project_Of_Renamed_Package_Of
1171 (Package_Declaration, In_Tree))
1172 then
1173 declare
1174 Current : Project_Node_Id :=
1175 First_Package_Of
1176 (Project_Of_Renamed_Package_Of
1177 (Package_Declaration, In_Tree),
1178 In_Tree);
1180 begin
1181 while Present (Current)
1182 and then Name_Of (Current, In_Tree) /= Token_Name
1183 loop
1184 Current :=
1185 Next_Package_In_Project (Current, In_Tree);
1186 end loop;
1188 if No (Current) then
1189 Error_Msg
1190 ("""" &
1191 Get_Name_String (Token_Name) &
1192 """ is not a package declared by the project",
1193 Token_Ptr);
1194 end if;
1195 end;
1196 end if;
1198 Scan (In_Tree);
1199 end if;
1200 end if;
1201 end if;
1203 Expect (Tok_Semicolon, "`;`");
1204 Set_End_Of_Line (Package_Declaration);
1205 Set_Previous_Line_Node (Package_Declaration);
1207 elsif Token = Tok_Is then
1208 Set_End_Of_Line (Package_Declaration);
1209 Set_Previous_Line_Node (Package_Declaration);
1210 Set_Next_End_Node (Package_Declaration);
1212 Parse_Declarative_Items
1213 (In_Tree => In_Tree,
1214 Declarations => First_Declarative_Item,
1215 In_Zone => In_Package,
1216 First_Attribute => First_Attribute,
1217 Current_Project => Current_Project,
1218 Current_Package => Package_Declaration,
1219 Packages_To_Check => Packages_To_Check);
1221 Set_First_Declarative_Item_Of
1222 (Package_Declaration, In_Tree, To => First_Declarative_Item);
1224 Expect (Tok_End, "END");
1226 if Token = Tok_End then
1228 -- Scan past "end"
1230 Scan (In_Tree);
1231 end if;
1233 -- We should have the name of the package after "end"
1235 Expect (Tok_Identifier, "identifier");
1237 if Token = Tok_Identifier
1238 and then Name_Of (Package_Declaration, In_Tree) /= No_Name
1239 and then Token_Name /= Name_Of (Package_Declaration, In_Tree)
1240 then
1241 Error_Msg_Name_1 := Name_Of (Package_Declaration, In_Tree);
1242 Error_Msg ("expected %%", Token_Ptr);
1243 end if;
1245 if Token /= Tok_Semicolon then
1247 -- Scan past the package name
1249 Scan (In_Tree);
1250 end if;
1252 Expect (Tok_Semicolon, "`;`");
1253 Remove_Next_End_Node;
1255 else
1256 Error_Msg ("expected IS or RENAMES", Token_Ptr);
1257 end if;
1259 end Parse_Package_Declaration;
1261 -----------------------------------
1262 -- Parse_String_Type_Declaration --
1263 -----------------------------------
1265 procedure Parse_String_Type_Declaration
1266 (In_Tree : Project_Node_Tree_Ref;
1267 String_Type : out Project_Node_Id;
1268 Current_Project : Project_Node_Id)
1270 Current : Project_Node_Id := Empty_Node;
1271 First_String : Project_Node_Id := Empty_Node;
1273 begin
1274 String_Type :=
1275 Default_Project_Node
1276 (Of_Kind => N_String_Type_Declaration, In_Tree => In_Tree);
1278 Set_Location_Of (String_Type, In_Tree, To => Token_Ptr);
1280 -- Scan past "type"
1282 Scan (In_Tree);
1284 Expect (Tok_Identifier, "identifier");
1286 if Token = Tok_Identifier then
1287 Set_Name_Of (String_Type, In_Tree, To => Token_Name);
1289 Current := First_String_Type_Of (Current_Project, In_Tree);
1290 while Present (Current)
1291 and then
1292 Name_Of (Current, In_Tree) /= Token_Name
1293 loop
1294 Current := Next_String_Type (Current, In_Tree);
1295 end loop;
1297 if Present (Current) then
1298 Error_Msg ("duplicate string type name """ &
1299 Get_Name_String (Token_Name) &
1300 """",
1301 Token_Ptr);
1302 else
1303 Current := First_Variable_Of (Current_Project, In_Tree);
1304 while Present (Current)
1305 and then Name_Of (Current, In_Tree) /= Token_Name
1306 loop
1307 Current := Next_Variable (Current, In_Tree);
1308 end loop;
1310 if Present (Current) then
1311 Error_Msg ("""" &
1312 Get_Name_String (Token_Name) &
1313 """ is already a variable name", Token_Ptr);
1314 else
1315 Set_Next_String_Type
1316 (String_Type, In_Tree,
1317 To => First_String_Type_Of (Current_Project, In_Tree));
1318 Set_First_String_Type_Of
1319 (Current_Project, In_Tree, To => String_Type);
1320 end if;
1321 end if;
1323 -- Scan past the name
1325 Scan (In_Tree);
1326 end if;
1328 Expect (Tok_Is, "IS");
1330 if Token = Tok_Is then
1331 Scan (In_Tree);
1332 end if;
1334 Expect (Tok_Left_Paren, "`(`");
1336 if Token = Tok_Left_Paren then
1337 Scan (In_Tree);
1338 end if;
1340 Parse_String_Type_List
1341 (In_Tree => In_Tree, First_String => First_String);
1342 Set_First_Literal_String (String_Type, In_Tree, To => First_String);
1344 Expect (Tok_Right_Paren, "`)`");
1346 if Token = Tok_Right_Paren then
1347 Scan (In_Tree);
1348 end if;
1350 end Parse_String_Type_Declaration;
1352 --------------------------------
1353 -- Parse_Variable_Declaration --
1354 --------------------------------
1356 procedure Parse_Variable_Declaration
1357 (In_Tree : Project_Node_Tree_Ref;
1358 Variable : out Project_Node_Id;
1359 Current_Project : Project_Node_Id;
1360 Current_Package : Project_Node_Id)
1362 Expression_Location : Source_Ptr;
1363 String_Type_Name : Name_Id := No_Name;
1364 Project_String_Type_Name : Name_Id := No_Name;
1365 Type_Location : Source_Ptr := No_Location;
1366 Project_Location : Source_Ptr := No_Location;
1367 Expression : Project_Node_Id := Empty_Node;
1368 Variable_Name : constant Name_Id := Token_Name;
1369 OK : Boolean := True;
1371 begin
1372 Variable :=
1373 Default_Project_Node
1374 (Of_Kind => N_Variable_Declaration, In_Tree => In_Tree);
1375 Set_Name_Of (Variable, In_Tree, To => Variable_Name);
1376 Set_Location_Of (Variable, In_Tree, To => Token_Ptr);
1378 -- Scan past the variable name
1380 Scan (In_Tree);
1382 if Token = Tok_Colon then
1384 -- Typed string variable declaration
1386 Scan (In_Tree);
1387 Set_Kind_Of (Variable, In_Tree, N_Typed_Variable_Declaration);
1388 Expect (Tok_Identifier, "identifier");
1390 OK := Token = Tok_Identifier;
1392 if OK then
1393 String_Type_Name := Token_Name;
1394 Type_Location := Token_Ptr;
1395 Scan (In_Tree);
1397 if Token = Tok_Dot then
1398 Project_String_Type_Name := String_Type_Name;
1399 Project_Location := Type_Location;
1401 -- Scan past the dot
1403 Scan (In_Tree);
1404 Expect (Tok_Identifier, "identifier");
1406 if Token = Tok_Identifier then
1407 String_Type_Name := Token_Name;
1408 Type_Location := Token_Ptr;
1409 Scan (In_Tree);
1410 else
1411 OK := False;
1412 end if;
1413 end if;
1415 if OK then
1416 declare
1417 Proj : Project_Node_Id := Current_Project;
1418 Current : Project_Node_Id := Empty_Node;
1420 begin
1421 if Project_String_Type_Name /= No_Name then
1422 declare
1423 The_Project_Name_And_Node : constant
1424 Tree_Private_Part.Project_Name_And_Node :=
1425 Tree_Private_Part.Projects_Htable.Get
1426 (In_Tree.Projects_HT, Project_String_Type_Name);
1428 use Tree_Private_Part;
1430 begin
1431 if The_Project_Name_And_Node =
1432 Tree_Private_Part.No_Project_Name_And_Node
1433 then
1434 Error_Msg ("unknown project """ &
1435 Get_Name_String
1436 (Project_String_Type_Name) &
1437 """",
1438 Project_Location);
1439 Current := Empty_Node;
1440 else
1441 Current :=
1442 First_String_Type_Of
1443 (The_Project_Name_And_Node.Node, In_Tree);
1444 while
1445 Present (Current)
1446 and then
1447 Name_Of (Current, In_Tree) /= String_Type_Name
1448 loop
1449 Current := Next_String_Type (Current, In_Tree);
1450 end loop;
1451 end if;
1452 end;
1454 else
1455 -- Look for a string type with the correct name in this
1456 -- project or in any of its ancestors.
1458 loop
1459 Current :=
1460 First_String_Type_Of (Proj, In_Tree);
1461 while
1462 Present (Current)
1463 and then
1464 Name_Of (Current, In_Tree) /= String_Type_Name
1465 loop
1466 Current := Next_String_Type (Current, In_Tree);
1467 end loop;
1469 exit when Present (Current);
1471 Proj := Parent_Project_Of (Proj, In_Tree);
1472 exit when No (Proj);
1473 end loop;
1474 end if;
1476 if No (Current) then
1477 Error_Msg ("unknown string type """ &
1478 Get_Name_String (String_Type_Name) &
1479 """",
1480 Type_Location);
1481 OK := False;
1483 else
1484 Set_String_Type_Of
1485 (Variable, In_Tree, To => Current);
1486 end if;
1487 end;
1488 end if;
1489 end if;
1490 end if;
1492 Expect (Tok_Colon_Equal, "`:=`");
1494 OK := OK and (Token = Tok_Colon_Equal);
1496 if Token = Tok_Colon_Equal then
1497 Scan (In_Tree);
1498 end if;
1500 -- Get the single string or string list value
1502 Expression_Location := Token_Ptr;
1504 Parse_Expression
1505 (In_Tree => In_Tree,
1506 Expression => Expression,
1507 Current_Project => Current_Project,
1508 Current_Package => Current_Package,
1509 Optional_Index => False);
1510 Set_Expression_Of (Variable, In_Tree, To => Expression);
1512 if Present (Expression) then
1513 -- A typed string must have a single string value, not a list
1515 if Kind_Of (Variable, In_Tree) = N_Typed_Variable_Declaration
1516 and then Expression_Kind_Of (Expression, In_Tree) = List
1517 then
1518 Error_Msg
1519 ("expression must be a single string", Expression_Location);
1520 end if;
1522 Set_Expression_Kind_Of
1523 (Variable, In_Tree,
1524 To => Expression_Kind_Of (Expression, In_Tree));
1525 end if;
1527 if OK then
1528 declare
1529 The_Variable : Project_Node_Id := Empty_Node;
1531 begin
1532 if Present (Current_Package) then
1533 The_Variable := First_Variable_Of (Current_Package, In_Tree);
1534 elsif Present (Current_Project) then
1535 The_Variable := First_Variable_Of (Current_Project, In_Tree);
1536 end if;
1538 while Present (The_Variable)
1539 and then Name_Of (The_Variable, In_Tree) /= Variable_Name
1540 loop
1541 The_Variable := Next_Variable (The_Variable, In_Tree);
1542 end loop;
1544 if No (The_Variable) then
1545 if Present (Current_Package) then
1546 Set_Next_Variable
1547 (Variable, In_Tree,
1548 To => First_Variable_Of (Current_Package, In_Tree));
1549 Set_First_Variable_Of
1550 (Current_Package, In_Tree, To => Variable);
1552 elsif Present (Current_Project) then
1553 Set_Next_Variable
1554 (Variable, In_Tree,
1555 To => First_Variable_Of (Current_Project, In_Tree));
1556 Set_First_Variable_Of
1557 (Current_Project, In_Tree, To => Variable);
1558 end if;
1560 else
1561 if Expression_Kind_Of (Variable, In_Tree) /= Undefined then
1562 if Expression_Kind_Of (The_Variable, In_Tree) =
1563 Undefined
1564 then
1565 Set_Expression_Kind_Of
1566 (The_Variable, In_Tree,
1567 To => Expression_Kind_Of (Variable, In_Tree));
1569 else
1570 if Expression_Kind_Of (The_Variable, In_Tree) /=
1571 Expression_Kind_Of (Variable, In_Tree)
1572 then
1573 Error_Msg ("wrong expression kind for variable """ &
1574 Get_Name_String
1575 (Name_Of (The_Variable, In_Tree)) &
1576 """",
1577 Expression_Location);
1578 end if;
1579 end if;
1580 end if;
1581 end if;
1582 end;
1583 end if;
1584 end Parse_Variable_Declaration;
1586 end Prj.Dect;