* c-decl.c (duplicate_decls): Conditionalize DECL_SAVED_TREE copy.
[official-gcc.git] / gcc / ada / gnatdll.adb
blobfbeb470c2755d30e608c3876efef1be1e9c6de11
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- G N A T D L L --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision$
10 -- --
11 -- Copyright (C) 1997-2001, Free Software Foundation, Inc. --
12 -- --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
23 -- --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
26 -- --
27 ------------------------------------------------------------------------------
29 -- GNATDLL is a Windows specific tool for building a DLL.
30 -- Both relocatable and non-relocatable DLL's are supported
32 with Ada.Text_IO;
33 with Ada.Strings.Unbounded;
34 with Ada.Exceptions;
35 with Ada.Command_Line;
36 with GNAT.OS_Lib;
37 with GNAT.Command_Line;
38 with Gnatvsn;
40 with MDLL.Files;
41 with MDLL.Tools;
43 procedure Gnatdll is
45 use GNAT;
46 use Ada;
47 use MDLL;
48 use Ada.Strings.Unbounded;
50 use type OS_Lib.Argument_List;
52 procedure Syntax;
53 -- Print out usage
55 procedure Check (Filename : String);
56 -- Check that the file whose name is Filename exists
58 procedure Parse_Command_Line;
59 -- Parse the command line arguments passed to gnatdll
61 procedure Check_Context;
62 -- Check the context before runing any commands to build the library
64 Syntax_Error : exception;
65 Context_Error : exception;
66 -- What are these for ???
68 Help : Boolean := False;
69 -- What is this for ???
71 Version : constant String := Gnatvsn.Gnat_Version_String;
72 -- Why should it be necessary to make a copy of this
74 Default_DLL_Address : constant String := "0x11000000";
75 -- Default address for non relocatable DLL (Win32)
77 Lib_Filename : Unbounded_String := Null_Unbounded_String;
78 Def_Filename : Unbounded_String := Null_Unbounded_String;
79 List_Filename : Unbounded_String := Null_Unbounded_String;
80 DLL_Address : Unbounded_String :=
81 To_Unbounded_String (Default_DLL_Address);
82 -- What are the above ???
84 Objects_Files : Argument_List_Access := Null_Argument_List_Access;
85 -- List of objects to put inside the library
87 Ali_Files : Argument_List_Access := Null_Argument_List_Access;
88 -- For each Ada file specified, we keep arecord of the corresponding
89 -- ALI file. This list of SLI files is used to build the binder program.
91 Options : Argument_List_Access := Null_Argument_List_Access;
92 -- A list of options set in the command line.
94 Largs_Options : Argument_List_Access := Null_Argument_List_Access;
95 Bargs_Options : Argument_List_Access := Null_Argument_List_Access;
96 -- GNAT linker and binder args options
98 type Build_Mode_State is (Import_Lib, Dynamic_Lib, Nil);
99 -- Comments needed ???
101 Build_Mode : Build_Mode_State := Nil;
102 Must_Build_Relocatable : Boolean := True;
103 Build_Import : Boolean := True;
104 -- Comments needed
106 ------------
107 -- Syntax --
108 ------------
110 procedure Syntax is
111 use Text_IO;
113 procedure P (Str : in String) renames Text_IO.Put_Line;
115 begin
116 P ("Usage : gnatdll [options] [list-of-files]");
117 New_Line;
118 P ("[list-of-files] a list of Ada libraries (.ali) and/or " &
119 "foreign object files");
120 New_Line;
121 P ("[options] can be");
122 P (" -h Help - display this message");
123 P (" -v Verbose");
124 P (" -q Quiet");
125 P (" -k Remove @nn suffix from exported names");
126 P (" -g Generate debugging information");
127 P (" -Idir Specify source and object files search path");
128 P (" -l file File contains a list-of-files to be added to "
129 & "the library");
130 P (" -e file Definition file containing exports");
131 P (" -d file Put objects in the relocatable dynamic "
132 & "library <file>");
133 P (" -a[addr] Build non-relocatable DLL at address <addr>");
134 P (" if <addr> is not specified use "
135 & Default_DLL_Address);
136 P (" -n No-import - do not create the import library");
137 P (" -bargs opts opts are passed to the binder");
138 P (" -largs opts opts are passed to the linker");
139 end Syntax;
141 -----------
142 -- Check --
143 -----------
145 procedure Check (Filename : in String) is
146 begin
147 if not OS_Lib.Is_Regular_File (Filename) then
148 Exceptions.Raise_Exception (Context_Error'Identity,
149 "Error: " & Filename & " not found.");
150 end if;
151 end Check;
153 ------------------------
154 -- Parse_Command_Line --
155 ------------------------
157 procedure Parse_Command_Line is
159 use GNAT.Command_Line;
161 procedure Add_File (Filename : in String);
162 -- add one file to the list of file to handle
164 procedure Add_Files_From_List (List_Filename : in String);
165 -- add the files listed in List_Filename (one by line) to the list
166 -- of file to handle
168 procedure Ali_To_Object_List;
169 -- for each ali file in Afiles set put a corresponding object file in
170 -- Ofiles set.
172 Max_Files : constant := 5_000;
173 Max_Options : constant := 100;
174 -- These are arbitrary limits, a better way will be to use linked list.
175 -- No, a better choice would be to use tables ???
176 -- Limits on what???
178 Ofiles : OS_Lib.Argument_List (1 .. Max_Files);
179 O : Positive := Ofiles'First;
180 -- List of object files to put in the library. O is the next entry
181 -- to be used.
183 Afiles : OS_Lib.Argument_List (1 .. Max_Files);
184 A : Positive := Afiles'First;
185 -- List of ALI files. A is the next entry to be used.
187 Gopts : OS_Lib.Argument_List (1 .. Max_Options);
188 G : Positive := Gopts'First;
189 -- List of gcc options. G is the next entry to be used.
191 Lopts : OS_Lib.Argument_List (1 .. Max_Options);
192 L : Positive := Lopts'First;
193 -- A list of -largs options (L is next entry to be used)
195 Bopts : OS_Lib.Argument_List (1 .. Max_Options);
196 B : Positive := Bopts'First;
197 -- A list of -bargs options (B is next entry to be used)
199 --------------
200 -- Add_File --
201 --------------
203 procedure Add_File (Filename : in String) is
204 begin
205 -- others files are to be put inside the dynamic library
206 -- ??? this makes no sense, should it be "Other files ..."
208 if Files.Is_Ali (Filename) then
210 Check (Filename);
212 -- Record it to generate the binder program when
213 -- building dynamic library
215 Afiles (A) := new String'(Filename);
216 A := A + 1;
218 elsif Files.Is_Obj (Filename) then
220 Check (Filename);
222 -- Just record this object file
224 Ofiles (O) := new String'(Filename);
225 O := O + 1;
227 else
228 -- Unknown file type
230 Exceptions.Raise_Exception
231 (Syntax_Error'Identity,
232 "don't know what to do with " & Filename & " !");
233 end if;
234 end Add_File;
236 -------------------------
237 -- Add_Files_From_List --
238 -------------------------
240 procedure Add_Files_From_List (List_Filename : in String) is
241 File : Text_IO.File_Type;
242 Buffer : String (1 .. 500);
243 Last : Natural;
245 begin
246 Text_IO.Open (File, Text_IO.In_File, List_Filename);
248 while not Text_IO.End_Of_File (File) loop
249 Text_IO.Get_Line (File, Buffer, Last);
250 Add_File (Buffer (1 .. Last));
251 end loop;
253 Text_IO.Close (File);
254 end Add_Files_From_List;
256 ------------------------
257 -- Ali_To_Object_List --
258 ------------------------
260 procedure Ali_To_Object_List is
261 begin
262 for K in 1 .. A - 1 loop
263 Ofiles (O) := new String'(Files.Ext_To (Afiles (K).all, "o"));
264 O := O + 1;
265 end loop;
266 end Ali_To_Object_List;
268 -- Start of processing for Parse_Command_Line
270 begin
271 Initialize_Option_Scan ('-', False, "bargs largs");
273 -- scan gnatdll switches
275 loop
276 case Getopt ("g h v q k a? d: e: l: n I:") is
278 when ASCII.Nul =>
279 exit;
281 when 'h' =>
282 Help := True;
284 when 'g' =>
285 Gopts (G) := new String'("-g");
286 G := G + 1;
288 when 'v' =>
290 -- Turn verbose mode on
292 MDLL.Verbose := True;
293 if MDLL.Quiet then
294 Exceptions.Raise_Exception
295 (Syntax_Error'Identity,
296 "impossible to use -q and -v together.");
297 end if;
299 when 'q' =>
301 -- Turn quiet mode on
303 MDLL.Quiet := True;
304 if MDLL.Verbose then
305 Exceptions.Raise_Exception
306 (Syntax_Error'Identity,
307 "impossible to use -v and -q together.");
308 end if;
310 when 'k' =>
312 MDLL.Kill_Suffix := True;
314 when 'a' =>
316 if Parameter = "" then
318 -- Default address for a relocatable dynamic library.
319 -- address for a non relocatable dynamic library.
321 DLL_Address := To_Unbounded_String (Default_DLL_Address);
323 else
324 DLL_Address := To_Unbounded_String (Parameter);
325 end if;
327 Must_Build_Relocatable := False;
329 when 'e' =>
331 Def_Filename := To_Unbounded_String (Parameter);
333 when 'd' =>
335 -- Build a non relocatable DLL
337 Lib_Filename := To_Unbounded_String (Parameter);
339 if Def_Filename = Null_Unbounded_String then
340 Def_Filename := To_Unbounded_String
341 (Files.Ext_To (Parameter, "def"));
342 end if;
344 Build_Mode := Dynamic_Lib;
346 when 'n' =>
348 Build_Import := False;
350 when 'l' =>
351 List_Filename := To_Unbounded_String (Parameter);
353 when 'I' =>
354 Gopts (G) := new String'("-I" & Parameter);
355 G := G + 1;
357 when others =>
358 raise Invalid_Switch;
360 end case;
361 end loop;
363 -- Get parameters
365 loop
366 declare
367 File : constant String := Get_Argument (Do_Expansion => True);
368 begin
369 exit when File'Length = 0;
370 Add_File (File);
371 end;
372 end loop;
374 -- Get largs parameters
376 Goto_Section ("largs");
378 loop
379 case Getopt ("*") is
381 when ASCII.Nul =>
382 exit;
384 when others =>
385 Lopts (L) := new String'(Full_Switch);
386 L := L + 1;
388 end case;
389 end loop;
391 -- Get bargs parameters
393 Goto_Section ("bargs");
395 loop
396 case Getopt ("*") is
398 when ASCII.Nul =>
399 exit;
401 when others =>
402 Bopts (B) := new String'(Full_Switch);
403 B := B + 1;
405 end case;
406 end loop;
408 -- if list filename has been specified, parse it
410 if List_Filename /= Null_Unbounded_String then
411 Add_Files_From_List (To_String (List_Filename));
412 end if;
414 -- Check if the set of parameters are compatible.
416 if Build_Mode = Nil and then not Help and then not Verbose then
417 Exceptions.Raise_Exception
418 (Syntax_Error'Identity,
419 "nothing to do.");
420 end if;
422 -- Check if we want to build an import library (option -e and
423 -- no file specified)
425 if Build_Mode = Dynamic_Lib
426 and then A = Afiles'First
427 and then O = Ofiles'First
428 then
429 Build_Mode := Import_Lib;
430 end if;
432 if O /= Ofiles'First then
433 Objects_Files := new OS_Lib.Argument_List'(Ofiles (1 .. O - 1));
434 end if;
436 if A /= Afiles'First then
437 Ali_Files := new OS_Lib.Argument_List'(Afiles (1 .. A - 1));
438 end if;
440 if G /= Gopts'First then
441 Options := new OS_Lib.Argument_List'(Gopts (1 .. G - 1));
442 end if;
444 if L /= Lopts'First then
445 Largs_Options := new OS_Lib.Argument_List'(Lopts (1 .. L - 1));
446 end if;
448 if B /= Bopts'First then
449 Bargs_Options := new OS_Lib.Argument_List'(Bopts (1 .. B - 1));
450 end if;
452 exception
454 when Invalid_Switch =>
455 Exceptions.Raise_Exception
456 (Syntax_Error'Identity,
457 Message => "Invalid Switch " & Full_Switch);
459 when Invalid_Parameter =>
460 Exceptions.Raise_Exception
461 (Syntax_Error'Identity,
462 Message => "No parameter for " & Full_Switch);
464 end Parse_Command_Line;
466 -------------------
467 -- Check_Context --
468 -------------------
470 procedure Check_Context is
471 begin
473 Check (To_String (Def_Filename));
475 -- Check that each object file specified exists and raise exception
476 -- Context_Error if it does not.
478 for F in Objects_Files'Range loop
479 Check (Objects_Files (F).all);
480 end loop;
481 end Check_Context;
483 -- Start of processing for Gnatdll
485 begin
486 if Ada.Command_Line.Argument_Count = 0 then
487 Help := True;
488 else
489 Parse_Command_Line;
490 end if;
492 if MDLL.Verbose or else Help then
493 Text_IO.New_Line;
494 Text_IO.Put_Line ("GNATDLL " & Version & " - Dynamic Libraries Builder");
495 Text_IO.New_Line;
496 end if;
498 MDLL.Tools.Locate;
500 if Help
501 or else (MDLL.Verbose and then Ada.Command_Line.Argument_Count = 1)
502 then
503 Syntax;
504 else
505 Check_Context;
507 case Build_Mode is
509 when Import_Lib =>
510 MDLL.Build_Import_Library
511 (To_String (Lib_Filename),
512 To_String (Def_Filename));
514 when Dynamic_Lib =>
515 MDLL.Build_Dynamic_Library
516 (Objects_Files.all,
517 Ali_Files.all,
518 Options.all,
519 Bargs_Options.all,
520 Largs_Options.all,
521 To_String (Lib_Filename),
522 To_String (Def_Filename),
523 To_String (DLL_Address),
524 Build_Import,
525 Must_Build_Relocatable);
527 when Nil =>
528 null;
530 end case;
532 end if;
534 Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Success);
536 exception
538 when SE : Syntax_Error =>
539 Text_IO.Put_Line ("Syntax error : " & Exceptions.Exception_Message (SE));
540 Text_IO.New_Line;
541 Syntax;
542 Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Failure);
544 when E : Tools_Error | Context_Error =>
545 Text_IO.Put_Line (Exceptions.Exception_Message (E));
546 Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Failure);
548 when others =>
549 Text_IO.Put_Line ("gnatdll: INTERNAL ERROR. Please report");
550 Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Failure);
552 end Gnatdll;