f231f65
From 33962967111fbed55e93260b12cd65e372a0958a Mon Sep 17 00:00:00 2001
f231f65
From: "Richard W.M. Jones" <rjones@redhat.com>
f231f65
Date: Sat, 9 Nov 2013 09:11:30 +0000
efb2ca1
Subject: [PATCH 08/11] stdlib: arg: Allow flags such as --flag=arg as well as
efb2ca1
 --flag arg.
f231f65
f231f65
Fix for the following issue:
f231f65
http://caml.inria.fr/mantis/view.php?id=5197
f231f65
---
f231f65
 stdlib/arg.ml  | 85 ++++++++++++++++++++++++++++++++++------------------------
f231f65
 stdlib/arg.mli |  3 ++-
f231f65
 2 files changed, 52 insertions(+), 36 deletions(-)
f231f65
f231f65
diff --git a/stdlib/arg.ml b/stdlib/arg.ml
f231f65
index 8b64236..d94b75f 100644
f231f65
--- a/stdlib/arg.ml
f231f65
+++ b/stdlib/arg.ml
f231f65
@@ -55,6 +55,12 @@ let rec assoc3 x l =
f231f65
   | _ :: t -> assoc3 x t
f231f65
 ;;
f231f65
 
f231f65
+let split s =
f231f65
+  let i = String.index s '=' in
f231f65
+  let len = String.length s in
f231f65
+  String.sub s 0 i, String.sub s (i+1) (len-(i+1))
f231f65
+;;
f231f65
+
f231f65
 let make_symlist prefix sep suffix l =
f231f65
   match l with
f231f65
   | [] -> "<none>"
f231f65
@@ -130,73 +136,82 @@ let parse_argv_dynamic ?(current=current) argv speclist anonfun errmsg =
f231f65
   while !current < l do
f231f65
     let s = argv.(!current) in
f231f65
     if String.length s >= 1 && String.get s 0 = '-' then begin
f231f65
-      let action =
f231f65
-        try assoc3 s !speclist
f231f65
-        with Not_found -> stop (Unknown s)
f231f65
+      let action, follow =
f231f65
+        try assoc3 s !speclist, None
f231f65
+        with Not_found ->
f231f65
+          try
f231f65
+            let keyword, arg = split s in
f231f65
+            assoc3 keyword !speclist, Some arg
f231f65
+          with Not_found -> stop (Unknown s)
f231f65
+      in
f231f65
+      let no_arg () =
f231f65
+        match follow with
f231f65
+        | None -> ()
f231f65
+        | Some arg -> stop (Wrong (s, arg, "no argument"))
f231f65
+      in
f231f65
+      let get_arg () =
f231f65
+        match follow with
f231f65
+        | None ->
f231f65
+          if !current + 1 < l then begin
f231f65
+            incr current;
f231f65
+            argv.(!current)
f231f65
+          end
f231f65
+          else stop (Missing s)
f231f65
+        | Some arg -> arg
f231f65
       in
f231f65
       begin try
f231f65
         let rec treat_action = function
f231f65
-        | Unit f -> f ();
f231f65
-        | Bool f when !current + 1 < l ->
f231f65
-            let arg = argv.(!current + 1) in
f231f65
+        | Unit f -> no_arg (); f ();
f231f65
+        | Bool f ->
f231f65
+            let arg = get_arg () in
f231f65
             begin try f (bool_of_string arg)
f231f65
             with Invalid_argument "bool_of_string" ->
f231f65
                    raise (Stop (Wrong (s, arg, "a boolean")))
f231f65
             end;
f231f65
-            incr current;
f231f65
-        | Set r -> r := true;
f231f65
-        | Clear r -> r := false;
f231f65
-        | String f when !current + 1 < l ->
f231f65
-            f argv.(!current + 1);
f231f65
-            incr current;
f231f65
-        | Symbol (symb, f) when !current + 1 < l ->
f231f65
-            let arg = argv.(!current + 1) in
f231f65
+        | Set r -> no_arg (); r := true;
f231f65
+        | Clear r -> no_arg (); r := false;
f231f65
+        | String f ->
f231f65
+            f (get_arg ());
f231f65
+        | Symbol (symb, f) ->
f231f65
+            let arg = get_arg () in
f231f65
             if List.mem arg symb then begin
