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 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 }
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 static char*
dir(void)64 dir(void)
65 {
66 	static char buf[1024];
67 
68 	return getcwd(buf, sizeof buf);
69 }
70 
71 int
work(Node * node,Node * p,Arc * parc)72 work(Node *node, Node *p, Arc *parc)
73 {
74 	Arc *a, *ra;
75 	int weoutofdate;
76 	int ready;
77 	int did = 0;
78 
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);
110 	}
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;
127 			}
128 		} else {
129 			if(node->time == 0){
130 				if(ra == 0)
131 					ra = a;
132 				weoutofdate = 1;
133 			}
134 		}
135 	if(ready == 0)	/* can't do anything now */
136 		return(did);
137 	if(weoutofdate == 0){
138 		MADESET(node, MADE);
139 		return(did);
140 	}
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);
152 	}
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");
162 
163 			unpretend(a->n);
164 			did = work(a->n, node, a) || did;
165 			ready = 0;
166 		}
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);
171 }
172 
173 void
update(int fake,Node * node)174 update(int fake, Node *node)
175 {
176 	Arc *a;
177 
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;
190 	}
191 /*	print("----node %s time=%ld flags=0x%x\n", node->name, node->time, node->flags);*/
192 }
193 
194 static int
pcmp(char * prog,char * p,char * q,Shell * sh,Word * shcmd)195 pcmp(char *prog, char *p, char *q, Shell *sh, Word *shcmd)
196 {
197 	char buf[3*NAMEBLOCK];
198 	int pid;
199 
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)
204 		;
205 	return(pid? 2:1);
206 }
207 
208 int
outofdate(Node * node,Arc * arc,int eval)209 outofdate(Node *node, Arc *arc, int eval)
210 {
211 	char buf[3*NAMEBLOCK], *str;
212 	Symtab *sym;
213 	int ret;
214 
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;
234 }
235