Logo Search packages:      
Sourcecode: 9base version File versions  Download package

graph.c

#include    "mk.h"

static Node *applyrules(char *, char *);
static void togo(Node *);
static int vacuous(Node *);
static Node *newnode(char *);
static void trace(char *, Arc *);
static void cyclechk(Node *);
static void ambiguous(Node *);
static void attribute(Node *);

Node *
graph(char *target)
{
      Node *node;
      char *cnt;

      cnt = rulecnt();
      node = applyrules(target, cnt);
      free(cnt);
      cyclechk(node);
      node->flags |= PROBABLE;      /* make sure it doesn't get deleted */
      vacuous(node);
      ambiguous(node);
      attribute(node);
      return(node);
}

static Node *
applyrules(char *target, char *cnt)
{
      Symtab *sym;
      Node *node;
      Rule *r;
      Arc head, *a = &head;
      Word *w;
      char stem[NAMEBLOCK], buf[NAMEBLOCK];
      Resub rmatch[NREGEXP];

/*    print("applyrules(%lux='%s')\n", target, target);*//**/
      sym = symlook(target, S_NODE, 0);
      if(sym)
            return (Node *)(sym->value);
      target = strdup(target);
      node = newnode(target);
      head.n = 0;
      head.next = 0;
      sym = symlook(target, S_TARGET, 0);
      memset((char*)rmatch, 0, sizeof(rmatch));
      for(r = sym? (Rule *)(sym->value):0; r; r = r->chain){
            if(r->attr&META) continue;
            if(strcmp(target, r->target)) continue;
            if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue;    /* no effect; ignore */
            if(cnt[r->rule] >= nreps) continue;
            cnt[r->rule]++;
            node->flags |= PROBABLE;

/*          if(r->attr&VIR)
 *                node->flags |= VIRTUAL;
 *          if(r->attr&NOREC)
 *                node->flags |= NORECIPE;
 *          if(r->attr&DEL)
 *                node->flags |= DELETE;
 */
            if(!r->tail || !r->tail->s || !*r->tail->s) {
                  a->next = newarc((Node *)0, r, "", rmatch);
                  a = a->next;
            } else
                  for(w = r->tail; w; w = w->next){
                        a->next = newarc(applyrules(w->s, cnt), r, "", rmatch);
                        a = a->next;
            }
            cnt[r->rule]--;
            head.n = node;
      }
      for(r = metarules; r; r = r->next){
            if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue;    /* no effect; ignore */
            if ((r->attr&NOVIRT) && a != &head && (a->r->attr&VIR))
                  continue;
            if(r->attr&REGEXP){
                  stem[0] = 0;
                  patrule = r;
                  memset((char*)rmatch, 0, sizeof(rmatch));
                  if(regexec(r->pat, node->name, rmatch, NREGEXP) == 0)
                        continue;
            } else {
                  if(!match(node->name, r->target, stem, r->shellt)) continue;
            }
            if(cnt[r->rule] >= nreps) continue;
            cnt[r->rule]++;

/*          if(r->attr&VIR)
 *                node->flags |= VIRTUAL;
 *          if(r->attr&NOREC)
 *                node->flags |= NORECIPE;
 *          if(r->attr&DEL)
 *                node->flags |= DELETE;
 */

            if(!r->tail || !r->tail->s || !*r->tail->s) {
                  a->next = newarc((Node *)0, r, stem, rmatch);
                  a = a->next;
            } else
                  for(w = r->tail; w; w = w->next){
                        if(r->attr&REGEXP)
                              regsub(w->s, buf, sizeof buf, rmatch, NREGEXP);
                        else
                              subst(stem, w->s, buf);
                        a->next = newarc(applyrules(buf, cnt), r, stem, rmatch);
                        a = a->next;
                  }
            cnt[r->rule]--;
      }
      a->next = node->prereqs;
      node->prereqs = head.next;
      return(node);
}

static void
togo(Node *node)
{
      Arc *la, *a;

      /* delete them now */
      la = 0;
      for(a = node->prereqs; a; la = a, a = a->next)
            if(a->flag&TOGO){
                  if(a == node->prereqs)
                        node->prereqs = a->next;
                  else
                        la->next = a->next, a = la;
            }
}

