scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

rules.c (9434B)


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