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;