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