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