f231f65
-              f argv.(!current + 1);
f231f65
-              incr current;
f231f65
+              f arg;
f231f65
             end else begin
f231f65
               raise (Stop (Wrong (s, arg, "one of: "
f231f65
                                           ^ (make_symlist "" " " "" symb))))
f231f65
             end
f231f65
-        | Set_string r when !current + 1 < l ->
f231f65
-            r := argv.(!current + 1);
f231f65
-            incr current;
f231f65
-        | Int f when !current + 1 < l ->
f231f65
-            let arg = argv.(!current + 1) in
f231f65
+        | Set_string r ->
f231f65
+            r := get_arg ();
f231f65
+        | Int f ->
f231f65
+            let arg = get_arg () in
f231f65
             begin try f (int_of_string arg)
f231f65
             with Failure "int_of_string" ->
f231f65
                    raise (Stop (Wrong (s, arg, "an integer")))
f231f65
             end;
f231f65
-            incr current;
f231f65
-        | Set_int r when !current + 1 < l ->
f231f65
-            let arg = argv.(!current + 1) in
f231f65
+        | Set_int r ->
f231f65
+            let arg = get_arg () in
f231f65
             begin try r := (int_of_string arg)
f231f65
             with Failure "int_of_string" ->
f231f65
                    raise (Stop (Wrong (s, arg, "an integer")))
f231f65
             end;
f231f65
-            incr current;
f231f65
-        | Float f when !current + 1 < l ->
f231f65
-            let arg = argv.(!current + 1) in
f231f65
+        | Float f ->
f231f65
+            let arg = get_arg () in
f231f65
             begin try f (float_of_string arg);
f231f65
             with Failure "float_of_string" ->
f231f65
                    raise (Stop (Wrong (s, arg, "a float")))
f231f65
             end;
f231f65
-            incr current;
f231f65
-        | Set_float r when !current + 1 < l ->
f231f65
-            let arg = argv.(!current + 1) in
f231f65
+        | Set_float r ->
f231f65
+            let arg = get_arg () in
f231f65
             begin try r := (float_of_string arg);
f231f65
             with Failure "float_of_string" ->
f231f65
                    raise (Stop (Wrong (s, arg, "a float")))
f231f65
             end;
f231f65
-            incr current;
f231f65
         | Tuple specs ->
f231f65
             List.iter treat_action specs;
f231f65
         | Rest f ->
f231f65
             while !current < l - 1 do
f231f65
-              f argv.(!current + 1);
f231f65
-              incr current;
f231f65
-            done;
f231f65
-        | _ -> raise (Stop (Missing s))
f231f65
+              f (get_arg ());
f231f65
+            done
f231f65
         in
f231f65
         treat_action action
f231f65
       with Bad m -> stop (Message m);
f231f65
diff --git a/stdlib/arg.mli b/stdlib/arg.mli
f231f65
index 869d030..b8c6f11 100644
f231f65
--- a/stdlib/arg.mli
f231f65
+++ b/stdlib/arg.mli
f231f65
@@ -25,7 +25,8 @@
f231f65
     [Unit], [Set] and [Clear] keywords take no argument. A [Rest]
f231f65
     keyword takes the remaining of the command line as arguments.
f231f65
     Every other keyword takes the following word on the command line
f231f65
-    as argument.
f231f65
+    as argument.  For compatibility with GNU getopt_long, [keyword=arg]
f231f65
+    is also allowed.
f231f65
     Arguments not preceded by a keyword are called anonymous arguments.
f231f65
 
f231f65
    Examples ([cmd] is assumed to be the command name):
f231f65
-- 
efb2ca1
1.8.4.2
f231f65