shithub: mc

ref: e686640da8441d0cae0e45d5d6ef9f96c45a8e24
dir: /mbld/fsel.myr/

View raw version
use std

use "opts.use"

pkg bld =
	type syssel(@a) = struct
		sysattrs	: std.htab(byte[:], bool)#
		_match	: std.htab(byte[:], int)#
		_best	: std.htab(byte[:], @a)#
	;;

	const mkfsel	: (-> syssel(byte[:])#)
	const fseladd	: (fsel : syssel(byte[:])#, file : byte[:] -> void)
	const fselfin	: (fsel : syssel(byte[:])# -> byte[:][:])
;;

const mkfsel = {
	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)
	addsysattrs(fsel.sysattrs)
	-> fsel
}

const fseladd = {fsel, f
	var basename, attrs
	var nmatch, curbest
	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(1, "unrecognized type for file %s\n", f)
		;;
	| `std.None:
		match std.strrfind(f, ".")
		| `std.None:	std.fatal(1, "unrecognized type for file %s\n", f)
		| `std.Some i:
			basename = f[:i]
			attrs = ""
		;;
	;;

	nmatch = 0
	attrlist = std.strsplit(attrs, "-")
	for a in attrlist
		if std.hthas(fsel.sysattrs, a)
			nmatch++
		else
			nmatch = -1
			break
		;;
	;;
	std.slfree(attrlist)
	curbest = std.htgetv(fsel._match, basename, -1)
	if curbest < nmatch
		std.htput(fsel._match, basename, nmatch)
		std.htput(fsel._best, basename, f)
	;;
}

const fselfin = {fsel
	var keys, nmatch, ret

	keys = std.htkeys(fsel._match)
	ret = [][:]
	for k in keys
		nmatch = std.htgetv(fsel._match, k, -1)
		if nmatch == -1
			std.fatal(1, "no applicable file for '%s'\n", k)
		;;
		ret = std.slpush(ret, std.htgetv(fsel._best, k, ""))
	;;
	std.htfree(fsel._match)
	std.htfree(fsel._best)
	std.htfree(fsel.sysattrs)
	-> ret
}

const addsysattrs = {sa
	var attrs
	match opt_sys
	| "freebsd":	attrs = ["freebsd", "posixy"][:]
	| "osx":	attrs = ["osx", "posixy"][:]
	| "linux":	attrs = ["linux", "posixy"][:]
	| "plan9":	attrs = ["plan9"][:]
	| unknown:	std.fatal(1, "unknown system \"%s\"\n", unknown)
	;;
	for a in attrs
		std.htput(sa, a, true)
	;;

	match opt_arch
	| "x64":	attrs = ["x64"][:]
	| unknown:	std.fatal(1, "unknown arch %s\n", unknown)
	;;
	for a in attrs
		std.htput(sa, a, true)
	;;
}