+#include "defs"
+
+/* BASIC PROCEDURE. RECURSIVE. */
+
+/*
+p->done = 0 don't know what to do yet
+p->done = 1 file in process of being updated
+p->done = 2 file already exists in current state
+p->done = 3 file make failed
+*/
+
+doname(p, reclevel, tval)
+register struct nameblock *p;
+int reclevel;
+TIMETYPE *tval;
+{
+int errstat;
+int okdel1;
+int didwork;
+TIMETYPE td, td1, tdep, ptime, ptime1, prestime();
+register struct depblock *q;
+struct depblock *qtemp, *srchdir(), *suffp, *suffp1;
+struct nameblock *p1, *p2;
+struct shblock *implcom, *explcom;
+register struct lineblock *lp;
+struct lineblock *lp1, *lp2;
+char sourcename[100], prefix[100], temp[100], concsuff[20];
+char *pnamep, *p1namep;
+char *mkqlist();
+struct chain *qchain, *appendq();
+
+if(p == 0)
+ {
+ *tval = 0;
+ return(0);
+ }
+
+if(dbgflag)
+ {
+ printf("doname(%s,%d)\n",p->namep,reclevel);
+ fflush(stdout);
+ }
+
+if(p->done > 0)
+ {
+ *tval = p->modtime;
+ return(p->done == 3);
+ }
+
+errstat = 0;
+tdep = 0;
+implcom = 0;
+explcom = 0;
+ptime = exists(p->namep);
+ptime1 = 0;
+didwork = NO;
+p->done = 1; /* avoid infinite loops */
+
+qchain = NULL;
+
+/* Expand any names that have embedded metacharaters */
+
+for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
+ for(q = lp->depp ; q ; q=qtemp )
+ {
+ qtemp = q->nxtdepblock;
+ expand(q);
+ }
+
+/* make sure all dependents are up to date */
+
+for(lp = p->linep ; lp ; lp = lp->nxtlineblock)
+ {
+ td = 0;
+ for(q = lp->depp ; q ; q = q->nxtdepblock)
+ {
+ errstat += doname(q->depname, reclevel+1, &td1);
+ if(dbgflag)
+ printf("TIME(%s)=%ld\n", q->depname->namep, td1);
+ if(td1 > td) td = td1;
+ if(ptime < td1)
+ qchain = appendq(qchain, q->depname->namep);
+ }
+ if(p->septype == SOMEDEPS)
+ {
+ if(lp->shp!=0)
+ if( ptime<td || (ptime==0 && td==0) || lp->depp==0)
+ {
+ okdel1 = okdel;
+ okdel = NO;
+ setvar("@", p->namep);
+ setvar("?", mkqlist(qchain) );
+ qchain = NULL;
+ if( !questflag )
+ errstat += docom(lp->shp);
+ setvar("@", (char *) NULL);
+ okdel = okdel1;
+ ptime1 = prestime();
+ didwork = YES;
+ }
+ }
+
+ else {
+ if(lp->shp != 0)
+ {
+ if(explcom)
+ fprintf(stderr, "Too many command lines for `%s'\n",
+ p->namep);
+ else explcom = lp->shp;
+ }
+
+ if(td > tdep) tdep = td;
+ }
+ }
+
+/* Look for implicit dependents, using suffix rules */
+
+for(lp = sufflist ; lp ; lp = lp->nxtlineblock)
+ for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock)
+ {
+ pnamep = suffp->depname->namep;
+ if(suffix(p->namep , pnamep , prefix))
+ {
+ srchdir( concat(prefix,"*",temp) , NO, (struct depblock *) NULL);
+ for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock)
+ for(suffp1=lp1->depp ; suffp1 ; suffp1 = suffp1->nxtdepblock)
+ {
+ p1namep = suffp1->depname->namep;
+ if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) &&
+ (p2=srchname(concat(prefix, p1namep ,sourcename))) )
+ {
+ errstat += doname(p2, reclevel+1, &td);
+ if(ptime < td)
+ qchain = appendq(qchain, p2->namep);
+if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td);
+ if(td > tdep) tdep = td;
+ setvar("*", prefix);
+ setvar("<", copys(sourcename));
+ for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
+ if(implcom = lp2->shp) break;
+ goto endloop;
+ }
+ }
+ }
+ }
+
+endloop:
+
+
+if(errstat==0 && (ptime<tdep || (ptime==0 && tdep==0) ) )
+ {
+ ptime = (tdep>0 ? tdep : prestime() );
+ setvar("@", p->namep);
+ setvar("?", mkqlist(qchain) );
+ if(explcom)
+ errstat += docom(explcom);
+ else if(implcom)
+ errstat += docom(implcom);
+ else if(p->septype == 0)
+ if(p1=srchname(".DEFAULT"))
+ {
+ setvar("<", p->namep);
+ for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock)
+ if(implcom = lp2->shp)
+ {
+ errstat += docom(implcom);
+ break;
+ }
+ }
+ else if(keepgoing)
+ {
+ printf("Don't know how to make %s\n", p->namep);
+ ++errstat;
+ }
+ else
+ fatal1(" Don't know how to make %s", p->namep);
+
+ setvar("@", (char *) NULL);
+ if(noexflag || (ptime = exists(p->namep)) == 0)
+ ptime = prestime();
+ }
+
+else if(errstat!=0 && reclevel==0)
+ printf("`%s' not remade because of errors\n", p->namep);
+
+else if(!questflag && reclevel==0 && didwork==NO)
+ printf("`%s' is up to date.\n", p->namep);
+
+if(questflag && reclevel==0)
+ exit(ndocoms>0 ? -1 : 0);
+
+p->done = (errstat ? 3 : 2);
+if(ptime1 > ptime) ptime = ptime1;
+p->modtime = ptime;
+*tval = ptime;
+return(errstat);
+}
+\f
+docom(q)
+struct shblock *q;
+{
+char *s;
+struct varblock *varptr();
+int ign, nopr;
+char string[OUTMAX];
+
+++ndocoms;
+if(questflag)
+ return(NO);
+
+if(touchflag)
+ {
+ s = varptr("@")->varval;
+ if(!silflag)
+ printf("touch(%s)\n", s);
+ if(!noexflag)
+ touch(YES, s);
+ }
+
+else for( ; q ; q = q->nxtshblock )
+ {
+ subst(q->shbp,string);
+
+ ign = ignerr;
+ nopr = NO;
+ for(s = string ; *s=='-' || *s=='@' ; ++s)
+ if(*s == '-') ign = YES;
+ else nopr = YES;
+
+ if( docom1(s, ign, nopr) && !ign)
+ if(keepgoing)
+ return(YES);
+ else fatal( (char *) NULL);
+ }
+return(NO);
+}
+
+
+
+docom1(comstring, nohalt, noprint)
+register char *comstring;
+int nohalt, noprint;
+{
+register int status;
+
+if(comstring[0] == '\0') return(0);
+
+if(!silflag && (!noprint || noexflag) )
+ {
+ printf("%s%s\n", (noexflag ? "" : prompt), comstring);
+ fflush(stdout);
+ }
+
+if(noexflag) return(0);
+
+if( status = dosys(comstring, nohalt) )
+ {
+ if( status>>8 )
+ printf("*** Error code %d", status>>8 );
+ else printf("*** Termination code %d", status );
+
+ if(nohalt) printf(" (ignored)\n");
+ else printf("\n");
+ fflush(stdout);
+ }
+
+return(status);
+}
+\f
+
+/*
+ If there are any Shell meta characters in the name,
+ expand into a list, after searching directory
+*/
+
+expand(q)
+register struct depblock *q;
+{
+register char *s;
+char *s1;
+struct depblock *p, *srchdir();
+
+s1 = q->depname->namep;
+for(s=s1 ; ;) switch(*s++)
+ {
+ case '\0':
+ return;
+
+ case '*':
+ case '?':
+ case '[':
+ if( p = srchdir(s1 , YES, q->nxtdepblock) )
+ {
+ q->nxtdepblock = p;
+ q->depname = 0;
+ }
+ return;
+ }
+}