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 "LVexcluded_source_dirs#" &
83 "LVlocally_removed_files#" &
84 "LVexcluded_source_files#" &
85 "SVsource_list_file#" &
92 "SVlibrary_version#" &
93 "LVlibrary_interface#" &
94 "SVlibrary_auto_init#" &
95 "LVlibrary_options#" &
96 "SVlibrary_src_dir#" &
97 "SVlibrary_ali_dir#" &
99 "SVlibrary_symbol_file#" &
100 "SVlibrary_symbol_policy#" &
101 "SVlibrary_reference_symbol_file#" &
103 -- Configuration - General
105 "SVdefault_language#" &
106 "LVrun_path_option#" &
107 "Satoolchain_version#" &
108 "Satoolchain_description#" &
110 -- Configuration - Libraries
112 "SVlibrary_builder#" &
113 "SVlibrary_support#" &
115 -- Configuration - Archives
117 "LVarchive_builder#" &
118 "LVarchive_indexer#" &
119 "SVarchive_suffix#" &
120 "LVlibrary_partial_linker#" &
122 -- Configuration - Shared libraries
124 "SVshared_library_prefix#" &
125 "SVshared_library_suffix#" &
126 "SVsymbolic_link_supported#" &
127 "SVlibrary_major_minor_id_supported#" &
128 "SVlibrary_auto_init_supported#" &
129 "LVshared_library_minimum_switches#" &
130 "LVlibrary_version_switches#" &
135 "Saspecification_suffix#" &
137 "Saimplementation_suffix#" &
139 "SVseparate_suffix#" &
141 "SVdot_replacement#" &
144 "sAimplementation#" &
146 "Laspecification_exceptions#" &
147 "Laimplementation_exceptions#" &
152 "Ladefault_switches#" &
154 "SVlocal_configuration_pragmas#" &
155 "Salocal_config_file#" &
157 -- Configuration - Compiling
162 -- Configuration - Mapping files
164 "Lamapping_file_switches#" &
165 "Samapping_spec_suffix#" &
166 "Samapping_body_suffix#" &
168 -- Configuration - Config files
170 "Laconfig_file_switches#" &
171 "Saconfig_body_file_name#" &
172 "Saconfig_spec_file_name#" &
173 "Saconfig_body_file_name_pattern#" &
174 "Saconfig_spec_file_name_pattern#" &
175 "Saconfig_file_unique#" &
177 -- Configuration - Dependencies
179 "Ladependency_switches#" &
180 "Lacompute_dependency#" &
182 -- Configuration - Search paths
184 "Lainclude_switches#" &
186 "Sainclude_path_file#" &
191 "Ladefault_switches#" &
194 "SVexecutable_suffix#" &
195 "SVglobal_configuration_pragmas#" &
196 "Saglobal_config_file#" &
206 "Ladefault_switches#" &
209 -- Configuration - Binding
214 "Saobjects_path_file#" &
219 "LVrequired_switches#" &
220 "Ladefault_switches#" &
222 "LVlinker_options#" &
224 -- Configuration - Linking
227 "LVexecutable_switch#" &
228 "SVlib_dir_switch#" &
229 "SVlib_name_switch#" &
231 -- package Cross_Reference
233 "Pcross_reference#" &
234 "Ladefault_switches#" &
240 "Ladefault_switches#" &
243 -- package Pretty_Printer
246 "Ladefault_switches#" &
252 "Ladefault_switches#" &
258 "Ladefault_switches#" &
264 "Ladefault_switches#" &
270 "Ladefault_switches#" &
276 "Ladefault_switches#" &
279 "SVcommunication_protocol#" &
280 "Sacompiler_command#" &
281 "SVdebugger_command#" &
284 "SVvcs_file_check#" &
294 Initialized : Boolean := False;
295 -- A flag to avoid multiple initialization
297 function Name_Id_Of (Name : String) return Name_Id;
298 -- Returns the Name_Id for Name in lower case
300 -----------------------
301 -- Attribute_Kind_Of --
302 -----------------------
304 function Attribute_Kind_Of
305 (Attribute : Attribute_Node_Id) return Attribute_Kind
308 if Attribute = Empty_Attribute then
311 return Attrs.Table (Attribute.Value).Attr_Kind;
313 end Attribute_Kind_Of;
315 -----------------------
316 -- Attribute_Name_Of --
317 -----------------------
319 function Attribute_Name_Of (Attribute : Attribute_Node_Id) return Name_Id is
321 if Attribute = Empty_Attribute then
324 return Attrs.Table (Attribute.Value).Name;
326 end Attribute_Name_Of;
328 --------------------------
329 -- Attribute_Node_Id_Of --
330 --------------------------
332 function Attribute_Node_Id_Of
334 Starting_At : Attribute_Node_Id) return Attribute_Node_Id
336 Id : Attr_Node_Id := Starting_At.Value;
339 while Id /= Empty_Attr
340 and then Attrs.Table (Id).Name /= Name
342 Id := Attrs.Table (Id).Next;
345 return (Value => Id);
346 end Attribute_Node_Id_Of;
352 procedure Initialize is
353 Start : Positive := Initialization_Data'First;
354 Finish : Positive := Start;
355 Current_Package : Pkg_Node_Id := Empty_Pkg;
356 Current_Attribute : Attr_Node_Id := Empty_Attr;
357 Is_An_Attribute : Boolean := False;
358 Var_Kind : Variable_Kind := Undefined;
359 Optional_Index : Boolean := False;
360 Attr_Kind : Attribute_Kind := Single;
361 Package_Name : Name_Id := No_Name;
362 Attribute_Name : Name_Id := No_Name;
363 First_Attribute : Attr_Node_Id := Attr.First_Attribute;
366 function Attribute_Location return String;
367 -- Returns a string depending if we are in the project level attributes
368 -- or in the attributes of a package.
370 ------------------------
371 -- Attribute_Location --
372 ------------------------
374 function Attribute_Location return String is
376 if Package_Name = No_Name then
377 return "project level attributes";
380 return "attribute of package """ &
381 Get_Name_String (Package_Name) & """";
383 end Attribute_Location;
385 -- Start of processing for Initialize
388 -- Don't allow Initialize action to be repeated
394 -- Make sure the two tables are empty
397 Package_Attributes.Init;
399 while Initialization_Data (Start) /= '#' loop
400 Is_An_Attribute := True;
401 case Initialization_Data (Start) is
404 -- New allowed package
409 while Initialization_Data (Finish) /= '#' loop
410 Finish := Finish + 1;
414 Name_Id_Of (Initialization_Data (Start .. Finish - 1));
416 for Index in First_Package .. Package_Attributes.Last loop
417 if Package_Name = Package_Attributes.Table (Index).Name then
418 Osint.Fail ("duplicate name """,
419 Initialization_Data (Start .. Finish - 1),
420 """ in predefined packages.");
424 Is_An_Attribute := False;
425 Current_Attribute := Empty_Attr;
426 Package_Attributes.Increment_Last;
427 Current_Package := Package_Attributes.Last;
428 Package_Attributes.Table (Current_Package) :=
429 (Name => Package_Name,
431 First_Attribute => Empty_Attr);
436 Optional_Index := False;
440 Optional_Index := True;
444 Optional_Index := False;
448 Optional_Index := True;
454 if Is_An_Attribute then
459 case Initialization_Data (Start) is
464 Attr_Kind := Associative_Array;
467 Attr_Kind := Case_Insensitive_Associative_Array;
470 if Osint.File_Names_Case_Sensitive then
471 Attr_Kind := Associative_Array;
473 Attr_Kind := Case_Insensitive_Associative_Array;
477 if Osint.File_Names_Case_Sensitive then
478 Attr_Kind := Optional_Index_Associative_Array;
481 Optional_Index_Case_Insensitive_Associative_Array;
490 if Initialization_Data (Start) = 'R' then
500 while Initialization_Data (Finish) /= '#' loop
501 Finish := Finish + 1;
505 Name_Id_Of (Initialization_Data (Start .. Finish - 1));
506 Attrs.Increment_Last;
508 if Current_Attribute = Empty_Attr then
509 First_Attribute := Attrs.Last;
511 if Current_Package /= Empty_Pkg then
512 Package_Attributes.Table (Current_Package).First_Attribute
517 -- Check that there are no duplicate attributes
519 for Index in First_Attribute .. Attrs.Last - 1 loop
520 if Attribute_Name = Attrs.Table (Index).Name then
521 Osint.Fail ("duplicate attribute """,
522 Initialization_Data (Start .. Finish - 1),
523 """ in " & Attribute_Location);
527 Attrs.Table (Current_Attribute).Next :=
531 Current_Attribute := Attrs.Last;
532 Attrs.Table (Current_Attribute) :=
533 (Name => Attribute_Name,
534 Var_Kind => Var_Kind,
535 Optional_Index => Optional_Index,
536 Attr_Kind => Attr_Kind,
537 Read_Only => Read_Only,
550 function Is_Read_Only (Attribute : Attribute_Node_Id) return Boolean is
552 return Attrs.Table (Attribute.Value).Read_Only;
559 function Name_Id_Of (Name : String) return Name_Id is
562 Add_Str_To_Name_Buffer (Name);
563 To_Lower (Name_Buffer (1 .. Name_Len));
571 function Next_Attribute
572 (After : Attribute_Node_Id) return Attribute_Node_Id
575 if After = Empty_Attribute then
576 return Empty_Attribute;
578 return (Value => Attrs.Table (After.Value).Next);
582 -----------------------
583 -- Optional_Index_Of --
584 -----------------------
586 function Optional_Index_Of (Attribute : Attribute_Node_Id) return Boolean is
588 if Attribute = Empty_Attribute then
591 return Attrs.Table (Attribute.Value).Optional_Index;
593 end Optional_Index_Of;
595 ------------------------
596 -- Package_Node_Id_Of --
597 ------------------------
599 function Package_Node_Id_Of (Name : Name_Id) return Package_Node_Id is
601 for Index in Package_Attributes.First .. Package_Attributes.Last loop
602 if Package_Attributes.Table (Index).Name = Name then
603 return (Value => Index);
607 -- If there is no package with this name, return Empty_Package
609 return Empty_Package;
610 end Package_Node_Id_Of;
612 ----------------------------
613 -- Register_New_Attribute --
614 ----------------------------
616 procedure Register_New_Attribute
618 In_Package : Package_Node_Id;
619 Attr_Kind : Defined_Attribute_Kind;
620 Var_Kind : Defined_Variable_Kind;
621 Index_Is_File_Name : Boolean := False;
622 Opt_Index : Boolean := False)
625 First_Attr : Attr_Node_Id := Empty_Attr;
626 Curr_Attr : Attr_Node_Id;
627 Real_Attr_Kind : Attribute_Kind;
630 if Name'Length = 0 then
631 Fail ("cannot register an attribute with no name");
635 if In_Package = Empty_Package then
636 Fail ("attempt to add attribute """, Name,
637 """ to an undefined package");
641 Attr_Name := Name_Id_Of (Name);
644 Package_Attributes.Table (In_Package.Value).First_Attribute;
646 -- Check if attribute name is a duplicate
648 Curr_Attr := First_Attr;
649 while Curr_Attr /= Empty_Attr loop
650 if Attrs.Table (Curr_Attr).Name = Attr_Name then
651 Fail ("duplicate attribute name """, Name,
654 (Package_Attributes.Table (In_Package.Value).Name) &
659 Curr_Attr := Attrs.Table (Curr_Attr).Next;
662 Real_Attr_Kind := Attr_Kind;
664 -- If Index_Is_File_Name, change the attribute kind if necessary
666 if Index_Is_File_Name and then not Osint.File_Names_Case_Sensitive then
668 when Associative_Array =>
669 Real_Attr_Kind := Case_Insensitive_Associative_Array;
671 when Optional_Index_Associative_Array =>
673 Optional_Index_Case_Insensitive_Associative_Array;
680 -- Add the new attribute
682 Attrs.Increment_Last;
683 Attrs.Table (Attrs.Last) :=
685 Var_Kind => Var_Kind,
686 Optional_Index => Opt_Index,
687 Attr_Kind => Real_Attr_Kind,
690 Package_Attributes.Table (In_Package.Value).First_Attribute :=
692 end Register_New_Attribute;
694 --------------------------
695 -- Register_New_Package --
696 --------------------------
698 procedure Register_New_Package (Name : String; Id : out Package_Node_Id) is
702 if Name'Length = 0 then
703 Fail ("cannot register a package with no name");
708 Pkg_Name := Name_Id_Of (Name);
710 for Index in Package_Attributes.First .. Package_Attributes.Last loop
711 if Package_Attributes.Table (Index).Name = Pkg_Name then
712 Fail ("cannot register a package with a non unique name""",
719 Package_Attributes.Increment_Last;
720 Id := (Value => Package_Attributes.Last);
721 Package_Attributes.Table (Package_Attributes.Last) :=
724 First_Attribute => Empty_Attr);
725 end Register_New_Package;
727 procedure Register_New_Package
729 Attributes : Attribute_Data_Array)
733 First_Attr : Attr_Node_Id := Empty_Attr;
734 Curr_Attr : Attr_Node_Id;
735 Attr_Kind : Attribute_Kind;
738 if Name'Length = 0 then
739 Fail ("cannot register a package with no name");
743 Pkg_Name := Name_Id_Of (Name);
745 for Index in Package_Attributes.First .. Package_Attributes.Last loop
746 if Package_Attributes.Table (Index).Name = Pkg_Name then
747 Fail ("cannot register a package with a non unique name""",
753 for Index in Attributes'Range loop
754 Attr_Name := Name_Id_Of (Attributes (Index).Name);
756 Curr_Attr := First_Attr;
757 while Curr_Attr /= Empty_Attr loop
758 if Attrs.Table (Curr_Attr).Name = Attr_Name then
759 Fail ("duplicate attribute name """, Attributes (Index).Name,
760 """ in new package """ & Name & """");
764 Curr_Attr := Attrs.Table (Curr_Attr).Next;
767 Attr_Kind := Attributes (Index).Attr_Kind;
769 if Attributes (Index).Index_Is_File_Name
770 and then not Osint.File_Names_Case_Sensitive
773 when Associative_Array =>
774 Attr_Kind := Case_Insensitive_Associative_Array;
776 when Optional_Index_Associative_Array =>
778 Optional_Index_Case_Insensitive_Associative_Array;
785 Attrs.Increment_Last;
786 Attrs.Table (Attrs.Last) :=
788 Var_Kind => Attributes (Index).Var_Kind,
789 Optional_Index => Attributes (Index).Opt_Index,
790 Attr_Kind => Attr_Kind,
793 First_Attr := Attrs.Last;
796 Package_Attributes.Increment_Last;
797 Package_Attributes.Table (Package_Attributes.Last) :=
800 First_Attribute => First_Attr);
801 end Register_New_Package;
803 ---------------------------
804 -- Set_Attribute_Kind_Of --
805 ---------------------------
807 procedure Set_Attribute_Kind_Of
808 (Attribute : Attribute_Node_Id;
812 if Attribute /= Empty_Attribute then
813 Attrs.Table (Attribute.Value).Attr_Kind := To;
815 end Set_Attribute_Kind_Of;
817 --------------------------
818 -- Set_Variable_Kind_Of --
819 --------------------------
821 procedure Set_Variable_Kind_Of
822 (Attribute : Attribute_Node_Id;
826 if Attribute /= Empty_Attribute then
827 Attrs.Table (Attribute.Value).Var_Kind := To;
829 end Set_Variable_Kind_Of;
831 ----------------------
832 -- Variable_Kind_Of --
833 ----------------------
835 function Variable_Kind_Of
836 (Attribute : Attribute_Node_Id) return Variable_Kind
839 if Attribute = Empty_Attribute then
842 return Attrs.Table (Attribute.Value).Var_Kind;
844 end Variable_Kind_Of;
846 ------------------------
847 -- First_Attribute_Of --
848 ------------------------
850 function First_Attribute_Of
851 (Pkg : Package_Node_Id) return Attribute_Node_Id
854 if Pkg = Empty_Package then
855 return Empty_Attribute;
858 (Value => Package_Attributes.Table (Pkg.Value).First_Attribute);
860 end First_Attribute_Of;