[Ada] Argument_String_To_List creates empty items from whitespace

This patch corrects an issue whereby leading whitespace in a non-quoted
argument list passed to Argument_String_To_List caused extraneous empty
arguments to be returned.

2018-07-17  Justin Squirek  <squirek@adacore.com>

gcc/ada/

	* libgnat/s-os_lib.adb (Argument_String_To_List): Fix trimming of
	whitespace.

gcc/testsuite/

	* gnat.dg/split_args.adb: New testcase.

From-SVN: r262783
This commit is contained in:
Justin Squirek 2018-07-17 08:07:42 +00:00 committed by Pierre-Marie de Rodat
parent e6bc029a34
commit 1b72a5637c
4 changed files with 77 additions and 57 deletions

View File

@ -1,3 +1,8 @@
2018-07-17 Justin Squirek <squirek@adacore.com>
* libgnat/s-os_lib.adb (Argument_String_To_List): Fix trimming of
whitespace.
2018-07-17 Hristian Kirtchev <kirtchev@adacore.com> 2018-07-17 Hristian Kirtchev <kirtchev@adacore.com>
* sem_prag.adb (Has_Visible_State): Do not consider constants as * sem_prag.adb (Has_Visible_State): Do not consider constants as

View File

@ -178,7 +178,6 @@ package body System.OS_Lib is
return Len; return Len;
end Args_Length; end Args_Length;
----------------------------- -----------------------------
-- Argument_String_To_List -- -- Argument_String_To_List --
----------------------------- -----------------------------
@ -191,6 +190,9 @@ package body System.OS_Lib is
Idx : Integer; Idx : Integer;
New_Argc : Natural := 0; New_Argc : Natural := 0;
Backqd : Boolean := False;
Quoted : Boolean := False;
Cleaned : String (1 .. Arg_String'Length); Cleaned : String (1 .. Arg_String'Length);
Cleaned_Idx : Natural; Cleaned_Idx : Natural;
-- A cleaned up version of the argument. This function is taking -- A cleaned up version of the argument. This function is taking
@ -205,75 +207,71 @@ package body System.OS_Lib is
Idx := Arg_String'First; Idx := Arg_String'First;
loop loop
-- Skip extraneous spaces
while Idx <= Arg_String'Last and then Arg_String (Idx) = ' ' loop
Idx := Idx + 1;
end loop;
exit when Idx > Arg_String'Last; exit when Idx > Arg_String'Last;
declare Cleaned_Idx := Cleaned'First;
Backqd : Boolean := False; Backqd := False;
Quoted : Boolean := False; Quoted := False;
begin loop
Cleaned_Idx := Cleaned'First; -- An unquoted space is the end of an argument
loop if not (Backqd or Quoted)
-- An unquoted space is the end of an argument and then Arg_String (Idx) = ' '
then
exit;
if not (Backqd or Quoted) -- Start of a quoted string
and then Arg_String (Idx) = ' '
then
exit;
-- Start of a quoted string elsif not (Backqd or Quoted)
and then Arg_String (Idx) = '"'
then
Quoted := True;
Cleaned (Cleaned_Idx) := Arg_String (Idx);
Cleaned_Idx := Cleaned_Idx + 1;
elsif not (Backqd or Quoted) -- End of a quoted string and end of an argument
and then Arg_String (Idx) = '"'
then
Quoted := True;
Cleaned (Cleaned_Idx) := Arg_String (Idx);
Cleaned_Idx := Cleaned_Idx + 1;
-- End of a quoted string and end of an argument
elsif (Quoted and not Backqd)
and then Arg_String (Idx) = '"'
then
Cleaned (Cleaned_Idx) := Arg_String (Idx);
Cleaned_Idx := Cleaned_Idx + 1;
Idx := Idx + 1;
exit;
-- Turn off backquoting after advancing one character
elsif Backqd then
Backqd := False;
Cleaned (Cleaned_Idx) := Arg_String (Idx);
Cleaned_Idx := Cleaned_Idx + 1;
-- Following character is backquoted
elsif not Backslash_Is_Sep and then Arg_String (Idx) = '\' then
Backqd := True;
else
Cleaned (Cleaned_Idx) := Arg_String (Idx);
Cleaned_Idx := Cleaned_Idx + 1;
end if;
elsif (Quoted and not Backqd)
and then Arg_String (Idx) = '"'
then
Cleaned (Cleaned_Idx) := Arg_String (Idx);
Cleaned_Idx := Cleaned_Idx + 1;
Idx := Idx + 1; Idx := Idx + 1;
exit when Idx > Arg_String'Last; exit;
end loop;
-- Found an argument -- Turn off backquoting after advancing one character
New_Argc := New_Argc + 1; elsif Backqd then
New_Argv (New_Argc) := Backqd := False;
new String'(Cleaned (Cleaned'First .. Cleaned_Idx - 1)); Cleaned (Cleaned_Idx) := Arg_String (Idx);
Cleaned_Idx := Cleaned_Idx + 1;
-- Skip extraneous spaces -- Following character is backquoted
while Idx <= Arg_String'Last and then Arg_String (Idx) = ' ' loop elsif not Backslash_Is_Sep and then Arg_String (Idx) = '\' then
Idx := Idx + 1; Backqd := True;
end loop;
end; else
Cleaned (Cleaned_Idx) := Arg_String (Idx);
Cleaned_Idx := Cleaned_Idx + 1;
end if;
Idx := Idx + 1;
exit when Idx > Arg_String'Last;
end loop;
-- Found an argument
New_Argc := New_Argc + 1;
New_Argv (New_Argc) :=
new String'(Cleaned (Cleaned'First .. Cleaned_Idx - 1));
end loop; end loop;
return new Argument_List'(New_Argv (1 .. New_Argc)); return new Argument_List'(New_Argv (1 .. New_Argc));

View File

@ -1,3 +1,7 @@
2018-07-17 Justin Squirek <squirek@adacore.com>
* gnat.dg/split_args.adb: New testcase.
2018-07-17 Ed Schonberg <schonberg@adacore.com> 2018-07-17 Ed Schonberg <schonberg@adacore.com>
* gnat.dg/discr54.adb, gnat.dg/discr54_pkg.ads: New testcase. * gnat.dg/discr54.adb, gnat.dg/discr54_pkg.ads: New testcase.

View File

@ -0,0 +1,13 @@
-- { dg-do run }
-- { dg-options "-gnatws" }
with System.OS_Lib; use System.OS_Lib;
procedure Split_Args is
X : constant Argument_List_Access :=
Argument_String_To_List (" -v");
begin
if X'Length /= 1 then
raise Program_Error;
end if;
end Split_Args;