# # initially generated by c2l # runerrs: int; mk(target: array of byte) { node: ref Node; did: int = 0; nproc(); # it can be updated dynamically nrep(); # it can be updated dynamically runerrs = 0; node = graph(target); if(debug&D_GRAPH){ dumpn(libc0->s2ab("new target\n"), node); bout.flush(); } clrmade(node); while(node.flags&NOTMADE){ if(work(node, nil, nil)) did = 1; # found something to do else{ if(waitup(1, nil) > 0){ if(node.flags&(NOTMADE|BEINGMADE)){ assert(libc0->s2ab("must be run errors"), runerrs); break; # nothing more waiting } } } } if(node.flags&BEINGMADE) waitup(-1, nil); while(jobs != nil) waitup(-2, nil); assert(libc0->s2ab("target didn't get done"), runerrs || node.flags&MADE); if(did == 0) bout.puts(sys->sprint("mk: '%s' is up to date\n", libc0->ab2s(node.name))); } clrmade(n: ref Node) { a: ref Arc; n.flags &= ~(CANPRETEND|PRETENDING); if(libc0->strchr(n.name, '(') == nil || n.time) n.flags |= CANPRETEND; n.flags = n.flags&~(NOTMADE|BEINGMADE|MADE)|NOTMADE; for(a = n.prereqs; a != nil; a = a.next) if(a.n != nil) clrmade(a.n); } unpretend(n: ref Node) { n.flags = n.flags&~(NOTMADE|BEINGMADE|MADE)|NOTMADE; n.flags &= ~(CANPRETEND|PRETENDING); n.time = 0; } work(node: ref Node, p: ref Node, parc: ref Arc): int { a, ra: ref Arc; weoutofdate, ready: int; did: int = 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 != nil && outofdate(p, parc, 0)){ if(explain != nil) sys->fprint(sys->fildes(1), "unpretending %s(%d) because %s is out of date(%d)\n", libc0->ab2s(node.name), node.time, libc0->ab2s(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 == nil){ if(node.time == 0){ sys->fprint(sys->fildes(2), "mk: don't know how to make '%s'\n", libc0->ab2s(node.name)); if(kflag){ node.flags |= BEINGMADE; runerrs++; } else Exit(); } else node.flags = node.flags&~(NOTMADE|BEINGMADE|MADE)|MADE; return did; } # # now see if we are out of date or what # ready = 1; weoutofdate = aflag; ra = nil; for(a = node.prereqs; a != nil; a = a.next) if(a.n != nil){ did = work(a.n, node, a) || did; if(a.n.flags&(NOTMADE|BEINGMADE)) ready = 0; if(outofdate(node, a, 0)){ weoutofdate = 1; if(ra == nil || ra.n == nil || ra.n.time < a.n.time) ra = a; } } else{ if(node.time == 0){ if(ra == nil) ra = a; weoutofdate = 1; } } if(ready == 0) # can't do anything now return did; if(weoutofdate == 0){ node.flags = node.flags&~(NOTMADE|BEINGMADE|MADE)|MADE; return did; } # # can we pretend to be made? # if(iflag == 0 && node.time == 0 && node.flags&(PRETENDING|CANPRETEND) && p != nil && ra.n != nil && !outofdate(p, ra, 0)){ node.flags &= ~CANPRETEND; node.flags = node.flags&~(NOTMADE|BEINGMADE|MADE)|MADE; if(explain != nil && (node.flags&PRETENDING) == 0) sys->fprint(sys->fildes(1), "pretending %s has time %d\n", libc0->ab2s(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 != nil; a = a.next) if(a.n != nil && a.n.flags&PRETENDING){ if(explain != nil) if(ra.n != nil) bout.puts(sys->sprint("unpretending %s because of %s because of %s\n", libc0->ab2s(a.n.name), libc0->ab2s(node.name), libc0->ab2s(ra.n.name))); else bout.puts(sys->sprint("unpretending %s because of %s because of %s\n", libc0->ab2s(a.n.name), libc0->ab2s(node.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; } update(fake: int, node: ref Node) { a: ref Arc; if(fake) node.flags = node.flags&~(NOTMADE|BEINGMADE|MADE)|BEINGMADE; else node.flags = node.flags&~(NOTMADE|BEINGMADE|MADE)|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 != nil; a = a.next) if(a.prog != nil) outofdate(node, a, 1); } else{ node.time = 1; for(a = node.prereqs; a != nil; a = a.next) if(a.n != nil && outofdate(node, a, 1)) node.time = a.n.time; } # print("----node %s time=%ld flags=0x%x\n", node->name, node->time, node->flags);/* } pcmp(prog: array of byte, p: array of byte, q: array of byte): int { buf := array[3*NAMEBLOCK] of byte; pid: int; bout.flush(); stob(buf, sys->sprint("%s '%s' '%s'\n", libc0->ab2s(prog), libc0->ab2s(p), libc0->ab2s(q))); pid = pipecmd(buf, nil, nil); apid := array[1] of int; apid[0] = pid; while(waitup(-3, apid) >= 0) ; pid = apid[0]; if(pid) return 2; else return 1; } outofdate(node: ref Node, arc: ref Arc, eval: int): int { buf := array[3*NAMEBLOCK] of byte; str: array of byte; sym: ref Symtab; ret: int; str = nil; if(arc.prog != nil){ stob(buf, sys->sprint("%s%c%s", libc0->ab2s(node.name), 8r377, libc0->ab2s(arc.n.name))); sym = symlooki(buf, S_OUTOFDATE, 0); if(sym == nil || eval){ if(sym == nil) str = libc0->strdup(buf); ret = pcmp(arc.prog, node.name, arc.n.name); if(sym != nil) sym.ivalue = ret; else symlooki(str, S_OUTOFDATE, ret); } else ret = int sym.ivalue; return ret-1; } else if(libc0->strchr(arc.n.name, '(') != nil && arc.n.time == 0) # missing archive member return 1; else return node.time < arc.n.time; }