rules.c - scc - simple c99 compiler
HTML git clone git://git.simple-cc.org/scc
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
rules.c (9699B)
---
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 *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
110 static int
111 is_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
124 void
125 addtarget(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
159 void
160 adddep(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
185 static void
186 freeaction(struct action *act)
187 {
188 free(act->line);
189 freeloc(&act->loc);
190 }
191
192 void
193 addrule(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
219 static int
220 execline(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
245 out_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
282 static int
283 touch(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
304 static int
305 touchdeps(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
325 static int
326 run(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
381 static int
382 enabled(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
394 static Target *
395 inference(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
468 static int
469 update(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
499 static int
500 rebuild(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
572 int
573 build(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 }