1#include <signal.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include "make.h"
7
8#define TABSIZ 128
9#define FORCE 1
10#define NOFORCE 0
11
12static Target *htab[TABSIZ], *deftarget;
13
14void
15dumprules(void)
16{
17 int i;
18 Target **pp, **q, *p;
19
20 for (pp = htab; pp < &htab[TABSIZ]; ++pp) {
21 for (p = *pp; p; p = p->next) {
22 if (!p->defined)
23 continue;
24 printf("%s:", p->name);
25 for (q = p->deps; q && *q; ++q)
26 printf(" %s", (*q)->name);
27 putchar('\n');
28 for (i = 0; i < p->nactions; i++)
29 printf("\t%s\n", p->actions[i].line);
30 putchar('\n');
31 }
32 }
33}
34
35static Target *
36lookup(char *name)
37{
38 Target *tp;
39 int h = hash(name) & (TABSIZ - 1);
40
41 for (tp = htab[h]; tp && strcmp(tp->name, name); tp = tp->next)
42 ;
43
44 if (tp)
45 return tp;
46
47 tp = emalloc(sizeof(*tp));
48 tp->name = estrdup(name);
49 tp->target = tp->name;
50 tp->req = NULL;
51 tp->ndeps = 0;
52 tp->deps = NULL;
53 tp->actions = NULL;
54 tp->nactions = 0;
55 tp->next = htab[h];
56 tp->defined = 0;
57 htab[h] = tp;
58
59 return tp;
60}
61
62static void
63cleanup(Target *tp)
64{
65 int sig, precious;
66 Target *p, **q;
67
68 sig = stop;
69 printf("make: signal %d arrived\n", sig);
70
71 precious = 0;
72 p = lookup(".PRECIOUS");
73 for (q = p->deps; q && *q; q++) {
74 if (strcmp((*q)->name, tp->name) == 0) {
75 precious = 1;
76 break;
77 }
78 }
79
80 if (!precious && !nflag && !qflag && !is_dir(tp->name)) {
81 printf("make: trying to remove target %s\n", tp->name);
82 remove(tp->name);
83 }
84
85 signal(sig, SIG_DFL);
86 raise(sig);
87}
88
89static int
90depends(char *target, char *dep)
91{
92 Target **p, *tp = lookup(target);
93
94 for (p = tp->deps; p && *p; ++p) {
95 if (strcmp((*p)->name, dep) == 0)
96 return 1;
97 }
98
99 return 0;
100}
101
102void
103addtarget(char *target, int ndeps)
104{
105 Target *tp = lookup(target);
106
107 tp->defined = 1;
108 if (!deftarget && target[0] != '.') {
109 deftarget = tp;
110 return;
111 }
112
113 if (strcmp(target, ".SUFFIXES") == 0 && ndeps == 0) {
114 free(tp->deps);
115 tp->deps = NULL;
116 tp->ndeps = 0;
117 return;
118 }
119
120 if (strcmp(target, ".DEFAULT") == 0) {
121 if (ndeps > 0)
122 error("DEFAULT rule with prerequisites");
123 return;
124 }
125
126 if (strcmp(target, ".SILENT") == 0 && ndeps == 0) {
127 sflag = 1;
128 return;
129 }
130
131 if (strcmp(target, ".IGNORE") == 0 && ndeps == 0) {
132 iflag = 1;
133 return;
134 }
135
136 /* .PHONY */
137 if (strcmp(target, ".PHONY") == 0) {
138 if (ndeps == 0) {
139 free(tp->deps);
140 tp->deps = NULL;
141 tp->ndeps = 0;
142 }
143 return;
144 }
145}
146
147void
148adddep(char *target, char *dep)
149{
150 size_t siz;
151 Target **p, *tp = lookup(target);
152
153 if (depends(dep, target)) {
154 warning("circular dependency %s <- %s dropped", target, dep);
155 return;
156 }
157
158 for (p = tp->deps; p && *p; ++p) {
159 if (strcmp((*p)->name, dep) == 0)
160 return;
161 }
162
163 tp->ndeps++;
164 siz = (tp->ndeps + 1) * sizeof(Target *);
165 tp->deps = erealloc(tp->deps, siz);
166 tp->deps[tp->ndeps - 1] = lookup(dep);
167 tp->deps[tp->ndeps] = NULL;
168
169 debug("adding dependency %s <- %s", target, dep);
170}
171
172static void
173freeaction(struct action *act)
174{
175 free(act->line);
176 freeloc(&act->loc);
177}
178
179void
180addrule(char *target, struct action *acts, int n)
181{
182 int i;
183 struct action *v;
184 Target *tp = lookup(target);
185
186 debug("adding actions for target %s", target);
187
188 if (tp->actions) {
189 debug("overring actions of target %s", target);
190 for (i = 0; i < tp->nactions; i++)
191 freeaction(&tp->actions[i]);
192 free(tp->actions);
193 }
194
195 v = emalloc(n * sizeof(*v));
196 for (i = 0; i < n; i++) {
197 v[i].line = estrdup(acts[i].line);
198 v[i].loc.lineno = acts[i].loc.lineno;
199 v[i].loc.fname = estrdup(acts[i].loc.fname);
200 }
201
202 tp->nactions = n;
203 tp->actions = v;
204}
205
206static int
207execline(Target *tp, char *line, int ignore, int silence)
208{
209 char *s, *t;
210 int r, at, plus, minus, l;
211
212 (void)tp;
213
214 debug("executing '%s'", line);
215
216 at = plus = minus = 0;
217 for (s = line;; s++) {
218 switch (*s) {
219 case '@':
220 at = 1;
221 break;
222 case '-':
223 minus = 1;
224 break;
225 case '+':
226 plus = 1;
227 break;
228 default:
229 goto out_loop;
230 }
231 }
232
233out_loop:
234 /* unescape $$ */
235 for (l = strlen(s) + 1, t = s; *t; --l, ++t) {
236 if (t[0] == '$' && t[1] == '$') {
237 memmove(t + 1, t + 2, l - 2);
238 l--;
239 }
240 }
241
242 if (tflag && !plus)
243 return 0;
244
245 if (sflag || silence || (qflag && !plus))
246 at = 1;
247 if (nflag)
248 at = 0;
249 if (!at) {
250 puts(s);
251 fflush(stdout);
252 }
253
254 if ((nflag || qflag) && !plus) {
255 if (qflag)
256 exitstatus = 1;
257 return 0;
258 }
259
260 if (minus || iflag || ignore)
261 ignore = 1;
262
263 r = launch(s, ignore);
264 if (ignore)
265 return 0;
266
267 return r;
268}
269
270static int
271touch(char *name, int ignore, int silence)
272{
273 char *cmd;
274 int r, n;
275
276 n = snprintf(NULL, 0, "touch %s", name) + 1;
277 cmd = emalloc(n);
278 snprintf(cmd, n, "touch %s", name);
279
280 if (!sflag && !silence)
281 puts(cmd);
282
283 r = wsystem(cmd);
284 free(cmd);
285
286 if (ignore || iflag)
287 return 0;
288
289 return r;
290}
291
292static int
293touchdeps(Target *tp, int ignore, int silent)
294{
295 int r;
296 Target **p;
297
298 if (tp->req) {
299 r = touch(tp->req, silent, ignore);
300 if (r)
301 return r;
302 }
303
304 for (p = tp->deps; p && *p; ++p) {
305 r = touch((*p)->name, silent, ignore);
306 if (r)
307 return r;
308 }
309
310 return 0;
311}
312
313static int
314run(Target *tp)
315{
316 int r, i, ignore, silent;
317 char *s;
318 Target *p, **q;
319
320 silent = 0;
321 p = lookup(".SILENT");
322 for (q = p->deps; q && *q; ++q) {
323 if (strcmp((*q)->name, tp->name) == 0) {
324 debug("target %s error silent by .SILENT", tp->name);
325 silent = 1;
326 }
327 }
328
329 ignore = 0;
330 p = lookup(".IGNORE");
331 for (q = p->deps; q && *q; ++q) {
332 if (strcmp((*q)->name, tp->name) == 0) {
333 debug("target %s error ignored by .IGNORE", tp->name);
334 ignore = 1;
335 }
336 }
337
338 if (tflag) {
339 r = touchdeps(tp, ignore, silent);
340 if (r)
341 return r;
342 }
343
344 for (i = 0; i < tp->nactions; i++) {
345 struct action *p;
346
347 if (stop)
348 cleanup(tp);
349
350 p = &tp->actions[i];
351 debug("executing action '%s'", p->line);
352 s = expandstring(p->line, tp, &p->loc);
353 r = execline(tp, s, ignore, silent);
354 free(s);
355
356 if (r)
357 return r;
358 }
359
360 if (tflag) {
361 r = touch(tp->target, ignore, silent);
362 if (r)
363 return r;
364 }
365
366 return 0;
367}
368
369static int
370enabled(char *suffix)
371{
372 Target **p, *tp = lookup(".SUFFIXES");
373
374 for (p = tp->deps; p && *p; ++p) {
375 if (strcmp(suffix, (*p)->name) == 0)
376 return 1;
377 }
378
379 return 0;
380}
381
382static Target *
383inference(Target *tp, int force)
384{
385 time_t t;
386 int tolen, r;
387 char *to, *from;
388 Target *q, **p, *suffixes;
389 char buf[FILENAME_MAX], fname[FILENAME_MAX];
390
391 debug("searching an inference rule for %s", tp->name);
392
393 to = strrchr(tp->name, '.');
394 if (to && !enabled(to))
395 return NULL;
396 tolen = to ? (int)(to - tp->name) : (int)strlen(tp->name);
397
398 if (!to)
399 to = "";
400
401 suffixes = lookup(".SUFFIXES");
402 for (p = suffixes->deps; p && *p; ++p) {
403 from = (*p)->name;
404 debug("trying suffix %s", from);
405
406 r = snprintf(buf, sizeof(buf), "%s%s", from, to);
407
408 if (r < 0 || (size_t)r >= sizeof(buf))
409 error("suffixes too long %s %s", from, to);
410
411 q = lookup(buf);
412 if (!q->actions)
413 continue;
414
415 r = snprintf(fname, sizeof(fname), "%*.*s%s", tolen, tolen, tp->name, from);
416
417 if (r < 0 || (size_t)r >= sizeof(fname)) {
418 error("prerequisite name too long %s %s", tp->name, from);
419 }
420
421 debug("\tsearching prerequisite %s", fname);
422
423 t = stamp(fname);
424 if (t == -1) {
425 debug("\tprerequisite %s not found", fname);
426 continue;
427 }
428
429 if (!force && t <= tp->stamp) {
430 debug("\tdiscarded because is newer");
431 debug("\t%s: %s", tp->name, ctime(&tp->stamp));
432 debug("\t%s: %s", fname, ctime(&t));
433 continue;
434 }
435
436 free(q->req);
437 q->req = estrdup(fname);
438 q->deps = tp->deps;
439 q->target = tp->name;
440 q->stamp = tp->stamp;
441
442 debug("using inference rule %s with %s", q->name, fname);
443 return q;
444 }
445
446 return NULL;
447}
448
449static int
450update(Target *tp)
451{
452 Target *p;
453
454 debug("%s needs to be updated", tp->name);
455
456 if (tp->actions) {
457 debug("using target rule to build %s", tp->name);
458 return run(tp);
459 }
460
461 if ((p = inference(tp, FORCE)) != NULL) {
462 debug("using inference rule %s", p->name);
463 return run(p);
464 }
465
466 p = lookup(".DEFAULT");
467 if (p->defined) {
468 debug("using default rule");
469 return run(p);
470 }
471
472 debug("not rule found to update %s", tp->name);
473
474 if (!tp->defined)
475 error("don't know how to make %s", tp->name);
476
477 return 0;
478}
479
480static int
481is_phony(Target *tp)
482{
483 Target **p, *ph = lookup(".PHONY");
484 for (p = ph->deps; p && *p; ++p)
485 if (strcmp((*p)->name, tp->name) == 0)
486 return 1;
487 return 0;
488}
489
490static int
491rebuild(Target *tp, int *buildp)
492{
493 Target **p, *q;
494 int r, need, build, err, def;
495
496 debug("checking rebuild of %s", tp->name);
497
498 if (is_phony(tp))
499 tp->stamp = -1;
500 else
501 tp->stamp = stamp(tp->name);
502
503 def = err = need = 0;
504 for (p = tp->deps; p && *p; ++p) {
505 if (stop)
506 cleanup(tp);
507
508 q = *p;
509 debug("checking dependency %s", q->name);
510
511 if (strcmp(q->name, tp->name) == 0 && q->actions)
512 def = 1;
513
514 build = 0;
515 if (rebuild(q, &build) != 0) {
516 err = 1;
517 continue;
518 }
519
520 if (build) {
521 debug("rebuild of %s forces rebuild of %s", q->name, tp->name);
522 need = 1;
523 } else if (q->stamp > tp->stamp) {
524 debug("dependency %s is newer than %s", q->name, tp->name);
525 need = 1;
526 }
527 }
528
529 if (tp->stamp == -1) {
530 need = 1;
531 } else if (!def) {
532 debug("no action found for %s, looking a inference rule", tp->name);
533 if (inference(tp, NOFORCE))
534 need = 1;
535 }
536
537 if (err) {
538 warning("target %s not remade because of errors", tp->name);
539 return 1;
540 } else if (need) {
541 *buildp = 1;
542
543 debug("target %s needs updating", tp->name);
544 r = update(tp);
545 if (r == 0)
546 return 0;
547
548 if (stop)
549 cleanup(tp);
550
551 exitstatus = 1;
552
553 if (!kflag)
554 error("target %s: error %d", tp->name, r);
555 else
556 warning("target %s: error %d", tp->name, r);
557 return r;
558 }
559
560 return 0;
561}
562
563int
564build(char *name)
565{
566 int build;
567
568 if (!name) {
569 if (!deftarget) {
570 printf("make: no target to make\n");
571 return 0;
572 }
573 name = deftarget->name;
574 }
575
576 debug("checking target %s", name);
577
578 build = 0;
579 return rebuild(lookup(name), &build);
580}