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