#line 71 "/home/ubuntu/felix/src/packages/program.fdoc"
open class CmdOpt
{
noinline fun cvt-key-arg (keys: list[string * string]) (x:list[string]) =
{
var out = Empty[string];
var inp = x.iterator;
for word in inp do
match keys.find word with
| #None => out = Cons (word,out);
| Some prefix =>
match inp() with
| #None => println$ "Error, expected argument to option " + word;
| Some arg => out = Cons (prefix+"=" + arg, out);
endmatch;
endmatch;
done
return rev out;
}
var rekv = RE2 "(--.*)=(.*)";
noinline gen parse-key-multi-value (keys:list[string]) (d:strdict[list[string]]) (x:list[string]) =
{
var out = Empty[string];
var va = varray[StringPiece] (StringPiece "", StringPiece "", StringPiece "");
for opt in x do
if Match (rekv, StringPiece (opt), 0,ANCHOR_BOTH, va.stl_begin, va.len.int) do
var key = va . 1 . string;
if key in keys do
val value= va . 2 . string ;
val nuval = Cons (value, d.get_dflt (key,Empty[string]));
d.add key nuval;
else
out = Cons (opt, out);
done
else
out = Cons (opt, out);
done
done
return rev out;
}
noinline gen parse-key-single-value (keys:list[string]) (d:strdict[string]) (x:list[string]) =
{
var out = Empty[string];
var va = varray[StringPiece] (StringPiece "", StringPiece "", StringPiece "");
for opt in x do
if Match (rekv, StringPiece (opt), 0,ANCHOR_BOTH, va.stl_begin, va.len.int) do
var key = va . 1 . string;
if key in keys do
val value= va . 2 . string ;
match d.get key with
| #None => d.add key value;
| _ => println$ "Duplicate option '" + opt +"'";
endmatch;
else
println$ "Invalid option '" + opt+"'";
done
else
out = Cons (opt, out);
done
done
return rev out;
}
var rek = RE2 "(--.*)";
noinline gen parse-key (keys:list[string]) (d:strdict[int]) (x:list[string]) =
{
var out = Empty[string];
var va = varray[StringPiece] (StringPiece "", StringPiece "");
for opt in x do
if Match (rek, StringPiece (opt), 0,ANCHOR_BOTH, va.stl_begin, va.len.int) do
var key = va . 1 . string;
if key in keys do
val nuval =d.get_dflt (key,0) + 1;
d.add key nuval;
else
println$ "Invalid option '" + opt+"'";
done
else
out = Cons (opt, out);
done
done
return rev out;
}
var resw = RE2 "(-.*)";
noinline gen parse-switches (switchmap: list[char * string] ) (d:strdict[int]) (x:list[string]) =
{
var out = Empty[string];
var va = varray[StringPiece] (StringPiece "", StringPiece "");
for opt in x do
if Match (resw, StringPiece (opt), 0,ANCHOR_BOTH, va.stl_begin, va.len.int) do
var switches = va . 1 . string . [1 to];
for switch in switches do
match switchmap.find switch with
| #None =>
println$ "Invalid option " + opt + " char '" + str switch+"'";
| Some key=>
val nuval = d.get_dflt (key,0) + 1;
d.add key nuval;
endmatch;
done
else
out = Cons (opt, out);
done
done
return rev out;
}
typedef cmdspec_t = (
split-key-value-spec: list[string * string],
multi-valued-keys-spec: list[string],
single-valued-keys-spec: list[string],
switches-spec: list[string],
short-switch-map-spec: list[char * string]
);
typedef cmdopt-parse-result_t = (
multi-valued-keys : strdict[list[string]],
single-valued-keys : strdict[string],
switches : strdict[int],
positional : list[string]
);
ctor cmdopt-parse-result_t () =>
(
multi-valued-keys = strdict[list[string]](),
single-valued-keys = strdict[string](),
switches = strdict[int](),
positional = Empty[string]
);
noinline gen parse-cmdline (spec:cmdspec_t) (x:list[string]) : cmdopt-parse-result_t = {
var result = cmdopt-parse-result_t ();
var nonk = cvt-key-arg spec.split-key-value-spec x;
nonk = parse-key-multi-value spec.multi-valued-keys-spec result.multi-valued-keys nonk;
nonk = parse-key-single-value spec.single-valued-keys-spec result.single-valued-keys nonk;
nonk = parse-key spec.switches-spec result.switches nonk;
&result.positional <- parse-switches spec.short-switch-map-spec result.switches nonk;
return result;
}
}