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