|
rpm-build |
0f2925 |
(*
|
|
rpm-build |
0f2925 |
* optParse - Functions for parsing command line arguments.
|
|
rpm-build |
0f2925 |
* Copyright (C) 2004 Bardur Arantsson
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* Heavily influenced by the optparse.py module from the Python
|
|
rpm-build |
0f2925 |
* standard library, but with lots of adaptation to the 'Ocaml Way'
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* This library is free software; you can redistribute it and/or
|
|
rpm-build |
0f2925 |
* modify it under the terms of the GNU Lesser General Public
|
|
rpm-build |
0f2925 |
* License as published by the Free Software Foundation; either
|
|
rpm-build |
0f2925 |
* version 2.1 of the License, or (at your option) any later version,
|
|
rpm-build |
0f2925 |
* with the special exception on linking described in file LICENSE.
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* This library is distributed in the hope that it will be useful,
|
|
rpm-build |
0f2925 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
rpm-build |
0f2925 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
rpm-build |
0f2925 |
* Lesser General Public License for more details.
|
|
rpm-build |
0f2925 |
*
|
|
rpm-build |
0f2925 |
* You should have received a copy of the GNU Lesser General Public
|
|
rpm-build |
0f2925 |
* License along with this library; if not, write to the Free Software
|
|
rpm-build |
0f2925 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
rpm-build |
0f2925 |
*)
|
|
rpm-build |
0f2925 |
open Printf
|
|
rpm-build |
0f2925 |
open ExtString
|
|
rpm-build |
0f2925 |
open ExtList
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let terminal_width =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
int_of_string (Sys.getenv "COLUMNS") (* Might as well use it if it's there... *)
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
Failure _ -> 80
|
|
rpm-build |
0f2925 |
| Not_found -> 80
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
module GetOpt =
|
|
rpm-build |
0f2925 |
struct
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
type action = string -> string list -> unit
|
|
rpm-build |
0f2925 |
type long_opt = string * int * action
|
|
rpm-build |
0f2925 |
type short_opt = char * int * action
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
exception Error of (string * string)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let split1 haystack needle =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
let (h, x) = String.split haystack needle in h, [x]
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
Invalid_string -> haystack, []
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let find_opt format_name options s =
|
|
rpm-build |
0f2925 |
let rec loop l =
|
|
rpm-build |
0f2925 |
match l with
|
|
rpm-build |
0f2925 |
(x, y, z) :: t -> if x = s then x, y, z else loop t
|
|
rpm-build |
0f2925 |
| [] -> raise (Error (format_name s, "no such option"))
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
loop options
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let find_short_opt options = find_opt (fun c -> sprintf "-%c" c) options
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let find_long_opt options = find_opt (fun s -> "--" ^ s) options
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let parse other find_short_opt find_long_opt args =
|
|
rpm-build |
0f2925 |
let rec loop args =
|
|
rpm-build |
0f2925 |
let rec gather_args name n args =
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
List.split_nth n args
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
List.Invalid_index _ ->
|
|
rpm-build |
0f2925 |
raise (Error (name, "missing required arguments"))
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let gather_long_opt s args =
|
|
rpm-build |
0f2925 |
let (h, t) = split1 s "=" in
|
|
rpm-build |
0f2925 |
let (_, nargs, action) = find_long_opt (String.slice ~first:2 h) in
|
|
rpm-build |
0f2925 |
let (accum, args') = gather_args h (nargs - List.length t) args in
|
|
rpm-build |
0f2925 |
action h (t @ accum); args'
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let rec gather_short_opt_concat seen_args s k args =
|
|
rpm-build |
0f2925 |
if k < String.length s then
|
|
rpm-build |
0f2925 |
let ostr = sprintf "-%c" s.[k]
|
|
rpm-build |
0f2925 |
and (_, nargs, action) = find_short_opt s.[k] in
|
|
rpm-build |
0f2925 |
if nargs = 0 then
|
|
rpm-build |
0f2925 |
begin
|
|
rpm-build |
0f2925 |
action ostr [];
|
|
rpm-build |
0f2925 |
gather_short_opt_concat seen_args s (k + 1) args
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
else if not seen_args then
|
|
rpm-build |
0f2925 |
let (accum, args') = gather_args ostr nargs args in
|
|
rpm-build |
0f2925 |
action ostr accum; gather_short_opt_concat true s (k + 1) args'
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
raise
|
|
rpm-build |
0f2925 |
(Error
|
|
rpm-build |
0f2925 |
(sprintf "-%c" s.[k],
|
|
rpm-build |
0f2925 |
sprintf "option list '%s' already contains an option requiring an argument"
|
|
rpm-build |
0f2925 |
s))
|
|
rpm-build |
0f2925 |
else args
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let gather_short_opt s k args =
|
|
rpm-build |
0f2925 |
let ostr = sprintf "-%c" s.[k] in
|
|
rpm-build |
0f2925 |
let (_, nargs, action) = find_short_opt s.[k] in
|
|
rpm-build |
0f2925 |
if nargs = 0 then gather_short_opt_concat false s k args
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let (accum, args') =
|
|
rpm-build |
0f2925 |
let h = String.slice ~first:(k+1) s in
|
|
rpm-build |
0f2925 |
if String.length h = 0 then gather_args ostr nargs args
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
let (t, args'') = gather_args ostr (nargs - 1) args in
|
|
rpm-build |
0f2925 |
h :: t, args''
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
action ostr accum; args'
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
match args with
|
|
rpm-build |
0f2925 |
[] -> []
|
|
rpm-build |
0f2925 |
| arg :: args' ->
|
|
rpm-build |
0f2925 |
if arg = "--" then args'
|
|
rpm-build |
0f2925 |
else if String.starts_with arg "--" then
|
|
rpm-build |
0f2925 |
loop (gather_long_opt arg args')
|
|
rpm-build |
0f2925 |
else if arg = "-" then begin other arg; loop args' end
|
|
rpm-build |
0f2925 |
else if String.starts_with arg "-" then
|
|
rpm-build |
0f2925 |
loop (gather_short_opt arg 1 args')
|
|
rpm-build |
0f2925 |
else begin other arg; loop args' end
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let args' = loop args in List.iter other args'
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
module Opt =
|
|
rpm-build |
0f2925 |
struct
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
exception No_value
|
|
rpm-build |
0f2925 |
exception Option_error of string * string
|
|
rpm-build |
0f2925 |
exception Option_help
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
type 'a t = {
|
|
rpm-build |
0f2925 |
option_set : string -> string list -> unit;
|
|
rpm-build |
0f2925 |
option_set_value : 'a -> unit;
|
|
rpm-build |
0f2925 |
option_get : unit -> 'a option;
|
|
rpm-build |
0f2925 |
option_metavars : string list;
|
|
rpm-build |
0f2925 |
option_defhelp : string option
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let get opt =
|
|
rpm-build |
0f2925 |
match opt.option_get () with
|
|
rpm-build |
0f2925 |
Some x -> x
|
|
rpm-build |
0f2925 |
| None -> raise No_value
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let set opt v =
|
|
rpm-build |
0f2925 |
opt.option_set_value v
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let is_set opt = Option.is_some (opt.option_get ())
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let opt opt = opt.option_get ()
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let value_option metavar default coerce errfmt =
|
|
rpm-build |
0f2925 |
let data = ref default in
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
option_metavars = [metavar];
|
|
rpm-build |
0f2925 |
option_defhelp = None;
|
|
rpm-build |
0f2925 |
option_get = (fun _ -> !data);
|
|
rpm-build |
0f2925 |
option_set_value = (fun x -> data := Some x);
|
|
rpm-build |
0f2925 |
option_set =
|
|
rpm-build |
0f2925 |
(fun option args ->
|
|
rpm-build |
0f2925 |
let arg = List.hd args in
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
data := Some (coerce arg)
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
exn -> raise (Option_error (option, errfmt exn arg)))
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let callback_option metavar coerce errfmt f =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
option_metavars = [metavar];
|
|
rpm-build |
0f2925 |
option_defhelp = None;
|
|
rpm-build |
0f2925 |
option_get = (fun _ -> Some ());
|
|
rpm-build |
0f2925 |
option_set_value = (fun () -> ());
|
|
rpm-build |
0f2925 |
option_set =
|
|
rpm-build |
0f2925 |
(fun option args ->
|
|
rpm-build |
0f2925 |
let arg = List.hd args in
|
|
rpm-build |
0f2925 |
let datum = ref None in
|
|
rpm-build |
0f2925 |
begin
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
datum := Some (coerce arg)
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
exn -> raise (Option_error (option, errfmt exn arg))
|
|
rpm-build |
0f2925 |
end;
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
Option.may f !datum)
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
module StdOpt =
|
|
rpm-build |
0f2925 |
struct
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
open Opt
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let store_const ?default const =
|
|
rpm-build |
0f2925 |
let data = ref default in
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
option_metavars = [];
|
|
rpm-build |
0f2925 |
option_defhelp = None;
|
|
rpm-build |
0f2925 |
option_get = (fun _ -> !data);
|
|
rpm-build |
0f2925 |
option_set_value = (fun x -> data := Some x);
|
|
rpm-build |
0f2925 |
option_set = fun _ _ -> data := Some const
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let store_true () = store_const ~default:false true
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let store_false () = store_const ~default:true false
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let int_option ?default ?(metavar = "INT") () =
|
|
rpm-build |
0f2925 |
value_option metavar default int_of_string
|
|
rpm-build |
0f2925 |
(fun _ s -> sprintf "invalid integer value '%s'" s)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let int_callback ?(metavar = "INT") =
|
|
rpm-build |
0f2925 |
callback_option metavar int_of_string
|
|
rpm-build |
0f2925 |
(fun _ s -> sprintf "invalid integer value '%s'" s)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let float_option ?default ?(metavar = "FLOAT") () =
|
|
rpm-build |
0f2925 |
value_option metavar default float_of_string
|
|
rpm-build |
0f2925 |
(fun _ s -> sprintf "invalid floating point value '%s'" s)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let float_callback ?(metavar = "FLOAT") =
|
|
rpm-build |
0f2925 |
callback_option metavar float_of_string
|
|
rpm-build |
0f2925 |
(fun _ s -> sprintf "invalid floating point value '%s'" s)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let str_option ?default ?(metavar = "STR") () =
|
|
rpm-build |
0f2925 |
value_option metavar default (fun s -> s) (fun _ _ -> "cannot happen")
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let str_callback ?(metavar = "STR") =
|
|
rpm-build |
0f2925 |
callback_option metavar (fun s -> s) (fun _ _ -> "cannot happen")
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let count_option ?(dest = ref 0) ?(increment = 1) () =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
option_metavars = [];
|
|
rpm-build |
0f2925 |
option_defhelp = None;
|
|
rpm-build |
0f2925 |
option_get = (fun _ -> Some !dest);
|
|
rpm-build |
0f2925 |
option_set_value = (fun x -> dest := x);
|
|
rpm-build |
0f2925 |
option_set = fun _ _ -> dest := !dest + increment
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let incr_option ?(dest = ref 0) =
|
|
rpm-build |
0f2925 |
count_option ~dest ~increment:1
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let decr_option ?(dest = ref 0) =
|
|
rpm-build |
0f2925 |
count_option ~dest ~increment:(-1)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let help_option () =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
option_metavars = [];
|
|
rpm-build |
0f2925 |
option_defhelp = Some "show this help message and exit";
|
|
rpm-build |
0f2925 |
option_get = (fun _ -> raise No_value);
|
|
rpm-build |
0f2925 |
option_set_value = (fun _ -> ());
|
|
rpm-build |
0f2925 |
option_set = fun _ _ -> raise Option_help
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let version_option vfunc =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
option_metavars = [];
|
|
rpm-build |
0f2925 |
option_defhelp = Some "show program's version and exit";
|
|
rpm-build |
0f2925 |
option_get = (fun _ -> raise No_value);
|
|
rpm-build |
0f2925 |
option_set_value = (fun _ -> ());
|
|
rpm-build |
0f2925 |
option_set = fun _ _ -> print_endline (vfunc ()); exit 0
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
module Formatter =
|
|
rpm-build |
0f2925 |
struct
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
(* Note that the whitespace regexps must NOT treat the non-breaking
|
|
rpm-build |
0f2925 |
space character as whitespace. *)
|
|
rpm-build |
0f2925 |
let whitespace = "\t\n\013\014\r "
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let split_into_chunks s =
|
|
rpm-build |
0f2925 |
let buf = Buffer.create (String.length s) in
|
|
rpm-build |
0f2925 |
let flush () =
|
|
rpm-build |
0f2925 |
let s = Buffer.contents buf
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
Buffer.clear buf;
|
|
rpm-build |
0f2925 |
s
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let rec loop state accum i =
|
|
rpm-build |
0f2925 |
if (i
|
|
rpm-build |
0f2925 |
if ((state && not (String.contains whitespace s.[i])) ||
|
|
rpm-build |
0f2925 |
((not state) && String.contains whitespace s.[i])) then
|
|
rpm-build |
0f2925 |
if Buffer.length buf > 0 then
|
|
rpm-build |
0f2925 |
loop (not state) (flush () :: accum) i
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
loop (not state) accum i
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
begin
|
|
rpm-build |
0f2925 |
Buffer.add_char buf s.[i];
|
|
rpm-build |
0f2925 |
loop state accum (i+1)
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
if Buffer.length buf > 0 then
|
|
rpm-build |
0f2925 |
flush () :: accum
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
accum
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
List.rev (loop false [] 0)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let is_whitespace s =
|
|
rpm-build |
0f2925 |
let rec loop i =
|
|
rpm-build |
0f2925 |
if i
|
|
rpm-build |
0f2925 |
if String.contains whitespace s.[i] then
|
|
rpm-build |
0f2925 |
loop (i+1)
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
false
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
true
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
loop 0
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let expand_tabs ?(tab_size = 8) s =
|
|
rpm-build |
0f2925 |
let len = String.length s in
|
|
rpm-build |
0f2925 |
let spaces n = String.make n ' '
|
|
rpm-build |
0f2925 |
and b = Buffer.create len in
|
|
rpm-build |
0f2925 |
let rec expand i col =
|
|
rpm-build |
0f2925 |
if i < len then
|
|
rpm-build |
0f2925 |
match s.[i] with
|
|
rpm-build |
0f2925 |
'\t' ->
|
|
rpm-build |
0f2925 |
let n = tab_size - col mod tab_size in
|
|
rpm-build |
0f2925 |
Buffer.add_string b (spaces n);
|
|
rpm-build |
0f2925 |
expand (i + 1) (col + n)
|
|
rpm-build |
0f2925 |
| '\n' ->
|
|
rpm-build |
0f2925 |
Buffer.add_string b "\n";
|
|
rpm-build |
0f2925 |
expand (i + 1) 0
|
|
rpm-build |
0f2925 |
| c ->
|
|
rpm-build |
0f2925 |
Buffer.add_char b c;
|
|
rpm-build |
0f2925 |
expand (i + 1) (col + 1)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
expand 0 0;
|
|
rpm-build |
0f2925 |
Buffer.contents b
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let wrap ?(initial_indent = 0) ?(subsequent_indent = 0) text _width =
|
|
rpm-build |
0f2925 |
let wrap_chunks_line width acc =
|
|
rpm-build |
0f2925 |
let rec wrap (chunks, cur_line, cur_len) =
|
|
rpm-build |
0f2925 |
match chunks with
|
|
rpm-build |
0f2925 |
[] -> [], cur_line, cur_len
|
|
rpm-build |
0f2925 |
| hd :: tl ->
|
|
rpm-build |
0f2925 |
let l = String.length hd in
|
|
rpm-build |
0f2925 |
if cur_len + l <= width then
|
|
rpm-build |
0f2925 |
wrap (tl, hd :: cur_line, cur_len + l)
|
|
rpm-build |
0f2925 |
else chunks, cur_line, cur_len
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
wrap acc
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let wrap_long_last_word width (chunks, cur_line, cur_len) =
|
|
rpm-build |
0f2925 |
match chunks with
|
|
rpm-build |
0f2925 |
[] -> [], cur_line, cur_len
|
|
rpm-build |
0f2925 |
| hd :: tl ->
|
|
rpm-build |
0f2925 |
let l = String.length hd in
|
|
rpm-build |
0f2925 |
if l > width then
|
|
rpm-build |
0f2925 |
match cur_line with
|
|
rpm-build |
0f2925 |
[] -> tl, [hd], cur_len + l
|
|
rpm-build |
0f2925 |
| _ -> chunks, cur_line, cur_len
|
|
rpm-build |
0f2925 |
else chunks, cur_line, cur_len
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let wrap_remove_last_ws (chunks, cur_line, cur_len) =
|
|
rpm-build |
0f2925 |
match cur_line with
|
|
rpm-build |
0f2925 |
[] -> chunks, cur_line, cur_len
|
|
rpm-build |
0f2925 |
| hd :: tl ->
|
|
rpm-build |
0f2925 |
if is_whitespace hd then chunks, tl, cur_len - String.length hd
|
|
rpm-build |
0f2925 |
else chunks, cur_line, cur_len
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let rec wrap_chunks_lines chunks lines =
|
|
rpm-build |
0f2925 |
let indent =
|
|
rpm-build |
0f2925 |
match lines with
|
|
rpm-build |
0f2925 |
[] -> initial_indent
|
|
rpm-build |
0f2925 |
| _ -> subsequent_indent
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let width = _width - indent in
|
|
rpm-build |
0f2925 |
match chunks with
|
|
rpm-build |
0f2925 |
hd :: tl ->
|
|
rpm-build |
0f2925 |
if is_whitespace hd && lines <> [] then wrap_chunks_lines tl lines
|
|
rpm-build |
0f2925 |
else (* skip *)
|
|
rpm-build |
0f2925 |
let (chunks', cur_line, _) =
|
|
rpm-build |
0f2925 |
wrap_remove_last_ws
|
|
rpm-build |
0f2925 |
(wrap_long_last_word width
|
|
rpm-build |
0f2925 |
(wrap_chunks_line width (chunks, [], 0)))
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
wrap_chunks_lines chunks'
|
|
rpm-build |
0f2925 |
((String.make indent ' ' ^
|
|
rpm-build |
0f2925 |
String.concat "" (List.rev cur_line)) ::
|
|
rpm-build |
0f2925 |
lines)
|
|
rpm-build |
0f2925 |
| [] -> List.rev lines
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let chunks = split_into_chunks (expand_tabs text) in
|
|
rpm-build |
0f2925 |
wrap_chunks_lines chunks []
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let fill ?(initial_indent = 0) ?(subsequent_indent = 0) text width =
|
|
rpm-build |
0f2925 |
String.concat "\n" (wrap ~initial_indent ~subsequent_indent text width)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
type t = {
|
|
rpm-build |
0f2925 |
indent : unit -> unit;
|
|
rpm-build |
0f2925 |
dedent : unit -> unit;
|
|
rpm-build |
0f2925 |
format_usage : string -> string;
|
|
rpm-build |
0f2925 |
format_heading : string -> string;
|
|
rpm-build |
0f2925 |
format_description : string -> string;
|
|
rpm-build |
0f2925 |
format_option : char list * string list -> string list ->
|
|
rpm-build |
0f2925 |
string option -> string
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let format_option_strings short_first (snames, lnames) metavars =
|
|
rpm-build |
0f2925 |
let metavar = String.concat " " metavars in
|
|
rpm-build |
0f2925 |
let lopts =
|
|
rpm-build |
0f2925 |
List.map
|
|
rpm-build |
0f2925 |
(match metavar with
|
|
rpm-build |
0f2925 |
"" -> (fun z -> sprintf "--%s" z)
|
|
rpm-build |
0f2925 |
| _ -> fun z -> sprintf "--%s=%s" z metavar)
|
|
rpm-build |
0f2925 |
lnames
|
|
rpm-build |
0f2925 |
and sopts = List.map (fun x -> sprintf "-%c%s" x metavar) snames in
|
|
rpm-build |
0f2925 |
match short_first with
|
|
rpm-build |
0f2925 |
true -> String.concat ", " (sopts @ lopts)
|
|
rpm-build |
0f2925 |
| false -> String.concat ", " (lopts @ sopts)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let indented_formatter ?level:(extlevel = ref 0)
|
|
rpm-build |
0f2925 |
?indent:(extindent = ref 0) ?(indent_increment = 2)
|
|
rpm-build |
0f2925 |
?(max_help_position = 24) ?(width = terminal_width - 1)
|
|
rpm-build |
0f2925 |
?(short_first = true) () =
|
|
rpm-build |
0f2925 |
let indent = ref 0
|
|
rpm-build |
0f2925 |
and level = ref 0 in
|
|
rpm-build |
0f2925 |
let help_position = ref max_help_position
|
|
rpm-build |
0f2925 |
and help_width = ref (width - max_help_position) in
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
indent =
|
|
rpm-build |
0f2925 |
(fun () ->
|
|
rpm-build |
0f2925 |
indent := !indent + indent_increment;
|
|
rpm-build |
0f2925 |
level := !level + 1;
|
|
rpm-build |
0f2925 |
extindent := !indent;
|
|
rpm-build |
0f2925 |
extlevel := !level);
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
dedent =
|
|
rpm-build |
0f2925 |
(fun () ->
|
|
rpm-build |
0f2925 |
indent := !indent - indent_increment;
|
|
rpm-build |
0f2925 |
level := !level - 1;
|
|
rpm-build |
0f2925 |
assert (!level >= 0);
|
|
rpm-build |
0f2925 |
extindent := !indent;
|
|
rpm-build |
0f2925 |
extlevel := !level);
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
format_usage = (fun usage -> sprintf "usage: %s\n" usage);
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
format_heading =
|
|
rpm-build |
0f2925 |
(fun heading -> sprintf "%*s%s:\n\n" !indent "" heading);
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
format_description =
|
|
rpm-build |
0f2925 |
(fun description ->
|
|
rpm-build |
0f2925 |
let x =
|
|
rpm-build |
0f2925 |
fill ~initial_indent:(!indent) ~subsequent_indent:(!indent)
|
|
rpm-build |
0f2925 |
description (width - !indent)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
if not (String.ends_with x "\n") then x ^ "\n\n" else x ^ "\n");
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
format_option =
|
|
rpm-build |
0f2925 |
fun names metavars help ->
|
|
rpm-build |
0f2925 |
let opt_width = !help_position - !indent - 2 in
|
|
rpm-build |
0f2925 |
let opt_strings =
|
|
rpm-build |
0f2925 |
format_option_strings short_first names metavars
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let buf = Buffer.create 256 in
|
|
rpm-build |
0f2925 |
let indent_first =
|
|
rpm-build |
0f2925 |
if String.length opt_strings > opt_width then
|
|
rpm-build |
0f2925 |
begin
|
|
rpm-build |
0f2925 |
bprintf buf "%*s%s\n" !indent "" opt_strings; !help_position
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
begin
|
|
rpm-build |
0f2925 |
bprintf buf "%*s%-*s " !indent "" opt_width opt_strings; 0
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
Option.may
|
|
rpm-build |
0f2925 |
(fun option_help ->
|
|
rpm-build |
0f2925 |
let lines = wrap option_help !help_width in
|
|
rpm-build |
0f2925 |
match lines with
|
|
rpm-build |
0f2925 |
h :: t ->
|
|
rpm-build |
0f2925 |
bprintf buf "%*s%s\n" indent_first "" h;
|
|
rpm-build |
0f2925 |
List.iter
|
|
rpm-build |
0f2925 |
(fun x -> bprintf buf "%*s%s\n" !help_position "" x) t
|
|
rpm-build |
0f2925 |
| [] -> ())
|
|
rpm-build |
0f2925 |
help;
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let contents =
|
|
rpm-build |
0f2925 |
Buffer.contents buf
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
if String.length contents > 0 && not (String.ends_with contents "\n") then
|
|
rpm-build |
0f2925 |
contents ^ "\n"
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
contents
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let titled_formatter ?(level = ref 0) ?(indent = ref 0)
|
|
rpm-build |
0f2925 |
?(indent_increment = 0) ?(max_help_position = 24)
|
|
rpm-build |
0f2925 |
?(width = terminal_width - 1) ?(short_first = true)
|
|
rpm-build |
0f2925 |
() =
|
|
rpm-build |
0f2925 |
let formatter =
|
|
rpm-build |
0f2925 |
indented_formatter ~level ~indent ~indent_increment ~max_help_position
|
|
rpm-build |
0f2925 |
~width ~short_first ()
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let format_heading h =
|
|
rpm-build |
0f2925 |
let c =
|
|
rpm-build |
0f2925 |
match !level with
|
|
rpm-build |
0f2925 |
0 -> '='
|
|
rpm-build |
0f2925 |
| 1 -> '-'
|
|
rpm-build |
0f2925 |
| _ -> failwith "titled_formatter: Too much indentation"
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
sprintf "%*s%s\n%*s%s\n\n" !indent "" (String.capitalize h) !indent ""
|
|
rpm-build |
0f2925 |
(String.make (String.length h) c)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let format_usage usage =
|
|
rpm-build |
0f2925 |
sprintf "%s %s\n" (format_heading "Usage") usage
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
{ formatter with
|
|
rpm-build |
0f2925 |
format_usage = format_usage;
|
|
rpm-build |
0f2925 |
format_heading = format_heading
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
end
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
open Opt
|
|
rpm-build |
0f2925 |
open Formatter
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
module OptParser =
|
|
rpm-build |
0f2925 |
struct
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
exception Option_conflict of string
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
type group = {
|
|
rpm-build |
0f2925 |
og_heading : string;
|
|
rpm-build |
0f2925 |
og_description : string option;
|
|
rpm-build |
0f2925 |
og_options :
|
|
rpm-build |
0f2925 |
((char list * string list) * string list * string option) RefList.t;
|
|
rpm-build |
0f2925 |
og_children : group RefList.t
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
type t = {
|
|
rpm-build |
0f2925 |
op_usage : string;
|
|
rpm-build |
0f2925 |
op_status : int;
|
|
rpm-build |
0f2925 |
op_suppress_usage : bool;
|
|
rpm-build |
0f2925 |
op_prog : string;
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
op_formatter : Formatter.t;
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
op_long_options : GetOpt.long_opt RefList.t;
|
|
rpm-build |
0f2925 |
op_short_options : GetOpt.short_opt RefList.t;
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
op_groups : group
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let unprogify optparser s =
|
|
rpm-build |
0f2925 |
(snd (String.replace ~str:s ~sub:"%prog" ~by:optparser.op_prog))
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let add optparser ?(group = optparser.op_groups) ?help ?(hide = false)
|
|
rpm-build |
0f2925 |
?short_name ?(short_names = []) ?long_name ?(long_names = []) opt =
|
|
rpm-build |
0f2925 |
let lnames =
|
|
rpm-build |
0f2925 |
match long_name with
|
|
rpm-build |
0f2925 |
None -> long_names
|
|
rpm-build |
0f2925 |
| Some x -> x :: long_names
|
|
rpm-build |
0f2925 |
and snames =
|
|
rpm-build |
0f2925 |
match short_name with
|
|
rpm-build |
0f2925 |
None -> short_names
|
|
rpm-build |
0f2925 |
| Some x -> x :: short_names
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
if lnames = [] && snames = [] then
|
|
rpm-build |
0f2925 |
failwith "Options must have at least one name"
|
|
rpm-build |
0f2925 |
else
|
|
rpm-build |
0f2925 |
(* Checking for duplicates: *)
|
|
rpm-build |
0f2925 |
let snames' =
|
|
rpm-build |
0f2925 |
List.fold_left (fun r (x, _, _) -> x :: r) []
|
|
rpm-build |
0f2925 |
(RefList.to_list optparser.op_short_options)
|
|
rpm-build |
0f2925 |
and lnames' =
|
|
rpm-build |
0f2925 |
List.fold_left (fun r (x, _, _) -> x :: r) []
|
|
rpm-build |
0f2925 |
(RefList.to_list optparser.op_long_options)
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
let sconf =
|
|
rpm-build |
0f2925 |
List.filter (fun e -> List.exists (( = ) e) snames') snames
|
|
rpm-build |
0f2925 |
and lconf =
|
|
rpm-build |
0f2925 |
List.filter (fun e -> List.exists (( = ) e) lnames') lnames
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
if List.length sconf > 0 then
|
|
rpm-build |
0f2925 |
raise (Option_conflict (sprintf "-%c" (List.hd sconf)))
|
|
rpm-build |
0f2925 |
else if List.length lconf > 0 then
|
|
rpm-build |
0f2925 |
raise (Option_conflict (sprintf "--%s" (List.hd lconf)));
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
(* Add to display list. *)
|
|
rpm-build |
0f2925 |
if not hide then
|
|
rpm-build |
0f2925 |
RefList.add group.og_options
|
|
rpm-build |
0f2925 |
((snames, lnames), opt.option_metavars,
|
|
rpm-build |
0f2925 |
(match help with
|
|
rpm-build |
0f2925 |
None -> opt.option_defhelp
|
|
rpm-build |
0f2925 |
| Some _ -> help));
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
(* Getopt: *)
|
|
rpm-build |
0f2925 |
let nargs = List.length opt.option_metavars in
|
|
rpm-build |
0f2925 |
List.iter
|
|
rpm-build |
0f2925 |
(fun short ->
|
|
rpm-build |
0f2925 |
RefList.add optparser.op_short_options
|
|
rpm-build |
0f2925 |
(short, nargs, opt.option_set))
|
|
rpm-build |
0f2925 |
snames;
|
|
rpm-build |
0f2925 |
List.iter
|
|
rpm-build |
0f2925 |
(fun long ->
|
|
rpm-build |
0f2925 |
RefList.add optparser.op_long_options
|
|
rpm-build |
0f2925 |
(long, nargs, opt.option_set))
|
|
rpm-build |
0f2925 |
lnames
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let add_group optparser ?(parent = optparser.op_groups) ?description heading =
|
|
rpm-build |
0f2925 |
let g =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
og_heading = heading;
|
|
rpm-build |
0f2925 |
og_description = description;
|
|
rpm-build |
0f2925 |
og_options = RefList.empty ();
|
|
rpm-build |
0f2925 |
og_children = RefList.empty ()
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
RefList.add parent.og_children g; g
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let make ?(usage = "%prog [options]") ?(status = 1) ?description ?version
|
|
rpm-build |
0f2925 |
?(suppress_usage = false) ?(suppress_help = false) ?prog
|
|
rpm-build |
0f2925 |
?(formatter = Formatter.indented_formatter ()) () =
|
|
rpm-build |
0f2925 |
let optparser =
|
|
rpm-build |
0f2925 |
{
|
|
rpm-build |
0f2925 |
op_usage = usage;
|
|
rpm-build |
0f2925 |
op_status = status;
|
|
rpm-build |
0f2925 |
op_suppress_usage = suppress_usage;
|
|
rpm-build |
0f2925 |
op_prog = Option.default (Filename.basename Sys.argv.(0)) prog;
|
|
rpm-build |
0f2925 |
op_formatter = formatter;
|
|
rpm-build |
0f2925 |
op_short_options = RefList.empty ();
|
|
rpm-build |
0f2925 |
op_long_options = RefList.empty ();
|
|
rpm-build |
0f2925 |
op_groups = {
|
|
rpm-build |
0f2925 |
og_heading = "options";
|
|
rpm-build |
0f2925 |
og_options = RefList.empty ();
|
|
rpm-build |
0f2925 |
og_children = RefList.empty ();
|
|
rpm-build |
0f2925 |
og_description = description
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
}
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
Option.may (* Add version option? *)
|
|
rpm-build |
0f2925 |
(fun version ->
|
|
rpm-build |
0f2925 |
add optparser ~long_name:"version"
|
|
rpm-build |
0f2925 |
(StdOpt.version_option
|
|
rpm-build |
0f2925 |
(fun () -> unprogify optparser version)))
|
|
rpm-build |
0f2925 |
version;
|
|
rpm-build |
0f2925 |
if not suppress_help then (* Add help option? *)
|
|
rpm-build |
0f2925 |
add optparser ~short_name:'h' ~long_name:"help"
|
|
rpm-build |
0f2925 |
(StdOpt.help_option ());
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
optparser
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let format_usage optparser eol =
|
|
rpm-build |
0f2925 |
match optparser.op_suppress_usage with
|
|
rpm-build |
0f2925 |
true -> ""
|
|
rpm-build |
0f2925 |
| false ->
|
|
rpm-build |
0f2925 |
unprogify optparser
|
|
rpm-build |
0f2925 |
(optparser.op_formatter.format_usage optparser.op_usage) ^ eol
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let error optparser ?(chn = stderr) ?status message =
|
|
rpm-build |
0f2925 |
fprintf chn "%s%s: %s\n" (format_usage optparser "\n") optparser.op_prog
|
|
rpm-build |
0f2925 |
message;
|
|
rpm-build |
0f2925 |
flush chn;
|
|
rpm-build |
0f2925 |
exit (Option.default optparser.op_status status)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let usage optparser ?(chn = stdout) () =
|
|
rpm-build |
0f2925 |
let rec loop g =
|
|
rpm-build |
0f2925 |
(* Heading: *)
|
|
rpm-build |
0f2925 |
output_string chn
|
|
rpm-build |
0f2925 |
(optparser.op_formatter.format_heading g.og_heading);
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
optparser.op_formatter.indent ();
|
|
rpm-build |
0f2925 |
(* Description: *)
|
|
rpm-build |
0f2925 |
Option.may
|
|
rpm-build |
0f2925 |
(fun x ->
|
|
rpm-build |
0f2925 |
output_string chn (optparser.op_formatter.format_description x))
|
|
rpm-build |
0f2925 |
g.og_description;
|
|
rpm-build |
0f2925 |
(* Options: *)
|
|
rpm-build |
0f2925 |
RefList.iter
|
|
rpm-build |
0f2925 |
(fun (names, metavars, help) ->
|
|
rpm-build |
0f2925 |
output_string chn
|
|
rpm-build |
0f2925 |
(optparser.op_formatter.format_option names metavars help))
|
|
rpm-build |
0f2925 |
g.og_options;
|
|
rpm-build |
0f2925 |
(* Child groups: *)
|
|
rpm-build |
0f2925 |
output_string chn "\n";
|
|
rpm-build |
0f2925 |
RefList.iter loop g.og_children;
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
optparser.op_formatter.dedent ()
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
output_string chn (format_usage optparser "\n");
|
|
rpm-build |
0f2925 |
loop optparser.op_groups;
|
|
rpm-build |
0f2925 |
flush chn
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let parse optparser ?(first = 0) ?last argv =
|
|
rpm-build |
0f2925 |
let args = RefList.empty ()
|
|
rpm-build |
0f2925 |
and n =
|
|
rpm-build |
0f2925 |
match last with
|
|
rpm-build |
0f2925 |
None -> Array.length argv - first
|
|
rpm-build |
0f2925 |
| Some m -> m - first + 1
|
|
rpm-build |
0f2925 |
in
|
|
rpm-build |
0f2925 |
begin
|
|
rpm-build |
0f2925 |
try
|
|
rpm-build |
0f2925 |
GetOpt.parse (RefList.push args)
|
|
rpm-build |
0f2925 |
(GetOpt.find_short_opt
|
|
rpm-build |
0f2925 |
(RefList.to_list optparser.op_short_options))
|
|
rpm-build |
0f2925 |
(GetOpt.find_long_opt (RefList.to_list optparser.op_long_options))
|
|
rpm-build |
0f2925 |
(Array.to_list (Array.sub argv first n))
|
|
rpm-build |
0f2925 |
with
|
|
rpm-build |
0f2925 |
GetOpt.Error (opt, errmsg) ->
|
|
rpm-build |
0f2925 |
error optparser (sprintf "option '%s': %s" opt errmsg)
|
|
rpm-build |
0f2925 |
| Option_error (opt, errmsg) ->
|
|
rpm-build |
0f2925 |
error optparser (sprintf "option '%s': %s" opt errmsg)
|
|
rpm-build |
0f2925 |
| Option_help -> usage optparser (); exit 0
|
|
rpm-build |
0f2925 |
end;
|
|
rpm-build |
0f2925 |
List.rev (RefList.to_list args)
|
|
rpm-build |
0f2925 |
|
|
rpm-build |
0f2925 |
let parse_argv optparser =
|
|
rpm-build |
0f2925 |
parse optparser ~first:1 Sys.argv
|
|
rpm-build |
0f2925 |
end
|