2005-12-29 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / ada / prj-strt.adb
blobb1388079719527156d316c7cf3dfbc66fff6a74f
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J . S T R T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2005, 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 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 -- --
25 ------------------------------------------------------------------------------
27 with Err_Vars; use Err_Vars;
28 with Namet; use Namet;
29 with Prj.Attr; use Prj.Attr;
30 with Prj.Err; use Prj.Err;
31 with Snames;
32 with Table;
33 with Uintp; use Uintp;
35 package body Prj.Strt is
37 Buffer : String_Access;
38 Buffer_Last : Natural := 0;
40 type Choice_String is record
41 The_String : Name_Id;
42 Already_Used : Boolean := False;
43 end record;
44 -- The string of a case label, and an indication that it has already
45 -- been used (to avoid duplicate case labels).
47 Choices_Initial : constant := 10;
48 Choices_Increment : constant := 50;
50 Choice_Node_Low_Bound : constant := 0;
51 Choice_Node_High_Bound : constant := 099_999_999;
52 -- In practice, infinite
54 type Choice_Node_Id is
55 range Choice_Node_Low_Bound .. Choice_Node_High_Bound;
57 First_Choice_Node_Id : constant Choice_Node_Id :=
58 Choice_Node_Low_Bound;
60 package Choices is
61 new Table.Table (Table_Component_Type => Choice_String,
62 Table_Index_Type => Choice_Node_Id,
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
70 new Table.Table (Table_Component_Type => Choice_Node_Id,
71 Table_Index_Type => Nat,
72 Table_Low_Bound => 1,
73 Table_Initial => 10,
74 Table_Increment => 100,
75 Table_Name => "Prj.Strt.Choice_Lasts");
76 -- Used to store the indices of the choices in table Choices,
77 -- to distinguish nested case constructions.
79 Choice_First : Choice_Node_Id := 0;
80 -- Index in table Choices of the first case label of the current
81 -- case construction. Zero means no current case construction.
83 type Name_Location is record
84 Name : Name_Id := No_Name;
85 Location : Source_Ptr := No_Location;
86 end record;
87 -- Store the identifier and the location of a simple name
89 package Names is
90 new Table.Table (Table_Component_Type => Name_Location,
91 Table_Index_Type => Nat,
92 Table_Low_Bound => 1,
93 Table_Initial => 10,
94 Table_Increment => 100,
95 Table_Name => "Prj.Strt.Names");
96 -- Used to accumulate the single names of a name
98 procedure Add (This_String : Name_Id);
99 -- Add a string to the case label list, indicating that it has not
100 -- yet been used.
102 procedure Add_To_Names (NL : Name_Location);
103 -- Add one single names to table Names
105 procedure External_Reference
106 (In_Tree : Project_Node_Tree_Ref;
107 Current_Project : Project_Node_Id;
108 Current_Package : Project_Node_Id;
109 External_Value : out Project_Node_Id);
110 -- Parse an external reference. Current token is "external"
112 procedure Attribute_Reference
113 (In_Tree : Project_Node_Tree_Ref;
114 Reference : out Project_Node_Id;
115 First_Attribute : Attribute_Node_Id;
116 Current_Project : Project_Node_Id;
117 Current_Package : Project_Node_Id);
118 -- Parse an attribute reference. Current token is an apostrophe
120 procedure Terms
121 (In_Tree : Project_Node_Tree_Ref;
122 Term : out Project_Node_Id;
123 Expr_Kind : in out Variable_Kind;
124 Current_Project : Project_Node_Id;
125 Current_Package : Project_Node_Id;
126 Optional_Index : Boolean);
127 -- Recursive procedure to parse one term or several terms concatenated
128 -- using "&".
130 ---------
131 -- Add --
132 ---------
134 procedure Add (This_String : Name_Id) is
135 begin
136 Choices.Increment_Last;
137 Choices.Table (Choices.Last) :=
138 (The_String => This_String,
139 Already_Used => False);
140 end Add;
142 ------------------
143 -- Add_To_Names --
144 ------------------
146 procedure Add_To_Names (NL : Name_Location) is
147 begin
148 Names.Increment_Last;
149 Names.Table (Names.Last) := NL;
150 end Add_To_Names;
152 -------------------------
153 -- Attribute_Reference --
154 -------------------------
156 procedure Attribute_Reference
157 (In_Tree : Project_Node_Tree_Ref;
158 Reference : out Project_Node_Id;
159 First_Attribute : Attribute_Node_Id;
160 Current_Project : Project_Node_Id;
161 Current_Package : Project_Node_Id)
163 Current_Attribute : Attribute_Node_Id := First_Attribute;
165 begin
166 -- Declare the node of the attribute reference
168 Reference :=
169 Default_Project_Node
170 (Of_Kind => N_Attribute_Reference, In_Tree => In_Tree);
171 Set_Location_Of (Reference, In_Tree, To => Token_Ptr);
172 Scan (In_Tree); -- past apostrophe
174 -- Body may be an attribute name
176 if Token = Tok_Body then
177 Token := Tok_Identifier;
178 Token_Name := Snames.Name_Body;
179 end if;
181 Expect (Tok_Identifier, "identifier");
183 if Token = Tok_Identifier then
184 Set_Name_Of (Reference, In_Tree, To => Token_Name);
186 -- Check if the identifier is one of the attribute identifiers in the
187 -- context (package or project level attributes).
189 Current_Attribute :=
190 Attribute_Node_Id_Of (Token_Name, Starting_At => First_Attribute);
192 -- If the identifier is not allowed, report an error
194 if Current_Attribute = Empty_Attribute then
195 Error_Msg_Name_1 := Token_Name;
196 Error_Msg ("unknown attribute %", Token_Ptr);
197 Reference := Empty_Node;
199 -- Scan past the attribute name
201 Scan (In_Tree);
203 else
204 -- Give its characteristics to this attribute reference
206 Set_Project_Node_Of (Reference, In_Tree, To => Current_Project);
207 Set_Package_Node_Of (Reference, In_Tree, To => Current_Package);
208 Set_Expression_Kind_Of
209 (Reference, In_Tree, To => Variable_Kind_Of (Current_Attribute));
210 Set_Case_Insensitive
211 (Reference, In_Tree,
212 To => Attribute_Kind_Of (Current_Attribute) =
213 Case_Insensitive_Associative_Array);
215 -- Scan past the attribute name
217 Scan (In_Tree);
219 -- If the attribute is an associative array, get the index
221 if Attribute_Kind_Of (Current_Attribute) /= Single then
222 Expect (Tok_Left_Paren, "`(`");
224 if Token = Tok_Left_Paren then
225 Scan (In_Tree);
226 Expect (Tok_String_Literal, "literal string");
228 if Token = Tok_String_Literal then
229 Set_Associative_Array_Index_Of
230 (Reference, In_Tree, To => Token_Name);
231 Scan (In_Tree);
232 Expect (Tok_Right_Paren, "`)`");
234 if Token = Tok_Right_Paren then
235 Scan (In_Tree);
236 end if;
237 end if;
238 end if;
239 end if;
240 end if;
242 -- Change name of obsolete attributes
244 if Reference /= Empty_Node then
245 case Name_Of (Reference, In_Tree) is
246 when Snames.Name_Specification =>
247 Set_Name_Of (Reference, In_Tree, To => Snames.Name_Spec);
249 when Snames.Name_Specification_Suffix =>
250 Set_Name_Of
251 (Reference, In_Tree, To => Snames.Name_Spec_Suffix);
253 when Snames.Name_Implementation =>
254 Set_Name_Of (Reference, In_Tree, To => Snames.Name_Body);
256 when Snames.Name_Implementation_Suffix =>
257 Set_Name_Of
258 (Reference, In_Tree, To => Snames.Name_Body_Suffix);
260 when others =>
261 null;
262 end case;
263 end if;
264 end if;
265 end Attribute_Reference;
267 ---------------------------
268 -- End_Case_Construction --
269 ---------------------------
271 procedure End_Case_Construction
272 (Check_All_Labels : Boolean;
273 Case_Location : Source_Ptr)
275 Non_Used : Natural := 0;
276 First_Non_Used : Choice_Node_Id := First_Choice_Node_Id;
277 begin
278 -- First, if Check_All_Labels is True, check if all values
279 -- of the string type have been used.
281 if Check_All_Labels then
282 for Choice in Choice_First .. Choices.Last loop
283 if not Choices.Table (Choice).Already_Used then
284 Non_Used := Non_Used + 1;
286 if Non_Used = 1 then
287 First_Non_Used := Choice;
288 end if;
289 end if;
290 end loop;
292 -- If only one is not used, report a single warning for this value
294 if Non_Used = 1 then
295 Error_Msg_Name_1 := Choices.Table (First_Non_Used).The_String;
296 Error_Msg ("?value { is not used as label", Case_Location);
298 -- If several are not used, report a warning for each one of them
300 elsif Non_Used > 1 then
301 Error_Msg
302 ("?the following values are not used as labels:",
303 Case_Location);
305 for Choice in First_Non_Used .. Choices.Last loop
306 if not Choices.Table (Choice).Already_Used then
307 Error_Msg_Name_1 := Choices.Table (Choice).The_String;
308 Error_Msg ("\?{", Case_Location);
309 end if;
310 end loop;
311 end if;
312 end if;
314 -- If this is the only case construction, empty the tables
316 if Choice_Lasts.Last = 1 then
317 Choice_Lasts.Set_Last (0);
318 Choices.Set_Last (First_Choice_Node_Id);
319 Choice_First := 0;
321 elsif Choice_Lasts.Last = 2 then
322 -- This is the second case onstruction, set the tables to the first
324 Choice_Lasts.Set_Last (1);
325 Choices.Set_Last (Choice_Lasts.Table (1));
326 Choice_First := 1;
328 else
329 -- This is the 3rd or more case construction, set the tables to the
330 -- previous one.
332 Choice_Lasts.Decrement_Last;
333 Choices.Set_Last (Choice_Lasts.Table (Choice_Lasts.Last));
334 Choice_First := Choice_Lasts.Table (Choice_Lasts.Last - 1) + 1;
335 end if;
336 end End_Case_Construction;
338 ------------------------
339 -- External_Reference --
340 ------------------------
342 procedure External_Reference
343 (In_Tree : Project_Node_Tree_Ref;
344 Current_Project : Project_Node_Id;
345 Current_Package : Project_Node_Id;
346 External_Value : out Project_Node_Id)
348 Field_Id : Project_Node_Id := Empty_Node;
350 begin
351 External_Value :=
352 Default_Project_Node
353 (Of_Kind => N_External_Value,
354 In_Tree => In_Tree,
355 And_Expr_Kind => Single);
356 Set_Location_Of (External_Value, In_Tree, To => Token_Ptr);
358 -- The current token is External
360 -- Get the left parenthesis
362 Scan (In_Tree);
363 Expect (Tok_Left_Paren, "`(`");
365 -- Scan past the left parenthesis
367 if Token = Tok_Left_Paren then
368 Scan (In_Tree);
369 end if;
371 -- Get the name of the external reference
373 Expect (Tok_String_Literal, "literal string");
375 if Token = Tok_String_Literal then
376 Field_Id :=
377 Default_Project_Node
378 (Of_Kind => N_Literal_String,
379 In_Tree => In_Tree,
380 And_Expr_Kind => Single);
381 Set_String_Value_Of (Field_Id, In_Tree, To => Token_Name);
382 Set_External_Reference_Of (External_Value, In_Tree, To => Field_Id);
384 -- Scan past the first argument
386 Scan (In_Tree);
388 case Token is
390 when Tok_Right_Paren =>
392 -- Scan past the right parenthesis
393 Scan (In_Tree);
395 when Tok_Comma =>
397 -- Scan past the comma
399 Scan (In_Tree);
401 -- Get the string expression for the default
403 declare
404 Loc : constant Source_Ptr := Token_Ptr;
406 begin
407 Parse_Expression
408 (In_Tree => In_Tree,
409 Expression => Field_Id,
410 Current_Project => Current_Project,
411 Current_Package => Current_Package,
412 Optional_Index => False);
414 if Expression_Kind_Of (Field_Id, In_Tree) = List then
415 Error_Msg ("expression must be a single string", Loc);
416 else
417 Set_External_Default_Of
418 (External_Value, In_Tree, To => Field_Id);
419 end if;
420 end;
422 Expect (Tok_Right_Paren, "`)`");
424 -- Scan past the right parenthesis
426 if Token = Tok_Right_Paren then
427 Scan (In_Tree);
428 end if;
430 when others =>
431 Error_Msg ("`,` or `)` expected", Token_Ptr);
432 end case;
433 end if;
434 end External_Reference;
436 -----------------------
437 -- Parse_Choice_List --
438 -----------------------
440 procedure Parse_Choice_List
441 (In_Tree : Project_Node_Tree_Ref;
442 First_Choice : out Project_Node_Id)
444 Current_Choice : Project_Node_Id := Empty_Node;
445 Next_Choice : Project_Node_Id := Empty_Node;
446 Choice_String : Name_Id := No_Name;
447 Found : Boolean := False;
449 begin
450 -- Declare the node of the first choice
452 First_Choice :=
453 Default_Project_Node
454 (Of_Kind => N_Literal_String,
455 In_Tree => In_Tree,
456 And_Expr_Kind => Single);
458 -- Initially Current_Choice is the same as First_Choice
460 Current_Choice := First_Choice;
462 loop
463 Expect (Tok_String_Literal, "literal string");
464 exit when Token /= Tok_String_Literal;
465 Set_Location_Of (Current_Choice, In_Tree, To => Token_Ptr);
466 Choice_String := Token_Name;
468 -- Give the string value to the current choice
470 Set_String_Value_Of (Current_Choice, In_Tree, To => Choice_String);
472 -- Check if the label is part of the string type and if it has not
473 -- been already used.
475 Found := False;
476 for Choice in Choice_First .. Choices.Last loop
477 if Choices.Table (Choice).The_String = Choice_String then
478 -- This label is part of the string type
480 Found := True;
482 if Choices.Table (Choice).Already_Used then
483 -- But it has already appeared in a choice list for this
484 -- case construction; report an error.
486 Error_Msg_Name_1 := Choice_String;
487 Error_Msg ("duplicate case label {", Token_Ptr);
488 else
489 Choices.Table (Choice).Already_Used := True;
490 end if;
492 exit;
493 end if;
494 end loop;
496 -- If the label is not part of the string list, report an error
498 if not Found then
499 Error_Msg_Name_1 := Choice_String;
500 Error_Msg ("illegal case label {", Token_Ptr);
501 end if;
503 -- Scan past the label
505 Scan (In_Tree);
507 -- If there is no '|', we are done
509 if Token = Tok_Vertical_Bar then
510 -- Otherwise, declare the node of the next choice, link it to
511 -- Current_Choice and set Current_Choice to this new node.
513 Next_Choice :=
514 Default_Project_Node
515 (Of_Kind => N_Literal_String,
516 In_Tree => In_Tree,
517 And_Expr_Kind => Single);
518 Set_Next_Literal_String
519 (Current_Choice, In_Tree, To => Next_Choice);
520 Current_Choice := Next_Choice;
521 Scan (In_Tree);
522 else
523 exit;
524 end if;
525 end loop;
526 end Parse_Choice_List;
528 ----------------------
529 -- Parse_Expression --
530 ----------------------
532 procedure Parse_Expression
533 (In_Tree : Project_Node_Tree_Ref;
534 Expression : out Project_Node_Id;
535 Current_Project : Project_Node_Id;
536 Current_Package : Project_Node_Id;
537 Optional_Index : Boolean)
539 First_Term : Project_Node_Id := Empty_Node;
540 Expression_Kind : Variable_Kind := Undefined;
542 begin
543 -- Declare the node of the expression
545 Expression :=
546 Default_Project_Node (Of_Kind => N_Expression, In_Tree => In_Tree);
547 Set_Location_Of (Expression, In_Tree, To => Token_Ptr);
549 -- Parse the term or terms of the expression
551 Terms (In_Tree => In_Tree,
552 Term => First_Term,
553 Expr_Kind => Expression_Kind,
554 Current_Project => Current_Project,
555 Current_Package => Current_Package,
556 Optional_Index => Optional_Index);
558 -- Set the first term and the expression kind
560 Set_First_Term (Expression, In_Tree, To => First_Term);
561 Set_Expression_Kind_Of (Expression, In_Tree, To => Expression_Kind);
562 end Parse_Expression;
564 ----------------------------
565 -- Parse_String_Type_List --
566 ----------------------------
568 procedure Parse_String_Type_List
569 (In_Tree : Project_Node_Tree_Ref;
570 First_String : out Project_Node_Id)
572 Last_String : Project_Node_Id := Empty_Node;
573 Next_String : Project_Node_Id := Empty_Node;
574 String_Value : Name_Id := No_Name;
576 begin
577 -- Declare the node of the first string
579 First_String :=
580 Default_Project_Node
581 (Of_Kind => N_Literal_String,
582 In_Tree => In_Tree,
583 And_Expr_Kind => Single);
585 -- Initially, Last_String is the same as First_String
587 Last_String := First_String;
589 loop
590 Expect (Tok_String_Literal, "literal string");
591 exit when Token /= Tok_String_Literal;
592 String_Value := Token_Name;
594 -- Give its string value to Last_String
596 Set_String_Value_Of (Last_String, In_Tree, To => String_Value);
597 Set_Location_Of (Last_String, In_Tree, To => Token_Ptr);
599 -- Now, check if the string is already part of the string type
601 declare
602 Current : Project_Node_Id := First_String;
604 begin
605 while Current /= Last_String loop
606 if String_Value_Of (Current, In_Tree) = String_Value then
607 -- This is a repetition, report an error
609 Error_Msg_Name_1 := String_Value;
610 Error_Msg ("duplicate value { in type", Token_Ptr);
611 exit;
612 end if;
614 Current := Next_Literal_String (Current, In_Tree);
615 end loop;
616 end;
618 -- Scan past the literal string
620 Scan (In_Tree);
622 -- If there is no comma following the literal string, we are done
624 if Token /= Tok_Comma then
625 exit;
627 else
628 -- Declare the next string, link it to Last_String and set
629 -- Last_String to its node.
631 Next_String :=
632 Default_Project_Node
633 (Of_Kind => N_Literal_String,
634 In_Tree => In_Tree,
635 And_Expr_Kind => Single);
636 Set_Next_Literal_String (Last_String, In_Tree, To => Next_String);
637 Last_String := Next_String;
638 Scan (In_Tree);
639 end if;
640 end loop;
641 end Parse_String_Type_List;
643 ------------------------------
644 -- Parse_Variable_Reference --
645 ------------------------------
647 procedure Parse_Variable_Reference
648 (In_Tree : Project_Node_Tree_Ref;
649 Variable : out Project_Node_Id;
650 Current_Project : Project_Node_Id;
651 Current_Package : Project_Node_Id)
653 Current_Variable : Project_Node_Id := Empty_Node;
655 The_Package : Project_Node_Id := Current_Package;
656 The_Project : Project_Node_Id := Current_Project;
658 Specified_Project : Project_Node_Id := Empty_Node;
659 Specified_Package : Project_Node_Id := Empty_Node;
660 Look_For_Variable : Boolean := True;
661 First_Attribute : Attribute_Node_Id := Empty_Attribute;
662 Variable_Name : Name_Id;
664 begin
665 Names.Init;
667 loop
668 Expect (Tok_Identifier, "identifier");
670 if Token /= Tok_Identifier then
671 Look_For_Variable := False;
672 exit;
673 end if;
675 Add_To_Names (NL => (Name => Token_Name, Location => Token_Ptr));
676 Scan (In_Tree);
677 exit when Token /= Tok_Dot;
678 Scan (In_Tree);
679 end loop;
681 if Look_For_Variable then
683 if Token = Tok_Apostrophe then
685 -- Attribute reference
687 case Names.Last is
688 when 0 =>
690 -- Cannot happen
692 null;
694 when 1 =>
695 -- This may be a project name or a package name.
696 -- Project name have precedence.
698 -- First, look if it can be a package name
700 First_Attribute :=
701 First_Attribute_Of
702 (Package_Node_Id_Of (Names.Table (1).Name));
704 -- Now, look if it can be a project name
706 The_Project := Imported_Or_Extended_Project_Of
707 (Current_Project, In_Tree, Names.Table (1).Name);
709 if The_Project = Empty_Node then
710 -- If it is neither a project name nor a package name,
711 -- report an error
713 if First_Attribute = Empty_Attribute then
714 Error_Msg_Name_1 := Names.Table (1).Name;
715 Error_Msg ("unknown project %",
716 Names.Table (1).Location);
717 First_Attribute := Attribute_First;
719 else
720 -- If it is a package name, check if the package
721 -- has already been declared in the current project.
723 The_Package :=
724 First_Package_Of (Current_Project, In_Tree);
726 while The_Package /= Empty_Node
727 and then Name_Of (The_Package, In_Tree) /=
728 Names.Table (1).Name
729 loop
730 The_Package :=
731 Next_Package_In_Project (The_Package, In_Tree);
732 end loop;
734 -- If it has not been already declared, report an
735 -- error.
737 if The_Package = Empty_Node then
738 Error_Msg_Name_1 := Names.Table (1).Name;
739 Error_Msg ("package % not yet defined",
740 Names.Table (1).Location);
741 end if;
742 end if;
744 else
745 -- It is a project name
747 First_Attribute := Attribute_First;
748 The_Package := Empty_Node;
749 end if;
751 when others =>
753 -- We have either a project name made of several simple
754 -- names (long project), or a project name (short project)
755 -- followed by a package name. The long project name has
756 -- precedence.
758 declare
759 Short_Project : Name_Id;
760 Long_Project : Name_Id;
762 begin
763 -- Clear the Buffer
765 Buffer_Last := 0;
767 -- Get the name of the short project
769 for Index in 1 .. Names.Last - 1 loop
770 Add_To_Buffer
771 (Get_Name_String (Names.Table (Index).Name),
772 Buffer, Buffer_Last);
774 if Index /= Names.Last - 1 then
775 Add_To_Buffer (".", Buffer, Buffer_Last);
776 end if;
777 end loop;
779 Name_Len := Buffer_Last;
780 Name_Buffer (1 .. Buffer_Last) :=
781 Buffer (1 .. Buffer_Last);
782 Short_Project := Name_Find;
784 -- Now, add the last simple name to get the name of the
785 -- long project.
787 Add_To_Buffer (".", Buffer, Buffer_Last);
788 Add_To_Buffer
789 (Get_Name_String (Names.Table (Names.Last).Name),
790 Buffer, Buffer_Last);
791 Name_Len := Buffer_Last;
792 Name_Buffer (1 .. Buffer_Last) :=
793 Buffer (1 .. Buffer_Last);
794 Long_Project := Name_Find;
796 -- Check if the long project is imported or extended
798 The_Project := Imported_Or_Extended_Project_Of
799 (Current_Project, In_Tree, Long_Project);
801 -- If the long project exists, then this is the prefix
802 -- of the attribute.
804 if The_Project /= Empty_Node then
805 First_Attribute := Attribute_First;
806 The_Package := Empty_Node;
808 else
809 -- Otherwise, check if the short project is imported
810 -- or extended.
812 The_Project := Imported_Or_Extended_Project_Of
813 (Current_Project, In_Tree,
814 Short_Project);
816 -- If the short project does not exist, we report an
817 -- error.
819 if The_Project = Empty_Node then
820 Error_Msg_Name_1 := Long_Project;
821 Error_Msg_Name_2 := Short_Project;
822 Error_Msg ("unknown projects % or %",
823 Names.Table (1).Location);
824 The_Package := Empty_Node;
825 First_Attribute := Attribute_First;
827 else
828 -- Now, we check if the package has been declared
829 -- in this project.
831 The_Package :=
832 First_Package_Of (The_Project, In_Tree);
833 while The_Package /= Empty_Node
834 and then Name_Of (The_Package, In_Tree) /=
835 Names.Table (Names.Last).Name
836 loop
837 The_Package :=
838 Next_Package_In_Project (The_Package, In_Tree);
839 end loop;
841 -- If it has not, then we report an error
843 if The_Package = Empty_Node then
844 Error_Msg_Name_1 :=
845 Names.Table (Names.Last).Name;
846 Error_Msg_Name_2 := Short_Project;
847 Error_Msg ("package % not declared in project %",
848 Names.Table (Names.Last).Location);
849 First_Attribute := Attribute_First;
851 else
852 -- Otherwise, we have the correct project and
853 -- package.
855 First_Attribute :=
856 First_Attribute_Of
857 (Package_Id_Of (The_Package, In_Tree));
858 end if;
859 end if;
860 end if;
861 end;
862 end case;
864 Attribute_Reference
865 (In_Tree,
866 Variable,
867 Current_Project => The_Project,
868 Current_Package => The_Package,
869 First_Attribute => First_Attribute);
870 return;
871 end if;
872 end if;
874 Variable :=
875 Default_Project_Node
876 (Of_Kind => N_Variable_Reference, In_Tree => In_Tree);
878 if Look_For_Variable then
879 case Names.Last is
880 when 0 =>
882 -- Cannot happen
884 null;
886 when 1 =>
888 -- Simple variable name
890 Set_Name_Of (Variable, In_Tree, To => Names.Table (1).Name);
892 when 2 =>
894 -- Variable name with a simple name prefix that can be
895 -- a project name or a package name. Project names have
896 -- priority over package names.
898 Set_Name_Of (Variable, In_Tree, To => Names.Table (2).Name);
900 -- Check if it can be a package name
902 The_Package := First_Package_Of (Current_Project, In_Tree);
904 while The_Package /= Empty_Node
905 and then Name_Of (The_Package, In_Tree) /=
906 Names.Table (1).Name
907 loop
908 The_Package :=
909 Next_Package_In_Project (The_Package, In_Tree);
910 end loop;
912 -- Now look for a possible project name
914 The_Project := Imported_Or_Extended_Project_Of
915 (Current_Project, In_Tree, Names.Table (1).Name);
917 if The_Project /= Empty_Node then
918 Specified_Project := The_Project;
920 elsif The_Package = Empty_Node then
921 Error_Msg_Name_1 := Names.Table (1).Name;
922 Error_Msg ("unknown package or project %",
923 Names.Table (1).Location);
924 Look_For_Variable := False;
926 else
927 Specified_Package := The_Package;
928 end if;
930 when others =>
932 -- Variable name with a prefix that is either a project name
933 -- made of several simple names, or a project name followed
934 -- by a package name.
936 Set_Name_Of
937 (Variable, In_Tree, To => Names.Table (Names.Last).Name);
939 declare
940 Short_Project : Name_Id;
941 Long_Project : Name_Id;
943 begin
944 -- First, we get the two possible project names
946 -- Clear the buffer
948 Buffer_Last := 0;
950 -- Add all the simple names, except the last two
952 for Index in 1 .. Names.Last - 2 loop
953 Add_To_Buffer
954 (Get_Name_String (Names.Table (Index).Name),
955 Buffer, Buffer_Last);
957 if Index /= Names.Last - 2 then
958 Add_To_Buffer (".", Buffer, Buffer_Last);
959 end if;
960 end loop;
962 Name_Len := Buffer_Last;
963 Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last);
964 Short_Project := Name_Find;
966 -- Add the simple name before the name of the variable
968 Add_To_Buffer (".", Buffer, Buffer_Last);
969 Add_To_Buffer
970 (Get_Name_String (Names.Table (Names.Last - 1).Name),
971 Buffer, Buffer_Last);
972 Name_Len := Buffer_Last;
973 Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last);
974 Long_Project := Name_Find;
976 -- Check if the prefix is the name of an imported or
977 -- extended project.
979 The_Project := Imported_Or_Extended_Project_Of
980 (Current_Project, In_Tree, Long_Project);
982 if The_Project /= Empty_Node then
983 Specified_Project := The_Project;
985 else
986 -- Now check if the prefix may be a project name followed
987 -- by a package name.
989 -- First check for a possible project name
991 The_Project := Imported_Or_Extended_Project_Of
992 (Current_Project, In_Tree, Short_Project);
994 if The_Project = Empty_Node then
995 -- Unknown prefix, report an error
997 Error_Msg_Name_1 := Long_Project;
998 Error_Msg_Name_2 := Short_Project;
999 Error_Msg ("unknown projects % or %",
1000 Names.Table (1).Location);
1001 Look_For_Variable := False;
1003 else
1004 Specified_Project := The_Project;
1006 -- Now look for the package in this project
1008 The_Package := First_Package_Of (The_Project, In_Tree);
1010 while The_Package /= Empty_Node
1011 and then Name_Of (The_Package, In_Tree) /=
1012 Names.Table (Names.Last - 1).Name
1013 loop
1014 The_Package :=
1015 Next_Package_In_Project (The_Package, In_Tree);
1016 end loop;
1018 if The_Package = Empty_Node then
1019 -- The package does not vexist, report an error
1021 Error_Msg_Name_1 := Names.Table (2).Name;
1022 Error_Msg ("unknown package %",
1023 Names.Table (Names.Last - 1).Location);
1024 Look_For_Variable := False;
1026 else
1027 Specified_Package := The_Package;
1028 end if;
1029 end if;
1030 end if;
1031 end;
1032 end case;
1033 end if;
1035 if Look_For_Variable then
1036 Variable_Name := Name_Of (Variable, In_Tree);
1037 Set_Project_Node_Of (Variable, In_Tree, To => Specified_Project);
1038 Set_Package_Node_Of (Variable, In_Tree, To => Specified_Package);
1040 if Specified_Project /= Empty_Node then
1041 The_Project := Specified_Project;
1043 else
1044 The_Project := Current_Project;
1045 end if;
1047 Current_Variable := Empty_Node;
1049 -- Look for this variable
1051 -- If a package was specified, check if the variable has been
1052 -- declared in this package.
1054 if Specified_Package /= Empty_Node then
1055 Current_Variable :=
1056 First_Variable_Of (Specified_Package, In_Tree);
1058 while Current_Variable /= Empty_Node
1059 and then
1060 Name_Of (Current_Variable, In_Tree) /= Variable_Name
1061 loop
1062 Current_Variable := Next_Variable (Current_Variable, In_Tree);
1063 end loop;
1065 else
1066 -- Otherwise, if no project has been specified and we are in
1067 -- a package, first check if the variable has been declared in
1068 -- the package.
1070 if Specified_Project = Empty_Node
1071 and then Current_Package /= Empty_Node
1072 then
1073 Current_Variable :=
1074 First_Variable_Of (Current_Package, In_Tree);
1076 while Current_Variable /= Empty_Node
1077 and then Name_Of (Current_Variable, In_Tree) /= Variable_Name
1078 loop
1079 Current_Variable :=
1080 Next_Variable (Current_Variable, In_Tree);
1081 end loop;
1082 end if;
1084 -- If we have not found the variable in the package, check if the
1085 -- variable has been declared in the project.
1087 if Current_Variable = Empty_Node then
1088 Current_Variable := First_Variable_Of (The_Project, In_Tree);
1090 while Current_Variable /= Empty_Node
1091 and then Name_Of (Current_Variable, In_Tree) /= Variable_Name
1092 loop
1093 Current_Variable :=
1094 Next_Variable (Current_Variable, In_Tree);
1095 end loop;
1096 end if;
1097 end if;
1099 -- If the variable was not found, report an error
1101 if Current_Variable = Empty_Node then
1102 Error_Msg_Name_1 := Variable_Name;
1103 Error_Msg
1104 ("unknown variable %", Names.Table (Names.Last).Location);
1105 end if;
1106 end if;
1108 if Current_Variable /= Empty_Node then
1109 Set_Expression_Kind_Of
1110 (Variable, In_Tree,
1111 To => Expression_Kind_Of (Current_Variable, In_Tree));
1114 Kind_Of (Current_Variable, In_Tree) = N_Typed_Variable_Declaration
1115 then
1116 Set_String_Type_Of
1117 (Variable, In_Tree,
1118 To => String_Type_Of (Current_Variable, In_Tree));
1119 end if;
1120 end if;
1122 -- If the variable is followed by a left parenthesis, report an error
1123 -- but attempt to scan the index.
1125 if Token = Tok_Left_Paren then
1126 Error_Msg ("\variables cannot be associative arrays", Token_Ptr);
1127 Scan (In_Tree);
1128 Expect (Tok_String_Literal, "literal string");
1130 if Token = Tok_String_Literal then
1131 Scan (In_Tree);
1132 Expect (Tok_Right_Paren, "`)`");
1134 if Token = Tok_Right_Paren then
1135 Scan (In_Tree);
1136 end if;
1137 end if;
1138 end if;
1139 end Parse_Variable_Reference;
1141 ---------------------------------
1142 -- Start_New_Case_Construction --
1143 ---------------------------------
1145 procedure Start_New_Case_Construction
1146 (In_Tree : Project_Node_Tree_Ref;
1147 String_Type : Project_Node_Id)
1149 Current_String : Project_Node_Id;
1151 begin
1152 -- Set Choice_First, depending on whether is the first case
1153 -- construction or not.
1155 if Choice_First = 0 then
1156 Choice_First := 1;
1157 Choices.Set_Last (First_Choice_Node_Id);
1158 else
1159 Choice_First := Choices.Last + 1;
1160 end if;
1162 -- Add to table Choices the literal of the string type
1164 if String_Type /= Empty_Node then
1165 Current_String := First_Literal_String (String_Type, In_Tree);
1167 while Current_String /= Empty_Node loop
1168 Add (This_String => String_Value_Of (Current_String, In_Tree));
1169 Current_String := Next_Literal_String (Current_String, In_Tree);
1170 end loop;
1171 end if;
1173 -- Set the value of the last choice in table Choice_Lasts
1175 Choice_Lasts.Increment_Last;
1176 Choice_Lasts.Table (Choice_Lasts.Last) := Choices.Last;
1178 end Start_New_Case_Construction;
1180 -----------
1181 -- Terms --
1182 -----------
1184 procedure Terms
1185 (In_Tree : Project_Node_Tree_Ref;
1186 Term : out Project_Node_Id;
1187 Expr_Kind : in out Variable_Kind;
1188 Current_Project : Project_Node_Id;
1189 Current_Package : Project_Node_Id;
1190 Optional_Index : Boolean)
1192 Next_Term : Project_Node_Id := Empty_Node;
1193 Term_Id : Project_Node_Id := Empty_Node;
1194 Current_Expression : Project_Node_Id := Empty_Node;
1195 Next_Expression : Project_Node_Id := Empty_Node;
1196 Current_Location : Source_Ptr := No_Location;
1197 Reference : Project_Node_Id := Empty_Node;
1199 begin
1200 -- Declare a new node for the term
1202 Term := Default_Project_Node (Of_Kind => N_Term, In_Tree => In_Tree);
1203 Set_Location_Of (Term, In_Tree, To => Token_Ptr);
1205 case Token is
1206 when Tok_Left_Paren =>
1208 -- If we have a left parenthesis and we don't know the expression
1209 -- kind, then this is a string list.
1211 case Expr_Kind is
1212 when Undefined =>
1213 Expr_Kind := List;
1215 when List =>
1216 null;
1218 when Single =>
1220 -- If we already know that this is a single string, report
1221 -- an error, but set the expression kind to string list to
1222 -- avoid several errors.
1224 Expr_Kind := List;
1225 Error_Msg
1226 ("literal string list cannot appear in a string",
1227 Token_Ptr);
1228 end case;
1230 -- Declare a new node for this literal string list
1232 Term_Id := Default_Project_Node
1233 (Of_Kind => N_Literal_String_List,
1234 In_Tree => In_Tree,
1235 And_Expr_Kind => List);
1236 Set_Current_Term (Term, In_Tree, To => Term_Id);
1237 Set_Location_Of (Term, In_Tree, To => Token_Ptr);
1239 -- Scan past the left parenthesis
1241 Scan (In_Tree);
1243 -- If the left parenthesis is immediately followed by a right
1244 -- parenthesis, the literal string list is empty.
1246 if Token = Tok_Right_Paren then
1247 Scan (In_Tree);
1249 else
1250 -- Otherwise, we parse the expression(s) in the literal string
1251 -- list.
1253 loop
1254 Current_Location := Token_Ptr;
1255 Parse_Expression
1256 (In_Tree => In_Tree,
1257 Expression => Next_Expression,
1258 Current_Project => Current_Project,
1259 Current_Package => Current_Package,
1260 Optional_Index => Optional_Index);
1262 -- The expression kind is String list, report an error
1264 if Expression_Kind_Of (Next_Expression, In_Tree) = List then
1265 Error_Msg ("single expression expected",
1266 Current_Location);
1267 end if;
1269 -- If Current_Expression is empty, it means that the
1270 -- expression is the first in the string list.
1272 if Current_Expression = Empty_Node then
1273 Set_First_Expression_In_List
1274 (Term_Id, In_Tree, To => Next_Expression);
1275 else
1276 Set_Next_Expression_In_List
1277 (Current_Expression, In_Tree, To => Next_Expression);
1278 end if;
1280 Current_Expression := Next_Expression;
1282 -- If there is a comma, continue with the next expression
1284 exit when Token /= Tok_Comma;
1285 Scan (In_Tree); -- past the comma
1286 end loop;
1288 -- We expect a closing right parenthesis
1290 Expect (Tok_Right_Paren, "`)`");
1292 if Token = Tok_Right_Paren then
1293 Scan (In_Tree);
1294 end if;
1295 end if;
1297 when Tok_String_Literal =>
1299 -- If we don't know the expression kind (first term), then it is
1300 -- a simple string.
1302 if Expr_Kind = Undefined then
1303 Expr_Kind := Single;
1304 end if;
1306 -- Declare a new node for the string literal
1308 Term_Id :=
1309 Default_Project_Node
1310 (Of_Kind => N_Literal_String, In_Tree => In_Tree);
1311 Set_Current_Term (Term, In_Tree, To => Term_Id);
1312 Set_String_Value_Of (Term_Id, In_Tree, To => Token_Name);
1314 -- Scan past the string literal
1316 Scan (In_Tree);
1318 -- Check for possible index expression
1320 if Token = Tok_At then
1321 if not Optional_Index then
1322 Error_Msg ("index not allowed here", Token_Ptr);
1323 Scan (In_Tree);
1325 if Token = Tok_Integer_Literal then
1326 Scan (In_Tree);
1327 end if;
1329 -- Set the index value
1331 else
1332 Scan (In_Tree);
1333 Expect (Tok_Integer_Literal, "integer literal");
1335 if Token = Tok_Integer_Literal then
1336 declare
1337 Index : constant Int := UI_To_Int (Int_Literal_Value);
1338 begin
1339 if Index = 0 then
1340 Error_Msg ("index cannot be zero", Token_Ptr);
1341 else
1342 Set_Source_Index_Of
1343 (Term_Id, In_Tree, To => Index);
1344 end if;
1345 end;
1347 Scan (In_Tree);
1348 end if;
1349 end if;
1350 end if;
1352 when Tok_Identifier =>
1353 Current_Location := Token_Ptr;
1355 -- Get the variable or attribute reference
1357 Parse_Variable_Reference
1358 (In_Tree => In_Tree,
1359 Variable => Reference,
1360 Current_Project => Current_Project,
1361 Current_Package => Current_Package);
1362 Set_Current_Term (Term, In_Tree, To => Reference);
1364 if Reference /= Empty_Node then
1366 -- If we don't know the expression kind (first term), then it
1367 -- has the kind of the variable or attribute reference.
1369 if Expr_Kind = Undefined then
1370 Expr_Kind := Expression_Kind_Of (Reference, In_Tree);
1372 elsif Expr_Kind = Single
1373 and then Expression_Kind_Of (Reference, In_Tree) = List
1374 then
1375 -- If the expression is a single list, and the reference is
1376 -- a string list, report an error, and set the expression
1377 -- kind to string list to avoid multiple errors.
1379 Expr_Kind := List;
1380 Error_Msg
1381 ("list variable cannot appear in single string expression",
1382 Current_Location);
1383 end if;
1384 end if;
1386 when Tok_Project =>
1388 -- project can appear in an expression as the prefix of an
1389 -- attribute reference of the current project.
1391 Current_Location := Token_Ptr;
1392 Scan (In_Tree);
1393 Expect (Tok_Apostrophe, "`'`");
1395 if Token = Tok_Apostrophe then
1396 Attribute_Reference
1397 (In_Tree => In_Tree,
1398 Reference => Reference,
1399 First_Attribute => Prj.Attr.Attribute_First,
1400 Current_Project => Current_Project,
1401 Current_Package => Empty_Node);
1402 Set_Current_Term (Term, In_Tree, To => Reference);
1403 end if;
1405 -- Same checks as above for the expression kind
1407 if Reference /= Empty_Node then
1408 if Expr_Kind = Undefined then
1409 Expr_Kind := Expression_Kind_Of (Reference, In_Tree);
1411 elsif Expr_Kind = Single
1412 and then Expression_Kind_Of (Reference, In_Tree) = List
1413 then
1414 Error_Msg
1415 ("lists cannot appear in single string expression",
1416 Current_Location);
1417 end if;
1418 end if;
1420 when Tok_External =>
1421 -- An external reference is always a single string
1423 if Expr_Kind = Undefined then
1424 Expr_Kind := Single;
1425 end if;
1427 External_Reference
1428 (In_Tree => In_Tree,
1429 Current_Project => Current_Project,
1430 Current_Package => Current_Package,
1431 External_Value => Reference);
1432 Set_Current_Term (Term, In_Tree, To => Reference);
1434 when others =>
1435 Error_Msg ("cannot be part of an expression", Token_Ptr);
1436 Term := Empty_Node;
1437 return;
1438 end case;
1440 -- If there is an '&', call Terms recursively
1442 if Token = Tok_Ampersand then
1444 -- Scan past the '&'
1446 Scan (In_Tree);
1448 Terms
1449 (In_Tree => In_Tree,
1450 Term => Next_Term,
1451 Expr_Kind => Expr_Kind,
1452 Current_Project => Current_Project,
1453 Current_Package => Current_Package,
1454 Optional_Index => Optional_Index);
1456 -- And link the next term to this term
1458 Set_Next_Term (Term, In_Tree, To => Next_Term);
1459 end if;
1460 end Terms;
1462 end Prj.Strt;