1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2008, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
27 with Prj.Com; use Prj.Com;
29 with GNAT.Case_Util; use GNAT.Case_Util;
31 package body Prj.Attr is
35 -- Data for predefined attributes and packages
37 -- Names are in lower case and end with '#'
39 -- Package names are preceded by 'P'
41 -- Attribute names are preceded by two or three letters:
43 -- The first letter is one of
45 -- 's' for Single with optional index
47 -- 'l' for List of strings with optional indexes
49 -- The second letter is one of
50 -- 'V' for single variable
51 -- 'A' for associative array
52 -- 'a' for case insensitive associative array
53 -- 'b' for associative array, case insensitive if file names are case
55 -- 'c' same as 'b', with optional index
57 -- The third optional letter is
58 -- 'R' to indicate that the attribute is read-only
59 -- 'O' to indicate that others is allowed as an index for an associative
62 -- End is indicated by two consecutive '#'
64 Initialization_Data : constant String :=
66 -- project level attributes
75 "SVexternally_built#" &
82 "Lainherit_source_path#" &
83 "LVexcluded_source_dirs#" &
88 "LVlocally_removed_files#" &
89 "LVexcluded_source_files#" &
90 "SVsource_list_file#" &
91 "SVexcluded_source_list_file#" &
99 "SVlibrary_version#" &
100 "LVlibrary_interface#" &
101 "SVlibrary_auto_init#" &
102 "LVlibrary_options#" &
103 "SVlibrary_src_dir#" &
104 "SVlibrary_ali_dir#" &
106 "SVlibrary_symbol_file#" &
107 "SVlibrary_symbol_policy#" &
108 "SVlibrary_reference_symbol_file#" &
110 -- Configuration - General
112 "SVdefault_language#" &
113 "LVrun_path_option#" &
114 "Satoolchain_version#" &
115 "Satoolchain_description#" &
116 "Saobject_generated#" &
117 "Saobjects_linked#" &
119 -- Configuration - Libraries
121 "SVlibrary_builder#" &
122 "SVlibrary_support#" &
124 -- Configuration - Archives
126 "LVarchive_builder#" &
127 "LVarchive_builder_append_option#" &
128 "LVarchive_indexer#" &
129 "SVarchive_suffix#" &
130 "LVlibrary_partial_linker#" &
132 -- Configuration - Shared libraries
134 "SVshared_library_prefix#" &
135 "SVshared_library_suffix#" &
136 "SVsymbolic_link_supported#" &
137 "SVlibrary_major_minor_id_supported#" &
138 "SVlibrary_auto_init_supported#" &
139 "LVshared_library_minimum_switches#" &
140 "LVlibrary_version_switches#" &
141 "Saruntime_library_dir#" &
146 "Saspecification_suffix#" &
148 "Saimplementation_suffix#" &
150 "SVseparate_suffix#" &
152 "SVdot_replacement#" &
155 "sAimplementation#" &
157 "Laspecification_exceptions#" &
158 "Laimplementation_exceptions#" &
163 "Ladefault_switches#" &
165 "SVlocal_configuration_pragmas#" &
166 "Salocal_config_file#" &
168 -- Configuration - Compiling
171 "Larequired_switches#" &
175 -- Configuration - Mapping files
177 "Lamapping_file_switches#" &
178 "Samapping_spec_suffix#" &
179 "Samapping_body_suffix#" &
181 -- Configuration - Config files
183 "Laconfig_file_switches#" &
184 "Saconfig_body_file_name#" &
185 "Saconfig_spec_file_name#" &
186 "Saconfig_body_file_name_pattern#" &
187 "Saconfig_spec_file_name_pattern#" &
188 "Saconfig_file_unique#" &
190 -- Configuration - Dependencies
192 "Ladependency_switches#" &
193 "Ladependency_driver#" &
195 -- Configuration - Search paths
197 "Lainclude_switches#" &
199 "Sainclude_path_file#" &
204 "Ladefault_switches#" &
206 "Lcglobal_compilation_switches#" &
208 "SVexecutable_suffix#" &
209 "SVglobal_configuration_pragmas#" &
210 "Saglobal_config_file#" &
220 "Ladefault_switches#" &
223 -- Configuration - Binding
226 "Larequired_switches#" &
229 "Saobjects_path_file#" &
234 "LVrequired_switches#" &
235 "Ladefault_switches#" &
237 "LVlinker_options#" &
238 "SVmap_file_option#" &
240 -- Configuration - Linking
243 "LVexecutable_switch#" &
244 "SVlib_dir_switch#" &
245 "SVlib_name_switch#" &
247 -- package Cross_Reference
249 "Pcross_reference#" &
250 "Ladefault_switches#" &
256 "Ladefault_switches#" &
259 -- package Pretty_Printer
262 "Ladefault_switches#" &
268 "Ladefault_switches#" &
274 "Ladefault_switches#" &
277 -- package Synchronize
280 "Ladefault_switches#" &
286 "Ladefault_switches#" &
292 "Ladefault_switches#" &
298 "Ladefault_switches#" &
301 "SVcommunication_protocol#" &
302 "Sacompiler_command#" &
303 "SVdebugger_command#" &
306 "SVvcs_file_check#" &
316 Initialized : Boolean := False;
317 -- A flag to avoid multiple initialization
319 Package_Names : String_List_Access := new Strings.String_List (1 .. 20);
320 Last_Package_Name : Natural := 0;
321 -- Package_Names (1 .. Last_Package_Name) contains the list of the known
322 -- package names, coming from the Initialization_Data string or from
323 -- calls to one of the two procedures Register_New_Package.
325 procedure Add_Package_Name (Name : String);
326 -- Add a package name in the Package_Name list, extending it, if necessary
328 function Name_Id_Of (Name : String) return Name_Id;
329 -- Returns the Name_Id for Name in lower case
331 ----------------------
332 -- Add_Package_Name --
333 ----------------------
335 procedure Add_Package_Name (Name : String) is
337 if Last_Package_Name = Package_Names'Last then
339 New_List : constant Strings.String_List_Access :=
340 new Strings.String_List (1 .. Package_Names'Last * 2);
342 New_List (Package_Names'Range) := Package_Names.all;
343 Package_Names := New_List;
347 Last_Package_Name := Last_Package_Name + 1;
348 Package_Names (Last_Package_Name) := new String'(Name);
349 end Add_Package_Name;
351 -----------------------
352 -- Attribute_Kind_Of --
353 -----------------------
355 function Attribute_Kind_Of
356 (Attribute : Attribute_Node_Id) return Attribute_Kind
359 if Attribute = Empty_Attribute then
362 return Attrs.Table (Attribute.Value).Attr_Kind;
364 end Attribute_Kind_Of;
366 -----------------------
367 -- Attribute_Name_Of --
368 -----------------------
370 function Attribute_Name_Of (Attribute : Attribute_Node_Id) return Name_Id is
372 if Attribute = Empty_Attribute then
375 return Attrs.Table (Attribute.Value).Name;
377 end Attribute_Name_Of;
379 --------------------------
380 -- Attribute_Node_Id_Of --
381 --------------------------
383 function Attribute_Node_Id_Of
385 Starting_At : Attribute_Node_Id) return Attribute_Node_Id
387 Id : Attr_Node_Id := Starting_At.Value;
390 while Id /= Empty_Attr
391 and then Attrs.Table (Id).Name /= Name
393 Id := Attrs.Table (Id).Next;
396 return (Value => Id);
397 end Attribute_Node_Id_Of;
403 procedure Initialize is
404 Start : Positive := Initialization_Data'First;
405 Finish : Positive := Start;
406 Current_Package : Pkg_Node_Id := Empty_Pkg;
407 Current_Attribute : Attr_Node_Id := Empty_Attr;
408 Is_An_Attribute : Boolean := False;
409 Var_Kind : Variable_Kind := Undefined;
410 Optional_Index : Boolean := False;
411 Attr_Kind : Attribute_Kind := Single;
412 Package_Name : Name_Id := No_Name;
413 Attribute_Name : Name_Id := No_Name;
414 First_Attribute : Attr_Node_Id := Attr.First_Attribute;
416 Others_Allowed : Boolean;
418 function Attribute_Location return String;
419 -- Returns a string depending if we are in the project level attributes
420 -- or in the attributes of a package.
422 ------------------------
423 -- Attribute_Location --
424 ------------------------
426 function Attribute_Location return String is
428 if Package_Name = No_Name then
429 return "project level attributes";
432 return "attribute of package """ &
433 Get_Name_String (Package_Name) & """";
435 end Attribute_Location;
437 -- Start of processing for Initialize
440 -- Don't allow Initialize action to be repeated
446 -- Make sure the two tables are empty
449 Package_Attributes.Init;
451 while Initialization_Data (Start) /= '#' loop
452 Is_An_Attribute := True;
453 case Initialization_Data (Start) is
456 -- New allowed package
461 while Initialization_Data (Finish) /= '#' loop
462 Finish := Finish + 1;
466 Name_Id_Of (Initialization_Data (Start .. Finish - 1));
468 for Index in First_Package .. Package_Attributes.Last loop
469 if Package_Name = Package_Attributes.Table (Index).Name then
470 Osint.Fail ("duplicate name """,
471 Initialization_Data (Start .. Finish - 1),
472 """ in predefined packages.");
476 Is_An_Attribute := False;
477 Current_Attribute := Empty_Attr;
478 Package_Attributes.Increment_Last;
479 Current_Package := Package_Attributes.Last;
480 Package_Attributes.Table (Current_Package) :=
481 (Name => Package_Name,
483 First_Attribute => Empty_Attr);
486 Add_Package_Name (Get_Name_String (Package_Name));
490 Optional_Index := False;
494 Optional_Index := True;
498 Optional_Index := False;
502 Optional_Index := True;
508 if Is_An_Attribute then
513 case Initialization_Data (Start) is
518 Attr_Kind := Associative_Array;
521 Attr_Kind := Case_Insensitive_Associative_Array;
524 if Osint.File_Names_Case_Sensitive then
525 Attr_Kind := Associative_Array;
527 Attr_Kind := Case_Insensitive_Associative_Array;
531 if Osint.File_Names_Case_Sensitive then
532 Attr_Kind := Optional_Index_Associative_Array;
535 Optional_Index_Case_Insensitive_Associative_Array;
545 Others_Allowed := False;
547 if Initialization_Data (Start) = 'R' then
551 elsif Initialization_Data (Start) = 'O' then
552 Others_Allowed := True;
558 while Initialization_Data (Finish) /= '#' loop
559 Finish := Finish + 1;
563 Name_Id_Of (Initialization_Data (Start .. Finish - 1));
564 Attrs.Increment_Last;
566 if Current_Attribute = Empty_Attr then
567 First_Attribute := Attrs.Last;
569 if Current_Package /= Empty_Pkg then
570 Package_Attributes.Table (Current_Package).First_Attribute
575 -- Check that there are no duplicate attributes
577 for Index in First_Attribute .. Attrs.Last - 1 loop
578 if Attribute_Name = Attrs.Table (Index).Name then
579 Osint.Fail ("duplicate attribute """,
580 Initialization_Data (Start .. Finish - 1),
581 """ in " & Attribute_Location);
585 Attrs.Table (Current_Attribute).Next :=
589 Current_Attribute := Attrs.Last;
590 Attrs.Table (Current_Attribute) :=
591 (Name => Attribute_Name,
592 Var_Kind => Var_Kind,
593 Optional_Index => Optional_Index,
594 Attr_Kind => Attr_Kind,
595 Read_Only => Read_Only,
596 Others_Allowed => Others_Allowed,
609 function Is_Read_Only (Attribute : Attribute_Node_Id) return Boolean is
611 return Attrs.Table (Attribute.Value).Read_Only;
618 function Name_Id_Of (Name : String) return Name_Id is
621 Add_Str_To_Name_Buffer (Name);
622 To_Lower (Name_Buffer (1 .. Name_Len));
630 function Next_Attribute
631 (After : Attribute_Node_Id) return Attribute_Node_Id
634 if After = Empty_Attribute then
635 return Empty_Attribute;
637 return (Value => Attrs.Table (After.Value).Next);
641 -----------------------
642 -- Optional_Index_Of --
643 -----------------------
645 function Optional_Index_Of (Attribute : Attribute_Node_Id) return Boolean is
647 if Attribute = Empty_Attribute then
650 return Attrs.Table (Attribute.Value).Optional_Index;
652 end Optional_Index_Of;
654 function Others_Allowed_For
655 (Attribute : Attribute_Node_Id) return Boolean
658 if Attribute = Empty_Attribute then
661 return Attrs.Table (Attribute.Value).Others_Allowed;
663 end Others_Allowed_For;
665 -----------------------
666 -- Package_Name_List --
667 -----------------------
669 function Package_Name_List return Strings.String_List is
671 return Package_Names (1 .. Last_Package_Name);
672 end Package_Name_List;
674 ------------------------
675 -- Package_Node_Id_Of --
676 ------------------------
678 function Package_Node_Id_Of (Name : Name_Id) return Package_Node_Id is
680 for Index in Package_Attributes.First .. Package_Attributes.Last loop
681 if Package_Attributes.Table (Index).Name = Name then
682 if Package_Attributes.Table (Index).Known then
683 return (Value => Index);
685 return Unknown_Package;
690 -- If there is no package with this name, return Empty_Package
692 return Empty_Package;
693 end Package_Node_Id_Of;
695 ----------------------------
696 -- Register_New_Attribute --
697 ----------------------------
699 procedure Register_New_Attribute
701 In_Package : Package_Node_Id;
702 Attr_Kind : Defined_Attribute_Kind;
703 Var_Kind : Defined_Variable_Kind;
704 Index_Is_File_Name : Boolean := False;
705 Opt_Index : Boolean := False)
708 First_Attr : Attr_Node_Id := Empty_Attr;
709 Curr_Attr : Attr_Node_Id;
710 Real_Attr_Kind : Attribute_Kind;
713 if Name'Length = 0 then
714 Fail ("cannot register an attribute with no name");
718 if In_Package = Empty_Package then
719 Fail ("attempt to add attribute """, Name,
720 """ to an undefined package");
724 Attr_Name := Name_Id_Of (Name);
727 Package_Attributes.Table (In_Package.Value).First_Attribute;
729 -- Check if attribute name is a duplicate
731 Curr_Attr := First_Attr;
732 while Curr_Attr /= Empty_Attr loop
733 if Attrs.Table (Curr_Attr).Name = Attr_Name then
734 Fail ("duplicate attribute name """, Name,
737 (Package_Attributes.Table (In_Package.Value).Name) &
742 Curr_Attr := Attrs.Table (Curr_Attr).Next;
745 Real_Attr_Kind := Attr_Kind;
747 -- If Index_Is_File_Name, change the attribute kind if necessary
749 if Index_Is_File_Name and then not Osint.File_Names_Case_Sensitive then
751 when Associative_Array =>
752 Real_Attr_Kind := Case_Insensitive_Associative_Array;
754 when Optional_Index_Associative_Array =>
756 Optional_Index_Case_Insensitive_Associative_Array;
763 -- Add the new attribute
765 Attrs.Increment_Last;
766 Attrs.Table (Attrs.Last) :=
768 Var_Kind => Var_Kind,
769 Optional_Index => Opt_Index,
770 Attr_Kind => Real_Attr_Kind,
772 Others_Allowed => False,
775 Package_Attributes.Table (In_Package.Value).First_Attribute :=
777 end Register_New_Attribute;
779 --------------------------
780 -- Register_New_Package --
781 --------------------------
783 procedure Register_New_Package (Name : String; Id : out Package_Node_Id) is
787 if Name'Length = 0 then
788 Fail ("cannot register a package with no name");
793 Pkg_Name := Name_Id_Of (Name);
795 for Index in Package_Attributes.First .. Package_Attributes.Last loop
796 if Package_Attributes.Table (Index).Name = Pkg_Name then
797 Fail ("cannot register a package with a non unique name""",
804 Package_Attributes.Increment_Last;
805 Id := (Value => Package_Attributes.Last);
806 Package_Attributes.Table (Package_Attributes.Last) :=
809 First_Attribute => Empty_Attr);
811 Add_Package_Name (Get_Name_String (Pkg_Name));
812 end Register_New_Package;
814 procedure Register_New_Package
816 Attributes : Attribute_Data_Array)
820 First_Attr : Attr_Node_Id := Empty_Attr;
821 Curr_Attr : Attr_Node_Id;
822 Attr_Kind : Attribute_Kind;
825 if Name'Length = 0 then
826 Fail ("cannot register a package with no name");
830 Pkg_Name := Name_Id_Of (Name);
832 for Index in Package_Attributes.First .. Package_Attributes.Last loop
833 if Package_Attributes.Table (Index).Name = Pkg_Name then
834 Fail ("cannot register a package with a non unique name""",
840 for Index in Attributes'Range loop
841 Attr_Name := Name_Id_Of (Attributes (Index).Name);
843 Curr_Attr := First_Attr;
844 while Curr_Attr /= Empty_Attr loop
845 if Attrs.Table (Curr_Attr).Name = Attr_Name then
846 Fail ("duplicate attribute name """, Attributes (Index).Name,
847 """ in new package """ & Name & """");
851 Curr_Attr := Attrs.Table (Curr_Attr).Next;
854 Attr_Kind := Attributes (Index).Attr_Kind;
856 if Attributes (Index).Index_Is_File_Name
857 and then not Osint.File_Names_Case_Sensitive
860 when Associative_Array =>
861 Attr_Kind := Case_Insensitive_Associative_Array;
863 when Optional_Index_Associative_Array =>
865 Optional_Index_Case_Insensitive_Associative_Array;
872 Attrs.Increment_Last;
873 Attrs.Table (Attrs.Last) :=
875 Var_Kind => Attributes (Index).Var_Kind,
876 Optional_Index => Attributes (Index).Opt_Index,
877 Attr_Kind => Attr_Kind,
879 Others_Allowed => False,
881 First_Attr := Attrs.Last;
884 Package_Attributes.Increment_Last;
885 Package_Attributes.Table (Package_Attributes.Last) :=
888 First_Attribute => First_Attr);
890 Add_Package_Name (Get_Name_String (Pkg_Name));
891 end Register_New_Package;
893 ---------------------------
894 -- Set_Attribute_Kind_Of --
895 ---------------------------
897 procedure Set_Attribute_Kind_Of
898 (Attribute : Attribute_Node_Id;
902 if Attribute /= Empty_Attribute then
903 Attrs.Table (Attribute.Value).Attr_Kind := To;
905 end Set_Attribute_Kind_Of;
907 --------------------------
908 -- Set_Variable_Kind_Of --
909 --------------------------
911 procedure Set_Variable_Kind_Of
912 (Attribute : Attribute_Node_Id;
916 if Attribute /= Empty_Attribute then
917 Attrs.Table (Attribute.Value).Var_Kind := To;
919 end Set_Variable_Kind_Of;
921 ----------------------
922 -- Variable_Kind_Of --
923 ----------------------
925 function Variable_Kind_Of
926 (Attribute : Attribute_Node_Id) return Variable_Kind
929 if Attribute = Empty_Attribute then
932 return Attrs.Table (Attribute.Value).Var_Kind;
934 end Variable_Kind_Of;
936 ------------------------
937 -- First_Attribute_Of --
938 ------------------------
940 function First_Attribute_Of
941 (Pkg : Package_Node_Id) return Attribute_Node_Id
944 if Pkg = Empty_Package then
945 return Empty_Attribute;
948 (Value => Package_Attributes.Table (Pkg.Value).First_Attribute);
950 end First_Attribute_Of;