with Debug; use Debug;
with Osint; use Osint;
with Opt; use Opt;
with Table;
package body Switch.M is
package Normalized_Switches is new Table.Table
(Table_Component_Type => String_Access,
Table_Index_Type => Integer,
Table_Low_Bound => 1,
Table_Initial => 20,
Table_Increment => 100,
Table_Name => "Switch.M.Normalized_Switches");
Initial_Number_Of_Switches : constant := 10;
Global_Switches : Argument_List_Access := null;
procedure Normalize_Compiler_Switches
(Switch_Chars : String;
Switches : in out Argument_List_Access;
Last : out Natural)
is
Switch_Starts_With_Gnat : Boolean;
Ptr : Integer := Switch_Chars'First;
Max : constant Integer := Switch_Chars'Last;
C : Character := ' ';
Storing : String := Switch_Chars;
First_Stored : Positive := Ptr + 1;
Last_Stored : Positive := First_Stored;
procedure Add_Switch_Component (S : String);
procedure Add_Switch_Component (S : String) is
begin
if Switches = null then
Switches := new Argument_List (1 .. Initial_Number_Of_Switches);
elsif Last = Switches'Last then
declare
New_Switches : constant Argument_List_Access :=
new Argument_List
(1 .. Switches'Length + Switches'Length);
begin
New_Switches (1 .. Switches'Length) := Switches.all;
Last := Switches'Length;
Switches := New_Switches;
end;
end if;
if Last = 0 then
Last := Switches'First;
else
Last := Last + 1;
end if;
for Index in 1 .. Normalized_Switches.Last loop
if S = Normalized_Switches.Table (Index).all then
Switches (Last) := Normalized_Switches.Table (Index);
return;
end if;
end loop;
Switches (Last) := new String'(S);
Normalized_Switches.Increment_Last;
Normalized_Switches.Table (Normalized_Switches.Last) :=
Switches (Last);
end Add_Switch_Component;
begin
Last := 0;
if Ptr = Max or else Switch_Chars (Ptr) /= '-' then
return;
end if;
Ptr := Ptr + 1;
Switch_Starts_With_Gnat :=
Ptr + 3 <= Max and then Switch_Chars (Ptr .. Ptr + 3) = "gnat";
if Switch_Starts_With_Gnat then
Ptr := Ptr + 4;
First_Stored := Ptr;
end if;
while Ptr <= Max loop
C := Switch_Chars (Ptr);
case Switch_Starts_With_Gnat is
when False =>
if Switch_Chars = "-pg" then
Add_Switch_Component ("-p");
elsif C /= 'v' then
Add_Switch_Component (Switch_Chars);
end if;
return;
when True =>
case C is
when 'a' | 'A' | 'b' | 'c' | 'D' | 'E' | 'f' |
'F' | 'g' | 'h' | 'H' | 'k' | 'l' | 'L' | 'n' | 'N' |
'o' | 'O' | 'p' | 'P' | 'q' | 'Q' | 'r' | 's' | 't' |
'u' | 'U' | 'v' | 'x' | 'X' | 'Z' =>
Storing (First_Stored) := C;
Add_Switch_Component
(Storing (Storing'First .. First_Stored));
Ptr := Ptr + 1;
when 'm' | 'T' =>
Storing (First_Stored) := C;
Last_Stored := First_Stored;
loop
Ptr := Ptr + 1;
exit when Ptr > Max
or else Switch_Chars (Ptr) not in '0' .. '9';
Last_Stored := Last_Stored + 1;
Storing (Last_Stored) := Switch_Chars (Ptr);
end loop;
Add_Switch_Component
(Storing (Storing'First .. Last_Stored));
when 'd' =>
Storing (First_Stored) := 'd';
while Ptr < Max loop
Ptr := Ptr + 1;
C := Switch_Chars (Ptr);
exit when C = ASCII.NUL or else C = '/'
or else C = '-';
if C in '1' .. '9' or else
C in 'a' .. 'z' or else
C in 'A' .. 'Z'
then
Storing (First_Stored + 1) := C;
Add_Switch_Component
(Storing (Storing'First .. First_Stored + 1));
else
Last := 0;
return;
end if;
end loop;
return;
when 'e' =>
Storing (First_Stored) := 'e';
Ptr := Ptr + 1;
if Ptr > Max
or else (Switch_Chars (Ptr) /= 'D'
and then Switch_Chars (Ptr) /= 'p')
then
Last := 0;
return;
end if;
if Switch_Chars (Ptr) = 'D' then
Storing (First_Stored + 1 ..
First_Stored + Max - Ptr + 1) :=
Switch_Chars (Ptr .. Max);
Add_Switch_Component
(Storing (Storing'First ..
First_Stored + Max - Ptr + 1));
else
Ptr := Ptr + 1;
if Ptr = Max then
Last := 0;
return;
end if;
if Switch_Chars (Ptr) = '=' then
Ptr := Ptr + 1;
end if;
declare
To_Store : String (1 .. Max - Ptr + 9);
begin
To_Store (1 .. 8) := "-gnatep=";
To_Store (9 .. Max - Ptr + 9) :=
Switch_Chars (Ptr .. Max);
Add_Switch_Component (To_Store);
end;
end if;
return;
when 'i' =>
Storing (First_Stored) := 'i';
Ptr := Ptr + 1;
if Ptr > Max then
Last := 0;
return;
end if;
C := Switch_Chars (Ptr);
if C in '1' .. '5'
or else C = '8'
or else C = 'p'
or else C = 'f'
or else C = 'n'
or else C = 'w'
then
Storing (First_Stored + 1) := C;
Add_Switch_Component
(Storing (Storing'First .. First_Stored + 1));
Ptr := Ptr + 1;
else
Last := 0;
return;
end if;
when 'R' =>
Last_Stored := First_Stored;
Storing (Last_Stored) := 'R';
Ptr := Ptr + 1;
if Ptr <= Max
and then Switch_Chars (Ptr) in '0' .. '9'
then
C := Switch_Chars (Ptr);
if C in '4' .. '9' then
Last := 0;
return;
else
Last_Stored := Last_Stored + 1;
Storing (Last_Stored) := C;
Ptr := Ptr + 1;
if Ptr <= Max
and then Switch_Chars (Ptr) = 's' then
Last_Stored := Last_Stored + 1;
Storing (Last_Stored) := 's';
Ptr := Ptr + 1;
end if;
end if;
end if;
Add_Switch_Component
(Storing (Storing'First .. Last_Stored));
when 'V' | 'w' | 'y' =>
Storing (First_Stored) := C;
Ptr := Ptr + 1;
if Ptr > Max then
if C = 'y' then
Add_Switch_Component
(Storing (Storing'First .. First_Stored));
else
Last := 0;
return;
end if;
end if;
while Ptr <= Max loop
C := Switch_Chars (Ptr);
Ptr := Ptr + 1;
if C /= 'w' or else Storing (First_Stored) /= 'w' then
if C = 'M'
and then Storing (First_Stored) = 'y' then
Last_Stored := First_Stored + 1;
Storing (Last_Stored) := 'M';
while Ptr <= Max loop
C := Switch_Chars (Ptr);
exit when C not in '0' .. '9';
Last_Stored := Last_Stored + 1;
Storing (Last_Stored) := C;
Ptr := Ptr + 1;
end loop;
if Last_Stored = First_Stored + 1 then
Last := 0;
return;
else
Add_Switch_Component
(Storing (Storing'First .. Last_Stored));
end if;
else
Storing (First_Stored + 1) := C;
Add_Switch_Component
(Storing (Storing'First .. First_Stored + 1));
end if;
end if;
end loop;
when others =>
Last := 0;
return;
end case;
end case;
end loop;
end Normalize_Compiler_Switches;
function Normalize_Compiler_Switches
(Switch_Chars : String)
return Argument_List
is
Last : Natural;
begin
Normalize_Compiler_Switches (Switch_Chars, Global_Switches, Last);
if Last = 0 then
return (1 .. 0 => null);
else
return Global_Switches (Global_Switches'First .. Last);
end if;
end Normalize_Compiler_Switches;
procedure Scan_Make_Switches (Switch_Chars : String) is
Ptr : Integer := Switch_Chars'First;
Max : constant Integer := Switch_Chars'Last;
C : Character := ' ';
begin
if Ptr = Max then
raise Bad_Switch;
else
Ptr := Ptr + 1;
end if;
if Switch_Chars'Length >= Ptr + 3
and then Switch_Chars (Ptr .. Ptr + 3) = "gnat"
then
Osint.Fail
("invalid switch: """, Switch_Chars, """ (gnat not needed here)");
end if;
Check_Switch : begin
C := Switch_Chars (Ptr);
case C is
when 'a' =>
Ptr := Ptr + 1;
Check_Readonly_Files := True;
when 'b' =>
Ptr := Ptr + 1;
Bind_Only := True;
Make_Steps := True;
when 'B' =>
Ptr := Ptr + 1;
Build_Bind_And_Link_Full_Project := True;
when 'c' =>
Ptr := Ptr + 1;
Compile_Only := True;
Make_Steps := True;
when 'C' =>
Ptr := Ptr + 1;
Create_Mapping_File := True;
when 'D' =>
Ptr := Ptr + 1;
if Object_Directory_Present then
Osint.Fail ("duplicate -D switch");
else
Object_Directory_Present := True;
end if;
when 'd' =>
while Ptr < Max loop
Ptr := Ptr + 1;
C := Switch_Chars (Ptr);
exit when C = ASCII.NUL or else C = '/' or else C = '-';
if C in '1' .. '9' or else
C in 'a' .. 'z' or else
C in 'A' .. 'Z'
then
Set_Debug_Flag (C);
else
raise Bad_Switch;
end if;
end loop;
if Debug_Flag_XX then
Zero_Cost_Exceptions_Set := True;
Zero_Cost_Exceptions_Val := True;
end if;
return;
when 'e' =>
Ptr := Ptr + 1;
if Ptr > Max then
raise Bad_Switch;
end if;
case Switch_Chars (Ptr) is
when 'I' =>
Ptr := Ptr + 1;
Scan_Pos (Switch_Chars, Max, Ptr, Main_Index);
when 'L' =>
Ptr := Ptr + 1;
Follow_Links := True;
when others =>
raise Bad_Switch;
end case;
when 'f' =>
Ptr := Ptr + 1;
Force_Compilations := True;
when 'F' =>
Ptr := Ptr + 1;
Full_Path_Name_For_Brief_Errors := True;
when 'h' =>
Ptr := Ptr + 1;
Usage_Requested := True;
when 'i' =>
Ptr := Ptr + 1;
In_Place_Mode := True;
when 'j' =>
Ptr := Ptr + 1;
declare
Max_Proc : Pos;
begin
Scan_Pos (Switch_Chars, Max, Ptr, Max_Proc);
Maximum_Processes := Positive (Max_Proc);
end;
when 'k' =>
Ptr := Ptr + 1;
Keep_Going := True;
when 'l' =>
Ptr := Ptr + 1;
Link_Only := True;
Make_Steps := True;
when 'M' =>
Ptr := Ptr + 1;
List_Dependencies := True;
when 'n' =>
Ptr := Ptr + 1;
Do_Not_Execute := True;
when 'o' =>
Ptr := Ptr + 1;
if Output_File_Name_Present then
raise Too_Many_Output_Files;
else
Output_File_Name_Present := True;
end if;
when 'q' =>
Ptr := Ptr + 1;
Quiet_Output := True;
when 'R' =>
Ptr := Ptr + 1;
Run_Path_Option := False;
when 's' =>
Ptr := Ptr + 1;
Check_Switches := True;
when 'v' =>
Ptr := Ptr + 1;
Verbose_Mode := True;
when 'x' =>
Ptr := Ptr + 1;
External_Unit_Compilation_Allowed := True;
when 'z' =>
Ptr := Ptr + 1;
No_Main_Subprogram := True;
when '/' | '-' =>
Ptr := Ptr + 1;
when others =>
raise Bad_Switch;
end case;
if Ptr <= Max then
Osint.Fail ("invalid switch: ", Switch_Chars);
end if;
end Check_Switch;
exception
when Bad_Switch =>
Osint.Fail ("invalid switch: ", (1 => C));
when Bad_Switch_Value =>
Osint.Fail ("numeric value out of range for switch: ", (1 => C));
when Missing_Switch_Value =>
Osint.Fail ("missing numeric value for switch: ", (1 => C));
when Too_Many_Output_Files =>
Osint.Fail ("duplicate -o switch");
end Scan_Make_Switches;
end Switch.M;