scc

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

rules.c (9625B)


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