1#include <signal.h>2#include <stdio.h>3#include <stdlib.h>4#include <string.h>56#include "make.h"78#define TABSIZ 1289#define FORCE 110#define NOFORCE 01112static Target *htab[TABSIZ], *deftarget;1314void15dumprules(void)16{17 int i;18 Target **pp, **q, *p;1920 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}3435static Target *36lookup(char *name)37{38 Target *tp;39 int h = hash(name) & TABSIZ-1;4041 for (tp = htab[h]; tp && strcmp(tp->name, name); tp = tp->next)42 ;4344 if (tp)45 return tp;4647 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;5859 return tp;60}6162static void63cleanup(Target *tp)64{65 int sig, precious;66 Target *p, **q;6768 sig = stop;69 printf("make: signal %d arrived\n", sig);7071 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 }7980 if (!precious && !nflag && !qflag && !is_dir(tp->name)) {81 printf("make: trying to remove target %s\n", tp->name);82 remove(tp->name);83 }8485 signal(sig, SIG_DFL);86 raise(sig);87}8889static int90depends(char *dep, char *target)91{9293 int i;94 char *dname;95 Target **p, *tp;9697 if (strcmp(target, dep) == 0)98 return 1;99100 tp = lookup(dep);101 for (p = tp->deps; p && *p; ++p) {102 dname = (*p)->name;103 if (depends(dname, target))104 return 1;105 }106107 return 0;108}109110static int111is_suffix(char *s)112{113 int n;114115 if (s[0] != '.')116 return 0;117118 for (n = 0; s = strchr(s, '.'); n++)119 s++;120121 return n == 2;122}123124void125addtarget(char *target, int ndeps)126{127 Target *tp = lookup(target);128129 tp->defined = 1;130 if (!deftarget && target[0] != '.') {131 deftarget = tp;132 return;133 }134135 if (strcmp(target, ".SUFFIXES") == 0 && ndeps == 0) {136 free(tp->deps);137 tp->deps = NULL;138 tp->ndeps = 0;139 return;140 }141142 if (strcmp(target, ".DEFAULT") == 0) {143 if (ndeps > 0)144 error("DEFAULT rule with prerequisites");145 return;146 }147148 if (strcmp(target, ".SILENT") == 0 && ndeps == 0) {149 sflag = 1;150 return;151 }152153 if (strcmp(target, ".IGNORE") == 0 && ndeps == 0) {154 iflag = 1;155 return;156 }157}158159void160adddep(char *target, char *dep)161{162 int i;163 size_t siz;164 Target **p, *tp = lookup(target);165166 if (depends(dep, target)) {167 warning("circular dependency %s <- %s dropped", target, dep);168 return;169 }170171 for (p = tp->deps; p && *p; ++p) {172 if (strcmp((*p)->name, dep) == 0)173 return;174 }175176 tp->ndeps++;177 siz = (tp->ndeps + 1) * sizeof(Target *);178 tp->deps = erealloc(tp->deps, siz);179 tp->deps[tp->ndeps-1] = lookup(dep);180 tp->deps[tp->ndeps] = NULL;181182 debug("adding dependency %s <- %s", target, dep);183}184185static void186freeaction(struct action *act)187{188 free(act->line);189 freeloc(&act->loc);190}191192void193addrule(char *target, struct action *acts, int n)194{195 int i;196 struct action *v;197 Target *tp = lookup(target);198199 debug("adding actions for target %s", target);200201 if (tp->actions) {202 debug("overring actions of target %s", target);203 for (i = 0; i < tp->nactions; i++)204 freeaction(&tp->actions[i]);205 free(tp->actions);206 }207208 v = emalloc(n * sizeof(*v));209 for (i = 0; i < n; i++) {210 v[i].line = estrdup(acts[i].line);211 v[i].loc.lineno = acts[i].loc.lineno;212 v[i].loc.fname = estrdup(acts[i].loc.fname);213 }214215 tp->nactions = n;216 tp->actions = v;217}218219static int220execline(Target *tp, char *line, int ignore, int silence)221{222 char *s, *t;223 Target *p, **q;224 int r, at, plus, minus, l;225226 debug("executing '%s'", line);227228 at = plus = minus = 0;229 for (s = line; ; s++) {230 switch (*s) {231 case '@':232 at = 1;233 break;234 case '-':235 minus = 1;236 break;237 case '+':238 plus = 1;239 break;240 default:241 goto out_loop;242 }243 }244245out_loop:246 /* unescape $$ */247 for (l = strlen(s)+1, t = s; *t; --l, ++t) {248 if (t[0] == '$' && t[1] == '$') {249 memmove(t+1, t+2, l-2);250 l--;251 }252 }253254 if (tflag && !plus)255 return 0;256257 if (sflag || silence || (qflag && !plus))258 at = 1;259 if (nflag)260 at = 0;261 if (!at) {262 puts(s);263 fflush(stdout);264 }265266 if ((nflag || qflag) && !plus) {267 if (qflag)268 exitstatus = 1;269 return 0;270 }271272 if (minus || iflag || ignore)273 ignore = 1;274275 r = launch(s, ignore);276 if (ignore)277 return 0;278279 return r;280}281282static int283touch(char *name, int ignore, int silence)284{285 char *cmd;286 int r, n;287288 n = snprintf(NULL, 0, "touch %s", name) + 1;289 cmd = emalloc(n);290 snprintf(cmd, n, "touch %s", name);291292 if (!sflag && !silence)293 puts(cmd);294295 r = system(cmd);296 free(cmd);297298 if (ignore || iflag)299 return 0;300301 return r;302}303304static int305touchdeps(Target *tp, int ignore, int silent)306{307 int r;308 Target **p;309310 if (tp->req) {311 r = touch(tp->req, silent, ignore);312 if (r)313 return r;314 }315316 for (p = tp->deps; p && *p; ++p) {317 r = touch((*p)->name, silent, ignore);318 if (r)319 return r;320 }321322 return 0;323}324325static int326run(Target *tp)327{328 int r, i, ignore, silent;329 char *s;330 Target *p, **q;331332 silent = 0;333 p = lookup(".SILENT");334 for (q = p->deps; q && *q; ++q) {335 if (strcmp((*q)->name, tp->name) == 0) {336 debug("target %s error silent by .SILENT", tp->name);337 silent = 1;338 }339 }340341 ignore = 0;342 p = lookup(".IGNORE");343 for (q = p->deps; q && *q; ++q) {344 if (strcmp((*q)->name, tp->name) == 0) {345 debug("target %s error ignored by .IGNORE", tp->name);346 ignore = 1;347 }348 }349350 if (tflag) {351 r = touchdeps(tp, ignore, silent);352 if (r)353 return r;354 }355356 for (i = 0; i < tp->nactions; i++) {357 struct action *p;358359 if (stop)360 cleanup(tp);361362 p = &tp->actions[i];363 debug("executing action '%s'", p->line);364 s = expandstring(p->line, tp, &p->loc);365 r = execline(tp, s, ignore, silent);366 free(s);367368 if (r)369 return r;370 }371372 if (tflag) {373 r = touch(tp->target, ignore, silent);374 if (r)375 return r;376 }377378 return 0;379}380381static int382enabled(char *suffix)383{384 Target **p, *tp = lookup(".SUFFIXES");385386 for (p = tp->deps; p && *p; ++p) {387 if (strcmp(suffix, (*p)->name) == 0)388 return 1;389 }390391 return 0;392}393394static Target *395inference(Target *tp, int force)396{397 time_t t;398 int tolen, r;399 char *to, *from;400 Target *q, **p, *suffixes;401 char buf[FILENAME_MAX], fname[FILENAME_MAX];402403 debug("searching an inference rule for %s", tp->name);404405 to = strrchr(tp->name, '.');406 if (to && !enabled(to))407 return NULL;408 tolen = to ? to - tp->name : strlen(tp->name);409410 if (!to)411 to = "";412413 suffixes = lookup(".SUFFIXES");414 for (p = suffixes->deps; p && *p; ++p) {415 from = (*p)->name;416 debug("trying suffix %s", from);417418 r = snprintf(buf,419 sizeof(buf),420 "%s%s",421 from, to);422423 if (r < 0 || r >= sizeof(buf))424 error("suffixes too long %s %s", from, to);425426 q = lookup(buf);427 if (!q->actions)428 continue;429430 r = snprintf(fname,431 sizeof(fname),432 "%*.*s%s",433 tolen, tolen, tp->name, from);434435 if (r < 0 || r >= sizeof(fname)) {436 error("prerequisite name too long %s %s",437 tp->name, from);438 }439440 debug("\tsearching prerequisite %s", fname);441442 t = stamp(fname);443 if (t == -1) {444 debug("\tprerequisite %s not found", fname);445 continue;446 }447448 if (!force && t <= tp->stamp) {449 debug("\tdiscarded because is newer");450 debug("\t%s: %s", tp->name, ctime(&tp->stamp));451 debug("\t%s: %s", fname, ctime(&t));452 continue;453 }454455 free(q->req);456 q->req = estrdup(fname);457 q->deps = tp->deps;458 q->target = tp->name;459 q->stamp = tp->stamp;460461 debug("using inference rule %s with %s", q->name, fname);462 return q;463 }464465 return NULL;466}467468static int469update(Target *tp)470{471 Target *p;472473 debug("%s needs to be updated", tp->name);474475 if (tp->actions) {476 debug("using target rule to build %s", tp->name);477 return run(tp);478 }479480 if ((p = inference(tp, FORCE)) != NULL) {481 debug("using inference rule %s", p->name);482 return run(p);483 }484485 p = lookup(".DEFAULT");486 if (p->defined) {487 debug("using default rule");488 return run(p);489 }490491 debug("not rule found to update %s", tp->name);492493 if (!tp->defined)494 error("don't know how to make %s", tp->name);495496 return 0;497}498499static int500rebuild(Target *tp, int *buildp)501{502 Target **p, *q;;503 int r, need, build, err, def;504505 debug("checking rebuild of %s", tp->name);506507 tp->stamp = stamp(tp->name);508509 def = err = need = 0;510 for (p = tp->deps; p && *p; ++p) {511 if (stop)512 cleanup(tp);513514 q = *p;515 debug("checking dependency %s", q->name);516517 if (strcmp(q->name, tp->name) == 0 && q->actions)518 def = 1;519520 build = 0;521 if (rebuild(q, &build) != 0) {522 err = 1;523 continue;524 }525526 if (build) {527 debug("rebuild of %s forces rebuild of %s",528 q->name, tp->name);529 need = 1;530 } else if (q->stamp > tp->stamp) {531 debug("dependency %s is newer than %s",532 q->name, tp->name);533 need = 1;534 }535 }536537 if (tp->stamp == -1) {538 need = 1;539 } else if (!def) {540 debug("no action found for %s, looking a inference rule",541 tp->name);542 if (inference(tp, NOFORCE))543 need = 1;544 }545546 if (err) {547 warning("target %s not remade because of errors", tp->name);548 return 1;549 } else if (need) {550 *buildp = 1;551552 debug("target %s needs updating", tp->name);553 r = update(tp);554 if (r == 0)555 return 0;556557 if (stop)558 cleanup(tp);559560 exitstatus = 1;561562 if (!kflag)563 error("target %s: error %d", tp->name, r);564 else565 warning("target %s: error %d", tp->name, r);566 return r;567 }568569 return 0;570}571572int573build(char *name)574{575 int build, r;576577 if (!name) {578 if (!deftarget) {579 printf("make: no target to make\n");580 return 0;581 }582 name = deftarget->name;583 }584585 debug("checking target %s", name);586587 build = 0;588 return rebuild(lookup(name), &build);589}