This is hashtable.c in view mode; [Download] [Up]
/* * $Id: hashtable.c,v 2.11 1996/10/15 20:16:35 hzoli Exp $ * * hashtable.c - hash tables * * This file is part of zsh, the Z shell. * * Copyright (c) 1992-1996 Paul Falstad * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and to distribute modified versions of this software for any * purpose, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * In no event shall Paul Falstad or the Zsh Development Group be liable * to any party for direct, indirect, special, incidental, or consequential * damages arising out of the use of this software and its documentation, * even if Paul Falstad and the Zsh Development Group have been advised of * the possibility of such damage. * * Paul Falstad and the Zsh Development Group specifically disclaim any * warranties, including, but not limited to, the implied warranties of * merchantability and fitness for a particular purpose. The software * provided hereunder is on an "as is" basis, and Paul Falstad and the * Zsh Development Group have no obligation to provide maintenance, * support, updates, enhancements, or modifications. * */ #include "zsh.h" /********************************/ /* Generic Hash Table functions */ /********************************/ /* Generic hash function */ /**/ unsigned hasher(char *str) { unsigned hashval = 0; while (*str) hashval += (hashval << 5) + ((unsigned) *str++); return hashval; } /* Get a new hash table */ /**/ HashTable newhashtable(int size) { HashTable ht; ht = (HashTable) zcalloc(sizeof *ht); ht->nodes = (HashNode *) zcalloc(size * sizeof(HashNode)); ht->hsize = size; ht->ct = 0; return ht; } /* Add a node to a hash table. * * nam is the key to use in hashing. dat is a pointer * * to the node to add. If there is already a node in * * the table with the same key, it is first freed, and * * then the new node is added. If the number of nodes * * is now greater than twice the number of hash values, * * the table is then expanded. */ /**/ void addhashnode(HashTable ht, char *nam, void *nodeptr) { unsigned hashval; HashNode hn, hp, hq; hn = (HashNode) nodeptr; hn->nam = nam; hashval = ht->hash(hn->nam) % ht->hsize; hp = ht->nodes[hashval]; /* check if this is the first node for this hash value */ if (!hp) { hn->next = NULL; ht->nodes[hashval] = hn; if (++ht->ct == ht->hsize * 2) expandhashtable(ht); return; } /* else check if the first node contains the same key */ if (!strcmp(hp->nam, hn->nam)) { hn->next = hp->next; ht->nodes[hashval] = hn; ht->freenode(hp); return; } /* else run through the list and check all the keys */ hq = hp; hp = hp->next; for (; hp; hq = hp, hp = hp->next) { if (!strcmp(hp->nam, hn->nam)) { hn->next = hp->next; hq->next = hn; ht->freenode(hp); return; } } /* else just add it at the front of the list */ hn->next = ht->nodes[hashval]; ht->nodes[hashval] = hn; if (++ht->ct == ht->hsize * 2) expandhashtable(ht); } /* Get an enabled entry in a hash table. * * If successful, it returns a pointer to * * the hashnode. If the node is DISABLED * * or isn't found, it returns NULL */ /**/ HashNode gethashnode(HashTable ht, char *nam) { unsigned hashval; HashNode hp; hashval = ht->hash(nam) % ht->hsize; for (hp = ht->nodes[hashval]; hp; hp = hp->next) { if (!strcmp(hp->nam, nam)) { if (hp->flags & DISABLED) return NULL; else return hp; } } return NULL; } /* Get an entry in a hash table. It will * * ignore the DISABLED flag and return a * * pointer to the hashnode if found, else * * it returns NULL. */ /**/ HashNode gethashnode2(HashTable ht, char *nam) { unsigned hashval; HashNode hp; hashval = ht->hash(nam) % ht->hsize; for (hp = ht->nodes[hashval]; hp; hp = hp->next) { if (!strcmp(hp->nam, nam)) return hp; } return NULL; } /* Remove an entry from a hash table. * * If successful, it removes the node from the * * table and returns a pointer to it. If there * * is no such node, then it returns NULL */ /**/ HashNode removehashnode(HashTable ht, char *nam) { unsigned hashval; HashNode hp, hq; hashval = ht->hash(nam) % ht->hsize; hp = ht->nodes[hashval]; /* if no nodes at this hash value, return NULL */ if (!hp) return NULL; /* else check if the key in the first one matches */ if (!strcmp(hp->nam, nam)) { ht->nodes[hashval] = hp->next; ht->ct--; return hp; } /* else run through the list and check the rest of the keys */ hq = hp; hp = hp->next; for (; hp; hq = hp, hp = hp->next) { if (!strcmp(hp->nam, nam)) { hq->next = hp->next; ht->ct--; return hp; } } /* else it is not in the list, so return NULL */ return NULL; } /* Disable a node in a hash table */ /**/ void disablehashnode(HashNode hn, int flags) { hn->flags |= DISABLED; } /* Enable a node in a hash table */ /**/ void enablehashnode(HashNode hn, int flags) { hn->flags &= ~DISABLED; } /* Compare two hash table entries */ /**/ int hnamcmp(struct hashnode **a, struct hashnode **b) { return ztrcmp((unsigned char *) (*a)->nam, (unsigned char *) (*b)->nam); } /* Scan the nodes in a hash table and execute scanfunc on nodes based on the flags * * that are set/unset. scanflags is passed unchanged to scanfunc (if executed). * * * * If sorted = 1, then sort entries of hash table before scanning. * * If sorted = 0, don't sort entries before scanning. * * If (flags1 > 0), then execute func on a node only if these flags are set. * * If (flags2 > 0), then execute func on a node only if these flags are NOT set. * * The conditions above for flags1/flags2 must both be true. */ /**/ void scanhashtable(HashTable ht, int sorted, int flags1, int flags2, ScanFunc scanfunc, int scanflags) { HashNode hn, *hnsorttab, *htp; int i; if (sorted) { hnsorttab = (HashNode *) zalloc(ht->ct * sizeof(HashNode)); for (htp = hnsorttab, i = 0; i < ht->hsize; i++) for (hn = ht->nodes[i]; hn; hn = hn->next) *htp++ = hn; qsort((void *) & hnsorttab[0], ht->ct, sizeof(HashNode), (int (*) _((const void *, const void *))) hnamcmp); /* Ignore the flags */ if (!flags1 && !flags2) { for (htp = hnsorttab, i = 0; i < ht->ct; i++, htp++) scanfunc(*htp, scanflags); } else if (flags1 && !flags2) { /* Only exec scanfunc if flags1 are set */ for (htp = hnsorttab, i = 0; i < ht->ct; i++, htp++) if ((*htp)->flags & flags1) scanfunc(*htp, scanflags); } else if (!flags1 && flags2) { /* Only exec scanfunc if flags2 are NOT set */ for (htp = hnsorttab, i = 0; i < ht->ct; i++, htp++) if (!((*htp)->flags & flags2)) scanfunc(*htp, scanflags); } else { /* Only exec scanfun if flags1 are set, and flags2 are NOT set */ for (htp = hnsorttab, i = 0; i < ht->ct; i++, htp++) if (((*htp)->flags & flags1) && !((*htp)->flags & flags2)) scanfunc(*htp, scanflags); } free(hnsorttab); return; } /* Don't sort, just use hash order. */ /* Ignore the flags */ if (!flags1 && !flags2) { for (i = 0; i < ht->hsize; i++) for (hn = ht->nodes[i]; hn; hn = hn->next) scanfunc(hn, scanflags); return; } /* Only exec scanfunc if flags1 are set */ if (flags1 && !flags2) { for (i = 0; i < ht->hsize; i++) for (hn = ht->nodes[i]; hn; hn = hn->next) if (hn->flags & flags1) scanfunc(hn, scanflags); return; } /* Only exec scanfunc if flags2 are NOT set */ if (!flags1 && flags2) { for (i = 0; i < ht->hsize; i++) for (hn = ht->nodes[i]; hn; hn = hn->next) if (!(hn->flags & flags2)) scanfunc(hn, scanflags); return; } /* Only exec scanfun if flags1 are set, and flags2 are NOT set */ for (i = 0; i < ht->hsize; i++) for (hn = ht->nodes[i]; hn; hn = hn->next) if ((hn->flags & flags1) && !(hn->flags & flags2)) scanfunc(hn, scanflags); } /* Scan all nodes in a hash table and executes scanfunc on the * * nodes which meet all the following criteria: * * The hash key must match the glob pattern given by `com'. * * If (flags1 > 0), then all flags in flags1 must be set. * * If (flags2 > 0), then all flags in flags2 must NOT be set. * * * * scanflags is passed unchanged to scanfunc (if executed). * * The return value if the number of matches. */ /**/ int scanmatchtable(HashTable ht, Comp com, int flags1, int flags2, ScanFunc scanfunc, int scanflags) { HashNode hn; int i, match = 0; /* ignore the flags */ if (!flags1 && !flags2) { for (i = 0; i < ht->hsize; i++) { for (hn = ht->nodes[i]; hn; hn = hn->next) { if (domatch(hn->nam, com, 0)) { scanfunc(hn, scanflags); match++; } } } return match; } /* flags in flags1 must be set */ if (flags1 && !flags2) { for (i = 0; i < ht->hsize; i++) { for (hn = ht->nodes[i]; hn; hn = hn->next) { if (domatch(hn->nam, com, 0) && (hn->flags & flags1)) { scanfunc(hn, scanflags); match++; } } } return match; } /* flags in flags2 must NOT be set */ if (!flags1 && flags2) { for (i = 0; i < ht->hsize; i++) { for (hn = ht->nodes[i]; hn; hn = hn->next) { if (domatch(hn->nam, com, 0) && !(hn->flags & flags2)) { scanfunc(hn, scanflags); match++; } } } return match; } /* flags in flags1 must be set, * * flags in flags2 must NOT be set */ for (i = 0; i < ht->hsize; i++) { for (hn = ht->nodes[i]; hn; hn = hn->next) { if (domatch(hn->nam, com, 0) && (hn->flags & flags1) && !(hn->flags & flags2)) { scanfunc(hn, scanflags); match++; } } } return match; } /* Expand hash tables when they get too many entries. * * The new size is 4 times the previous size. */ /**/ void expandhashtable(HashTable ht) { struct hashnode **onodes, **ha, *hn, *hp; int i, osize; osize = ht->hsize; onodes = ht->nodes; ht->hsize = osize * 4; ht->nodes = (HashNode *) zcalloc(ht->hsize * sizeof(HashNode)); ht->ct = 0; /* scan through the old list of nodes, and * * rehash them into the new list of nodes */ for (i = 0, ha = onodes; i < osize; i++, ha++) { for (hn = *ha; hn;) { hp = hn->next; ht->addnode(ht, hn->nam, hn); hn = hp; } } zfree(onodes, osize * sizeof(HashNode)); } /* Empty the hash table and resize it if necessary */ /**/ void emptyhashtable(HashTable ht, int newsize) { struct hashnode **ha, *hn, *hp; int i; /* free all the hash nodes */ ha = ht->nodes; for (i = 0; i < ht->hsize; i++, ha++) { for (hn = *ha; hn;) { hp = hn->next; ht->freenode(hn); hn = hp; } } /* If new size desired is different from current size, * * we free it and allocate a new nodes array. */ if (ht->hsize != newsize) { zfree(ht->nodes, ht->hsize * sizeof(HashNode)); ht->nodes = (HashNode *) zcalloc(newsize * sizeof(HashNode)); ht->hsize = newsize; } else { /* else we just re-zero the current nodes array */ memset(ht->nodes, 0, newsize * sizeof(HashNode)); } ht->ct = 0; } /* Print info about hash table */ #ifdef ZSH_HASH_DEBUG #define MAXDEPTH 7 /**/ void printhashtabinfo(HashTable ht) { HashNode hn; int chainlen[MAXDEPTH + 1]; int i, tmpcount, total; printf("name of table : %s\n", ht->tablename); printf("size of nodes[] : %d\n", ht->hsize); printf("number of nodes : %d\n\n", ht->ct); memset(chainlen, 0, sizeof(chainlen)); /* count the number of nodes just to be sure */ total = 0; for (i = 0; i < ht->hsize; i++) { tmpcount = 0; for (hn = ht->nodes[i]; hn; hn = hn->next) tmpcount++; if (tmpcount >= MAXDEPTH) chainlen[MAXDEPTH]++; else chainlen[tmpcount]++; total += tmpcount; } for (i = 0; i < MAXDEPTH; i++) printf("number of hash values with chain of length %d : %4d\n", i, chainlen[i]); printf("number of hash values with chain of length %d+ : %4d\n", MAXDEPTH, chainlen[MAXDEPTH]); printf("total number of nodes : %4d\n", total); } #endif /********************************/ /* Command Hash Table Functions */ /********************************/ /* size of the initial cmdnamtab hash table */ #define INITIAL_CMDNAMTAB 201 /* Create a new command hash table */ /**/ void createcmdnamtable(void) { cmdnamtab = newhashtable(INITIAL_CMDNAMTAB); cmdnamtab->hash = hasher; cmdnamtab->emptytable = emptycmdnamtable; cmdnamtab->filltable = fillcmdnamtable; cmdnamtab->addnode = addhashnode; cmdnamtab->getnode = gethashnode2; cmdnamtab->getnode2 = gethashnode2; cmdnamtab->removenode = removehashnode; cmdnamtab->disablenode = NULL; cmdnamtab->enablenode = NULL; cmdnamtab->freenode = freecmdnamnode; cmdnamtab->printnode = printcmdnamnode; #ifdef ZSH_HASH_DEBUG cmdnamtab->printinfo = printhashtabinfo; cmdnamtab->tablename = ztrdup("cmdnamtab"); #endif pathchecked = path; } /**/ void emptycmdnamtable(HashTable ht) { emptyhashtable(ht, INITIAL_CMDNAMTAB); pathchecked = path; } /* Add all commands in a given directory * * to the command hashtable. */ /**/ void hashdir(char **dirp) { Cmdnam cn; DIR *dir; char *fn; if (isrelative(*dirp) || !(dir = opendir(unmeta(*dirp)))) return; while ((fn = zreaddir(dir))) { /* Ignore `.' and `..'. */ if (fn[0] == '.' && (fn[1] == '\0' || (fn[1] == '.' && fn[2] == '\0'))) continue; if (!cmdnamtab->getnode(cmdnamtab, fn)) { cn = (Cmdnam) zcalloc(sizeof *cn); cn->flags = 0; cn->u.name = dirp; cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn); } } closedir(dir); } /* Go through user's PATH and add everything to * * the command hashtable. */ /**/ void fillcmdnamtable(HashTable ht) { char **pq; for (pq = pathchecked; *pq; pq++) hashdir(pq); pathchecked = pq; } /**/ void freecmdnamnode(HashNode hn) { Cmdnam cn = (Cmdnam) hn; zsfree(cn->nam); if (cn->flags & HASHED) zsfree(cn->u.cmd); zfree(cn, sizeof(struct cmdnam)); } /* Print an element of the cmdnamtab hash table (external command) */ /**/ void printcmdnamnode(HashNode hn, int printflags) { Cmdnam cn = (Cmdnam) hn; if ((printflags & PRINT_WHENCE_CSH) || (printflags & PRINT_WHENCE_SIMPLE)) { if (cn->flags & HASHED) { zputs(cn->u.cmd, stdout); putchar('\n'); } else { zputs(*(cn->u.name), stdout); putchar('/'); zputs(cn->nam, stdout); putchar('\n'); } return; } if (printflags & PRINT_WHENCE_VERBOSE) { if (cn->flags & HASHED) { nicezputs(cn->nam, stdout); printf(" is hashed to "); nicezputs(cn->u.cmd, stdout); putchar('\n'); } else { nicezputs(cn->nam, stdout); printf(" is "); nicezputs(*(cn->u.name), stdout); putchar('/'); nicezputs(cn->nam, stdout); putchar('\n'); } return; } if (cn->flags & HASHED) { quotedzputs(cn->nam, stdout); putchar('='); quotedzputs(cn->u.cmd, stdout); putchar('\n'); } else { quotedzputs(cn->nam, stdout); putchar('='); quotedzputs(*(cn->u.name), stdout); putchar('/'); quotedzputs(cn->nam, stdout); putchar('\n'); } } /***************************************/ /* Shell Function Hash Table Functions */ /***************************************/ /**/ void createshfunctable(void) { shfunctab = newhashtable(7); shfunctab->hash = hasher; shfunctab->emptytable = NULL; shfunctab->filltable = NULL; shfunctab->addnode = addhashnode; shfunctab->getnode = gethashnode; shfunctab->getnode2 = gethashnode2; shfunctab->removenode = removeshfuncnode; shfunctab->disablenode = disableshfuncnode; shfunctab->enablenode = enableshfuncnode; shfunctab->freenode = freeshfuncnode; shfunctab->printnode = printshfuncnode; #ifdef ZSH_HASH_DEBUG shfunctab->printinfo = printhashtabinfo; shfunctab->tablename = ztrdup("shfunctab"); #endif } /* Remove an entry from the shell function hash table. * * It checks if the function is a signal trap and if so, * * it will disable the trapping of that signal. */ /**/ HashNode removeshfuncnode(HashTable ht, char *nam) { HashNode hn; if ((hn = removehashnode(shfunctab, nam))) { if (!strncmp(hn->nam, "TRAP", 4)) unsettrap(getsignum(hn->nam + 4)); return hn; } else return NULL; } /* Disable an entry in the shell function hash table. * * It checks if the function is a signal trap and if so, * * it will disable the trapping of that signal. */ /**/ void disableshfuncnode(HashNode hn, int flags) { hn->flags |= DISABLED; if (!strncmp(hn->nam, "TRAP", 4)) { int signum = getsignum(hn->nam + 4); sigtrapped[signum] &= ~ZSIG_FUNC; sigfuncs[signum] = NULL; unsettrap(signum); } } /* Re-enable an entry in the shell function hash table. * * It checks if the function is a signal trap and if so, * * it will re-enable the trapping of that signal. */ /**/ void enableshfuncnode(HashNode hn, int flags) { Shfunc shf = (Shfunc) hn; int signum; shf->flags &= ~DISABLED; if (!strncmp(shf->nam, "TRAP", 4)) { signum = getsignum(shf->nam + 4); if (signum != -1) { settrap(signum, shf->funcdef); sigtrapped[signum] |= ZSIG_FUNC; } } } /**/ void freeshfuncnode(HashNode hn) { Shfunc shf = (Shfunc) hn; zsfree(shf->nam); if (shf->funcdef) freestruct(shf->funcdef); zfree(shf, sizeof(struct shfunc)); } /* Print a shell function */ /**/ void printshfuncnode(HashNode hn, int printflags) { Shfunc f = (Shfunc) hn; char *t; if ((printflags & PRINT_NAMEONLY) || ((printflags & PRINT_WHENCE_SIMPLE) && !(printflags & PRINT_WHENCE_FUNCDEF))) { zputs(f->nam, stdout); putchar('\n'); return; } if ((printflags & PRINT_WHENCE_VERBOSE) && !(printflags & PRINT_WHENCE_FUNCDEF)) { nicezputs(f->nam, stdout); printf(" is a shell function\n"); return; } if (f->flags & PM_UNDEFINED) printf("undefined "); if (f->flags & PM_TAGGED) printf("traced "); if (!f->funcdef) { nicezputs(f->nam, stdout); printf(" () { }\n"); return; } t = getpermtext((void *) dupstruct((void *) f->funcdef)); quotedzputs(f->nam, stdout); printf(" () {\n\t"); zputs(t, stdout); printf("\n}\n"); zsfree(t); } /****************************************/ /* Builtin Command Hash Table Functions */ /****************************************/ /**/ void createbuiltintable(void) { Builtin bn; builtintab = newhashtable(85); builtintab->hash = hasher; builtintab->emptytable = NULL; builtintab->filltable = NULL; builtintab->addnode = addhashnode; builtintab->getnode = gethashnode; builtintab->getnode2 = gethashnode2; builtintab->removenode = NULL; builtintab->disablenode = disablehashnode; builtintab->enablenode = enablehashnode; builtintab->freenode = NULL; builtintab->printnode = printbuiltinnode; #ifdef ZSH_HASH_DEBUG builtintab->printinfo = printhashtabinfo; builtintab->tablename = ztrdup("builtintab"); #endif for (bn = builtins; bn->nam; bn++) builtintab->addnode(builtintab, bn->nam, bn); } /* Print a builtin */ /**/ void printbuiltinnode(HashNode hn, int printflags) { Builtin bn = (Builtin) hn; if (printflags & PRINT_WHENCE_CSH) { printf("%s: shell built-in command\n", bn->nam); return; } if (printflags & PRINT_WHENCE_VERBOSE) { printf("%s is a shell builtin\n", bn->nam); return; } /* default is name only */ printf("%s\n", bn->nam); } /**************************************/ /* Reserved Word Hash Table Functions */ /**************************************/ /* Build the hash table containing zsh's reserved words. */ /**/ void createreswdtable(void) { Reswd rw; reswdtab = newhashtable(23); reswdtab->hash = hasher; reswdtab->emptytable = NULL; reswdtab->filltable = NULL; reswdtab->addnode = addhashnode; reswdtab->getnode = gethashnode; reswdtab->getnode2 = gethashnode2; reswdtab->removenode = NULL; reswdtab->disablenode = disablehashnode; reswdtab->enablenode = enablehashnode; reswdtab->freenode = NULL; reswdtab->printnode = printreswdnode; #ifdef ZSH_HASH_DEBUG reswdtab->printinfo = printhashtabinfo; reswdtab->tablename = ztrdup("reswdtab"); #endif for (rw = reswds; rw->nam; rw++) reswdtab->addnode(reswdtab, rw->nam, rw); } /* Print a reserved word */ /**/ void printreswdnode(HashNode hn, int printflags) { Reswd rw = (Reswd) hn; if (printflags & PRINT_WHENCE_CSH) { printf("%s: shell reserved word\n", rw->nam); return; } if (printflags & PRINT_WHENCE_VERBOSE) { printf("%s is a reserved word\n", rw->nam); return; } /* default is name only */ printf("%s\n", rw->nam); } /********************************/ /* Aliases Hash Table Functions */ /********************************/ /* Create new hash table for aliases */ /**/ void createaliastable(void) { aliastab = newhashtable(23); aliastab->hash = hasher; aliastab->emptytable = NULL; aliastab->filltable = NULL; aliastab->addnode = addhashnode; aliastab->getnode = gethashnode; aliastab->getnode2 = gethashnode2; aliastab->removenode = removehashnode; aliastab->disablenode = disablehashnode; aliastab->enablenode = enablehashnode; aliastab->freenode = freealiasnode; aliastab->printnode = printaliasnode; #ifdef ZSH_HASH_DEBUG aliastab->printinfo = printhashtabinfo; aliastab->tablename = ztrdup("aliastab"); #endif /* add the default aliases */ aliastab->addnode(aliastab, ztrdup("run-help"), createaliasnode(ztrdup("man"), 0)); aliastab->addnode(aliastab, ztrdup("which-command"), createaliasnode(ztrdup("whence"), 0)); } /* Create a new alias node */ /**/ Alias createaliasnode(char *txt, int flags) { Alias al; al = (Alias) zcalloc(sizeof *al); al->flags = flags; al->text = txt; al->inuse = 0; return al; } /**/ void freealiasnode(HashNode hn) { Alias al = (Alias) hn; zsfree(al->nam); zsfree(al->text); zfree(al, sizeof(struct alias)); } /* Print an alias */ /**/ void printaliasnode(HashNode hn, int printflags) { Alias a = (Alias) hn; if (printflags & PRINT_NAMEONLY) { zputs(a->nam, stdout); putchar('\n'); return; } if (printflags & PRINT_WHENCE_SIMPLE) { zputs(a->text, stdout); putchar('\n'); return; } if (printflags & PRINT_WHENCE_CSH) { nicezputs(a->nam, stdout); if (a->flags & ALIAS_GLOBAL) printf(": globally aliased to "); else printf(": aliased to "); nicezputs(a->text, stdout); putchar('\n'); return; } if (printflags & PRINT_WHENCE_VERBOSE) { nicezputs(a->nam, stdout); if (a->flags & ALIAS_GLOBAL) printf(" is a global alias for "); else printf(" is an alias for "); nicezputs(a->text, stdout); putchar('\n'); return; } if (printflags & PRINT_LIST) { printf("alias "); if (a->flags & ALIAS_GLOBAL) printf("-g "); /* If an alias begins with `-', then we must output `-- ' * * first, so that it is not interpreted as an option. */ if(a->nam[0] == '-') printf("-- "); } quotedzputs(a->nam, stdout); putchar('='); quotedzputs(a->text, stdout); putchar('\n'); } /**********************************/ /* Parameter Hash Table Functions */ /**********************************/ /**/ void freeparamnode(HashNode hn) { Param pm = (Param) hn; zsfree(pm->nam); zfree(pm, sizeof(struct param)); } /* Print a parameter */ /**/ void printparamnode(HashNode hn, int printflags) { Param p = (Param) hn; char *t, **u; if (p->flags & PM_UNSET) return; /* Print the attributes of the parameter */ if (printflags & PRINT_TYPE) { if (p->flags & PM_INTEGER) printf("integer "); if (p->flags & PM_ARRAY) printf("array "); if (p->flags & PM_LEFT) printf("left justified %d ", p->ct); if (p->flags & PM_RIGHT_B) printf("right justified %d ", p->ct); if (p->flags & PM_RIGHT_Z) printf("zero filled %d ", p->ct); if (p->flags & PM_LOWER) printf("lowercase "); if (p->flags & PM_UPPER) printf("uppercase "); if (p->flags & PM_READONLY) printf("readonly "); if (p->flags & PM_TAGGED) printf("tagged "); if (p->flags & PM_EXPORTED) printf("exported "); } if (printflags & PRINT_NAMEONLY) { zputs(p->nam, stdout); putchar('\n'); return; } /* How the value is displayed depends * * on the type of the parameter */ quotedzputs(p->nam, stdout); putchar('='); switch (PM_TYPE(p->flags)) { case PM_SCALAR: /* string: simple output */ if (p->gets.cfn && (t = p->gets.cfn(p))) quotedzputs(t, stdout); putchar('\n'); break; case PM_INTEGER: /* integer */ printf("%ld\n", p->gets.ifn(p)); break; case PM_ARRAY: /* array */ putchar('('); u = p->gets.afn(p); if(*u) { quotedzputs(*u++, stdout); while (*u) { putchar(' '); quotedzputs(*u++, stdout); } } printf(")\n"); break; } } /****************************************/ /* Named Directory Hash Table Functions */ /****************************************/ /* size of the initial name directory hash table */ #define INITIAL_NAMEDDIR 201 /* != 0 if all the usernames have already been * * added to the named directory hash table. */ int allusersadded; /* Create new hash table for named directories */ /**/ void createnameddirtable(void) { nameddirtab = newhashtable(INITIAL_NAMEDDIR); nameddirtab->hash = hasher; nameddirtab->emptytable = emptynameddirtable; nameddirtab->filltable = fillnameddirtable; nameddirtab->addnode = addnameddirnode; nameddirtab->getnode = gethashnode; nameddirtab->getnode2 = gethashnode2; nameddirtab->removenode = removenameddirnode; nameddirtab->disablenode = NULL; nameddirtab->enablenode = NULL; nameddirtab->freenode = freenameddirnode; nameddirtab->printnode = printnameddirnode; #ifdef ZSH_HASH_DEBUG nameddirtab->printinfo = printhashtabinfo; nameddirtab->tablename = ztrdup("nameddirtab"); #endif allusersadded = 0; finddir(NULL); /* clear the finddir cache */ } /* Empty the named directories table */ /**/ void emptynameddirtable(HashTable ht) { emptyhashtable(ht, INITIAL_NAMEDDIR); allusersadded = 0; finddir(NULL); /* clear the finddir cache */ } /* Add all the usernames in the password file/database * * to the named directories table. */ /**/ void fillnameddirtable(HashTable ht) { if (!allusersadded) { struct passwd *pw; setpwent(); /* loop through the password file/database * * and add all entries returned. */ while ((pw = getpwent()) && !errflag) adduserdir(ztrdup(pw->pw_name), pw->pw_dir, ND_USERNAME, 1); endpwent(); allusersadded = 1; } return; } /* Add an entry to the named directory hash * * table, clearing the finddir() cache and * * initialising the `diff' member. */ /**/ void addnameddirnode(HashTable ht, char *nam, void *nodeptr) { Nameddir nd = (Nameddir) nodeptr; nd->diff = strlen(nd->dir) - strlen(nam); finddir(NULL); /* clear the finddir cache */ addhashnode(ht, nam, nodeptr); } /* Remove an entry from the named directory * * hash table, clearing the finddir() cache. */ /**/ HashNode removenameddirnode(HashTable ht, char *nam) { HashNode hn = removehashnode(ht, nam); if(hn) finddir(NULL); /* clear the finddir cache */ return hn; } /* Free up the memory used by a named directory hash node. */ /**/ void freenameddirnode(HashNode hn) { Nameddir nd = (Nameddir) hn; zsfree(nd->nam); zsfree(nd->dir); zfree(nd, sizeof(struct nameddir)); } /* Print a named directory */ /**/ void printnameddirnode(HashNode hn, int printflags) { Nameddir nd = (Nameddir) hn; if (printflags & PRINT_NAMEONLY) { zputs(nd->nam, stdout); putchar('\n'); return; } quotedzputs(nd->nam, stdout); putchar('='); quotedzputs(nd->dir, stdout); putchar('\n'); } /********************************/ /* Compctl Hash Table Functions */ /********************************/ /**/ void createcompctltable(void) { compctltab = newhashtable(23); compctltab->hash = hasher; compctltab->emptytable = NULL; compctltab->filltable = NULL; compctltab->addnode = addhashnode; compctltab->getnode = gethashnode2; compctltab->getnode2 = gethashnode2; compctltab->removenode = removehashnode; compctltab->disablenode = NULL; compctltab->enablenode = NULL; compctltab->freenode = freecompctlp; compctltab->printnode = printcompctlp; #ifdef ZSH_HASH_DEBUG compctltab->printinfo = printhashtabinfo; compctltab->tablename = ztrdup("compctltab"); #endif } /**/ void freecompctl(Compctl cc) { if (cc == &cc_default || cc == &cc_first || cc == &cc_compos || --cc->refc > 0) return; zsfree(cc->keyvar); zsfree(cc->glob); zsfree(cc->str); zsfree(cc->func); zsfree(cc->explain); zsfree(cc->prefix); zsfree(cc->suffix); zsfree(cc->hpat); zsfree(cc->subcmd); if (cc->cond) freecompcond(cc->cond); if (cc->ext) { Compctl n, m; n = cc->ext; do { m = (Compctl) (n->next); freecompctl(n); n = m; } while (n); } if (cc->xor && cc->xor != &cc_default) freecompctl(cc->xor); zfree(cc, sizeof(struct compctl)); } /**/ void freecompctlp(HashNode hn) { Compctlp ccp = (Compctlp) hn; zsfree(ccp->nam); freecompctl(ccp->cc); zfree(ccp, sizeof(struct compctlp)); } /***********************************************************/ /* Emacs Multi-Character Key Bindings Hash Table Functions */ /***********************************************************/ /* size of the initial hashtable for multi-character * * emacs key bindings. */ #define INITIAL_EMKEYBINDTAB 67 /**/ void createemkeybindtable(void) { emkeybindtab = newhashtable(INITIAL_EMKEYBINDTAB); emkeybindtab->hash = hasher; emkeybindtab->emptytable = emptyemkeybindtable; emkeybindtab->filltable = NULL; emkeybindtab->addnode = addhashnode; emkeybindtab->getnode = gethashnode2; emkeybindtab->getnode2 = gethashnode2; emkeybindtab->removenode = removehashnode; emkeybindtab->disablenode = NULL; emkeybindtab->enablenode = NULL; emkeybindtab->freenode = freekeynode; /* need to combine printbinding and printfuncbinding for this */ emkeybindtab->printnode = NULL; #ifdef ZSH_HASH_DEBUG emkeybindtab->printinfo = printhashtabinfo; emkeybindtab->tablename = ztrdup("emkeybindtab"); #endif } /**/ void emptyemkeybindtable(HashTable ht) { emptyhashtable(ht, INITIAL_EMKEYBINDTAB); } /********************************************************/ /* Vi Multi-Character Key Bindings Hash Table Functions */ /********************************************************/ /* size of the initial hash table for * * multi-character vi key bindings. */ #define INITIAL_VIKEYBINDTAB 20 /**/ void createvikeybindtable(void) { vikeybindtab = newhashtable(INITIAL_VIKEYBINDTAB); vikeybindtab->hash = hasher; vikeybindtab->emptytable = emptyvikeybindtable; vikeybindtab->filltable = NULL; vikeybindtab->addnode = addhashnode; vikeybindtab->getnode = gethashnode2; vikeybindtab->getnode2 = gethashnode2; vikeybindtab->removenode = removehashnode; vikeybindtab->disablenode = NULL; vikeybindtab->enablenode = NULL; vikeybindtab->freenode = freekeynode; /* need to combine printbinding and printfuncbinding for this */ vikeybindtab->printnode = NULL; #ifdef ZSH_HASH_DEBUG vikeybindtab->printinfo = printhashtabinfo; vikeybindtab->tablename = ztrdup("vikeybindtab"); #endif } /**/ void emptyvikeybindtable(HashTable ht) { emptyhashtable(ht, INITIAL_VIKEYBINDTAB); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.