|
|
1.1 root 1: #include "mk.h"
2:
3: static Node *newnode(), *applyrules();
4: static cyclechk(), vacuous(), ambiguous(), attribute();
5:
6: Node *
7: graph(target)
8: char *target;
9: {
10: Node *node;
11: char *cnt;
12:
13: node = applyrules(target, cnt = rulecnt());
14: free(cnt);
15: cyclechk(node);
16: node->flags |= PROBABLE; /* make sure it doesn't get deleted */
17: (void)vacuous(node);
18: (void)ambiguous(node);
19: (void)attribute(node);
20: return(node);
21: }
22:
23: static Node *
24: applyrules(target, cnt)
25: char *target, *cnt;
26: {
27: Symtab *sym;
28: Node *node;
29: Rule *r;
30: Arc head, *a = &head;
31: Word *w;
32: char stem[NAMEBLOCK], buf[NAMEBLOCK];
33: regsubexp rmatch[NREGEXP];
34:
35: /* print("appplyrules(%ld='%s')\n", target, target);/**/
36: if(sym = symlook(target, S_NODE, (char *)0)){
37: node = (Node *)(sym->value);
38: return(node);
39: }
40: target = strdup(target);
41: node = newnode(target);
42: head.n = 0;
43: head.next = 0;
44: sym = symlook(target, S_TARGET, (char *)0);
45: for(r = sym? (Rule *)(sym->value):0; r; r = r->chain){
46: if(r->attr&META) continue;
47: if(strcmp(target, r->target)) continue;
48: if(cnt[r->rule] >= nreps) continue;
49: cnt[r->rule]++;
50: node->flags |= PROBABLE;
51: if(r->attr&VIR)
52: node->flags |= VIRTUAL;
53: if(r->attr&NOREC)
54: node->flags |= NORECIPE;
55: if(r->attr&DEL)
56: node->flags |= DELETE;
57: if(r->tail == 0)
58: a = a->next = newarc((Node *)0, r, "", rmatch);
59: else
60: for(w = r->tail; w; w = w->next){
61: a = a->next = newarc(applyrules(w->s, cnt), r, "", rmatch);
62: }
63: cnt[r->rule]--;
64: head.n = node;
65: }
66: for(r = metarules; r; r = r->next){
67: if(r->attr®EXP){
68: stem[0] = 0;
69: patrule = r;
70: if(regexec(r->pat, node->name, rmatch, NREGEXP) == 0)
71: continue;
72: } else {
73: if(!match(node->name, r->target, stem)) continue;
74: }
75: if(cnt[r->rule] >= nreps) continue;
76: cnt[r->rule]++;
77: if(r->attr&VIR)
78: node->flags |= VIRTUAL;
79: if(r->attr&NOREC)
80: node->flags |= NORECIPE;
81: if(r->attr&DEL)
82: node->flags |= DELETE;
83: if(r->tail == 0)
84: a = a->next = newarc((Node *)0, r, strdup(stem), rmatch);
85: else
86: for(w = r->tail; w; w = w->next){
87: if(r->attr®EXP)
88: regsub(w->s, buf, rmatch, NREGEXP);
89: else
90: subst(stem, w->s, buf);
91: a = a->next = newarc(applyrules(buf, cnt), r, strdup(stem), rmatch);
92: }
93: cnt[r->rule]--;
94: }
95: a->next = node->prereqs;
96: node->prereqs = head.next;
97: return(node);
98: }
99:
100: static
101: togo(node)
102: register Node *node;
103: {
104: register Arc *la, *a;
105:
106: /* delete them now */
107: for(a = node->prereqs; a; la = a, a = a->next)
108: if(a->flag&TOGO){
109: if(a == node->prereqs)
110: node->prereqs = a->next;
111: else
112: la->next = a->next, a = la;
113: }
114: }
115:
116: static
117: vacuous(node)
118: register Node *node;
119: {
120: register Arc *la, *a;
121: int vac = !(node->flags&PROBABLE);
122:
123: if(node->flags&READY)
124: return(node->flags&VACUOUS);
125: node->flags |= READY;
126: for(a = node->prereqs; a; a = a->next)
127: if(a->n && vacuous(a->n) && (a->r->attr&META))
128: a->flag |= TOGO;
129: else
130: vac = 0;
131: /* if a rule generated arcs that DON'T go; no others from that rule go */
132: for(a = node->prereqs; a; a = a->next)
133: if((a->flag&TOGO) == 0)
134: for(la = node->prereqs; la; la = la->next)
135: if((la->flag&TOGO) && (la->r == a->r)){
136: la->flag &= ~TOGO;
137: }
138: togo(node);
139: if(vac)
140: node->flags |= VACUOUS;
141: return(vac);
142: }
143:
144: static Node *
145: newnode(name)
146: char *name;
147: {
148: register Node *node;
149:
150: node = (Node *)Malloc(sizeof(Node));
151: symlook(name, S_NODE, (char *)node);
152: node->name = name;
153: node->time = timeof(name, 0);
154: node->prereqs = 0;
155: node->flags = node->time? PROBABLE : 0;
156: node->next = 0;
157: return(node);
158: }
159:
160: dumpn(s, n)
161: char *s;
162: register Node *n;
163: {
164: char buf[1024];
165: register Arc *a;
166:
167: sprint(buf, "%s ", (*s == ' ')? s:"");
168: Fprint(1, "%s%s@%ld: time=%ld flags=0x%x next=%ld\n",
169: s, n->name, n, n->time, n->flags, n->next);
170: for(a = n->prereqs; a; a = a->next)
171: dumpa(buf, a);
172: }
173:
174: static
175: trace(s, a)
176: char *s;
177: register Arc *a;
178: {
179: Fprint(2, "\t%s", s);
180: while(a){
181: Fprint(2, " <-(%s:%d)- %s", a->r->file, a->r->line,
182: a->n? a->n->name:"");
183: if(a->n){
184: for(a = a->n->prereqs; a; a = a->next)
185: if(*a->r->recipe) break;
186: } else
187: a = 0;
188: }
189: Fputc(2, '\n');
190: }
191:
192: static
193: cyclechk(n)
194: register Node *n;
195: {
196: register Arc *a;
197:
198: if((n->flags&CYCLE) && n->prereqs){
199: Fprint(2, "mk: cycle in graph detected at target %s\n", n->name);
200: Exit();
201: }
202: n->flags |= CYCLE;
203: for(a = n->prereqs; a; a = a->next)
204: if(a->n)
205: cyclechk(a->n);
206: n->flags &= ~CYCLE;
207: }
208:
209: static
210: ambiguous(n)
211: register Node *n;
212: {
213: register Arc *a;
214: register Rule *r = 0;
215: Arc *la;
216: int bad = 0;
217:
218: for(a = n->prereqs; a; a = a->next){
219: if(a->n)
220: ambiguous(a->n);
221: if(*a->r->recipe == 0) continue;
222: if(r == 0)
223: r = a->r, la = a;
224: else{
225: if(r->recipe != a->r->recipe){
226: if((r->attr&META) && !(a->r->attr&META)){
227: la->flag |= TOGO;
228: r = a->r, la = a;
229: } else if(!(r->attr&META) && (a->r->attr&META)){
230: a->flag |= TOGO;
231: continue;
232: }
233: }
234: if(r->recipe != a->r->recipe){
235: if(bad == 0){
236: Fprint(2, "mk: ambiguous recipes for %s:\n", n->name);
237: bad = 1;
238: trace(n->name, la);
239: }
240: trace(n->name, a);
241: }
242: }
243: }
244: if(bad)
245: Exit();
246: togo(n);
247: }
248:
249: static
250: attribute(n)
251: register Node *n;
252: {
253: register Arc *a;
254:
255: for(a = n->prereqs; a; a = a->next){
256: if(a->r->attr&VIR)
257: n->flags |= VIRTUAL;
258: if(a->r->attr&NOREC)
259: n->flags |= NORECIPE;
260: if(a->r->attr&DEL)
261: n->flags |= DELETE;
262: if(a->n)
263: attribute(a->n);
264: }
265: if(n->flags&VIRTUAL)
266: n->time = 0;
267: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.