summaryrefslogtreecommitdiff
path: root/mbld/fsel.myr
blob: e40d16ca7491bbcc6e96b2a29c9ae216c2d8caa5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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("unrecognized type for file %s\n", f)
		;;
	| `std.None:
		match std.strrfind(f, ".")
		| `std.None:	std.fatal("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("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("unknown system \"%s\"\n", unknown)
	;;
	for a in attrs
		std.htput(sa, a, true)
	;;

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