1 #include "mk.h"
2
3 int runerrs;
4
5 void
mk(char * target)6 mk(char *target)
7 {
8 Node *node;
9 int did = 0;
10
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 didnt get done*/ runerrs || (node->flags&MADE));
37 if(did == 0)
38 Bprint(&bout, "mk: '%s' is up to date\n", node->name);
39 }
40
41 void
clrmade(Node * n)42 clrmade(Node *n)
43 {
44 Arc *a;
45
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 }
54
55 static void
unpretend(Node * n)56 unpretend(Node *n)
57 {
58 MADESET(n, NOTMADE);
59 n->flags &= ~(CANPRETEND|PRETENDING);
60 n->time = 0;
61 }
62
63 int
work(Node * node,Node * p,Arc * parc)64 work(Node *node, Node *p, Arc *parc)
65 {
66 Arc *a, *ra;
67 int weoutofdate;
68 int ready;
69 int did = 0;
70 char cwd[256];
71
72 /*print("work(%s) flags=0x%x time=%lud\n", node->name, node->flags, node->time);/**/
73 if(node->flags&BEINGMADE)
74 return(did);
75 if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){
76 if(explain)
77 fprint(1, "unpretending %s(%lud) because %s is out of date(%lud)\n",
78 node->name, node->time, p->name, p->time);
79 unpretend(node);
80 }
81 /*
82 have a look if we are pretending in case
83 someone has been unpretended out from underneath us
84 */
85 if(node->flags&MADE){
86 if(node->flags&PRETENDING){
87 node->time = 0;
88 }else
89 return(did);
90 }
91 /* consider no prerequisite case */
92 if(node->prereqs == 0){
93 if(node->time == 0){
94 if(getwd(cwd, sizeof cwd))
95 fprint(2, "mk: don't know how to make '%s' in directory %s\n", node->name, cwd);
96 else
97 fprint(2, "mk: don't know how to make '%s'\n", node->name);
98 if(kflag){
99 node->flags |= BEINGMADE;
100 runerrs++;
101 } else
102 Exit();
103 } else
104 MADESET(node, MADE);
105 return(did);
106 }
107 /*
108 now see if we are out of date or what
109 */
110 ready = 1;
111 weoutofdate = aflag;
112 ra = 0;
113 for(a = node->prereqs; a; a = a->next)
114 if(a->n){
115 did = work(a->n, node, a) || did;
116 if(a->n->flags&(NOTMADE|BEINGMADE))
117 ready = 0;
118 if(outofdate(node, a, 0)){
119 weoutofdate = 1;
120 if((ra == 0) || (ra->n == 0)
121 || (ra->n->time < a->n->time))
122 ra = a;
123 }
124 } else {
125 if(node->time == 0){
126 if(ra == 0)
127 ra = a;
128 weoutofdate = 1;
129 }
130 }
131 if(ready == 0) /* can't do anything now */
132 return(did);
133 if(weoutofdate == 0){
134 MADESET(node, MADE);
135 return(did);
136 }
137 /*
138 can we pretend to be made?
139 */
140 if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND))
141 && p && ra->n && !outofdate(p, ra, 0)){
142 node->flags &= ~CANPRETEND;
143 MADESET(node, MADE);
144 if(explain && ((node->flags&PRETENDING) == 0))
145 fprint(1, "pretending %s has time %lud\n", node->name, node->time);
146 node->flags |= PRETENDING;
147 return(did);
148 }
149 /*
150 node is out of date and we REALLY do have to do something.
151 quickly rescan for pretenders
152 */
153 for(a = node->prereqs; a; a = a->next)
154 if(a->n && (a->n->flags&PRETENDING)){
155 if(explain)
156 Bprint(&bout, "unpretending %s because of %s because of %s\n",
157 a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites");
158
159 unpretend(a->n);
160 did = work(a->n, node, a) || did;
161 ready = 0;
162 }
163 if(ready == 0) /* try later unless nothing has happened for -k's sake */
164 return(did || work(node, p, parc));
165 did = dorecipe(node) || did;
166 return(did);
167 }
168
169 void
update(int fake,Node * node)170 update(int fake, Node *node)
171 {
172 Arc *a;
173
174 MADESET(node, fake? BEINGMADE : MADE);
175 if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){
176 node->time = timeof(node->name, 1);
177 node->flags &= ~(CANPRETEND|PRETENDING);
178 for(a = node->prereqs; a; a = a->next)
179 if(a->prog)
180 outofdate(node, a, 1);
181 } else {
182 node->time = 1;
183 for(a = node->prereqs; a; a = a->next)
184 if(a->n && outofdate(node, a, 1))
185 node->time = a->n->time;
186 }
187 /* print("----node %s time=%lud flags=0x%x\n", node->name, node->time, node->flags);/**/
188 }
189
190 static
pcmp(char * prog,char * p,char * q)191 pcmp(char *prog, char *p, char *q)
192 {
193 char buf[3*NAMEBLOCK];
194 int pid;
195
196 Bflush(&bout);
197 snprint(buf, sizeof buf, "%s '%s' '%s'\n", prog, p, q);
198 pid = pipecmd(buf, 0, 0);
199 while(waitup(-3, &pid) >= 0)
200 ;
201 return(pid? 2:1);
202 }
203
204 int
outofdate(Node * node,Arc * arc,int eval)205 outofdate(Node *node, Arc *arc, int eval)
206 {
207 char buf[3*NAMEBLOCK], *str;
208 Symtab *sym;
209 int ret;
210
211 str = 0;
212 if(arc->prog){
213 snprint(buf, sizeof buf, "%s%c%s", node->name, 0377,
214 arc->n->name);
215 sym = symlook(buf, S_OUTOFDATE, 0);
216 if(sym == 0 || eval){
217 if(sym == 0)
218 str = strdup(buf);
219 ret = pcmp(arc->prog, node->name, arc->n->name);
220 if(sym)
221 sym->u.value = ret;
222 else
223 symlook(str, S_OUTOFDATE, (void *)ret);
224 } else
225 ret = sym->u.value;
226 return(ret-1);
227 } else if(strchr(arc->n->name, '(') && arc->n->time == 0) /* missing archive member */
228 return 1;
229 else
230 /*
231 * Treat equal times as out-of-date.
232 * It's a race, and the safer option is to do
233 * extra building rather than not enough.
234 */
235 return node->time <= arc->n->time;
236 }
237