ref: f59920b9d0a977ddb735bf792c11ac44da46d93c
parent: 18386e4095db52452505a6855117ca80a349be60
author: Ori Bernstein <[email protected]>
date: Thu Apr 30 16:05:56 EDT 2015
Rework the option parsing api a bit.
--- a/libstd/optparse.myr
+++ b/libstd/optparse.myr
@@ -10,12 +10,24 @@
use "utf.use"
pkg std =
+ type optdef = struct
+ argdesc : byte[:]
+ opts : optdesc[:]
+ ;;
+
+ type optdesc = struct
+ opt : char
+ arg : byte[:]
+ desc : byte[:]
+ needed : bool
+ ;;
+
type optctx = struct
/* public variables */
args : byte[:][:]
/* data passed in */
- optstr : byte[:]
+ optdef : optdef#
optargs : byte[:][:]
/* state */
@@ -25,18 +37,19 @@
curarg : byte[:]
;;
- const optinit : (optstr: byte[:], optargs : byte[:][:] -> optctx#)
+ const optinit : (optargs : byte[:][:], def : optdef# -> optctx#)
const optnext : (ctx : optctx# -> (char, byte[:]))
const optdone : (ctx : optctx# -> bool)
const optfin : (ctx : optctx# -> byte[:][:])
+ const optusage : (ctx : optctx# -> void)
;;
-const optinit = {optstr, optargs
+const optinit = {args, def
var ctx
ctx = alloc()
- ctx.optstr= optstr
- ctx.optargs =optargs
+ ctx.optargs = args
+ ctx.optdef = def
ctx.optdone = false
ctx.finished = false
@@ -65,7 +78,12 @@
match optinfo(ctx, c)
| `None:
- fatal(1, "Unexpected argument '%c'\n", c)
+ if c == 'h' || c == '?'
+ optusage(ctx)
+ exit(0)
+ else
+ fatal(1, "unexpected argument '%c'\n", c)
+ ;;
| `Some (true, needed):
/* -arg => '-a' 'rg' */
if ctx.curarg.len > 0
@@ -96,25 +114,10 @@
-> ctx.curarg.len == 0 && ctx.finished
}
-const optinfo = {ctx, arg
- var s
- var c
-
- s = ctx.optstr
- while s.len != 0
- (c, s) = striter(s)
- if c == arg
- (c, s) = striter(s)
- /* mandatory arg */
- if c == ':'
- -> `Some (true, true)
- /* optional arg */
- elif c == '?'
- -> `Some (true, false)
- /* no arg */
- else
- -> `Some (false, false)
- ;;
+const optinfo = {ctx, opt
+ for o in ctx.optdef.opts
+ if o.opt == opt
+ -> `Some (o.arg.len != 0, o.needed)
;;
;;
-> `None
@@ -136,4 +139,25 @@
ctx.argidx = i
ctx.curarg = ctx.optargs[i][1:]
-> true
+}
+
+const optusage = {ctx
+ std.put("usage: %s [-h?]", ctx.optargs[0])
+ for o in ctx.optdef.opts
+ std.put("[-%c%s%s] ", o.opt, sep(o.arg), o.arg)
+ ;;
+ std.put("%s\n", ctx.optdef.argdesc)
+ std.put("\t-h\tprint this help message\n")
+ std.put("\t-?\tprint this help message\n")
+ for o in ctx.optdef.opts
+ std.put("\t%c%s%s\t%s\n", o.opt, sep(o.arg), o.arg, o.desc)
+ ;;
+}
+
+const sep = {s
+ if s.len > 0
+ -> " "
+ else
+ -> ""
+ ;;
}
--- a/mbld/main.myr
+++ b/mbld/main.myr
@@ -19,8 +19,20 @@
var bintarg
var optctx
var libpath
+ var opts
- optctx = std.optinit("hb:l:s:Sr:I:C:A:M:L:R:d", args)
+ opts = [
+ .argdesc = "[inputs...]",
+ .opts = [
+ [.opt= 'I', .arg="inc", .desc="add 'inc' to your include path"],
+ [.opt= 'R', .arg="root", .desc="install into 'root'"],
+ [.opt= 'b', .arg="bin", .desc="compile binary named 'bin' from inputs"],
+ [.opt= 'l', .arg="lib", .desc="compile lib named 'lib' from inputs"],
+ [.opt= 'r', .arg="rt", .desc="link against runtime 'rt' instead of default"],
+ [.opt= 'S', .desc = "generate assembly when building"],
+ ][:]
+ ]
+ optctx = std.optinit(args, &opts)
bld.initopts()
while !std.optdone(optctx)
match std.optnext(optctx)
@@ -47,7 +59,8 @@
| ('d', arg): bld.opt_debug = true
| ('C', arg): bld.opt_mc = arg
| ('M', arg): bld.opt_muse = arg
- | _: std.die("got invalid arg\n")
+ | _: std.optusage(optctx)
+
;;
;;
if bld.opt_instroot.len > 0 && !std.sleq(bld.opt_instroot, "none")
--- a/mbldwrap.sh
+++ b/mbldwrap.sh
@@ -6,7 +6,7 @@
# this should be a bourne compatible shell script.
if test -f mbld/mbld; then
- ./mbld/mbld $@
+ mbld $@
else
./bootstrap.sh
fi