scc

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

rules.c (8472B)


      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]);
     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 void
    142 addrule(char *target, char **actions, int n)
    143 {
    144 	int i;
    145 	char **v;
    146 	Target *tp = lookup(target);
    147 
    148 	debug("adding actions for target %s", target);
    149 
    150 	if (tp->actions) {
    151 		debug("overring actions of target %s", target);
    152 		for (i = 0; i < tp->nactions; i++)
    153 			free(tp->actions[i]);
    154 		free(tp->actions);
    155 	}
    156 
    157 	v = emalloc(n * sizeof(char *));
    158 	for (i = 0; i < n; i++)
    159 		v[i] = estrdup(actions[i]);
    160 
    161 	tp->nactions = n;
    162 	tp->actions = v;
    163 }
    164 
    165 static int
    166 execline(Target *tp, char *line, int ignore, int silence)
    167 {
    168 	char *s;
    169 	Target *p, **q;
    170 	int r, at, plus, minus;
    171 
    172 	debug("executing '%s'", line);
    173 
    174 	at = plus = minus = 0;
    175 	for (s = line; ; s++) {
    176 		switch (*s) {
    177 		case '@':
    178 			at = 1;
    179 			break;
    180 		case '-':
    181 			minus = 1;
    182 			break;
    183 		case '+':
    184 			plus = 1;
    185 			break;
    186 		default:
    187 			goto out_loop;
    188 		}
    189 	}
    190 
    191 out_loop:
    192 	if (tflag && !plus)
    193 		return 0;
    194 
    195 	if (sflag || silence || (qflag && !plus))
    196 		at = 1;
    197 	if (nflag)
    198 		at = 0;
    199 	if (!at) {
    200 		puts(s);
    201 		fflush(stdout);
    202 	}
    203 
    204 	if ((nflag || qflag) && !plus) {
    205 		if (qflag)
    206 			exitstatus = 1;
    207 		return 0;
    208 	}
    209 
    210 	if (minus || iflag || ignore)
    211 		ignore = 1;
    212 
    213 	r = launch(s, ignore);
    214 	if (ignore)
    215 		return 0;
    216 
    217 	return r;
    218 }
    219 
    220 static int
    221 touch(char *name, int ignore, int silence)
    222 {
    223 	char *cmd;
    224 	int r, n;
    225 
    226 	n = snprintf(NULL, 0, "touch %s", name) + 1;
    227 	cmd = emalloc(n);
    228 	snprintf(cmd, n, "touch %s", name);
    229 
    230 	if (!sflag && !silence)
    231 		puts(cmd);
    232 
    233 	r = system(cmd);
    234 	free(cmd);
    235 
    236 	if (ignore || iflag)
    237 		return 0;
    238 
    239 	return r;
    240 }
    241 
    242 static int
    243 touchdeps(Target *tp, int ignore, int silent)
    244 {
    245 	int r;
    246 	Target **p;
    247 
    248 	if (tp->req) {
    249 		r = touch(tp->req, silent, ignore);
    250 		if (r)
    251 			return r;
    252 	}
    253 
    254 	for (p = tp->deps; p && *p; ++p) {
    255 		r = touch((*p)->name, silent, ignore);
    256 		if (r)
    257 			return r;
    258 	}
    259 
    260 	return 0;
    261 }
    262 
    263 static int
    264 run(Target *tp)
    265 {
    266 	int r, i, ignore, silent;
    267 	char *s;
    268 	Target *p, **q;
    269 
    270 	silent = 0;
    271 	p = lookup(".SILENT");
    272 	for (q = p->deps; q && *q; ++q) {
    273 		if (strcmp((*q)->name, tp->name) == 0) {
    274 			debug("target %s error silent by .SILENT", tp->name);
    275 			silent = 1;
    276 		}
    277 	}
    278 
    279 	ignore = 0;
    280 	p = lookup(".IGNORE");
    281 	for (q = p->deps; q && *q; ++q) {
    282 		if (strcmp((*q)->name, tp->name) == 0) {
    283 			debug("target %s error ignored by .IGNORE", tp->name);
    284 			ignore = 1;
    285 		}
    286 	}
    287 
    288 	if (tflag) {
    289 		r = touchdeps(tp, ignore, silent);
    290 		if (r)
    291 			return r;
    292 	}
    293 
    294 	for (i = 0; i < tp->nactions; i++) {
    295 		s = expandstring(tp->actions[i], tp);
    296 		r = execline(tp, s, ignore, silent);
    297 		free(s);
    298 
    299 		if (r)
    300 			return r;
    301 	}
    302 
    303 	if (tflag) {
    304 		r = touch(tp->target, ignore, silent);
    305 		if (r)
    306 			return r;
    307 	}
    308 
    309 	return 0;
    310 }
    311 
    312 static int
    313 enabled(char *suffix)
    314 {
    315 	Target **p, *tp = lookup(".SUFFIXES");
    316 
    317 	for (p = tp->deps; p && *p; ++p) {
    318 		if (strcmp(suffix, (*p)->name) == 0)
    319 			return 1;
    320 	}
    321 
    322 	return 0;
    323 }
    324 
    325 static Target *
    326 inference(Target *tp)
    327 {
    328 	time_t t;
    329 	int tolen, r;
    330 	char *to, *from;
    331 	Target *q, **p, *suffixes;
    332 	char buf[20], fname[FILENAME_MAX];
    333 
    334 	debug("searching an inference rule for %s", tp->name);
    335 
    336 	to = strrchr(tp->name, '.');
    337 	if (to && !enabled(to))
    338 		return NULL;
    339 	tolen = to ? to - tp->name : strlen(tp->name);
    340 
    341 	if (!to)
    342 		to = "";
    343 
    344 	suffixes = lookup(".SUFFIXES");
    345 	for (p = suffixes->deps; p && *p; ++p) {
    346 		from = (*p)->name;
    347 		debug("trying suffix %s", from);
    348 
    349 		r = snprintf(buf,
    350 		             sizeof(buf),
    351 		             "%s%s",
    352 		             from, to);
    353 
    354 		if (r < 0 || r >= sizeof(buf))
    355 			error("suffixes too long %s %s", from, to);
    356 
    357 		q = lookup(buf);
    358 		if (!q->actions)
    359 			continue;
    360 
    361 		r = snprintf(fname,
    362 		             sizeof(fname),
    363 		             "%*.*s%s",
    364 		             tolen, tolen, tp->name, from);
    365 
    366 		if (r < 0 || r >= sizeof(fname)) {
    367 			error("prerequisite name too long %s %s",
    368 			      tp->name, from);
    369 		}
    370 
    371 		debug("\tsearching prerequisite %s", fname);
    372 
    373 		t = stamp(fname);
    374 		if (t == -1 || t <= tp->stamp)
    375 			continue;
    376 
    377 		free(q->req);
    378 		q->req = estrdup(fname);
    379 		q->deps = tp->deps;
    380 		q->target = tp->name;
    381 		q->stamp = tp->stamp;
    382 
    383 		debug("using inference rule %s with %s", q->name, fname);
    384 		return q;
    385 	}
    386 
    387 	return NULL;
    388 }
    389 
    390 static int
    391 update(Target *tp)
    392 {
    393 	Target *p;
    394 
    395 	debug("%s needs to be updated", tp->name);
    396 
    397 	if (tp->actions) {
    398 		debug("using target rule to build %s", tp->name);
    399 		return run(tp);
    400 	}
    401 
    402 	if ((p = inference(tp)) != NULL) {
    403 		debug("using inference rule %s", p->name);
    404 		return run(p);
    405 	}
    406 
    407 	p = lookup(".DEFAULT");
    408 	if (p->defined) {
    409 		debug("using default rule");
    410 		return run(p);
    411 	}
    412 
    413 	debug("not rule found to update %s", tp->name);
    414 
    415 	if (!tp->defined)
    416 		error("don't know how to make %s", tp->name);
    417 
    418 	return 0;
    419 }
    420 
    421 static int
    422 cleanup(Target *tp)
    423 {
    424 	int precious;
    425 	Target *p, **q;
    426 
    427 	printf("make: signal %d arrived\n", stop);
    428 
    429 	precious = 0;
    430 	p = lookup(".PRECIOUS");
    431 	for (q = p->deps; q && *q; q++) {
    432 		if (strcmp((*q)->name, tp->name) == 0) {
    433 			precious = 1;
    434 			break;
    435 		}
    436 	}
    437 
    438 	if (!precious) {
    439 		printf("make: trying to remove target %s\n", tp->name);
    440 		remove(tp->name);
    441 	}
    442 
    443 	signal(stop, SIG_DFL);
    444 	raise(stop);
    445 }
    446 
    447 static int 
    448 rebuild(Target *tp, int *buildp)
    449 {
    450 	Target **p, *q;;
    451 	int r, need, build, err;
    452 
    453 	debug("checking rebuild of %s", tp->name);
    454 
    455 	tp->stamp = stamp(tp->name);
    456 
    457 	err = need = 0;
    458 	for (p = tp->deps; p && *p; ++p) {
    459 		if (stop)
    460 			cleanup(tp);
    461 
    462 		q = *p;
    463 		debug("checking dependency %s", q->name);
    464 
    465 		build = 0;
    466 		if (rebuild(q, &build) != 0) {
    467 			err = 1;
    468 			continue;
    469 		}
    470 
    471 		if (build) {
    472 			debug("rebuild of %s forces rebuild of %s",
    473 			       q->name, tp->name);
    474 			need = 1;
    475 		} else if (q->stamp > tp->stamp) {
    476 			debug("dependency %s is newer than %s",
    477 			      q->name, tp->name);
    478 			need = 1;
    479 		}
    480 	}
    481 
    482 	if (tp->stamp == -1)
    483 		need = 1;
    484 
    485 	if (err) {
    486 		warning("target %s not remade because of errors", tp->name);
    487 		return 1;
    488 	} else if (need) {
    489 		*buildp = 1;
    490 
    491 		r = update(tp);
    492 		if (r == 0)
    493 			return 0;
    494 
    495 		if (stop)
    496 			cleanup(tp);
    497 
    498 		exitstatus = 1;
    499 
    500 		if (!kflag)
    501 			error("target %s: error %d", tp->name, r);
    502 		else
    503 			warning("target %s: error %d", tp->name, r);
    504 		return r;
    505 	}
    506 
    507 	return 0;
    508 }
    509 
    510 int
    511 build(char *name)
    512 {
    513 	int build, r;;
    514 
    515 	if (!name) {
    516 		if (!deftarget) {
    517 			printf("make: no target to make\n");
    518 			return 0;
    519 		}
    520 		name = deftarget->name;
    521 	}
    522 
    523 	debug("checking target %s", name);
    524 
    525 	build = 0;
    526 	return  rebuild(lookup(name), &build);
    527 }