scc

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

rules.c (9699B)


      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 void
     63 cleanup(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 
     89 static int
     90 depends(char *dep, char *target)
     91 {
     92 
     93 	int i;
     94 	char *dname;
     95 	Target **p, *tp;
     96 
     97 	if (strcmp(target, dep) == 0)
     98 		return 1;
     99 
    100 	tp = lookup(dep);
    101 	for (p = tp->deps; p && *p; ++p) {
    102 		dname = (*p)->name;
    103 		if (depends(dname, target))
    104 			return 1;
    105 	}
    106 
    107 	return 0;
    108 }
    109 
    110 static int
    111 is_suffix(char *s)
    112 {
    113 	int n;
    114 
    115 	if (s[0] != '.')
    116 		return 0;
    117 
    118 	for (n = 0; s = strchr(s, '.'); n++)
    119 		s++;
    120 
    121 	return n == 2;
    122 }
    123 
    124 void
    125 addtarget(char *target, int ndeps)
    126 {
    127 	Target *tp = lookup(target);
    128 
    129 	tp->defined = 1;
    130 	if (!deftarget && target[0] != '.') {
    131 		deftarget = tp;
    132 		return;
    133 	}
    134 
    135 	if (strcmp(target, ".SUFFIXES") == 0 && ndeps == 0) {
    136 		free(tp->deps);
    137 		tp->deps = NULL;
    138 		tp->ndeps = 0;
    139 		return;
    140 	}
    141 
    142 	if (strcmp(target, ".DEFAULT") == 0) {
    143 		if (ndeps > 0)
    144 			error("DEFAULT rule with prerequisites");
    145 		return;
    146 	}
    147 
    148 	if (strcmp(target, ".SILENT") == 0 && ndeps == 0) {
    149 		sflag = 1;
    150 		return;
    151 	}
    152 
    153 	if (strcmp(target, ".IGNORE") == 0 && ndeps == 0) {
    154 		iflag = 1;
    155 		return;
    156 	}
    157 }
    158 
    159 void
    160 adddep(char *target, char *dep)
    161 {
    162 	int i;
    163 	size_t siz;
    164 	Target **p, *tp = lookup(target);
    165 
    166 	if (depends(dep, target)) {
    167 		warning("circular dependency %s <- %s dropped", target, dep);
    168 		return;
    169 	}
    170 
    171 	for (p = tp->deps; p && *p; ++p) {
    172 		if (strcmp((*p)->name, dep) == 0)
    173 			return;
    174 	}
    175 
    176 	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;
    181 
    182 	debug("adding dependency %s <- %s", target, dep);
    183 }
    184 
    185 static void
    186 freeaction(struct action *act)
    187 {
    188 	free(act->line);
    189 	freeloc(&act->loc);
    190 }
    191 
    192 void
    193 addrule(char *target, struct action  *acts, int n)
    194 {
    195 	int i;
    196 	struct action *v;
    197 	Target *tp = lookup(target);
    198 
    199 	debug("adding actions for target %s", target);
    200 
    201 	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 	}
    207 
    208 	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 	}
    214 
    215 	tp->nactions = n;
    216 	tp->actions = v;
    217 }
    218 
    219 static int
    220 execline(Target *tp, char *line, int ignore, int silence)
    221 {
    222 	char *s, *t;
    223 	Target *p, **q;
    224 	int r, at, plus, minus, l;
    225 
    226 	debug("executing '%s'", line);
    227 
    228 	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 	}
    244 
    245 out_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 	}
    253 
    254 	if (tflag && !plus)
    255 		return 0;
    256 
    257 	if (sflag || silence || (qflag && !plus))
    258 		at = 1;
    259 	if (nflag)
    260 		at = 0;
    261 	if (!at) {
    262 		puts(s);
    263 		fflush(stdout);
    264 	}
    265 
    266 	if ((nflag || qflag) && !plus) {
    267 		if (qflag)
    268 			exitstatus = 1;
    269 		return 0;
    270 	}
    271 
    272 	if (minus || iflag || ignore)
    273 		ignore = 1;
    274 
    275 	r = launch(s, ignore);
    276 	if (ignore)
    277 		return 0;
    278 
    279 	return r;
    280 }
    281 
    282 static int
    283 touch(char *name, int ignore, int silence)
    284 {
    285 	char *cmd;
    286 	int r, n;
    287 
    288 	n = snprintf(NULL, 0, "touch %s", name) + 1;
    289 	cmd = emalloc(n);
    290 	snprintf(cmd, n, "touch %s", name);
    291 
    292 	if (!sflag && !silence)
    293 		puts(cmd);
    294 
    295 	r = system(cmd);
    296 	free(cmd);
    297 
    298 	if (ignore || iflag)
    299 		return 0;
    300 
    301 	return r;
    302 }
    303 
    304 static int
    305 touchdeps(Target *tp, int ignore, int silent)
    306 {
    307 	int r;
    308 	Target **p;
    309 
    310 	if (tp->req) {
    311 		r = touch(tp->req, silent, ignore);
    312 		if (r)
    313 			return r;
    314 	}
    315 
    316 	for (p = tp->deps; p && *p; ++p) {
    317 		r = touch((*p)->name, silent, ignore);
    318 		if (r)
    319 			return r;
    320 	}
    321 
    322 	return 0;
    323 }
    324 
    325 static int
    326 run(Target *tp)
    327 {
    328 	int r, i, ignore, silent;
    329 	char *s;
    330 	Target *p, **q;
    331 
    332 	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 	}
    340 
    341 	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 	}
    349 
    350 	if (tflag) {
    351 		r = touchdeps(tp, ignore, silent);
    352 		if (r)
    353 			return r;
    354 	}
    355 
    356 	for (i = 0; i < tp->nactions; i++) {
    357 		struct action *p;
    358 
    359 		if (stop)
    360 			cleanup(tp);
    361 
    362 		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);
    367 
    368 		if (r)
    369 			return r;
    370 	}
    371 
    372 	if (tflag) {
    373 		r = touch(tp->target, ignore, silent);
    374 		if (r)
    375 			return r;
    376 	}
    377 
    378 	return 0;
    379 }
    380 
    381 static int
    382 enabled(char *suffix)
    383 {
    384 	Target **p, *tp = lookup(".SUFFIXES");
    385 
    386 	for (p = tp->deps; p && *p; ++p) {
    387 		if (strcmp(suffix, (*p)->name) == 0)
    388 			return 1;
    389 	}
    390 
    391 	return 0;
    392 }
    393 
    394 static Target *
    395 inference(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];
    402 
    403 	debug("searching an inference rule for %s", tp->name);
    404 
    405 	to = strrchr(tp->name, '.');
    406 	if (to && !enabled(to))
    407 		return NULL;
    408 	tolen = to ? to - tp->name : strlen(tp->name);
    409 
    410 	if (!to)
    411 		to = "";
    412 
    413 	suffixes = lookup(".SUFFIXES");
    414 	for (p = suffixes->deps; p && *p; ++p) {
    415 		from = (*p)->name;
    416 		debug("trying suffix %s", from);
    417 
    418 		r = snprintf(buf,
    419 		             sizeof(buf),
    420 		             "%s%s",
    421 		             from, to);
    422 
    423 		if (r < 0 || r >= sizeof(buf))
    424 			error("suffixes too long %s %s", from, to);
    425 
    426 		q = lookup(buf);
    427 		if (!q->actions)
    428 			continue;
    429 
    430 		r = snprintf(fname,
    431 		             sizeof(fname),
    432 		             "%*.*s%s",
    433 		             tolen, tolen, tp->name, from);
    434 
    435 		if (r < 0 || r >= sizeof(fname)) {
    436 			error("prerequisite name too long %s %s",
    437 			      tp->name, from);
    438 		}
    439 
    440 		debug("\tsearching prerequisite %s", fname);
    441 
    442 		t = stamp(fname);
    443 		if (t == -1) {
    444 			debug("\tprerequisite %s not found", fname);
    445 			continue;
    446 		}
    447 
    448 		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 		}
    454 
    455 		free(q->req);
    456 		q->req = estrdup(fname);
    457 		q->deps = tp->deps;
    458 		q->target = tp->name;
    459 		q->stamp = tp->stamp;
    460 
    461 		debug("using inference rule %s with %s", q->name, fname);
    462 		return q;
    463 	}
    464 
    465 	return NULL;
    466 }
    467 
    468 static int
    469 update(Target *tp)
    470 {
    471 	Target *p;
    472 
    473 	debug("%s needs to be updated", tp->name);
    474 
    475 	if (tp->actions) {
    476 		debug("using target rule to build %s", tp->name);
    477 		return run(tp);
    478 	}
    479 
    480 	if ((p = inference(tp, FORCE)) != NULL) {
    481 		debug("using inference rule %s", p->name);
    482 		return run(p);
    483 	}
    484 
    485 	p = lookup(".DEFAULT");
    486 	if (p->defined) {
    487 		debug("using default rule");
    488 		return run(p);
    489 	}
    490 
    491 	debug("not rule found to update %s", tp->name);
    492 
    493 	if (!tp->defined)
    494 		error("don't know how to make %s", tp->name);
    495 
    496 	return 0;
    497 }
    498 
    499 static int 
    500 rebuild(Target *tp, int *buildp)
    501 {
    502 	Target **p, *q;;
    503 	int r, need, build, err, def;
    504 
    505 	debug("checking rebuild of %s", tp->name);
    506 
    507 	tp->stamp = stamp(tp->name);
    508 
    509 	def = err = need = 0;
    510 	for (p = tp->deps; p && *p; ++p) {
    511 		if (stop)
    512 			cleanup(tp);
    513 
    514 		q = *p;
    515 		debug("checking dependency %s", q->name);
    516 
    517 		if (strcmp(q->name, tp->name) == 0 && q->actions)
    518 			def = 1;
    519 
    520 		build = 0;
    521 		if (rebuild(q, &build) != 0) {
    522 			err = 1;
    523 			continue;
    524 		}
    525 
    526 		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 	}
    536 
    537 	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 	}
    545 
    546 	if (err) {
    547 		warning("target %s not remade because of errors", tp->name);
    548 		return 1;
    549 	} else if (need) {
    550 		*buildp = 1;
    551 
    552 		debug("target %s needs updating", tp->name);
    553 		r = update(tp);
    554 		if (r == 0)
    555 			return 0;
    556 
    557 		if (stop)
    558 			cleanup(tp);
    559 
    560 		exitstatus = 1;
    561 
    562 		if (!kflag)
    563 			error("target %s: error %d", tp->name, r);
    564 		else
    565 			warning("target %s: error %d", tp->name, r);
    566 		return r;
    567 	}
    568 
    569 	return 0;
    570 }
    571 
    572 int
    573 build(char *name)
    574 {
    575 	int build, r;
    576 
    577 	if (!name) {
    578 		if (!deftarget) {
    579 			printf("make: no target to make\n");
    580 			return 0;
    581 		}
    582 		name = deftarget->name;
    583 	}
    584 
    585 	debug("checking target %s", name);
    586 
    587 	build = 0;
    588 	return rebuild(lookup(name), &build);
    589 }