Commit Diff


commit - /dev/null
commit + 23b7ad133bdb262106b265ca87f252b6bf812abb
blob - /dev/null
blob + 62e0d949b816082fc0d86f486f63a3b5fddb74de (mode 644)
Binary files /dev/null and .make.awk.swp differ
blob - /dev/null
blob + 38e0700e0b24c4bf13936f27cd9bef79fdde5b47 (mode 644)
--- /dev/null
+++ Makefile
@@ -0,0 +1,16 @@
+.POSIX:
+
+PREFIX = /usr/local
+
+all: make
+
+clean:
+	rm -f make
+
+install: make
+	mkdir -p ${DESTDIR}${PREFIX}/bin
+	cp -f make ${DESTDIR}${PREFIX}/bin/
+
+make: make.awk
+	(printf "#!/bin/sh\ncode=%c\n" \'; cat make.awk; printf '%c\nawk -v args="$$*" "$$code" Makefile\n' \') > $@
+	chmod +x $@
blob - /dev/null
blob + dc9f14a18c2d872ae9a5631634bf40e1ac051faf (mode 644)
--- /dev/null
+++ make.awk
@@ -0,0 +1,189 @@
+# awkward make
+
+function strip(s) {
+	sub(/^[[:space:]]*/, "", s);
+	sub(/[[:space:]]*$/, "", s);
+	return s;
+}
+
+function find(name) {
+	for (i = 1; i <= length(data);) {
+		if (data[i] == name)
+			return i;
+		i += data[++i] + 1;
+		i += data[i] + 1;
+	}
+	return 0;
+}
+
+function isnewer(a, b) {
+	cmd = sprintf("ls -1t '%s' '%s' 2>&1", a, b);
+	cmd | getline file;
+	close(cmd);
+	regex = "^" a "\*?$";
+	return file ~ regex;
+}
+
+function exists(f) {
+	cmd = sprintf("ls '%s' > /dev/null 2>&1", f);
+	return system(cmd) == 0;
+}
+
+function expand(s, rulename, i, out, name, ch, chars) {
+	out = "";
+	split(s, chars, "");
+	for (i = 1; i <= length(chars);) {
+		ch = chars[i++];
+		if (ch != "$") {
+			out = out ch;
+			continue;
+		}
+
+		ch = chars[i++];
+
+		if (ch == "{") {
+			name = "";
+			while (1) {
+				ch = chars[i++];
+				if (ch == "}")
+					break;
+				name = name ch;
+			}
+
+			out = out macros[name];
+		} else if (ch == "$") {
+			out = out "$";
+		} else if (ch == "@") {
+			out = out rulename;
+		} else {
+			print "ERROR: invalid replacement";
+			exit 1;
+		}
+	}
+	return out;
+}
+
+function run(pos, name, updated, num, i, dep, cmd) {
+	name = data[pos];
+	num = data[++pos];
+	++pos;
+
+	updated = !exists(name);
+
+	for (i = 1; i <= num; ++i) {
+		dep = data[pos++];
+		rule = find(dep);
+
+		if (exists(dep)) {
+			if (isnewer(dep, name))
+				updated = 1;
+		}
+
+		if (rule != 0) {
+			if (run(rule))
+				updated = 1;
+		} else if (!exists(dep)) {
+			print "ERROR: No rule for", dep;
+			exit 1;
+		}
+	}
+
+	if (updated == 0)
+		return 0;
+
+	num = data[pos++];
+	for (i = 1; i <= num; ++i) {
+		cmd = data[pos++];
+		print cmd;
+		cmd = expand(cmd, name);
+		if (system(cmd) != 0) {
+			print "ERROR: Command failed";
+			exit 1;
+		}
+	}
+	return 1;
+}
+
+BEGIN {
+	pos = 1;
+	saved = -1;
+}
+
+# Empty lines and comments
+/^[[:space:]]*(#.*)?$/ { next; }
+
+# Macro Definitions
+/^[a-zA-Z_][a-zA-Z_0-9]*[[:space:]]*=.*$/ {
+	split($0, x, "=");
+	macros[strip(x[1])] = strip(x[2]);
+	next;
+}
+
+# Rule Declarations
+/^[^:]+:[^:]*$/ {
+	split($0, x, ":");
+	split(strip(x[1]), targets, "[[:space:]]+");
+	if (length(targets) != 1) {
+		print "ERROR: no multi-targets supported";
+		exit 1;
+	}
+	target = targets[1];
+	split(strip(x[2]), deps, "[[:space:]]+");
+
+	if (target ~ /^\..*$/) {
+		if (target == ".POSIX")
+			next;
+		print "ERROR: invalid directive" target;
+		exit 1;
+	}
+
+	data[pos++] = target;
+	data[pos++] = length(deps);
+	for (i = 1; i <= length(deps); ++i) {
+		data[pos++] = deps[i];
+	}
+	saved = pos++;
+	data[saved] = 0;
+	next;
+}
+
+# Rule Commands
+/^\t.*$/ {
+	if (saved == -1) {
+		print "ERROR: no rule declaration";
+		exit 1;
+	}
+	gsub(/^\t/, "");
+	data[saved]++;
+	data[pos++] = $0;
+}
+
+END {
+	split(args, argv, "[[:space:]]+");
+
+	k = 1;
+
+	for (i = 1; i <= length(argv); ++i) {
+		arg = argv[i];
+		if (arg ~ /^[^=]+=.*$/) {
+			split(arg, m, "=");
+			macros[m[1]] = m[2];
+		} else {
+			rules[k++] = arg;
+		}
+	}
+
+	if (length(rules) != 0) {
+		for (k = 1; k <= length(rules); ++k) {
+			name = rules[k];
+			rule = find(name);
+			if (rule == 0) {
+				print "No such rule:", name;
+				exit 1;
+			}
+			run(rule);
+		}
+	} else {
+		run(1);
+	}
+}