summaryrefslogtreecommitdiff
path: root/mbld/util.myr
blob: dc03bdc5d0465e9f438318ca8f836adca3064615 (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
135
136
137
use std

use "opts"
use "types"

pkg bld =
	const run	: (cmd : byte[:][:] -> bool)
	const printcmd	: (cmd : byte[:][:] -> void)
	const mbldput	: (fmt : byte[:], args : ... -> void)
	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 setdir	: (b : build#, dir : byte[:] -> void)
;;

const run = {cmd
	var pid

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

const mbldput = {fmt, args
	var ap

	if !opt_silent
		ap = std.vastart(&args)
		std.putv(fmt, &ap)
	;;
}

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

const srcsplit = {src
	var platf, fbase, suff

	platf = ""
	suff = ""

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

	match std.strrfind(src[fbase:], "+")
	| `std.Some i:
		platf = src[fbase+i:]
		src = src[:fbase+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("{}{}", f, newsuff)
}

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

	(base, platf, suff) = srcsplit(src)
	if std.hassuffix(suff, ".myr")
		-> std.strcat(base, new)
	elif std.hassuffix(suff, ".s")
		-> std.strcat(base, new)
	elif std.hassuffix(suff, ".glue.c")
		-> std.strjoin([base, ".glue", new][:], "")
	else
		std.fatal("unrecognized source {}\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("unknown target '{}'\n", n)
	| `std.Some t:	-> t
	;;
}

const setdir = {b, dir
	var p

	if !std.sleq(b.curdir, dir)
		p = std.pathcat(b.basedir, dir)
		if !std.chdir(p)
			std.fatal("could not cd into {}\n", p)
		;;
		b.curdir = dir
		std.slfree(p)
	;;
}