1: /* pathalias -- by steve bellovin, as told to peter honeyman */
   2: #ifndef lint
   3: static char *sccsid = "@(#)addnode.c	9.1 87/10/04";
   4: #endif
   5: 
   6: #include "def.h"
   7: 
   8: /* exports */
   9: p_node addnode();
  10: p_node addprivate();
  11: void alias(), hashanalyze(), fixprivate(), penalize();
  12: p_node *Table;              /* hash table ^ priority queue */
  13: long Tabsize;               /* size of Table */
  14: 
  15: /* imports */
  16: extern p_link addlink();
  17: extern p_node newnode();
  18: extern p_node *newtable();
  19: #ifndef TMPFILES
  20: #define getnode(x) x
  21: #define getlink(y) y
  22: #else  /*TMPFILES*/
  23: extern node *getnode();
  24: extern link *getlink();
  25: #endif /*TMPFILES*/
  26: extern char *strsave();
  27: extern int Iflag, Tflag, Vflag;
  28: extern p_node *Table;
  29: extern long Ncount, Tabsize;
  30: extern char **Argv;
  31: extern void atrace(), die();
  32: 
  33: /* privates */
  34: STATIC void crcinit(), rehash(), lowercase();
  35: STATIC long fold();
  36: STATIC long hash();
  37: STATIC p_node isprivate();
  38: static p_node Private;  /* list of private nodes in current input file */
  39: /*
  40:  * these numbers are chosen because:
  41:  *	-> they are prime,
  42:  *	-> they are monotonic increasing,
  43:  *	-> each is a tad smaller than a multiple of 1024,
  44:  *	-> they form a fibonacci sequence (almost).
  45:  * the first point yields good hash functions, the second is used for the
  46:  * standard re-hashing implementation of open addressing, the third
  47:  * optimizes for quirks in some mallocs i have seen, and the fourth simply
  48:  * appeals to me.
  49:  */
  50: static long Primes[] = {
  51: #ifndef TMPFILES
  52:     1021, 2039, 3067, 5113, 8179, 13309, 21499, 34807, 56311, 0
  53: #else /*TMPFILES*/
  54:     20183, 34807, 56311, 0  /* 21499 almost fits, 13309 + 8179 doesn't. */
  55: #endif /*TMPFILES*/
  56: };
  57: 
  58: static int  Tabindex;
  59: static long Tab128;     /* Tabsize * 128 */
  60: 
  61: p_node
  62: addnode(name)
  63:     register char *name;
  64: {   register long i;
  65:     register p_node n;
  66: 
  67:     if (Iflag)
  68:         lowercase(name);
  69: 
  70: #ifdef TMPFILES
  71:     if (strlen(name) >= MAXNAME) {
  72:         fprintf(stderr, "name %s exceeds maximum length %d\n",
  73:             name, MAXNAME);
  74:         die("name too long");
  75:     }
  76: #endif
  77: 
  78:     /* is it a private host? */
  79:     n = isprivate(name);
  80:     if (n)
  81:         return n;
  82: 
  83:     i = hash(name, 0);
  84:     if (Table[i])
  85:         return Table[i];
  86: 
  87:     n = newnode();
  88:     getnode(n)->n_name = strsave(name);
  89:     Table[i] = n;
  90:     getnode(n)->n_tloc = i; /* essentially a back link to the table */
  91: 
  92:     return n;
  93: }
  94: 
  95: void
  96: alias(n1, n2)
  97:     p_node n1;
  98:     p_node n2;
  99: {
 100:     p_link  l;
 101: 
 102:     if (ISADOMAIN(getnode(n1)) && ISADOMAIN(getnode(n2))) {
 103:         fprintf(stderr, "%s: domain alias %s = %s is illegal\n",
 104:             Argv[0], getnode(n1)->n_name, getnode(n2)->n_name);
 105:         return;
 106:     }
 107:     l = addlink(n1, n2, (Cost) 0, DEFNET, DEFDIR);
 108:     getlink(l)->l_flag |= LALIAS;
 109:     l = addlink(n2, n1, (Cost) 0, DEFNET, DEFDIR);
 110:     getlink(l)->l_flag |= LALIAS;
 111:     if (Tflag)
 112:         atrace(n1, n2);
 113: }
 114: 
 115: /*
 116:  * fold a string into a long int.  31 bit crc (from andrew appel).
 117:  * the crc table is computed at run time by crcinit() -- we could
 118:  * precompute, but it takes 1 clock tick on a 750.
 119:  *
 120:  * This fast table calculation works only if POLY is a prime polynomial
 121:  * in the field of integers modulo 2.  Since the coefficients of a
 122:  * 32-bit polynomail won't fit in a 32-bit word, the high-order bit is
 123:  * implicit.  IT MUST ALSO BE THE CASE that the coefficients of orders
 124:  * 31 down to 25 are zero.  Happily, we have candidates, from
 125:  * E. J.  Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962):
 126:  *	x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0
 127:  *	x^31 + x^3 + x^0
 128:  *
 129:  * We reverse the bits to get:
 130:  *	111101010000000000000000000000001 but drop the last 1
 131:  *         f   5   0   0   0   0   0   0
 132:  *	010010000000000000000000000000001 ditto, for 31-bit crc
 133:  *	   4   8   0   0   0   0   0   0
 134:  */
 135: 
 136: #define POLY32 0xf5000000   /* 32-bit polynomial */
 137: #define POLY31 0x48000000   /* 31-bit polynomial */
 138: #define POLY POLY31 /* use 31-bit to avoid sign problems */
 139: 
 140: static long CrcTable[128];
 141: 
 142: STATIC void
 143: crcinit()
 144: {   register int i,j;
 145:     register long sum;
 146: 
 147:     for (i = 0; i < 128; i++) {
 148:         sum = 0;
 149:         for (j = 7-1; j >= 0; --j)
 150:             if (i & (1 << j))
 151:                 sum ^= POLY >> j;
 152:         CrcTable[i] = sum;
 153:     }
 154: }
 155: 
 156: STATIC long
 157: fold(s)
 158:     register char *s;
 159: {   register long sum = 0;
 160:     register int c;
 161: 
 162:     while (c = *s++)
 163:         sum = (sum >> 7) ^ CrcTable[(sum ^ c) & 0x7f];
 164:     return sum;
 165: }
 166: 
 167: 
 168: #define HASH1(n) ((n) % Tabsize);
 169: #define HASH2(n) (Tabsize - 2 - ((n) % (Tabsize-2)))    /* sedgewick */
 170: 
 171: /*
 172:  * when alpha is 0.79, there should be 2 probes per access (gonnet).
 173:  * use long constant to force promotion.  Tab128 biases HIGHWATER by
 174:  * 128/100 for reduction in strength in isfull().
 175:  */
 176: #define HIGHWATER   79L
 177: #define isfull(n)   ((n) * 128 >= Tab128)
 178: 
 179: STATIC long
 180: hash(name, unique)
 181:     char *name;
 182: {   register long probe;
 183:     register long hash2;
 184:     register p_node n;
 185: #ifdef TMPFILES
 186:     char cache_keep[MAXNAME];   /* The name may not stay in the
 187: 					 * cache during a rehash(). */
 188:     name = strcpy(cache_keep, name);
 189: #endif /*TMPFILES*/
 190:     if (isfull(Ncount)) {
 191:         if (Tabsize == 0) {     /* first time */
 192:             crcinit();
 193:             Tabindex = 0;
 194:             Tabsize = Primes[0];
 195:             Table = newtable(Tabsize);
 196:             Tab128 = (HIGHWATER * Tabsize * 128L)/100L;
 197:         } else
 198:             rehash();       /* more, more! */
 199:     }
 200: 
 201:     probe = fold(name);
 202:     hash2 = HASH2(probe);
 203:     probe = HASH1(probe);
 204: 
 205:     /*
 206: 	 * probe the hash table.
 207: 	 * if unique is set, we require a fresh slot.
 208: 	 * otherwise, use double hashing to find either
 209: 	 *  (1) an empty slot, or
 210: 	 *  (2) a non-private copy of this host name
 211: 	 */
 212:     while ((n = Table[probe]) != 0) {
 213:         if (unique)
 214:             goto skip;
 215:         if (getnode(n)->n_flag & ISPRIVATE)
 216:             goto skip;
 217:         if (strcmp(getnode(n)->n_name, name) == 0)
 218:             break;          /* this is it! */
 219: skip:
 220:         probe -= hash2;
 221:         if (probe < 0)
 222:             probe += Tabsize;
 223:     }
 224:     return probe;
 225: }
 226: 
 227: STATIC void
 228: rehash()
 229: {   register p_node *otable;
 230:     register p_node *optr;
 231:     register long probe;
 232:     long osize;
 233: 
 234: #ifdef DEBUG
 235:     hashanalyze();
 236: #endif
 237:     optr = Table + Tabsize - 1; /* ptr to last */
 238:     otable = Table;
 239:     osize = Tabsize;
 240:     Tabsize = Primes[++Tabindex];
 241:     if (Tabsize == 0)
 242:         die("too many hosts");  /* need more prime numbers */
 243:     vprintf(stderr, "rehash into %ld\n", Tabsize);
 244:     Table = newtable(Tabsize);
 245:     Tab128 = (HIGHWATER * Tabsize * 128L)/100L;
 246: 
 247:     do {
 248:         if (*optr == 0)
 249:             continue;   /* empty slot in old table */
 250:         probe = hash(getnode((*optr))->n_name,
 251:                  (int) (getnode((*optr))->n_flag & ISPRIVATE));
 252:         if (Table[probe] != 0)
 253:             die("rehash error");
 254:         Table[probe] = *optr;
 255:         getnode((*optr))->n_tloc = probe;
 256:     } while (optr-- > otable);
 257:     freetable(otable, osize);
 258: }
 259: 
 260: void
 261: hashanalyze()
 262: {   long    probe, hash2;
 263:     int count, i, collision[8];
 264:     int longest = 0, total = 0, slots = 0, longprobe = 0;
 265:     int nslots = sizeof(collision)/sizeof(collision[0]);
 266: 
 267:     if (!Vflag)
 268:         return;
 269: 
 270:     strclear((char *) collision, sizeof(collision));
 271:     for (i = 0; i < Tabsize; i++) {
 272:         if (Table[i] == 0)
 273:             continue;
 274:         /* private hosts too hard to account for ... */
 275:         if (getnode(Table[i])->n_flag & ISPRIVATE)
 276:             continue;
 277:         count = 1;
 278:         probe = fold(getnode(Table[i])->n_name);
 279:         /* don't change the order of the next two lines */
 280:         hash2 = HASH2(probe);
 281:         probe = HASH1(probe);
 282:         /* thank you! */
 283:         while (Table[probe] != 0
 284:             && strcmp(getnode(Table[probe])->n_name,
 285:                   getnode(Table[i])->n_name) != 0) {
 286:             count++;
 287:             probe -= hash2;
 288:             if (probe < 0)
 289:                 probe += Tabsize;
 290:         }
 291:         if (Table[probe] == 0)
 292:             die("impossible hash error");
 293:         total += count;
 294:         slots++;
 295:         if (count > longest) {
 296:             longest = count;
 297:             longprobe = i;
 298:         }
 299:         if (count >= nslots)
 300:             count = 0;
 301:         collision[count]++;
 302:     }
 303:     for (i = 1; i < nslots; i++)
 304:         if (collision[i])
 305:             fprintf(stderr, "%d chains: %d (%ld%%)\n",
 306:                 i, collision[i], (collision[i] * 100L)/ slots);
 307:         if (collision[0])
 308:             fprintf(stderr, "> %d chains: %d (%ld%%)\n",
 309:                 nslots - 1, collision[0],
 310:                 (collision[0] * 100L)/ slots);
 311:     fprintf(stderr, "%2.2f probes per access, longest chain: %d, %s\n",
 312:         (double) total / slots, longest, getnode(Table[longprobe])->n_name);
 313:     if (Vflag < 2)
 314:         return;
 315:     probe = fold(getnode(Table[longprobe])->n_name);
 316:     hash2 = HASH2(probe);
 317:     probe = HASH1(probe);
 318:     while (Table[probe] != 0
 319:         && strcmp(getnode(Table[probe])->n_name,
 320:               getnode(Table[longprobe])->n_name) != 0) {
 321:         fprintf(stderr, "%5d %s\n", probe, getnode(Table[probe])->n_name);
 322:         probe -= hash2;
 323:         if (probe < 0)
 324:             probe += Tabsize;
 325:     }
 326:     fprintf(stderr, "%5d %s\n", probe, getnode(Table[probe])->n_name);
 327: 
 328: }
 329: 
 330: /* convert to lower case in place */
 331: STATIC void
 332: lowercase(s)
 333:     register char *s;
 334: {
 335:     do {
 336:         if (isupper(*s))
 337:             *s -= 'A' - 'a';    /* ASCII */
 338:     } while (*s++);
 339: }
 340: 
 341: /*
 342:  * this might need change if privates catch on
 343:  */
 344: STATIC p_node
 345: isprivate(name)
 346:     register char *name;
 347: {   register p_node n;
 348: 
 349:     for (n = Private; n != 0; n = getnode(n)->n_private)
 350:         if (strcmp(name, getnode(n)->n_name) == 0)
 351:             return n;
 352:     return 0;
 353: }
 354: 
 355: void
 356: fixprivate()
 357: {   register p_node n;
 358:     register p_node next;
 359:     register long i;
 360: 
 361:     for (n = Private; n != 0; n = next) {
 362:         getnode(n)->n_flag |= ISPRIVATE;  /* overkill, but safe */
 363:         i = hash(getnode(n)->n_name, 1);
 364:         if (Table[i] != 0)
 365:             die("impossible private node error");
 366: 
 367:         Table[i] = n;
 368:         getnode(n)->n_tloc = i; /* essentially a back link to the table */
 369:         next = getnode(n)->n_private;
 370:         getnode(n)->n_private = 0;  /* clear for later use */
 371:     }
 372:     Private = 0;
 373: }
 374: 
 375: p_node
 376: addprivate(name)
 377:     register char *name;
 378: {   register p_node n;
 379: 
 380:     if (Iflag)
 381:         lowercase(name);
 382:     if ((n = isprivate(name)) != 0)
 383:         return n;
 384: 
 385:     n = newnode();
 386:     getnode(n)->n_name = strsave(name);
 387:     getnode(n)->n_private = Private;
 388:     Private = n;
 389:     return n;
 390: }
 391: 
 392: void
 393: penalize(name, cost)
 394:     char *name;
 395:     Cost cost;
 396: {   p_node n;
 397: 
 398:     if (Iflag)
 399:         lowercase(name);
 400:     n = addnode(name);
 401:     getnode(n)->n_cost += cost; /* cumulative */
 402: }

