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