summaryrefslogtreecommitdiff
path: root/fsel.myr
blob: ea45b4f2928b9fa296aa3b9e10c220875f060f91 (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 fsel = struct
		filematch	: std.htab(byte[:], int)#
		filebest	: std.htab(byte[:], byte[:])#
		sysattrs	: std.htab(byte[:], bool)#
	;;

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

const mkfsel = {
	var fsel

	fsel = std.alloc()
	fsel.filematch = std.mkht(std.strhash, std.streq)
	fsel.filebest = 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.filematch, basename, -1)
	if curbest < nmatch
		std.htput(fsel.filematch, basename, nmatch)
		std.htput(fsel.filebest, basename, f)
	;;
}

const fselfin = {fsel
	var keys, nmatch, ret

	keys = std.htkeys(fsel.filematch)
	ret = [][:]
	for k in keys
		nmatch = std.htgetv(fsel.filematch, k, -1)
		if nmatch == -1
			std.fatal(1, "no applicable file for '%s'\n", k)
		;;
		ret = std.slpush(ret, std.htgetv(fsel.filebest, k, ""))
	;;
	std.htfree(fsel.filematch)
	std.htfree(fsel.filebest)
	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)
	;;
}