xref: /csrg-svn/old/make/doname.c (revision 17682)
1 static	char *sccsid = "@(#)doname.c	4.5 (Berkeley) 85/01/09";
2 #include "defs"
3 #include <strings.h>
4 
5 /*  BASIC PROCEDURE.  RECURSIVE.  */
6 
7 /*
8 p->done = 0   don't know what to do yet
9 p->done = 1   file in process of being updated
10 p->done = 2   file already exists in current state
11 p->done = 3   file make failed
12 */
13 
14 doname(p, reclevel, tval)
15 register struct nameblock *p;
16 int reclevel;
17 TIMETYPE *tval;
18 {
19 int errstat;
20 int okdel1;
21 int didwork;
22 TIMETYPE td, td1, tdep, ptime, ptime1, prestime();
23 register struct depblock *q;
24 struct depblock *qtemp, *srchdir(), *suffp, *suffp1;
25 struct nameblock *p1, *p2;
26 struct shblock *implcom, *explcom;
27 register struct lineblock *lp;
28 struct lineblock *lp1, *lp2;
29 char sourcename[100], prefix[100], temp[100], concsuff[20];
30 char *pnamep, *p1namep, *cp;
31 char *mkqlist();
32 struct chain *qchain, *appendq();
33 
34 if(p == 0)
35 	{
36 	*tval = 0;
37 	return(0);
38 	}
39 
40 if(dbgflag)
41 	{
42 	printf("doname(%s,%d)\n",p->namep,reclevel);
43 	fflush(stdout);
44 	}
45 
46 if(p->done > 0)
47 	{
48 	*tval = p->modtime;
49 	return(p->done == 3);
50 	}
51 
52 errstat = 0;
53 tdep = 0;
54 implcom = 0;
55 explcom = 0;
56 ptime = exists(p->namep);
57 ptime1 = 0;
58 didwork = NO;
59 p->done = 1;	/* avoid infinite loops */
60 
61 qchain = NULL;
62 
63 /* Expand any names that have embedded metacharaters */
64 
65 for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
66 	for(q = lp->depp ; q ; q=qtemp )
67 		{
68 		qtemp = q->nxtdepblock;
69 		expand(q);
70 		}
71 
72 /* make sure all dependents are up to date */
73 
74 for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
75 	{
76 	td = 0;
77 	for(q = lp->depp ; q ; q = q->nxtdepblock)
78 		{
79 		errstat += doname(q->depname, reclevel+1, &td1);
80 		if(dbgflag)
81 		    printf("TIME(%s)=%ld\n", q->depname->namep, td1);
82 		if(td1 > td) td = td1;
83 		if(ptime < td1)
84 			qchain = appendq(qchain, q->depname->namep);
85 		}
86 	if(p->septype == SOMEDEPS)
87 		{
88 		if(lp->shp!=0)
89 		     if( ptime<td || (ptime==0 && td==0) || lp->depp==0)
90 			{
91 			okdel1 = okdel;
92 			okdel = NO;
93 			setvar("@", p->namep);
94 			setvar("?", mkqlist(qchain) );
95 			qchain = NULL;
96 			if( !questflag )
97 				errstat += docom(lp->shp);
98 			setvar("@", (char *) NULL);
99 			okdel = okdel1;
100 			ptime1 = prestime();
101 			didwork = YES;
102 			}
103 		}
104 
105 	else	{
106 		if(lp->shp != 0)
107 			{
108 			if(explcom)
109 				fprintf(stderr, "Too many command lines for `%s'\n",
110 					p->namep);
111 			else	explcom = lp->shp;
112 			}
113 
114 		if(td > tdep) tdep = td;
115 		}
116 	}
117 
118 /* Look for implicit dependents, using suffix rules */
119 
120 for(lp = sufflist ; lp ; lp = lp->nxtlineblock)
121     for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock)
122 	{
123 	pnamep = suffp->depname->namep;
124 	if(suffix(p->namep , pnamep , prefix))
125 		{
126 		srchdir( concat(prefix,"*",temp) , NO, (struct depblock *) NULL);
127 		for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock)
128 		    for(suffp1=lp1->depp ; suffp1 ; suffp1 = suffp1->nxtdepblock)
129 			{
130 			p1namep = suffp1->depname->namep;
131 			if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) &&
132 			    (p2=srchname(concat(prefix, p1namep ,sourcename))) )
133 				{
134 				errstat += doname(p2, reclevel+1, &td);
135 				if(ptime < td)
136 					qchain = appendq(qchain, p2->namep);
137 if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td);
138 				if(td > tdep) tdep = td;
139 				setvar("*", prefix);
140 				setvar("<", copys(sourcename));
141 				for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
142 					if(implcom = lp2->shp) break;
143 				goto endloop;
144 				}
145 			}
146 		cp = rindex(prefix, '/');
147 		if (cp++ == 0)
148 			cp = prefix;
149 		setvar("*", cp);
150 		}
151 	}
152 
153 endloop:
154 
155 
156 if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) )
157 	{
158 	ptime = (tdep>0 ? tdep : prestime() );
159 	setvar("@", p->namep);
160 	setvar("?", mkqlist(qchain) );
161 	if(explcom)
162 		errstat += docom(explcom);
163 	else if(implcom)
164 		errstat += docom(implcom);
165 	else if(p->septype == 0)
166 		if(p1=srchname(".DEFAULT"))
167 			{
168 			setvar("<", p->namep);
169 			for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
170 				if(implcom = lp2->shp)
171 					{
172 					errstat += docom(implcom);
173 					break;
174 					}
175 			}
176 		else if(keepgoing)
177 			{
178 			printf("Don't know how to make %s\n", p->namep);
179 			++errstat;
180 			}
181 		else
182 			fatal1(" Don't know how to make %s", p->namep);
183 
184 	setvar("@", (char *) NULL);
185 	if(noexflag || (ptime = exists(p->namep)) == 0)
186 		ptime = prestime();
187 	}
188 
189 else if(errstat!=0 && reclevel==0)
190 	printf("`%s' not remade because of errors\n", p->namep);
191 
192 else if(!questflag && reclevel==0  &&  didwork==NO)
193 	printf("`%s' is up to date.\n", p->namep);
194 
195 if(questflag && reclevel==0)
196 	exit(ndocoms>0 ? -1 : 0);
197 
198 p->done = (errstat ? 3 : 2);
199 if(ptime1 > ptime) ptime = ptime1;
200 p->modtime = ptime;
201 *tval = ptime;
202 return(errstat);
203 }
204 
205 docom(q)
206 struct shblock *q;
207 {
208 char *s;
209 struct varblock *varptr();
210 int ign, nopr;
211 char string[OUTMAX];
212 
213 ++ndocoms;
214 if(questflag)
215 	return(NO);
216 
217 if(touchflag)
218 	{
219 	s = varptr("@")->varval;
220 	if(!silflag)
221 		printf("touch(%s)\n", s);
222 	if(!noexflag)
223 		touch(YES, s);
224 	}
225 
226 else for( ; q ; q = q->nxtshblock )
227 	{
228 	subst(q->shbp,string);
229 
230 	ign = ignerr;
231 	nopr = NO;
232 	for(s = string ; *s=='-' || *s=='@' ; ++s)
233 		if(*s == '-')  ign = YES;
234 		else nopr = YES;
235 
236 	if( docom1(s, ign, nopr) && !ign)
237 		if(keepgoing)
238 			return(YES);
239 		else	fatal( (char *) NULL);
240 	}
241 return(NO);
242 }
243 
244 
245 
246 docom1(comstring, nohalt, noprint)
247 register char *comstring;
248 int nohalt, noprint;
249 {
250 register int status;
251 
252 if(comstring[0] == '\0') return(0);
253 
254 if(!silflag && (!noprint || noexflag) )
255 	{
256 	printf("%s%s\n", (noexflag ? "" : prompt), comstring);
257 	fflush(stdout);
258 	}
259 
260 if(noexflag) return(0);
261 
262 if( status = dosys(comstring, nohalt) )
263 	{
264 	if( status>>8 )
265 		printf("*** Error code %d", status>>8 );
266 	else	printf("*** Termination code %d", status );
267 
268 	if(nohalt) printf(" (ignored)\n");
269 	else	printf("\n");
270 	fflush(stdout);
271 	}
272 
273 return(status);
274 }
275 
276 
277 /*
278    If there are any Shell meta characters in the name,
279    expand into a list, after searching directory
280 */
281 
282 expand(q)
283 register struct depblock *q;
284 {
285 register char *s;
286 char *s1;
287 struct depblock *p, *srchdir();
288 
289 if (q->depname == NULL)
290 	return;
291 s1 = q->depname->namep;
292 for(s=s1 ; ;) switch(*s++)
293 	{
294 	case '\0':
295 		return;
296 
297 	case '*':
298 	case '?':
299 	case '[':
300 		if( p = srchdir(s1 , YES, q->nxtdepblock) )
301 			{
302 			q->nxtdepblock = p;
303 			q->depname = 0;
304 			}
305 		return;
306 	}
307 }
308