OSDN Git Service

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