OSDN Git Service

2008-08-06 Jerome Lambourg <lambourg@adacore.com>
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Aug 2008 08:33:21 +0000 (08:33 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Aug 2008 08:33:21 +0000 (08:33 +0000)
* g-comlin.adb (Define_Switch, Get_Switches): New.
(Can_Have_Parameter, Require_Parameter, Actual_Switch): New, used when
ungrouping switches.
(For_Each_Simple_Switch): Allow more control over parameters handling.
This generic method now allows ungrouping of switches with parameters
and switches with more than one letter after the prefix.
(Set_Command_Line): Take care of switches that are prefixed with a
switch handling parameters without delimiter (-gnatya and -gnaty3 for
example).
(Add_Switch, Remove_Switch): Handle parameters possibly present inside
a group, as in gnaty3aM80 (3 and 80 are parameters). Report status of
the operation.
(Start, Alias_Switches, Group_Switches): Take care of parameters
possibly present inside a group.

* g-comlin.ads (Define_Switch): New method used to define a list of
expected switches, that are necessary for correctly ungrouping switches
with more that one character after the prefix.
(Get_Switches): Method that builds a getopt string from the list of
switches as set previously by Define_Switch.
(Add_Switch, Remove_Switch): New versions of the methods, reporting the
status of the operation. Also allow the removal of switches with
parameters only.
(Command_Line_Configuration_Record): Maintain a list of expected
switches.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@138775 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/ChangeLog
gcc/ada/g-comlin.adb
gcc/ada/g-comlin.ads

index 19f9e38..9b2088b 100644 (file)
@@ -1,3 +1,63 @@
+2008-08-06  Thomas Quinot  <quinot@adacore.com>
+
+       * xnmake.adb: Use new XUtil package for platform independent text
+       output.
+
+2008-08-06  Vincent Celier  <celier@adacore.com>
+
+       * gnat_ugn.texi: Document compiler switch -gnateG
+
+2008-08-06  Quentin Ochem  <ochem@adacore.com>
+
+       * s-stausa.adb (Fill_Stack): Fixed pragma assert and top pattern mark
+       in the case of an empty pattern size.
+       (Compute_Result): Do not do any computation in the case of an empty
+       pattern size.
+       (Report_Result): Fixed computation of the overflow guard.
+
+2008-08-06  Ed Schonberg  <schonberg@adacore.com>
+
+       * g-awk.adb (Finalize): Do not use directly objects of the type in the
+       finalization routine to prevent elaboration order anomalies in new
+       finalization scheme.
+
+2008-08-06  Ed Schonberg  <schonberg@adacore.com>
+
+       * sem_ch3.adb (Find_Type_Name): protect against duplicate incomplete
+       declaration for the same type.
+
+2008-08-06  Thomas Quinot  <quinot@adacore.com>
+
+       * sem.adb: Minor rewording (comment)
+
+2008-08-06  Jerome Lambourg  <lambourg@adacore.com>
+
+       * g-comlin.adb (Define_Switch, Get_Switches): New.
+       (Can_Have_Parameter, Require_Parameter, Actual_Switch): New, used when
+       ungrouping switches.
+       (For_Each_Simple_Switch): Allow more control over parameters handling.
+       This generic method now allows ungrouping of switches with parameters
+       and switches with more than one letter after the prefix.
+       (Set_Command_Line): Take care of switches that are prefixed with a
+       switch handling parameters without delimiter (-gnatya and -gnaty3 for
+       example).
+       (Add_Switch, Remove_Switch): Handle parameters possibly present inside
+       a group, as in gnaty3aM80 (3 and 80 are parameters). Report status of
+       the operation.
+       (Start, Alias_Switches, Group_Switches): Take care of parameters
+       possibly present inside a group.
+
+       * g-comlin.ads (Define_Switch): New method used to define a list of
+       expected switches, that are necessary for correctly ungrouping switches
+       with more that one character after the prefix.
+       (Get_Switches): Method that builds a getopt string from the list of
+       switches as set previously by Define_Switch.
+       (Add_Switch, Remove_Switch): New versions of the methods, reporting the
+       status of the operation. Also allow the removal of switches with
+       parameters only.
+       (Command_Line_Configuration_Record): Maintain a list of expected
+       switches.
+
 2008-08-06  Doug Rupp  <rupp@adacore.com>
 
        * gcc-interface/decl.c (gnat_to_gnu_param): Force 32bit descriptor if
index a3faf53..221b3a3 100644 (file)
@@ -111,11 +111,22 @@ package body GNAT.Command_Line is
       Str  : String_Access);
    --  Append a new element to Line
 