static int
vacuous(Node *node)
{
      Arc *la, *a;
      int vac = !(node->flags&PROBABLE);

      if(node->flags&READY)
            return(node->flags&VACUOUS);
      node->flags |= READY;
      for(a = node->prereqs; a; a = a->next)
            if(a->n && vacuous(a->n) && (a->r->attr&META))
                  a->flag |= TOGO;
            else
                  vac = 0;
      /* if a rule generated arcs that DON'T go; no others from that rule go */
      for(a = node->prereqs; a; a = a->next)
            if((a->flag&TOGO) == 0)
                  for(la = node->prereqs; la; la = la->next)
                        if((la->flag&TOGO) && (la->r == a->r)){
                              la->flag &= ~TOGO;
                        }
      togo(node);
      if(vac)
            node->flags |= VACUOUS;
      return(vac);
}

static Node *
newnode(char *name)
{
      register Node *node;

      node = (Node *)Malloc(sizeof(Node));
      symlook(name, S_NODE, (void *)node);
      node->name = name;
      node->time = timeof(name, 0);
      node->prereqs = 0;
      node->flags = node->time? PROBABLE : 0;
      node->next = 0;
      return(node);
}

void
dumpn(char *s, Node *n)
{
      char buf[1024];
      Arc *a;

      snprint(buf, sizeof buf, "%s   ", (*s == ' ')? s:"");
      Bprint(&bout, "%s%s@%ld: time=%ld flags=0x%x next=%ld\n",
            s, n->name, n, n->time, n->flags, n->next);
      for(a = n->prereqs; a; a = a->next)
            dumpa(buf, a);
}

static void
trace(char *s, Arc *a)
{
      fprint(2, "\t%s", s);
      while(a){
            fprint(2, " <-(%s:%d)- %s", a->r->file, a->r->line,
                  a->n? a->n->name:"");
            if(a->n){
                  for(a = a->n->prereqs; a; a = a->next)
                        if(*a->r->recipe) break;
            } else
                  a = 0;
      }
      fprint(2, "\n");
}

static void
cyclechk(Node *n)
{
      Arc *a;

      if((n->flags&CYCLE) && n->prereqs){
            fprint(2, "mk: cycle in graph detected at target %s\n", n->name);
            Exit();
      }
      n->flags |= CYCLE;
      for(a = n->prereqs; a; a = a->next)
            if(a->n)
                  cyclechk(a->n);
      n->flags &= ~CYCLE;
}

static void
ambiguous(Node *n)
{
      Arc *a;
      Rule *r = 0;
      Arc *la;
      int bad = 0;

      la = 0;
      for(a = n->prereqs; a; a = a->next){
            if(a->n)
                  ambiguous(a->n);
            if(*a->r->recipe == 0) continue;
            if(r == 0)
                  r = a->r, la = a;
            else{
                  if(r->recipe != a->r->recipe){
                        if((r->attr&META) && !(a->r->attr&META)){
                              la->flag |= TOGO;
                              r = a->r, la = a;
                        } else if(!(r->attr&META) && (a->r->attr&META)){
                              a->flag |= TOGO;
                              continue;
                        }
                  }
                  if(r->recipe != a->r->recipe){
                        if(bad == 0){
                              fprint(2, "mk: ambiguous recipes for %s:\n", n->name);
                              bad = 1;
                              trace(n->name, la);
                        }
                        trace(n->name, a);
                  }
            }
      }
      if(bad)
            Exit();
      togo(n);
}

static void
attribute(Node *n)
{
      register Arc *a;

      for(a = n->prereqs; a; a = a->next){
            if(a->r->attr&VIR)
                  n->flags |= VIRTUAL;
            if(a->r->attr&NOREC)
                  n->flags |= NORECIPE;
            if(a->r->attr&DEL)
                  n->flags |= DELETE;
            if(a->n)
                  attribute(a->n);
      }
      if(n->flags&VIRTUAL)
            n->time = 0;
}

Generated by  Doxygen 1.6.0   Back to index