diff options
Diffstat (limited to 'src/cmd/mk/mk.c')
-rw-r--r-- | src/cmd/mk/mk.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/src/cmd/mk/mk.c b/src/cmd/mk/mk.c new file mode 100644 index 00000000..26b8a976 --- /dev/null +++ b/src/cmd/mk/mk.c @@ -0,0 +1,226 @@ +#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; +} |