| #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; |
| } |
| |
| static char* |
| dir(void) |
| { |
| static char buf[1024]; |
| |
| return getcwd(buf, sizeof buf); |
| } |
| |
| 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' in %s\n", node->name, dir()); |
| 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, Shell *sh, Word *shcmd) |
| { |
| char buf[3*NAMEBLOCK]; |
| int pid; |
| |
| Bflush(&bout); |
| snprint(buf, sizeof buf, "%s '%s' '%s'\n", prog, p, q); |
| pid = pipecmd(buf, envy, 0, sh, shcmd); |
| 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){ |
| snprint(buf, sizeof 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, arc->r->shellt, arc->r->shellcmd); |
| if(sym) |
| sym->u.value = ret; |
| else |
| symlook(str, S_OUTOFDATE, (void *)(uintptr)ret); |
| } else |
| ret = sym->u.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; |
| } |