shithub: mc

Download patch

ref: 58f59a52b75a9bd3d1be9ae6f4532f5949e45896
parent: c7b5ad4772e5ad2183d24f6ae9ffde85dfdc42dd
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Jun 18 10:23:30 EDT 2015

Update libfmt to preparse options for std.fmt()

--- a/libstd/fmt.myr
+++ b/libstd/fmt.myr
@@ -3,11 +3,17 @@
 use "die.use"
 use "extremum.use"
 use "fltfmt.use"
-use "htab.use"
 use "hashfuncs.use"
+use "hasprefix.use"
+use "htab.use"
 use "introspect.use"
+use "intparse.use"
 use "option.use"
+use "sleq.use"
+use "slpush.use"
 use "strbuf.use"
+use "strfind.use"
+use "strsplit.use"
 use "syswrap-ss.use"
 use "syswrap.use"
 use "types.use"
@@ -33,7 +39,8 @@
 
 	/* add a formatter function */
 	const fmtinstall	: (ty : byte[:], \
-		fn : (sb : strbuf#, ap : valist#, opts : byte[:] -> void) \
+		fn : (sb : strbuf#, ap : valist#, opts : (byte[:],byte[:])[:] -> void), \
+		optdesc : (byte[:], bool)[:] \
 		-> void)
 
 	$noret const fatal	: (fmt : byte[:], args : ... -> void)
@@ -40,6 +47,11 @@
 	$noret const fatalv	: (fmt : byte[:], ap : valist# -> void)
 ;;
 
+type fmtdesc = struct
+	fn	: (sb : strbuf#, ap : valist#, opts : (byte[:],byte[:])[:] -> void)
+	optdesc	: (byte[:], bool)[:]
+;;
+
 /* same as 'put', but exits the program after printing */
 const fatal = {fmt, args
 	var ap
@@ -56,14 +68,14 @@
 }
 
 var fmtmapinited : bool = false
-var fmtmap : htab(byte[:], (sb : strbuf#, ap : valist#, opts : byte[:] -> void))#
+var fmtmap : htab(byte[:], fmtdesc)#
 
-const fmtinstall = {ty, fn
+const fmtinstall = {ty, fn, optdesc
 	if !fmtmapinited
 		fmtmapinited = true
 		fmtmap = mkht(strhash, streq)
 	;;
-	htput(fmtmap, ty, fn)
+	htput(fmtmap, ty, [.fn=fn, .optdesc=optdesc])
 }
 
 const put = {fmt, args
@@ -131,8 +143,8 @@
 }
 
 const sbfmtv = {sb, fmt, ap -> size
+	var nfmt, nparams, pl
 	var c, params, ty
-	var nfmt, nparams
 
 	nparams = ap.tc.nelt
 	nfmt = 0
@@ -156,8 +168,10 @@
 
 				ty = vatype(ap)
 				match htget(fmtmap, ty)
-				| `Some func:
-					func(sb, ap, params)
+				| `Some f:
+					pl = parseparams(params, f.optdesc)
+					f.fn(sb, ap, pl)
+					std.slfree(pl)
 				| `None:
 					fallbackfmt(sb, params, ty, ap)
 				;;
@@ -177,6 +191,43 @@
 	-> sb.len
 }
 
+const parseparams = {paramstr, optdesc
+	var params, opts
+	var o, a, ha : bool, gotarg : bool
+
+	opts = [][:]
+	params = strsplit(paramstr, ",")
+	for p in params
+		/* parse out the key/value pair */
+		match std.strfind(p, "=")
+		| `std.Some idx:
+			o = p[:idx]
+			a = p[idx+1:]
+			gotarg = true
+		| `std.None:
+			o = p
+			a = ""
+			gotarg = false
+		;;
+
+		/* verify and add the arg */
+		for (opt, hasarg) in optdesc
+			if !std.sleq(opt, o)
+				continue
+			;;
+			ha = hasarg
+			if ha == gotarg
+				opts = std.slpush(opts, (o, a))
+			else
+				std.fatal("invalid option {}", o)
+			;;
+		;;
+	;;
+	slfree(params)
+	-> opts
+}
+
+
 const fallbackfmt = {sb, params, tyenc, ap : valist# -> void
 	/* value types */
 	var t_val : bool
@@ -317,9 +368,9 @@
 	-> (fmt[:i], fmt[i+1:])
 }
 
+
 const intparams = {params
 	var ip : intparams
-	var c
 
 	ip = [
 		.base = 10,
@@ -327,20 +378,27 @@
 		.padto = 0
 	]
 
-	while params.len > 0
-		(c, params) = striter(params)
-		match c
-		| 'x':	ip.base = 16
-		| '0':	ip.padfill = '0'
-		| chr:
-			while isdigit(c)
-				ip.padto = ip.padto*10 + charval(c, 10)
-				(c, params) = striter(params)
+	var pl = parseparams(params, [
+		("x", false),
+		("w", true),
+		("p", true)][:])
+	for p in pl
+		match p
+		| ("x", ""):	ip.base = 16
+		| ("w", wid):	
+			/* would use get(), but that's a dep loop */
+			match std.intparse(wid)
+			| `Some w:	ip.padto = w;
+			| `None:	die("width was not number")
 			;;
+		| ("p", pad):
+			std.assert(pad.len == 1, "pad takes one character")
+			ip.padfill = decode(pad)
+		| _:
 		;;
 	;;
+	std.slfree(pl)
 	-> ip
-
 }
 
 const digitchars = [
--- a/libstd/htab.myr
+++ b/libstd/htab.myr
@@ -86,6 +86,8 @@
 			-> `None
 		;;
 		if ht.eq(ht.keys[i], k)
+			break
+		else
 			di++
 			i = (h + di) & (ht.keys.len - 1)
 		;;
--- a/mbld/fsel.myr
+++ b/mbld/fsel.myr
@@ -4,23 +4,30 @@
 
 pkg bld =
 	type syssel(@a) = struct
+		file	: byte[:]
+		line	: int
+		targ	: byte[:]
 		sysattrs	: std.htab(byte[:], bool)#
 		_match	: std.htab(byte[:], int)#
 		_best	: std.htab(byte[:], @a)#
 	;;
 
-	const mkfsel	: (-> syssel(byte[:])#)
+	const mkfsel	: (f : byte[:], line : int, targ : byte[:] -> syssel(byte[:])#)
 	const fseladd	: (fsel : syssel(byte[:])#, file : byte[:] -> void)
 	const fselfin	: (fsel : syssel(byte[:])# -> byte[:][:])
 ;;
 
-const mkfsel = {
+const mkfsel = {file, line, targ
 	var fsel
 
-	fsel = std.alloc()
-	fsel._match = std.mkht(std.strhash, std.streq)
-	fsel._best = std.mkht(std.strhash, std.streq)
-	fsel.sysattrs = std.mkht(std.strhash, std.streq)
+	fsel = std.mk([
+		.file = file,
+		.line = line,
+		.targ = targ,
+		._match = std.mkht(std.strhash, std.streq),
+		._best = std.mkht(std.strhash, std.streq),
+		.sysattrs = std.mkht(std.strhash, std.streq),
+	])
 	addsysattrs(fsel.sysattrs)
 	-> fsel
 }
@@ -72,7 +79,7 @@
 	for k in keys
 		nmatch = std.htgetv(fsel._match, k, -1)
 		if nmatch == -1
-			std.fatal("no applicable file for '{}'\n", k)
+			std.fatal("{}:{}: target {}, no applicable file for '{}'\n", fsel.file, fsel.line, fsel.targ, k)
 		;;
 		ret = std.slpush(ret, std.htgetv(fsel._best, k, ""))
 	;;
--- a/mbld/parse.myr
+++ b/mbld/parse.myr
@@ -324,7 +324,7 @@
 
 	match inputlist(p)
 	| `std.Some (wl, libs): 
-		fsel = mkfsel()
+		fsel = mkfsel(p.fname, p.line, targ)
 		libdeps = libs
 		for w in wl
 			fseladd(fsel, w)
--- a/parse/type.c
+++ b/parse/type.c
@@ -304,7 +304,7 @@
     switch (tybase(t)->type) {
         case Tybyte: case Tyuint8: case Tyuint16: case Tyuint:
         case Tychar: case Tyuint32: case Tyuint64: case Tyulong:
-        case Typtr:
+	case Typtr: case Tybool:
             return 1;
         default:
             return 0;