1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2007, 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 ------------------------------------------------------------------------------
28 with Prj.Com; use Prj.Com;
29 with System.Case_Util; use System.Case_Util;
31 package body Prj.Attr is
33 -- Data for predefined attributes and packages
35 -- Names are in lower case and end with '#'
37 -- Package names are preceded by 'P'
39 -- Attribute names are preceded by two or three letters:
41 -- The first letter is one of
43 -- 's' for Single with optional index
45 -- 'l' for List of strings with optional indexes
47 -- The second letter is one of
48 -- 'V' for single variable
49 -- 'A' for associative array
50 -- 'a' for case insensitive associative array
51 -- 'b' for associative array, case insensitive if file names are case
53 -- 'c' same as 'b', with optional index
55 -- The third optional letter is
56 -- 'R' to indicate that the attribute is read-only
58 -- End is indicated by two consecutive '#'
60 Initialization_Data : constant String :=
62 -- project level attributes
71 "SVexternally_built#" &
78 "LVremoved_source_dirs#" &
83 "LVlocally_removed_files#" &
84 "SVsource_list_file#" &
91 "SVlibrary_version#" &
92 "LVlibrary_interface#" &
93 "SVlibrary_auto_init#" &
94 "LVlibrary_options#" &
95 "SVlibrary_src_dir#" &
96 "SVlibrary_ali_dir#" &
98 "SVlibrary_symbol_file#" &
99 "SVlibrary_symbol_policy#" &
100 "SVlibrary_reference_symbol_file#" &
102 -- Configuration - General
104 "SVdefault_language#" &
105 "LVrun_path_option#" &
106 "Satoolchain_version#" &
107 "Satoolchain_description#" &
109 -- Configuration - Libraries
111 "SVlibrary_builder#" &
112 "SVlibrary_support#" &
114 -- Configuration - Archives
116 "LVarchive_builder#" &
117 "LVarchive_indexer#" &
118 "SVarchive_suffix#" &
119 "LVlibrary_partial_linker#" &
121 -- Configuration - Shared libraries
123 "SVshared_library_prefix#" &
124 "SVshared_library_suffix#" &
125 "SVsymbolic_link_supported#" &
126 "SVlibrary_major_minor_id_supported#" &
127 "SVlibrary_auto_init_supported#" &
128 "LVshared_library_minimum_switches#" &
129 "LVlibrary_version_switches#" &
134 "Saspecification_suffix#" &
136 "Saimplementation_suffix#" &
138 "SVseparate_suffix#" &
140 "SVdot_replacement#" &
143 "sAimplementation#" &
145 "Laspecification_exceptions#" &
146 "Laimplementation_exceptions#" &
151 "Ladefault_switches#" &
153 "SVlocal_configuration_pragmas#" &
154 "Salocal_config_file#" &
156 -- Configuration - Compiling
161 -- Configuration - Mapping files
163 "Lamapping_file_switches#" &
164 "Samapping_spec_suffix#" &
165 "Samapping_body_suffix#" &
167 -- Configuration - Config files
169 "Laconfig_file_switches#" &
170 "Saconfig_body_file_name#" &
171 "Saconfig_spec_file_name#" &
172 "Saconfig_body_file_name_pattern#" &
173 "Saconfig_spec_file_name_pattern#" &
174 "Saconfig_file_unique#" &
176 -- Configuration - Dependencies
178 "Ladependency_switches#" &
179 "Lacompute_dependency#" &
181 -- Configuration - Search paths
183 "Lainclude_switches#" &
185 "Sainclude_path_file#" &
190 "Ladefault_switches#" &
193 "SVexecutable_suffix#" &
194 "SVglobal_configuration_pragmas#" &
195 "Saglobal_config_file#" &
205 "Ladefault_switches#" &
208 -- Configuration - Binding
213 "Saobjects_path_file#" &
218 "LVrequired_switches#" &
219 "Ladefault_switches#" &
221 "LVlinker_options#" &
223 -- Configuration - Linking
226 "LVexecutable_switch#" &
227 "SVlib_dir_switch#" &
228 "SVlib_name_switch#" &
230 -- package Cross_Reference
232 "Pcross_reference#" &
233 "Ladefault_switches#" &
239 "Ladefault_switches#" &
242 -- package Pretty_Printer
245 "Ladefault_switches#" &
251 "Ladefault_switches#" &
257 "Ladefault_switches#" &
263 "Ladefault_switches#" &
269 "Ladefault_switches#" &
275 "Ladefault_switches#" &
278 "SVcommunication_protocol#" &
279 "Sacompiler_command#" &
280 "SVdebugger_command#" &
283 "SVvcs_file_check#" &
293 Initialized : Boolean := False;
294 -- A flag to avoid multiple initialization
296 function Name_Id_Of (Name : String) return Name_Id;
297 -- Returns the Name_Id for Name in lower case
299 -----------------------
300 -- Attribute_Kind_Of --
301 -----------------------
303 function Attribute_Kind_Of
304 (Attribute : Attribute_Node_Id) return Attribute_Kind
307 if Attribute = Empty_Attribute then
310 return Attrs.Table (Attribute.Value).Attr_Kind;
312 end Attribute_Kind_Of;
314 -----------------------
315 -- Attribute_Name_Of --
316 -----------------------
318 function Attribute_Name_Of (Attribute : Attribute_Node_Id) return Name_Id is
320 if Attribute = Empty_Attribute then
323 return Attrs.Table (Attribute.Value).Name;
325 end Attribute_Name_Of;
327 --------------------------
328 -- Attribute_Node_Id_Of --
329 --------------------------
331 function Attribute_Node_Id_Of
333 Starting_At : Attribute_Node_Id) return Attribute_Node_Id
335 Id : Attr_Node_Id := Starting_At.Value;
338 while Id /= Empty_Attr
339 and then Attrs.Table (Id).Name /= Name
341 Id := Attrs.Table (Id).Next;
344 return (Value => Id);
345 end Attribute_Node_Id_Of;
351 procedure Initialize is
352 Start : Positive := Initialization_Data'First;
353 Finish : Positive := Start;
354 Current_Package : Pkg_Node_Id := Empty_Pkg;
355 Current_Attribute : Attr_Node_Id := Empty_Attr;
356 Is_An_Attribute : Boolean := False;
357 Var_Kind : Variable_Kind := Undefined;
358 Optional_Index : Boolean := False;
359 Attr_Kind : Attribute_Kind := Single;
360 Package_Name : Name_Id := No_Name;
361 Attribute_Name : Name_Id := No_Name;
362 First_Attribute : Attr_Node_Id := Attr.First_Attribute;
365 function Attribute_Location return String;
366 -- Returns a string depending if we are in the project level attributes
367 -- or in the attributes of a package.
369 ------------------------
370 -- Attribute_Location --
371 ------------------------
373 function Attribute_Location return String is
375 if Package_Name = No_Name then
376 return "project level attributes";
379 return "attribute of package """ &
380 Get_Name_String (Package_Name) & """";
382 end Attribute_Location;
384 -- Start of processing for Initialize
387 -- Don't allow Initialize action to be repeated
393 -- Make sure the two tables are empty
396 Package_Attributes.Init;
398 while Initialization_Data (Start) /= '#' loop
399 Is_An_Attribute := True;
400 case Initialization_Data (Start) is
403 -- New allowed package
408 while Initialization_Data (Finish) /= '#' loop
409 Finish := Finish + 1;
413 Name_Id_Of (Initialization_Data (Start .. Finish - 1));
415 for Index in First_Package .. Package_Attributes.Last loop
416 if Package_Name = Package_Attributes.Table (Index).Name then
417 Osint.Fail ("duplicate name """,
418 Initialization_Data (Start .. Finish - 1),
419 """ in predefined packages.");
423 Is_An_Attribute := False;
424 Current_Attribute := Empty_Attr;
425 Package_Attributes.Increment_Last;
426 Current_Package := Package_Attributes.Last;
427 Package_Attributes.Table (Current_Package) :=
428 (Name => Package_Name,
430 First_Attribute => Empty_Attr);
435 Optional_Index := False;
439 Optional_Index := True;
443 Optional_Index := False;
447 Optional_Index := True;
453 if Is_An_Attribute then
458 case Initialization_Data (Start) is
463 Attr_Kind := Associative_Array;
466 Attr_Kind := Case_Insensitive_Associative_Array;
469 if Osint.File_Names_Case_Sensitive then
470 Attr_Kind := Associative_Array;
472 Attr_Kind := Case_Insensitive_Associative_Array;
476 if Osint.File_Names_Case_Sensitive then
477 Attr_Kind := Optional_Index_Associative_Array;
480 Optional_Index_Case_Insensitive_Associative_Array;
489 if Initialization_Data (Start) = 'R' then
499 while Initialization_Data (Finish) /= '#' loop
500 Finish := Finish + 1;
504 Name_Id_Of (Initialization_Data (Start .. Finish - 1));
505 Attrs.Increment_Last;
507 if Current_Attribute = Empty_Attr then
508 First_Attribute := Attrs.Last;
510 if Current_Package /= Empty_Pkg then
511 Package_Attributes.Table (Current_Package).First_Attribute
516 -- Check that there are no duplicate attributes
518 for Index in First_Attribute .. Attrs.Last - 1 loop
519 if Attribute_Name = Attrs.Table (Index).Name then
520 Osint.Fail ("duplicate attribute """,
521 Initialization_Data (Start .. Finish - 1),
522 """ in " & Attribute_Location);
526 Attrs.Table (Current_Attribute).Next :=
530 Current_Attribute := Attrs.Last;
531 Attrs.Table (Current_Attribute) :=
532 (Name => Attribute_Name,
533 Var_Kind => Var_Kind,
534 Optional_Index => Optional_Index,
535 Attr_Kind => Attr_Kind,
536 Read_Only => Read_Only,
549 function Is_Read_Only (Attribute : Attribute_Node_Id) return Boolean is
551 return Attrs.Table (Attribute.Value).Read_Only;
558 function Name_Id_Of (Name : String) return Name_Id is
561 Add_Str_To_Name_Buffer (Name);
562 To_Lower (Name_Buffer (1 .. Name_Len));
570 function Next_Attribute
571 (After : Attribute_Node_Id) return Attribute_Node_Id
574 if After = Empty_Attribute then
575 return Empty_Attribute;
577 return (Value => Attrs.Table (After.Value).Next);
581 -----------------------
582 -- Optional_Index_Of --
583 -----------------------
585 function Optional_Index_Of (Attribute : Attribute_Node_Id) return Boolean is
587 if Attribute = Empty_Attribute then
590 return Attrs.Table (Attribute.Value).Optional_Index;
592 end Optional_Index_Of;
594 ------------------------
595 -- Package_Node_Id_Of --
596 ------------------------
598 function Package_Node_Id_Of (Name : Name_Id) return Package_Node_Id is
600 for Index in Package_Attributes.First .. Package_Attributes.Last loop
601 if Package_Attributes.Table (Index).Name = Name then
602 return (Value => Index);
606 -- If there is no package with this name, return Empty_Package
608 return Empty_Package;
609 end Package_Node_Id_Of;
611 ----------------------------
612 -- Register_New_Attribute --
613 ----------------------------
615 procedure Register_New_Attribute
617 In_Package : Package_Node_Id;
618 Attr_Kind : Defined_Attribute_Kind;
619 Var_Kind : Defined_Variable_Kind;
620 Index_Is_File_Name : Boolean := False;
621 Opt_Index : Boolean := False)
624 First_Attr : Attr_Node_Id := Empty_Attr;
625 Curr_Attr : Attr_Node_Id;
626 Real_Attr_Kind : Attribute_Kind;
629 if Name'Length = 0 then
630 Fail ("cannot register an attribute with no name");
634 if In_Package = Empty_Package then
635 Fail ("attempt to add attribute """, Name,
636 """ to an undefined package");
640 Attr_Name := Name_Id_Of (Name);
643 Package_Attributes.Table (In_Package.Value).First_Attribute;
645 -- Check if attribute name is a duplicate
647 Curr_Attr := First_Attr;
648 while Curr_Attr /= Empty_Attr loop
649 if Attrs.Table (Curr_Attr).Name = Attr_Name then
650 Fail ("duplicate attribute name """, Name,
653 (Package_Attributes.Table (In_Package.Value).Name) &
658 Curr_Attr := Attrs.Table (Curr_Attr).Next;
661 Real_Attr_Kind := Attr_Kind;
663 -- If Index_Is_File_Name, change the attribute kind if necessary
665 if Index_Is_File_Name and then not Osint.File_Names_Case_Sensitive then
667 when Associative_Array =>
668 Real_Attr_Kind := Case_Insensitive_Associative_Array;
670 when Optional_Index_Associative_Array =>
672 Optional_Index_Case_Insensitive_Associative_Array;
679 -- Add the new attribute
681 Attrs.Increment_Last;
682 Attrs.Table (Attrs.Last) :=
684 Var_Kind => Var_Kind,
685 Optional_Index => Opt_Index,
686 Attr_Kind => Real_Attr_Kind,
689 Package_Attributes.Table (In_Package.Value).First_Attribute :=
691 end Register_New_Attribute;
693 --------------------------
694 -- Register_New_Package --
695 --------------------------
697 procedure Register_New_Package (Name : String; Id : out Package_Node_Id) is
701 if Name'Length = 0 then
702 Fail ("cannot register a package with no name");
707 Pkg_Name := Name_Id_Of (Name);
709 for Index in Package_Attributes.First .. Package_Attributes.Last loop
710 if Package_Attributes.Table (Index).Name = Pkg_Name then
711 Fail ("cannot register a package with a non unique name""",
718 Package_Attributes.Increment_Last;
719 Id := (Value => Package_Attributes.Last);
720 Package_Attributes.Table (Package_Attributes.Last) :=
723 First_Attribute => Empty_Attr);
724 end Register_New_Package;
726 procedure Register_New_Package
728 Attributes : Attribute_Data_Array)
732 First_Attr : Attr_Node_Id := Empty_Attr;
733 Curr_Attr : Attr_Node_Id;
734 Attr_Kind : Attribute_Kind;
737 if Name'Length = 0 then
738 Fail ("cannot register a package with no name");
742 Pkg_Name := Name_Id_Of (Name);
744 for Index in Package_Attributes.First .. Package_Attributes.Last loop
745 if Package_Attributes.Table (Index).Name = Pkg_Name then
746 Fail ("cannot register a package with a non unique name""",
752 for Index in Attributes'Range loop
753 Attr_Name := Name_Id_Of (Attributes (Index).Name);
755 Curr_Attr := First_Attr;
756 while Curr_Attr /= Empty_Attr loop
757 if Attrs.Table (Curr_Attr).Name = Attr_Name then
758 Fail ("duplicate attribute name """, Attributes (Index).Name,
759 """ in new package """ & Name & """");
763 Curr_Attr := Attrs.Table (Curr_Attr).Next;
766 Attr_Kind := Attributes (Index).Attr_Kind;
768 if Attributes (Index).Index_Is_File_Name
769 and then not Osint.File_Names_Case_Sensitive
772 when Associative_Array =>
773 Attr_Kind := Case_Insensitive_Associative_Array;
775 when Optional_Index_Associative_Array =>
777 Optional_Index_Case_Insensitive_Associative_Array;
784 Attrs.Increment_Last;
785 Attrs.Table (Attrs.Last) :=
787 Var_Kind => Attributes (Index).Var_Kind,
788 Optional_Index => Attributes (Index).Opt_Index,
789 Attr_Kind => Attr_Kind,
792 First_Attr := Attrs.Last;
795 Package_Attributes.Increment_Last;
796 Package_Attributes.Table (Package_Attributes.Last) :=
799 First_Attribute => First_Attr);
800 end Register_New_Package;
802 ---------------------------
803 -- Set_Attribute_Kind_Of --
804 ---------------------------
806 procedure Set_Attribute_Kind_Of
807 (Attribute : Attribute_Node_Id;
811 if Attribute /= Empty_Attribute then
812 Attrs.Table (Attribute.Value).Attr_Kind := To;
814 end Set_Attribute_Kind_Of;
816 --------------------------
817 -- Set_Variable_Kind_Of --
818 --------------------------
820 procedure Set_Variable_Kind_Of
821 (Attribute : Attribute_Node_Id;
825 if Attribute /= Empty_Attribute then
826 Attrs.Table (Attribute.Value).Var_Kind := To;
828 end Set_Variable_Kind_Of;
830 ----------------------
831 -- Variable_Kind_Of --
832 ----------------------
834 function Variable_Kind_Of
835 (Attribute : Attribute_Node_Id) return Variable_Kind
838 if Attribute = Empty_Attribute then
841 return Attrs.Table (Attribute.Value).Var_Kind;
843 end Variable_Kind_Of;
845 ------------------------
846 -- First_Attribute_Of --
847 ------------------------
849 function First_Attribute_Of
850 (Pkg : Package_Node_Id) return Attribute_Node_Id
853 if Pkg = Empty_Package then
854 return Empty_Attribute;
857 (Value => Package_Attributes.Table (Pkg.Value).First_Attribute);
859 end First_Attribute_Of;