#include "mk.h" int runerrs; voidmk(char *target){ Node *node; int did = 0; nproc(); /* it can be updated dynamically */ nrep(); /* it can be updated dynamically */ runerrs = 0; node = graph(target); if(DEBUG(D_GRAPH)){ dumpn("new target\n", node); Bflush(&bout); } clrmade(node); while(node->flags&NOTMADE){ if(work(node, (Node *)0, (Arc *)0)) did = 1; /* found something to do */ else { if(waitup(1, (int *)0) > 0){ if(node->flags&(NOTMADE|BEINGMADE)){ assert("must be run errors", runerrs); break; /* nothing more waiting */ } } } } if(node->flags&BEINGMADE) waitup(-1, (int *)0); while(jobs) waitup(-2, (int *)0); assert("target didn't get done", runerrs || (node->flags&MADE)); if(did == 0) Bprint(&bout, "mk: '%s' is up to date\n", node->name);} voidclrmade(Node *n){ Arc *a; n->flags &= ~(CANPRETEND|PRETENDING); if(strchr(n->name, '(') ==0 || n->time) n->flags |= CANPRETEND; MADESET(n, NOTMADE); for(a = n->prereqs; a; a = a->next) if(a->n) clrmade(a->n);} static voidunpretend(Node *n){ MADESET(n, NOTMADE); n->flags &= ~(CANPRETEND|PRETENDING); n->time = 0;} intwork(Node *node, Node *p, Arc *parc){ Arc *a, *ra; int weoutofdate; int ready; int did = 0; /*print("work(%s) flags=0x%x time=%ld\n", node->name, node->flags, node->time);/**/ if(node->flags&BEINGMADE) return(did); if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){ if(explain) fprint(1, "unpretending %s(%ld) because %s is out of date(%ld)\n", node->name, node->time, p->name, p->time); unpretend(node); } /* have a look if we are pretending in case someone has been unpretended out from underneath us */ if(node->flags&MADE){ if(node->flags&PRETENDING){ node->time = 0; }else return(did); } /* consider no prerequsite case */ if(node->prereqs == 0){ if(node->time == 0){ fprint(2, "mk: don't know how to make '%s'\n", node->name); if(kflag){ node->flags |= BEINGMADE; runerrs++; } else Exit(); } else MADESET(node, MADE); return(did); } /* now see if we are out of date or what */ ready = 1; weoutofdate = aflag; ra = 0; for(a = node->prereqs; a; a = a->next) if(a->n){ did = work(a->n, node, a) || did; if(a->n->flags&(NOTMADE|BEINGMADE)) ready = 0; if(outofdate(node, a, 0)){ weoutofdate = 1; if((ra == 0) || (ra->n == 0) || (ra->n->time < a->n->time)) ra = a; } } else { if(node->time == 0){ if(ra == 0) ra = a; weoutofdate = 1; } } if(ready == 0) /* can't do anything now */ return(did); if(weoutofdate == 0){ MADESET(node, MADE); return(did); } /* can we pretend to be made? */ if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND)) && p && ra->n && !outofdate(p, ra, 0)){ node->flags &= ~CANPRETEND; MADESET(node, MADE); if(explain && ((node->flags&PRETENDING) == 0)) fprint(1, "pretending %s has time %ld\n", node->name, node->time); node->flags |= PRETENDING; return(did); } /* node is out of date and we REALLY do have to do something. quickly rescan for pretenders */ for(a = node->prereqs; a; a = a->next) if(a->n && (a->n->flags&PRETENDING)){ if(explain) Bprint(&bout, "unpretending %s because of %s because of %s\n", a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites"); unpretend(a->n); did = work(a->n, node, a) || did; ready = 0; } if(ready == 0) /* try later unless nothing has happened for -k's sake */ return(did || work(node, p, parc)); did = dorecipe(node) || did; return(did);} voidupdate(int fake, Node *node){ Arc *a; MADESET(node, fake? BEINGMADE : MADE); if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){ node->time = timeof(node->name, 1); node->flags &= ~(CANPRETEND|PRETENDING); for(a = node->prereqs; a; a = a->next) if(a->prog) outofdate(node, a, 1); } else { node->time = 1; for(a = node->prereqs; a; a = a->next) if(a->n && outofdate(node, a, 1)) node->time = a->n->time; }/* print("----node %s time=%ld flags=0x%x\n", node->name, node->time, node->flags);/**/} static intpcmp(char *prog, char *p, char *q){ char buf[3*NAMEBLOCK]; int pid; Bflush(&bout); sprint(buf, "%s '%s' '%s'\n", prog, p, q); pid = pipecmd(buf, 0, 0); while(waitup(-3, &pid) >= 0) ; return(pid? 2:1);} intoutofdate(Node *node, Arc *arc, int eval){ char buf[3*NAMEBLOCK], *str; Symtab *sym; int ret; str = 0; if(arc->prog){ sprint(buf, "%s%c%s", node->name, 0377, arc->n->name); sym = symlook(buf, S_OUTOFDATE, 0); if(sym == 0 || eval){ if(sym == 0) str = strdup(buf); ret = pcmp(arc->prog, node->name, arc->n->name); if(sym) sym->value = (void *)ret; else symlook(str, S_OUTOFDATE, (void *)ret); } else ret = (int)sym->value; return(ret-1); } else if(strchr(arc->n->name, '(') && arc->n->time == 0) /* missing archive member */ return 1; else return node->time <= arc->n->time;}
#include "mk.h"
int runerrs;
void
mk(char *target)
{
Node *node;
int did = 0;
nproc(); /* it can be updated dynamically */
nrep(); /* it can be updated dynamically */
runerrs = 0;
node = graph(target);
if(DEBUG(D_GRAPH)){
dumpn("new target\n", node);
Bflush(&bout);
}
clrmade(node);
while(node->flags&NOTMADE){
if(work(node, (Node *)0, (Arc *)0))
did = 1; /* found something to do */
else {
if(waitup(1, (int *)0) > 0){
if(node->flags&(NOTMADE|BEINGMADE)){
assert("must be run errors", runerrs);
break; /* nothing more waiting */
}
}
}
}
if(node->flags&BEINGMADE)
waitup(-1, (int *)0);
while(jobs)
waitup(-2, (int *)0);
assert("target didn't get done", runerrs || (node->flags&MADE));
if(did == 0)
Bprint(&bout, "mk: '%s' is up to date\n", node->name);
}
void
clrmade(Node *n)
{
Arc *a;
n->flags &= ~(CANPRETEND|PRETENDING);
if(strchr(n->name, '(') ==0 || n->time)
n->flags |= CANPRETEND;
MADESET(n, NOTMADE);
for(a = n->prereqs; a; a = a->next)
if(a->n)
clrmade(a->n);
}
static void
unpretend(Node *n)
{
MADESET(n, NOTMADE);
n->flags &= ~(CANPRETEND|PRETENDING);
n->time = 0;
}
int
work(Node *node, Node *p, Arc *parc)
{
Arc *a, *ra;
int weoutofdate;
int ready;
int did = 0;
/*print("work(%s) flags=0x%x time=%ld\n", node->name, node->flags, node->time);/**/
if(node->flags&BEINGMADE)
return(did);
if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){
if(explain)
fprint(1, "unpretending %s(%ld) because %s is out of date(%ld)\n",
node->name, node->time, p->name, p->time);
unpretend(node);
}
/*
have a look if we are pretending in case
someone has been unpretended out from underneath us
*/
if(node->flags&MADE){
if(node->flags&PRETENDING){
node->time = 0;
}else
return(did);
}
/* consider no prerequsite case */
if(node->prereqs == 0){
if(node->time == 0){
fprint(2, "mk: don't know how to make '%s'\n", node->name);
if(kflag){
node->flags |= BEINGMADE;
runerrs++;
} else
Exit();
} else
MADESET(node, MADE);
return(did);
}
/*
now see if we are out of date or what
*/
ready = 1;
weoutofdate = aflag;
ra = 0;
for(a = node->prereqs; a; a = a->next)
if(a->n){
did = work(a->n, node, a) || did;
if(a->n->flags&(NOTMADE|BEINGMADE))
ready = 0;
if(outofdate(node, a, 0)){
weoutofdate = 1;
if((ra == 0) || (ra->n == 0)
|| (ra->n->time < a->n->time))
ra = a;
}
} else {
if(node->time == 0){
if(ra == 0)
ra = a;
weoutofdate = 1;
}
}
if(ready == 0) /* can't do anything now */
return(did);
if(weoutofdate == 0){
MADESET(node, MADE);
return(did);
}
/*
can we pretend to be made?
*/
if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND))
&& p && ra->n && !outofdate(p, ra, 0)){
node->flags &= ~CANPRETEND;
MADESET(node, MADE);
if(explain && ((node->flags&PRETENDING) == 0))
fprint(1, "pretending %s has time %ld\n", node->name, node->time);
node->flags |= PRETENDING;
return(did);
}
/*
node is out of date and we REALLY do have to do something.
quickly rescan for pretenders
*/
for(a = node->prereqs; a; a = a->next)
if(a->n && (a->n->flags&PRETENDING)){
if(explain)
Bprint(&bout, "unpretending %s because of %s because of %s\n",
a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites");
unpretend(a->n);
did = work(a->n, node, a) || did;
ready = 0;
}
if(ready == 0) /* try later unless nothing has happened for -k's sake */
return(did || work(node, p, parc));
did = dorecipe(node) || did;
return(did);
}
void
update(int fake, Node *node)
{
Arc *a;
MADESET(node, fake? BEINGMADE : MADE);
if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){
node->time = timeof(node->name, 1);
node->flags &= ~(CANPRETEND|PRETENDING);
for(a = node->prereqs; a; a = a->next)
if(a->prog)
outofdate(node, a, 1);
} else {
node->time = 1;
for(a = node->prereqs; a; a = a->next)
if(a->n && outofdate(node, a, 1))
node->time = a->n->time;
}
/* print("----node %s time=%ld flags=0x%x\n", node->name, node->time, node->flags);/**/
}
static int
pcmp(char *prog, char *p, char *q)
{
char buf[3*NAMEBLOCK];
int pid;
Bflush(&bout);
sprint(buf, "%s '%s' '%s'\n", prog, p, q);
pid = pipecmd(buf, 0, 0);
while(waitup(-3, &pid) >= 0)
;
return(pid? 2:1);
}
int
outofdate(Node *node, Arc *arc, int eval)
{
char buf[3*NAMEBLOCK], *str;
Symtab *sym;
int ret;
str = 0;
if(arc->prog){
sprint(buf, "%s%c%s", node->name, 0377, arc->n->name);
sym = symlook(buf, S_OUTOFDATE, 0);
if(sym == 0 || eval){
if(sym == 0)
str = strdup(buf);
ret = pcmp(arc->prog, node->name, arc->n->name);
if(sym)
sym->value = (void *)ret;
else
symlook(str, S_OUTOFDATE, (void *)ret);
} else
ret = (int)sym->value;
return(ret-1);
} else if(strchr(arc->n->name, '(') && arc->n->time == 0) /* missing archive member */
return 1;
else
return node->time <= arc->n->time;
}