summaryrefslogtreecommitdiff
path: root/gcc/ada/g-comlin.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/g-comlin.adb')
-rw-r--r--gcc/ada/g-comlin.adb333
1 files changed, 294 insertions, 39 deletions
diff --git a/gcc/ada/g-comlin.adb b/gcc/ada/g-comlin.adb
index 32460c0599b..a3faf53040b 100644
--- a/gcc/ada/g-comlin.adb
+++ b/gcc/ada/g-comlin.adb
@@ -120,10 +120,18 @@ package body GNAT.Command_Line is
-- ungrouping common prefixes when possible), and call Callback for each of
-- these.
+ procedure Sort_Sections
+ (Line : GNAT.OS_Lib.Argument_List_Access;
+ Sections : GNAT.OS_Lib.Argument_List_Access;
+ Params : GNAT.OS_Lib.Argument_List_Access);
+ -- Reorder the command line switches so that the switches belonging to a
+ -- section are grouped together.
+
procedure Group_Switches
- (Cmd : Command_Line;
- Result : Argument_List_Access;
- Params : Argument_List_Access);
+ (Cmd : Command_Line;
+ Result : Argument_List_Access;
+ Sections : Argument_List_Access;
+ Params : Argument_List_Access);
-- Group switches with common prefixes whenever possible.
-- Once they have been grouped, we also check items for possible aliasing
@@ -1081,6 +1089,22 @@ package body GNAT.Command_Line is
Append (Config.Prefixes, new String'(Prefix));
end Define_Prefix;
+ --------------------
+ -- Define_Section --
+ --------------------
+
+ procedure Define_Section
+ (Config : in out Command_Line_Configuration;
+ Section : String)
+ is
+ begin
+ if Config = null then
+ Config := new Command_Line_Configuration_Record;
+ end if;
+
+ Append (Config.Sections, new String'(Section));
+ end Define_Section;
+
-----------------------
-- Set_Configuration --
-----------------------
@@ -1113,9 +1137,34 @@ package body GNAT.Command_Line is
Getopt_Description : String := "";
Switch_Char : Character := '-')
is
- Tmp : Argument_List_Access;
- Parser : Opt_Parser;
- S : Character;
+ Tmp : Argument_List_Access;
+ Parser : Opt_Parser;
+ S : Character;
+ Section : String_Access := null;
+
+ function Real_Full_Switch
+ (S : Character;
+ Parser : Opt_Parser) return String;
+ -- Ensure that the returned switch value contains the
+ -- Switch_Char prefix if needed.
+
+ ----------------------
+ -- Real_Full_Switch --
+ ----------------------
+
+ function Real_Full_Switch
+ (S : Character;
+ Parser : Opt_Parser) return String
+ is
+ begin
+ if S = '*' then
+ return Full_Switch (Parser);
+ else
+ return Switch_Char & Full_Switch (Parser);
+ end if;
+ end Real_Full_Switch;
+
+ -- Start of processing for Set_Command_Line
begin
Free (Cmd.Expanded);
@@ -1132,20 +1181,55 @@ package body GNAT.Command_Line is
Parser => Parser);
exit when S = ASCII.NUL;
- if S = '*' then
- Add_Switch (Cmd, Full_Switch (Parser), Parameter (Parser),
- Separator (Parser));
- else
- Add_Switch
- (Cmd, Switch_Char & Full_Switch (Parser),
- Parameter (Parser), Separator (Parser));
- end if;
+ declare
+ Sw : constant String :=
+ Real_Full_Switch (S, Parser);
+ Is_Section : Boolean := False;
+
+ begin
+ if Cmd.Config /= null
+ and then Cmd.Config.Sections /= null
+ then
+ Section_Search :
+ for S in Cmd.Config.Sections'Range loop
+ if Sw = Cmd.Config.Sections (S).all then
+ Section := Cmd.Config.Sections (S);
+ Is_Section := True;
+
+ exit Section_Search;
+ end if;
+ end loop Section_Search;
+ end if;
+
+ if not Is_Section then
+ if Section = null then
+ Add_Switch
+ (Cmd, Sw,
+ Parameter (Parser),
+ Separator (Parser));
+ else
+ Add_Switch
+ (Cmd, Sw,
+ Parameter (Parser),
+ Separator (Parser),
+ Section.all);
+ end if;
+ end if;
+ end;
exception
when Invalid_Parameter =>
+
-- Add it with no parameter, if that's the way the user
- -- wants it
- Add_Switch (Cmd, Switch_Char & Full_Switch (Parser));
+ -- wants it.
+
+ if Section = null then
+ Add_Switch
+ (Cmd, Switch_Char & Full_Switch (Parser));
+ else
+ Add_Switch
+ (Cmd, Switch_Char & Full_Switch (Parser), Section.all);
+ end if;
end;
end loop;
@@ -1230,7 +1314,8 @@ package body GNAT.Command_Line is
(Cmd : in out Command_Line;
Switch : String;
Parameter : String := "";
- Separator : Character := ' ')
+ Separator : Character := ' ';
+ Section : String := "")
is
procedure Add_Simple_Switch (Simple : String);
-- Add a new switch that has had all its aliases expanded, and switches
@@ -1250,7 +1335,12 @@ package body GNAT.Command_Line is
Cmd.Params := new Argument_List'
(1 .. 1 => new String'(Separator & Parameter));
end if;
-
+ if Section = "" then
+ Cmd.Sections := new Argument_List'(1 .. 1 => null);
+ else
+ Cmd.Sections := new Argument_List'
+ (1 .. 1 => new String'(Section));
+ end if;
else
-- Do we already have this switch ?
@@ -1261,6 +1351,11 @@ package body GNAT.Command_Line is
or else
(Cmd.Params (C) /= null
and then Cmd.Params (C).all = Separator & Parameter))
+ and then
+ ((Cmd.Sections (C) = null and then Section = "")
+ or else
+ (Cmd.Sections (C) /= null
+ and then Cmd.Sections (C).all = Section))
then
return;
end if;
@@ -1273,6 +1368,12 @@ package body GNAT.Command_Line is
else
Append (Cmd.Params, new String'(Separator & Parameter));
end if;
+
+ if Section = "" then
+ Append (Cmd.Sections, null);
+ else
+ Append (Cmd.Sections, new String'(Section));
+ end if;
end if;
end Add_Simple_Switch;
@@ -1337,7 +1438,8 @@ package body GNAT.Command_Line is
procedure Remove_Switch
(Cmd : in out Command_Line;
Switch : String;
- Remove_All : Boolean := False)
+ Remove_All : Boolean := False;
+ Section : String := "")
is
procedure Remove_Simple_Switch (Simple : String);
-- Removes a simple switch, with no aliasing or grouping
@@ -1353,9 +1455,17 @@ package body GNAT.Command_Line is
if Cmd.Expanded /= null then
C := Cmd.Expanded'First;
while C <= Cmd.Expanded'Last loop
- if Cmd.Expanded (C).all = Simple then
+ if Cmd.Expanded (C).all = Simple
+ and then
+ (Remove_All
+ or else (Cmd.Sections (C) = null
+ and then Section = "")
+ or else (Cmd.Sections (C) /= null
+ and then Section = Cmd.Sections (C).all))
+ then
Remove (Cmd.Expanded, C);
Remove (Cmd.Params, C);
+ Remove (Cmd.Sections, C);
if not Remove_All then
return;
@@ -1385,7 +1495,8 @@ package body GNAT.Command_Line is
procedure Remove_Switch
(Cmd : in out Command_Line;
Switch : String;
- Parameter : String)
+ Parameter : String;
+ Section : String := "")
is
procedure Remove_Simple_Switch (Simple : String);
-- Removes a simple switch, with no aliasing or grouping
@@ -1403,6 +1514,12 @@ package body GNAT.Command_Line is
while C <= Cmd.Expanded'Last loop
if Cmd.Expanded (C).all = Simple
and then
+ ((Cmd.Sections (C) = null
+ and then Section = "")
+ or else
+ (Cmd.Sections (C) /= null
+ and then Section = Cmd.Sections (C).all))
+ and then
((Cmd.Params (C) = null and then Parameter = "")
or else
(Cmd.Params (C) /= null
@@ -1416,6 +1533,7 @@ package body GNAT.Command_Line is
then
Remove (Cmd.Expanded, C);
Remove (Cmd.Params, C);
+ Remove (Cmd.Sections, C);
-- The switch is necessarily unique by construction of
-- Add_Switch
@@ -1444,12 +1562,13 @@ package body GNAT.Command_Line is
--------------------
procedure Group_Switches
- (Cmd : Command_Line;
- Result : Argument_List_Access;
- Params : Argument_List_Access)
+ (Cmd : Command_Line;
+ Result : Argument_List_Access;
+ Sections : Argument_List_Access;
+ Params : Argument_List_Access)
is
- Group : Ada.Strings.Unbounded.Unbounded_String;
- First : Natural;
+ Group : Ada.Strings.Unbounded.Unbounded_String;
+ First : Natural;
use type Ada.Strings.Unbounded.Unbounded_String;
begin
@@ -1469,17 +1588,40 @@ package body GNAT.Command_Line is
and then Looking_At
(Result (C).all, Result (C)'First, Cmd.Config.Prefixes (P).all)
then
- Group :=
- Group &
- Result (C)
- (Result (C)'First + Cmd.Config.Prefixes (P)'Length ..
- Result (C)'Last);
+ -- If we are still in the same section, group the switches
+ if First = 0
+ or else
+ (Sections (C) = null
+ and then Sections (First) = null)
+ or else
+ (Sections (C) /= null
+ and then Sections (First) /= null
+ and then Sections (C).all = Sections (First).all)
+ then
+ Group :=
+ Group &
+ Result (C)
+ (Result (C)'First + Cmd.Config.Prefixes (P)'Length ..
+ Result (C)'Last);
+ if First = 0 then
+ First := C;
+ end if;
- if First = 0 then
+ Free (Result (C));
+ else
+ -- We changed section: we put the grouped switches to the
+ -- first place, on continue with the new section.
+ Result (First) :=
+ new String'
+ (Cmd.Config.Prefixes (P).all &
+ Ada.Strings.Unbounded.To_String (Group));
+ Group :=
+ Ada.Strings.Unbounded.To_Unbounded_String
+ (Result (C)
+ (Result (C)'First + Cmd.Config.Prefixes (P)'Length ..
+ Result (C)'Last));
First := C;
end if;
-
- Free (Result (C));
end if;
end loop;
@@ -1576,6 +1718,70 @@ package body GNAT.Command_Line is
end loop;
end Alias_Switches;
+ -------------------
+ -- Sort_Sections --
+ -------------------
+
+ procedure Sort_Sections
+ (Line : GNAT.OS_Lib.Argument_List_Access;
+ Sections : GNAT.OS_Lib.Argument_List_Access;
+ Params : GNAT.OS_Lib.Argument_List_Access)
+ is
+ Sections_List : Argument_List_Access :=
+ new Argument_List'(1 .. 1 => null);
+ Found : Boolean;
+ Old_Line : constant Argument_List := Line.all;
+ Old_Sections : constant Argument_List := Sections.all;
+ Old_Params : constant Argument_List := Params.all;
+ Index : Natural;
+
+ begin
+ if Line = null then
+ return;
+ end if;
+
+ -- First construct a list of all sections
+
+ for E in Line'Range loop
+ if Sections (E) /= null then
+ Found := False;
+ for S in Sections_List'Range loop
+ if (Sections_List (S) = null and then Sections (E) = null)
+ or else
+ (Sections_List (S) /= null
+ and then Sections (E) /= null
+ and then Sections_List (S).all = Sections (E).all)
+ then
+ Found := True;
+ exit;
+ end if;
+ end loop;
+
+ if not Found then
+ Append (Sections_List, Sections (E));
+ end if;
+ end if;
+ end loop;
+
+ Index := Line'First;
+
+ for S in Sections_List'Range loop
+ for E in Old_Line'Range loop
+ if (Sections_List (S) = null and then Old_Sections (E) = null)
+ or else
+ (Sections_List (S) /= null
+ and then Old_Sections (E) /= null
+ and then Sections_List (S).all = Old_Sections (E).all)
+ then
+ Line (Index) := Old_Line (E);
+ Sections (Index) := Old_Sections (E);
+ Params (Index) := Old_Params (E);
+ Index := Index + 1;
+ end if;
+ end loop;
+ end loop;
+ end Sort_Sections;
+
-----------
-- Start --
-----------
@@ -1591,6 +1797,10 @@ package body GNAT.Command_Line is
return;
end if;
+ -- Reorder the expanded line so that sections are grouped
+
+ Sort_Sections (Cmd.Expanded, Cmd.Sections, Cmd.Params);
+
-- Coalesce the switches as much as possible
if not Expanded
@@ -1601,19 +1811,30 @@ package body GNAT.Command_Line is
Cmd.Coalesce (E) := new String'(Cmd.Expanded (E).all);
end loop;
+ Cmd.Coalesce_Sections := new Argument_List (Cmd.Sections'Range);
+ for E in Cmd.Sections'Range loop
+ if Cmd.Sections (E) = null then
+ Cmd.Coalesce_Sections (E) := null;
+ else
+ Cmd.Coalesce_Sections (E) := new String'(Cmd.Sections (E).all);
+ end if;
+ end loop;
+
-- Not a clone, since we will not modify the parameters anyway
Cmd.Coalesce_Params := Cmd.Params;
Alias_Switches (Cmd, Cmd.Coalesce, Cmd.Params);
- Group_Switches (Cmd, Cmd.Coalesce, Cmd.Params);
+ Group_Switches (Cmd, Cmd.Coalesce, Cmd.Coalesce_Sections, Cmd.Params);
end if;
if Expanded then
- Iter.List := Cmd.Expanded;
- Iter.Params := Cmd.Params;
+ Iter.List := Cmd.Expanded;
+ Iter.Params := Cmd.Params;
+ Iter.Sections := Cmd.Sections;
else
- Iter.List := Cmd.Coalesce;
- Iter.Params := Cmd.Coalesce_Params;
+ Iter.List := Cmd.Coalesce;
+ Iter.Params := Cmd.Coalesce_Params;
+ Iter.Sections := Cmd.Coalesce_Sections;
end if;
if Iter.List = null then
@@ -1637,6 +1858,40 @@ package body GNAT.Command_Line is
return Iter.List (Iter.Current).all;
end Current_Switch;
+ --------------------
+ -- Is_New_Section --
+ --------------------
+
+ function Is_New_Section (Iter : Command_Line_Iterator) return Boolean is
+ Section : constant String := Current_Section (Iter);
+ begin
+ if Iter.Sections = null then
+ return False;
+ elsif Iter.Current = Iter.Sections'First
+ or else Iter.Sections (Iter.Current - 1) = null
+ then
+ return Section /= "";
+ end if;
+
+ return Section /= Iter.Sections (Iter.Current - 1).all;
+ end Is_New_Section;
+
+ ---------------------
+ -- Current_Section --
+ ---------------------
+
+ function Current_Section (Iter : Command_Line_Iterator) return String is
+ begin
+ if Iter.Sections = null
+ or else Iter.Current > Iter.Sections'Last
+ or else Iter.Sections (Iter.Current) = null
+ then
+ return "";
+ end if;
+
+ return Iter.Sections (Iter.Current).all;
+ end Current_Section;
+
-----------------------
-- Current_Separator --
-----------------------