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 18219b2ee8SDavid du Colombier cnt = rulecnt(); 19219b2ee8SDavid 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 407dd7cddfSDavid du Colombier /* print("applyrules(%lux='%s')\n", target, target);/**/ 417dd7cddfSDavid du Colombier sym = symlook(target, S_NODE, 0); 42219b2ee8SDavid du Colombier if(sym) 43*4de34a7eSDavid du Colombier return sym->u.ptr; 443e12c5d1SDavid du Colombier target = strdup(target); 453e12c5d1SDavid du Colombier node = newnode(target); 463e12c5d1SDavid du Colombier head.n = 0; 473e12c5d1SDavid du Colombier head.next = 0; 487dd7cddfSDavid du Colombier sym = symlook(target, S_TARGET, 0); 497dd7cddfSDavid du Colombier memset((char*)rmatch, 0, sizeof(rmatch)); 50*4de34a7eSDavid du Colombier for(r = sym? sym->u.ptr:0; r; r = r->chain){ 513e12c5d1SDavid du Colombier if(r->attr&META) continue; 523e12c5d1SDavid du Colombier if(strcmp(target, r->target)) continue; 53219b2ee8SDavid du Colombier if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue; /* no effect; ignore */ 543e12c5d1SDavid du Colombier if(cnt[r->rule] >= nreps) continue; 553e12c5d1SDavid du Colombier cnt[r->rule]++; 563e12c5d1SDavid du Colombier node->flags |= PROBABLE; 57219b2ee8SDavid du Colombier 583e12c5d1SDavid du Colombier /* if(r->attr&VIR) 59219b2ee8SDavid du Colombier * node->flags |= VIRTUAL; 60219b2ee8SDavid du Colombier * if(r->attr&NOREC) 61219b2ee8SDavid du Colombier * node->flags |= NORECIPE; 62219b2ee8SDavid du Colombier * if(r->attr&DEL) 63219b2ee8SDavid du Colombier * node->flags |= DELETE; 643e12c5d1SDavid du Colombier */ 653e12c5d1SDavid du Colombier if(!r->tail || !r->tail->s || !*r->tail->s) { 663e12c5d1SDavid du Colombier a->next = newarc((Node *)0, r, "", rmatch); 673e12c5d1SDavid du Colombier a = a->next; 683e12c5d1SDavid du Colombier } else 693e12c5d1SDavid du Colombier for(w = r->tail; w; w = w->next){ 703e12c5d1SDavid du Colombier a->next = newarc(applyrules(w->s, cnt), r, "", rmatch); 713e12c5d1SDavid du Colombier a = a->next; 723e12c5d1SDavid du Colombier } 733e12c5d1SDavid du Colombier cnt[r->rule]--; 743e12c5d1SDavid du Colombier head.n = node; 753e12c5d1SDavid du Colombier } 763e12c5d1SDavid du Colombier for(r = metarules; r; r = r->next){ 77219b2ee8SDavid du Colombier if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue; /* no effect; ignore */ 783e12c5d1SDavid du Colombier if ((r->attr&NOVIRT) && a != &head && (a->r->attr&VIR)) 793e12c5d1SDavid du Colombier continue; 803e12c5d1SDavid du Colombier if(r->attr®EXP){ 813e12c5d1SDavid du Colombier stem[0] = 0; 823e12c5d1SDavid du Colombier patrule = r; 837dd7cddfSDavid du Colombier memset((char*)rmatch, 0, sizeof(rmatch)); 843e12c5d1SDavid du Colombier if(regexec(r->pat, node->name, rmatch, NREGEXP) == 0) 853e12c5d1SDavid du Colombier continue; 863e12c5d1SDavid du Colombier } else { 873e12c5d1SDavid du Colombier if(!match(node->name, r->target, stem)) continue; 883e12c5d1SDavid du Colombier } 893e12c5d1SDavid du Colombier if(cnt[r->rule] >= nreps) continue; 903e12c5d1SDavid du Colombier cnt[r->rule]++; 91219b2ee8SDavid du Colombier 923e12c5d1SDavid du Colombier /* if(r->attr&VIR) 93219b2ee8SDavid du Colombier * node->flags |= VIRTUAL; 94219b2ee8SDavid du Colombier * if(r->attr&NOREC) 95219b2ee8SDavid du Colombier * node->flags |= NORECIPE; 96219b2ee8SDavid du Colombier * if(r->attr&DEL) 97219b2ee8SDavid du Colombier * node->flags |= DELETE; 983e12c5d1SDavid du Colombier */ 993e12c5d1SDavid du Colombier if(!r->tail || !r->tail->s || !*r->tail->s) { 1007dd7cddfSDavid du Colombier a->next = newarc((Node *)0, r, 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) 1059a747e4fSDavid du Colombier regsub(w->s, buf, sizeof(buf), rmatch, NREGEXP); 1063e12c5d1SDavid du Colombier else 1079a747e4fSDavid du Colombier subst(stem, w->s, buf, sizeof(buf)); 1087dd7cddfSDavid du Colombier a->next = newarc(applyrules(buf, cnt), r, 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)); 1677dd7cddfSDavid du Colombier symlook(name, S_NODE, (void *)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 1827dd7cddfSDavid du Colombier Bprint(&bout, "%s%s@%p: time=%ld flags=0x%x next=%p\n", 1833e12c5d1SDavid du Colombier s, n->name, n, n->time, n->flags, n->next); 1847dd7cddfSDavid du Colombier for(a = n->prereqs; a; a = a->next){ 1857dd7cddfSDavid du Colombier sprint(buf, "%s ", (*s == ' ')? s:""); 1863e12c5d1SDavid du Colombier dumpa(buf, a); 1873e12c5d1SDavid du Colombier } 1887dd7cddfSDavid du Colombier } 1893e12c5d1SDavid du Colombier 1903e12c5d1SDavid du Colombier static void 1913e12c5d1SDavid du Colombier trace(char *s, Arc *a) 1923e12c5d1SDavid du Colombier { 1933e12c5d1SDavid du Colombier fprint(2, "\t%s", s); 1943e12c5d1SDavid du Colombier while(a){ 1953e12c5d1SDavid du Colombier fprint(2, " <-(%s:%d)- %s", a->r->file, a->r->line, 1963e12c5d1SDavid du Colombier a->n? a->n->name:""); 1973e12c5d1SDavid du Colombier if(a->n){ 1983e12c5d1SDavid du Colombier for(a = a->n->prereqs; a; a = a->next) 1993e12c5d1SDavid du Colombier if(*a->r->recipe) break; 2003e12c5d1SDavid du Colombier } else 2013e12c5d1SDavid du Colombier a = 0; 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier fprint(2, "\n"); 2043e12c5d1SDavid du Colombier } 2053e12c5d1SDavid du Colombier 2063e12c5d1SDavid du Colombier static void 2073e12c5d1SDavid du Colombier cyclechk(Node *n) 2083e12c5d1SDavid du Colombier { 2093e12c5d1SDavid du Colombier Arc *a; 2103e12c5d1SDavid du Colombier 2113e12c5d1SDavid du Colombier if((n->flags&CYCLE) && n->prereqs){ 2123e12c5d1SDavid du Colombier fprint(2, "mk: cycle in graph detected at target %s\n", n->name); 2133e12c5d1SDavid du Colombier Exit(); 2143e12c5d1SDavid du Colombier } 2153e12c5d1SDavid du Colombier n->flags |= CYCLE; 2163e12c5d1SDavid du Colombier for(a = n->prereqs; a; a = a->next) 2173e12c5d1SDavid du Colombier if(a->n) 2183e12c5d1SDavid du Colombier cyclechk(a->n); 2193e12c5d1SDavid du Colombier n->flags &= ~CYCLE; 2203e12c5d1SDavid du Colombier } 2213e12c5d1SDavid du Colombier 2223e12c5d1SDavid du Colombier static void 2233e12c5d1SDavid du Colombier ambiguous(Node *n) 2243e12c5d1SDavid du Colombier { 2253e12c5d1SDavid du Colombier Arc *a; 2263e12c5d1SDavid du Colombier Rule *r = 0; 2273e12c5d1SDavid du Colombier Arc *la; 2283e12c5d1SDavid du Colombier int bad = 0; 2293e12c5d1SDavid du Colombier 2303e12c5d1SDavid du Colombier la = 0; 2313e12c5d1SDavid du Colombier for(a = n->prereqs; a; a = a->next){ 2323e12c5d1SDavid du Colombier if(a->n) 2333e12c5d1SDavid du Colombier ambiguous(a->n); 2343e12c5d1SDavid du Colombier if(*a->r->recipe == 0) continue; 2353e12c5d1SDavid du Colombier if(r == 0) 2363e12c5d1SDavid du Colombier r = a->r, la = a; 2373e12c5d1SDavid du Colombier else{ 2383e12c5d1SDavid du Colombier if(r->recipe != a->r->recipe){ 2393e12c5d1SDavid du Colombier if((r->attr&META) && !(a->r->attr&META)){ 2403e12c5d1SDavid du Colombier la->flag |= TOGO; 2413e12c5d1SDavid du Colombier r = a->r, la = a; 2423e12c5d1SDavid du Colombier } else if(!(r->attr&META) && (a->r->attr&META)){ 2433e12c5d1SDavid du Colombier a->flag |= TOGO; 2443e12c5d1SDavid du Colombier continue; 2453e12c5d1SDavid du Colombier } 2463e12c5d1SDavid du Colombier } 2473e12c5d1SDavid du Colombier if(r->recipe != a->r->recipe){ 2483e12c5d1SDavid du Colombier if(bad == 0){ 2493e12c5d1SDavid du Colombier fprint(2, "mk: ambiguous recipes for %s:\n", n->name); 2503e12c5d1SDavid du Colombier bad = 1; 2513e12c5d1SDavid du Colombier trace(n->name, la); 2523e12c5d1SDavid du Colombier } 2533e12c5d1SDavid du Colombier trace(n->name, a); 2543e12c5d1SDavid du Colombier } 2553e12c5d1SDavid du Colombier } 2563e12c5d1SDavid du Colombier } 2573e12c5d1SDavid du Colombier if(bad) 2583e12c5d1SDavid du Colombier Exit(); 2593e12c5d1SDavid du Colombier togo(n); 2603e12c5d1SDavid du Colombier } 2613e12c5d1SDavid du Colombier 2623e12c5d1SDavid du Colombier static void 2633e12c5d1SDavid du Colombier attribute(Node *n) 2643e12c5d1SDavid du Colombier { 2653e12c5d1SDavid du Colombier register Arc *a; 2663e12c5d1SDavid du Colombier 2673e12c5d1SDavid du Colombier for(a = n->prereqs; a; a = a->next){ 2683e12c5d1SDavid du Colombier if(a->r->attr&VIR) 2693e12c5d1SDavid du Colombier n->flags |= VIRTUAL; 2703e12c5d1SDavid du Colombier if(a->r->attr&NOREC) 2713e12c5d1SDavid du Colombier n->flags |= NORECIPE; 2723e12c5d1SDavid du Colombier if(a->r->attr&DEL) 2733e12c5d1SDavid du Colombier n->flags |= DELETE; 2743e12c5d1SDavid du Colombier if(a->n) 2753e12c5d1SDavid du Colombier attribute(a->n); 2763e12c5d1SDavid du Colombier } 2773e12c5d1SDavid du Colombier if(n->flags&VIRTUAL) 2783e12c5d1SDavid du Colombier n->time = 0; 2793e12c5d1SDavid du Colombier } 280