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