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
+.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
+# 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);
+ }
+}