blob: e4f3215cc3562bef390d5e3fc3e65dd4d0563e60 [file]
module Argp =
def mode ArgOpt = struct (char name, string long_name,
bool arg_required, proc(string)bool handler);
proc argp = (int p, [][]ArgOpt opts,
proc(int,string)bool no_opt_handler,
proc(string)void error_handler) void:
begin
proc getopt = (string prefix, string arg) ArgOpt:
begin ArgOpt res, bool found := false;
for i to UPB opts while NOT found
do for j to UPB opts[i] while NOT found
do if arg = long_name of opts[i][j]
OR (arg /= " " AND arg = name of opts[i][j])
then res := opts[i][j]; found := true
fi
od
od;
(NOT found | error_handler ("unknown option " + prefix + arg));
res
end;
bool found_dash_dash := false,
skip_next_opt := false,
continue := true;
for i from p to argc while continue
do string arg = argv (i);
if skip_next_opt
then skip_next_opt := false
elif arg = "--" AND NOT found_dash_dash
then found_dash_dash := true
elif found_dash_dash OR (UPB arg >= 1 andth arg[1] /= "-")
then continue := no_opt_handler (i + 1, arg)
elif UPB arg > 1 andth arg[2] = "-"
then { Long option. It may have an argument. }
int eqidx = char_in_string (arg, "=");
string optname = (eqidx > 0 | arg[3:eqidx - 1] | arg[3:]),
optarg = (eqidx > 0 AND UPB arg >= (eqidx + 1) | arg[eqidx + 1:]);
ArgOpt opt = getopt ("--", optname);
if (arg_required of opt) AND optarg = ""
then error_handler ("option --" + arg + " requires an argument") fi;
continue := (handler of opt) (optarg)
else { This is one or more short options. }
for j to UPB arg[2:]
do ArgOpt opt = getopt ("-", arg[j + 1]);
if arg_required of opt
then if i = argc orel (ELEMS argv (i + 1) > 1 andth argv (i + 1)[1] = "-")
then error_handler ("option -" + arg[2+j] + " requires an argument")
fi;
(handler of opt) (argv (i + 1));
skip_next_opt := true
else continue := (handler of opt) ("")
fi
od
fi
od
end;
proc char_in_string = (string s, char c) int:
begin int res := 0, bool found := false;
for i to UPB s while NOT found
do (s[i] = c | res := i; found := true) od;
res
end;
skip
fed