Defined functions

addnode defined in line 61; used 21 times
addprivate defined in line 375; used 3 times
alias defined in line 95; used 4 times
crcinit defined in line 142; used 2 times
fixprivate defined in line 355; used 4 times
fold defined in line 156; used 4 times
hash defined in line 179; used 4 times
hashanalyze defined in line 260; used 4 times
isprivate defined in line 344; used 3 times
lowercase defined in line 331; used 4 times
penalize defined in line 392; used 3 times
rehash defined in line 227; used 2 times

Defined variables

CrcTable defined in line 140; used 2 times
Primes defined in line 50; used 2 times
STATIC defined in line 331; used 8 times
Tab128 defined in line 59; used 3 times
Tabindex defined in line 58; used 2 times
Tabsize declared in line 29; defined in line 13; used 28 times
p_node defined in line 375; never used
sccsid defined in line 3; never used

Defined macros

HASH1 defined in line 168; used 3 times
HASH2 defined in line 169; used 3 times
HIGHWATER defined in line 176; used 2 times
POLY defined in line 138; used 1 times
POLY31 defined in line 137; used 1 times
POLY32 defined in line 136; never used
getlink defined in line 21; used 3 times
getnode defined in line 20; used 32 times
isfull defined in line 177; used 1 times
Last modified: 1988-03-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1768
Valid CSS Valid XHTML 1.0 Strict