]>
Commit | Line | Data |
---|---|---|
38cbfe40 RK |
1 | ------------------------------------------------------------------------------ |
2 | -- -- | |
3 | -- GNAT COMPILER COMPONENTS -- | |
4 | -- -- | |
5 | -- G N A T C M D -- | |
6 | -- -- | |
7 | -- B o d y -- | |
8 | -- -- | |
fbf5a39b | 9 | -- Copyright (C) 1996-2003 Free Software Foundation, Inc. -- |
38cbfe40 RK |
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, 59 Temple Place - Suite 330, Boston, -- | |
20 | -- MA 02111-1307, USA. -- | |
21 | -- -- | |
22 | -- GNAT was originally developed by the GNAT team at New York University. -- | |
71ff80dc | 23 | -- Extensive contributions were provided by Ada Core Technologies Inc. -- |
38cbfe40 RK |
24 | -- -- |
25 | ------------------------------------------------------------------------------ | |
26 | ||
07fc65c4 | 27 | with GNAT.Directory_Operations; use GNAT.Directory_Operations; |
38cbfe40 | 28 | |
07fc65c4 | 29 | with Csets; |
fbf5a39b | 30 | with MLib.Tgt; use MLib.Tgt; |
07fc65c4 GB |
31 | with MLib.Utl; |
32 | with Namet; use Namet; | |
33 | with Opt; | |
38cbfe40 | 34 | with Osint; use Osint; |
07fc65c4 GB |
35 | with Output; |
36 | with Prj; use Prj; | |
37 | with Prj.Env; | |
38 | with Prj.Ext; use Prj.Ext; | |
39 | with Prj.Pars; | |
40 | with Prj.Util; use Prj.Util; | |
07fc65c4 | 41 | with Snames; use Snames; |
07fc65c4 GB |
42 | with Table; |
43 | with Types; use Types; | |
38cbfe40 RK |
44 | with Hostparm; use Hostparm; |
45 | -- Used to determine if we are in VMS or not for error message purposes | |
46 | ||
07fc65c4 GB |
47 | with Ada.Characters.Handling; use Ada.Characters.Handling; |
48 | with Ada.Command_Line; use Ada.Command_Line; | |
49 | with Ada.Text_IO; use Ada.Text_IO; | |
50 | ||
38cbfe40 RK |
51 | with GNAT.OS_Lib; use GNAT.OS_Lib; |
52 | ||
53 | with Table; | |
54 | ||
fbf5a39b | 55 | with VMS_Conv; use VMS_Conv; |
07fc65c4 | 56 | |
fbf5a39b | 57 | procedure GNATCmd is |
07fc65c4 GB |
58 | Project_File : String_Access; |
59 | Project : Prj.Project_Id; | |
60 | Current_Verbosity : Prj.Verbosity := Prj.Default; | |
61 | Tool_Package_Name : Name_Id := No_Name; | |
62 | ||
63 | -- This flag indicates a switch -p (for gnatxref and gnatfind) for | |
64 | -- an old fashioned project file. -p cannot be used in conjonction | |
65 | -- with -P. | |
66 | ||
67 | Old_Project_File_Used : Boolean := False; | |
68 | ||
07fc65c4 GB |
69 | -- A table to keep the switches from the project file |
70 | ||
71 | package First_Switches is new Table.Table | |
72 | (Table_Component_Type => String_Access, | |
73 | Table_Index_Type => Integer, | |
74 | Table_Low_Bound => 1, | |
75 | Table_Initial => 20, | |
76 | Table_Increment => 100, | |
77 | Table_Name => "Gnatcmd.First_Switches"); | |
78 | ||
fbf5a39b AC |
79 | package Library_Paths is new Table.Table ( |
80 | Table_Component_Type => String_Access, | |
81 | Table_Index_Type => Integer, | |
82 | Table_Low_Bound => 1, | |
83 | Table_Initial => 20, | |
84 | Table_Increment => 100, | |
85 | Table_Name => "Make.Library_Path"); | |
07fc65c4 | 86 | |
fbf5a39b AC |
87 | -- Packages of project files to pass to Prj.Pars.Parse, depending on the |
88 | -- tool. We allocate objects because we cannot declare aliased objects | |
89 | -- as we are in a procedure, not a library level package. | |
38cbfe40 | 90 | |
fbf5a39b AC |
91 | Naming_String : constant String_Access := new String'("naming"); |
92 | Binder_String : constant String_Access := new String'("binder"); | |
93 | Eliminate_String : constant String_Access := new String'("eliminate"); | |
94 | Finder_String : constant String_Access := new String'("finder"); | |
95 | Linker_String : constant String_Access := new String'("linker"); | |
96 | Gnatls_String : constant String_Access := new String'("gnatls"); | |
97 | Pretty_String : constant String_Access := new String'("pretty_printer"); | |
98 | Gnatstub_String : constant String_Access := new String'("gnatstub"); | |
99 | Xref_String : constant String_Access := new String'("cross_reference"); | |
38cbfe40 | 100 | |
fbf5a39b AC |
101 | Packages_To_Check_By_Binder : constant String_List_Access := |
102 | new String_List'((Naming_String, Binder_String)); | |
07fc65c4 | 103 | |
fbf5a39b AC |
104 | Packages_To_Check_By_Eliminate : constant String_List_Access := |
105 | new String_List'((Naming_String, Eliminate_String)); | |
07fc65c4 | 106 | |
fbf5a39b AC |
107 | Packages_To_Check_By_Finder : constant String_List_Access := |
108 | new String_List'((Naming_String, Finder_String)); | |
07fc65c4 | 109 | |
fbf5a39b AC |
110 | Packages_To_Check_By_Linker : constant String_List_Access := |
111 | new String_List'((Naming_String, Linker_String)); | |
07fc65c4 | 112 | |
fbf5a39b AC |
113 | Packages_To_Check_By_Gnatls : constant String_List_Access := |
114 | new String_List'((Naming_String, Gnatls_String)); | |
38cbfe40 | 115 | |
fbf5a39b AC |
116 | Packages_To_Check_By_Pretty : constant String_List_Access := |
117 | new String_List'((Naming_String, Pretty_String)); | |
38cbfe40 | 118 | |
fbf5a39b AC |
119 | Packages_To_Check_By_Gnatstub : constant String_List_Access := |
120 | new String_List'((Naming_String, Gnatstub_String)); | |
38cbfe40 | 121 | |
fbf5a39b AC |
122 | Packages_To_Check_By_Xref : constant String_List_Access := |
123 | new String_List'((Naming_String, Xref_String)); | |
07fc65c4 | 124 | |
fbf5a39b | 125 | Packages_To_Check : String_List_Access := Prj.All_Packages; |
38cbfe40 RK |
126 | |
127 | ---------------------------------- | |
128 | -- Declarations for GNATCMD use -- | |
129 | ---------------------------------- | |
130 | ||
fbf5a39b | 131 | The_Command : Command_Type; |
38cbfe40 | 132 | |
07fc65c4 GB |
133 | Command_Arg : Positive := 1; |
134 | ||
38cbfe40 RK |
135 | My_Exit_Status : Exit_Status := Success; |
136 | ||
fbf5a39b | 137 | Current_Work_Dir : constant String := Get_Current_Dir; |
38cbfe40 RK |
138 | |
139 | ----------------------- | |
140 | -- Local Subprograms -- | |
141 | ----------------------- | |
142 | ||
fbf5a39b AC |
143 | procedure Check_Relative_Executable (Name : in out String_Access); |
144 | -- Check if an executable is specified as a relative path. | |
145 | -- If it is, and the path contains directory information, fail. | |
146 | -- Otherwise, prepend the exec directory. | |
147 | -- This procedure is only used for GNAT LINK when a project file | |
148 | -- is specified. | |
149 | ||
150 | function Configuration_Pragmas_File return Name_Id; | |
151 | -- Return an argument, if there is a configuration pragmas file to be | |
152 | -- specified for Project, otherwise return No_Name. | |
153 | -- Used for gnatstub (GNAT STUB), gnatpp (GNAT PRETTY) and gnatelim | |
154 | -- (GNAT ELIM). | |
155 | ||
156 | procedure Delete_Temp_Config_Files; | |
157 | -- Delete all temporary config files | |
158 | ||
07fc65c4 GB |
159 | function Index (Char : Character; Str : String) return Natural; |
160 | -- Returns the first occurrence of Char in Str. | |
161 | -- Returns 0 if Char is not in Str. | |
162 | ||
07fc65c4 GB |
163 | procedure Non_VMS_Usage; |
164 | -- Display usage for platforms other than VMS | |
165 | ||
07fc65c4 GB |
166 | procedure Set_Library_For |
167 | (Project : Project_Id; | |
168 | There_Are_Libraries : in out Boolean); | |
169 | -- If Project is a library project, add the correct | |
170 | -- -L and -l switches to the linker invocation. | |
171 | ||
172 | procedure Set_Libraries is | |
173 | new For_Every_Project_Imported (Boolean, Set_Library_For); | |
174 | -- Add the -L and -l switches to the linker for all | |
175 | -- of the library projects. | |
176 | ||
fbf5a39b AC |
177 | procedure Test_If_Relative_Path |
178 | (Switch : in out String_Access; | |
179 | Parent : String); | |
180 | -- Test if Switch is a relative search path switch. | |
181 | -- If it is and it includes directory information, prepend the path with | |
182 | -- Parent.This subprogram is only called when using project files. | |
07fc65c4 | 183 | |
fbf5a39b AC |
184 | ------------------------------- |
185 | -- Check_Relative_Executable -- | |
186 | ------------------------------- | |
38cbfe40 | 187 | |
fbf5a39b AC |
188 | procedure Check_Relative_Executable (Name : in out String_Access) is |
189 | Exec_File_Name : constant String := Name.all; | |
38cbfe40 RK |
190 | |
191 | begin | |
fbf5a39b AC |
192 | if not Is_Absolute_Path (Exec_File_Name) then |
193 | for Index in Exec_File_Name'Range loop | |
194 | if Exec_File_Name (Index) = Directory_Separator then | |
195 | Fail ("relative executable (""" & | |
196 | Exec_File_Name & | |
197 | """) with directory part not allowed " & | |
198 | "when using project files"); | |
199 | end if; | |
200 | end loop; | |
38cbfe40 | 201 | |
fbf5a39b AC |
202 | Get_Name_String (Projects.Table |
203 | (Project).Exec_Directory); | |
38cbfe40 | 204 | |
fbf5a39b AC |
205 | if Name_Buffer (Name_Len) /= Directory_Separator then |
206 | Name_Len := Name_Len + 1; | |
207 | Name_Buffer (Name_Len) := Directory_Separator; | |
208 | end if; | |
38cbfe40 | 209 | |
fbf5a39b AC |
210 | Name_Buffer (Name_Len + 1 .. |
211 | Name_Len + Exec_File_Name'Length) := | |
212 | Exec_File_Name; | |
213 | Name_Len := Name_Len + Exec_File_Name'Length; | |
214 | Name := new String'(Name_Buffer (1 .. Name_Len)); | |
38cbfe40 | 215 | end if; |
fbf5a39b | 216 | end Check_Relative_Executable; |
38cbfe40 | 217 | |
fbf5a39b AC |
218 | -------------------------------- |
219 | -- Configuration_Pragmas_File -- | |
220 | -------------------------------- | |
38cbfe40 | 221 | |
fbf5a39b AC |
222 | function Configuration_Pragmas_File return Name_Id is |
223 | begin | |
224 | Prj.Env.Create_Config_Pragmas_File | |
225 | (Project, Project, Include_Config_Files => False); | |
226 | return Projects.Table (Project).Config_File_Name; | |
227 | end Configuration_Pragmas_File; | |
38cbfe40 | 228 | |
fbf5a39b AC |
229 | ------------------------------ |
230 | -- Delete_Temp_Config_Files -- | |
231 | ------------------------------ | |
38cbfe40 | 232 | |
fbf5a39b AC |
233 | procedure Delete_Temp_Config_Files is |
234 | Success : Boolean; | |
38cbfe40 RK |
235 | |
236 | begin | |
fbf5a39b AC |
237 | if Project /= No_Project then |
238 | for Prj in 1 .. Projects.Last loop | |
239 | if Projects.Table (Prj).Config_File_Temp then | |
240 | if Opt.Verbose_Mode then | |
241 | Output.Write_Str ("Deleting temp configuration file """); | |
242 | Output.Write_Str (Get_Name_String | |
243 | (Projects.Table (Prj).Config_File_Name)); | |
244 | Output.Write_Line (""""); | |
245 | end if; | |
38cbfe40 | 246 | |
fbf5a39b AC |
247 | Delete_File |
248 | (Name => Get_Name_String | |
249 | (Projects.Table (Prj).Config_File_Name), | |
250 | Success => Success); | |
251 | end if; | |
252 | end loop; | |
253 | end if; | |
254 | end Delete_Temp_Config_Files; | |
38cbfe40 | 255 | |
fbf5a39b AC |
256 | ----------- |
257 | -- Index -- | |
258 | ----------- | |
38cbfe40 | 259 | |
fbf5a39b | 260 | function Index (Char : Character; Str : String) return Natural is |
38cbfe40 | 261 | begin |
fbf5a39b AC |
262 | for Index in Str'Range loop |
263 | if Str (Index) = Char then | |
264 | return Index; | |
38cbfe40 RK |
265 | end if; |
266 | end loop; | |
267 | ||
fbf5a39b AC |
268 | return 0; |
269 | end Index; | |
38cbfe40 | 270 | |
fbf5a39b AC |
271 | --------------------- |
272 | -- Set_Library_For -- | |
273 | --------------------- | |
38cbfe40 | 274 | |
fbf5a39b AC |
275 | procedure Set_Library_For |
276 | (Project : Project_Id; | |
277 | There_Are_Libraries : in out Boolean) | |
278 | is | |
279 | Path_Option : constant String_Access := | |
280 | MLib.Tgt.Linker_Library_Path_Option; | |
38cbfe40 RK |
281 | |
282 | begin | |
fbf5a39b | 283 | -- Case of library project |
38cbfe40 | 284 | |
fbf5a39b AC |
285 | if Projects.Table (Project).Library then |
286 | There_Are_Libraries := True; | |
38cbfe40 | 287 | |
fbf5a39b | 288 | -- Add the -L switch |
07fc65c4 GB |
289 | |
290 | Last_Switches.Increment_Last; | |
291 | Last_Switches.Table (Last_Switches.Last) := | |
292 | new String'("-L" & | |
293 | Get_Name_String | |
294 | (Projects.Table (Project).Library_Dir)); | |
295 | ||
296 | -- Add the -l switch | |
297 | ||
298 | Last_Switches.Increment_Last; | |
299 | Last_Switches.Table (Last_Switches.Last) := | |
fbf5a39b AC |
300 | new String'("-l" & |
301 | Get_Name_String | |
302 | (Projects.Table (Project).Library_Name)); | |
38cbfe40 | 303 | |
fbf5a39b AC |
304 | -- Add the directory to table Library_Paths, to be processed later |
305 | -- if library is not static and if Path_Option is not null. | |
38cbfe40 | 306 | |
fbf5a39b AC |
307 | if Projects.Table (Project).Library_Kind /= Static |
308 | and then Path_Option /= null | |
309 | then | |
310 | Library_Paths.Increment_Last; | |
311 | Library_Paths.Table (Library_Paths.Last) := | |
312 | new String'(Get_Name_String | |
313 | (Projects.Table (Project).Library_Dir)); | |
07fc65c4 | 314 | end if; |
38cbfe40 | 315 | |
07fc65c4 | 316 | end if; |
fbf5a39b | 317 | end Set_Library_For; |
38cbfe40 | 318 | |
fbf5a39b AC |
319 | --------------------------- |
320 | -- Test_If_Relative_Path -- | |
321 | --------------------------- | |
38cbfe40 | 322 | |
fbf5a39b AC |
323 | procedure Test_If_Relative_Path |
324 | (Switch : in out String_Access; | |
325 | Parent : String) | |
326 | is | |
327 | begin | |
328 | if Switch /= null then | |
38cbfe40 | 329 | |
07fc65c4 | 330 | declare |
fbf5a39b AC |
331 | Sw : String (1 .. Switch'Length); |
332 | Start : Positive := 1; | |
38cbfe40 | 333 | |
07fc65c4 | 334 | begin |
fbf5a39b | 335 | Sw := Switch.all; |
38cbfe40 | 336 | |
fbf5a39b AC |
337 | if Sw (1) = '-' then |
338 | if Sw'Length >= 3 | |
339 | and then (Sw (2) = 'A' | |
340 | or else Sw (2) = 'I' | |
341 | or else Sw (2) = 'L') | |
342 | then | |
343 | Start := 3; | |
07fc65c4 | 344 | |
fbf5a39b AC |
345 | if Sw = "-I-" then |
346 | return; | |
07fc65c4 | 347 | end if; |
07fc65c4 | 348 | |
fbf5a39b AC |
349 | elsif Sw'Length >= 4 |
350 | and then (Sw (2 .. 3) = "aL" | |
351 | or else Sw (2 .. 3) = "aO" | |
352 | or else Sw (2 .. 3) = "aI") | |
353 | then | |
354 | Start := 4; | |
38cbfe40 | 355 | |
fbf5a39b AC |
356 | elsif Sw'Length >= 7 |
357 | and then Sw (2 .. 6) = "-RTS=" | |
358 | then | |
359 | Start := 7; | |
07fc65c4 | 360 | else |
fbf5a39b | 361 | return; |
38cbfe40 | 362 | end if; |
fbf5a39b AC |
363 | end if; |
364 | ||
365 | -- If the path is relative, test if it includes directory | |
366 | -- information. If it does, prepend Parent to the path. | |
367 | ||
368 | if not Is_Absolute_Path (Sw (Start .. Sw'Last)) then | |
369 | for J in Start .. Sw'Last loop | |
370 | if Sw (J) = Directory_Separator then | |
371 | Switch := | |
372 | new String' | |
373 | (Sw (1 .. Start - 1) & | |
374 | Parent & | |
375 | Directory_Separator & | |
376 | Sw (Start .. Sw'Last)); | |
377 | return; | |
378 | end if; | |
379 | end loop; | |
380 | end if; | |
07fc65c4 GB |
381 | end; |
382 | end if; | |
fbf5a39b AC |
383 | end Test_If_Relative_Path; |
384 | ||
385 | ------------------- | |
386 | -- Non_VMS_Usage -- | |
387 | ------------------- | |
388 | ||
389 | procedure Non_VMS_Usage is | |
390 | begin | |
391 | Output_Version; | |
392 | New_Line; | |
393 | Put_Line ("List of available commands"); | |
394 | New_Line; | |
395 | ||
396 | for C in Command_List'Range loop | |
397 | if not Command_List (C).VMS_Only then | |
398 | Put ("GNAT " & Command_List (C).Cname.all); | |
399 | Set_Col (25); | |
400 | Put (Command_List (C).Unixcmd.all); | |
401 | ||
402 | declare | |
403 | Sws : Argument_List_Access renames Command_List (C).Unixsws; | |
404 | begin | |
405 | if Sws /= null then | |
406 | for J in Sws'Range loop | |
407 | Put (' '); | |
408 | Put (Sws (J).all); | |
409 | end loop; | |
410 | end if; | |
411 | end; | |
412 | ||
413 | New_Line; | |
414 | end if; | |
415 | end loop; | |
416 | ||
417 | New_Line; | |
418 | Put_Line ("Commands FIND, LIST, PRETTY, STUB and XREF accept " & | |
419 | "project file switches -vPx, -Pprj and -Xnam=val"); | |
420 | New_Line; | |
421 | end Non_VMS_Usage; | |
38cbfe40 | 422 | |
07fc65c4 GB |
423 | ------------------------------------- |
424 | -- Start of processing for GNATCmd -- | |
425 | ------------------------------------- | |
426 | ||
427 | begin | |
428 | -- Initializations | |
38cbfe40 | 429 | |
07fc65c4 GB |
430 | Namet.Initialize; |
431 | Csets.Initialize; | |
38cbfe40 | 432 | |
07fc65c4 | 433 | Snames.Initialize; |
38cbfe40 | 434 | |
07fc65c4 | 435 | Prj.Initialize; |
38cbfe40 | 436 | |
07fc65c4 GB |
437 | Last_Switches.Init; |
438 | Last_Switches.Set_Last (0); | |
439 | ||
440 | First_Switches.Init; | |
441 | First_Switches.Set_Last (0); | |
38cbfe40 | 442 | |
fbf5a39b AC |
443 | VMS_Conv.Initialize; |
444 | ||
07fc65c4 GB |
445 | -- If on VMS, or if VMS emulation is on, convert VMS style /qualifiers, |
446 | -- filenames and pathnames to Unix style. | |
38cbfe40 | 447 | |
07fc65c4 GB |
448 | if Hostparm.OpenVMS |
449 | or else To_Lower (Getenv ("EMULATE_VMS").all) = "true" | |
38cbfe40 | 450 | then |
07fc65c4 GB |
451 | VMS_Conversion (The_Command); |
452 | ||
453 | -- If not on VMS, scan the command line directly | |
38cbfe40 | 454 | |
38cbfe40 | 455 | else |
07fc65c4 GB |
456 | if Argument_Count = 0 then |
457 | Non_VMS_Usage; | |
458 | return; | |
459 | else | |
460 | begin | |
461 | if Argument_Count > 1 and then Argument (1) = "-v" then | |
462 | Opt.Verbose_Mode := True; | |
463 | Command_Arg := 2; | |
464 | end if; | |
38cbfe40 | 465 | |
07fc65c4 | 466 | The_Command := Real_Command_Type'Value (Argument (Command_Arg)); |
38cbfe40 | 467 | |
07fc65c4 GB |
468 | if Command_List (The_Command).VMS_Only then |
469 | Non_VMS_Usage; | |
fbf5a39b AC |
470 | Fail |
471 | ("Command """, | |
472 | Command_List (The_Command).Cname.all, | |
473 | """ can only be used on VMS"); | |
07fc65c4 | 474 | end if; |
fbf5a39b | 475 | |
07fc65c4 GB |
476 | exception |
477 | when Constraint_Error => | |
478 | ||
479 | -- Check if it is an alternate command | |
fbf5a39b | 480 | |
07fc65c4 GB |
481 | declare |
482 | Alternate : Alternate_Command; | |
483 | ||
484 | begin | |
485 | Alternate := Alternate_Command'Value | |
486 | (Argument (Command_Arg)); | |
487 | The_Command := Corresponding_To (Alternate); | |
488 | ||
489 | exception | |
490 | when Constraint_Error => | |
491 | Non_VMS_Usage; | |
fbf5a39b | 492 | Fail ("Unknown command: ", Argument (Command_Arg)); |
07fc65c4 GB |
493 | end; |
494 | end; | |
38cbfe40 | 495 | |
07fc65c4 GB |
496 | for Arg in Command_Arg + 1 .. Argument_Count loop |
497 | Last_Switches.Increment_Last; | |
498 | Last_Switches.Table (Last_Switches.Last) := | |
499 | new String'(Argument (Arg)); | |
38cbfe40 | 500 | end loop; |
07fc65c4 GB |
501 | end if; |
502 | end if; | |
38cbfe40 | 503 | |
07fc65c4 GB |
504 | declare |
505 | Program : constant String := | |
fbf5a39b | 506 | Program_Name (Command_List (The_Command).Unixcmd.all).all; |
38cbfe40 | 507 | |
07fc65c4 | 508 | Exec_Path : String_Access; |
38cbfe40 | 509 | |
07fc65c4 GB |
510 | begin |
511 | -- Locate the executable for the command | |
38cbfe40 | 512 | |
07fc65c4 | 513 | Exec_Path := Locate_Exec_On_Path (Program); |
38cbfe40 | 514 | |
07fc65c4 GB |
515 | if Exec_Path = null then |
516 | Put_Line (Standard_Error, "Couldn't locate " & Program); | |
517 | raise Error_Exit; | |
518 | end if; | |
519 | ||
520 | -- If there are switches for the executable, put them as first switches | |
521 | ||
522 | if Command_List (The_Command).Unixsws /= null then | |
523 | for J in Command_List (The_Command).Unixsws'Range loop | |
524 | First_Switches.Increment_Last; | |
525 | First_Switches.Table (First_Switches.Last) := | |
526 | Command_List (The_Command).Unixsws (J); | |
527 | end loop; | |
528 | end if; | |
529 | ||
fbf5a39b AC |
530 | -- For BIND, FIND, LINK, LIST, PRETTY ad XREF, look for project file |
531 | -- related switches. | |
07fc65c4 GB |
532 | |
533 | if The_Command = Bind | |
fbf5a39b | 534 | or else The_Command = Elim |
07fc65c4 GB |
535 | or else The_Command = Find |
536 | or else The_Command = Link | |
537 | or else The_Command = List | |
538 | or else The_Command = Xref | |
fbf5a39b AC |
539 | or else The_Command = Pretty |
540 | or else The_Command = Stub | |
07fc65c4 GB |
541 | then |
542 | case The_Command is | |
543 | when Bind => | |
544 | Tool_Package_Name := Name_Binder; | |
fbf5a39b AC |
545 | Packages_To_Check := Packages_To_Check_By_Binder; |
546 | when Elim => | |
547 | Tool_Package_Name := Name_Eliminate; | |
548 | Packages_To_Check := Packages_To_Check_By_Eliminate; | |
07fc65c4 GB |
549 | when Find => |
550 | Tool_Package_Name := Name_Finder; | |
fbf5a39b | 551 | Packages_To_Check := Packages_To_Check_By_Finder; |
07fc65c4 GB |
552 | when Link => |
553 | Tool_Package_Name := Name_Linker; | |
fbf5a39b | 554 | Packages_To_Check := Packages_To_Check_By_Linker; |
07fc65c4 GB |
555 | when List => |
556 | Tool_Package_Name := Name_Gnatls; | |
fbf5a39b AC |
557 | Packages_To_Check := Packages_To_Check_By_Gnatls; |
558 | when Pretty => | |
559 | Tool_Package_Name := Name_Pretty_Printer; | |
560 | Packages_To_Check := Packages_To_Check_By_Pretty; | |
561 | when Stub => | |
562 | Tool_Package_Name := Name_Gnatstub; | |
563 | Packages_To_Check := Packages_To_Check_By_Gnatstub; | |
07fc65c4 GB |
564 | when Xref => |
565 | Tool_Package_Name := Name_Cross_Reference; | |
fbf5a39b | 566 | Packages_To_Check := Packages_To_Check_By_Xref; |
07fc65c4 GB |
567 | when others => |
568 | null; | |
569 | end case; | |
570 | ||
fbf5a39b AC |
571 | -- Check that the switches are consistent. |
572 | -- Detect project file related switches. | |
573 | ||
574 | Inspect_Switches : | |
07fc65c4 GB |
575 | declare |
576 | Arg_Num : Positive := 1; | |
577 | Argv : String_Access; | |
578 | ||
579 | procedure Remove_Switch (Num : Positive); | |
580 | -- Remove a project related switch from table Last_Switches | |
581 | ||
582 | ------------------- | |
583 | -- Remove_Switch -- | |
584 | ------------------- | |
585 | ||
586 | procedure Remove_Switch (Num : Positive) is | |
587 | begin | |
588 | Last_Switches.Table (Num .. Last_Switches.Last - 1) := | |
589 | Last_Switches.Table (Num + 1 .. Last_Switches.Last); | |
590 | Last_Switches.Decrement_Last; | |
591 | end Remove_Switch; | |
592 | ||
fbf5a39b | 593 | -- Start of processing for Inspect_Switches |
07fc65c4 GB |
594 | |
595 | begin | |
596 | while Arg_Num <= Last_Switches.Last loop | |
597 | Argv := Last_Switches.Table (Arg_Num); | |
598 | ||
599 | if Argv (Argv'First) = '-' then | |
600 | if Argv'Length = 1 then | |
fbf5a39b AC |
601 | Fail |
602 | ("switch character cannot be followed by a blank"); | |
07fc65c4 GB |
603 | end if; |
604 | ||
605 | -- The two style project files (-p and -P) cannot be used | |
606 | -- together | |
607 | ||
608 | if (The_Command = Find or else The_Command = Xref) | |
609 | and then Argv (2) = 'p' | |
610 | then | |
611 | Old_Project_File_Used := True; | |
612 | if Project_File /= null then | |
613 | Fail ("-P and -p cannot be used together"); | |
614 | end if; | |
615 | end if; | |
616 | ||
617 | -- -vPx Specify verbosity while parsing project files | |
618 | ||
619 | if Argv'Length = 4 | |
620 | and then Argv (Argv'First + 1 .. Argv'First + 2) = "vP" | |
621 | then | |
622 | case Argv (Argv'Last) is | |
623 | when '0' => | |
624 | Current_Verbosity := Prj.Default; | |
625 | when '1' => | |
626 | Current_Verbosity := Prj.Medium; | |
627 | when '2' => | |
628 | Current_Verbosity := Prj.High; | |
629 | when others => | |
fbf5a39b | 630 | Fail ("Invalid switch: ", Argv.all); |
07fc65c4 GB |
631 | end case; |
632 | ||
633 | Remove_Switch (Arg_Num); | |
634 | ||
635 | -- -Pproject_file Specify project file to be used | |
636 | ||
fbf5a39b | 637 | elsif Argv (Argv'First + 1) = 'P' then |
07fc65c4 GB |
638 | |
639 | -- Only one -P switch can be used | |
640 | ||
641 | if Project_File /= null then | |
fbf5a39b AC |
642 | Fail |
643 | (Argv.all, | |
644 | ": second project file forbidden (first is """, | |
645 | Project_File.all & """)"); | |
07fc65c4 GB |
646 | |
647 | -- The two style project files (-p and -P) cannot be | |
648 | -- used together. | |
649 | ||
650 | elsif Old_Project_File_Used then | |
651 | Fail ("-p and -P cannot be used together"); | |
38cbfe40 | 652 | |
fbf5a39b AC |
653 | elsif Argv'Length = 2 then |
654 | -- There is space between -P and the project file | |
655 | -- name. -P cannot be the last option. | |
656 | ||
657 | if Arg_Num = Last_Switches.Last then | |
658 | Fail ("project file name missing after -P"); | |
659 | ||
660 | else | |
661 | Remove_Switch (Arg_Num); | |
662 | Argv := Last_Switches.Table (Arg_Num); | |
663 | ||
664 | -- After -P, there must be a project file name, | |
665 | -- not another switch. | |
666 | ||
667 | if Argv (Argv'First) = '-' then | |
668 | Fail ("project file name missing after -P"); | |
669 | ||
670 | else | |
671 | Project_File := new String'(Argv.all); | |
672 | end if; | |
673 | end if; | |
674 | ||
38cbfe40 | 675 | else |
fbf5a39b AC |
676 | -- No space between -P and project file name |
677 | ||
07fc65c4 GB |
678 | Project_File := |
679 | new String'(Argv (Argv'First + 2 .. Argv'Last)); | |
38cbfe40 | 680 | end if; |
07fc65c4 GB |
681 | |
682 | Remove_Switch (Arg_Num); | |
683 | ||
684 | -- -Xexternal=value Specify an external reference to be | |
685 | -- used in project files | |
686 | ||
687 | elsif Argv'Length >= 5 | |
688 | and then Argv (Argv'First + 1) = 'X' | |
689 | then | |
690 | declare | |
691 | Equal_Pos : constant Natural := | |
692 | Index ('=', Argv (Argv'First + 2 .. Argv'Last)); | |
693 | begin | |
694 | if Equal_Pos >= Argv'First + 3 and then | |
695 | Equal_Pos /= Argv'Last then | |
696 | Add (External_Name => | |
697 | Argv (Argv'First + 2 .. Equal_Pos - 1), | |
698 | Value => Argv (Equal_Pos + 1 .. Argv'Last)); | |
699 | else | |
fbf5a39b AC |
700 | Fail |
701 | (Argv.all, | |
702 | " is not a valid external assignment."); | |
07fc65c4 GB |
703 | end if; |
704 | end; | |
705 | ||
706 | Remove_Switch (Arg_Num); | |
707 | ||
708 | else | |
709 | Arg_Num := Arg_Num + 1; | |
38cbfe40 | 710 | end if; |
38cbfe40 | 711 | |
07fc65c4 GB |
712 | else |
713 | Arg_Num := Arg_Num + 1; | |
714 | end if; | |
715 | end loop; | |
fbf5a39b | 716 | end Inspect_Switches; |
07fc65c4 GB |
717 | end if; |
718 | ||
719 | -- If there is a project file specified, parse it, get the switches | |
720 | -- for the tool and setup PATH environment variables. | |
721 | ||
722 | if Project_File /= null then | |
723 | Prj.Pars.Set_Verbosity (To => Current_Verbosity); | |
724 | ||
725 | Prj.Pars.Parse | |
726 | (Project => Project, | |
fbf5a39b AC |
727 | Project_File_Name => Project_File.all, |
728 | Packages_To_Check => Packages_To_Check); | |
07fc65c4 GB |
729 | |
730 | if Project = Prj.No_Project then | |
fbf5a39b | 731 | Fail ("""", Project_File.all, """ processing failed"); |
07fc65c4 GB |
732 | end if; |
733 | ||
734 | -- Check if a package with the name of the tool is in the project | |
735 | -- file and if there is one, get the switches, if any, and scan them. | |
736 | ||
737 | declare | |
fbf5a39b AC |
738 | Data : constant Prj.Project_Data := |
739 | Prj.Projects.Table (Project); | |
740 | ||
741 | Pkg : constant Prj.Package_Id := | |
742 | Prj.Util.Value_Of | |
743 | (Name => Tool_Package_Name, | |
744 | In_Packages => Data.Decl.Packages); | |
07fc65c4 GB |
745 | |
746 | Element : Package_Element; | |
747 | ||
748 | Default_Switches_Array : Array_Element_Id; | |
749 | ||
750 | The_Switches : Prj.Variable_Value; | |
751 | Current : Prj.String_List_Id; | |
752 | The_String : String_Element; | |
753 | ||
754 | begin | |
755 | if Pkg /= No_Package then | |
756 | Element := Packages.Table (Pkg); | |
757 | ||
758 | -- Packages Gnatls has a single attribute Switches, that is | |
759 | -- not an associative array. | |
760 | ||
761 | if The_Command = List then | |
762 | The_Switches := | |
763 | Prj.Util.Value_Of | |
764 | (Variable_Name => Snames.Name_Switches, | |
765 | In_Variables => Element.Decl.Attributes); | |
766 | ||
767 | -- Packages Binder (for gnatbind), Cross_Reference (for | |
fbf5a39b AC |
768 | -- gnatxref), Linker (for gnatlink) Finder (for gnatfind), |
769 | -- Pretty_Printer (for gnatpp) and Eliminate (for gnatelim) | |
770 | -- have an attributed Switches, an associative array, indexed | |
771 | -- by the name of the file. | |
772 | -- They also have an attribute Default_Switches, indexed | |
773 | -- by the name of the programming language. | |
07fc65c4 | 774 | |
fbf5a39b AC |
775 | else |
776 | if The_Switches.Kind = Prj.Undefined then | |
777 | Default_Switches_Array := | |
778 | Prj.Util.Value_Of | |
779 | (Name => Name_Default_Switches, | |
780 | In_Arrays => Packages.Table (Pkg).Decl.Arrays); | |
781 | The_Switches := Prj.Util.Value_Of | |
782 | (Index => Name_Ada, | |
783 | In_Array => Default_Switches_Array); | |
784 | end if; | |
07fc65c4 GB |
785 | end if; |
786 | ||
787 | -- If there are switches specified in the package of the | |
788 | -- project file corresponding to the tool, scan them. | |
789 | ||
790 | case The_Switches.Kind is | |
791 | when Prj.Undefined => | |
792 | null; | |
793 | ||
794 | when Prj.Single => | |
fbf5a39b AC |
795 | declare |
796 | Switch : constant String := | |
797 | Get_Name_String (The_Switches.Value); | |
798 | ||
799 | begin | |
800 | if Switch'Length > 0 then | |
801 | First_Switches.Increment_Last; | |
802 | First_Switches.Table (First_Switches.Last) := | |
803 | new String'(Switch); | |
804 | end if; | |
805 | end; | |
07fc65c4 GB |
806 | |
807 | when Prj.List => | |
808 | Current := The_Switches.Values; | |
809 | while Current /= Prj.Nil_String loop | |
810 | The_String := String_Elements.Table (Current); | |
811 | ||
fbf5a39b AC |
812 | declare |
813 | Switch : constant String := | |
814 | Get_Name_String (The_String.Value); | |
815 | ||
816 | begin | |
817 | if Switch'Length > 0 then | |
818 | First_Switches.Increment_Last; | |
819 | First_Switches.Table (First_Switches.Last) := | |
820 | new String'(Switch); | |
821 | end if; | |
822 | end; | |
07fc65c4 GB |
823 | |
824 | Current := The_String.Next; | |
825 | end loop; | |
826 | end case; | |
38cbfe40 | 827 | end if; |
07fc65c4 GB |
828 | end; |
829 | ||
fbf5a39b AC |
830 | if The_Command = Bind |
831 | or else The_Command = Link | |
832 | or else The_Command = Elim | |
833 | then | |
07fc65c4 GB |
834 | Change_Dir |
835 | (Get_Name_String | |
836 | (Projects.Table (Project).Object_Directory)); | |
837 | end if; | |
838 | ||
fbf5a39b AC |
839 | -- Set up the env vars for project path files |
840 | ||
841 | Prj.Env.Set_Ada_Paths (Project, Including_Libraries => False); | |
842 | ||
843 | -- For gnatstub, gnatpp and gnatelim, create a configuration pragmas | |
844 | -- file, if necessary. | |
845 | ||
846 | if The_Command = Pretty | |
847 | or else The_Command = Stub | |
848 | or else The_Command = Elim | |
849 | then | |
850 | declare | |
851 | CP_File : constant Name_Id := Configuration_Pragmas_File; | |
852 | ||
853 | begin | |
854 | if CP_File /= No_Name then | |
855 | First_Switches.Increment_Last; | |
856 | ||
857 | if The_Command = Elim then | |
858 | First_Switches.Table (First_Switches.Last) := | |
859 | new String'("-C" & Get_Name_String (CP_File)); | |
860 | ||
861 | else | |
862 | First_Switches.Table (First_Switches.Last) := | |
863 | new String'("-gnatec=" & Get_Name_String (CP_File)); | |
864 | end if; | |
865 | end if; | |
866 | end; | |
867 | end if; | |
868 | ||
07fc65c4 GB |
869 | if The_Command = Link then |
870 | ||
871 | -- Add the default search directories, to be able to find | |
872 | -- libgnat in call to MLib.Utl.Lib_Directory. | |
873 | ||
874 | Add_Default_Search_Dirs; | |
875 | ||
876 | declare | |
877 | There_Are_Libraries : Boolean := False; | |
fbf5a39b AC |
878 | Path_Option : constant String_Access := |
879 | MLib.Tgt.Linker_Library_Path_Option; | |
07fc65c4 GB |
880 | |
881 | begin | |
fbf5a39b AC |
882 | Library_Paths.Set_Last (0); |
883 | ||
07fc65c4 GB |
884 | -- Check if there are library project files |
885 | ||
fbf5a39b | 886 | if MLib.Tgt.Support_For_Libraries /= MLib.Tgt.None then |
07fc65c4 GB |
887 | Set_Libraries (Project, There_Are_Libraries); |
888 | end if; | |
889 | ||
890 | -- If there are, add the necessary additional switches | |
891 | ||
892 | if There_Are_Libraries then | |
893 | ||
894 | -- Add -L<lib_dir> -lgnarl -lgnat -Wl,-rpath,<lib_dir> | |
895 | ||
896 | Last_Switches.Increment_Last; | |
897 | Last_Switches.Table (Last_Switches.Last) := | |
898 | new String'("-L" & MLib.Utl.Lib_Directory); | |
899 | Last_Switches.Increment_Last; | |
900 | Last_Switches.Table (Last_Switches.Last) := | |
901 | new String'("-lgnarl"); | |
902 | Last_Switches.Increment_Last; | |
903 | Last_Switches.Table (Last_Switches.Last) := | |
904 | new String'("-lgnat"); | |
905 | ||
fbf5a39b AC |
906 | -- If Path_Option is not null, create the switch |
907 | -- ("-Wl,-rpath," or equivalent) with all the library dirs | |
908 | -- plus the standard GNAT library dir. | |
909 | ||
910 | if Path_Option /= null then | |
911 | declare | |
912 | Option : String_Access; | |
913 | Length : Natural := Path_Option'Length; | |
914 | Current : Natural; | |
915 | ||
916 | begin | |
917 | -- First, compute the exact length for the switch | |
918 | ||
919 | for Index in | |
920 | Library_Paths.First .. Library_Paths.Last | |
921 | loop | |
922 | -- Add the length of the library dir plus one | |
923 | -- for the directory separator. | |
924 | ||
925 | Length := | |
926 | Length + | |
927 | Library_Paths.Table (Index)'Length + 1; | |
928 | end loop; | |
929 | ||
930 | -- Finally, add the length of the standard GNAT | |
931 | -- library dir. | |
932 | ||
933 | Length := Length + MLib.Utl.Lib_Directory'Length; | |
934 | Option := new String (1 .. Length); | |
935 | Option (1 .. Path_Option'Length) := Path_Option.all; | |
936 | Current := Path_Option'Length; | |
937 | ||
938 | -- Put each library dir followed by a dir separator | |
939 | ||
940 | for Index in | |
941 | Library_Paths.First .. Library_Paths.Last | |
942 | loop | |
943 | Option | |
944 | (Current + 1 .. | |
945 | Current + | |
946 | Library_Paths.Table (Index)'Length) := | |
947 | Library_Paths.Table (Index).all; | |
948 | Current := | |
949 | Current + | |
950 | Library_Paths.Table (Index)'Length + 1; | |
951 | Option (Current) := Path_Separator; | |
952 | end loop; | |
953 | ||
954 | -- Finally put the standard GNAT library dir | |
955 | ||
956 | Option | |
957 | (Current + 1 .. | |
958 | Current + MLib.Utl.Lib_Directory'Length) := | |
959 | MLib.Utl.Lib_Directory; | |
960 | ||
961 | -- And add the switch to the last switches | |
07fc65c4 | 962 | |
07fc65c4 GB |
963 | Last_Switches.Increment_Last; |
964 | Last_Switches.Table (Last_Switches.Last) := | |
965 | Option; | |
fbf5a39b AC |
966 | end; |
967 | end if; | |
968 | end if; | |
969 | end; | |
970 | ||
971 | -- Check if the first ALI file specified can be found, either | |
972 | -- in the object directory of the main project or in an object | |
973 | -- directory of a project file extended by the main project. | |
974 | -- If the ALI file can be found, replace its name with its | |
975 | -- absolute path. | |
976 | ||
977 | declare | |
978 | Skip_Executable : Boolean := False; | |
979 | ||
980 | begin | |
981 | Switch_Loop : for J in 1 .. Last_Switches.Last loop | |
982 | ||
983 | -- If we have an executable just reset the flag | |
984 | ||
985 | if Skip_Executable then | |
986 | Skip_Executable := False; | |
987 | ||
988 | -- If -o, set flag so that next switch is not processed | |
989 | ||
990 | elsif Last_Switches.Table (J).all = "-o" then | |
991 | Skip_Executable := True; | |
992 | ||
993 | -- Normal case | |
994 | ||
995 | else | |
996 | declare | |
997 | Switch : constant String := | |
998 | Last_Switches.Table (J).all; | |
999 | ||
1000 | ALI_File : constant String (1 .. Switch'Length + 4) := | |
1001 | Switch & ".ali"; | |
1002 | ||
1003 | Last : Natural := Switch'Length; | |
1004 | Test_Existence : Boolean := False; | |
1005 | ||
1006 | begin | |
1007 | -- Skip real switches | |
1008 | ||
1009 | if Switch'Length /= 0 and then | |
1010 | Switch (Switch'First) /= '-' | |
1011 | then | |
1012 | -- Append ".ali" if file name does not end with it | |
1013 | ||
1014 | if Switch'Length <= 4 or else | |
1015 | Switch (Switch'Last - 3 .. Switch'Last) /= ".ali" | |
1016 | then | |
1017 | Last := ALI_File'Last; | |
1018 | end if; | |
1019 | ||
1020 | -- If file name includes directory information, | |
1021 | -- stop if ALI file exists. | |
1022 | ||
1023 | if Is_Absolute_Path (ALI_File (1 .. Last)) then | |
1024 | Test_Existence := True; | |
1025 | ||
1026 | else | |
1027 | for K in Switch'Range loop | |
1028 | if Switch (K) = '/' or else | |
1029 | Switch (K) = Directory_Separator | |
1030 | then | |
1031 | Test_Existence := True; | |
1032 | exit; | |
1033 | end if; | |
1034 | end loop; | |
1035 | end if; | |
1036 | ||
1037 | if Test_Existence then | |
1038 | if Is_Regular_File (ALI_File (1 .. Last)) then | |
1039 | exit Switch_Loop; | |
1040 | end if; | |
1041 | ||
1042 | else | |
1043 | -- Look in the object directories if the ALI | |
1044 | -- file exists. | |
1045 | ||
1046 | declare | |
1047 | Prj : Project_Id := Project; | |
1048 | begin | |
1049 | Project_Loop : | |
1050 | loop | |
1051 | declare | |
1052 | Dir : constant String := | |
1053 | Get_Name_String | |
1054 | (Projects.Table (Prj). | |
1055 | Object_Directory); | |
1056 | begin | |
1057 | if Is_Regular_File | |
1058 | (Dir & Directory_Separator & | |
1059 | ALI_File (1 .. Last)) | |
1060 | then | |
1061 | -- We have found the correct | |
1062 | -- project, so we replace the file | |
1063 | -- with the absolute path. | |
1064 | ||
1065 | Last_Switches.Table (J) := | |
1066 | new String' | |
1067 | (Dir & Directory_Separator & | |
1068 | ALI_File (1 .. Last)); | |
1069 | ||
1070 | -- And we are done | |
1071 | ||
1072 | exit Switch_Loop; | |
1073 | end if; | |
1074 | end; | |
1075 | ||
1076 | -- Go to the project being extended, | |
1077 | -- if any. | |
1078 | ||
1079 | Prj := Projects.Table (Prj).Extends; | |
1080 | exit Project_Loop when Prj = No_Project; | |
1081 | end loop Project_Loop; | |
1082 | end; | |
1083 | end if; | |
1084 | end if; | |
1085 | end; | |
1086 | end if; | |
1087 | end loop Switch_Loop; | |
1088 | end; | |
1089 | ||
1090 | -- If a relative path output file has been specified, we add | |
1091 | -- the exec directory. | |
1092 | ||
1093 | declare | |
1094 | Look_For_Executable : Boolean := True; | |
1095 | ||
1096 | begin | |
1097 | ||
1098 | for J in reverse 1 .. Last_Switches.Last - 1 loop | |
1099 | if Last_Switches.Table (J).all = "-o" then | |
1100 | Check_Relative_Executable | |
1101 | (Name => Last_Switches.Table (J + 1)); | |
1102 | Look_For_Executable := False; | |
1103 | exit; | |
1104 | end if; | |
1105 | end loop; | |
1106 | ||
1107 | if Look_For_Executable then | |
1108 | for J in reverse 1 .. First_Switches.Last - 1 loop | |
1109 | if First_Switches.Table (J).all = "-o" then | |
1110 | Look_For_Executable := False; | |
1111 | Check_Relative_Executable | |
1112 | (Name => First_Switches.Table (J + 1)); | |
1113 | exit; | |
1114 | end if; | |
1115 | end loop; | |
1116 | end if; | |
1117 | ||
1118 | -- If no executable is specified, then find the name | |
1119 | -- of the first ALI file on the command line and issue | |
1120 | -- a -o switch with the absolute path of the executable | |
1121 | -- in the exec directory. | |
1122 | ||
1123 | if Look_For_Executable then | |
1124 | for J in 1 .. Last_Switches.Last loop | |
1125 | declare | |
1126 | Arg : constant String_Access := | |
1127 | Last_Switches.Table (J); | |
1128 | Last : Natural := 0; | |
1129 | ||
1130 | begin | |
1131 | if Arg'Length /= 0 and then Arg (Arg'First) /= '-' then | |
1132 | if Arg'Length > 4 | |
1133 | and then Arg (Arg'Last - 3 .. Arg'Last) = ".ali" | |
1134 | then | |
1135 | Last := Arg'Last - 4; | |
1136 | ||
1137 | elsif Is_Regular_File (Arg.all & ".ali") then | |
1138 | Last := Arg'Last; | |
1139 | end if; | |
1140 | ||
1141 | if Last /= 0 then | |
1142 | declare | |
1143 | Executable_Name : constant String := | |
1144 | Base_Name (Arg (Arg'First .. Last)); | |
1145 | begin | |
1146 | Last_Switches.Increment_Last; | |
1147 | Last_Switches.Table (Last_Switches.Last) := | |
1148 | new String'("-o"); | |
1149 | Get_Name_String | |
1150 | (Projects.Table (Project).Exec_Directory); | |
1151 | Last_Switches.Increment_Last; | |
1152 | Last_Switches.Table (Last_Switches.Last) := | |
1153 | new String'(Name_Buffer (1 .. Name_Len) & | |
1154 | Directory_Separator & | |
1155 | Executable_Name & | |
1156 | Get_Executable_Suffix.all); | |
1157 | exit; | |
1158 | end; | |
1159 | end if; | |
1160 | end if; | |
1161 | end; | |
1162 | end loop; | |
1163 | end if; | |
1164 | end; | |
1165 | end if; | |
1166 | ||
1167 | if The_Command = Link or The_Command = Bind then | |
1168 | ||
1169 | -- For files that are specified as relative paths with directory | |
1170 | -- information, we convert them to absolute paths, with parent | |
1171 | -- being the current working directory if specified on the command | |
1172 | -- line and the project directory if specified in the project | |
1173 | -- file. This is what gnatmake is doing for linker and binder | |
1174 | -- arguments. | |
1175 | ||
1176 | for J in 1 .. Last_Switches.Last loop | |
1177 | Test_If_Relative_Path | |
1178 | (Last_Switches.Table (J), Current_Work_Dir); | |
1179 | end loop; | |
1180 | ||
1181 | Get_Name_String (Projects.Table (Project).Directory); | |
1182 | ||
1183 | declare | |
1184 | Project_Dir : constant String := Name_Buffer (1 .. Name_Len); | |
1185 | ||
1186 | begin | |
1187 | for J in 1 .. First_Switches.Last loop | |
1188 | Test_If_Relative_Path | |
1189 | (First_Switches.Table (J), Project_Dir); | |
1190 | end loop; | |
1191 | end; | |
1192 | ||
1193 | elsif The_Command = Stub then | |
1194 | declare | |
1195 | Data : constant Prj.Project_Data := | |
1196 | Prj.Projects.Table (Project); | |
1197 | File_Index : Integer := 0; | |
1198 | Dir_Index : Integer := 0; | |
1199 | Last : constant Integer := Last_Switches.Last; | |
1200 | ||
1201 | begin | |
1202 | for Index in 1 .. Last loop | |
1203 | if Last_Switches.Table (Index) | |
1204 | (Last_Switches.Table (Index)'First) /= '-' | |
1205 | then | |
1206 | File_Index := Index; | |
1207 | exit; | |
1208 | end if; | |
1209 | end loop; | |
1210 | ||
1211 | -- If the naming scheme of the project file is not standard, | |
1212 | -- and if the file name ends with the spec suffix, then | |
1213 | -- indicate to gnatstub the name of the body file with | |
1214 | -- a -o switch. | |
1215 | ||
1216 | if Data.Naming.Current_Spec_Suffix /= | |
1217 | Prj.Default_Ada_Spec_Suffix | |
1218 | then | |
1219 | if File_Index /= 0 then | |
1220 | declare | |
1221 | Spec : constant String := | |
1222 | Base_Name (Last_Switches.Table (File_Index).all); | |
1223 | Last : Natural := Spec'Last; | |
1224 | ||
1225 | begin | |
1226 | Get_Name_String (Data.Naming.Current_Spec_Suffix); | |
1227 | ||
1228 | if Spec'Length > Name_Len | |
1229 | and then Spec (Last - Name_Len + 1 .. Last) = | |
1230 | Name_Buffer (1 .. Name_Len) | |
1231 | then | |
1232 | Last := Last - Name_Len; | |
1233 | Get_Name_String (Data.Naming.Current_Body_Suffix); | |
1234 | Last_Switches.Increment_Last; | |
1235 | Last_Switches.Table (Last_Switches.Last) := | |
1236 | new String'("-o"); | |
1237 | Last_Switches.Increment_Last; | |
1238 | Last_Switches.Table (Last_Switches.Last) := | |
1239 | new String'(Spec (Spec'First .. Last) & | |
1240 | Name_Buffer (1 .. Name_Len)); | |
1241 | end if; | |
1242 | end; | |
1243 | end if; | |
1244 | end if; | |
1245 | ||
1246 | -- Add the directory of the spec as the destination directory | |
1247 | -- of the body, if there is no destination directory already | |
1248 | -- specified. | |
1249 | ||
1250 | if File_Index /= 0 then | |
1251 | for Index in File_Index + 1 .. Last loop | |
1252 | if Last_Switches.Table (Index) | |
1253 | (Last_Switches.Table (Index)'First) /= '-' | |
1254 | then | |
1255 | Dir_Index := Index; | |
1256 | exit; | |
07fc65c4 | 1257 | end if; |
fbf5a39b AC |
1258 | end loop; |
1259 | ||
1260 | if Dir_Index = 0 then | |
1261 | Last_Switches.Increment_Last; | |
1262 | Last_Switches.Table (Last_Switches.Last) := | |
1263 | new String' | |
1264 | (Dir_Name (Last_Switches.Table (File_Index).all)); | |
1265 | end if; | |
07fc65c4 GB |
1266 | end if; |
1267 | end; | |
1268 | end if; | |
1269 | end if; | |
1270 | ||
1271 | -- Gather all the arguments and invoke the executable | |
1272 | ||
1273 | declare | |
1274 | The_Args : Argument_List | |
1275 | (1 .. First_Switches.Last + Last_Switches.Last); | |
1276 | Arg_Num : Natural := 0; | |
1277 | begin | |
1278 | for J in 1 .. First_Switches.Last loop | |
1279 | Arg_Num := Arg_Num + 1; | |
1280 | The_Args (Arg_Num) := First_Switches.Table (J); | |
1281 | end loop; | |
1282 | ||
1283 | for J in 1 .. Last_Switches.Last loop | |
1284 | Arg_Num := Arg_Num + 1; | |
1285 | The_Args (Arg_Num) := Last_Switches.Table (J); | |
38cbfe40 RK |
1286 | end loop; |
1287 | ||
fbf5a39b AC |
1288 | -- If Display_Command is on, only display the generated command |
1289 | ||
1290 | if Display_Command then | |
1291 | Put (Standard_Error, "generated command -->"); | |
1292 | Put (Standard_Error, Exec_Path.all); | |
1293 | ||
1294 | for Arg in The_Args'Range loop | |
1295 | Put (Standard_Error, " "); | |
1296 | Put (Standard_Error, The_Args (Arg).all); | |
1297 | end loop; | |
1298 | ||
1299 | Put (Standard_Error, "<--"); | |
1300 | New_Line (Standard_Error); | |
1301 | raise Normal_Exit; | |
1302 | end if; | |
1303 | ||
07fc65c4 GB |
1304 | if Opt.Verbose_Mode then |
1305 | Output.Write_Str (Exec_Path.all); | |
38cbfe40 | 1306 | |
07fc65c4 GB |
1307 | for Arg in The_Args'Range loop |
1308 | Output.Write_Char (' '); | |
1309 | Output.Write_Str (The_Args (Arg).all); | |
1310 | end loop; | |
1311 | ||
1312 | Output.Write_Eol; | |
38cbfe40 RK |
1313 | end if; |
1314 | ||
fbf5a39b AC |
1315 | My_Exit_Status := |
1316 | Exit_Status (Spawn (Exec_Path.all, The_Args)); | |
07fc65c4 | 1317 | raise Normal_Exit; |
38cbfe40 | 1318 | end; |
07fc65c4 | 1319 | end; |
38cbfe40 RK |
1320 | |
1321 | exception | |
1322 | when Error_Exit => | |
fbf5a39b AC |
1323 | Prj.Env.Delete_All_Path_Files; |
1324 | Delete_Temp_Config_Files; | |
38cbfe40 RK |
1325 | Set_Exit_Status (Failure); |
1326 | ||
1327 | when Normal_Exit => | |
fbf5a39b AC |
1328 | Prj.Env.Delete_All_Path_Files; |
1329 | Delete_Temp_Config_Files; | |
1330 | ||
1331 | -- Since GNATCmd is normally called from DCL (the VMS shell), | |
1332 | -- it must return an understandable VMS exit status. However | |
1333 | -- the exit status returned *to* GNATCmd is a Posix style code, | |
1334 | -- so we test it and return just a simple success or failure on VMS. | |
1335 | ||
1336 | if Hostparm.OpenVMS and then My_Exit_Status /= Success then | |
1337 | Set_Exit_Status (Failure); | |
1338 | else | |
1339 | Set_Exit_Status (My_Exit_Status); | |
1340 | end if; | |
38cbfe40 RK |
1341 | |
1342 | end GNATCmd; |