+   function Can_Have_Parameter (S : String) return Boolean;
+   --  Tell if S can have a parameter.
+
+   function Require_Parameter (S : String) return Boolean;
+   --  Tell if S requires a paramter.
+
+   function Actual_Switch (S : String) return String;
+   --  Remove any possible trailing '!', ':', '?' and '='
+
    generic
-      with procedure Callback (Simple_Switch : String);
+      with procedure Callback (Simple_Switch : String; Parameter : String);
    procedure For_Each_Simple_Switch
-     (Cmd    : Command_Line;
-      Switch : String);
+     (Cmd       : Command_Line;
+      Switch    : String;
+      Parameter : String := "";
+      Unalias   : Boolean := True);
    --  Breaks Switch into as simple switches as possible (expanding aliases and
    --  ungrouping common prefixes when possible), and call Callback for each of
    --  these.
@@ -1089,6 +1100,22 @@ package body GNAT.Command_Line is
       Append (Config.Prefixes, new String'(Prefix));
    end Define_Prefix;
 
+   -------------------
+   -- Define_Switch --
+   -------------------
+
+   procedure Define_Switch
+     (Config : in out Command_Line_Configuration;
+      Switch : String)
+   is
+   begin
+      if Config = null then
+         Config := new Command_Line_Configuration_Record;
+      end if;
+
+      Append (Config.Switches, new String'(Switch));
+   end Define_Switch;
+
    --------------------
    -- Define_Section --
    --------------------
@@ -1105,6 +1132,35 @@ package body GNAT.Command_Line is
       Append (Config.Sections, new String'(Section));
    end Define_Section;
 
+   ------------------
+   -- Get_Switches --
+   ------------------
+
+   function Get_Switches
+     (Config      : Command_Line_Configuration;
+      Switch_Char : Character)
+      return String
+   is
+      Ret : Ada.Strings.Unbounded.Unbounded_String;
+      use type Ada.Strings.Unbounded.Unbounded_String;
+   begin
+      if Config = null or else Config.Switches = null then
+         return "";
+      end if;
+
+      for J in Config.Switches'Range loop
+         if Config.Switches (J) (Config.Switches (J)'First) = Switch_Char then
+            Ret := Ret & " " &
+              Config.Switches (J)
+                (Config.Switches (J)'First + 1 .. Config.Switches (J)'Last);
+         else
+            Ret := Ret & " " & Config.Switches (J).all;
+         end if;
+      end loop;
+
+      return Ada.Strings.Unbounded.To_String (Ret);
+   end Get_Switches;
+
    -----------------------
    -- Set_Configuration --
    -----------------------
@@ -1203,16 +1259,33 @@ package body GNAT.Command_Line is
 
                   if not Is_Section then
                      if Section = null then
-                        Add_Switch
-                          (Cmd, Sw,
-                           Parameter (Parser),
-                           Separator (Parser));
+                        --  Workaround some weird cases: some switches may
+                        --  expect parameters, but have the same value as
+                        --  longer switches: -gnaty3 (-gnaty, parameter=3) and
+                        --  -gnatya (-gnatya, no parameter).
+                        --  So we are calling add_switch here with parameter
+                        --  attached. This will be anyway correctly handled by
+                        --  Add_Switch if -gnaty3 is actually furnished.
+                        if Separator (Parser) = ASCII.NUL then
+                           Add_Switch
+                             (Cmd, Sw & Parameter (Parser), "");
+                        else
+                           Add_Switch
+                             (Cmd, Sw, Parameter (Parser), Separator (Parser));
+                        end if;
                      else
-                        Add_Switch
-                          (Cmd, Sw,
-                           Parameter (Parser),
-                           Separator (Parser),
-                           Section.all);
+                        if Separator (Parser) = ASCII.NUL then
+                           Add_Switch
+                             (Cmd, Sw & Parameter (Parser), "",
+                              Separator (Parser),
+                              Section.all);
+                        else
+                           Add_Switch
+                             (Cmd, Sw,
+                              Parameter (Parser),
+                              Separator (Parser),
+                              Section.all);
+                        end if;
                      end if;
                   end if;
                end;
@@ -1250,14 +1323,157 @@ package body GNAT.Command_Line is
         and then Type_Str (Index .. Index + Substring'Length - 1) = Substring;
    end Looking_At;
 
+   ------------------------
+   -- Can_Have_Parameter --
+   ------------------------
+
+   function Can_Have_Parameter (S : String) return Boolean is
+   begin
+      if S'Length <= 1 then
+         return False;
+      end if;
+
+      case S (S'Last) is
+         when '!' | ':' | '?' | '=' =>
+            return True;
+         when others =>
+            return False;
+      end case;
+   end Can_Have_Parameter;
+
+   -----------------------
+   -- Require_Parameter --
+   -----------------------
+
+   function Require_Parameter (S : String) return Boolean is
+   begin
+      if S'Length <= 1 then
+         return False;
+      end if;
+
+      case S (S'Last) is
+         when '!' | ':' | '=' =>
+            return True;
+         when others =>
+            return False;
+      end case;
+   end Require_Parameter;
+
+   -------------------
+   -- Actual_Switch --
+   -------------------
+
+   function Actual_Switch (S : String) return String is
+   begin
+      if S'Length <= 1 then
+         return S;
+      end if;
+
+      case S (S'Last) is
+         when '!' | ':' | '?' | '=' =>
+            return S (S'First .. S'Last - 1);
+         when others =>
+            return S;
+      end case;
+   end Actual_Switch;
+
    ----------------------------
    -- For_Each_Simple_Switch --
    ----------------------------
 
    procedure For_Each_Simple_Switch
-     (Cmd    : Command_Line;
-      Switch : String)
+     (Cmd       : Command_Line;
+      Switch    : String;
+      Parameter : String := "";
+      Unalias   : Boolean := True)
    is
+      function Group_Analysis
+        (Prefix : String;
+         Group  : String) return Boolean;
+      --  Perform the analysis of a group of switches.
+
+      --------------------
+      -- Group_Analysis --
+      --------------------
+
+      function Group_Analysis
+        (Prefix : String;
+         Group  : String) return Boolean
+      is
+         Idx   : Natural := Group'First;
+         Found : Boolean;
+      begin
+         while Idx <= Group'Last loop
+            Found := False;
+
+            for S in Cmd.Config.Switches'Range loop
+               declare
+                  Sw              : constant String :=
+                                      Actual_Switch
+                                        (Cmd.Config.Switches (S).all);
+                  Full            : constant String :=
+                                      Prefix & Group (Idx .. Group'Last);
+                  Last            : Natural;
+                  Param           : Natural;
+
+               begin
+                  if Sw'Length >= Prefix'Length
+                  --  Verify that sw starts with Prefix
+                    and then Looking_At (Sw, Sw'First, Prefix)
+                  --  Verify that the group starts with sw
+                    and then Looking_At (Full, Full'First, Sw)
+                  then
+                     Last := Idx + Sw'Length - Prefix'Length - 1;
+                     Param := Last + 1;
+
+                     if Can_Have_Parameter (Cmd.Config.Switches (S).all) then
+                        --  Include potential parameter to the recursive call.
+                        --  Only numbers are allowed.
+                        while Last < Group'Last
+                          and then Group (Last + 1) in '0' .. '9'
+                        loop
+                           Last := Last + 1;
+                        end loop;
+                     end if;
+
+                     if not Require_Parameter (Cmd.Config.Switches (S).all)
+                       or else Last >= Param
+                     then
+                        if Idx = Group'First and then Last = Group'Last then
+                           --  The group only concerns a single switch. Do not
+                           --  perform recursive call.
+                           return False;
+                        end if;
+
+                        Found := True;
+
+                        --  Recursive call, using the detected parameter if any
+                        if Last >= Param then
+                           For_Each_Simple_Switch
+                             (Cmd,
+                              Prefix & Group (Idx .. Param - 1),
+                              Group (Param .. Last));
+                        else
+                           For_Each_Simple_Switch
+                             (Cmd, Prefix & Group (Idx .. Last), "");
+                        end if;
+
+                        Idx := Last + 1;
+                        exit;
+                     end if;
+                  end if;
+               end;
+            end loop;
+
+            if not Found then
+               For_Each_Simple_Switch (Cmd, Prefix & Group (Idx), "");
+               Idx := Idx + 1;
+            end if;
+         end loop;
+
+         return True;
+      end Group_Analysis;
+
    begin
       --  Are we adding a switch that can in fact be expanded through aliases ?
       --  If yes, we add separately each of its expansion.
@@ -1267,13 +1483,16 @@ package body GNAT.Command_Line is
       --  in which we do things here, the expansion of the alias will itself
       --  be checked for a common prefix and further split into simple switches
 
-      if Cmd.Config /= null
+      if Unalias
+        and then Cmd.Config /= null
         and then Cmd.Config.Aliases /= null
       then
          for A in Cmd.Config.Aliases'Range loop
-            if Cmd.Config.Aliases (A).all = Switch then
+            if Cmd.Config.Aliases (A).all = Switch
+              and then Parameter = ""
+            then
                For_Each_Simple_Switch
-                 (Cmd, Cmd.Config.Expansions (A).all);
+                 (Cmd, Cmd.Config.Expansions (A).all, "");
                return;
             end if;
          end loop;
@@ -1291,19 +1510,31 @@ package body GNAT.Command_Line is
                 (Switch, Switch'First, Cmd.Config.Prefixes (P).all)
             then
                --  Alias expansion will be done recursively
+               if Cmd.Config.Switches = null then
+                  for S in Switch'First + Cmd.Config.Prefixes (P)'Length
+                            .. Switch'Last
+                  loop
+                     For_Each_Simple_Switch
+                       (Cmd, Cmd.Config.Prefixes (P).all & Switch (S), "");
+                  end loop;
 
-               for S in Switch'First + Cmd.Config.Prefixes (P)'Length
-                          .. Switch'Last
-               loop
-                  For_Each_Simple_Switch
-                    (Cmd, Cmd.Config.Prefixes (P).all & Switch (S));
-               end loop;
-               return;
+                  return;
+
+               elsif Group_Analysis
+                 (Cmd.Config.Prefixes (P).all,
+                  Switch
+                    (Switch'First + Cmd.Config.Prefixes (P)'Length
+                      .. Switch'Last))
+               then
+                  --  Recursive calls already done on each switch of the
+                  --  group. Let's return to not call Callback.
+                  return;
+               end if;
             end if;
          end loop;
       end if;
 
-      Callback (Switch);
+      Callback (Switch, Parameter);
    end For_Each_Simple_Switch;
 
    ----------------
@@ -1317,7 +1548,25 @@ package body GNAT.Command_Line is
       Separator : Character := ' ';
       Section   : String := "")
    is
-      procedure Add_Simple_Switch (Simple : String);
+      Success : Boolean;
+      pragma Unreferenced (Success);
+   begin
+      Add_Switch (Cmd, Switch, Parameter, Separator, Section, Success);
+   end Add_Switch;
+
+   ----------------
+   -- Add_Switch --
+   ----------------
+
+   procedure Add_Switch
+     (Cmd       : in out Command_Line;
+      Switch    : String;
+      Parameter : String := "";
+      Separator : Character := ' ';
+      Section   : String := "";
+      Success   : out Boolean)
+   is
+      procedure Add_Simple_Switch (Simple : String; Param : String);
       --  Add a new switch that has had all its aliases expanded, and switches
       --  ungrouped. We know there is no more aliases in Switches
 
@@ -1325,32 +1574,37 @@ package body GNAT.Command_Line is
       -- Add_Simple_Switch --
       -----------------------
 
-      procedure Add_Simple_Switch (Simple : String) is
+      procedure Add_Simple_Switch (Simple : String; Param : String) is
       begin
          if Cmd.Expanded = null then
             Cmd.Expanded := new Argument_List'(1 .. 1 => new String'(Simple));
-            if Parameter = "" then
-               Cmd.Params := new Argument_List'(1 .. 1 => null);
-            else
+
+            if Param /= "" then
                Cmd.Params := new Argument_List'
-                 (1 .. 1 => new String'(Separator & Parameter));
+                 (1 .. 1 => new String'(Separator & Param));
+
+            else
+               Cmd.Params := new Argument_List'(1 .. 1 => null);
             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 ?
 
             for C in Cmd.Expanded'Range loop
                if Cmd.Expanded (C).all = Simple
                  and then
-                   ((Cmd.Params (C) = null and then Parameter = "")
+                   ((Cmd.Params (C) = null and then Param = "")
                     or else
                       (Cmd.Params (C) /= null
-                       and then Cmd.Params (C).all = Separator & Parameter))
+                       and then Cmd.Params (C).all = Separator & Param))
                  and then
                    ((Cmd.Sections (C) = null and then Section = "")
                     or else
@@ -1361,12 +1615,15 @@ package body GNAT.Command_Line is
                end if;
             end loop;
 
+            --  Inserting at least one switch
+            Success := True;
             Append (Cmd.Expanded, new String'(Simple));
 
-            if Parameter = "" then
-               Append (Cmd.Params, null);
+            if Param /= "" then
+               Append (Cmd.Params, new String'(Separator & Param));
+
             else
-               Append (Cmd.Params, new String'(Separator & Parameter));
+               Append (Cmd.Params, null);
             end if;
 
             if Section = "" then
@@ -1383,7 +1640,8 @@ package body GNAT.Command_Line is
    --  Start of processing for Add_Switch
 
    begin
-      Add_Simple_Switches (Cmd, Switch);
+      Success := False;
+      Add_Simple_Switches (Cmd, Switch, Parameter);
       Free (Cmd.Coalesce);
    end Add_Switch;
 
@@ -1436,20 +1694,40 @@ package body GNAT.Command_Line is
    -------------------
 
    procedure Remove_Switch
-     (Cmd        : in out Command_Line;
-      Switch     : String;
-      Remove_All : Boolean := False;
-      Section    : String  := "")
+     (Cmd           : in out Command_Line;
+      Switch        : String;
+      Remove_All    : Boolean := False;
+      Has_Parameter : Boolean := False;
+      Section       : String := "")
    is
-      procedure Remove_Simple_Switch (Simple : String);
+      Success : Boolean;
+      pragma Unreferenced (Success);
+   begin
+      Remove_Switch (Cmd, Switch, Remove_All, Has_Parameter, Section, Success);
+   end Remove_Switch;
+
+   -------------------
+   -- Remove_Switch --
+   -------------------
+
+   procedure Remove_Switch
+     (Cmd           : in out Command_Line;
+      Switch        : String;
+      Remove_All    : Boolean := False;
+      Has_Parameter : Boolean := False;
+      Section       : String  := "";
+      Success       : out Boolean)
+   is
+      procedure Remove_Simple_Switch (Simple : String; Param : String);
       --  Removes a simple switch, with no aliasing or grouping
 
       --------------------------
       -- Remove_Simple_Switch --
       --------------------------
 
-      procedure Remove_Simple_Switch (Simple : String) is
+      procedure Remove_Simple_Switch (Simple : String; Param : String) is
          C : Integer;
+         pragma Unreferenced (Param);
 
       begin
          if Cmd.Expanded /= null then
@@ -1462,10 +1740,12 @@ package body GNAT.Command_Line is
                              and then Section = "")
                     or else (Cmd.Sections (C) /= null
                              and then Section = Cmd.Sections (C).all))
+                 and then (not Has_Parameter or else Cmd.Params (C) /= null)
                then
                   Remove (Cmd.Expanded, C);
                   Remove (Cmd.Params, C);
                   Remove (Cmd.Sections, C);
+                  Success := True;
 
                   if not Remove_All then
                      return;
@@ -1484,7 +1764,8 @@ package body GNAT.Command_Line is
    --  Start of processing for Remove_Switch
 
    begin
-      Remove_Simple_Switches (Cmd, Switch);
+      Success := False;
+      Remove_Simple_Switches (Cmd, Switch, "", Unalias => not Has_Parameter);
       Free (Cmd.Coalesce);
    end Remove_Switch;
 
@@ -1498,14 +1779,14 @@ package body GNAT.Command_Line is
       Parameter : String;
       Section   : String  := "")
    is
-      procedure Remove_Simple_Switch (Simple : String);
+      procedure Remove_Simple_Switch (Simple : String; Param : String);
       --  Removes a simple switch, with no aliasing or grouping
 
       --------------------------
       -- Remove_Simple_Switch --
       --------------------------
 
-      procedure Remove_Simple_Switch (Simple : String) is
+      procedure Remove_Simple_Switch (Simple : String; Param : String) is
          C : Integer;
 
       begin
@@ -1520,7 +1801,7 @@ package body GNAT.Command_Line is
                       (Cmd.Sections (C) /= null
                        and then Section = Cmd.Sections (C).all))
                  and then
-                   ((Cmd.Params (C) = null and then Parameter = "")
+                   ((Cmd.Params (C) = null and then Param = "")
                       or else
                         (Cmd.Params (C) /= null
                            and then
@@ -1529,7 +1810,7 @@ package body GNAT.Command_Line is
 
                              Cmd.Params (C) (Cmd.Params (C)'First + 1
                                              .. Cmd.Params (C)'Last) =
-                         Parameter))
+                           Param))
                then
                   Remove (Cmd.Expanded, C);
                   Remove (Cmd.Params, C);
@@ -1553,7 +1834,7 @@ package body GNAT.Command_Line is
    --  Start of processing for Remove_Switch
 
    begin
-      Remove_Simple_Switches (Cmd, Switch);
+      Remove_Simple_Switches (Cmd, Switch, Parameter);
       Free (Cmd.Coalesce);
    end Remove_Switch;
 
@@ -1567,6 +1848,36 @@ package body GNAT.Command_Line is
       Sections : Argument_List_Access;
       Params   : Argument_List_Access)
    is
+      function Compatible_Parameter (Param : String_Access) return Boolean;
+      --  Tell if the parameter can be part of a group
+
+      --------------------------
+      -- Compatible_Parameter --
+      --------------------------
+
+      function Compatible_Parameter (Param : String_Access) return Boolean is
+      begin
+         if Param = null then
+            --  No parameter, OK
+            return True;
+
+         elsif Param (Param'First) /= ASCII.NUL then
+            --  We need parameters without separators...
+            return False;
+
+         else
+            --  We need number only parameters.
+            for J in Param'First + 1 .. Param'Last loop
+               if Param (J) not in '0' .. '9' then
+                  return False;
+               end if;
+            end loop;
+
+            return True;
+         end if;
+
+      end Compatible_Parameter;
+
       Group   : Ada.Strings.Unbounded.Unbounded_String;
       First   : Natural;
       use type Ada.Strings.Unbounded.Unbounded_String;
@@ -1584,7 +1895,7 @@ package body GNAT.Command_Line is
 
          for C in Result'Range loop
             if Result (C) /= null
-              and then Params (C) = null  --  ignored if has a parameter
+              and then Compatible_Parameter (Params (C))
               and then Looking_At
                 (Result (C).all, Result (C)'First, Cmd.Config.Prefixes (P).all)
             then
@@ -1602,7 +1913,14 @@ package body GNAT.Command_Line is
                     Group &
                       Result (C)
                         (Result (C)'First + Cmd.Config.Prefixes (P)'Length ..
-                         Result (C)'Last);
+                           Result (C)'Last);
+
+                  if Params (C) /= null then
+                     Group := Group &
+                       Params (C) (Params (C)'First + 1 .. Params (C)'Last);
+                     Free (Params (C));
+                  end if;
+
                   if First = 0 then
                      First := C;
                   end if;
@@ -1646,22 +1964,25 @@ package body GNAT.Command_Line is
       Found : Boolean;
       First : Natural;
 
-      procedure Check_Cb (Switch : String);
+      procedure Check_Cb (Switch : String; Param : String);
       --  Comment required ???
 
-      procedure Remove_Cb (Switch : String);
+      procedure Remove_Cb (Switch : String; Param : String);
       --  Comment required ???
 
       --------------
       -- Check_Cb --
       --------------
 
-      procedure Check_Cb (Switch : String) is
+      procedure Check_Cb (Switch : String; Param : String) is
       begin
          if Found then
             for E in Result'Range loop
                if Result (E) /= null
-                 and then Params (E) = null    --  Ignore if has a param
+                 and then
+                   (Params (E) = null
+                    or else Params (E) (Params (E)'First + 1
+                                            .. Params (E)'Last) = Param)
                  and then Result (E).all = Switch
                then
                   return;
@@ -1676,14 +1997,21 @@ package body GNAT.Command_Line is
       -- Remove_Cb --
       ---------------
 
-      procedure Remove_Cb (Switch : String) is
+      procedure Remove_Cb (Switch : String; Param : String) is
       begin
          for E in Result'Range loop
-            if Result (E) /= null and then Result (E).all = Switch then
+            if Result (E) /= null
+                 and then
+                   (Params (E) = null
+                    or else Params (E) (Params (E)'First + 1
+                                            .. Params (E)'Last) = Param)
+              and then Result (E).all = Switch
+            then
                if First > E then
                   First := E;
                end if;
                Free (Result (E));
+               Free (Params (E));
                return;
             end if;
          end loop;
@@ -1820,11 +2148,20 @@ package body GNAT.Command_Line is
             end if;
          end loop;
 
+         Cmd.Coalesce_Params := new Argument_List (Cmd.Params'Range);
+         for E in Cmd.Params'Range loop
+            if Cmd.Params (E) = null then
+               Cmd.Coalesce_Params (E) := null;
+            else
+               Cmd.Coalesce_Params (E) := new String'(Cmd.Params (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.Coalesce_Sections, Cmd.Params);
+         Alias_Switches (Cmd, Cmd.Coalesce, Cmd.Coalesce_Params);
+         Group_Switches
+           (Cmd, Cmd.Coalesce, Cmd.Coalesce_Sections, Cmd.Coalesce_Params);
       end if;
 
       if Expanded then
@@ -1841,6 +2178,7 @@ package body GNAT.Command_Line is
          Iter.Current := Integer'Last;
       else
          Iter.Current := Iter.List'First;
+
          while Iter.Current <= Iter.List'Last
            and then Iter.List (Iter.Current) = null
          loop
index d92c157..738afe9 100644 (file)
@@ -513,6 +513,14 @@ package GNAT.Command_Line is
    --  characters whose order is irrelevant. In fact, this package will sort
    --  them alphabetically.
 
+   procedure Define_Switch
+     (Config : in out Command_Line_Configuration;
+      Switch : String);
+   --  Indicates a new switch. The format of this switch follows the getopt
+   --  format (trailing ':', '?', etc for defining a switch with parameters).
+   --  The switches defined in the command_line_configuration object are used
+   --  when ungrouping switches with more that one character after the prefix.
+
    procedure Define_Section
      (Config  : in out Command_Line_Configuration;
       Section : String);
@@ -520,6 +528,13 @@ package GNAT.Command_Line is
    --  section are ordered together, preceded by the section. They are placed
    --  at the end of the command line (as in 'gnatmake somefile.adb -cargs -g')
 
+   function Get_Switches
+     (Config      : Command_Line_Configuration;
+      Switch_Char : Character)
+      return String;
+   --  Get the switches list as expected by getopt. This list is built using
+   --  all switches defined previously via Define_Switch above.
+
    procedure Free (Config : in out Command_Line_Configuration);
    --  Free the memory used by Config
 
@@ -595,11 +610,22 @@ package GNAT.Command_Line is
    --  added if not already present. For example, to add the -g switch into the
    --  -cargs section, you need to call (Cmd, "-g", Section => "-cargs")
 
+   procedure Add_Switch
+     (Cmd       : in out Command_Line;
+      Switch    : String;
+      Parameter : String    := "";
+      Separator : Character := ' ';
+      Section   : String    := "";
+      Success   : out Boolean);
+   --  Same as above, returning the status of
+   --  the operation
+
    procedure Remove_Switch
-     (Cmd        : in out Command_Line;
-      Switch     : String;
-      Remove_All : Boolean := False;
-      Section    : String := "");
+     (Cmd           : in out Command_Line;
+      Switch        : String;
+      Remove_All    : Boolean := False;
+      Has_Parameter : Boolean := False;
+      Section       : String := "");
    --  Remove Switch from the command line, and ungroup existing switches if
    --  necessary.
    --
@@ -610,6 +636,9 @@ package GNAT.Command_Line is
    --  If Remove_All is True, then all matching switches are removed, otherwise
    --  only the first matching one is removed.
    --
+   --  if Has_Parameter is set to True, then only switches having a parameter
+   --  are removed.
+   --
    --  If the switch belongs to a section, then this section should be
    --  specified: Remove_Switch (Cmd_Line, "-g", Section => "-cargs") called
    --  on the command line "-g -cargs -g" will result in "-g", while if
@@ -617,6 +646,16 @@ package GNAT.Command_Line is
    --  If Remove_All is set, then both "-g" will be removed.
 
    procedure Remove_Switch
+     (Cmd           : in out Command_Line;
+      Switch        : String;
+      Remove_All    : Boolean := False;
+      Has_Parameter : Boolean := False;
+      Section       : String  := "";
+      Success       : out Boolean);
+   --  Same as above, reporting the success of the operation (Success is False
+   --  if no switch was removed).
+
+   procedure Remove_Switch
      (Cmd       : in out Command_Line;
       Switch    : String;
       Parameter : String;
@@ -774,6 +813,9 @@ private
       Aliases    : GNAT.OS_Lib.Argument_List_Access;
       Expansions : GNAT.OS_Lib.Argument_List_Access;
       --  The aliases. Both arrays have the same indices
+
+      Switches   : GNAT.OS_Lib.Argument_List_Access;
+      --  List of expected switches. Used when expanding switch groups.
    end record;
    type Command_Line_Configuration is access Command_Line_Configuration_Record;