shithub: mc

Download patch

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)
-}