xref: /plan9/sys/src/ape/cmd/make/doname.c (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
1 #include "defs.h"
2 
3 static int docom1(char *, int, int, int, int);
4 static void expand(depblkp);
5 
6 /*  BASIC PROCEDURE.  RECURSIVE.  */
7 
8 /*
9 p->done = 0   don't know what to do yet
10 p->done = 1   file in process of being updated
11 p->done = 2   file already exists in current state
12 p->done = 3   file make failed
13 */
14 
15 int
doname(nameblkp p,int reclevel,time_t * tval,int nowait)16 doname(nameblkp p, int reclevel, time_t *tval, int nowait)
17 {
18 int errstat;
19 int okdel1;
20 int didwork;
21 int len;
22 time_t td, td1, tdep, ptime, ptime1;
23 depblkp q;
24 depblkp qtemp, suffp, suffp1;
25 nameblkp p1, p2;
26 struct shblock *implcom, *explcom;
27 lineblkp lp;
28 lineblkp lp1, lp2;
29 char sourcename[100], prefix[100], temp[100], concsuff[20];
30 char *stem;
31 char *pnamep, *p1namep;
32 chainp allchain, qchain;
33 char qbuf[QBUFMAX], tgsbuf[QBUFMAX];
34 wildp wp;
35 int nproc1;
36 char *lastslash, *s;
37 
38 if(p == 0)
39 	{
40 	*tval = 0;
41 	return 0;
42 	}
43 
44 if(dbgflag)
45 	{
46 	printf("doname(%s,%d)\n",p->namep,reclevel);
47 	fflush(stdout);
48 	}
49 
50 if(p->done > 0)
51 	{
52 	*tval = p->modtime;
53 	return (p->done == 3);
54 	}
55 
56 errstat = 0;
57 tdep = 0;
58 implcom = 0;
59 explcom = 0;
60 ptime = exists(p->namep);
61 ptime1 = 0;
62 didwork = NO;
63 p->done = 1;	/* avoid infinite loops */
64 nproc1 = nproc;	/* current depth of process stack */
65 
66 qchain = NULL;
67 allchain = NULL;
68 
69 /* define values of Bradford's $$@ and $$/ macros */
70 for(s = lastslash = p->namep; *s; ++s)
71 	if(*s == '/')
72 		lastslash = s;
73 setvar("$@", p->namep, YES);
74 setvar("$/", lastslash, YES);
75 
76 
77 /* expand any names that have embedded metacharacters */
78 
79 for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
80 	for(q = lp->depp ; q ; q=qtemp )
81 		{
82 		qtemp = q->nxtdepblock;
83 		expand(q);
84 		}
85 
86 /* make sure all dependents are up to date */
87 
88 for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
89 	{
90 	td = 0;
91 	for(q = lp->depp ; q ; q = q->nxtdepblock)
92 		if(q->depname)
93 			{
94 			errstat += doname(q->depname, reclevel+1, &td1, q->nowait);
95 			if(dbgflag)
96 				printf("TIME(%s)=%ld\n",q->depname->namep, td1);
97 			if(td1 > td)
98 				td = td1;
99 			if(ptime < td1)
100 				qchain = appendq(qchain, q->depname->namep);
101 			allchain = appendq(allchain, q->depname->namep);
102 			}
103 	if(p->septype == SOMEDEPS)
104 		{
105 		if(lp->shp)
106 		     if( ptime<td || (ptime==0 && td==0) || lp->depp==0)
107 			{
108 			okdel1 = okdel;
109 			okdel = NO;
110 			set3var("@", p->namep);
111 			setvar("?", mkqlist(qchain,qbuf), YES);
112 			setvar("^", mkqlist(allchain,tgsbuf), YES);
113 			qchain = NULL;
114 			if( !questflag )
115 				errstat += docom(lp->shp, nowait, nproc1);
116 			set3var("@", CHNULL);
117 			okdel = okdel1;
118 			ptime1 = prestime();
119 			didwork = YES;
120 			}
121 		}
122 
123 	else	{
124 		if(lp->shp != 0)
125 			{
126 			if(explcom)
127 				fprintf(stderr, "Too many command lines for `%s'\n",
128 					p->namep);
129 			else	explcom = lp->shp;
130 			}
131 
132 		if(td > tdep) tdep = td;
133 		}
134 	}
135 
136 
137 
138 /* Look for implicit dependents, using suffix rules */
139 
140 for(lp = sufflist ; lp ; lp = lp->nxtlineblock)
141     for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock)
142 	{
143 	pnamep = suffp->depname->namep;
144 	if(suffix(p->namep , pnamep , prefix))
145 		{
146 		(void)srchdir(concat(prefix,"*",temp), NO, (depblkp) NULL);
147 		for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock)
148 		    for(suffp1=lp1->depp; suffp1 ; suffp1 = suffp1->nxtdepblock)
149 			{
150 			p1namep = suffp1->depname->namep;
151 			if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) &&
152 			    (p2=srchname(concat(prefix, p1namep ,sourcename))) )
153 				{
154 				errstat += doname(p2, reclevel+1, &td, NO);
155 				if(ptime < td)
156 					qchain = appendq(qchain, p2->namep);
157 if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td);
158 				if(td > tdep) tdep = td;
159 				set3var("*", prefix);
160 				set3var("<", copys(sourcename));
161 				for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
162 					if(implcom = lp2->shp) break;
163 				goto endloop;
164 				}
165 			}
166 		}
167 	}
168 
169 /* Look for implicit dependents, using pattern matching rules */
170 
171 len = strlen(p->namep);
172 for(wp = firstwild ; wp ; wp = wp->next)
173 	if(stem = wildmatch(wp, p->namep, len) )
174 		{
175 		lp = wp->linep;
176 		for(q = lp->depp; q; q = q->nxtdepblock)
177 			{
178 			if(dbgflag>1 && q->depname)
179 				fprintf(stderr,"check dep of %s on %s\n", p->namep,
180 					wildsub(q->depname->namep,stem));
181 			if(q->depname &&
182 				! chkname(wildsub(q->depname->namep,stem)))
183 					break;
184 			}
185 
186 		if(q)	/* some name not found, go to next line */
187 			continue;
188 
189 		for(q = lp->depp; q; q = q->nxtdepblock)
190 			{
191 			nameblkp tamep;
192 			if(q->depname == NULL)
193 				continue;
194 			tamep = srchname( wildsub(q->depname->namep,stem));
195 /*TEMP fprintf(stderr,"check dep %s on %s =>%s\n",p->namep,q->depname->namep,tamep->namep);*/
196 /*TEMP*/if(dbgflag) printf("%s depends on %s. stem=%s\n", p->namep,tamep->namep, stem);
197 			errstat += doname(tamep, reclevel+1, &td, q->nowait);
198 			if(ptime < td)
199 				qchain = appendq(qchain, tamep->namep);
200 			allchain = appendq(allchain, tamep->namep);
201 			if(dbgflag) printf("TIME(%s)=%ld\n", tamep->namep, td);
202 			if(td > tdep)
203 				tdep = td;
204 			set3var("<", copys(tamep->namep) );
205 			}
206 		set3var("*", stem);
207 		setvar("%", stem, YES);
208 		implcom = lp->shp;
209 		goto endloop;
210 		}
211 
212 endloop:
213 
214 
215 if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) )
216 	{
217 	ptime = (tdep>0 ? tdep : prestime() );
218 	set3var("@", p->namep);
219 	setvar("?", mkqlist(qchain,qbuf), YES);
220 	setvar("^", mkqlist(allchain,tgsbuf), YES);
221 	if(explcom)
222 		errstat += docom(explcom, nowait, nproc1);
223 	else if(implcom)
224 		errstat += docom(implcom, nowait, nproc1);
225 	else if(p->septype == 0)
226 		if(p1=srchname(".DEFAULT"))
227 			{
228 			set3var("<", p->namep);
229 			for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
230 				if(implcom = lp2->shp)
231 					{
232 					errstat += docom(implcom, nowait,nproc1);
233 					break;
234 					}
235 			}
236 		else if(keepgoing)
237 			{
238 			printf("Don't know how to make %s\n", p->namep);
239 			++errstat;
240 			}
241 		else
242 			fatal1(" Don't know how to make %s", p->namep);
243 
244 	set3var("@", CHNULL);
245 	if(noexflag || nowait || (ptime = exists(p->namep)) == 0 )
246 		ptime = prestime();
247 	}
248 
249 else if(errstat!=0 && reclevel==0)
250 	printf("`%s' not remade because of errors\n", p->namep);
251 
252 else if(!questflag && reclevel==0  &&  didwork==NO)
253 	printf("`%s' is up to date.\n", p->namep);
254 
255 if(questflag && reclevel==0)
256 	exit(ndocoms>0 ? -1 : 0);
257 
258 p->done = (errstat ? 3 : 2);
259 if(ptime1 > ptime)
260 	ptime = ptime1;
261 p->modtime = ptime;
262 *tval = ptime;
263 return errstat;
264 }
265 
docom(struct shblock * q,int nowait,int nproc1)266 docom(struct shblock *q, int nowait, int nproc1)
267 {
268 char *s;
269 int ign, nopr, doit;
270 char string[OUTMAX];
271 
272 ++ndocoms;
273 if(questflag)
274 	return NO;
275 
276 if(touchflag)
277 	{
278 	s = varptr("@")->varval;
279 	if(!silflag)
280 		printf("touch(%s)\n", s);
281 	if(!noexflag)
282 		touch(YES, s);
283 	return NO;
284 	}
285 
286 if(nproc1 < nproc)
287 	waitstack(nproc1);
288 
289 for( ; q ; q = q->nxtshblock )
290 	{
291 	subst(q->shbp, string, &string[sizeof string - 1]);
292 	ign = ignerr;
293 	nopr = NO;
294 	doit = NO;
295 	for(s = string ; ; ++s)
296 		{
297 		switch(*s)
298 			{
299 			case '-':
300 				ign = YES;
301 				continue;
302 			case '@':
303 				nopr = YES;
304 				continue;
305 			case '+':
306 				doit = YES;
307 				continue;
308 			default:
309 				break;
310 			}
311 		break;
312 		}
313 
314 	if( docom1(s, ign, nopr, doit||!noexflag, nowait&&!q->nxtshblock) && !ign)
315 		return YES;
316 	}
317 return NO;
318 }
319 
320 
321 static int
docom1(char * comstring,int nohalt,int noprint,int doit,int nowait)322 docom1(char *comstring, int nohalt, int noprint, int doit, int nowait)
323 {
324 int status;
325 char *prefix;
326 
327 if(comstring[0] == '\0')
328 	return 0;
329 
330 if(!silflag && (!noprint || !doit) )
331 	prefix = doit ? prompt : "" ;
332 else
333 	prefix = CHNULL;
334 
335 if(dynmacro(comstring) || !doit)
336 	{
337 	if(prefix)
338 		{
339 		fputs(prefix, stdout);
340 		puts(comstring);	/* with a newline */
341 		fflush(stdout);
342 		}
343 	return 0;
344 	}
345 
346 status = dosys(comstring, nohalt, nowait, prefix);
347 baddirs();	/* directories may have changed */
348 return status;
349 }
350 
351 
352 /*
353    If there are any Shell meta characters in the name,
354    expand into a list, after searching directory
355 */
356 
357 static void
expand(depblkp q)358 expand(depblkp q)
359 {
360 char *s;
361 char *s1;
362 depblkp p;
363 
364 s1 = q->depname->namep;
365 for(s=s1 ; ;) switch(*s++)
366 	{
367 	case '\0':
368 		return;
369 
370 	case '*':
371 	case '?':
372 	case '[':
373 		if( p = srchdir(s1 , YES, q->nxtdepblock) )
374 			{
375 			q->nxtdepblock = p;
376 			q->depname = 0;
377 			}
378 		return;
379 	}
380 }
381