13e12c5d1SDavid du Colombier #include "mk.h" 23e12c5d1SDavid du Colombier 33e12c5d1SDavid du Colombier static Node *applyrules(char *, char *); 43e12c5d1SDavid du Colombier static void togo(Node *); 53e12c5d1SDavid du Colombier static int vacuous(Node *); 63e12c5d1SDavid du Colombier static Node *newnode(char *); 73e12c5d1SDavid du Colombier static void trace(char *, Arc *); 83e12c5d1SDavid du Colombier static void cyclechk(Node *); 93e12c5d1SDavid du Colombier static void ambiguous(Node *); 103e12c5d1SDavid du Colombier static void attribute(Node *); 113e12c5d1SDavid du Colombier 123e12c5d1SDavid du Colombier Node * 133e12c5d1SDavid du Colombier graph(char *target) 143e12c5d1SDavid du Colombier { 153e12c5d1SDavid du Colombier Node *node; 163e12c5d1SDavid du Colombier char *cnt; 173e12c5d1SDavid du Colombier 18*219b2ee8SDavid du Colombier cnt = rulecnt(); 19*219b2ee8SDavid du Colombier node = applyrules(target, cnt); 203e12c5d1SDavid du Colombier free(cnt); 213e12c5d1SDavid du Colombier cyclechk(node); 223e12c5d1SDavid du Colombier node->flags |= PROBABLE; /* make sure it doesn't get deleted */ 233e12c5d1SDavid du Colombier vacuous(node); 243e12c5d1SDavid du Colombier ambiguous(node); 253e12c5d1SDavid du Colombier attribute(node); 263e12c5d1SDavid du Colombier return(node); 273e12c5d1SDavid du Colombier } 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier static Node * 303e12c5d1SDavid du Colombier applyrules(char *target, char *cnt) 313e12c5d1SDavid du Colombier { 323e12c5d1SDavid du Colombier Symtab *sym; 333e12c5d1SDavid du Colombier Node *node; 343e12c5d1SDavid du Colombier Rule *r; 353e12c5d1SDavid du Colombier Arc head, *a = &head; 363e12c5d1SDavid du Colombier Word *w; 373e12c5d1SDavid du Colombier char stem[NAMEBLOCK], buf[NAMEBLOCK]; 383e12c5d1SDavid du Colombier Resub rmatch[NREGEXP]; 393e12c5d1SDavid du Colombier 403e12c5d1SDavid du Colombier /* print("applyrules(%ld='%s')\n", target, target);/**/ 41*219b2ee8SDavid du Colombier sym = symlook(target, S_NODE, (char *)0); 42*219b2ee8SDavid du Colombier if(sym) 43*219b2ee8SDavid du Colombier return (Node *)(sym->value); 443e12c5d1SDavid du Colombier target = strdup(target); 453e12c5d1SDavid du Colombier node = newnode(target); 463e12c5d1SDavid du Colombier head.n = 0; 473e12c5d1SDavid du Colombier head.next = 0; 483e12c5d1SDavid du Colombier sym = symlook(target, S_TARGET, (char *)0); 493e12c5d1SDavid du Colombier for(r = sym? (Rule *)(sym->value):0; r; r = r->chain){ 503e12c5d1SDavid du Colombier if(r->attr&META) continue; 513e12c5d1SDavid du Colombier if(strcmp(target, r->target)) continue; 52*219b2ee8SDavid du Colombier if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue; /* no effect; ignore */ 533e12c5d1SDavid du Colombier if(cnt[r->rule] >= nreps) continue; 543e12c5d1SDavid du Colombier cnt[r->rule]++; 553e12c5d1SDavid du Colombier node->flags |= PROBABLE; 56*219b2ee8SDavid du Colombier 573e12c5d1SDavid du Colombier /* if(r->attr&VIR) 58*219b2ee8SDavid du Colombier * node->flags |= VIRTUAL; 59*219b2ee8SDavid du Colombier * if(r->attr&NOREC) 60*219b2ee8SDavid du Colombier * node->flags |= NORECIPE; 61*219b2ee8SDavid du Colombier * if(r->attr&DEL) 62*219b2ee8SDavid du Colombier * node->flags |= DELETE; 633e12c5d1SDavid du Colombier */ 643e12c5d1SDavid du Colombier if(!r->tail || !r->tail->s || !*r->tail->s) { 653e12c5d1SDavid du Colombier a->next = newarc((Node *)0, r, "", rmatch); 663e12c5d1SDavid du Colombier a = a->next; 673e12c5d1SDavid du Colombier } else 683e12c5d1SDavid du Colombier for(w = r->tail; w; w = w->next){ 693e12c5d1SDavid du Colombier a->next = newarc(applyrules(w->s, cnt), r, "", rmatch); 703e12c5d1SDavid du Colombier a = a->next; 713e12c5d1SDavid du Colombier } 723e12c5d1SDavid du Colombier cnt[r->rule]--; 733e12c5d1SDavid du Colombier head.n = node; 743e12c5d1SDavid du Colombier } 753e12c5d1SDavid du Colombier for(r = metarules; r; r = r->next){ 76*219b2ee8SDavid du Colombier if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue; /* no effect; ignore */ 773e12c5d1SDavid du Colombier if ((r->attr&NOVIRT) && a != &head && (a->r->attr&VIR)) 783e12c5d1SDavid du Colombier continue; 793e12c5d1SDavid du Colombier if(r->attr®EXP){ 803e12c5d1SDavid du Colombier stem[0] = 0; 813e12c5d1SDavid du Colombier patrule = r; 823e12c5d1SDavid du Colombier rmatch[0].sp = rmatch[0].ep = 0; 833e12c5d1SDavid du Colombier if(regexec(r->pat, node->name, rmatch, NREGEXP) == 0) 843e12c5d1SDavid du Colombier continue; 853e12c5d1SDavid du Colombier } else { 863e12c5d1SDavid du Colombier if(!match(node->name, r->target, stem)) continue; 873e12c5d1SDavid du Colombier } 883e12c5d1SDavid du Colombier if(cnt[r->rule] >= nreps) continue; 893e12c5d1SDavid du Colombier cnt[r->rule]++; 90*219b2ee8SDavid du Colombier 913e12c5d1SDavid du Colombier /* if(r->attr&VIR) 92*219b2ee8SDavid du Colombier * node->flags |= VIRTUAL; 93*219b2ee8SDavid du Colombier * if(r->attr&NOREC) 94*219b2ee8SDavid du Colombier * node->flags |= NORECIPE; 95*219b2ee8SDavid du Colombier * if(r->attr&DEL) 96*219b2ee8SDavid du Colombier * node->flags |= DELETE; 973e12c5d1SDavid du Colombier */ 98*219b2ee8SDavid du Colombier 993e12c5d1SDavid du Colombier if(!r->tail || !r->tail->s || !*r->tail->s) { 1003e12c5d1SDavid du Colombier a->next = newarc((Node *)0, r, strdup(stem), rmatch); 1013e12c5d1SDavid du Colombier a = a->next; 1023e12c5d1SDavid du Colombier } else 1033e12c5d1SDavid du Colombier for(w = r->tail; w; w = w->next){ 1043e12c5d1SDavid du Colombier if(r->attr®EXP) 1053e12c5d1SDavid du Colombier regsub(w->s, buf, rmatch, NREGEXP); 1063e12c5d1SDavid du Colombier else 1073e12c5d1SDavid du Colombier subst(stem, w->s, buf); 1083e12c5d1SDavid du Colombier a->next = newarc(applyrules(buf, cnt), r, strdup(stem), rmatch); 1093e12c5d1SDavid du Colombier a = a->next; 1103e12c5d1SDavid du Colombier } 1113e12c5d1SDavid du Colombier cnt[r->rule]--; 1123e12c5d1SDavid du Colombier } 1133e12c5d1SDavid du Colombier a->next = node->prereqs; 1143e12c5d1SDavid du Colombier node->prereqs = head.next; 1153e12c5d1SDavid du Colombier return(node); 1163e12c5d1SDavid du Colombier } 1173e12c5d1SDavid du Colombier 1183e12c5d1SDavid du Colombier static void 1193e12c5d1SDavid du Colombier togo(Node *node) 1203e12c5d1SDavid du Colombier { 1213e12c5d1SDavid du Colombier Arc *la, *a; 1223e12c5d1SDavid du Colombier 1233e12c5d1SDavid du Colombier /* delete them now */ 1243e12c5d1SDavid du Colombier la = 0; 1253e12c5d1SDavid du Colombier for(a = node->prereqs; a; la = a, a = a->next) 1263e12c5d1SDavid du Colombier if(a->flag&TOGO){ 1273e12c5d1SDavid du Colombier if(a == node->prereqs) 1283e12c5d1SDavid du Colombier node->prereqs = a->next; 1293e12c5d1SDavid du Colombier else 1303e12c5d1SDavid du Colombier la->next = a->next, a = la; 1313e12c5d1SDavid du Colombier } 1323e12c5d1SDavid du Colombier } 1333e12c5d1SDavid du Colombier 1343e12c5d1SDavid du Colombier static 1353e12c5d1SDavid du Colombier vacuous(Node *node) 1363e12c5d1SDavid du Colombier { 1373e12c5d1SDavid du Colombier Arc *la, *a; 1383e12c5d1SDavid du Colombier int vac = !(node->flags&PROBABLE); 1393e12c5d1SDavid du Colombier 1403e12c5d1SDavid du Colombier if(node->flags&READY) 1413e12c5d1SDavid du Colombier return(node->flags&VACUOUS); 1423e12c5d1SDavid du Colombier node->flags |= READY; 1433e12c5d1SDavid du Colombier for(a = node->prereqs; a; a = a->next) 1443e12c5d1SDavid du Colombier if(a->n && vacuous(a->n) && (a->r->attr&META)) 1453e12c5d1SDavid du Colombier a->flag |= TOGO; 1463e12c5d1SDavid du Colombier else 1473e12c5d1SDavid du Colombier vac = 0; 1483e12c5d1SDavid du Colombier /* if a rule generated arcs that DON'T go; no others from that rule go */ 1493e12c5d1SDavid du Colombier for(a = node->prereqs; a; a = a->next) 1503e12c5d1SDavid du Colombier if((a->flag&TOGO) == 0) 1513e12c5d1SDavid du Colombier for(la = node->prereqs; la; la = la->next) 1523e12c5d1SDavid du Colombier if((la->flag&TOGO) && (la->r == a->r)){ 1533e12c5d1SDavid du Colombier la->flag &= ~TOGO; 1543e12c5d1SDavid du Colombier } 1553e12c5d1SDavid du Colombier togo(node); 1563e12c5d1SDavid du Colombier if(vac) 1573e12c5d1SDavid du Colombier node->flags |= VACUOUS; 1583e12c5d1SDavid du Colombier return(vac); 1593e12c5d1SDavid du Colombier } 1603e12c5d1SDavid du Colombier 1613e12c5d1SDavid du Colombier static Node * 1623e12c5d1SDavid du Colombier newnode(char *name) 1633e12c5d1SDavid du Colombier { 1643e12c5d1SDavid du Colombier register Node *node; 1653e12c5d1SDavid du Colombier 1663e12c5d1SDavid du Colombier node = (Node *)Malloc(sizeof(Node)); 1673e12c5d1SDavid du Colombier symlook(name, S_NODE, (char *)node); 1683e12c5d1SDavid du Colombier node->name = name; 1693e12c5d1SDavid du Colombier node->time = timeof(name, 0); 1703e12c5d1SDavid du Colombier node->prereqs = 0; 1713e12c5d1SDavid du Colombier node->flags = node->time? PROBABLE : 0; 1723e12c5d1SDavid du Colombier node->next = 0; 1733e12c5d1SDavid du Colombier return(node); 1743e12c5d1SDavid du Colombier } 1753e12c5d1SDavid du Colombier 1763e12c5d1SDavid du Colombier void 1773e12c5d1SDavid du Colombier dumpn(char *s, Node *n) 1783e12c5d1SDavid du Colombier { 1793e12c5d1SDavid du Colombier char buf[1024]; 1803e12c5d1SDavid du Colombier Arc *a; 1813e12c5d1SDavid du Colombier 1823e12c5d1SDavid du Colombier sprint(buf, "%s ", (*s == ' ')? s:""); 1833e12c5d1SDavid du Colombier Bprint(&stdout, "%s%s@%ld: time=%ld flags=0x%x next=%ld\n", 1843e12c5d1SDavid du Colombier s, n->name, n, n->time, n->flags, n->next); 1853e12c5d1SDavid du Colombier for(a = n->prereqs; a; a = a->next) 1863e12c5d1SDavid du Colombier dumpa(buf, a); 1873e12c5d1SDavid du Colombier } 1883e12c5d1SDavid du Colombier 1893e12c5d1SDavid du Colombier static void 1903e12c5d1SDavid du Colombier trace(char *s, Arc *a) 1913e12c5d1SDavid du Colombier { 1923e12c5d1SDavid du Colombier fprint(2, "\t%s", s); 1933e12c5d1SDavid du Colombier while(a){ 1943e12c5d1SDavid du Colombier fprint(2, " <-(%s:%d)- %s", a->r->file, a->r->line, 1953e12c5d1SDavid du Colombier a->n? a->n->name:""); 1963e12c5d1SDavid du Colombier if(a->n){ 1973e12c5d1SDavid du Colombier for(a = a->n->prereqs; a; a = a->next) 1983e12c5d1SDavid du Colombier if(*a->r->recipe) break; 1993e12c5d1SDavid du Colombier } else 2003e12c5d1SDavid du Colombier a = 0; 2013e12c5d1SDavid du Colombier } 2023e12c5d1SDavid du Colombier fprint(2, "\n"); 2033e12c5d1SDavid du Colombier } 2043e12c5d1SDavid du Colombier 2053e12c5d1SDavid du Colombier static void 2063e12c5d1SDavid du Colombier cyclechk(Node *n) 2073e12c5d1SDavid du Colombier { 2083e12c5d1SDavid du Colombier Arc *a; 2093e12c5d1SDavid du Colombier 2103e12c5d1SDavid du Colombier if((n->flags&CYCLE) && n->prereqs){ 2113e12c5d1SDavid du Colombier fprint(2, "mk: cycle in graph detected at target %s\n", n->name); 2123e12c5d1SDavid du Colombier Exit(); 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier n->flags |= CYCLE; 2153e12c5d1SDavid du Colombier for(a = n->prereqs; a; a = a->next) 2163e12c5d1SDavid du Colombier if(a->n) 2173e12c5d1SDavid du Colombier cyclechk(a->n); 2183e12c5d1SDavid du Colombier n->flags &= ~CYCLE; 2193e12c5d1SDavid du Colombier } 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier static void 2223e12c5d1SDavid du Colombier ambiguous(Node *n) 2233e12c5d1SDavid du Colombier { 2243e12c5d1SDavid du Colombier Arc *a; 2253e12c5d1SDavid du Colombier Rule *r = 0; 2263e12c5d1SDavid du Colombier Arc *la; 2273e12c5d1SDavid du Colombier int bad = 0; 2283e12c5d1SDavid du Colombier 2293e12c5d1SDavid du Colombier la = 0; 2303e12c5d1SDavid du Colombier for(a = n->prereqs; a; a = a->next){ 2313e12c5d1SDavid du Colombier if(a->n) 2323e12c5d1SDavid du Colombier ambiguous(a->n); 2333e12c5d1SDavid du Colombier if(*a->r->recipe == 0) continue; 2343e12c5d1SDavid du Colombier if(r == 0) 2353e12c5d1SDavid du Colombier r = a->r, la = a; 2363e12c5d1SDavid du Colombier else{ 2373e12c5d1SDavid du Colombier if(r->recipe != a->r->recipe){ 2383e12c5d1SDavid du Colombier if((r->attr&META) && !(a->r->attr&META)){ 2393e12c5d1SDavid du Colombier la->flag |= TOGO; 2403e12c5d1SDavid du Colombier r = a->r, la = a; 2413e12c5d1SDavid du Colombier } else if(!(r->attr&META) && (a->r->attr&META)){ 2423e12c5d1SDavid du Colombier a->flag |= TOGO; 2433e12c5d1SDavid du Colombier continue; 2443e12c5d1SDavid du Colombier } 2453e12c5d1SDavid du Colombier } 2463e12c5d1SDavid du Colombier if(r->recipe != a->r->recipe){ 2473e12c5d1SDavid du Colombier if(bad == 0){ 2483e12c5d1SDavid du Colombier fprint(2, "mk: ambiguous recipes for %s:\n", n->name); 2493e12c5d1SDavid du Colombier bad = 1; 2503e12c5d1SDavid du Colombier trace(n->name, la); 2513e12c5d1SDavid du Colombier } 2523e12c5d1SDavid du Colombier trace(n->name, a); 2533e12c5d1SDavid du Colombier } 2543e12c5d1SDavid du Colombier } 2553e12c5d1SDavid du Colombier } 2563e12c5d1SDavid du Colombier if(bad) 2573e12c5d1SDavid du Colombier Exit(); 2583e12c5d1SDavid du Colombier togo(n); 2593e12c5d1SDavid du Colombier } 2603e12c5d1SDavid du Colombier 2613e12c5d1SDavid du Colombier static void 2623e12c5d1SDavid du Colombier attribute(Node *n) 2633e12c5d1SDavid du Colombier { 2643e12c5d1SDavid du Colombier register Arc *a; 2653e12c5d1SDavid du Colombier 2663e12c5d1SDavid du Colombier for(a = n->prereqs; a; a = a->next){ 2673e12c5d1SDavid du Colombier if(a->r->attr&VIR) 2683e12c5d1SDavid du Colombier n->flags |= VIRTUAL; 2693e12c5d1SDavid du Colombier if(a->r->attr&NOREC) 2703e12c5d1SDavid du Colombier n->flags |= NORECIPE; 2713e12c5d1SDavid du Colombier if(a->r->attr&DEL) 2723e12c5d1SDavid du Colombier n->flags |= DELETE; 2733e12c5d1SDavid du Colombier if(a->n) 2743e12c5d1SDavid du Colombier attribute(a->n); 2753e12c5d1SDavid du Colombier } 2763e12c5d1SDavid du Colombier if(n->flags&VIRTUAL) 2773e12c5d1SDavid du Colombier n->time = 0; 2783e12c5d1SDavid du Colombier } 279