Blob


1 #include "mk.h"
3 int runerrs;
5 void
6 mk(char *target)
7 {
8 Node *node;
9 int did = 0;
11 nproc(); /* it can be updated dynamically */
12 nrep(); /* it can be updated dynamically */
13 runerrs = 0;
14 node = graph(target);
15 if(DEBUG(D_GRAPH)){
16 dumpn("new target\n", node);
17 Bflush(&bout);
18 }
19 clrmade(node);
20 while(node->flags&NOTMADE){
21 if(work(node, (Node *)0, (Arc *)0))
22 did = 1; /* found something to do */
23 else {
24 if(waitup(1, (int *)0) > 0){
25 if(node->flags&(NOTMADE|BEINGMADE)){
26 assert("must be run errors", runerrs);
27 break; /* nothing more waiting */
28 }
29 }
30 }
31 }
32 if(node->flags&BEINGMADE)
33 waitup(-1, (int *)0);
34 while(jobs)
35 waitup(-2, (int *)0);
36 assert("target didn't get done", runerrs || (node->flags&MADE));
37 if(did == 0)
38 Bprint(&bout, "mk: '%s' is up to date\n", node->name);
39 }
41 void
42 clrmade(Node *n)
43 {
44 Arc *a;
46 n->flags &= ~(CANPRETEND|PRETENDING);
47 if(strchr(n->name, '(') ==0 || n->time)
48 n->flags |= CANPRETEND;
49 MADESET(n, NOTMADE);
50 for(a = n->prereqs; a; a = a->next)
51 if(a->n)
52 clrmade(a->n);
53 }
55 static void
56 unpretend(Node *n)
57 {
58 MADESET(n, NOTMADE);
59 n->flags &= ~(CANPRETEND|PRETENDING);
60 n->time = 0;
61 }
63 static char*
64 dir(void)
65 {
66 static char buf[1024];
68 return getcwd(buf, sizeof buf);
69 }
71 int
72 work(Node *node, Node *p, Arc *parc)
73 {
74 Arc *a, *ra;
75 int weoutofdate;
76 int ready;
77 int did = 0;
79 /*print("work(%s) flags=0x%x time=%ld\n", node->name, node->flags, node->time); */
80 if(node->flags&BEINGMADE)
81 return(did);
82 if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){
83 if(explain)
84 fprint(1, "unpretending %s(%ld) because %s is out of date(%ld)\n",
85 node->name, node->time, p->name, p->time);
86 unpretend(node);
87 }
88 /*
89 have a look if we are pretending in case
90 someone has been unpretended out from underneath us
91 */
92 if(node->flags&MADE){
93 if(node->flags&PRETENDING){
94 node->time = 0;
95 }else
96 return(did);
97 }
98 /* consider no prerequsite case */
99 if(node->prereqs == 0){
100 if(node->time == 0){
101 fprint(2, "mk: don't know how to make '%s' in %s\n", node->name, dir());
102 if(kflag){
103 node->flags |= BEINGMADE;
104 runerrs++;
105 } else
106 Exit();
107 } else
108 MADESET(node, MADE);
109 return(did);
111 /*
112 now see if we are out of date or what
113 */
114 ready = 1;
115 weoutofdate = aflag;
116 ra = 0;
117 for(a = node->prereqs; a; a = a->next)
118 if(a->n){
119 did = work(a->n, node, a) || did;
120 if(a->n->flags&(NOTMADE|BEINGMADE))
121 ready = 0;
122 if(outofdate(node, a, 0)){
123 weoutofdate = 1;
124 if((ra == 0) || (ra->n == 0)
125 || (ra->n->time < a->n->time))
126 ra = a;
128 } else {
129 if(node->time == 0){
130 if(ra == 0)
131 ra = a;
132 weoutofdate = 1;
135 if(ready == 0) /* can't do anything now */
136 return(did);
137 if(weoutofdate == 0){
138 MADESET(node, MADE);
139 return(did);
141 /*
142 can we pretend to be made?
143 */
144 if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND))
145 && p && ra->n && !outofdate(p, ra, 0)){
146 node->flags &= ~CANPRETEND;
147 MADESET(node, MADE);
148 if(explain && ((node->flags&PRETENDING) == 0))
149 fprint(1, "pretending %s has time %ld\n", node->name, node->time);
150 node->flags |= PRETENDING;
151 return(did);
153 /*
154 node is out of date and we REALLY do have to do something.
155 quickly rescan for pretenders
156 */
157 for(a = node->prereqs; a; a = a->next)
158 if(a->n && (a->n->flags&PRETENDING)){
159 if(explain)
160 Bprint(&bout, "unpretending %s because of %s because of %s\n",
161 a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites");
163 unpretend(a->n);
164 did = work(a->n, node, a) || did;
165 ready = 0;
167 if(ready == 0) /* try later unless nothing has happened for -k's sake */
168 return(did || work(node, p, parc));
169 did = dorecipe(node) || did;
170 return(did);
173 void
174 update(int fake, Node *node)
176 Arc *a;
178 MADESET(node, fake? BEINGMADE : MADE);
179 if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){
180 node->time = timeof(node->name, 1);
181 node->flags &= ~(CANPRETEND|PRETENDING);
182 for(a = node->prereqs; a; a = a->next)
183 if(a->prog)
184 outofdate(node, a, 1);
185 } else {
186 node->time = 1;
187 for(a = node->prereqs; a; a = a->next)
188 if(a->n && outofdate(node, a, 1))
189 node->time = a->n->time;
191 /* print("----node %s time=%ld flags=0x%x\n", node->name, node->time, node->flags);*/
194 static int
195 pcmp(char *prog, char *p, char *q, Shell *sh, Word *shcmd)
197 char buf[3*NAMEBLOCK];
198 int pid;
200 Bflush(&bout);
201 snprint(buf, sizeof buf, "%s '%s' '%s'\n", prog, p, q);
202 pid = pipecmd(buf, envy, 0, sh, shcmd);
203 while(waitup(-3, &pid) >= 0)
205 return(pid? 2:1);
208 int
209 outofdate(Node *node, Arc *arc, int eval)
211 char buf[3*NAMEBLOCK], *str;
212 Symtab *sym;
213 int ret;
215 str = 0;
216 if(arc->prog){
217 snprint(buf, sizeof buf, "%s%c%s", node->name, 0377, arc->n->name);
218 sym = symlook(buf, S_OUTOFDATE, 0);
219 if(sym == 0 || eval){
220 if(sym == 0)
221 str = strdup(buf);
222 ret = pcmp(arc->prog, node->name, arc->n->name, arc->r->shellt, arc->r->shellcmd);
223 if(sym)
224 sym->u.value = ret;
225 else
226 symlook(str, S_OUTOFDATE, (void *)(uintptr)ret);
227 } else
228 ret = sym->u.value;
229 return(ret-1);
230 } else if(strchr(arc->n->name, '(') && arc->n->time == 0) /* missing archive member */
231 return 1;
232 else
233 return node->time <= arc->n->time;