1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2006, 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
;
30 with System
.Case_Util
; use System
.Case_Util
;
32 package body Prj
.Attr
is
34 -- Data for predefined attributes and packages
38 -- Package names are preceded by 'P'
40 -- Attribute names are preceded by two letters:
42 -- The first letter is one of
44 -- 's' for Single with optional index
46 -- 'l' for List of strings with optional indexes
48 -- The second letter is one of
49 -- 'V' for single variable
50 -- 'A' for associative array
51 -- 'a' for case insensitive associative array
52 -- 'b' for associative array, case insensitive if file names are case
54 -- 'c' same as 'b', with optional index
56 -- End is indicated by two consecutive '#'
58 Initialization_Data
: constant String :=
66 "LVlocally_removed_files#" &
67 "SVsource_list_file#" &
71 "SVlibrary_version#" &
72 "LVlibrary_interface#" &
73 "SVlibrary_auto_init#" &
74 "LVlibrary_options#" &
75 "SVlibrary_src_dir#" &
76 "SVlibrary_ali_dir#" &
78 "SVlibrary_symbol_file#" &
79 "SVlibrary_symbol_policy#" &
80 "SVlibrary_reference_symbol_file#" &
85 "SVexternally_built#" &
90 "Saspecification_suffix#" &
92 "Saimplementation_suffix#" &
94 "SVseparate_suffix#" &
96 "SVdot_replacement#" &
101 "Laspecification_exceptions#" &
102 "Laimplementation_exceptions#" &
107 "Ladefault_switches#" &
109 "SVlocal_configuration_pragmas#" &
114 "Ladefault_switches#" &
117 "SVexecutable_suffix#" &
118 "SVglobal_configuration_pragmas#" &
128 "Ladefault_switches#" &
134 "Ladefault_switches#" &
136 "LVlinker_options#" &
138 -- package Cross_Reference
140 "Pcross_reference#" &
141 "Ladefault_switches#" &
147 "Ladefault_switches#" &
150 -- package Pretty_Printer
153 "Ladefault_switches#" &
159 "Ladefault_switches#" &
165 "Ladefault_switches#" &
171 "Ladefault_switches#" &
177 "Ladefault_switches#" &
183 "Ladefault_switches#" &
186 "SVcommunication_protocol#" &
187 "Sacompiler_command#" &
188 "SVdebugger_command#" &
191 "SVvcs_file_check#" &
194 -- package Language_Processing
196 "Planguage_processing#" &
197 "Lacompiler_driver#" &
199 "Ladependency_option#" &
200 "Lacompute_dependency#" &
201 "Lainclude_option#" &
203 "SVdefault_linker#" &
207 Initialized
: Boolean := False;
208 -- A flag to avoid multiple initialization
210 function Name_Id_Of
(Name
: String) return Name_Id
;
211 -- Returns the Name_Id for Name in lower case
213 -----------------------
214 -- Attribute_Kind_Of --
215 -----------------------
217 function Attribute_Kind_Of
218 (Attribute
: Attribute_Node_Id
) return Attribute_Kind
221 if Attribute
= Empty_Attribute
then
224 return Attrs
.Table
(Attribute
.Value
).Attr_Kind
;
226 end Attribute_Kind_Of
;
228 -----------------------
229 -- Attribute_Name_Of --
230 -----------------------
232 function Attribute_Name_Of
(Attribute
: Attribute_Node_Id
) return Name_Id
is
234 if Attribute
= Empty_Attribute
then
237 return Attrs
.Table
(Attribute
.Value
).Name
;
239 end Attribute_Name_Of
;
241 --------------------------
242 -- Attribute_Node_Id_Of --
243 --------------------------
245 function Attribute_Node_Id_Of
247 Starting_At
: Attribute_Node_Id
) return Attribute_Node_Id
249 Id
: Attr_Node_Id
:= Starting_At
.Value
;
252 while Id
/= Empty_Attr
253 and then Attrs
.Table
(Id
).Name
/= Name
255 Id
:= Attrs
.Table
(Id
).Next
;
258 return (Value
=> Id
);
259 end Attribute_Node_Id_Of
;
265 procedure Initialize
is
266 Start
: Positive := Initialization_Data
'First;
267 Finish
: Positive := Start
;
268 Current_Package
: Pkg_Node_Id
:= Empty_Pkg
;
269 Current_Attribute
: Attr_Node_Id
:= Empty_Attr
;
270 Is_An_Attribute
: Boolean := False;
271 Var_Kind
: Variable_Kind
:= Undefined
;
272 Optional_Index
: Boolean := False;
273 Attr_Kind
: Attribute_Kind
:= Single
;
274 Package_Name
: Name_Id
:= No_Name
;
275 Attribute_Name
: Name_Id
:= No_Name
;
276 First_Attribute
: Attr_Node_Id
:= Attr
.First_Attribute
;
278 function Attribute_Location
return String;
279 -- Returns a string depending if we are in the project level attributes
280 -- or in the attributes of a package.
282 ------------------------
283 -- Attribute_Location --
284 ------------------------
286 function Attribute_Location
return String is
288 if Package_Name
= No_Name
then
289 return "project level attributes";
292 return "attribute of package """ &
293 Get_Name_String
(Package_Name
) & """";
295 end Attribute_Location
;
297 -- Start of processing for Initialize
300 -- Don't allow Initialize action to be repeated
306 -- Make sure the two tables are empty
309 Package_Attributes
.Init
;
311 while Initialization_Data
(Start
) /= '#' loop
312 Is_An_Attribute
:= True;
313 case Initialization_Data
(Start
) is
316 -- New allowed package
321 while Initialization_Data
(Finish
) /= '#' loop
322 Finish
:= Finish
+ 1;
326 Name_Id_Of
(Initialization_Data
(Start
.. Finish
- 1));
328 for Index
in First_Package
.. Package_Attributes
.Last
loop
329 if Package_Name
= Package_Attributes
.Table
(Index
).Name
then
330 Osint
.Fail
("duplicate name """,
331 Initialization_Data
(Start
.. Finish
- 1),
332 """ in predefined packages.");
336 Is_An_Attribute
:= False;
337 Current_Attribute
:= Empty_Attr
;
338 Package_Attributes
.Increment_Last
;
339 Current_Package
:= Package_Attributes
.Last
;
340 Package_Attributes
.Table
(Current_Package
) :=
341 (Name
=> Package_Name
,
343 First_Attribute
=> Empty_Attr
);
348 Optional_Index
:= False;
352 Optional_Index
:= True;
356 Optional_Index
:= False;
360 Optional_Index
:= True;
366 if Is_An_Attribute
then
371 case Initialization_Data
(Start
) is
376 Attr_Kind
:= Associative_Array
;
379 Attr_Kind
:= Case_Insensitive_Associative_Array
;
382 if Osint
.File_Names_Case_Sensitive
then
383 Attr_Kind
:= Associative_Array
;
385 Attr_Kind
:= Case_Insensitive_Associative_Array
;
389 if Osint
.File_Names_Case_Sensitive
then
390 Attr_Kind
:= Optional_Index_Associative_Array
;
393 Optional_Index_Case_Insensitive_Associative_Array
;
403 while Initialization_Data
(Finish
) /= '#' loop
404 Finish
:= Finish
+ 1;
408 Name_Id_Of
(Initialization_Data
(Start
.. Finish
- 1));
409 Attrs
.Increment_Last
;
411 if Current_Attribute
= Empty_Attr
then
412 First_Attribute
:= Attrs
.Last
;
414 if Current_Package
/= Empty_Pkg
then
415 Package_Attributes
.Table
(Current_Package
).First_Attribute
420 -- Check that there are no duplicate attributes
422 for Index
in First_Attribute
.. Attrs
.Last
- 1 loop
423 if Attribute_Name
= Attrs
.Table
(Index
).Name
then
424 Osint
.Fail
("duplicate attribute """,
425 Initialization_Data
(Start
.. Finish
- 1),
426 """ in " & Attribute_Location
);
430 Attrs
.Table
(Current_Attribute
).Next
:=
434 Current_Attribute
:= Attrs
.Last
;
435 Attrs
.Table
(Current_Attribute
) :=
436 (Name
=> Attribute_Name
,
437 Var_Kind
=> Var_Kind
,
438 Optional_Index
=> Optional_Index
,
439 Attr_Kind
=> Attr_Kind
,
452 function Name_Id_Of
(Name
: String) return Name_Id
is
455 Add_Str_To_Name_Buffer
(Name
);
456 To_Lower
(Name_Buffer
(1 .. Name_Len
));
464 function Next_Attribute
465 (After
: Attribute_Node_Id
) return Attribute_Node_Id
468 if After
= Empty_Attribute
then
469 return Empty_Attribute
;
471 return (Value
=> Attrs
.Table
(After
.Value
).Next
);
475 -----------------------
476 -- Optional_Index_Of --
477 -----------------------
479 function Optional_Index_Of
(Attribute
: Attribute_Node_Id
) return Boolean is
481 if Attribute
= Empty_Attribute
then
484 return Attrs
.Table
(Attribute
.Value
).Optional_Index
;
486 end Optional_Index_Of
;
488 ------------------------
489 -- Package_Node_Id_Of --
490 ------------------------
492 function Package_Node_Id_Of
(Name
: Name_Id
) return Package_Node_Id
is
494 for Index
in Package_Attributes
.First
.. Package_Attributes
.Last
loop
495 if Package_Attributes
.Table
(Index
).Name
= Name
then
496 return (Value
=> Index
);
500 -- If there is no package with this name, return Empty_Package
502 return Empty_Package
;
503 end Package_Node_Id_Of
;
505 ----------------------------
506 -- Register_New_Attribute --
507 ----------------------------
509 procedure Register_New_Attribute
511 In_Package
: Package_Node_Id
;
512 Attr_Kind
: Defined_Attribute_Kind
;
513 Var_Kind
: Defined_Variable_Kind
;
514 Index_Is_File_Name
: Boolean := False;
515 Opt_Index
: Boolean := False)
518 First_Attr
: Attr_Node_Id
:= Empty_Attr
;
519 Curr_Attr
: Attr_Node_Id
;
520 Real_Attr_Kind
: Attribute_Kind
;
523 if Name
'Length = 0 then
524 Fail
("cannot register an attribute with no name");
528 if In_Package
= Empty_Package
then
529 Fail
("attempt to add attribute """, Name
,
530 """ to an undefined package");
534 Attr_Name
:= Name_Id_Of
(Name
);
537 Package_Attributes
.Table
(In_Package
.Value
).First_Attribute
;
539 -- Check if attribute name is a duplicate
541 Curr_Attr
:= First_Attr
;
542 while Curr_Attr
/= Empty_Attr
loop
543 if Attrs
.Table
(Curr_Attr
).Name
= Attr_Name
then
544 Fail
("duplicate attribute name """, Name
,
547 (Package_Attributes
.Table
(In_Package
.Value
).Name
) &
552 Curr_Attr
:= Attrs
.Table
(Curr_Attr
).Next
;
555 Real_Attr_Kind
:= Attr_Kind
;
557 -- If Index_Is_File_Name, change the attribute kind if necessary
559 if Index_Is_File_Name
and then not Osint
.File_Names_Case_Sensitive
then
561 when Associative_Array
=>
562 Real_Attr_Kind
:= Case_Insensitive_Associative_Array
;
564 when Optional_Index_Associative_Array
=>
566 Optional_Index_Case_Insensitive_Associative_Array
;
573 -- Add the new attribute
575 Attrs
.Increment_Last
;
576 Attrs
.Table
(Attrs
.Last
) :=
578 Var_Kind
=> Var_Kind
,
579 Optional_Index
=> Opt_Index
,
580 Attr_Kind
=> Real_Attr_Kind
,
582 Package_Attributes
.Table
(In_Package
.Value
).First_Attribute
:=
584 end Register_New_Attribute
;
586 --------------------------
587 -- Register_New_Package --
588 --------------------------
590 procedure Register_New_Package
(Name
: String; Id
: out Package_Node_Id
) is
594 if Name
'Length = 0 then
595 Fail
("cannot register a package with no name");
600 Pkg_Name
:= Name_Id_Of
(Name
);
602 for Index
in Package_Attributes
.First
.. Package_Attributes
.Last
loop
603 if Package_Attributes
.Table
(Index
).Name
= Pkg_Name
then
604 Fail
("cannot register a package with a non unique name""",
611 Package_Attributes
.Increment_Last
;
612 Id
:= (Value
=> Package_Attributes
.Last
);
613 Package_Attributes
.Table
(Package_Attributes
.Last
) :=
614 (Name
=> Pkg_Name
, Known
=> True, First_Attribute
=> Empty_Attr
);
615 end Register_New_Package
;
617 procedure Register_New_Package
619 Attributes
: Attribute_Data_Array
)
623 First_Attr
: Attr_Node_Id
:= Empty_Attr
;
624 Curr_Attr
: Attr_Node_Id
;
625 Attr_Kind
: Attribute_Kind
;
628 if Name
'Length = 0 then
629 Fail
("cannot register a package with no name");
633 Pkg_Name
:= Name_Id_Of
(Name
);
635 for Index
in Package_Attributes
.First
.. Package_Attributes
.Last
loop
636 if Package_Attributes
.Table
(Index
).Name
= Pkg_Name
then
637 Fail
("cannot register a package with a non unique name""",
643 for Index
in Attributes
'Range loop
644 Attr_Name
:= Name_Id_Of
(Attributes
(Index
).Name
);
646 Curr_Attr
:= First_Attr
;
647 while Curr_Attr
/= Empty_Attr
loop
648 if Attrs
.Table
(Curr_Attr
).Name
= Attr_Name
then
649 Fail
("duplicate attribute name """, Attributes
(Index
).Name
,
650 """ in new package """ & Name
& """");
654 Curr_Attr
:= Attrs
.Table
(Curr_Attr
).Next
;
657 Attr_Kind
:= Attributes
(Index
).Attr_Kind
;
659 if Attributes
(Index
).Index_Is_File_Name
660 and then not Osint
.File_Names_Case_Sensitive
663 when Associative_Array
=>
664 Attr_Kind
:= Case_Insensitive_Associative_Array
;
666 when Optional_Index_Associative_Array
=>
668 Optional_Index_Case_Insensitive_Associative_Array
;
675 Attrs
.Increment_Last
;
676 Attrs
.Table
(Attrs
.Last
) :=
678 Var_Kind
=> Attributes
(Index
).Var_Kind
,
679 Optional_Index
=> Attributes
(Index
).Opt_Index
,
680 Attr_Kind
=> Attr_Kind
,
682 First_Attr
:= Attrs
.Last
;
685 Package_Attributes
.Increment_Last
;
686 Package_Attributes
.Table
(Package_Attributes
.Last
) :=
687 (Name
=> Pkg_Name
, Known
=> True, First_Attribute
=> First_Attr
);
688 end Register_New_Package
;
690 ---------------------------
691 -- Set_Attribute_Kind_Of --
692 ---------------------------
694 procedure Set_Attribute_Kind_Of
695 (Attribute
: Attribute_Node_Id
;
699 if Attribute
/= Empty_Attribute
then
700 Attrs
.Table
(Attribute
.Value
).Attr_Kind
:= To
;
702 end Set_Attribute_Kind_Of
;
704 --------------------------
705 -- Set_Variable_Kind_Of --
706 --------------------------
708 procedure Set_Variable_Kind_Of
709 (Attribute
: Attribute_Node_Id
;
713 if Attribute
/= Empty_Attribute
then
714 Attrs
.Table
(Attribute
.Value
).Var_Kind
:= To
;
716 end Set_Variable_Kind_Of
;
718 ----------------------
719 -- Variable_Kind_Of --
720 ----------------------
722 function Variable_Kind_Of
723 (Attribute
: Attribute_Node_Id
) return Variable_Kind
726 if Attribute
= Empty_Attribute
then
729 return Attrs
.Table
(Attribute
.Value
).Var_Kind
;
731 end Variable_Kind_Of
;
733 ------------------------
734 -- First_Attribute_Of --
735 ------------------------
737 function First_Attribute_Of
738 (Pkg
: Package_Node_Id
) return Attribute_Node_Id
741 if Pkg
= Empty_Package
then
742 return Empty_Attribute
;
745 (Value
=> Package_Attributes
.Table
(Pkg
.Value
).First_Attribute
);
747 end First_Attribute_Of
;