1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2005, 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 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. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Namet; use Namet;
29 with Prj.Com; use Prj.Com;
32 with System.Case_Util; use System.Case_Util;
34 package body Prj.Attr is
36 -- Data for predefined attributes and packages
40 -- Package names are preceded by 'P'
42 -- Attribute names are preceded by two letters:
44 -- The first letter is one of
46 -- 's' for Single with optional index
48 -- 'l' for List of strings with optional indexes
50 -- The second letter is one of
51 -- 'V' for single variable
52 -- 'A' for associative array
53 -- 'a' for case insensitive associative array
54 -- 'b' for associative array, case insensitive if file names are case
56 -- 'c' same as 'b', with optional index
58 -- End is indicated by two consecutive '#'
60 Initialization_Data : constant String :=
68 "LVlocally_removed_files#" &
69 "SVsource_list_file#" &
73 "SVlibrary_version#" &
74 "LVlibrary_interface#" &
75 "SVlibrary_auto_init#" &
76 "LVlibrary_options#" &
77 "SVlibrary_src_dir#" &
78 "SVlibrary_ali_dir#" &
80 "SVlibrary_symbol_file#" &
81 "SVlibrary_symbol_policy#" &
82 "SVlibrary_reference_symbol_file#" &
87 "SVexternally_built#" &
92 "Saspecification_suffix#" &
94 "Saimplementation_suffix#" &
96 "SVseparate_suffix#" &
98 "SVdot_replacement#" &
101 "sAimplementation#" &
103 "Laspecification_exceptions#" &
104 "Laimplementation_exceptions#" &
109 "Ladefault_switches#" &
111 "SVlocal_configuration_pragmas#" &
116 "Ladefault_switches#" &
119 "SVexecutable_suffix#" &
120 "SVglobal_configuration_pragmas#" &
130 "Ladefault_switches#" &
136 "Ladefault_switches#" &
138 "LVlinker_options#" &
140 -- package Cross_Reference
142 "Pcross_reference#" &
143 "Ladefault_switches#" &
149 "Ladefault_switches#" &
152 -- package Pretty_Printer
155 "Ladefault_switches#" &
161 "Ladefault_switches#" &
167 "Ladefault_switches#" &
173 "Ladefault_switches#" &
179 "Ladefault_switches#" &
182 "SVcommunication_protocol#" &
183 "Sacompiler_command#" &
184 "SVdebugger_command#" &
187 "SVvcs_file_check#" &
190 -- package Language_Processing
192 "Planguage_processing#" &
193 "Lacompiler_driver#" &
195 "Ladependency_option#" &
196 "Lacompute_dependency#" &
197 "Lainclude_option#" &
199 "SVdefault_linker#" &
203 Initialized : Boolean := False;
204 -- A flag to avoid multiple initialization
206 function Name_Id_Of (Name : String) return Name_Id;
207 -- Returns the Name_Id for Name in lower case
209 -----------------------
210 -- Attribute_Kind_Of --
211 -----------------------
213 function Attribute_Kind_Of
214 (Attribute : Attribute_Node_Id) return Attribute_Kind
217 if Attribute = Empty_Attribute then
220 return Attrs.Table (Attribute.Value).Attr_Kind;
222 end Attribute_Kind_Of;
224 -----------------------
225 -- Attribute_Name_Of --
226 -----------------------
228 function Attribute_Name_Of (Attribute : Attribute_Node_Id) return Name_Id is
230 if Attribute = Empty_Attribute then
233 return Attrs.Table (Attribute.Value).Name;
235 end Attribute_Name_Of;
237 --------------------------
238 -- Attribute_Node_Id_Of --
239 --------------------------
241 function Attribute_Node_Id_Of
243 Starting_At : Attribute_Node_Id) return Attribute_Node_Id
245 Id : Attr_Node_Id := Starting_At.Value;
248 while Id /= Empty_Attr
249 and then Attrs.Table (Id).Name /= Name
251 Id := Attrs.Table (Id).Next;
254 return (Value => Id);
255 end Attribute_Node_Id_Of;
261 procedure Initialize is
262 Start : Positive := Initialization_Data'First;
263 Finish : Positive := Start;
264 Current_Package : Pkg_Node_Id := Empty_Pkg;
265 Current_Attribute : Attr_Node_Id := Empty_Attr;
266 Is_An_Attribute : Boolean := False;
267 Var_Kind : Variable_Kind := Undefined;
268 Optional_Index : Boolean := False;
269 Attr_Kind : Attribute_Kind := Single;
270 Package_Name : Name_Id := No_Name;
271 Attribute_Name : Name_Id := No_Name;
272 First_Attribute : Attr_Node_Id := Attr.First_Attribute;
274 function Attribute_Location return String;
275 -- Returns a string depending if we are in the project level attributes
276 -- or in the attributes of a package.
278 ------------------------
279 -- Attribute_Location --
280 ------------------------
282 function Attribute_Location return String is
284 if Package_Name = No_Name then
285 return "project level attributes";
288 return "attribute of package """ &
289 Get_Name_String (Package_Name) & """";
291 end Attribute_Location;
293 -- Start of processing for Initialize
296 -- Don't allow Initialize action to be repeated
302 -- Make sure the two tables are empty
305 Package_Attributes.Init;
307 while Initialization_Data (Start) /= '#' loop
308 Is_An_Attribute := True;
309 case Initialization_Data (Start) is
312 -- New allowed package
317 while Initialization_Data (Finish) /= '#' loop
318 Finish := Finish + 1;
322 Name_Id_Of (Initialization_Data (Start .. Finish - 1));
324 for Index in First_Package .. Package_Attributes.Last loop
325 if Package_Name = Package_Attributes.Table (Index).Name then
326 Osint.Fail ("duplicate name """,
327 Initialization_Data (Start .. Finish - 1),
328 """ in predefined packages.");
332 Is_An_Attribute := False;
333 Current_Attribute := Empty_Attr;
334 Package_Attributes.Increment_Last;
335 Current_Package := Package_Attributes.Last;
336 Package_Attributes.Table (Current_Package) :=
337 (Name => Package_Name,
339 First_Attribute => Empty_Attr);
344 Optional_Index := False;
348 Optional_Index := True;
352 Optional_Index := False;
356 Optional_Index := True;
362 if Is_An_Attribute then
367 case Initialization_Data (Start) is
372 Attr_Kind := Associative_Array;
375 Attr_Kind := Case_Insensitive_Associative_Array;
378 if Osint.File_Names_Case_Sensitive then
379 Attr_Kind := Associative_Array;
381 Attr_Kind := Case_Insensitive_Associative_Array;
385 if Osint.File_Names_Case_Sensitive then
386 Attr_Kind := Optional_Index_Associative_Array;
389 Optional_Index_Case_Insensitive_Associative_Array;
399 while Initialization_Data (Finish) /= '#' loop
400 Finish := Finish + 1;
404 Name_Id_Of (Initialization_Data (Start .. Finish - 1));
405 Attrs.Increment_Last;
407 if Current_Attribute = Empty_Attr then
408 First_Attribute := Attrs.Last;
410 if Current_Package /= Empty_Pkg then
411 Package_Attributes.Table (Current_Package).First_Attribute
416 -- Check that there are no duplicate attributes
418 for Index in First_Attribute .. Attrs.Last - 1 loop
419 if Attribute_Name = Attrs.Table (Index).Name then
420 Osint.Fail ("duplicate attribute """,
421 Initialization_Data (Start .. Finish - 1),
422 """ in " & Attribute_Location);
426 Attrs.Table (Current_Attribute).Next :=
430 Current_Attribute := Attrs.Last;
431 Attrs.Table (Current_Attribute) :=
432 (Name => Attribute_Name,
433 Var_Kind => Var_Kind,
434 Optional_Index => Optional_Index,
435 Attr_Kind => Attr_Kind,
448 function Name_Id_Of (Name : String) return Name_Id is
451 Add_Str_To_Name_Buffer (Name);
452 To_Lower (Name_Buffer (1 .. Name_Len));
460 function Next_Attribute
461 (After : Attribute_Node_Id) return Attribute_Node_Id
464 if After = Empty_Attribute then
465 return Empty_Attribute;
467 return (Value => Attrs.Table (After.Value).Next);
471 -----------------------
472 -- Optional_Index_Of --
473 -----------------------
475 function Optional_Index_Of (Attribute : Attribute_Node_Id) return Boolean is
477 if Attribute = Empty_Attribute then
480 return Attrs.Table (Attribute.Value).Optional_Index;
482 end Optional_Index_Of;
484 ------------------------
485 -- Package_Node_Id_Of --
486 ------------------------
488 function Package_Node_Id_Of (Name : Name_Id) return Package_Node_Id is
490 for Index in Package_Attributes.First .. Package_Attributes.Last loop
491 if Package_Attributes.Table (Index).Name = Name then
492 return (Value => Index);
496 -- If there is no package with this name, return Empty_Package
498 return Empty_Package;
499 end Package_Node_Id_Of;
501 ----------------------------
502 -- Register_New_Attribute --
503 ----------------------------
505 procedure Register_New_Attribute
507 In_Package : Package_Node_Id;
508 Attr_Kind : Defined_Attribute_Kind;
509 Var_Kind : Defined_Variable_Kind;
510 Index_Is_File_Name : Boolean := False;
511 Opt_Index : Boolean := False)
514 First_Attr : Attr_Node_Id := Empty_Attr;
515 Curr_Attr : Attr_Node_Id;
516 Real_Attr_Kind : Attribute_Kind;
519 if Name'Length = 0 then
520 Fail ("cannot register an attribute with no name");
524 if In_Package = Empty_Package then
525 Fail ("attempt to add attribute """, Name,
526 """ to an undefined package");
530 Attr_Name := Name_Id_Of (Name);
533 Package_Attributes.Table (In_Package.Value).First_Attribute;
535 -- Check if attribute name is a duplicate
537 Curr_Attr := First_Attr;
538 while Curr_Attr /= Empty_Attr loop
539 if Attrs.Table (Curr_Attr).Name = Attr_Name then
540 Fail ("duplicate attribute name """, Name,
543 (Package_Attributes.Table (In_Package.Value).Name) &
548 Curr_Attr := Attrs.Table (Curr_Attr).Next;
551 Real_Attr_Kind := Attr_Kind;
553 -- If Index_Is_File_Name, change the attribute kind if necessary
555 if Index_Is_File_Name and then not Osint.File_Names_Case_Sensitive then
557 when Associative_Array =>
558 Real_Attr_Kind := Case_Insensitive_Associative_Array;
560 when Optional_Index_Associative_Array =>
562 Optional_Index_Case_Insensitive_Associative_Array;
569 -- Add the new attribute
571 Attrs.Increment_Last;
572 Attrs.Table (Attrs.Last) :=
574 Var_Kind => Var_Kind,
575 Optional_Index => Opt_Index,
576 Attr_Kind => Real_Attr_Kind,
578 Package_Attributes.Table (In_Package.Value).First_Attribute :=
580 end Register_New_Attribute;
582 --------------------------
583 -- Register_New_Package --
584 --------------------------
586 procedure Register_New_Package (Name : String; Id : out Package_Node_Id) is
590 if Name'Length = 0 then
591 Fail ("cannot register a package with no name");
596 Pkg_Name := Name_Id_Of (Name);
598 for Index in Package_Attributes.First .. Package_Attributes.Last loop
599 if Package_Attributes.Table (Index).Name = Pkg_Name then
600 Fail ("cannot register a package with a non unique name""",
607 Package_Attributes.Increment_Last;
608 Id := (Value => Package_Attributes.Last);
609 Package_Attributes.Table (Package_Attributes.Last) :=
610 (Name => Pkg_Name, Known => True, First_Attribute => Empty_Attr);
611 end Register_New_Package;
613 procedure Register_New_Package
615 Attributes : Attribute_Data_Array)
619 First_Attr : Attr_Node_Id := Empty_Attr;
620 Curr_Attr : Attr_Node_Id;
621 Attr_Kind : Attribute_Kind;
624 if Name'Length = 0 then
625 Fail ("cannot register a package with no name");
629 Pkg_Name := Name_Id_Of (Name);
631 for Index in Package_Attributes.First .. Package_Attributes.Last loop
632 if Package_Attributes.Table (Index).Name = Pkg_Name then
633 Fail ("cannot register a package with a non unique name""",
639 for Index in Attributes'Range loop
640 Attr_Name := Name_Id_Of (Attributes (Index).Name);
642 Curr_Attr := First_Attr;
643 while Curr_Attr /= Empty_Attr loop
644 if Attrs.Table (Curr_Attr).Name = Attr_Name then
645 Fail ("duplicate attribute name """, Attributes (Index).Name,
646 """ in new package """ & Name & """");
650 Curr_Attr := Attrs.Table (Curr_Attr).Next;
653 Attr_Kind := Attributes (Index).Attr_Kind;
655 if Attributes (Index).Index_Is_File_Name
656 and then not Osint.File_Names_Case_Sensitive
659 when Associative_Array =>
660 Attr_Kind := Case_Insensitive_Associative_Array;
662 when Optional_Index_Associative_Array =>
664 Optional_Index_Case_Insensitive_Associative_Array;
671 Attrs.Increment_Last;
672 Attrs.Table (Attrs.Last) :=
674 Var_Kind => Attributes (Index).Var_Kind,
675 Optional_Index => Attributes (Index).Opt_Index,
676 Attr_Kind => Attr_Kind,
678 First_Attr := Attrs.Last;
681 Package_Attributes.Increment_Last;
682 Package_Attributes.Table (Package_Attributes.Last) :=
683 (Name => Pkg_Name, Known => True, First_Attribute => First_Attr);
684 end Register_New_Package;
686 ---------------------------
687 -- Set_Attribute_Kind_Of --
688 ---------------------------
690 procedure Set_Attribute_Kind_Of
691 (Attribute : Attribute_Node_Id;
695 if Attribute /= Empty_Attribute then
696 Attrs.Table (Attribute.Value).Attr_Kind := To;
698 end Set_Attribute_Kind_Of;
700 --------------------------
701 -- Set_Variable_Kind_Of --
702 --------------------------
704 procedure Set_Variable_Kind_Of
705 (Attribute : Attribute_Node_Id;
709 if Attribute /= Empty_Attribute then
710 Attrs.Table (Attribute.Value).Var_Kind := To;
712 end Set_Variable_Kind_Of;
714 ----------------------
715 -- Variable_Kind_Of --
716 ----------------------
718 function Variable_Kind_Of
719 (Attribute : Attribute_Node_Id) return Variable_Kind
722 if Attribute = Empty_Attribute then
725 return Attrs.Table (Attribute.Value).Var_Kind;
727 end Variable_Kind_Of;
729 ------------------------
730 -- First_Attribute_Of --
731 ------------------------
733 function First_Attribute_Of
734 (Pkg : Package_Node_Id) return Attribute_Node_Id
737 if Pkg = Empty_Package then
738 return Empty_Attribute;
741 (Value => Package_Attributes.Table (Pkg.Value).First_Attribute);
743 end First_Attribute_Of;