ref: 4a2263e9daa8ce34bfb9796b36f23c15d060e306
parent: bd76a980365606972001adb6d974d94834dd0093
author: Ori Bernstein <[email protected]>
date: Fri May 1 18:06:57 EDT 2015
More improvements in CLI option parsing.
--- a/libstd/optparse.myr
+++ b/libstd/optparse.myr
@@ -12,8 +12,9 @@
pkg std =
type optdef = struct
- argdesc : byte[:]
- opts : optdesc[:]
+ argdesc : byte[:] /* the description for the usage */
+ minargs : std.size /* the minimum number of positional args */
+ opts : optdesc[:] /* the description of the options */
;;
type optdesc = struct
@@ -23,32 +24,50 @@
needed : bool
;;
- type optctx = struct
- /* public variables */
+ type optparsed = struct
+ opts : (char, byte[:])[:]
args : byte[:][:]
+ ;;
- /* data passed in */
- optdef : optdef#
- optargs : byte[:][:]
+ const optparse : (optargs : byte[:][:], def : optdef# -> optparsed)
+;;
- /* state */
- optdone : bool /* if we've seen '--', everything's an arg */
- finished : bool /* if we've processed all the optargs */
- argidx : size
- curarg : byte[:]
- ;;
+type optctx = struct
+ /* public variables */
+ args : byte[:][:]
- 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)
+ /* data passed in */
+ optdef : optdef#
+ optargs : byte[:][:]
+
+ /* state */
+ optdone : bool /* if we've seen '--', everything's an arg */
+ finished : bool /* if we've processed all the optargs */
+ argidx : size
+ curarg : byte[:]
;;
-const optinit = {args, def
+
+const optparse = {args, def
+ var ctx : optctx
+ var parsed
+
+ optinit(&ctx, args, def)
+ while !optdone(&ctx)
+ parsed.opts = slpush(parsed.opts, optnext(&ctx))
+ ;;
+ if ctx.args.len < def.minargs
+ put("error: expected at least %z args, got %z\n", def.minargs, ctx.args.len)
+ optusage(&ctx)
+ exit(1)
+ ;;
+ parsed.args = ctx.args
+ -> parsed
+}
+
+const optinit = {ctx, args, def
var ctx
- ctx = alloc()
ctx.optargs = args
ctx.optdef = def
@@ -61,14 +80,6 @@
next(ctx)
-> ctx
-}
-
-const optfin = {ctx
- var a
-
- a = ctx.args
- free(ctx)
- -> a
}
const optnext = {ctx
--- a/mbld/main.myr
+++ b/mbld/main.myr
@@ -17,7 +17,7 @@
var mt : bld.myrtarg
var targname
var bintarg
- var optctx
+ var cmd
var libpath
var opts
@@ -35,11 +35,10 @@
[.opt='d', .desc="dump debugging information for mbld"],
][:]
]
- optctx = std.optinit(args, &opts)
+ cmd = std.optparse(args, &opts)
bld.initopts()
- while !std.optdone(optctx)
- match std.optnext(optctx)
- | ('h', arg): usage(args[0])
+ for opt in cmd.opts
+ match opt
| ('I', arg): bld.opt_incpaths = std.slpush(bld.opt_incpaths, arg)
| ('S', _): bld.opt_genasm = true
| ('R', arg): bld.opt_instroot = arg
@@ -62,7 +61,7 @@
| ('d', arg): bld.opt_debug = true
| ('C', arg): bld.opt_mc = arg
| ('M', arg): bld.opt_muse = arg
- | _: std.optusage(optctx)
+ | _: std.die("unreachable\n")
;;
;;
@@ -80,7 +79,7 @@
if targname.len != 0
mt = [
.name=targname,
- .inputs=optctx.args,
+ .inputs=cmd.args,
.runtime=bld.opt_runtime,
.incpath=bld.opt_incpaths,
.libdeps=[][:]
@@ -95,11 +94,11 @@
bld.load(b)
/*bld.configure()*/
/* default: buildall */
- if optctx.args.len == 0
+ if cmd.args.len == 0
bld.buildall(b)
else
- for cmd in optctx.args
- match cmd
+ for c in cmd.args
+ match c
| "all": bld.buildall(b)
| "gen": bld.genall(b)
| "clean": bld.cleanall(b)
@@ -148,12 +147,3 @@
-> false
}
-const usage = {prog
- std.put("%s [-h] [-I path] [-l lib] [-b bin] inputs...\n", prog)
- std.put("\t-h\tprint this help\n")
- std.put("\t-b bin\tBuild a binary called 'bin'\n")
- std.put("\t-l lib\tBuild a library called 'name'\n")
- std.put("\t-s script\tUse the linker script 'script' when linking\n")
- std.put("\t-I path\tAdd 'path' to use search path\n")
- std.exit(0)
-}