13e12c5d1SDavid du Colombier #include "mk.h"
23e12c5d1SDavid du Colombier
33e12c5d1SDavid du Colombier int runerrs;
43e12c5d1SDavid du Colombier
53e12c5d1SDavid du Colombier void
mk(char * target)63e12c5d1SDavid du Colombier mk(char *target)
73e12c5d1SDavid du Colombier {
83e12c5d1SDavid du Colombier Node *node;
93e12c5d1SDavid du Colombier int did = 0;
103e12c5d1SDavid du Colombier
113e12c5d1SDavid du Colombier nproc(); /* it can be updated dynamically */
123e12c5d1SDavid du Colombier nrep(); /* it can be updated dynamically */
133e12c5d1SDavid du Colombier runerrs = 0;
143e12c5d1SDavid du Colombier node = graph(target);
153e12c5d1SDavid du Colombier if(DEBUG(D_GRAPH)){
163e12c5d1SDavid du Colombier dumpn("new target\n", node);
177dd7cddfSDavid du Colombier Bflush(&bout);
183e12c5d1SDavid du Colombier }
193e12c5d1SDavid du Colombier clrmade(node);
203e12c5d1SDavid du Colombier while(node->flags&NOTMADE){
213e12c5d1SDavid du Colombier if(work(node, (Node *)0, (Arc *)0))
223e12c5d1SDavid du Colombier did = 1; /* found something to do */
233e12c5d1SDavid du Colombier else {
243e12c5d1SDavid du Colombier if(waitup(1, (int *)0) > 0){
253e12c5d1SDavid du Colombier if(node->flags&(NOTMADE|BEINGMADE)){
267dd7cddfSDavid du Colombier assert(/*must be run errors*/ runerrs);
273e12c5d1SDavid du Colombier break; /* nothing more waiting */
283e12c5d1SDavid du Colombier }
293e12c5d1SDavid du Colombier }
303e12c5d1SDavid du Colombier }
313e12c5d1SDavid du Colombier }
323e12c5d1SDavid du Colombier if(node->flags&BEINGMADE)
333e12c5d1SDavid du Colombier waitup(-1, (int *)0);
343e12c5d1SDavid du Colombier while(jobs)
353e12c5d1SDavid du Colombier waitup(-2, (int *)0);
367dd7cddfSDavid du Colombier assert(/*target didnt get done*/ runerrs || (node->flags&MADE));
373e12c5d1SDavid du Colombier if(did == 0)
387dd7cddfSDavid du Colombier Bprint(&bout, "mk: '%s' is up to date\n", node->name);
393e12c5d1SDavid du Colombier }
403e12c5d1SDavid du Colombier
413e12c5d1SDavid du Colombier void
clrmade(Node * n)423e12c5d1SDavid du Colombier clrmade(Node *n)
433e12c5d1SDavid du Colombier {
443e12c5d1SDavid du Colombier Arc *a;
453e12c5d1SDavid du Colombier
463e12c5d1SDavid du Colombier n->flags &= ~(CANPRETEND|PRETENDING);
477dd7cddfSDavid du Colombier if(strchr(n->name, '(') ==0 || n->time)
483e12c5d1SDavid du Colombier n->flags |= CANPRETEND;
493e12c5d1SDavid du Colombier MADESET(n, NOTMADE);
503e12c5d1SDavid du Colombier for(a = n->prereqs; a; a = a->next)
513e12c5d1SDavid du Colombier if(a->n)
523e12c5d1SDavid du Colombier clrmade(a->n);
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier
553e12c5d1SDavid du Colombier static void
unpretend(Node * n)563e12c5d1SDavid du Colombier unpretend(Node *n)
573e12c5d1SDavid du Colombier {
583e12c5d1SDavid du Colombier MADESET(n, NOTMADE);
593e12c5d1SDavid du Colombier n->flags &= ~(CANPRETEND|PRETENDING);
603e12c5d1SDavid du Colombier n->time = 0;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier
633e12c5d1SDavid du Colombier int
work(Node * node,Node * p,Arc * parc)643e12c5d1SDavid du Colombier work(Node *node, Node *p, Arc *parc)
653e12c5d1SDavid du Colombier {
663e12c5d1SDavid du Colombier Arc *a, *ra;
673e12c5d1SDavid du Colombier int weoutofdate;
683e12c5d1SDavid du Colombier int ready;
693e12c5d1SDavid du Colombier int did = 0;
70276e7d6dSDavid du Colombier char cwd[256];
713e12c5d1SDavid du Colombier
72*7f49a7ffSDavid du Colombier /*print("work(%s) flags=0x%x time=%lud\n", node->name, node->flags, node->time);/**/
733e12c5d1SDavid du Colombier if(node->flags&BEINGMADE)
743e12c5d1SDavid du Colombier return(did);
753e12c5d1SDavid du Colombier if((node->flags&MADE) && (node->flags&PRETENDING) && p && outofdate(p, parc, 0)){
763e12c5d1SDavid du Colombier if(explain)
77*7f49a7ffSDavid du Colombier fprint(1, "unpretending %s(%lud) because %s is out of date(%lud)\n",
783e12c5d1SDavid du Colombier node->name, node->time, p->name, p->time);
793e12c5d1SDavid du Colombier unpretend(node);
803e12c5d1SDavid du Colombier }
813e12c5d1SDavid du Colombier /*
823e12c5d1SDavid du Colombier have a look if we are pretending in case
833e12c5d1SDavid du Colombier someone has been unpretended out from underneath us
843e12c5d1SDavid du Colombier */
853e12c5d1SDavid du Colombier if(node->flags&MADE){
863e12c5d1SDavid du Colombier if(node->flags&PRETENDING){
873e12c5d1SDavid du Colombier node->time = 0;
883e12c5d1SDavid du Colombier }else
893e12c5d1SDavid du Colombier return(did);
903e12c5d1SDavid du Colombier }
919a747e4fSDavid du Colombier /* consider no prerequisite case */
923e12c5d1SDavid du Colombier if(node->prereqs == 0){
933e12c5d1SDavid du Colombier if(node->time == 0){
949a747e4fSDavid du Colombier if(getwd(cwd, sizeof cwd))
959a747e4fSDavid du Colombier fprint(2, "mk: don't know how to make '%s' in directory %s\n", node->name, cwd);
969a747e4fSDavid du Colombier else
973e12c5d1SDavid du Colombier fprint(2, "mk: don't know how to make '%s'\n", node->name);
983e12c5d1SDavid du Colombier if(kflag){
993e12c5d1SDavid du Colombier node->flags |= BEINGMADE;
1003e12c5d1SDavid du Colombier runerrs++;
1013e12c5d1SDavid du Colombier } else
1023e12c5d1SDavid du Colombier Exit();
1033e12c5d1SDavid du Colombier } else
1043e12c5d1SDavid du Colombier MADESET(node, MADE);
1053e12c5d1SDavid du Colombier return(did);
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier /*
1083e12c5d1SDavid du Colombier now see if we are out of date or what
1093e12c5d1SDavid du Colombier */
1103e12c5d1SDavid du Colombier ready = 1;
1113e12c5d1SDavid du Colombier weoutofdate = aflag;
1123e12c5d1SDavid du Colombier ra = 0;
1133e12c5d1SDavid du Colombier for(a = node->prereqs; a; a = a->next)
1143e12c5d1SDavid du Colombier if(a->n){
1153e12c5d1SDavid du Colombier did = work(a->n, node, a) || did;
1163e12c5d1SDavid du Colombier if(a->n->flags&(NOTMADE|BEINGMADE))
1173e12c5d1SDavid du Colombier ready = 0;
1183e12c5d1SDavid du Colombier if(outofdate(node, a, 0)){
1193e12c5d1SDavid du Colombier weoutofdate = 1;
1203e12c5d1SDavid du Colombier if((ra == 0) || (ra->n == 0)
1213e12c5d1SDavid du Colombier || (ra->n->time < a->n->time))
1223e12c5d1SDavid du Colombier ra = a;
1233e12c5d1SDavid du Colombier }
1243e12c5d1SDavid du Colombier } else {
1253e12c5d1SDavid du Colombier if(node->time == 0){
1263e12c5d1SDavid du Colombier if(ra == 0)
1273e12c5d1SDavid du Colombier ra = a;
1283e12c5d1SDavid du Colombier weoutofdate = 1;
1293e12c5d1SDavid du Colombier }
1303e12c5d1SDavid du Colombier }
1313e12c5d1SDavid du Colombier if(ready == 0) /* can't do anything now */
1323e12c5d1SDavid du Colombier return(did);
1333e12c5d1SDavid du Colombier if(weoutofdate == 0){
1343e12c5d1SDavid du Colombier MADESET(node, MADE);
1353e12c5d1SDavid du Colombier return(did);
1363e12c5d1SDavid du Colombier }
1373e12c5d1SDavid du Colombier /*
1383e12c5d1SDavid du Colombier can we pretend to be made?
1393e12c5d1SDavid du Colombier */
1407dd7cddfSDavid du Colombier if((iflag == 0) && (node->time == 0) && (node->flags&(PRETENDING|CANPRETEND))
1417dd7cddfSDavid du Colombier && p && ra->n && !outofdate(p, ra, 0)){
1423e12c5d1SDavid du Colombier node->flags &= ~CANPRETEND;
1433e12c5d1SDavid du Colombier MADESET(node, MADE);
1443e12c5d1SDavid du Colombier if(explain && ((node->flags&PRETENDING) == 0))
145*7f49a7ffSDavid du Colombier fprint(1, "pretending %s has time %lud\n", node->name, node->time);
1463e12c5d1SDavid du Colombier node->flags |= PRETENDING;
1473e12c5d1SDavid du Colombier return(did);
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier /*
1503e12c5d1SDavid du Colombier node is out of date and we REALLY do have to do something.
1513e12c5d1SDavid du Colombier quickly rescan for pretenders
1523e12c5d1SDavid du Colombier */
1533e12c5d1SDavid du Colombier for(a = node->prereqs; a; a = a->next)
1543e12c5d1SDavid du Colombier if(a->n && (a->n->flags&PRETENDING)){
1553e12c5d1SDavid du Colombier if(explain)
1567dd7cddfSDavid du Colombier Bprint(&bout, "unpretending %s because of %s because of %s\n",
1573e12c5d1SDavid du Colombier a->n->name, node->name, ra->n? ra->n->name : "rule with no prerequisites");
1583e12c5d1SDavid du Colombier
1593e12c5d1SDavid du Colombier unpretend(a->n);
1603e12c5d1SDavid du Colombier did = work(a->n, node, a) || did;
1613e12c5d1SDavid du Colombier ready = 0;
1623e12c5d1SDavid du Colombier }
1633e12c5d1SDavid du Colombier if(ready == 0) /* try later unless nothing has happened for -k's sake */
1643e12c5d1SDavid du Colombier return(did || work(node, p, parc));
1653e12c5d1SDavid du Colombier did = dorecipe(node) || did;
1663e12c5d1SDavid du Colombier return(did);
1673e12c5d1SDavid du Colombier }
1683e12c5d1SDavid du Colombier
1693e12c5d1SDavid du Colombier void
update(int fake,Node * node)1703e12c5d1SDavid du Colombier update(int fake, Node *node)
1713e12c5d1SDavid du Colombier {
1723e12c5d1SDavid du Colombier Arc *a;
1733e12c5d1SDavid du Colombier
1743e12c5d1SDavid du Colombier MADESET(node, fake? BEINGMADE : MADE);
1753e12c5d1SDavid du Colombier if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){
1763e12c5d1SDavid du Colombier node->time = timeof(node->name, 1);
1773e12c5d1SDavid du Colombier node->flags &= ~(CANPRETEND|PRETENDING);
1783e12c5d1SDavid du Colombier for(a = node->prereqs; a; a = a->next)
1793e12c5d1SDavid du Colombier if(a->prog)
1803e12c5d1SDavid du Colombier outofdate(node, a, 1);
1813e12c5d1SDavid du Colombier } else {
1823e12c5d1SDavid du Colombier node->time = 1;
1833e12c5d1SDavid du Colombier for(a = node->prereqs; a; a = a->next)
1843e12c5d1SDavid du Colombier if(a->n && outofdate(node, a, 1))
1853e12c5d1SDavid du Colombier node->time = a->n->time;
1863e12c5d1SDavid du Colombier }
187*7f49a7ffSDavid du Colombier /* print("----node %s time=%lud flags=0x%x\n", node->name, node->time, node->flags);/**/
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier
1903e12c5d1SDavid du Colombier static
pcmp(char * prog,char * p,char * q)1917dd7cddfSDavid du Colombier pcmp(char *prog, char *p, char *q)
1923e12c5d1SDavid du Colombier {
1933e12c5d1SDavid du Colombier char buf[3*NAMEBLOCK];
1943e12c5d1SDavid du Colombier int pid;
1953e12c5d1SDavid du Colombier
1967dd7cddfSDavid du Colombier Bflush(&bout);
197276e7d6dSDavid du Colombier snprint(buf, sizeof buf, "%s '%s' '%s'\n", prog, p, q);
1987dd7cddfSDavid du Colombier pid = pipecmd(buf, 0, 0);
1993e12c5d1SDavid du Colombier while(waitup(-3, &pid) >= 0)
2003e12c5d1SDavid du Colombier ;
2013e12c5d1SDavid du Colombier return(pid? 2:1);
2023e12c5d1SDavid du Colombier }
2033e12c5d1SDavid du Colombier
2043e12c5d1SDavid du Colombier int
outofdate(Node * node,Arc * arc,int eval)2053e12c5d1SDavid du Colombier outofdate(Node *node, Arc *arc, int eval)
2063e12c5d1SDavid du Colombier {
2073e12c5d1SDavid du Colombier char buf[3*NAMEBLOCK], *str;
2083e12c5d1SDavid du Colombier Symtab *sym;
2093e12c5d1SDavid du Colombier int ret;
2103e12c5d1SDavid du Colombier
2113e12c5d1SDavid du Colombier str = 0;
2123e12c5d1SDavid du Colombier if(arc->prog){
213276e7d6dSDavid du Colombier snprint(buf, sizeof buf, "%s%c%s", node->name, 0377,
214276e7d6dSDavid du Colombier arc->n->name);
2157dd7cddfSDavid du Colombier sym = symlook(buf, S_OUTOFDATE, 0);
2167dd7cddfSDavid du Colombier if(sym == 0 || eval){
2177dd7cddfSDavid du Colombier if(sym == 0)
2183e12c5d1SDavid du Colombier str = strdup(buf);
2193e12c5d1SDavid du Colombier ret = pcmp(arc->prog, node->name, arc->n->name);
2203e12c5d1SDavid du Colombier if(sym)
2214de34a7eSDavid du Colombier sym->u.value = ret;
2223e12c5d1SDavid du Colombier else
2237dd7cddfSDavid du Colombier symlook(str, S_OUTOFDATE, (void *)ret);
2243e12c5d1SDavid du Colombier } else
2254de34a7eSDavid du Colombier ret = sym->u.value;
2263e12c5d1SDavid du Colombier return(ret-1);
22799eb86a7SDavid du Colombier } else if(strchr(arc->n->name, '(') && arc->n->time == 0) /* missing archive member */
22899eb86a7SDavid du Colombier return 1;
2297dd7cddfSDavid du Colombier else
2302db064f5SDavid du Colombier /*
2312db064f5SDavid du Colombier * Treat equal times as out-of-date.
2322db064f5SDavid du Colombier * It's a race, and the safer option is to do
2332db064f5SDavid du Colombier * extra building rather than not enough.
2342db064f5SDavid du Colombier */
2352db064f5SDavid du Colombier return node->time <= arc->n->time;
2363e12c5d1SDavid du Colombier }
237