sem_prag.adb (Analyze_Pragma): Add appropriate calls to Resolve_Suppressible in the...
[platform/upstream/gcc.git] / gcc / ada / gnatdll.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                              G N A T D L L                               --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1997-2013, 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 --  GNATDLL is a Windows specific tool for building a DLL.
27 --  Both relocatable and non-relocatable DLL's are supported
28
29 with Gnatvsn;
30 with MDLL.Fil; use MDLL.Fil;
31 with MDLL.Utl; use MDLL.Utl;
32 with Switch;   use Switch;
33
34 with Ada.Text_IO;           use Ada.Text_IO;
35 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
36 with Ada.Exceptions;        use Ada.Exceptions;
37 with Ada.Command_Line;      use Ada.Command_Line;
38
39 with GNAT.OS_Lib;       use GNAT.OS_Lib;
40 with GNAT.Command_Line; use GNAT.Command_Line;
41
42 procedure Gnatdll is
43
44    use type GNAT.OS_Lib.Argument_List;
45
46    procedure Syntax;
47    --  Print out usage
48
49    procedure Check (Filename : String);
50    --  Check that the file whose name is Filename exists
51
52    procedure Parse_Command_Line;
53    --  Parse the command line arguments passed to gnatdll
54
55    procedure Check_Context;
56    --  Check the context before running any commands to build the library
57
58    Syntax_Error : exception;
59    --  Raised when a syntax error is detected, in this case a usage info will
60    --  be displayed.
61
62    Context_Error : exception;
63    --  Raised when some files (specified on the command line) are missing to
64    --  build the DLL.
65
66    Help : Boolean := False;
67    --  Help will be set to True the usage information is to be displayed
68
69    Version : constant String := Gnatvsn.Gnat_Version_String;
70    --  Why should it be necessary to make a copy of this
71
72    Default_DLL_Address : constant String := "0x11000000";
73    --  Default address for non relocatable DLL (Win32)
74
75    Lib_Filename : Unbounded_String := Null_Unbounded_String;
76    --  The DLL filename that will be created (.dll)
77
78    Def_Filename : Unbounded_String := Null_Unbounded_String;
79    --  The definition filename (.def)
80
81    List_Filename : Unbounded_String := Null_Unbounded_String;
82    --  The name of the file containing the objects file to put into the DLL
83
84    DLL_Address : Unbounded_String := To_Unbounded_String (Default_DLL_Address);
85    --  The DLL's base address
86
87    Gen_Map_File : Boolean := False;
88    --  Set to True if a map file is to be generated
89
90    Objects_Files : Argument_List_Access := MDLL.Null_Argument_List_Access;
91    --  List of objects to put inside the library
92
93    Ali_Files : Argument_List_Access := MDLL.Null_Argument_List_Access;
94    --  For each Ada file specified, we keep a record of the corresponding
95    --  ALI file. This list of SLI files is used to build the binder program.
96
97    Options : Argument_List_Access := MDLL.Null_Argument_List_Access;
98    --  A list of options set in the command line
99
100    Largs_Options : Argument_List_Access := MDLL.Null_Argument_List_Access;
101    Bargs_Options : Argument_List_Access := MDLL.Null_Argument_List_Access;
102    --  GNAT linker and binder args options
103
104    type Build_Mode_State is (Import_Lib, Dynamic_Lib, Dynamic_Lib_Only, Nil);
105    --  Import_Lib means only the .a file will be created, Dynamic_Lib means
106    --  that both the DLL and the import library will be created.
107    --  Dynamic_Lib_Only means that only the DLL will be created (no import
108    --  library).
109
110    Build_Mode : Build_Mode_State := Nil;
111    --  Will be set when parsing the command line
112
113    Must_Build_Relocatable : Boolean := True;
114    --  True means build a relocatable DLL, will be set to False if a
115    --  non-relocatable DLL must be built.
116
117    ------------
118    -- Syntax --
119    ------------
120
121    procedure Syntax is
122       procedure P (Str : String) renames Put_Line;
123    begin
124       P ("Usage : gnatdll [options] [list-of-files]");
125       New_Line;
126       P ("[list-of-files] a list of Ada libraries (.ali) and/or " &
127          "foreign object files");
128       New_Line;
129       P ("[options] can be");
130       P ("   -h            Help - display this message");
131       P ("   -v            Verbose");
132       P ("   -q            Quiet");
133       P ("   -k            Remove @nn suffix from exported names");
134       P ("   -g            Generate debugging information");
135       P ("   -Idir         Specify source and object files search path");
136       P ("   -l file       File contains a list-of-files to be added to "
137          & "the library");
138       P ("   -e file       Definition file containing exports");
139       P ("   -d file       Put objects in the relocatable dynamic "
140          & "library <file>");
141       P ("   -b addr       Set base address for the relocatable DLL");
142       P ("                 default address is " & Default_DLL_Address);
143       P ("   -a[addr]      Build non-relocatable DLL at address <addr>");
144       P ("                 if <addr> is not specified use "
145          & Default_DLL_Address);
146       P ("   -m            Generate map file");
147       P ("   -n            No-import - do not create the import library");
148       P ("   -bargs opts   opts are passed to the binder");
149       P ("   -largs opts   opts are passed to the linker");
150    end Syntax;
151
152    -----------
153    -- Check --
154    -----------
155
156    procedure Check (Filename : String) is
157    begin
158       if not Is_Regular_File (Filename) then
159          Raise_Exception
160            (Context_Error'Identity, "Error: " & Filename & " not found.");
161       end if;
162    end Check;
163
164    ------------------------
165    -- Parse_Command_Line --
166    ------------------------
167
168    procedure Parse_Command_Line is
169
170       procedure Add_File (Filename : String);
171       --  Add one file to the list of file to handle
172
173       procedure Add_Files_From_List (List_Filename : String);
174       --  Add the files listed in List_Filename (one by line) to the list
175       --  of file to handle
176
177       Max_Files   : constant := 5_000;
178       Max_Options : constant :=   100;
179       --  These are arbitrary limits, a better way will be to use linked list.
180       --  No, a better choice would be to use tables ???
181       --  Limits on what???
182
183       Ofiles : Argument_List (1 .. Max_Files);
184       O      : Positive := Ofiles'First;
185       --  List of object files to put in the library. O is the next entry
186       --  to be used.
187
188       Afiles : Argument_List (1 .. Max_Files);
189       A      : Positive := Afiles'First;
190       --  List of ALI files. A is the next entry to be used
191
192       Gopts  : Argument_List (1 .. Max_Options);
193       G      : Positive := Gopts'First;
194       --  List of gcc options. G is the next entry to be used
195
196       Lopts  : Argument_List (1 .. Max_Options);
197       L      : Positive := Lopts'First;
198       --  A list of -largs options (L is next entry to be used)
199
200       Bopts  : Argument_List (1 .. Max_Options);
201       B      : Positive := Bopts'First;
202       --  A list of -bargs options (B is next entry to be used)
203
204       Build_Import : Boolean := True;
205       --  Set to False if option -n if specified (no-import)
206
207       --------------
208       -- Add_File --
209       --------------
210
211       procedure Add_File (Filename : String) is
212       begin
213          if Is_Ali (Filename) then
214             Check (Filename);
215
216             --  Record it to generate the binder program when
217             --  building dynamic library
218
219             Afiles (A) := new String'(Filename);
220             A := A + 1;
221
222          elsif Is_Obj (Filename) then
223             Check (Filename);
224
225             --  Just record this object file
226
227             Ofiles (O) := new String'(Filename);
228             O := O + 1;
229
230          else
231             --  Unknown file type
232
233             Raise_Exception
234               (Syntax_Error'Identity,
235                "don't know what to do with " & Filename & " !");
236          end if;
237       end Add_File;
238
239       -------------------------
240       -- Add_Files_From_List --
241       -------------------------
242
243       procedure Add_Files_From_List (List_Filename : String) is
244          File   : File_Type;
245          Buffer : String (1 .. 500);
246          Last   : Natural;
247
248       begin
249          Open (File, In_File, List_Filename);
250
251          while not End_Of_File (File) loop
252             Get_Line (File, Buffer, Last);
253             Add_File (Buffer (1 .. Last));
254          end loop;
255
256          Close (File);
257
258       exception
259          when Name_Error =>
260             Raise_Exception
261               (Syntax_Error'Identity,
262                "list-of-files file " & List_Filename & " not found.");
263       end Add_Files_From_List;
264
265    --  Start of processing for Parse_Command_Line
266
267    begin
268       Initialize_Option_Scan ('-', False, "bargs largs");
269
270       --  scan gnatdll switches
271
272       loop
273          case Getopt ("g h v q k a? b: d: e: l: n m I:") is
274
275             when ASCII.NUL =>
276                exit;
277
278             when 'h' =>
279                Help := True;
280
281             when 'g' =>
282                Gopts (G) := new String'("-g");
283                G := G + 1;
284
285             when 'v' =>
286
287                --  Turn verbose mode on
288
289                MDLL.Verbose := True;
290                if MDLL.Quiet then
291                   Raise_Exception
292                     (Syntax_Error'Identity,
293                      "impossible to use -q and -v together.");
294                end if;
295
296             when 'q' =>
297
298                --  Turn quiet mode on
299
300                MDLL.Quiet := True;
301                if MDLL.Verbose then
302                   Raise_Exception
303                     (Syntax_Error'Identity,
304                      "impossible to use -v and -q together.");
305                end if;
306
307             when 'k' =>
308
309                MDLL.Kill_Suffix := True;
310
311             when 'a' =>
312
313                if Parameter = "" then
314
315                   --  Default address for a relocatable dynamic library.
316                   --  address for a non relocatable dynamic library.
317
318                   DLL_Address := To_Unbounded_String (Default_DLL_Address);
319
320                else
321                   DLL_Address := To_Unbounded_String (Parameter);
322                end if;
323
324                Must_Build_Relocatable := False;
325
326             when 'b' =>
327
328                DLL_Address := To_Unbounded_String (Parameter);
329
330                Must_Build_Relocatable := True;
331
332             when 'e' =>
333
334                Def_Filename := To_Unbounded_String (Parameter);
335
336             when 'd' =>
337
338                --  Build a non relocatable DLL
339
340                Lib_Filename := To_Unbounded_String (Parameter);
341
342                if Def_Filename = Null_Unbounded_String then
343                   Def_Filename := To_Unbounded_String
344                     (Ext_To (Parameter, "def"));
345                end if;
346
347                Build_Mode := Dynamic_Lib;
348
349             when 'm' =>
350
351                Gen_Map_File := True;
352
353             when 'n' =>
354
355                Build_Import := False;
356
357             when 'l' =>
358                List_Filename := To_Unbounded_String (Parameter);
359
360             when 'I' =>
361                Gopts (G) := new String'("-I" & Parameter);
362                G := G + 1;
363
364             when others =>
365                raise Invalid_Switch;
366          end case;
367       end loop;
368
369       --  Get parameters
370
371       loop
372          declare
373             File : constant String := Get_Argument (Do_Expansion => True);
374          begin
375             exit when File'Length = 0;
376             Add_File (File);
377          end;
378       end loop;
379
380       --  Get largs parameters
381
382       Goto_Section ("largs");
383
384       loop
385          case Getopt ("*") is
386             when ASCII.NUL =>
387                exit;
388
389             when others =>
390                Lopts (L) := new String'(Full_Switch);
391                L := L + 1;
392          end case;
393       end loop;
394
395       --  Get bargs parameters
396
397       Goto_Section ("bargs");
398
399       loop
400          case Getopt ("*") is
401
402             when ASCII.NUL =>
403                exit;
404
405             when others =>
406                Bopts (B) := new String'(Full_Switch);
407                B := B + 1;
408
409          end case;
410       end loop;
411
412       --  if list filename has been specified, parse it
413
414       if List_Filename /= Null_Unbounded_String then
415          Add_Files_From_List (To_String (List_Filename));
416       end if;
417
418       --  Check if the set of parameters are compatible
419
420       if Build_Mode = Nil and then not Help and then not MDLL.Verbose then
421          Raise_Exception (Syntax_Error'Identity, "nothing to do.");
422       end if;
423
424       --  -n option but no file specified
425
426       if not Build_Import
427         and then A = Afiles'First
428         and then O = Ofiles'First
429       then
430          Raise_Exception
431            (Syntax_Error'Identity,
432             "-n specified but there are no objects to build the library.");
433       end if;
434
435       --  Check if we want to build an import library (option -e and
436       --  no file specified)
437
438       if Build_Mode = Dynamic_Lib
439         and then A = Afiles'First
440         and then O = Ofiles'First
441       then
442          Build_Mode := Import_Lib;
443       end if;
444
445       --  If map file is to be generated, add linker option here
446
447       if Gen_Map_File and then Build_Mode = Import_Lib then
448          Raise_Exception
449            (Syntax_Error'Identity,
450             "Can't generate a map file for an import library.");
451       end if;
452
453       --  Check if only a dynamic library must be built
454
455       if Build_Mode = Dynamic_Lib and then not Build_Import then
456          Build_Mode := Dynamic_Lib_Only;
457       end if;
458
459       if O /= Ofiles'First then
460          Objects_Files := new Argument_List'(Ofiles (1 .. O - 1));
461       end if;
462
463       if A /= Afiles'First then
464          Ali_Files     := new Argument_List'(Afiles (1 .. A - 1));
465       end if;
466
467       if G /= Gopts'First then
468          Options       := new Argument_List'(Gopts (1 .. G - 1));
469       end if;
470
471       if L /= Lopts'First then
472          Largs_Options := new Argument_List'(Lopts (1 .. L - 1));
473       end if;
474
475       if B /= Bopts'First then
476          Bargs_Options := new Argument_List'(Bopts (1 .. B - 1));
477       end if;
478
479    exception
480       when Invalid_Switch    =>
481          Raise_Exception
482            (Syntax_Error'Identity,
483             Message => "Invalid Switch " & Full_Switch);
484
485       when Invalid_Parameter =>
486          Raise_Exception
487            (Syntax_Error'Identity,
488             Message => "No parameter for " & Full_Switch);
489    end Parse_Command_Line;
490
491    -------------------
492    -- Check_Context --
493    -------------------
494
495    procedure Check_Context is
496    begin
497       Check (To_String (Def_Filename));
498
499       --  Check that each object file specified exists and raise exception
500       --  Context_Error if it does not.
501
502       for F in Objects_Files'Range loop
503          Check (Objects_Files (F).all);
504       end loop;
505    end Check_Context;
506
507    procedure Check_Version_And_Help is new Check_Version_And_Help_G (Syntax);
508
509 --  Start of processing for Gnatdll
510
511 begin
512    Check_Version_And_Help ("GNATDLL", "1997");
513
514    if Ada.Command_Line.Argument_Count = 0 then
515       Help := True;
516    else
517       Parse_Command_Line;
518    end if;
519
520    if MDLL.Verbose or else Help then
521       New_Line;
522       Put_Line ("GNATDLL " & Version & " - Dynamic Libraries Builder");
523       New_Line;
524    end if;
525
526    MDLL.Utl.Locate;
527
528    if Help
529      or else (MDLL.Verbose and then Ada.Command_Line.Argument_Count = 1)
530    then
531       Syntax;
532    else
533       Check_Context;
534
535       case Build_Mode is
536          when Import_Lib =>
537             MDLL.Build_Import_Library
538               (To_String (Lib_Filename),
539                To_String (Def_Filename));
540
541          when Dynamic_Lib =>
542             MDLL.Build_Dynamic_Library
543               (Objects_Files.all,
544                Ali_Files.all,
545                Options.all,
546                Bargs_Options.all,
547                Largs_Options.all,
548                To_String (Lib_Filename),
549                To_String (Def_Filename),
550                To_String (DLL_Address),
551                Build_Import => True,
552                Relocatable  => Must_Build_Relocatable,
553                Map_File     => Gen_Map_File);
554
555          when Dynamic_Lib_Only =>
556             MDLL.Build_Dynamic_Library
557               (Objects_Files.all,
558                Ali_Files.all,
559                Options.all,
560                Bargs_Options.all,
561                Largs_Options.all,
562                To_String (Lib_Filename),
563                To_String (Def_Filename),
564                To_String (DLL_Address),
565                Build_Import => False,
566                Relocatable  => Must_Build_Relocatable,
567                Map_File     => Gen_Map_File);
568
569          when Nil =>
570             null;
571       end case;
572    end if;
573
574    Set_Exit_Status (Success);
575
576 exception
577    when SE : Syntax_Error =>
578       Put_Line ("Syntax error : " & Exception_Message (SE));
579       New_Line;
580       Syntax;
581       Set_Exit_Status (Failure);
582
583    when E : MDLL.Tools_Error | Context_Error =>
584       Put_Line (Exception_Message (E));
585       Set_Exit_Status (Failure);
586
587    when others =>
588       Put_Line ("gnatdll: INTERNAL ERROR. Please report");
589       Set_Exit_Status (Failure);
590 end Gnatdll;