ref: f8e8b084dad7b4b7ea813bc4b612f64a07f27cd7
dir: /mbld/syssel.myr/
use std
use "opts"
use "types"
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)#
;;
generic mksyssel : (b : build#, f : byte[:], line : int, targ : byte[:] -> syssel(@a)#)
generic sysseladd : (syssel : syssel(byte[:])#, file : byte[:] -> void)
generic sysseladdlist : (syssel : syssel(@a)#, base : byte[:], attrs : byte[:][:], val : @a -> void)
generic sysselfin : (syssel : syssel(@a)# -> @a[:])
const addsysattrs : (sa : build#, tags : byte[:][:] -> void)
;;
generic mksyssel = {b, file, line, targ
var syssel
syssel = std.mk([
.file = file,
.line = line,
.targ = targ,
._match = std.mkht(std.strhash, std.streq),
._best = std.mkht(std.strhash, std.streq),
.sysattrs = b.sysattrs
])
-> syssel
}
generic sysseladd = {syssel, f
var basename, attrs
var attrlist
match std.strfind(f, "+")
| `std.Some i:
basename = f[:i]
match std.strrfind(f[i+1:], ".")
| `std.Some j: attrs = f[i+1:][:j]
| `std.None: std.fatal("unrecognized type for file {}\n", f)
;;
| `std.None:
match std.strrfind(f, ".")
| `std.None: std.fatal("unrecognized type for file {}\n", f)
| `std.Some i:
basename = f[:i]
attrs = ""
;;
;;
attrlist = std.strsplit(attrs, "-")
sysseladdlist(syssel, basename, attrlist, f)
std.slfree(attrlist)
}
generic sysseladdlist = {syssel, base, attrs, val
var nmatch, curbest
nmatch = 0
for a in attrs
if std.hthas(syssel.sysattrs, a)
nmatch++
else
nmatch = -1
break
;;
;;
curbest = std.htgetv(syssel._match, base, -1)
if curbest < nmatch
std.htput(syssel._match, base, nmatch)
std.htput(syssel._best, base, val)
;;
}
generic sysselfin = {syssel
var keys, nmatch, ret
keys = std.htkeys(syssel._match)
ret = [][:]
for k in keys
nmatch = std.htgetv(syssel._match, k, -1)
if nmatch == -1
std.fatal("{}:{}: target {}, no applicable file for '{}'\n", syssel.file, syssel.line, syssel.targ, k)
;;
std.slpush(&ret, std.get(std.htget(syssel._best, k)))
;;
std.htfree(syssel._match)
std.htfree(syssel._best)
-> ret
}
const addsysattrs = {b, tags
var tagfile
match opt_sys
| "freebsd": tag(b.sysattrs, ["freebsd", "posixy"][:])
| "openbsd": tag(b.sysattrs, ["openbsd", "posixy"][:])
| "osx": tag(b.sysattrs, ["osx", "posixy"][:])
| "linux": tag(b.sysattrs, ["linux", "posixy"][:])
| "plan9": tag(b.sysattrs, ["plan9"][:])
| unknown: std.fatal("unknown systemx \"{}\"\n", unknown)
;;
match opt_arch
| "x64": tag(b.sysattrs, ["x64"][:])
| unknown: std.fatal("unknown architecture {}\n", unknown)
;;
tag(b.sysattrs, tags)
tagfile = std.pathcat(b.basedir, "systags")
if std.fexists(tagfile)
loadtagfile(b, tagfile)
;;
std.slfree(tagfile)
}
const loadtagfile = {b, tagfile
var data, tag
data = std.try(std.slurp(tagfile))
while true
data = skipspace(data)
(tag, data) = word(data)
match tag
| `std.Some w:
std.htput(b.sysattrs, w, true)
| `std.None:
if data.len > 0
std.fatal("junk character near '{}'\n", trailing(data, 10))
else
break
;;
;;
;;
}
const skipspace = {data
var c
c = std.decode(data)
while std.isspace(c)
data = data[std.charlen(c):]
;;
-> data
}
const word = {data
var c, split
split = 0
c = std.decode(data[:])
while std.isalnum(c) || c == '.' || c == '_' || c == '$'
split += std.charlen(c)
;;
if split > 0
-> (`std.Some data[:split], data[split:])
else
-> (`std.None, data)
;;
}
const tag = {sa, tags
for t in tags
std.htput(sa, t, true)
;;
}
const trailing = {str, len
-> str[:std.min(len, str.len)]
}