OSDN Git Service

2007-09-26 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / prj-ext.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                              P R J . E X T                               --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 2000-2007, Free Software Foundation, Inc.         --
10 --                                                                          --
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.          --
20 --                                                                          --
21 -- GNAT was originally developed  by the GNAT team at  New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
23 --                                                                          --
24 ------------------------------------------------------------------------------
25
26 with Hostparm;
27 with Makeutl;  use Makeutl;
28 with Output;   use Output;
29 with Osint;    use Osint;
30 with Sdefault;
31 with Table;
32
33 with GNAT.HTable;
34
35 package body Prj.Ext is
36
37    Ada_Project_Path : constant String := "ADA_PROJECT_PATH";
38    --  Name of alternate env. variable that contain path name(s) of directories
39    --  where project files may reside. GPR_PROJECT_PATH has precedence over
40    --  ADA_PROJECT_PATH.
41
42    Gpr_Prj_Path : constant String_Access := Getenv (Gpr_Project_Path);
43    Ada_Prj_Path : constant String_Access := Getenv (Ada_Project_Path);
44    --  The path name(s) of directories where project files may reside.
45    --  May be empty.
46
47    No_Project_Default_Dir : constant String := "-";
48
49    Current_Project_Path : String_Access;
50    --  The project path. Initialized by procedure Initialize_Project_Path
51    --  below.
52
53    procedure Initialize_Project_Path;
54    --  Initialize Current_Project_Path
55
56    package Htable is new GNAT.HTable.Simple_HTable
57      (Header_Num => Header_Num,
58       Element    => Name_Id,
59       No_Element => No_Name,
60       Key        => Name_Id,
61       Hash       => Hash,
62       Equal      => "=");
63    --  External references are stored in this hash table, either by procedure
64    --  Add (directly or through a call to function Check) or by function
65    --  Value_Of when an environment variable is found non empty. Value_Of
66    --  first for external reference in this table, before checking the
67    --  environment. Htable is emptied (reset) by procedure Reset.
68
69    ---------
70    package Search_Directories is new Table.Table
71      (Table_Component_Type => Name_Id,
72       Table_Index_Type     => Natural,
73       Table_Low_Bound      => 1,
74       Table_Initial        => 4,
75       Table_Increment      => 100,
76       Table_Name           => "Prj.Ext.Search_Directories");
77    --  The table for the directories specified with -aP switches
78
79    -- Add --
80    ---------
81
82    procedure Add
83      (External_Name : String;
84       Value         : String)
85    is
86       The_Key   : Name_Id;
87       The_Value : Name_Id;
88    begin
89       Name_Len := Value'Length;
90       Name_Buffer (1 .. Name_Len) := Value;
91       The_Value := Name_Find;
92       Name_Len := External_Name'Length;
93       Name_Buffer (1 .. Name_Len) := External_Name;
94       Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
95       The_Key := Name_Find;
96       Htable.Set (The_Key, The_Value);
97    end Add;
98
99    -----------
100    ----------------------------------
101    -- Add_Search_Project_Directory --
102    ----------------------------------
103
104    procedure Add_Search_Project_Directory (Path : String) is
105    begin
106       Name_Len := 0;
107       Add_Str_To_Name_Buffer (Path);
108       Search_Directories.Append (Name_Find);
109    end Add_Search_Project_Directory;
110
111    -- Check --
112    -----------
113
114    function Check (Declaration : String) return Boolean is
115    begin
116       for Equal_Pos in Declaration'Range loop
117          if Declaration (Equal_Pos) = '=' then
118             exit when Equal_Pos = Declaration'First;
119             exit when Equal_Pos = Declaration'Last;
120             Add
121               (External_Name =>
122                  Declaration (Declaration'First .. Equal_Pos - 1),
123                Value =>
124                  Declaration (Equal_Pos + 1 .. Declaration'Last));
125             return True;
126          end if;
127       end loop;
128
129       return False;
130    end Check;
131
132    -----------------------------
133    -- Initialize_Project_Path --
134    -----------------------------
135
136    procedure Initialize_Project_Path is
137       Add_Default_Dir : Boolean := True;
138       First           : Positive;
139       Last            : Positive;
140       New_Len         : Positive;
141       New_Last        : Positive;
142       Prj_Path        : String_Access := Gpr_Prj_Path;
143
144    begin
145       if Get_Mode = Ada_Only then
146          if Gpr_Prj_Path.all /= "" then
147
148             --  Warn if both environment variables are defined
149
150             if Ada_Prj_Path.all /= "" then
151                Write_Line
152                  ("Warning: ADA_PROJECT_PATH is not taken into account");
153                Write_Line ("         when GPR_PROJECT_PATH is defined");
154             end if;
155
156          else
157             Prj_Path := Ada_Prj_Path;
158          end if;
159       end if;
160
161       --  The current directory is always first
162
163       Name_Len := 1;
164       Name_Buffer (Name_Len) := '.';
165
166       --  If there are directories in the Search_Directories table, add them
167
168       for J in 1 .. Search_Directories.Last loop
169          Name_Len := Name_Len + 1;
170          Name_Buffer (Name_Len) := Path_Separator;
171          Add_Str_To_Name_Buffer
172            (Get_Name_String (Search_Directories.Table (J)));
173       end loop;
174
175       --  If environment variable is defined and not empty, add its content
176
177       if Prj_Path.all /= "" then
178          Name_Len := Name_Len + 1;
179          Name_Buffer (Name_Len) := Path_Separator;
180
181          Add_Str_To_Name_Buffer (Prj_Path.all);
182       end if;
183
184       --  Scan the directory path to see if "-" is one of the directories.
185       --  Remove each occurence of "-" and set Add_Default_Dir to False.
186       --  Also resolve relative paths and symbolic links.
187
188       First := 3;
189       loop
190          while First <= Name_Len
191            and then (Name_Buffer (First) = Path_Separator)
192          loop
193             First := First + 1;
194          end loop;
195
196          exit when First > Name_Len;
197
198          Last := First;
199
200          while Last < Name_Len
201            and then Name_Buffer (Last + 1) /= Path_Separator
202          loop
203             Last := Last + 1;
204          end loop;
205
206          --  If the directory is "-", set Add_Default_Dir to False and
207          --  remove from path.
208
209          if Name_Buffer (First .. Last) = No_Project_Default_Dir then
210             Add_Default_Dir := False;
211
212             for J in Last + 1 .. Name_Len loop
213                Name_Buffer (J - No_Project_Default_Dir'Length - 1) :=
214                  Name_Buffer (J);
215             end loop;
216
217             Name_Len := Name_Len - No_Project_Default_Dir'Length - 1;
218
219             --  After removing the '-', go back one character to get the next
220             --  directory corectly.
221
222             Last := Last - 1;
223
224          elsif not Hostparm.OpenVMS
225            or else not Is_Absolute_Path (Name_Buffer (First .. Last))
226          then
227             --  On VMS, only expand relative path names, as absolute paths
228             --  may correspond to multi-valued VMS logical names.
229
230             declare
231                New_Dir : constant String :=
232                            Normalize_Pathname (Name_Buffer (First .. Last));
233
234             begin
235                --  If the absolute path was resolved and is different from
236                --  the original, replace original with the resolved path.
237
238                if New_Dir /= Name_Buffer (First .. Last)
239                  and then New_Dir'Length /= 0
240                then
241                   New_Len := Name_Len + New_Dir'Length - (Last - First + 1);
242                   New_Last := First + New_Dir'Length - 1;
243                   Name_Buffer (New_Last + 1 .. New_Len) :=
244                     Name_Buffer (Last + 1 .. Name_Len);
245                   Name_Buffer (First .. New_Last) := New_Dir;
246                   Name_Len := New_Len;
247                   Last := New_Last;
248                end if;
249             end;
250          end if;
251
252          First := Last + 1;
253       end loop;
254
255       --  Set the initial value of Current_Project_Path
256
257       if Add_Default_Dir then
258          declare
259             Prefix : String_Ptr := Sdefault.Search_Dir_Prefix;
260          begin
261             if Prefix = null then
262                Prefix := new String'(Executable_Prefix_Path);
263
264                if Prefix.all /= "" then
265                   if Get_Mode = Ada_Only then
266                      Current_Project_Path :=
267                        new String'(Name_Buffer (1 .. Name_Len) &
268                                    Path_Separator &
269                                    Prefix.all & Directory_Separator & "gnat");
270
271                   else
272                      Current_Project_Path :=
273                        new String'(Name_Buffer (1 .. Name_Len) &
274                                    Path_Separator &
275                                    Prefix.all & Directory_Separator &
276                                    "share" & Directory_Separator & "gpr");
277                   end if;
278                end if;
279
280             else
281                Current_Project_Path :=
282                  new String'(Name_Buffer (1 .. Name_Len) & Path_Separator &
283                              Prefix.all &
284                              ".." &  Directory_Separator &
285                              ".." & Directory_Separator &
286                              ".." & Directory_Separator & "gnat");
287             end if;
288          end;
289       end if;
290
291       if Current_Project_Path = null then
292          Current_Project_Path := new String'(Name_Buffer (1 .. Name_Len));
293       end if;
294    end Initialize_Project_Path;
295
296    ------------------
297    -- Project_Path --
298    ------------------
299
300    function Project_Path return String is
301    begin
302       if Current_Project_Path = null then
303          Initialize_Project_Path;
304       end if;
305
306       return Current_Project_Path.all;
307    end Project_Path;
308
309    -----------
310    -- Reset --
311    -----------
312
313    procedure Reset is
314    begin
315       Htable.Reset;
316    end Reset;
317
318    ----------------------
319    -- Set_Project_Path --
320    ----------------------
321
322    procedure Set_Project_Path (New_Path : String) is
323    begin
324       Free (Current_Project_Path);
325       Current_Project_Path := new String'(New_Path);
326    end Set_Project_Path;
327
328    --------------
329    -- Value_Of --
330    --------------
331
332    function Value_Of
333      (External_Name : Name_Id;
334       With_Default  : Name_Id := No_Name)
335       return          Name_Id
336    is
337       The_Value : Name_Id;
338       Name      : String := Get_Name_String (External_Name);
339
340    begin
341       Canonical_Case_File_Name (Name);
342       Name_Len := Name'Length;
343       Name_Buffer (1 .. Name_Len) := Name;
344       The_Value := Htable.Get (Name_Find);
345
346       if The_Value /= No_Name then
347          return The_Value;
348       end if;
349
350       --  Find if it is an environment, if it is, put value in the hash table
351
352       declare
353          Env_Value : String_Access := Getenv (Name);
354
355       begin
356          if Env_Value /= null and then Env_Value'Length > 0 then
357             Name_Len := Env_Value'Length;
358             Name_Buffer (1 .. Name_Len) := Env_Value.all;
359             The_Value := Name_Find;
360             Htable.Set (External_Name, The_Value);
361             Free (Env_Value);
362             return The_Value;
363
364          else
365             Free (Env_Value);
366             return With_Default;
367          end if;
368       end;
369    end Value_Of;
370
371 end Prj.Ext;