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