shithub: mc

Download patch

ref: 9125dee98dc51e46a35c5e30a8a228031dcca44d
parent: 03af679a2a685afe93242d2751ea1a94d9c17569
author: Ori Bernstein <[email protected]>
date: Thu Apr 4 12:40:54 EDT 2013

Fix up option parsing code.

--- a/libstd/fmt.myr
+++ b/libstd/fmt.myr
@@ -15,6 +15,7 @@
 	  %w	- A 16 bit integer
 	  %i	- A 32 bit integer
 	  %l	- A 64 bit integer
+	  %z	- A size
 	  %p	- A pointer
 	  %c	- A char
 */
@@ -90,6 +91,7 @@
 	var w_val : int16
 	var i_val : int32
 	var l_val : int64
+	var z_val : size
 	var p_val : byte#
         var c_val : char
 
@@ -119,6 +121,10 @@
 			'l':
 				(l_val, ap) = vanext(ap)
 				n += intfmt(buf[n:], l_val castto(int64), 10)
+				;;
+			'z':
+				(z_val, ap) = vanext(ap)
+				n += intfmt(buf[n:], z_val castto(int64), 10)
 				;;
 			'p':
 				(p_val, ap) = vanext(ap)
--- a/libstd/optparse.myr
+++ b/libstd/optparse.myr
@@ -1,7 +1,9 @@
 use "alloc.use"
 use "die.use"
 use "extremum.use"
+use "fmt.use"
 use "slappend.use"
+use "sys.use"
 use "types.use"
 use "utf.use"
 
@@ -12,6 +14,7 @@
 		args	: byte[:][:]
 
 		/* state */
+		done	: bool	/* if we've seen '--', everything's an arg */
 		argidx	: size
 		curarg	: byte[:]
 		arglist	: byte[:][:]
@@ -18,8 +21,7 @@
 	;;
 
 	const optinit	: (opts	: byte[:], args : byte[:][:] -> optctx#)
-	const optnext	: (ctx : optctx# -> char)
-	const optarg	: (ctx : optctx# -> byte[:])
+	const optnext	: (ctx : optctx# -> [char, byte[:]])
 ;;
 
 const optinit = {opts, args
@@ -28,49 +30,83 @@
 	ctx = alloc()
 	ctx.opts = opts
 	ctx.args = args
+
+	ctx.done = false
 	ctx.argidx = 0
 	ctx.arglist = [][:]
 	ctx.curarg = [][:]
-	next(ctx)
 	-> ctx
 }
 
 const optnext = {ctx
 	var c
+	var arg
+	var valid
+	var tryarg
+	var needarg
 
+	/* end of arguments */
 	if !ctx.curarg.len
 		if !next(ctx)
-			-> Badchar
+			-> (Badchar, "")
 		;;
 	;;
+
 	(c, ctx.curarg) = striter(ctx.curarg)
-	-> c
-}
 
-const optarg = {ctx
-	var arg
-
-	if ctx.curarg.len > 0
+	(valid, tryarg, needarg) = optinfo(ctx, c)
+	if !valid
+		put("Unexpected argument %c\n", c)
+		exit(1)
+	elif tryarg && ctx.curarg.len > 0
 		arg = ctx.curarg
 		ctx.curarg = ctx.curarg[ctx.curarg.len:]
-	elif ctx.argidx > ctx.args.len
+	elif tryarg && ctx.argidx < (ctx.args.len - 1)
 		arg = ctx.args[ctx.argidx + 1]
 		ctx.argidx++
 		next(ctx)
+	elif needarg
+		put("Expected argument for %c\n", c)
+		exit(1)
 	else
-		die("Arg needed")
+		arg = ""
 	;;
-	-> arg
+
+	-> (c, arg)
 }
 
+const optinfo = {ctx, arg
+	var s
+	var c
+
+	s = ctx.opts
+	while s.len != 0
+		(c, s) = striter(s)
+		if c == arg
+			(c, s) = striter(s)
+			/* mandatory arg */
+			if c == ':'
+				-> (true, true, true)
+			/* optional arg */
+			elif c == '?'
+				-> (true, true, false)
+			/* no arg */
+			else
+				-> (true, false, false)
+			;;
+		;;
+	;;
+	-> (false, false)
+}
+
 const next = {ctx
 	var i
 
 	for i = ctx.argidx + 1; i < ctx.args.len; i++
-		if decode(ctx.args[i]) == '-'
+		if !ctx.done && decode(ctx.args[i]) == '-'
 			goto foundopt
 		else
-			ctx.args = slappend(ctx.args, ctx.args[i])
+			ctx.arglist = slappend(ctx.arglist, ctx.args[i])
 		;;
 	;;
 	-> false
--- a/libstd/test.myr
+++ b/libstd/test.myr
@@ -6,6 +6,7 @@
 	var i
         var opt
         var o
+	var a
 
 	std.put("args.len = %i\n", args.len)
 	for i = 0; i < args.len; i++
@@ -12,14 +13,19 @@
 		std.put("args[%i] = %s\n", i, args[i])
 	;;
 
-        opt = std.optinit("asdf:", args)
-        while (o = std.optnext(opt)) != std.Badchar
-        	std.put("option %c\n", o)
-		match o
-		'a':	std.put("\targ=%s\n", std.optarg(opt));;
-		'b':	std.put("\targ=%s\n", std.optarg(opt));;
+        opt = std.optinit("asdf:g?", args)
+	std.put("arglen = %i\n", opt.args.len)
+        while true
+		(o, a) = std.optnext(opt)
+		if o == std.Badchar
+			goto done
 		;;
+		std.put("option %c, arg = %s\n", o, a)
         ;;
+:done
+	for i = 0; i < opt.arglist.len; i++
+		std.put("arg %s\n", opt.arglist[i])
+	;;
 
         
 	/* try the byte allocator for large variety of sizes. */