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.
Tested on x86_64-pc-linux-gnu, committed on trunk
2018-07-17 Justin Squirek <squi...@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.
--- gcc/ada/libgnat/s-os_lib.adb
+++ gcc/ada/libgnat/s-os_lib.adb
@@ -178,7 +178,6 @@ package body System.OS_Lib is
return Len;
end Args_Length;
-
-----------------------------
-- Argument_String_To_List --
-----------------------------
@@ -191,6 +190,9 @@ package body System.OS_Lib is
Idx : Integer;
New_Argc : Natural := 0;
+ Backqd : Boolean := False;
+ Quoted : Boolean := False;
+
Cleaned : String (1 .. Arg_String'Length);
Cleaned_Idx : Natural;
-- 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;
loop
- exit when Idx > Arg_String'Last;
+ -- Skip extraneous spaces
- declare
- Backqd : Boolean := False;
- Quoted : Boolean := False;
-
- begin
- Cleaned_Idx := Cleaned'First;
+ while Idx <= Arg_String'Last and then Arg_String (Idx) = ' ' loop
+ Idx := Idx + 1;
+ end loop;
- loop
- -- An unquoted space is the end of an argument
+ exit when Idx > Arg_String'Last;
- if not (Backqd or Quoted)
- and then Arg_String (Idx) = ' '
- then
- exit;
+ Cleaned_Idx := Cleaned'First;
+ Backqd := False;
+ Quoted := False;
- -- Start of a quoted string
+ loop
+ -- An unquoted space is the end of an argument
- elsif not (Backqd or Quoted)
- and then Arg_String (Idx) = '"'
- then
- Quoted := True;
- Cleaned (Cleaned_Idx) := Arg_String (Idx);
- Cleaned_Idx := Cleaned_Idx + 1;
+ if not (Backqd or Quoted)
+ and then Arg_String (Idx) = ' '
+ then
+ exit;
- -- End of a quoted string and end of an argument
+ -- Start of a quoted string
- 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;
+ elsif not (Backqd or Quoted)
+ and then Arg_String (Idx) = '"'
+ then
+ Quoted := True;
+ Cleaned (Cleaned_Idx) := Arg_String (Idx);
+ Cleaned_Idx := Cleaned_Idx + 1;
- -- Turn off backquoting after advancing one character
+ -- End of a quoted string and end of an argument
- elsif Backqd then
- Backqd := False;
- Cleaned (Cleaned_Idx) := Arg_String (Idx);
- Cleaned_Idx := Cleaned_Idx + 1;
+ 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;
- -- Following character is backquoted
+ -- Turn off backquoting after advancing one character
- elsif not Backslash_Is_Sep and then Arg_String (Idx) = '\' then
- Backqd := True;
+ elsif Backqd then
+ Backqd := False;
+ Cleaned (Cleaned_Idx) := Arg_String (Idx);
+ Cleaned_Idx := Cleaned_Idx + 1;
- else
- Cleaned (Cleaned_Idx) := Arg_String (Idx);
- Cleaned_Idx := Cleaned_Idx + 1;
- end if;
+ -- Following character is backquoted
- Idx := Idx + 1;
- exit when Idx > Arg_String'Last;
- end loop;
+ elsif not Backslash_Is_Sep and then Arg_String (Idx) = '\' then
+ Backqd := True;
- -- Found an argument
+ else
+ Cleaned (Cleaned_Idx) := Arg_String (Idx);
+ Cleaned_Idx := Cleaned_Idx + 1;
+ end if;
- New_Argc := New_Argc + 1;
- New_Argv (New_Argc) :=
- new String'(Cleaned (Cleaned'First .. Cleaned_Idx - 1));
+ Idx := Idx + 1;
+ exit when Idx > Arg_String'Last;
+ end loop;
- -- Skip extraneous spaces
+ -- Found an argument
- while Idx <= Arg_String'Last and then Arg_String (Idx) = ' ' loop
- Idx := Idx + 1;
- end loop;
- end;
+ New_Argc := New_Argc + 1;
+ New_Argv (New_Argc) :=
+ new String'(Cleaned (Cleaned'First .. Cleaned_Idx - 1));
end loop;
return new Argument_List'(New_Argv (1 .. New_Argc));
--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/split_args.adb
@@ -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;