1
1
------------------------------------------------------------------------------
3
-- GNATELIM COMPONENTS --
5
-- G N A T E L I M . D R I V E R --
7
-- P r o c e d u r e B o d y --
9
-- Copyright (C) 1998-2005 Ada Core Technologies, Inc. --
11
-- GNATELIM is free software; you can redistribute it and/or modify it --
12
-- under the terms of the GNU General Public License as published by the --
13
-- Free Software Foundation; either version 2 or (at your option) any later --
14
-- version. GNATELIM is distributed in the hope that it will be useful, but --
15
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABI- --
16
-- LITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Li- --
17
-- cense for more details. You should have received a copy of the GNU --
18
-- General Public License distributed with GNAT; see file COPYING. If not, --
19
-- write to the Free Software Foundation, 59 Temple Place - Suite 330, --
3
20
-- Boston, MA 02111-1307, USA. --
22
-- The original version of Gnatelim was developed by Alain Le Guennec --
23
-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com) --
5
25
------------------------------------------------------------------------------
7
with GNATELIM.Process_Bind_File; use GNATELIM.Process_Bind_File;
9
with GNATELIM.Analysis; use GNATELIM.Analysis;
10
with GNATELIM.Output; use GNATELIM.Output;
11
with GNATELIM.Options; use GNATELIM.Options;
12
with GNATELIM.Errors; use GNATELIM.Errors;
17
with Asis.Implementation;
18
with Asis.Ada_Environments;
19
with Asis.Compilation_Units;
21
with Ada.Command_Line; use Ada.Command_Line;
22
with Ada.Exceptions; use Ada.Exceptions;
23
with Ada.Characters.Handling; use Ada.Characters.Handling;
24
with Ada.Wide_Text_IO; use Ada.Wide_Text_IO;
26
procedure GNATELIM.Driver is
28
My_Context : Asis.Context;
30
Dirs : String (1 .. 1000);
31
Dirs_Ptr : Natural := 0;
32
-- Storage for "-T" switches
34
Bindfile : String (1 .. 256);
35
Bindfile_Ptr : Natural := 0;
36
-- Storage for bindfile name
27
with Ada.Characters.Handling; use Ada.Characters.Handling;
28
with Ada.Exceptions; use Ada.Exceptions;
29
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
30
with Ada.Wide_Text_IO; use Ada.Wide_Text_IO;
31
with Ada.Command_Line; use Ada.Command_Line;
33
with GNAT.OS_Lib; use GNAT.OS_Lib;
34
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
35
with GNAT.Command_Line; use GNAT.Command_Line;
37
with ASIS_UL.Compiler_Options; use ASIS_UL.Compiler_Options;
39
with Gnatelim.Analyze;
40
with Gnatelim.Bind_File;
41
with Gnatelim.Nodes; use Gnatelim.Nodes;
42
with Gnatelim.Output; use Gnatelim.Output;
43
with Gnatelim.Errors; use Gnatelim.Errors;
45
procedure Gnatelim.Driver is
47
Bindfile, Main_Proc : String_Access;
48
-- Storage for bindfile and main procedure names
38
53
-------------------------
39
54
-- Local subprograms --
40
55
-------------------------
43
-- does the ASIS finalization steps (Close->Dissociate->Finalize)
44
-- in case of any failure, if necessary
46
57
procedure Brief_Help;
47
58
-- Prints brief help information to stdout.
60
function Detect_Target return String;
61
-- Detects if this is a cross version of the tool by analysing its name.
62
-- In case if it is a cross version, returns the prefix of the name
63
-- detecting the specific cross version, othervise returns an empty
64
-- string (in case of gnaampelim, returns "AAMP")
66
function Compiler_To_Call return String;
67
-- Detects the name of the compiler to call
69
function Gnatmake_To_Call return String;
70
-- Detects the name of gnatmake to call
72
procedure Locate_Main_Unit (Par : String);
73
-- This procedure tries to locate the file containing the main procedure
74
-- name and to set full normalized name of this file as the value of
75
-- Main_Proc. In case if it is impossible because of any reason, this
76
-- procesure assigns to Main_Proc the reference to a Par string as it is
77
-- passed to the procedure
79
83
procedure Brief_Help is
83
Put_Line ("Usage: gnatelim [options] name");
84
Put_Line (" name full expanded Ada name of a main subprogram "
85
& "of a program (partition)");
88
Put_Line ("Usage: gnatelim [options] name [gcc_switches]");
89
Put_Line (" name the name of the source file containing the main");
90
Put_Line (" subprogram of a program (partition)");
86
91
Put_Line ("gnatelim options:");
87
92
Put_Line (" -v verbose mode");
88
Put_Line (" -a process RTL components");
93
Put_Line (" -a also analyze RTL components used by a program");
89
94
Put_Line (" -b<file> process specific bind file");
90
Put_Line (" -m check missed units");
91
95
Put_Line (" -q quiet mode");
92
Put_Line (" -T<dir> look in this dir for tree files");
96
Put_Line (" -I<dir> look in this dir for source files; can be repeated"
98
Put_Line (" of times. Specify -I- to exclude current dir.");
99
Put_Line (" -C<file> file that contains configuration pragmas. Must be"
100
& " with full path.");
101
Put_Line (" --GCC=<file> use this GCC instead of the one on the path");
102
Put_Line (" --GNATMAKE=<file> "
103
& "use this GNATMAKE instead of the one on the path");
104
Put (" gcc_switches '-cargs switches' where 'switches' is ");
105
Put_Line ("a list of of switches");
106
Put_Line (" that are valid switches for gcc");
103
if Asis.Ada_Environments.Is_Open (My_Context) then
104
Asis.Ada_Environments.Close (My_Context);
107
Asis.Ada_Environments.Dissociate (My_Context);
108
Asis.Implementation.Finalize;
112
First_Parameter_Index : Natural := 0;
114
Main_Unit : Asis.Compilation_Unit;
116
begin -- GNATELIM.Driver's body.
109
----------------------
110
-- Compiler_To_Call --
111
----------------------
113
function Compiler_To_Call return String is
114
Target : constant String := Detect_Target;
117
if Target = "AAMP" then
120
return Target & "gcc";
123
end Compiler_To_Call;
129
function Detect_Target return String is
130
Name : constant String :=
131
To_Lower (Base_Name (Normalize_Pathname (Command_Name)));
132
Tgt_Last : constant Integer := Index (Name, "gnatelim") - 1;
135
if Name = "gnaampelim" then
137
elsif Tgt_Last > Name'First then
138
return Name (Name'First .. Tgt_Last);
149
----------------------
150
-- Gnatmake_To_Call --
151
----------------------
153
function Gnatmake_To_Call return String is
154
Target : constant String := Detect_Target;
157
if Target = "AAMP" then
160
return Target & "gnatmake";
163
end Gnatmake_To_Call;
165
----------------------
166
-- Locate_Main_Unit --
167
----------------------
169
procedure Locate_Main_Unit (Par : String) is
172
if Is_Regular_File (Par) then
173
Main_Proc := new String'(Normalize_Pathname (Par));
174
elsif Is_Regular_File (Par & ".adb") then
175
Main_Proc := new String'(Normalize_Pathname (Par & ".adb"));
176
elsif Is_Regular_File (Par & ".ads") then
177
Main_Proc := new String'(Normalize_Pathname (Par & ".ads"));
180
if Main_Proc = null then
181
Main_Proc := new String'(Par);
184
end Locate_Main_Unit;
186
begin -- Gnatelim.Driver's body.
118
188
-- Parse command-line arguments.
120
for C in 1 .. Argument_Count loop
123
Arg : String := Argument (C);
126
if Arg (Arg'First) = '-' then
128
if Arg (Arg'First + 1 .. Arg'Last) = "q" then
129
GNATELIM.Options.Quiet_Mode := True;
131
elsif Arg (Arg'First + 1 .. Arg'Last) = "dv" then
132
GNATELIM.Options.Debug_Mode := True;
134
elsif Arg (Arg'First + 1 .. Arg'Last) = "v" then
135
GNATELIM.Options.Verbose_Mode := True;
137
elsif Arg (Arg'First + 1 .. Arg'Last) = "m" then
138
GNATELIM.Options.Skip_Missed_Units := False;
140
elsif Arg (Arg'First + 1 .. Arg'Last) = "a" then
141
GNATELIM.Options.Dont_Eliminate_In_RTS := False;
143
elsif Arg (Arg'First + 1) = 'T' and then Arg'Length > 2 then
144
Dirs (Dirs_Ptr + 1 .. Dirs_Ptr + Arg'Length + 1) := Arg & ' ';
145
Dirs_Ptr := Dirs_Ptr + Arg'Length + 1;
147
elsif Arg (Arg'First + 1) = 'b' and then Arg'Length > 2 then
148
Bindfile_Ptr := Arg'Length - 2;
149
Bindfile (1 .. Bindfile_Ptr) := Arg (3 .. Arg'Length);
152
Error ("gnatelim: invalid switch: "
153
& To_Wide_String (Arg (Arg'First + 1 .. Arg'Last)));
157
First_Parameter_Index := C;
190
Initialize_Option_Scan
191
(Stop_At_First_Non_Switch => True,
192
Section_Delimiters => "cargs");
195
case Getopt ("-help -GCC=: -GNATMAKE=: a b: m q v C: I: d dv dh v") is
201
Gnatelim.Eliminate_In_RTL := True;
204
Bindfile := new String'(Parameter);
207
null; -- Obsolete switch, for backwards compatibility
210
Gnatelim.Quiet_Mode := True;
213
Gnatelim.Verbose_Mode := True;
216
Store_gnatec_Option (Parameter);
219
Store_I_Option (Parameter);
222
if Full_Switch = "-help" then
226
elsif Full_Switch = "-GCC=" then
227
Gcc := new String'(Parameter);
229
elsif Full_Switch = "-GNATMAKE=" then
230
Gnatmake := new String'(Parameter);
236
if Full_Switch = "dv" then
237
Gnatelim.Output_Debug_Information := True;
239
elsif Full_Switch = "dh" then
240
Gnatelim.Eliminate_Homonyms_By_Profile := True;
242
elsif Full_Switch = "d" then
243
Gnatelim.Progress_Indicator_Mode := True;
254
if Bindfile = null then
255
Bindfile := new String'("");
258
if Gnatmake = null then
259
Gnatmake := Locate_Exec_On_Path (Gnatmake_To_Call);
262
if Gnatmake = null then
263
Error (To_Wide_String (Gnatmake_To_Call) & " not found on the path");
267
Gcc := Locate_Exec_On_Path (Compiler_To_Call);
271
Error (To_Wide_String (Compiler_To_Call) & " not found on the path");
274
-- Clear environment variables that set objects path for gnatmake, as
275
-- gnatelim will define its own
276
Setenv ("ADA_PRJ_OBJECTS_FILE", "");
277
Setenv ("ADA_OBJECTS_PATH", "");
279
Locate_Main_Unit (Get_Argument);
281
if Main_Proc = null or else Main_Proc.all = "" then
282
Error ("gnatelim: can not locate the main unit");
285
Process_cargs_Section;
289
if Main_Proc.all = "" then
165
294
if Verbose_Mode then
166
296
Put_Gnatelim_Version;
168
Put_Line ("-- Copyright 1997-2000, Free Software Foundation, Inc.");
298
Put_Line ("-- Copyright 1997-2003, Free Software Foundation, Inc.");
172
if (First_Parameter_Index = 0) then
180
-- ASIS Initialization:
182
Asis.Implementation.Initialize;
183
Asis.Ada_Environments.Associate
184
(My_Context, "My_Context", To_Wide_String (Dirs (1 .. Dirs_Ptr)) & "-CA");
185
Asis.Ada_Environments.Open (My_Context);
187
-- Computing the main unit:
189
Main_Unit := Asis.Compilation_Units.Library_Unit_Declaration
190
(To_Wide_String (Argument (First_Parameter_Index)), My_Context);
192
if Asis.Compilation_Units.Is_Nil (Main_Unit) then
193
-- May be this is a spec-less subprogram. Let's get the body.
194
Main_Unit := Asis.Compilation_Units.Compilation_Unit_Body
195
(To_Wide_String (Argument (First_Parameter_Index)), My_Context);
198
if Asis.Compilation_Units.Is_Nil (Main_Unit) then
199
Error ("gnatelim: Library item corresponding to "
200
& To_Wide_String (Argument (First_Parameter_Index))
204
if not Asis.Compilation_Units.Can_Be_Main_Program (Main_Unit) then
205
Error ("gnatelim: the unit corresponding to "
206
& To_Wide_String (Argument (First_Parameter_Index))
207
& " cannot be a main program.");
210
-- obtaining from a bind file a list of units making up a program
213
Partition_Complete : Boolean := False;
214
Needed_Units : Asis.Compilation_Unit_List :=
215
Get_Units_From_Bind_File
216
(My_Context, Argument (Argument_Count), Bindfile (1 .. Bindfile_Ptr));
218
Partition_Complete := True;
220
Warning ("gnatelim: starting analysis...", True);
222
Analyze_Partition (Main_Unit, Needed_Units);
228
if Partition_Complete then
229
-- We let the global handler provide more informations.
232
-- ??? How could we get here
233
Error ("gnatelim: the set of files making the partition "
238
-- Reporting results of the analysis:
239
Report_Unused_Subprograms;
241
-- ASIS Finalization:
302
Warning ("Processing bind file...");
303
Gnatelim.Bind_File.Process_Bind_File
304
(Main_Proc.all, Bindfile.all);
306
Warning ("Registering subprograms...");
307
Main := Gnatelim.Analyze (Main_Proc);
309
Main.Flags (FLAG_USED) := True;
310
Register_Node (Main);
312
Warning ("Analyzing usage...");
314
Gnatelim.Nodes.Transitive_Closure;
316
Warning ("Generating pragmas...");
317
Gnatelim.Output.Report_Unused_Subprograms;
246
when Ex : Asis.Exceptions.ASIS_Inappropriate_Context
247
| Asis.Exceptions.ASIS_Inappropriate_Container
248
| Asis.Exceptions.ASIS_Inappropriate_Compilation_Unit
249
| Asis.Exceptions.ASIS_Inappropriate_Element
250
| Asis.Exceptions.ASIS_Inappropriate_Line
251
| Asis.Exceptions.ASIS_Inappropriate_Line_Number
252
| Asis.Exceptions.ASIS_Failed
254
Set_Output (Standard_Error);
258
Put ("Unexpected bug in ");
259
Put_Gnatelim_Version;
261
Put (To_Wide_String (Exception_Name (Ex)));
262
Put_Line (" raised");
263
Put ("gnatelim: ASIS Diagnosis is " & Asis.Implementation.Diagnosis);
265
Put ("gnatelim: Status Value is ");
267
(Asis.Errors.Error_Kinds 'Wide_Image (Asis.Implementation.Status));
269
Put_Line ("Please report to report@gnat.com.");
272
Set_Output (Standard_Output);
273
Set_Exit_Status (Failure);
276
321
when Fatal_Error =>
324
when Invalid_Switch =>
327
Put_Line ("Unknown switch: -" & To_Wide_String (Full_Switch));
279
329
when Ex : others =>
280
330
Set_Output (Standard_Error);
283
if Exception_Identity (Ex) = Program_Error'Identity and then
284
Exception_Message (Ex) = "Inconsistent versions of GNAT and ASIS"
286
Put_Gnatelim_Version;
288
Put ("is inconsistent with the GNAT version");
290
Put ("Check your installation of GNAT, ASIS and the GNAT toolset");
333
Put ("Unexpected exception in ");
334
Put_Gnatelim_Version;
336
Put (To_Wide_String (Exception_Name (Ex)));
337
Put (" was raised: ");
339
if Exception_Message (Ex)'Length = 0 then
340
Put_Line ("(no exception message)");
293
Put ("Unexpected bug in ");
294
Put_Gnatelim_Version;
296
Put (To_Wide_String (Exception_Name (Ex)));
297
Put (" was raised: ");
299
if Exception_Message (Ex)'Length = 0 then
300
Put_Line ("(no exception message)");
302
Put_Line (To_Wide_String (Exception_Message (Ex)));
305
Put_Line ("Please report to report@gnat.com");
342
Put_Line (To_Wide_String (Exception_Message (Ex)));
345
Put_Line ("Please report to report@gnat.com");
309
348
Set_Output (Standard_Output);
310
Set_Exit_Status (Failure);