scc

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

rules.c (8968B)


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