summaryrefslogtreecommitdiff
path: root/mbld/util.myr
blob: 383cdbdf4f26a80c64a13a351eea8c82c9d5eff6 (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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std

use "opts.use"
use "types.use"

pkg bld =
	const run	: (cmd : byte[:][:] -> void)
	const printcmd
	const srcsplit	: (src : byte[:] -> (byte[:], byte[:], byte[:]))
	const swapsuffix	: (f : byte[:], suff : byte[:], newsuff : byte[:] -> byte[:])
	const srcswapsuffix	: (f : byte[:], newsuff : byte[:] -> byte[:])
	const strlistfree	: (sl : byte[:][:] -> void)
	const gettarg	: (tab : std.htab(byte[:], targ)#, n : byte[:] -> targ)
	const pushdir	: (b : build#, dir : byte[:] -> void)
	const popdir	: (b : build# -> void)
;;

const run = {cmd
	var pid

	printcmd(cmd)
	pid = std.fork()
	if pid == -1
		std.fatal(1, "could not fork command\n")
	elif pid == 0
		if std.execvp(cmd[0], cmd) < 0
			std.fatal(1, "failed to exec %s\n", cmd[0])
		;;
	else
		match std.wait(pid)
		| `std.Wsuccess:	/* nothing */
		| `std.Wfailure:	std.fatal(1, "FAIL: \"%s\"\n", std.strjoin(cmd, " "))
		| `std.Wsignalled:	std.fatal(1, "CRASH: \"%s\"\n", std.strjoin(cmd, " "))
		| `std.Waiterror:	std.fatal(1, "WAT: \"%s\"\n", std.strjoin(cmd, " "))
		;;
	;;
}

const printcmd = {lst
	if lst.len > 0
		std.put("\t")
		std.put("%s\t", lst[0])
		for l in lst[1:]
			std.put("%s ", l)
		;;
	;;
	std.put("\n")
}

const srcsplit = {src
	var platf, suff

	platf = ""
	suff = ""
	match std.strrfind(src, ".")
	| `std.Some i:
		suff = src[i:]
		src = src[:i]
	| `std.None:
		/* no suffix to trim */
	;;

	match std.strrfind(src, "+")
	| `std.Some i:
		platf = src[i:]
		src = src[:i]
	| `std.None:
		/* no platform to trim */
	;;
	-> (src, platf, suff)
}

const swapsuffix = {f, suff, newsuff
	if std.hassuffix(f, suff)
		f = f[:f.len - suff.len]
	;;
	-> std.fmt("%s%s", f, newsuff)
}

const srcswapsuffix = {src, new
	var base, platf, suff

	(base, platf, suff) = srcsplit(src)
	if std.sleq(suff, ".myr")
		-> std.strcat(base, new)
	elif std.sleq(suff, ".s")
		-> std.strcat(base, new)
	else
		std.fatal(1, "unrecognized source %s\n", src)
	;;
}

const strlistfree = {sl
	for s in sl
		std.slfree(s)
	;;
	std.slfree(sl)
}

const gettarg = {tab, n
	match std.htget(tab, n)
	| `std.None:	std.fatal(1, "internal: nonexistent %s\n", n)
	| `std.Some t:	-> t
	;;
}

const pushdir = {b, dir
	b.dirstk = std.slpush(b.dirstk, dir)
	setdir(b, dir)
}

const popdir = {b
	b.dirstk = b.dirstk[:b.dirstk.len-1]
	setdir(b, b.dirstk[b.dirstk.len-1])
}

const setdir = {b, dir
	var p

	if !std.sleq(b.curdir, dir)
		p = std.pathcat(b.basedir, dir)
		if b.curdir.len != 0
			std.put("Leaving directory '%s'\n", b.curdir)
		;;

		std.put("Entering directory '%s'\n", dir)
		if !std.chdir(p)
			std.fatal(1, "could not cd into %s\n", p)
		;;
		b.curdir = dir
		std.slfree(p)
	;;
}