Blob


1 # awkward make
3 function strip(s) {
4 sub(/^[[:space:]]*/, "", s);
5 sub(/[[:space:]]*$/, "", s);
6 return s;
7 }
9 function find(name) {
10 for (i = 1; i <= length(data);) {
11 if (data[i] == name)
12 return i;
13 i += data[++i] + 1;
14 i += data[i] + 1;
15 }
16 return 0;
17 }
19 function isnewer(a, b) {
20 cmd = sprintf("ls -1t '%s' '%s' 2>&1", a, b);
21 cmd | getline file;
22 close(cmd);
23 regex = "^" a "\*?$";
24 return file ~ regex;
25 }
27 function exists(f) {
28 cmd = sprintf("ls '%s' > /dev/null 2>&1", f);
29 return system(cmd) == 0;
30 }
32 function expand(s, rulename, i, out, name, ch, chars) {
33 out = "";
34 split(s, chars, "");
35 for (i = 1; i <= length(chars);) {
36 ch = chars[i++];
37 if (ch != "$") {
38 out = out ch;
39 continue;
40 }
42 ch = chars[i++];
44 if (ch == "{") {
45 name = "";
46 while (1) {
47 ch = chars[i++];
48 if (ch == "}")
49 break;
50 name = name ch;
51 }
53 out = out macros[name];
54 } else if (ch == "$") {
55 out = out "$";
56 } else if (ch == "@") {
57 out = out rulename;
58 } else {
59 print "ERROR: invalid replacement";
60 exit 1;
61 }
62 }
63 return out;
64 }
66 function run(pos, name, updated, num, i, dep, cmd) {
67 name = data[pos];
68 num = data[++pos];
69 ++pos;
71 updated = !exists(name);
73 for (i = 1; i <= num; ++i) {
74 dep = data[pos++];
75 rule = find(dep);
77 if (exists(dep)) {
78 if (isnewer(dep, name))
79 updated = 1;
80 }
82 if (rule != 0) {
83 if (run(rule))
84 updated = 1;
85 } else if (!exists(dep)) {
86 print "ERROR: No rule for", dep;
87 exit 1;
88 }
89 }
91 if (updated == 0)
92 return 0;
94 num = data[pos++];
95 for (i = 1; i <= num; ++i) {
96 cmd = data[pos++];
97 print cmd;
98 cmd = expand(cmd, name);
99 if (system(cmd) != 0) {
100 print "ERROR: Command failed";
101 exit 1;
104 return 1;
107 BEGIN {
108 pos = 1;
109 saved = -1;
112 # Empty lines and comments
113 /^[[:space:]]*(#.*)?$/ { next; }
115 # Macro Definitions
116 /^[a-zA-Z_][a-zA-Z_0-9]*[[:space:]]*=.*$/ {
117 split($0, x, "=");
118 macros[strip(x[1])] = strip(x[2]);
119 next;
122 # Rule Declarations
123 /^[^:]+:[^:]*$/ {
124 split($0, x, ":");
125 split(strip(x[1]), targets, "[[:space:]]+");
126 if (length(targets) != 1) {
127 print "ERROR: no multi-targets supported";
128 exit 1;
130 target = targets[1];
131 split(strip(x[2]), deps, "[[:space:]]+");
133 if (target ~ /^\..*$/) {
134 if (target == ".POSIX")
135 next;
136 print "ERROR: invalid directive" target;
137 exit 1;
140 data[pos++] = target;
141 data[pos++] = length(deps);
142 for (i = 1; i <= length(deps); ++i) {
143 data[pos++] = deps[i];
145 saved = pos++;
146 data[saved] = 0;
147 next;
150 # Rule Commands
151 /^\t.*$/ {
152 if (saved == -1) {
153 print "ERROR: no rule declaration";
154 exit 1;
156 gsub(/^\t/, "");
157 data[saved]++;
158 data[pos++] = $0;
161 END {
162 split(args, argv, "[[:space:]]+");
164 k = 1;
166 for (i = 1; i <= length(argv); ++i) {
167 arg = argv[i];
168 if (arg ~ /^[^=]+=.*$/) {
169 split(arg, m, "=");
170 macros[m[1]] = m[2];
171 } else {
172 rules[k++] = arg;
176 if (length(rules) != 0) {
177 for (k = 1; k <= length(rules); ++k) {
178 name = rules[k];
179 rule = find(name);
180 if (rule == 0) {
181 print "No such rule:", name;
182 exit 1;
184 run(rule);
186 } else {
187 run(1);