The following code should find two switches on the command line: -gnatyL (with parameter "1") and -gnatya. Instead, we used to find a single switch -gnatyL with parameter "1a".
Define_Switch (Config, "-gnatyL!"); Define_Switch (Config, "-gnatya"); Define_Prefix (Config, "-gnaty"); Set_Configuration (Cmd, Config); set_Command_Line (Cmd, "-gnatyL1a"); Start (Cmd, Iter, Expanded => True); while Has_More (Iter) loop Put_Line (Current_Switch (Iter)); Next (Iter); end loop; Tested on x86_64-pc-linux-gnu, committed on trunk 2011-08-03 Emmanuel Briot <br...@adacore.com> * g-comlin.adb, g-comlin.ads (Set_Command_Line): ignore the parameter Getopt_Switches when we have already define a command line configuration.
Index: g-comlin.adb =================================================================== --- g-comlin.adb (revision 177274) +++ g-comlin.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1999-2010, Free Software Foundation, Inc. -- +-- Copyright (C) 1999-2011, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -19,10 +19,10 @@ -- additional permissions described in the GCC Runtime Library Exception, -- -- version 3.1, as published by the Free Software Foundation. -- -- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- +-- In particular, you can freely distribute your programs built with the -- +-- GNAT Pro compiler, including any required library run-time units, using -- +-- any licensing terms of your choosing. See the AdaCore Software License -- +-- for full details. -- -- -- -- GNAT was originally developed by the GNAT team at New York University. -- -- Extensive contributions were provided by Ada Core Technologies Inc. -- @@ -200,7 +200,8 @@ (Config : Command_Line_Configuration; Section : String); -- Iterate over all switches defined in Config, for a specific section. - -- Index is set to the index in Config.Switches + -- Index is set to the index in Config.Switches. + -- Stop iterating when Callback returns False. -------------- -- Argument -- @@ -1238,6 +1239,10 @@ Unchecked_Free (Tmp); end if; + if Switch.Switch /= null and then Switch.Switch.all = "*" then + Config.Star_Switch := True; + end if; + Config.Switches (Config.Switches'Last) := Switch; end Add; @@ -1592,9 +1597,28 @@ loop begin - S := Getopt (Switches => "* " & Getopt_Description, - Concatenate => False, - Parser => Parser); + if Cmd.Config /= null then + -- Do not use Getopt_Description in this case. Otherwise, + -- if we have defined a prefix -gnaty, and two switches + -- -gnatya and -gnatyL!, we would have a different behavior + -- depending on the order of switches: + -- -gnatyL1a => -gnatyL with argument "1a" + -- -gnatyaL1 => -gnatya and -gnatyL with argument "1" + -- This is because the call to Getopt below knows nothing + -- about prefixes, and in the first case finds a valid + -- switch with arguments, so returns it without analyzing + -- the argument. In the second case, the switch matches "*", + -- and is then decomposed below. + + S := Getopt (Switches => "*", + Concatenate => False, + Parser => Parser); + else + S := Getopt (Switches => "* " & Getopt_Description, + Concatenate => False, + Parser => Parser); + end if; + exit when S = ASCII.NUL; declare @@ -1761,6 +1785,8 @@ function Analyze_Simple_Switch (Switch : String; Index : Integer) return Boolean; + -- "Switches" is one of the switch definitions passed to the + -- configuration, not one of the switches found on the command line. --------------------------- -- Analyze_Simple_Switch -- @@ -1772,26 +1798,26 @@ pragma Unreferenced (Index); Full : constant String := Prefix & Group (Idx .. Group'Last); + Sw : constant String := Actual_Switch (Switch); + -- Switches definition minus argument definition + Last : Natural; Param : Natural; begin - if Sw'Length >= Prefix'Length + if + -- Verify that sw starts with Prefix + Looking_At (Sw, Sw'First, Prefix) - -- Verify that sw starts with Prefix + -- Verify that the group starts with sw + and then Looking_At (Full, Full'First, Sw) - 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 (Switch) then - -- Include potential parameter to the recursive call. -- Only numbers are allowed. @@ -1989,8 +2015,10 @@ -- First determine if the switch corresponds to one belonging to the -- configuration. If so, run callback and exit. + -- ??? Is this necessary. On simple tests, we seem to have the same + -- results with or without this call. + Foreach_In_Config (Config, Section); - if Found_In_Config then return; end if; @@ -2127,10 +2155,17 @@ Param : String; Index : Integer) is - pragma Unreferenced (Index); Sep : Character; begin + if Index = -1 + and then Cmd.Config /= null + and then not Cmd.Config.Star_Switch + then + raise Invalid_Switch + with "Invalid switch " & Simple; + end if; + if Separator = "" then Sep := ASCII.NUL; else @@ -2808,13 +2843,8 @@ if Iter.List = null then Iter.Current := Integer'Last; else - Iter.Current := Iter.List'First; - - while Iter.Current <= Iter.List'Last - and then Iter.List (Iter.Current) = null - loop - Iter.Current := Iter.Current + 1; - end loop; + Iter.Current := Iter.List'First - 1; + Next (Iter); end if; end Start; Index: g-comlin.ads =================================================================== --- g-comlin.ads (revision 177274) +++ g-comlin.ads (working copy) @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1999-2010, AdaCore -- +-- Copyright (C) 1999-2011, AdaCore -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -583,6 +583,10 @@ -- assumed that the remainder of the switch ("uv") is a set of characters -- whose order is irrelevant. In fact, this package will sort them -- alphabetically. + -- When grouping switches that accept arguments (for instance "-gnatyL!" + -- as the definition, and "-gnatyaL12b" as the command line), only + -- numerical arguments are accepted. The above is equivalent to + -- "-gnatya -gnatyL12 -gnatyb". procedure Define_Switch (Config : in out Command_Line_Configuration; @@ -768,7 +772,9 @@ Config : Command_Line_Configuration); function Get_Configuration (Cmd : Command_Line) return Command_Line_Configuration; - -- Set or retrieve the configuration used for that command line + -- Set or retrieve the configuration used for that command line. + -- The Config must have been initialized first, by calling one of the + -- Define_Switches subprograms. procedure Set_Command_Line (Cmd : in out Command_Line; @@ -781,6 +787,8 @@ -- The parsing of Switches is done through calls to Getopt, by passing -- Getopt_Description as an argument. (A "*" is automatically prepended so -- that all switches and command line arguments are accepted). + -- If a config was defined via Set_Configuration, the Getopt_Description + -- parameter will be ignored. -- -- To properly handle switches that take parameters, you should document -- them in Getopt_Description. Otherwise, the switch and its parameter will @@ -792,6 +800,12 @@ -- should be listed in the Sections parameter (as "-bargs -cargs"). -- -- This function can be used to reset Cmd by passing an empty string. + -- + -- If an invalid switch is found on the command line (ie wasn't defined in + -- the configuration via Define_Switch), and the configuration wasn't set + -- to accept all switches (by defining "*" as a valid switch), then an + -- exception Invalid_Switch is raised. The exception message indicates the + -- invalid switch. procedure Add_Switch (Cmd : in out Command_Line; @@ -1084,6 +1098,11 @@ Sections : GNAT.OS_Lib.Argument_List_Access; -- The list of sections + Star_Switch : Boolean := False; + -- Whether switches not described in this configuration should be + -- returned to the user (True). If False, an exception Invalid_Switch + -- is raised. + Aliases : Alias_Definitions_List; Usage : GNAT.OS_Lib.String_Access; Help : GNAT.OS_Lib.String_Access;