scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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 *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
110static int
111is_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
124void
125addtarget(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
159void
160adddep(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
185static void
186freeaction(struct action *act)
187{
188	free(act->line);
189	freeloc(&act->loc);
190}
191
192void
193addrule(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
219static int
220execline(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
245out_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
282static int
283touch(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
304static int
305touchdeps(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
325static int
326run(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
381static int
382enabled(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
394static Target *
395inference(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
468static int
469update(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
499static int 
500rebuild(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
572int
573build(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}