diff --git a/lib/modules/Arg.pmod b/lib/modules/Arg.pmod
index 2a4677cfec1dda5a4f7f5afe04ea23d6a53d34e2..76d6dff858dc39a614cddb13165e11fd18789d15 100644
--- a/lib/modules/Arg.pmod
+++ b/lib/modules/Arg.pmod
@@ -18,11 +18,13 @@ class OptLibrary
     //! Should return 1 for set options or a string containing the
     //! value of the option. Returning 0 means the option was not set
     //! (or matched). To properly chain arguments parsers, return
-    //! @expr{::get_value(argv, env)@} instead of @expr{0@}, unless
-    //! you want to explicitly stop the chain and not set this option.
-    int(0..1)|string get_value(array(string) argv, mapping(string:string) env)
+    //! @expr{::get_value(argv, env, previous)@} instead of @expr{0@},
+    //! unless you want to explicitly stop the chain and not set this
+    //! option.
+    mixed get_value(array(string) argv, mapping(string:string) env,
+                         int|string previous)
     {
-      if(next) return next->get_value(argv, env);
+      if(next) return next->get_value(argv, env, previous);
       return 0;
     }
 
@@ -88,18 +90,18 @@ class OptLibrary
       opt = _opt;
     }
 
-    int(0..1)|string get_value(array(string) argv, mapping(string:string) env)
+    mixed get_value(array(string) argv, mapping(string:string) env, mixed previous)
     {
-      if( !sizeof(argv) ) return ::get_value(argv, env);
+      if( !sizeof(argv) ) return previous || ::get_value(argv, env, previous);
 
       if( double )
       {
         if( argv[0]==opt )
         {
           argv[0] = 0;
-          return 1;
+          return (int)previous+1;
         }
-        return ::get_value(argv, env);
+        return previous || ::get_value(argv, env, previous);
       }
 
       if( sizeof(argv[0])>1 && argv[0][0]=='-' && argv[0][1]!='-' )
@@ -110,11 +112,11 @@ class OptLibrary
           parts[0] -= opt[1..1];
           argv[0] = parts*"=";
           if(argv[0]=="-") argv[0] = 0;
-          return 1;
+          return (int)previous+1;
         }
       }
 
-      return ::get_value(argv, env);
+      return previous || ::get_value(argv, env, previous);
     }
 
     array(string) get_opts()
@@ -143,10 +145,10 @@ class OptLibrary
       name = _name;
     }
 
-    int(0..1)|string get_value(array(string) argv, mapping(string:string) env)
+    mixed get_value(array(string) argv, mapping(string:string) env, mixed previous)
     {
       if( env[name] ) return env[name];
-      return ::get_value(argv, env);
+      return ::get_value(argv, env, previous);
     }
 
     protected string __sprintf()
@@ -169,7 +171,7 @@ class OptLibrary
       value = _value;
     }
 
-    string get_value(array(string) argv, mapping(string:string) env)
+    string get_value(array(string) argv, mapping(string:string) env, mixed previous)
     {
       return value;
     }
@@ -191,9 +193,9 @@ class OptLibrary
   {
     inherit NoOpt;
 
-    int(0..1)|string get_value(array(string) argv, mapping(string:string) env)
+    mixed get_value(array(string) argv, mapping(string:string) env, mixed previous)
     {
-      if( !sizeof(argv) ) return ::get_value(argv, env);
+      if( !sizeof(argv) ) return previous || ::get_value(argv, env, previous);
 
       if( double )
       {
@@ -201,17 +203,18 @@ class OptLibrary
         if( argv[0]==opt )
         {
           argv[0] = 0;
-          return 1;
+          return (int)previous+1;
         }
 
         // --foo=bar
         if( sscanf(argv[0], opt+"=%s", string ret)==1 )
         {
           argv[0] = 0;
+          // FIXME: Make an array if previous is set?
           return ret;
         }
 
-        return ::get_value(argv, env);
+        return previous || ::get_value(argv, env, previous);
       }
 
       // -x
@@ -227,7 +230,7 @@ class OptLibrary
           parts[0] -= opt[1..1];
           argv[0] = parts*"=";
           if(argv[0]=="-") argv[0] = 0;
-          return 1;
+          return (int)previous+1;
         }
         else if( sizeof(parts)>1 && parts[0][-1]==opt[1] )
         {
@@ -240,10 +243,10 @@ class OptLibrary
           return parts[1..]*"=";
         }
 
-        return ::get_value(argv, env);
+        return previous || ::get_value(argv, env, previous);
       }
 
-      return ::get_value(argv, env);
+      return previous || ::get_value(argv, env, previous);
     }
 
     protected string __sprintf()
@@ -261,9 +264,9 @@ class OptLibrary
   {
     inherit NoOpt;
 
-    int(0..1)|string get_value(array(string) argv, mapping(string:string) env)
+    mixed get_value(array(string) argv, mapping(string:string) env, mixed previous)
     {
-      if( !sizeof(argv) ) return ::get_value(argv, env);
+      if( !sizeof(argv) ) return previous || ::get_value(argv, env, previous);
 
       if( double )
       {
@@ -286,7 +289,7 @@ class OptLibrary
           argv[0] = 0;
           return ret;
         }
-        return ::get_value(argv, env);
+        return previous || ::get_value(argv, env, previous);
       }
 
       if( sizeof(argv[0])>1 && argv[0][0]=='-' && argv[0][1]!='-' )
@@ -310,7 +313,7 @@ class OptLibrary
             }
 
             // Fail. "-y" without any more elements in argv.
