1 static char *sccsid = "@(#)doname.c 4.6 (Berkeley) 85/04/16"; 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); 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 127 srchdir( concat(prefix,"*",temp) , NO, (struct depblock *) NULL); 128 for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock) 129 for(suffp1=lp1->depp ; suffp1 ; suffp1 = suffp1->nxtdepblock) 130 { 131 p1namep = suffp1->depname->namep; 132 if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) && 133 (p2=srchname(concat(prefix, p1namep ,sourcename))) ) 134 { 135 errstat += doname(p2, reclevel+1, &td); 136 if(ptime < td) 137 qchain = appendq(qchain, p2->namep); 138 if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td); 139 if(td > tdep) tdep = td; 140 setvar("*", prefix); 141 if (p2->alias) setvar("<", copys(p2->alias)); 142 else setvar("<", copys(p2->namep)); 143 for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) 144 if(implcom = lp2->shp) break; 145 goto endloop; 146 } 147 } 148 cp = rindex(prefix, '/'); 149 if (cp++ == 0) 150 cp = prefix; 151 setvar("*", cp); 152 } 153 } 154 155 endloop: 156 157 158 if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) ) 159 { 160 ptime = (tdep>0 ? tdep : prestime() ); 161 setvar("@", p->namep); 162 setvar("?", mkqlist(qchain) ); 163 if(explcom) 164 errstat += docom(explcom); 165 else if(implcom) 166 errstat += docom(implcom); 167 else if(p->septype == 0) 168 if(p1=srchname(".DEFAULT")) 169 { 170 if (p->alias) setvar("<", p->alias); 171 else setvar("<", p->namep); 172 for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) 173 if(implcom = lp2->shp) 174 { 175 errstat += docom(implcom); 176 break; 177 } 178 } 179 else if(keepgoing) 180 { 181 printf("Don't know how to make %s\n", p->namep); 182 ++errstat; 183 } 184 else 185 fatal1(" Don't know how to make %s", p->namep); 186 187 setvar("@", (char *) NULL); 188 if(noexflag || (ptime = exists(p)) == 0) 189 ptime = prestime(); 190 } 191 192 else if(errstat!=0 && reclevel==0) 193 printf("`%s' not remade because of errors\n", p->namep); 194 195 else if(!questflag && reclevel==0 && didwork==NO) 196 printf("`%s' is up to date.\n", p->namep); 197 198 if(questflag && reclevel==0) 199 exit(ndocoms>0 ? -1 : 0); 200 201 p->done = (errstat ? 3 : 2); 202 if(ptime1 > ptime) ptime = ptime1; 203 p->modtime = ptime; 204 *tval = ptime; 205 return(errstat); 206 } 207 208 docom(q) 209 struct shblock *q; 210 { 211 char *s; 212 struct varblock *varptr(); 213 int ign, nopr; 214 char string[OUTMAX]; 215 char string2[OUTMAX]; 216 217 ++ndocoms; 218 if(questflag) 219 return(NO); 220 221 if(touchflag) 222 { 223 s = varptr("@")->varval; 224 if(!silflag) 225 printf("touch(%s)\n", s); 226 if(!noexflag) 227 touch(YES, s); 228 } 229 230 else for( ; q ; q = q->nxtshblock ) 231 { 232 subst(q->shbp,string2); 233 fixname(string2, string); 234 235 ign = ignerr; 236 nopr = NO; 237 for(s = string ; *s=='-' || *s=='@' ; ++s) 238 if(*s == '-') ign = YES; 239 else nopr = YES; 240 241 if( docom1(s, ign, nopr) && !ign) 242 if(keepgoing) 243 return(YES); 244 else fatal( (char *) NULL); 245 } 246 return(NO); 247 } 248 249 250 251 docom1(comstring, nohalt, noprint) 252 register char *comstring; 253 int nohalt, noprint; 254 { 255 register int status; 256 257 if(comstring[0] == '\0') return(0); 258 259 if(!silflag && (!noprint || noexflag) ) 260 { 261 printf("%s%s\n", (noexflag ? "" : prompt), comstring); 262 fflush(stdout); 263 } 264 265 if(noexflag) return(0); 266 267 if( status = dosys(comstring, nohalt) ) 268 { 269 if( status>>8 ) 270 printf("*** Error code %d", status>>8 ); 271 else printf("*** Termination code %d", status ); 272 273 if(nohalt) printf(" (ignored)\n"); 274 else printf("\n"); 275 fflush(stdout); 276 } 277 278 return(status); 279 } 280 281 282 /* 283 If there are any Shell meta characters in the name, 284 expand into a list, after searching directory 285 */ 286 287 expand(q) 288 register struct depblock *q; 289 { 290 register char *s; 291 char *s1; 292 struct depblock *p, *srchdir(); 293 294 if (q->depname == NULL) 295 return; 296 s1 = q->depname->namep; 297 for(s=s1 ; ;) switch(*s++) 298 { 299 case '\0': 300 return; 301 302 case '*': 303 case '?': 304 case '[': 305 if( p = srchdir(s1 , YES, q->nxtdepblock) ) 306 { 307 q->nxtdepblock = p; 308 q->depname = 0; 309 } 310 return; 311 } 312 } 313