home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume12 / pathalias9 / part01 / addlink.c next >
Encoding:
C/C++ Source or Header  |  1987-10-08  |  4.6 KB  |  231 lines

  1. /* pathalias -- by steve bellovin, as told to peter honeyman */
  2. #ifndef lint
  3. static char    *sccsid = "@(#)addlink.c    9.1 87/10/04";
  4. #endif /* lint */
  5.  
  6. #include "def.h"
  7.  
  8. /* exports */
  9. extern link *addlink();
  10. extern void deadlink(), atrace();
  11. extern int tracelink();
  12. char *Netchars = "!:@%";    /* sparse, but sufficient */
  13. long Lcount;            /* how many edges? */
  14.  
  15.  
  16. /* imports */
  17. extern int Tflag, Dflag;
  18. extern link *newlink();
  19. extern node *addnode();
  20. extern void yyerror(), die();
  21.  
  22. /* privates */
  23. STATIC void netbits(), ltrace(), ltrprint();
  24. static link    *Trace[NTRACE];
  25. static int    Tracecount;
  26.  
  27. link *
  28. addlink(from, to, cost, netchar, netdir)
  29.     node *from;
  30.     register node *to;
  31.     Cost cost;
  32.     char netchar, netdir;
  33. {    register link *l, *prev = 0;
  34.  
  35.     if (Tflag)
  36.         ltrace(from, to, cost, netchar, netdir);
  37.     /*
  38.      * maintain uniqueness for dead links (only).
  39.      */
  40.     for (l = from->n_link; l; l = l->l_next) {
  41.         if (!(l->l_flag & LDEAD))
  42.             break;
  43.         if (to == l->l_to) {
  44.             /* what the hell, use cheaper dead cost */
  45.             if (cost < l->l_cost) {
  46.                 l->l_cost = cost;
  47.                 netbits(l, netchar, netdir);
  48.             }
  49.             return l;
  50.         }
  51.         prev = l;
  52.     }
  53.     
  54.  
  55.     /* allocate and link in the new link struct */
  56.     l = newlink();
  57.     if (cost != INF)    /* ignore back links */
  58.         Lcount++;
  59.     if (prev) {
  60.         l->l_next = prev->l_next;
  61.         prev->l_next = l;
  62.     } else {
  63.         l->l_next = from->n_link;
  64.         from->n_link = l;
  65.     }
  66.  
  67.     l->l_to = to;
  68.     l->l_cost = cost + from->n_cost;    /* add penalty */
  69.     if (netchar == 0) {
  70.         netchar = DEFNET;
  71.         netdir = DEFDIR;
  72.     }
  73.     netbits(l, netchar, netdir);
  74.     if (Dflag && ISADOMAIN(from) && !ISADOMAIN(to))
  75.         l->l_flag |= LTERMINAL;
  76.  
  77.     return l;
  78. }
  79.  
  80. void
  81. deadlink(nleft, nright) 
  82.     node *nleft, *nright;
  83. {    link *l, *lhold = 0, *lprev, *lnext;
  84.  
  85.     /* DEAD host */
  86.     if (nright == 0) {
  87.         nleft->n_flag |= NDEAD;        /* DEAD host */
  88.         return;
  89.     }
  90.  
  91.     /* DEAD link */
  92.  
  93.     /* grab <nleft, nright> instances at head of nleft adjacency list */
  94.     while ((l = nleft->n_link) != 0 && l->l_to == nright) {
  95.         nleft->n_link = l->l_next;    /* disconnect */
  96.         l->l_next = lhold;        /* terminate */
  97.         lhold = l;            /* add to lhold */
  98.     }
  99.  
  100.     /* move remaining <nleft, nright> instances */
  101.     for (lprev = nleft->n_link; lprev && lprev->l_next; lprev = lprev->l_next) {
  102.         if (lprev->l_next->l_to == nright) {
  103.             l = lprev->l_next;
  104.             lprev->l_next = l->l_next;    /* disconnect */
  105.             l->l_next = lhold;        /* terminate */
  106.             lhold = l;
  107.         }
  108.     }
  109.  
  110.     /* check for emptiness */
  111.     if (lhold == 0) {
  112.         addlink(nleft, nright, INF / 2, DEFNET, DEFDIR)->l_flag |= LDEAD;
  113.         return;
  114.     }
  115.  
  116.     /* reinsert deleted edges as DEAD links */
  117.     for (l = lhold; l; l = lnext) {
  118.         lnext = l->l_next;
  119.         addlink(nleft, nright, l->l_cost, NETCHAR(l), NETDIR(l))->l_flag |= LDEAD;
  120.         freelink(l);
  121.     }
  122. }
  123.  
  124. STATIC void
  125. netbits(l, netchar, netdir)
  126.     register link *l;
  127.     char netchar, netdir;
  128. {
  129.     l->l_flag &= ~LDIR;
  130.     l->l_flag |= netdir;
  131.     l->l_netop = netchar;
  132. }
  133.  
  134. int
  135. tracelink(arg) 
  136.     char *arg;
  137. {    char *bang;
  138.     link *l;
  139.  
  140.     if (Tracecount >= NTRACE)
  141.         return -1;
  142.     l = newlink();
  143.     bang = index(arg, '!');
  144.     if (bang) {
  145.         *bang = 0;
  146.         l->l_to = addnode(bang+1);
  147.     } else 
  148.         l->l_to = 0;
  149.  
  150.     l->l_from = addnode(arg);
  151.     Trace[Tracecount++] = l;
  152.     return 0;
  153. }
  154.  
  155. STATIC void
  156. ltrace(from, to, cost, netchar, netdir)
  157.     node *from, *to;
  158.     Cost cost;
  159.     char netchar, netdir;
  160. {    link *l;
  161.     int i;
  162.  
  163.     for (i = 0; i < Tracecount; i++) {
  164.         l = Trace[i];
  165.         /* overkill, but you asked for it! */
  166.         if ((l->l_to == 0
  167.           && (from == (node *) l->l_from || to == (node *) l->l_from))
  168.          || (from == (node *) l->l_from && to == l->l_to)
  169.          || (to == (node *) l->l_from && from == l->l_to)) {
  170.             ltrprint(from, to, cost, netchar, netdir);
  171.             return;
  172.         }
  173.     }
  174. }
  175.  
  176. /* print a trace item */
  177. STATIC void
  178. ltrprint(from, to, cost, netchar, netdir)
  179.     node *from, *to;
  180.     Cost cost;
  181.     char netchar;
  182.     char netdir;
  183. {    char buf[256], *bptr = buf;
  184.  
  185.     strcpy(bptr, from->n_name);
  186.     bptr += strlen(bptr);
  187.     *bptr++ = ' ';
  188.     if (netdir == LRIGHT)            /* @% */
  189.         *bptr++ = netchar;
  190.     strcpy(bptr, to->n_name);
  191.     bptr += strlen(bptr);
  192.     if (netdir == LLEFT)            /* !: */
  193.         *bptr++ = netchar;
  194.     sprintf(bptr, "(%ld)", cost);
  195.     yyerror(buf);
  196. }
  197.  
  198. void
  199. atrace(n1, n2)
  200.     node *n1, *n2;
  201. {    link *l;
  202.     int i;
  203.     char buf[256];
  204.  
  205.     for (i = 0; i < Tracecount; i++) {
  206.         l = Trace[i];
  207.         if (l->l_to == 0 && ((node *) l->l_from == n1 || (node *) l->l_from == n2)) {
  208.             sprintf(buf, "%s = %s", n1->n_name, n2->n_name);
  209.             yyerror(buf);
  210.             return;
  211.         }
  212.     }
  213. }
  214.  
  215. #define EQ(n1, n2) strcmp(n1->n_name, n2->n_name) == 0
  216. maptrace(from, to)
  217.     register node *from, *to;
  218. {    register link *l;
  219.     register int i;
  220.  
  221.     for (i = 0; i < Tracecount; i++) {
  222.         l = Trace[i];
  223.         if (l->l_to == 0) {
  224.             if (EQ(from, l->l_from) || EQ(to, l->l_from))
  225.                 return 1;
  226.         } else if (EQ(from, l->l_from) && EQ(to, l->l_to))
  227.                 return 1;
  228.     }
  229.     return 0;
  230. }
  231.