[Ada] Argument_String_To_List creates empty items from whitespace

Message ID 20180717082347.GA1419@adacore.com
State New
Headers show
Series
  • [Ada] Argument_String_To_List creates empty items from whitespace
Related show

Commit Message

Pierre-Marie de Rodat July 17, 2018, 8:23 a.m.
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  <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.

Patch

--- 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;