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