1 static char *sccsid = "@(#)doname.c 4.1 (Berkeley) 81/02/28"; 2 #include "defs" 3 4 /* BASIC PROCEDURE. RECURSIVE. */ 5 6 /* 7 p->done = 0 don't know what to do yet 8 p->done = 1 file in process of being updated 9 p->done = 2 file already exists in current state 10 p->done = 3 file make failed 11 */ 12 13 doname(p, reclevel, tval) 14 register struct nameblock *p; 15 int reclevel; 16 TIMETYPE *tval; 17 { 18 int errstat; 19 int okdel1; 20 int didwork; 21 TIMETYPE td, td1, tdep, ptime, ptime1, prestime(); 22 register struct depblock *q; 23 struct depblock *qtemp, *srchdir(), *suffp, *suffp1; 24 struct nameblock *p1, *p2; 25 struct shblock *implcom, *explcom; 26 register struct lineblock *lp; 27 struct lineblock *lp1, *lp2; 28 char sourcename[100], prefix[100], temp[100], concsuff[20]; 29 char *pnamep, *p1namep; 30 char *mkqlist(); 31 struct chain *qchain, *appendq(); 32 33 if(p == 0) 34 { 35 *tval = 0; 36 return(0); 37 } 38 39 if(dbgflag) 40 { 41 printf("doname(%s,%d)\n",p->namep,reclevel); 42 fflush(stdout); 43 } 44 45 if(p->done > 0) 46 { 47 *tval = p->modtime; 48 return(p->done == 3); 49 } 50 51 errstat = 0; 52 tdep = 0; 53 implcom = 0; 54 explcom = 0; 55 ptime = exists(p->namep); 56 ptime1 = 0; 57 didwork = NO; 58 p->done = 1; /* avoid infinite loops */ 59 60 qchain = NULL; 61 62 /* Expand any names that have embedded metacharaters */ 63 64 for(lp = p->linep ; lp ; lp = lp->nxtlineblock) 65 for(q = lp->depp ; q ; q=qtemp ) 66 { 67 qtemp = q->nxtdepblock; 68 expand(q); 69 } 70 71 /* make sure all dependents are up to date */ 72 73 for(lp = p->linep ; lp ; lp = lp->nxtlineblock) 74 { 75 td = 0; 76 for(q = lp->depp ; q ; q = q->nxtdepblock) 77 { 78 errstat += doname(q->depname, reclevel+1, &td1); 79 if(dbgflag) 80 printf("TIME(%s)=%ld\n", q->depname->namep, td1); 81 if(td1 > td) td = td1; 82 if(ptime < td1) 83 qchain = appendq(qchain, q->depname->namep); 84 } 85 if(p->septype == SOMEDEPS) 86 { 87 if(lp->shp!=0) 88 if( ptime<td || (ptime==0 && td==0) || lp->depp==0) 89 { 90 okdel1 = okdel; 91 okdel = NO; 92 setvar("@", p->namep); 93 setvar("?", mkqlist(qchain) ); 94 qchain = NULL; 95 if( !questflag ) 96 errstat += docom(lp->shp); 97 setvar("@", (char *) NULL); 98 okdel = okdel1; 99 ptime1 = prestime(); 100 didwork = YES; 101 } 102 } 103 104 else { 105 if(lp->shp != 0) 106 { 107 if(explcom) 108 fprintf(stderr, "Too many command lines for `%s'\n", 109 p->namep); 110 else explcom = lp->shp; 111 } 112 113 if(td > tdep) tdep = td; 114 } 115 } 116 117 /* Look for implicit dependents, using suffix rules */ 118 119 for(lp = sufflist ; lp ; lp = lp->nxtlineblock) 120 for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock) 121 { 122 pnamep = suffp->depname->namep; 123 if(suffix(p->namep , pnamep , prefix)) 124 { 125 srchdir( concat(prefix,"*",temp) , NO, (struct depblock *) NULL); 126 for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock) 127 for(suffp1=lp1->depp ; suffp1 ; suffp1 = suffp1->nxtdepblock) 128 { 129 p1namep = suffp1->depname->namep; 130 if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) && 131 (p2=srchname(concat(prefix, p1namep ,sourcename))) ) 132 { 133 errstat += doname(p2, reclevel+1, &td); 134 if(ptime < td) 135 qchain = appendq(qchain, p2->namep); 136 if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td); 137 if(td > tdep) tdep = td; 138 setvar("*", prefix); 139 setvar("<", copys(sourcename)); 140 for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) 141 if(implcom = lp2->shp) break; 142 goto endloop; 143 } 144 } 145 } 146 } 147 148 endloop: 149 150 151 if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) ) 152 { 153 ptime = (tdep>0 ? tdep : prestime() ); 154 setvar("@", p->namep); 155 setvar("?", mkqlist(qchain) ); 156 if(explcom) 157 errstat += docom(explcom); 158 else if(implcom) 159 errstat += docom(implcom); 160 else if(p->septype == 0) 161 if(p1=srchname(".DEFAULT")) 162 { 163 setvar("<", p->namep); 164 for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) 165 if(implcom = lp2->shp) 166 { 167 errstat += docom(implcom); 168 break; 169 } 170 } 171 else if(keepgoing) 172 { 173 printf("Don't know how to make %s\n", p->namep); 174 ++errstat; 175 } 176 else 177 fatal1(" Don't know how to make %s", p->namep); 178 179 setvar("@", (char *) NULL); 180 if(noexflag || (ptime = exists(p->namep)) == 0) 181 ptime = prestime(); 182 } 183 184 else if(errstat!=0 && reclevel==0) 185 printf("`%s' not remade because of errors\n", p->namep); 186 187 else if(!questflag && reclevel==0 && didwork==NO) 188 printf("`%s' is up to date.\n", p->namep); 189 190 if(questflag && reclevel==0) 191 exit(ndocoms>0 ? -1 : 0); 192 193 p->done = (errstat ? 3 : 2); 194 if(ptime1 > ptime) ptime = ptime1; 195 p->modtime = ptime; 196 *tval = ptime; 197 return(errstat); 198 } 199 200 docom(q) 201 struct shblock *q; 202 { 203 char *s; 204 struct varblock *varptr(); 205 int ign, nopr; 206 char string[OUTMAX]; 207 208 ++ndocoms; 209 if(questflag) 210 return(NO); 211 212 if(touchflag) 213 { 214 s = varptr("@")->varval; 215 if(!silflag) 216 printf("touch(%s)\n", s); 217 if(!noexflag) 218 touch(YES, s); 219 } 220 221 else for( ; q ; q = q->nxtshblock ) 222 { 223 subst(q->shbp,string); 224 225 ign = ignerr; 226 nopr = NO; 227 for(s = string ; *s=='-' || *s=='@' ; ++s) 228 if(*s == '-') ign = YES; 229 else nopr = YES; 230 231 if( docom1(s, ign, nopr) && !ign) 232 if(keepgoing) 233 return(YES); 234 else fatal( (char *) NULL); 235 } 236 return(NO); 237 } 238 239 240 241 docom1(comstring, nohalt, noprint) 242 register char *comstring; 243 int nohalt, noprint; 244 { 245 register int status; 246 247 if(comstring[0] == '\0') return(0); 248 249 if(!silflag && (!noprint || noexflag) ) 250 { 251 printf("%s%s\n", (noexflag ? "" : prompt), comstring); 252 fflush(stdout); 253 } 254 255 if(noexflag) return(0); 256 257 if( status = dosys(comstring, nohalt) ) 258 { 259 if( status>>8 ) 260 printf("*** Error code %d", status>>8 ); 261 else printf("*** Termination code %d", status ); 262 263 if(nohalt) printf(" (ignored)\n"); 264 else printf("\n"); 265 fflush(stdout); 266 } 267 268 return(status); 269 } 270 271 272 /* 273 If there are any Shell meta characters in the name, 274 expand into a list, after searching directory 275 */ 276 277 expand(q) 278 register struct depblock *q; 279 { 280 register char *s; 281 char *s1; 282 struct depblock *p, *srchdir(); 283 284 s1 = q->depname->namep; 285 for(s=s1 ; ;) switch(*s++) 286 { 287 case '\0': 288 return; 289 290 case '*': 291 case '?': 292 case '[': 293 if( p = srchdir(s1 , YES, q->nxtdepblock) ) 294 { 295 q->nxtdepblock = p; 296 q->depname = 0; 297 } 298 return; 299 } 300 } 301