-            return ::get_value(argv, env);
+            return previous || ::get_value(argv, env, previous);
           }
           else
           {
@@ -325,7 +328,7 @@ class OptLibrary
         }
       }
 
-      return ::get_value(argv, env);
+      return previous || ::get_value(argv, env, previous);
     }
 
     protected string __sprintf()
@@ -371,30 +374,27 @@ class LowOptions
     argv = _argv[1..];
     mapping(string:Opt) unset = opts+([]);
 
-    while(1)
+    while(sizeof(argv))
     {
-      if(!sizeof(argv)) break;
-
-      int(0..1)|string value;
-      foreach(unset; string index; Opt arg)
+      array(string) pre = argv+({});
+      foreach(opts; string index; Opt arg)
       {
-        value = arg->get_value(argv, env);
+        int(0..1)|string value = arg->get_value(argv, env, values[index]);
         if(value)
         {
           m_delete(unset, index);
           values[index] = value;
-          break;
+          argv -= ({ 0 });
         }
       }
+      argv -= ({ 0 });
 
-      if(!value)
-        value = unhandled_argument(argv, env);
-
-      if(!value)
-        break;
-      else
-        while( sizeof(argv) && argv[0] == 0 )
-          argv = argv[1..];
+      if(equal(pre, argv))
+      {
+        unhandled_argument(argv, env);
+        if(equal(pre, argv))
+          break;
+      }
     }
 
     if( sizeof(unset) )
@@ -402,12 +402,9 @@ class LowOptions
       int(0..1)|string value;
       foreach(unset; string index; Opt arg)
       {
-        value = arg->get_value(({}), env);
+        value = arg->get_value(({}), env, values[index]);
         if(value)
-        {
-          m_delete(unset, index);
           values[index] = value;
-        }
       }
     }
 
@@ -502,7 +499,10 @@ class SimpleOptions
     {
       sscanf( arg, "--%s=%s", name, value ) || sscanf( arg, "--%s", name );
       if(!name) return 0; // arg == "--"
-      values[name] = value||1;
+      if( value )
+        values[name] = value;
+      else
+        values[name]++;
       argv[0]=0;
       return 1;
     }
@@ -510,10 +510,12 @@ class SimpleOptions
     sscanf( arg, "-%s=%s", name, value ) || sscanf( arg, "-%s", name );
     if( !name || !sizeof(name) ) return 0;
     foreach( name/1; int pos; string c )
-      if( pos == sizeof(name)-1 )
-        values[c] = value||1;
+    {
+      if( value && pos == sizeof(name)-1 )
+        values[c] = value;
       else
-        values[c] = 1;
+        values[c]++;
+    }
     argv[0]=0;
     return 1;
   }
@@ -525,8 +527,10 @@ class SimpleOptions
 // -bar          ->  "b":1,"a":1,"r":1
 // -bar=foo      ->  "b":1,"a":1,"r":"foo" (?)
 // --foo --bar   ->  "foo":1,"bar":1
-// --foo - --bar -> "foo":1
-// --foo x --bar -> "foo":1 (?)
+// --foo - --bar ->  "foo":1
+// --foo x --bar ->  "foo":1 (?)
+// -foo          ->  "f":1,"o":2
+// -x -x -x      ->  "x":3
 //
 // void main(int n, array argv)
 // {
diff --git a/lib/modules/testsuite.in b/lib/modules/testsuite.in
index ae320ac8eef2b6d1688170e313d7d835b6092993..63bd81b923432216218a33d2c5c52e11645a2aa6 100644
--- a/lib/modules/testsuite.in
+++ b/lib/modules/testsuite.in
@@ -13,6 +13,8 @@ test_equal( Arg.parse("aa --foo - --bar"/" "),
  ([ "foo":1, Arg.REST: ({ "-","--bar" }) ]) )
 test_equal( Arg.parse("aa --foo x --bar"/" "),
  ([ "foo":1, Arg.REST: ({ "x","--bar" }) ]) )
+test_equal( Arg.parse("aa -foo -o"/" "),
+ ([ "f":1, "o":3, Arg.REST: ({}) ]) )
 
 test_any([[
 
@@ -39,6 +41,7 @@ test_equal( o("x -n foo"/" ",([]))->name , "foo" )
 test_equal( (mapping)o("x -dvn foo xor"/" ",([])), ([ "debug":1, "verbose":1, "name":"foo", Arg.REST : ({ "xor" }) ]) )
 test_equal( o(({"x"}),(["VERBOSE":"1"]))->verbose, "1" )
 test_equal( (mapping)o("x --verbose=5"/" ",([])), ([ "name":"Donald", Arg.REST : ({ "--verbose=5" }) ]) )
+test_equal( o("x -v -v"/" ",([]))->verbose , 2 )
 
 test_do(add_constant("o"))