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