OSDN Git Service

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