home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Shells / zsh-3.0.5-MIHS / src / Src / hashtable.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-17  |  32.3 KB  |  1,387 lines

  1. /*
  2.  * $Id: hashtable.c,v 2.11 1996/10/15 20:16:35 hzoli Exp $
  3.  *
  4.  * hashtable.c - hash tables
  5.  *
  6.  * This file is part of zsh, the Z shell.
  7.  *
  8.  * Copyright (c) 1992-1996 Paul Falstad
  9.  * All rights reserved.
  10.  *
  11.  * Permission is hereby granted, without written agreement and without
  12.  * license or royalty fees, to use, copy, modify, and distribute this
  13.  * software and to distribute modified versions of this software for any
  14.  * purpose, provided that the above copyright notice and the following
  15.  * two paragraphs appear in all copies of this software.
  16.  *
  17.  * In no event shall Paul Falstad or the Zsh Development Group be liable
  18.  * to any party for direct, indirect, special, incidental, or consequential
  19.  * damages arising out of the use of this software and its documentation,
  20.  * even if Paul Falstad and the Zsh Development Group have been advised of
  21.  * the possibility of such damage.
  22.  *
  23.  * Paul Falstad and the Zsh Development Group specifically disclaim any
  24.  * warranties, including, but not limited to, the implied warranties of
  25.  * merchantability and fitness for a particular purpose.  The software
  26.  * provided hereunder is on an "as is" basis, and Paul Falstad and the
  27.  * Zsh Development Group have no obligation to provide maintenance,
  28.  * support, updates, enhancements, or modifications.
  29.  *
  30.  */
  31.  
  32. #include "zsh.h"
  33.  
  34. /********************************/
  35. /* Generic Hash Table functions */
  36. /********************************/
  37.  
  38. /* Generic hash function */
  39.  
  40. /**/
  41. unsigned
  42. hasher(char *str)
  43. {
  44.     unsigned hashval = 0;
  45.  
  46.     while (*str)
  47.     hashval += (hashval << 5) + ((unsigned) *str++);
  48.  
  49.     return hashval;
  50. }
  51.  
  52. /* Get a new hash table */
  53.  
  54. /**/
  55. HashTable
  56. newhashtable(int size)
  57. {
  58.     HashTable ht;
  59.  
  60.     ht = (HashTable) zcalloc(sizeof *ht);
  61.     ht->nodes = (HashNode *) zcalloc(size * sizeof(HashNode));
  62.     ht->hsize = size;
  63.     ht->ct = 0;
  64.     return ht;
  65. }
  66.  
  67. /* Add a node to a hash table.                          *
  68.  * nam is the key to use in hashing.  dat is a pointer  *
  69.  * to the node to add.  If there is already a node in   *
  70.  * the table with the same key, it is first freed, and  *
  71.  * then the new node is added.  If the number of nodes  *
  72.  * is now greater than twice the number of hash values, *
  73.  * the table is then expanded.                          */
  74.  
  75. /**/
  76. void
  77. addhashnode(HashTable ht, char *nam, void *nodeptr)
  78. {
  79.     unsigned hashval;
  80.     HashNode hn, hp, hq;
  81.  
  82.     hn = (HashNode) nodeptr;
  83.     hn->nam = nam;
  84.  
  85.     hashval = ht->hash(hn->nam) % ht->hsize;
  86.     hp = ht->nodes[hashval];
  87.  
  88.     /* check if this is the first node for this hash value */
  89.     if (!hp) {
  90.     hn->next = NULL;
  91.     ht->nodes[hashval] = hn;
  92.     if (++ht->ct == ht->hsize * 2)
  93.         expandhashtable(ht);
  94.     return;
  95.     }
  96.  
  97.     /* else check if the first node contains the same key */
  98.     if (!strcmp(hp->nam, hn->nam)) {
  99.     hn->next = hp->next;
  100.     ht->nodes[hashval] = hn;
  101.     ht->freenode(hp);
  102.     return;
  103.     }
  104.  
  105.     /* else run through the list and check all the keys */
  106.     hq = hp;
  107.     hp = hp->next;
  108.     for (; hp; hq = hp, hp = hp->next) {
  109.     if (!strcmp(hp->nam, hn->nam)) {
  110.         hn->next = hp->next;
  111.         hq->next = hn;
  112.         ht->freenode(hp);
  113.         return;
  114.     }
  115.     }
  116.  
  117.     /* else just add it at the front of the list */
  118.     hn->next = ht->nodes[hashval];
  119.     ht->nodes[hashval] = hn;
  120.     if (++ht->ct == ht->hsize * 2)
  121.         expandhashtable(ht);
  122. }
  123.  
  124. /* Get an enabled entry in a hash table.  *
  125.  * If successful, it returns a pointer to *
  126.  * the hashnode.  If the node is DISABLED *
  127.  * or isn't found, it returns NULL        */
  128.  
  129. /**/
  130. HashNode
  131. gethashnode(HashTable ht, char *nam)
  132. {
  133.     unsigned hashval;
  134.     HashNode hp;
  135.  
  136.     hashval = ht->hash(nam) % ht->hsize;
  137.     for (hp = ht->nodes[hashval]; hp; hp = hp->next) {
  138.     if (!strcmp(hp->nam, nam)) {
  139.         if (hp->flags & DISABLED)
  140.         return NULL;
  141.         else
  142.         return hp;
  143.     }
  144.     }
  145.     return NULL;
  146. }
  147.  
  148. /* Get an entry in a hash table.  It will *
  149.  * ignore the DISABLED flag and return a  *
  150.  * pointer to the hashnode if found, else *
  151.  * it returns NULL.                       */
  152.  
  153. /**/
  154. HashNode
  155. gethashnode2(HashTable ht, char *nam)
  156. {
  157.     unsigned hashval;
  158.     HashNode hp;
  159.  
  160.     hashval = ht->hash(nam) % ht->hsize;
  161.     for (hp = ht->nodes[hashval]; hp; hp = hp->next) {
  162.     if (!strcmp(hp->nam, nam))
  163.         return hp;
  164.     }
  165.     return NULL;
  166. }
  167.  
  168. /* Remove an entry from a hash table.           *
  169.  * If successful, it removes the node from the  *
  170.  * table and returns a pointer to it.  If there *
  171.  * is no such node, then it returns NULL        */
  172.  
  173. /**/
  174. HashNode
  175. removehashnode(HashTable ht, char *nam)
  176. {
  177.     unsigned hashval;
  178.     HashNode hp, hq;
  179.  
  180.     hashval = ht->hash(nam) % ht->hsize;
  181.     hp = ht->nodes[hashval];
  182.  
  183.     /* if no nodes at this hash value, return NULL */
  184.     if (!hp)
  185.     return NULL;
  186.  
  187.     /* else check if the key in the first one matches */
  188.     if (!strcmp(hp->nam, nam)) {
  189.     ht->nodes[hashval] = hp->next;
  190.     ht->ct--;
  191.     return hp;
  192.     }
  193.  
  194.     /* else run through the list and check the rest of the keys */
  195.     hq = hp;
  196.     hp = hp->next;
  197.     for (; hp; hq = hp, hp = hp->next) {
  198.     if (!strcmp(hp->nam, nam)) {
  199.         hq->next = hp->next;
  200.         ht->ct--;
  201.         return hp;
  202.     }
  203.     }
  204.  
  205.     /* else it is not in the list, so return NULL */
  206.     return NULL;
  207. }
  208.  
  209. /* Disable a node in a hash table */
  210.  
  211. /**/
  212. void
  213. disablehashnode(HashNode hn, int flags)
  214. {
  215.     hn->flags |= DISABLED;
  216. }
  217.  
  218. /* Enable a node in a hash table */
  219.  
  220. /**/
  221. void
  222. enablehashnode(HashNode hn, int flags)
  223. {
  224.     hn->flags &= ~DISABLED;
  225. }
  226.  
  227. /* Compare two hash table entries */
  228.  
  229. /**/
  230. int
  231. hnamcmp(struct hashnode **a, struct hashnode **b)
  232. {
  233.     return ztrcmp((unsigned char *) (*a)->nam, (unsigned char *) (*b)->nam);
  234. }
  235.  
  236. /* Scan the nodes in a hash table and execute scanfunc on nodes based on the flags *
  237.  * that are set/unset.  scanflags is passed unchanged to scanfunc (if executed).   *
  238.  *                                                                                 *
  239.  * If sorted = 1, then sort entries of hash table before scanning.                 *
  240.  * If sorted = 0, don't sort entries before scanning.                              *
  241.  * If (flags1 > 0), then execute func on a node only if these flags are set.       *
  242.  * If (flags2 > 0), then execute func on a node only if these flags are NOT set.   *
  243.  * The conditions above for flags1/flags2 must both be true.                       */
  244.  
  245. /**/
  246. void
  247. scanhashtable(HashTable ht, int sorted, int flags1, int flags2, ScanFunc scanfunc, int scanflags)
  248. {
  249.     HashNode hn, *hnsorttab, *htp;
  250.     int i;
  251.  
  252.     if (sorted) {
  253.     hnsorttab = (HashNode *) zalloc(ht->ct * sizeof(HashNode));
  254.  
  255.     for (htp = hnsorttab, i = 0; i < ht->hsize; i++)
  256.         for (hn = ht->nodes[i]; hn; hn = hn->next)
  257.         *htp++ = hn;
  258.  
  259.     qsort((void *) & hnsorttab[0], ht->ct, sizeof(HashNode),
  260.                (int (*) _((const void *, const void *))) hnamcmp);
  261.  
  262.     /* Ignore the flags */
  263.     if (!flags1 && !flags2) {
  264.         for (htp = hnsorttab, i = 0; i < ht->ct; i++, htp++)
  265.         scanfunc(*htp, scanflags);
  266.     } else if (flags1 && !flags2) {
  267.     /* Only exec scanfunc if flags1 are set */
  268.         for (htp = hnsorttab, i = 0; i < ht->ct; i++, htp++)
  269.         if ((*htp)->flags & flags1)
  270.             scanfunc(*htp, scanflags);
  271.     } else if (!flags1 && flags2) {
  272.     /* Only exec scanfunc if flags2 are NOT set */
  273.         for (htp = hnsorttab, i = 0; i < ht->ct; i++, htp++)
  274.         if (!((*htp)->flags & flags2))
  275.             scanfunc(*htp, scanflags);
  276.     } else {
  277.     /* Only exec scanfun if flags1 are set, and flags2 are NOT set */
  278.         for (htp = hnsorttab, i = 0; i < ht->ct; i++, htp++)
  279.         if (((*htp)->flags & flags1) && !((*htp)->flags & flags2))
  280.             scanfunc(*htp, scanflags);
  281.     }
  282.     free(hnsorttab);
  283.     return;
  284.     }
  285.  
  286.     /* Don't sort, just use hash order. */
  287.  
  288.     /* Ignore the flags */
  289.     if (!flags1 && !flags2) {
  290.     for (i = 0; i < ht->hsize; i++)
  291.         for (hn = ht->nodes[i]; hn; hn = hn->next)
  292.         scanfunc(hn, scanflags);
  293.     return;
  294.     }
  295.  
  296.     /* Only exec scanfunc if flags1 are set */
  297.     if (flags1 && !flags2) {
  298.     for (i = 0; i < ht->hsize; i++)
  299.         for (hn = ht->nodes[i]; hn; hn = hn->next)
  300.         if (hn->flags & flags1)
  301.             scanfunc(hn, scanflags);
  302.     return;
  303.     }
  304.  
  305.     /* Only exec scanfunc if flags2 are NOT set */
  306.     if (!flags1 && flags2) {
  307.     for (i = 0; i < ht->hsize; i++)
  308.         for (hn = ht->nodes[i]; hn; hn = hn->next)
  309.         if (!(hn->flags & flags2))
  310.             scanfunc(hn, scanflags);
  311.     return;
  312.     }
  313.  
  314.     /* Only exec scanfun if flags1 are set, and flags2 are NOT set */
  315.     for (i = 0; i < ht->hsize; i++)
  316.     for (hn = ht->nodes[i]; hn; hn = hn->next)
  317.         if ((hn->flags & flags1) && !(hn->flags & flags2))
  318.         scanfunc(hn, scanflags);
  319. }
  320.  
  321.  
  322. /* Scan all nodes in a hash table and executes scanfunc on the *
  323.  * nodes which meet all the following criteria:                *
  324.  * The hash key must match the glob pattern given by `com'.    *
  325.  * If (flags1 > 0), then all flags in flags1 must be set.      *
  326.  * If (flags2 > 0), then all flags in flags2 must NOT be set.  *
  327.  *                                                             *
  328.  * scanflags is passed unchanged to scanfunc (if executed).    *
  329.  * The return value if the number of matches.                  */
  330.  
  331. /**/
  332. int
  333. scanmatchtable(HashTable ht, Comp com, int flags1, int flags2, ScanFunc scanfunc, int scanflags)
  334. {
  335.     HashNode hn;
  336.     int i, match = 0;
  337.  
  338.     /* ignore the flags */
  339.     if (!flags1 && !flags2) {
  340.     for (i = 0; i < ht->hsize; i++) {
  341.         for (hn = ht->nodes[i]; hn; hn = hn->next) {
  342.         if (domatch(hn->nam, com, 0)) {
  343.             scanfunc(hn, scanflags);
  344.             match++;
  345.         }
  346.         }
  347.     }
  348.     return match;
  349.     }
  350.  
  351.     /* flags in flags1 must be set */
  352.     if (flags1 && !flags2) {
  353.     for (i = 0; i < ht->hsize; i++) {
  354.         for (hn = ht->nodes[i]; hn; hn = hn->next) {
  355.         if (domatch(hn->nam, com, 0) && (hn->flags & flags1)) {
  356.             scanfunc(hn, scanflags);
  357.             match++;
  358.         }
  359.         }
  360.     }
  361.     return match;
  362.     }
  363.  
  364.     /* flags in flags2 must NOT be set */
  365.     if (!flags1 && flags2) {
  366.     for (i = 0; i < ht->hsize; i++) {
  367.         for (hn = ht->nodes[i]; hn; hn = hn->next) {
  368.         if (domatch(hn->nam, com, 0) && !(hn->flags & flags2)) {
  369.             scanfunc(hn, scanflags);
  370.             match++;
  371.         }
  372.         }
  373.     }
  374.     return match;
  375.     }
  376.  
  377.     /* flags in flags1 must be set,    *
  378.      * flags in flags2 must NOT be set */
  379.     for (i = 0; i < ht->hsize; i++) {
  380.     for (hn = ht->nodes[i]; hn; hn = hn->next) {
  381.         if (domatch(hn->nam, com, 0) && (hn->flags & flags1) && !(hn->flags & flags2)) {
  382.         scanfunc(hn, scanflags);
  383.         match++;
  384.         }
  385.     }
  386.     }
  387.     return match;
  388. }
  389.  
  390.  
  391. /* Expand hash tables when they get too many entries. *
  392.  * The new size is 4 times the previous size.         */
  393.  
  394. /**/
  395. void
  396. expandhashtable(HashTable ht)
  397. {
  398.     struct hashnode **onodes, **ha, *hn, *hp;
  399.     int i, osize;
  400.  
  401.     osize = ht->hsize;
  402.     onodes = ht->nodes;
  403.  
  404.     ht->hsize = osize * 4;
  405.     ht->nodes = (HashNode *) zcalloc(ht->hsize * sizeof(HashNode));
  406.     ht->ct = 0;
  407.  
  408.     /* scan through the old list of nodes, and *
  409.      * rehash them into the new list of nodes  */
  410.     for (i = 0, ha = onodes; i < osize; i++, ha++) {
  411.     for (hn = *ha; hn;) {
  412.         hp = hn->next;
  413.         ht->addnode(ht, hn->nam, hn);
  414.         hn = hp;
  415.     }
  416.     }
  417.     zfree(onodes, osize * sizeof(HashNode));
  418. }
  419.  
  420. /* Empty the hash table and resize it if necessary */
  421.  
  422. /**/
  423. void
  424. emptyhashtable(HashTable ht, int newsize)
  425. {
  426.     struct hashnode **ha, *hn, *hp;
  427.     int i;
  428.  
  429.     /* free all the hash nodes */
  430.     ha = ht->nodes;
  431.     for (i = 0; i < ht->hsize; i++, ha++) {
  432.     for (hn = *ha; hn;) {
  433.         hp = hn->next;
  434.         ht->freenode(hn);
  435.         hn = hp;
  436.     }
  437.     }
  438.  
  439.     /* If new size desired is different from current size, *
  440.      * we free it and allocate a new nodes array.          */
  441.     if (ht->hsize != newsize) {
  442.     zfree(ht->nodes, ht->hsize * sizeof(HashNode));
  443.     ht->nodes = (HashNode *) zcalloc(newsize * sizeof(HashNode));
  444.     ht->hsize = newsize;
  445.     } else {
  446.     /* else we just re-zero the current nodes array */
  447.     memset(ht->nodes, 0, newsize * sizeof(HashNode));
  448.     }
  449.  
  450.     ht->ct = 0;
  451. }
  452.  
  453. /* Print info about hash table */
  454.  
  455. #ifdef ZSH_HASH_DEBUG
  456.  
  457. #define MAXDEPTH 7
  458.  
  459. /**/
  460. void
  461. printhashtabinfo(HashTable ht)
  462. {
  463.     HashNode hn;
  464.     int chainlen[MAXDEPTH + 1];
  465.     int i, tmpcount, total;
  466.  
  467.     printf("name of table   : %s\n",   ht->tablename);
  468.     printf("size of nodes[] : %d\n",   ht->hsize);
  469.     printf("number of nodes : %d\n\n", ht->ct);
  470.  
  471.     memset(chainlen, 0, sizeof(chainlen));
  472.  
  473.     /* count the number of nodes just to be sure */
  474.     total = 0;
  475.     for (i = 0; i < ht->hsize; i++) {
  476.     tmpcount = 0;
  477.     for (hn = ht->nodes[i]; hn; hn = hn->next)
  478.         tmpcount++;
  479.     if (tmpcount >= MAXDEPTH)
  480.         chainlen[MAXDEPTH]++;
  481.     else
  482.         chainlen[tmpcount]++;
  483.     total += tmpcount;
  484.     }
  485.  
  486.     for (i = 0; i < MAXDEPTH; i++)
  487.     printf("number of hash values with chain of length %d  : %4d\n", i, chainlen[i]);
  488.     printf("number of hash values with chain of length %d+ : %4d\n", MAXDEPTH, chainlen[MAXDEPTH]);
  489.     printf("total number of nodes                         : %4d\n", total);
  490. }
  491. #endif
  492.  
  493. /********************************/
  494. /* Command Hash Table Functions */
  495. /********************************/
  496.  
  497. /* size of the initial cmdnamtab hash table */
  498. #define INITIAL_CMDNAMTAB 201
  499.  
  500. /* Create a new command hash table */
  501.  
  502. /**/
  503. void
  504. createcmdnamtable(void)
  505. {
  506.     cmdnamtab = newhashtable(INITIAL_CMDNAMTAB);
  507.  
  508.     cmdnamtab->hash        = hasher;
  509.     cmdnamtab->emptytable  = emptycmdnamtable;
  510.     cmdnamtab->filltable   = fillcmdnamtable;
  511.     cmdnamtab->addnode     = addhashnode;
  512.     cmdnamtab->getnode     = gethashnode2;
  513.     cmdnamtab->getnode2    = gethashnode2;
  514.     cmdnamtab->removenode  = removehashnode;
  515.     cmdnamtab->disablenode = NULL;
  516.     cmdnamtab->enablenode  = NULL;
  517.     cmdnamtab->freenode    = freecmdnamnode;
  518.     cmdnamtab->printnode   = printcmdnamnode;
  519. #ifdef ZSH_HASH_DEBUG
  520.     cmdnamtab->printinfo   = printhashtabinfo;
  521.     cmdnamtab->tablename   = ztrdup("cmdnamtab");
  522. #endif
  523.  
  524.     pathchecked = path;
  525. }
  526.  
  527. /**/
  528. void
  529. emptycmdnamtable(HashTable ht)
  530. {
  531.     emptyhashtable(ht, INITIAL_CMDNAMTAB);
  532.     pathchecked = path;
  533. }
  534.  
  535. /* Add all commands in a given directory *
  536.  * to the command hashtable.             */
  537.  
  538. /**/
  539. void
  540. hashdir(char **dirp)
  541. {
  542.     Cmdnam cn;
  543.     DIR *dir;
  544.     char *fn;
  545.  
  546.     if (isrelative(*dirp) || !(dir = opendir(unmeta(*dirp))))
  547.     return;
  548.  
  549.     while ((fn = zreaddir(dir))) {
  550.     /* Ignore `.' and `..'. */
  551.     if (fn[0] == '.' &&
  552.         (fn[1] == '\0' ||
  553.          (fn[1] == '.' && fn[2] == '\0')))
  554.         continue;
  555.     if (!cmdnamtab->getnode(cmdnamtab, fn)) {
  556.         cn = (Cmdnam) zcalloc(sizeof *cn);
  557.         cn->flags = 0;
  558.         cn->u.name = dirp;
  559.         cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
  560.     }
  561.     }
  562.     closedir(dir);
  563. }
  564.  
  565. /* Go through user's PATH and add everything to *
  566.  * the command hashtable.                       */
  567.  
  568. /**/
  569. void
  570. fillcmdnamtable(HashTable ht)
  571. {
  572.     char **pq;
  573.  
  574.     for (pq = pathchecked; *pq; pq++)
  575.     hashdir(pq);
  576.  
  577.     pathchecked = pq;
  578. }
  579.  
  580. /**/
  581. void
  582. freecmdnamnode(HashNode hn)
  583. {
  584.     Cmdnam cn = (Cmdnam) hn;
  585.  
  586.     zsfree(cn->nam);
  587.     if (cn->flags & HASHED)
  588.     zsfree(cn->u.cmd);
  589.  
  590.     zfree(cn, sizeof(struct cmdnam));
  591. }
  592.  
  593. /* Print an element of the cmdnamtab hash table (external command) */
  594.  
  595. /**/
  596. void
  597. printcmdnamnode(HashNode hn, int printflags)
  598. {
  599.     Cmdnam cn = (Cmdnam) hn;
  600.  
  601.     if ((printflags & PRINT_WHENCE_CSH) || (printflags & PRINT_WHENCE_SIMPLE)) {
  602.     if (cn->flags & HASHED) {
  603.         zputs(cn->u.cmd, stdout);
  604.         putchar('\n');
  605.     } else {
  606.         zputs(*(cn->u.name), stdout);
  607.         putchar('/');
  608.         zputs(cn->nam, stdout);
  609.         putchar('\n');
  610.     }
  611.     return;
  612.     }
  613.  
  614.     if (printflags & PRINT_WHENCE_VERBOSE) {
  615.     if (cn->flags & HASHED) {
  616.         nicezputs(cn->nam, stdout);
  617.         printf(" is hashed to ");
  618.         nicezputs(cn->u.cmd, stdout);
  619.         putchar('\n');
  620.     } else {
  621.         nicezputs(cn->nam, stdout);
  622.         printf(" is ");
  623.         nicezputs(*(cn->u.name), stdout);
  624.         putchar('/');
  625.         nicezputs(cn->nam, stdout);
  626.         putchar('\n');
  627.     }
  628.     return;
  629.     }
  630.  
  631.     if (cn->flags & HASHED) {
  632.     quotedzputs(cn->nam, stdout);
  633.     putchar('=');
  634.     quotedzputs(cn->u.cmd, stdout);
  635.     putchar('\n');
  636.     } else {
  637.     quotedzputs(cn->nam, stdout);
  638.     putchar('=');
  639.     quotedzputs(*(cn->u.name), stdout);
  640.     putchar('/');
  641.     quotedzputs(cn->nam, stdout);
  642.     putchar('\n');
  643.     }
  644. }
  645.  
  646. /***************************************/
  647. /* Shell Function Hash Table Functions */
  648. /***************************************/
  649.  
  650. /**/
  651. void
  652. createshfunctable(void)
  653. {
  654.     shfunctab = newhashtable(7);
  655.  
  656.     shfunctab->hash        = hasher;
  657.     shfunctab->emptytable  = NULL;
  658.     shfunctab->filltable   = NULL;
  659.     shfunctab->addnode     = addhashnode;
  660.     shfunctab->getnode     = gethashnode;
  661.     shfunctab->getnode2    = gethashnode2;
  662.     shfunctab->removenode  = removeshfuncnode;
  663.     shfunctab->disablenode = disableshfuncnode;
  664.     shfunctab->enablenode  = enableshfuncnode;
  665.     shfunctab->freenode    = freeshfuncnode;
  666.     shfunctab->printnode   = printshfuncnode;
  667. #ifdef ZSH_HASH_DEBUG
  668.     shfunctab->printinfo   = printhashtabinfo;
  669.     shfunctab->tablename   = ztrdup("shfunctab");
  670. #endif
  671. }
  672.  
  673. /* Remove an entry from the shell function hash table.   *
  674.  * It checks if the function is a signal trap and if so, *
  675.  * it will disable the trapping of that signal.          */
  676.  
  677. /**/
  678. HashNode
  679. removeshfuncnode(HashTable ht, char *nam)
  680. {
  681.     HashNode hn;
  682.  
  683.     if ((hn = removehashnode(shfunctab, nam))) {
  684.     if (!strncmp(hn->nam, "TRAP", 4))
  685.         unsettrap(getsignum(hn->nam + 4));
  686.     return hn;
  687.     } else
  688.     return NULL;
  689. }
  690.  
  691. /* Disable an entry in the shell function hash table.    *
  692.  * It checks if the function is a signal trap and if so, *
  693.  * it will disable the trapping of that signal.          */
  694.  
  695. /**/
  696. void
  697. disableshfuncnode(HashNode hn, int flags)
  698. {
  699.     hn->flags |= DISABLED;
  700.     if (!strncmp(hn->nam, "TRAP", 4)) {
  701.     int signum = getsignum(hn->nam + 4);
  702.     sigtrapped[signum] &= ~ZSIG_FUNC;
  703.     sigfuncs[signum] = NULL;
  704.     unsettrap(signum);
  705.     }
  706. }
  707.  
  708. /* Re-enable an entry in the shell function hash table.  *
  709.  * It checks if the function is a signal trap and if so, *
  710.  * it will re-enable the trapping of that signal.        */
  711.  
  712. /**/
  713. void
  714. enableshfuncnode(HashNode hn, int flags)
  715. {
  716.     Shfunc shf = (Shfunc) hn;
  717.     int signum;
  718.  
  719.     shf->flags &= ~DISABLED;
  720.     if (!strncmp(shf->nam, "TRAP", 4)) {
  721.     signum = getsignum(shf->nam + 4);
  722.     if (signum != -1) {
  723.         settrap(signum, shf->funcdef);
  724.         sigtrapped[signum] |= ZSIG_FUNC;
  725.     }
  726.     }
  727. }
  728.  
  729. /**/
  730. void
  731. freeshfuncnode(HashNode hn)
  732. {
  733.     Shfunc shf = (Shfunc) hn;
  734.  
  735.     zsfree(shf->nam);
  736.     if (shf->funcdef)
  737.     freestruct(shf->funcdef);
  738.     zfree(shf, sizeof(struct shfunc));
  739. }
  740.  
  741. /* Print a shell function */
  742.  
  743. /**/
  744. void
  745. printshfuncnode(HashNode hn, int printflags)
  746. {
  747.     Shfunc f = (Shfunc) hn;
  748.     char *t;
  749.  
  750.     if ((printflags & PRINT_NAMEONLY) ||
  751.     ((printflags & PRINT_WHENCE_SIMPLE) &&
  752.     !(printflags & PRINT_WHENCE_FUNCDEF))) {
  753.     zputs(f->nam, stdout);
  754.     putchar('\n');
  755.     return;
  756.     }
  757.  
  758.     if ((printflags & PRINT_WHENCE_VERBOSE) &&
  759.     !(printflags & PRINT_WHENCE_FUNCDEF)) {
  760.     nicezputs(f->nam, stdout);
  761.     printf(" is a shell function\n");
  762.     return;
  763.     }
  764.  
  765.     if (f->flags & PM_UNDEFINED)
  766.     printf("undefined ");
  767.     if (f->flags & PM_TAGGED)
  768.     printf("traced ");
  769.     if (!f->funcdef) {
  770.     nicezputs(f->nam, stdout);
  771.     printf(" () { }\n");
  772.     return;
  773.     }
  774.  
  775.     t = getpermtext((void *) dupstruct((void *) f->funcdef));
  776.     quotedzputs(f->nam, stdout);
  777.     printf(" () {\n\t");
  778.     zputs(t, stdout);
  779.     printf("\n}\n");
  780.     zsfree(t);
  781. }
  782.  
  783. /****************************************/
  784. /* Builtin Command Hash Table Functions */
  785. /****************************************/
  786.  
  787. /**/
  788. void
  789. createbuiltintable(void)
  790. {
  791.     Builtin bn;
  792.  
  793.     builtintab = newhashtable(85);
  794.  
  795.     builtintab->hash        = hasher;
  796.     builtintab->emptytable  = NULL;
  797.     builtintab->filltable   = NULL;
  798.     builtintab->addnode     = addhashnode;
  799.     builtintab->getnode     = gethashnode;
  800.     builtintab->getnode2    = gethashnode2;
  801.     builtintab->removenode  = NULL;
  802.     builtintab->disablenode = disablehashnode;
  803.     builtintab->enablenode  = enablehashnode;
  804.     builtintab->freenode    = NULL;
  805.     builtintab->printnode   = printbuiltinnode;
  806. #ifdef ZSH_HASH_DEBUG
  807.     builtintab->printinfo   = printhashtabinfo;
  808.     builtintab->tablename   = ztrdup("builtintab");
  809. #endif
  810.  
  811.     for (bn = builtins; bn->nam; bn++)
  812.     builtintab->addnode(builtintab, bn->nam, bn);
  813. }
  814.  
  815. /* Print a builtin */
  816.  
  817. /**/
  818. void
  819. printbuiltinnode(HashNode hn, int printflags)
  820. {
  821.     Builtin bn = (Builtin) hn;
  822.  
  823.     if (printflags & PRINT_WHENCE_CSH) {
  824.     printf("%s: shell built-in command\n", bn->nam);
  825.     return;
  826.     }
  827.  
  828.     if (printflags & PRINT_WHENCE_VERBOSE) {
  829.     printf("%s is a shell builtin\n", bn->nam);
  830.     return;
  831.     }
  832.  
  833.     /* default is name only */
  834.     printf("%s\n", bn->nam);
  835. }
  836.  
  837. /**************************************/
  838. /* Reserved Word Hash Table Functions */
  839. /**************************************/
  840.  
  841. /* Build the hash table containing zsh's reserved words. */
  842.  
  843. /**/
  844. void
  845. createreswdtable(void)
  846. {
  847.     Reswd rw;
  848.  
  849.     reswdtab = newhashtable(23);
  850.  
  851.     reswdtab->hash        = hasher;
  852.     reswdtab->emptytable  = NULL;
  853.     reswdtab->filltable   = NULL;
  854.     reswdtab->addnode     = addhashnode;
  855.     reswdtab->getnode     = gethashnode;
  856.     reswdtab->getnode2    = gethashnode2;
  857.     reswdtab->removenode  = NULL;
  858.     reswdtab->disablenode = disablehashnode;
  859.     reswdtab->enablenode  = enablehashnode;
  860.     reswdtab->freenode    = NULL;
  861.     reswdtab->printnode   = printreswdnode;
  862. #ifdef ZSH_HASH_DEBUG
  863.     reswdtab->printinfo   = printhashtabinfo;
  864.     reswdtab->tablename   = ztrdup("reswdtab");
  865. #endif
  866.  
  867.     for (rw = reswds; rw->nam; rw++)
  868.     reswdtab->addnode(reswdtab, rw->nam, rw);
  869. }
  870.  
  871. /* Print a reserved word */
  872.  
  873. /**/
  874. void
  875. printreswdnode(HashNode hn, int printflags)
  876. {
  877.     Reswd rw = (Reswd) hn;
  878.  
  879.     if (printflags & PRINT_WHENCE_CSH) {
  880.     printf("%s: shell reserved word\n", rw->nam);
  881.     return;
  882.     }
  883.  
  884.     if (printflags & PRINT_WHENCE_VERBOSE) {
  885.     printf("%s is a reserved word\n", rw->nam);
  886.     return;
  887.     }
  888.  
  889.     /* default is name only */
  890.     printf("%s\n", rw->nam);
  891. }
  892.  
  893. /********************************/
  894. /* Aliases Hash Table Functions */
  895. /********************************/
  896.  
  897. /* Create new hash table for aliases */
  898.  
  899. /**/
  900. void
  901. createaliastable(void)
  902. {
  903.     aliastab = newhashtable(23);
  904.  
  905.     aliastab->hash        = hasher;
  906.     aliastab->emptytable  = NULL;
  907.     aliastab->filltable   = NULL;
  908.     aliastab->addnode     = addhashnode;
  909.     aliastab->getnode     = gethashnode;
  910.     aliastab->getnode2    = gethashnode2;
  911.     aliastab->removenode  = removehashnode;
  912.     aliastab->disablenode = disablehashnode;
  913.     aliastab->enablenode  = enablehashnode;
  914.     aliastab->freenode    = freealiasnode;
  915.     aliastab->printnode   = printaliasnode;
  916. #ifdef ZSH_HASH_DEBUG
  917.     aliastab->printinfo   = printhashtabinfo;
  918.     aliastab->tablename   = ztrdup("aliastab");
  919. #endif
  920.  
  921.     /* add the default aliases */
  922.     aliastab->addnode(aliastab, ztrdup("run-help"), createaliasnode(ztrdup("man"), 0));
  923.     aliastab->addnode(aliastab, ztrdup("which-command"), createaliasnode(ztrdup("whence"), 0));
  924. }
  925.  
  926. /* Create a new alias node */
  927.  
  928. /**/
  929. Alias
  930. createaliasnode(char *txt, int flags)
  931. {
  932.     Alias al;
  933.  
  934.     al = (Alias) zcalloc(sizeof *al);
  935.     al->flags = flags;
  936.     al->text = txt;
  937.     al->inuse = 0;
  938.     return al;
  939. }
  940.  
  941. /**/
  942. void
  943. freealiasnode(HashNode hn)
  944. {
  945.     Alias al = (Alias) hn;
  946.  
  947.     zsfree(al->nam);
  948.     zsfree(al->text);
  949.     zfree(al, sizeof(struct alias));
  950. }
  951.  
  952. /* Print an alias */
  953.  
  954. /**/
  955. void
  956. printaliasnode(HashNode hn, int printflags)
  957. {
  958.     Alias a = (Alias) hn;
  959.  
  960.     if (printflags & PRINT_NAMEONLY) {
  961.     zputs(a->nam, stdout);
  962.     putchar('\n');
  963.     return;
  964.     }
  965.  
  966.     if (printflags & PRINT_WHENCE_SIMPLE) {
  967.     zputs(a->text, stdout);
  968.     putchar('\n');
  969.     return;
  970.     }
  971.  
  972.     if (printflags & PRINT_WHENCE_CSH) {
  973.     nicezputs(a->nam, stdout);
  974.     if (a->flags & ALIAS_GLOBAL)
  975.         printf(": globally aliased to ");
  976.     else
  977.         printf(": aliased to ");
  978.     nicezputs(a->text, stdout);
  979.     putchar('\n');
  980.     return;
  981.     }
  982.  
  983.     if (printflags & PRINT_WHENCE_VERBOSE) {
  984.     nicezputs(a->nam, stdout);
  985.     if (a->flags & ALIAS_GLOBAL)
  986.         printf(" is a global alias for ");
  987.     else
  988.         printf(" is an alias for ");
  989.     nicezputs(a->text, stdout);
  990.     putchar('\n');
  991.     return;
  992.     }
  993.  
  994.     if (printflags & PRINT_LIST) {
  995.     printf("alias ");
  996.     if (a->flags & ALIAS_GLOBAL)
  997.         printf("-g ");
  998.  
  999.     /* If an alias begins with `-', then we must output `-- ' *
  1000.      * first, so that it is not interpreted as an option.     */
  1001.     if(a->nam[0] == '-')
  1002.         printf("-- ");
  1003.     }
  1004.  
  1005.     quotedzputs(a->nam, stdout);
  1006.     putchar('=');
  1007.     quotedzputs(a->text, stdout);
  1008.     putchar('\n');
  1009. }
  1010.  
  1011. /**********************************/
  1012. /* Parameter Hash Table Functions */
  1013. /**********************************/
  1014.  
  1015. /**/
  1016. void
  1017. freeparamnode(HashNode hn)
  1018. {
  1019.     Param pm = (Param) hn;
  1020.  
  1021.     zsfree(pm->nam);
  1022.     zfree(pm, sizeof(struct param));
  1023. }
  1024.  
  1025. /* Print a parameter */
  1026.  
  1027. /**/
  1028. void
  1029. printparamnode(HashNode hn, int printflags)
  1030. {
  1031.     Param p = (Param) hn;
  1032.     char *t, **u;
  1033.  
  1034.     if (p->flags & PM_UNSET)
  1035.     return;
  1036.  
  1037.     /* Print the attributes of the parameter */
  1038.     if (printflags & PRINT_TYPE) {
  1039.     if (p->flags & PM_INTEGER)
  1040.         printf("integer ");
  1041.     if (p->flags & PM_ARRAY)
  1042.         printf("array ");
  1043.     if (p->flags & PM_LEFT)
  1044.         printf("left justified %d ", p->ct);
  1045.     if (p->flags & PM_RIGHT_B)
  1046.         printf("right justified %d ", p->ct);
  1047.     if (p->flags & PM_RIGHT_Z)
  1048.         printf("zero filled %d ", p->ct);
  1049.     if (p->flags & PM_LOWER)
  1050.         printf("lowercase ");
  1051.     if (p->flags & PM_UPPER)
  1052.         printf("uppercase ");
  1053.     if (p->flags & PM_READONLY)
  1054.         printf("readonly ");
  1055.     if (p->flags & PM_TAGGED)
  1056.         printf("tagged ");
  1057.     if (p->flags & PM_EXPORTED)
  1058.         printf("exported ");
  1059.     }
  1060.  
  1061.     if (printflags & PRINT_NAMEONLY) {
  1062.     zputs(p->nam, stdout);
  1063.     putchar('\n');
  1064.     return;
  1065.     }
  1066.  
  1067.     /* How the value is displayed depends *
  1068.      * on the type of the parameter       */
  1069.     quotedzputs(p->nam, stdout);
  1070.     putchar('=');
  1071.     switch (PM_TYPE(p->flags)) {
  1072.     case PM_SCALAR:
  1073.     /* string: simple output */
  1074.     if (p->gets.cfn && (t = p->gets.cfn(p)))
  1075.         quotedzputs(t, stdout);
  1076.     putchar('\n');
  1077.     break;
  1078.     case PM_INTEGER:
  1079.     /* integer */
  1080.     printf("%ld\n", p->gets.ifn(p));
  1081.     break;
  1082.     case PM_ARRAY:
  1083.     /* array */
  1084.     putchar('(');
  1085.     u = p->gets.afn(p);
  1086.     if(*u) {
  1087.         quotedzputs(*u++, stdout);
  1088.         while (*u) {
  1089.         putchar(' ');
  1090.         quotedzputs(*u++, stdout);
  1091.         }
  1092.     }
  1093.     printf(")\n");
  1094.     break;
  1095.     }
  1096. }
  1097.  
  1098. /****************************************/
  1099. /* Named Directory Hash Table Functions */
  1100. /****************************************/
  1101.  
  1102. /* size of the initial name directory hash table */
  1103. #define INITIAL_NAMEDDIR 201
  1104.  
  1105. /* != 0 if all the usernames have already been *
  1106.  * added to the named directory hash table.    */
  1107. int allusersadded;
  1108.  
  1109. /* Create new hash table for named directories */
  1110.  
  1111. /**/
  1112. void
  1113. createnameddirtable(void)
  1114. {
  1115.     nameddirtab = newhashtable(INITIAL_NAMEDDIR);
  1116.  
  1117.     nameddirtab->hash        = hasher;
  1118.     nameddirtab->emptytable  = emptynameddirtable;
  1119.     nameddirtab->filltable   = fillnameddirtable;
  1120.     nameddirtab->addnode     = addnameddirnode;
  1121.     nameddirtab->getnode     = gethashnode;
  1122.     nameddirtab->getnode2    = gethashnode2;
  1123.     nameddirtab->removenode  = removenameddirnode;
  1124.     nameddirtab->disablenode = NULL;
  1125.     nameddirtab->enablenode  = NULL;
  1126.     nameddirtab->freenode    = freenameddirnode;
  1127.     nameddirtab->printnode   = printnameddirnode;
  1128. #ifdef ZSH_HASH_DEBUG
  1129.     nameddirtab->printinfo   = printhashtabinfo;
  1130.     nameddirtab->tablename   = ztrdup("nameddirtab");
  1131. #endif
  1132.  
  1133.     allusersadded = 0;
  1134.     finddir(NULL);        /* clear the finddir cache */
  1135. }
  1136.  
  1137. /* Empty the named directories table */
  1138.  
  1139. /**/
  1140. void
  1141. emptynameddirtable(HashTable ht)
  1142. {
  1143.     emptyhashtable(ht, INITIAL_NAMEDDIR);
  1144.     allusersadded = 0;
  1145.     finddir(NULL);        /* clear the finddir cache */
  1146. }
  1147.  
  1148. /* Add all the usernames in the password file/database *
  1149.  * to the named directories table.                     */
  1150.  
  1151. /**/
  1152. void
  1153. fillnameddirtable(HashTable ht)
  1154. {
  1155.     if (!allusersadded) {
  1156.     struct passwd *pw;
  1157.  
  1158.     setpwent();
  1159.  
  1160.     /* loop through the password file/database *
  1161.      * and add all entries returned.           */
  1162.     while ((pw = getpwent()) && !errflag)
  1163.         adduserdir(ztrdup(pw->pw_name), pw->pw_dir, ND_USERNAME, 1);
  1164.  
  1165.     endpwent();
  1166.     allusersadded = 1;
  1167.     }
  1168.     return;
  1169. }
  1170.  
  1171. /* Add an entry to the named directory hash *
  1172.  * table, clearing the finddir() cache and  *
  1173.  * initialising the `diff' member.          */
  1174.  
  1175. /**/
  1176. void
  1177. addnameddirnode(HashTable ht, char *nam, void *nodeptr)
  1178. {
  1179.     Nameddir nd = (Nameddir) nodeptr;
  1180.  
  1181.     nd->diff = strlen(nd->dir) - strlen(nam);
  1182.     finddir(NULL);        /* clear the finddir cache */
  1183.     addhashnode(ht, nam, nodeptr);
  1184. }
  1185.  
  1186. /* Remove an entry from the named directory  *
  1187.  * hash table, clearing the finddir() cache. */
  1188.  
  1189. /**/
  1190. HashNode
  1191. removenameddirnode(HashTable ht, char *nam)
  1192. {
  1193.     HashNode hn = removehashnode(ht, nam);
  1194.  
  1195.     if(hn)
  1196.     finddir(NULL);        /* clear the finddir cache */
  1197.     return hn;
  1198. }
  1199.  
  1200. /* Free up the memory used by a named directory hash node. */
  1201.  
  1202. /**/
  1203. void
  1204. freenameddirnode(HashNode hn)
  1205. {
  1206.     Nameddir nd = (Nameddir) hn;
  1207.  
  1208.     zsfree(nd->nam);
  1209.     zsfree(nd->dir);
  1210.     zfree(nd, sizeof(struct nameddir));
  1211. }
  1212.  
  1213. /* Print a named directory */
  1214.  
  1215. /**/
  1216. void
  1217. printnameddirnode(HashNode hn, int printflags)
  1218. {
  1219.     Nameddir nd = (Nameddir) hn;
  1220.  
  1221.     if (printflags & PRINT_NAMEONLY) {
  1222.     zputs(nd->nam, stdout);
  1223.     putchar('\n');
  1224.     return;
  1225.     }
  1226.  
  1227.     quotedzputs(nd->nam, stdout);
  1228.     putchar('=');
  1229.     quotedzputs(nd->dir, stdout);
  1230.     putchar('\n');
  1231. }
  1232.  
  1233. /********************************/
  1234. /* Compctl Hash Table Functions */
  1235. /********************************/
  1236.  
  1237. /**/
  1238. void
  1239. createcompctltable(void)
  1240. {
  1241.     compctltab = newhashtable(23);
  1242.  
  1243.     compctltab->hash        = hasher;
  1244.     compctltab->emptytable  = NULL;
  1245.     compctltab->filltable   = NULL;
  1246.     compctltab->addnode     = addhashnode;
  1247.     compctltab->getnode     = gethashnode2;
  1248.     compctltab->getnode2    = gethashnode2;
  1249.     compctltab->removenode  = removehashnode;
  1250.     compctltab->disablenode = NULL;
  1251.     compctltab->enablenode  = NULL;
  1252.     compctltab->freenode    = freecompctlp;
  1253.     compctltab->printnode   = printcompctlp;
  1254. #ifdef ZSH_HASH_DEBUG
  1255.     compctltab->printinfo   = printhashtabinfo;
  1256.     compctltab->tablename   = ztrdup("compctltab");
  1257. #endif
  1258. }
  1259.  
  1260. /**/
  1261. void
  1262. freecompctl(Compctl cc)
  1263. {
  1264.     if (cc == &cc_default ||
  1265.      cc == &cc_first ||
  1266.     cc == &cc_compos ||
  1267.     --cc->refc > 0)
  1268.     return;
  1269.  
  1270.     zsfree(cc->keyvar);
  1271.     zsfree(cc->glob);
  1272.     zsfree(cc->str);
  1273.     zsfree(cc->func);
  1274.     zsfree(cc->explain);
  1275.     zsfree(cc->prefix);
  1276.     zsfree(cc->suffix);
  1277.     zsfree(cc->hpat);
  1278.     zsfree(cc->subcmd);
  1279.     if (cc->cond)
  1280.     freecompcond(cc->cond);
  1281.     if (cc->ext) {
  1282.     Compctl n, m;
  1283.  
  1284.     n = cc->ext;
  1285.     do {
  1286.         m = (Compctl) (n->next);
  1287.         freecompctl(n);
  1288.         n = m;
  1289.     }
  1290.     while (n);
  1291.     }
  1292.     if (cc->xor && cc->xor != &cc_default)
  1293.     freecompctl(cc->xor);
  1294.     zfree(cc, sizeof(struct compctl));
  1295. }
  1296.  
  1297. /**/
  1298. void
  1299. freecompctlp(HashNode hn)
  1300. {
  1301.     Compctlp ccp = (Compctlp) hn;
  1302.  
  1303.     zsfree(ccp->nam);
  1304.     freecompctl(ccp->cc);
  1305.     zfree(ccp, sizeof(struct compctlp));
  1306. }
  1307.  
  1308. /***********************************************************/
  1309. /* Emacs Multi-Character Key Bindings Hash Table Functions */
  1310. /***********************************************************/
  1311.  
  1312. /* size of the initial hashtable for multi-character *
  1313.  * emacs key bindings.                               */
  1314. #define INITIAL_EMKEYBINDTAB 67
  1315.  
  1316. /**/
  1317. void
  1318. createemkeybindtable(void)
  1319. {
  1320.     emkeybindtab = newhashtable(INITIAL_EMKEYBINDTAB);
  1321.  
  1322.     emkeybindtab->hash        = hasher;
  1323.     emkeybindtab->emptytable  = emptyemkeybindtable;
  1324.     emkeybindtab->filltable   = NULL;
  1325.     emkeybindtab->addnode     = addhashnode;
  1326.     emkeybindtab->getnode     = gethashnode2;
  1327.     emkeybindtab->getnode2    = gethashnode2;
  1328.     emkeybindtab->removenode  = removehashnode;
  1329.     emkeybindtab->disablenode = NULL;
  1330.     emkeybindtab->enablenode  = NULL;
  1331.     emkeybindtab->freenode    = freekeynode;
  1332.  
  1333.     /* need to combine printbinding and printfuncbinding for this */
  1334.     emkeybindtab->printnode   = NULL;
  1335. #ifdef ZSH_HASH_DEBUG
  1336.     emkeybindtab->printinfo   = printhashtabinfo;
  1337.     emkeybindtab->tablename   = ztrdup("emkeybindtab");
  1338. #endif
  1339. }
  1340.  
  1341. /**/
  1342. void
  1343. emptyemkeybindtable(HashTable ht)
  1344. {
  1345.     emptyhashtable(ht, INITIAL_EMKEYBINDTAB);
  1346. }
  1347.  
  1348. /********************************************************/
  1349. /* Vi Multi-Character Key Bindings Hash Table Functions */
  1350. /********************************************************/
  1351.  
  1352. /* size of the initial hash table for *
  1353.  * multi-character vi key bindings.   */
  1354. #define INITIAL_VIKEYBINDTAB 20
  1355.  
  1356. /**/
  1357. void
  1358. createvikeybindtable(void)
  1359. {
  1360.     vikeybindtab = newhashtable(INITIAL_VIKEYBINDTAB);
  1361.  
  1362.     vikeybindtab->hash        = hasher;
  1363.     vikeybindtab->emptytable  = emptyvikeybindtable;
  1364.     vikeybindtab->filltable   = NULL;
  1365.     vikeybindtab->addnode     = addhashnode;
  1366.     vikeybindtab->getnode     = gethashnode2;
  1367.     vikeybindtab->getnode2    = gethashnode2;
  1368.     vikeybindtab->removenode  = removehashnode;
  1369.     vikeybindtab->disablenode = NULL;
  1370.     vikeybindtab->enablenode  = NULL;
  1371.     vikeybindtab->freenode    = freekeynode;
  1372.  
  1373.     /* need to combine printbinding and printfuncbinding for this */
  1374.     vikeybindtab->printnode   = NULL;
  1375. #ifdef ZSH_HASH_DEBUG
  1376.     vikeybindtab->printinfo   = printhashtabinfo;
  1377.     vikeybindtab->tablename   = ztrdup("vikeybindtab");
  1378. #endif
  1379. }
  1380.  
  1381. /**/
  1382. void
  1383. emptyvikeybindtable(HashTable ht)
  1384. {
  1385.     emptyhashtable(ht, INITIAL_VIKEYBINDTAB);
  1386. }
  1387.