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 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 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 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