1 static char *sccsid = "@(#)doname.c 4.10 (Berkeley) 93/03/01";
2 #include "defs"
3 #include <strings.h>
4 #include <signal.h>
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
doname(p,reclevel,tval)15 doname(p, reclevel, tval)
16 register struct nameblock *p;
17 int reclevel;
18 TIMETYPE *tval;
19 {
20 int errstat;
21 int okdel1;
22 int didwork;
23 TIMETYPE td, td1, tdep, ptime, ptime1, prestime();
24 register struct depblock *q;
25 struct depblock *qtemp, *srchdir(), *suffp, *suffp1;
26 struct nameblock *p1, *p2;
27 struct shblock *implcom, *explcom;
28 register struct lineblock *lp;
29 struct lineblock *lp1, *lp2;
30 char sourcename[BUFSIZ], prefix[BUFSIZ], temp[BUFSIZ], concsuff[20];
31 char *pnamep, *p1namep, *cp;
32 char *mkqlist();
33 struct chain *qchain, *appendq();
34
35 {
36 /*
37 * VPATH= ${PATH1}:${PATH2} didn't work. This fix is so ugly I don't
38 * even want to think about it. Basically it grabs VPATH and
39 * explicitly does macro expansion before resolving names. Why
40 * VPATH didn't get handled correctly I have no idea; the symptom
41 * was that, while macro expansion got done, the .c files in the
42 * non-local directories wouldn't be found.
43 */
44 struct varblock *vpath_cp, *varptr();
45 static int vpath_first;
46 char vpath_exp[INMAX];
47
48 if (!vpath_first) {
49 vpath_first = 1;
50 vpath_cp = varptr("VPATH");
51 if (vpath_cp->varval) {
52 subst(vpath_cp->varval, vpath_exp);
53 setvar("VPATH",vpath_exp);
54 }
55 }
56 }
57 if(p == 0)
58 {
59 *tval = 0;
60 return(0);
61 }
62
63 if(dbgflag)
64 {
65 printf("doname(%s,%d)\n",p->namep,reclevel);
66 fflush(stdout);
67 }
68
69 if(p->done > 0)
70 {
71 *tval = p->modtime;
72 return(p->done == 3);
73 }
74
75 errstat = 0;
76 tdep = 0;
77 implcom = 0;
78 explcom = 0;
79 ptime = exists(p);
80 ptime1 = 0;
81 didwork = NO;
82 p->done = 1; /* avoid infinite loops */
83
84 qchain = NULL;
85
86 /* Expand any names that have embedded metacharaters */
87
88 for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
89 for(q = lp->depp ; q ; q=qtemp )
90 {
91 qtemp = q->nxtdepblock;
92 expand(q);
93 }
94
95 /* make sure all dependents are up to date */
96
97 for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
98 {
99 td = 0;
100 for(q = lp->depp ; q ; q = q->nxtdepblock)
101 {
102 errstat += doname(q->depname, reclevel+1, &td1);
103 if(dbgflag)
104 printf("TIME(%s)=%ld\n", q->depname->namep, td1);
105 if(td1 > td) td = td1;
106 if(ptime < td1)
107 qchain = appendq(qchain, q->depname->namep);
108 }
109 if(p->septype == SOMEDEPS)
110 {
111 if(lp->shp!=0)
112 if( ptime<td || (ptime==0 && td==0) || lp->depp==0)
113 {
114 okdel1 = okdel;
115 okdel = NO;
116 setvar("@", p->namep);
117 setvar("?", mkqlist(qchain) );
118 qchain = NULL;
119 if( !questflag )
120 errstat += docom(lp->shp);
121 setvar("@", (char *) NULL);
122 okdel = okdel1;
123 ptime1 = prestime();
124 didwork = YES;
125 }
126 }
127
128 else {
129 if(lp->shp != 0)
130 {
131 if(explcom)
132 fprintf(stderr, "Too many command lines for `%s'\n",
133 p->namep);
134 else explcom = lp->shp;
135 }
136
137 if(td > tdep) tdep = td;
138 }
139 }
140
141 /* Look for implicit dependents, using suffix rules */
142
143 for(lp = sufflist ; lp ; lp = lp->nxtlineblock)
144 for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock)
145 {
146 pnamep = suffp->depname->namep;
147 if(suffix(p->namep , pnamep , prefix))
148 {
149
150 srchdir( concat(prefix,"*",temp) , NO, (struct depblock *) NULL);
151 for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock)
152 for(suffp1=lp1->depp ; suffp1 ; suffp1 = suffp1->nxtdepblock)
153 {
154 p1namep = suffp1->depname->namep;
155 if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) &&
156 (p2=srchname(concat(prefix, p1namep ,sourcename))) )
157 {
158 errstat += doname(p2, reclevel+1, &td);
159 if(ptime < td)
160 qchain = appendq(qchain, p2->namep);
161 if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td);
162 if(td > tdep) tdep = td;
163 setvar("*", prefix);
164 if (p2->alias) setvar("<", copys(p2->alias));
165 else setvar("<", copys(p2->namep));
166 for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
167 if(implcom = lp2->shp) break;
168 goto endloop;
169 }
170 }
171 cp = rindex(prefix, '/');
172 if (cp++ == 0)
173 cp = prefix;
174 setvar("*", cp);
175 }
176 }
177
178 endloop:
179
180
181 if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) )
182 {
183 ptime = (tdep>0 ? tdep : prestime() );
184 setvar("@", p->namep);
185 setvar("?", mkqlist(qchain) );
186 if(explcom)
187 errstat += docom(explcom);
188 else if(implcom)
189 errstat += docom(implcom);
190 else if(p->septype == 0)
191 if(p1=srchname(".DEFAULT"))
192 {
193 if (p->alias) setvar("<", p->alias);
194 else setvar("<", p->namep);
195 for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
196 if(implcom = lp2->shp)
197 {
198 errstat += docom(implcom);
199 break;
200 }
201 }
202 else if(keepgoing)
203 {
204 printf("Don't know how to make %s\n", p->namep);
205 ++errstat;
206 }
207 else
208 fatal1(" Don't know how to make %s", p->namep);
209
210 setvar("@", (char *) NULL);
211 if(noexflag || (ptime = exists(p)) == 0)
212 ptime = prestime();
213 }
214
215 else if(errstat!=0 && reclevel==0)
216 printf("`%s' not remade because of errors\n", p->namep);
217
218 else if(!questflag && reclevel==0 && didwork==NO)
219 printf("`%s' is up to date.\n", p->namep);
220
221 if(questflag && reclevel==0)
222 exit(ndocoms>0 ? -1 : 0);
223
224 p->done = (errstat ? 3 : 2);
225 if(ptime1 > ptime) ptime = ptime1;
226 p->modtime = ptime;
227 *tval = ptime;
228 return(errstat);
229 }
230
231 docom(q)
232 struct shblock *q;
233 {
234 char *s;
235 struct varblock *varptr();
236 int ign, nopr;
237 char string[OUTMAX];
238 char string2[OUTMAX];
239
240 ++ndocoms;
241 if(questflag)
242 return(NO);
243
244 if(touchflag)
245 {
246 s = varptr("@")->varval;
247 if(!silflag)
248 printf("touch(%s)\n", s);
249 if(!noexflag)
250 touch(YES, s);
251 }
252
253 else for( ; q ; q = q->nxtshblock )
254 {
255 subst(q->shbp,string2);
256 fixname(string2, string);
257
258 ign = ignerr;
259 nopr = NO;
260 for(s = string ; *s=='-' || *s=='@' ; ++s)
261 if(*s == '-') ign = YES;
262 else nopr = YES;
263
264 if( docom1(s, ign, nopr) && !ign)
265 if(keepgoing)
266 return(YES);
267 else fatal( (char *) NULL);
268 }
269 return(NO);
270 }
271
272
273
docom1(comstring,nohalt,noprint)274 docom1(comstring, nohalt, noprint)
275 register char *comstring;
276 int nohalt, noprint;
277 {
278 register int status;
279
280 if(comstring[0] == '\0') return(0);
281
282 if(!silflag && (!noprint || noexflag) )
283 {
284 printf("%s%s\n", (noexflag ? "" : prompt), comstring);
285 fflush(stdout);
286 }
287
288 if(noexflag) return(0);
289
290 if( status = dosys(comstring, nohalt) )
291 {
292 unsigned sig = status & 0177;
293 if( sig ) {
294 if (sig < NSIG && sys_siglist[sig] != NULL &&
295 *sys_siglist[sig] != '\0')
296 printf("*** %s", sys_siglist[sig]);
297 else
298 printf("*** Signal %d", sig);
299 if (status & 0200)
300 printf(" - core dumped");
301 } else
302 printf("*** Exit %d", status>>8 );
303
304 if(nohalt) printf(" (ignored)\n");
305 else printf("\n");
306 fflush(stdout);
307 }
308
309 return(status);
310 }
311
312
313 /*
314 If there are any Shell meta characters in the name,
315 expand into a list, after searching directory
316 */
317
expand(q)318 expand(q)
319 register struct depblock *q;
320 {
321 register char *s;
322 char *s1;
323 struct depblock *p, *srchdir();
324
325 if (q->depname == NULL)
326 return;
327 s1 = q->depname->namep;
328 for(s=s1 ; ;) switch(*s++)
329 {
330 case '\0':
331 return;
332
333 case '*':
334 case '?':
335 case '[':
336 if( p = srchdir(s1 , YES, q->nxtdepblock) )
337 {
338 q->nxtdepblock = p;
339 q->depname = 0;
340 }
341 return;
342 }
343 }
344