[multiple changes]
[gcc.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-2010, 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 Opt;
29 with Osint; use Osint;
30 with Prj.Tree; use Prj.Tree;
31 with Sdefault;
32
33 package body Prj.Ext is
34
35 No_Project_Default_Dir : constant String := "-";
36 -- Indicator in the project path to indicate that the default search
37 -- directories should not be added to the path
38
39 Uninitialized_Prefix : constant String := '#' & Path_Separator;
40 -- Prefix to indicate that the project path has not been initilized yet.
41 -- Must be two characters long
42
43 procedure Initialize_Project_Path (Tree : Prj.Tree.Project_Node_Tree_Ref);
44 -- Initialize Current_Project_Path
45
46 ---------
47 -- Add --
48 ---------
49
50 procedure Add
51 (Tree : Prj.Tree.Project_Node_Tree_Ref;
52 External_Name : String;
53 Value : String)
54 is
55 The_Key : Name_Id;
56 The_Value : Name_Id;
57 begin
58 Name_Len := Value'Length;
59 Name_Buffer (1 .. Name_Len) := Value;
60 The_Value := Name_Find;
61 Name_Len := External_Name'Length;
62 Name_Buffer (1 .. Name_Len) := External_Name;
63 Canonical_Case_Env_Var_Name (Name_Buffer (1 .. Name_Len));
64 The_Key := Name_Find;
65 Name_To_Name_HTable.Set (Tree.External_References, The_Key, The_Value);
66 end Add;
67
68 ----------------------------------
69 -- Add_Search_Project_Directory --
70 ----------------------------------
71
72 procedure Add_Search_Project_Directory
73 (Tree : Prj.Tree.Project_Node_Tree_Ref;
74 Path : String)
75 is
76 Tmp : String_Access;
77 begin
78 if Tree.Project_Path = null then
79 Tree.Project_Path := new String'(Uninitialized_Prefix & Path);
80 else
81 Tmp := Tree.Project_Path;
82 Tree.Project_Path := new String'(Tmp.all & Path_Separator & Path);
83 Free (Tmp);
84 end if;
85 end Add_Search_Project_Directory;
86
87 -----------
88 -- Check --
89 -----------
90
91 function Check
92 (Tree : Prj.Tree.Project_Node_Tree_Ref;
93 Declaration : String) return Boolean
94 is
95 begin
96 for Equal_Pos in Declaration'Range loop
97 if Declaration (Equal_Pos) = '=' then
98 exit when Equal_Pos = Declaration'First;
99 Add
100 (Tree => Tree,
101 External_Name =>
102 Declaration (Declaration'First .. Equal_Pos - 1),
103 Value =>
104 Declaration (Equal_Pos + 1 .. Declaration'Last));
105 return True;
106 end if;
107 end loop;
108
109 return False;
110 end Check;
111
112 -----------------------------
113 -- Initialize_Project_Path --
114 -----------------------------
115
116 procedure Initialize_Project_Path (Tree : Prj.Tree.Project_Node_Tree_Ref) is
117 Add_Default_Dir : Boolean := True;
118 First : Positive;
119 Last : Positive;
120 New_Len : Positive;
121 New_Last : Positive;
122
123 Ada_Project_Path : constant String := "ADA_PROJECT_PATH";
124 Gpr_Project_Path : constant String := "GPR_PROJECT_PATH";
125 -- Name of alternate env. variable that contain path name(s) of
126 -- directories where project files may reside. GPR_PROJECT_PATH has
127 -- precedence over ADA_PROJECT_PATH.
128
129 Gpr_Prj_Path : String_Access := Getenv (Gpr_Project_Path);
130 Ada_Prj_Path : String_Access := Getenv (Ada_Project_Path);
131 -- The path name(s) of directories where project files may reside.
132 -- May be empty.
133
134 begin
135 -- The current directory is always first in the search path. Since the
136 -- Project_Path currently starts with '#:' as a sign that it isn't
137 -- initialized, we simply replace '#' with '.'
138
139 if Tree.Project_Path = null then
140 Tree.Project_Path := new String'('.' & Path_Separator);
141 else
142 Tree.Project_Path (Tree.Project_Path'First) := '.';
143 end if;
144
145 -- Then the reset of the project path (if any) currently contains the
146 -- directories added through Add_Search_Project_Directory
147
148 -- If environment variables are defined and not empty, add their content
149
150 if Gpr_Prj_Path.all /= "" then
151 Add_Search_Project_Directory (Tree, Gpr_Prj_Path.all);
152 end if;
153
154 Free (Gpr_Prj_Path);
155
156 if Ada_Prj_Path.all /= "" then
157 Add_Search_Project_Directory (Tree, Ada_Prj_Path.all);
158 end if;
159
160 Free (Ada_Prj_Path);
161
162 -- Copy to Name_Buffer, since we will need to manipulate the path
163
164 Name_Len := Tree.Project_Path'Length;
165 Name_Buffer (1 .. Name_Len) := Tree.Project_Path.all;
166
167 -- Scan the directory path to see if "-" is one of the directories.
168 -- Remove each occurrence of "-" and set Add_Default_Dir to False.
169 -- Also resolve relative paths and symbolic links.
170
171 First := 3;
172 loop
173 while First <= Name_Len
174 and then (Name_Buffer (First) = Path_Separator)
175 loop
176 First := First + 1;
177 end loop;
178
179 exit when First > Name_Len;
180
181 Last := First;
182
183 while Last < Name_Len
184 and then Name_Buffer (Last + 1) /= Path_Separator
185 loop
186 Last := Last + 1;
187 end loop;
188
189 -- If the directory is "-", set Add_Default_Dir to False and
190 -- remove from path.
191
192 if Name_Buffer (First .. Last) = No_Project_Default_Dir then
193 Add_Default_Dir := False;
194
195 for J in Last + 1 .. Name_Len loop
196 Name_Buffer (J - No_Project_Default_Dir'Length - 1) :=
197 Name_Buffer (J);
198 end loop;
199
200 Name_Len := Name_Len - No_Project_Default_Dir'Length - 1;
201
202 -- After removing the '-', go back one character to get the next
203 -- directory correctly.
204
205 Last := Last - 1;
206
207 elsif not Hostparm.OpenVMS
208 or else not Is_Absolute_Path (Name_Buffer (First .. Last))
209 then
210 -- On VMS, only expand relative path names, as absolute paths
211 -- may correspond to multi-valued VMS logical names.
212
213 declare
214 New_Dir : constant String :=
215 Normalize_Pathname
216 (Name_Buffer (First .. Last),
217 Resolve_Links => Opt.Follow_Links_For_Dirs);
218
219 begin
220 -- If the absolute path was resolved and is different from
221 -- the original, replace original with the resolved path.
222
223 if New_Dir /= Name_Buffer (First .. Last)
224 and then New_Dir'Length /= 0
225 then
226 New_Len := Name_Len + New_Dir'Length - (Last - First + 1);
227 New_Last := First + New_Dir'Length - 1;
228 Name_Buffer (New_Last + 1 .. New_Len) :=
229 Name_Buffer (Last + 1 .. Name_Len);
230 Name_Buffer (First .. New_Last) := New_Dir;
231 Name_Len := New_Len;
232 Last := New_Last;
233 end if;
234 end;
235 end if;
236
237 First := Last + 1;
238 end loop;
239
240 Free (Tree.Project_Path);
241
242 -- Set the initial value of Current_Project_Path
243
244 if Add_Default_Dir then
245 declare
246 Prefix : String_Ptr := Sdefault.Search_Dir_Prefix;
247
248 begin
249 if Prefix = null then
250 Prefix := new String'(Executable_Prefix_Path);
251
252 if Prefix.all /= "" then
253 if Tree.Target_Name /= null and then
254 Tree.Target_Name.all /= ""
255 then
256 Add_Str_To_Name_Buffer
257 (Path_Separator & Prefix.all &
258 "lib" & Directory_Separator & "gpr" &
259 Directory_Separator & Tree.Target_Name.all);
260 end if;
261
262 Add_Str_To_Name_Buffer
263 (Path_Separator & Prefix.all &
264 "share" & Directory_Separator & "gpr");
265 Add_Str_To_Name_Buffer
266 (Path_Separator & Prefix.all &
267 "lib" & Directory_Separator & "gnat");
268 end if;
269
270 else
271 Tree.Project_Path :=
272 new String'(Name_Buffer (1 .. Name_Len) & Path_Separator &
273 Prefix.all &
274 ".." & Directory_Separator &
275 ".." & Directory_Separator &
276 ".." & Directory_Separator & "gnat");
277 end if;
278
279 Free (Prefix);
280 end;
281 end if;
282
283 if Tree.Project_Path = null then
284 Tree.Project_Path := new String'(Name_Buffer (1 .. Name_Len));
285 end if;
286 end Initialize_Project_Path;
287
288 ------------------
289 -- Project_Path --
290 ------------------
291
292 function Project_Path (Tree : Project_Node_Tree_Ref) return String is
293 begin
294 if Tree.Project_Path = null
295 or else Tree.Project_Path (Tree.Project_Path'First) = '#'
296 then
297 Initialize_Project_Path (Tree);
298 end if;
299
300 return Tree.Project_Path.all;
301 end Project_Path;
302
303 -----------
304 -- Reset --
305 -----------
306
307 procedure Reset (Tree : Prj.Tree.Project_Node_Tree_Ref) is
308 begin
309 Name_To_Name_HTable.Reset (Tree.External_References);
310 end Reset;
311
312 ----------------------
313 -- Set_Project_Path --
314 ----------------------
315
316 procedure Set_Project_Path
317 (Tree : Project_Node_Tree_Ref;
318 New_Path : String) is
319 begin
320 Free (Tree.Project_Path);
321 Tree.Project_Path := new String'(New_Path);
322 end Set_Project_Path;
323
324 --------------
325 -- Value_Of --
326 --------------
327
328 function Value_Of
329 (Tree : Prj.Tree.Project_Node_Tree_Ref;
330 External_Name : Name_Id;
331 With_Default : Name_Id := No_Name)
332 return Name_Id
333 is
334 The_Value : Name_Id;
335 Name : String := Get_Name_String (External_Name);
336
337 begin
338 Canonical_Case_Env_Var_Name (Name);
339 Name_Len := Name'Length;
340 Name_Buffer (1 .. Name_Len) := Name;
341 The_Value :=
342 Name_To_Name_HTable.Get (Tree.External_References, Name_Find);
343
344 if The_Value /= No_Name then
345 return The_Value;
346 end if;
347
348 -- Find if it is an environment, if it is, put value in the hash table
349
350 declare
351 Env_Value : String_Access := Getenv (Name);
352
353 begin
354 if Env_Value /= null and then Env_Value'Length > 0 then
355 Name_Len := Env_Value'Length;
356 Name_Buffer (1 .. Name_Len) := Env_Value.all;
357 The_Value := Name_Find;
358 Name_To_Name_HTable.Set
359 (Tree.External_References, External_Name, The_Value);
360 Free (Env_Value);
361 return The_Value;
362
363 else
364 Free (Env_Value);
365 return With_Default;
366 end if;
367 end;
368 end Value_Of;
369
370 end Prj.Ext;