summaryrefslogtreecommitdiff
path: root/dotfiles/system/.zsh/modules/Src/hashtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'dotfiles/system/.zsh/modules/Src/hashtable.c')
-rw-r--r--dotfiles/system/.zsh/modules/Src/hashtable.c1617
1 files changed, 0 insertions, 1617 deletions
diff --git a/dotfiles/system/.zsh/modules/Src/hashtable.c b/dotfiles/system/.zsh/modules/Src/hashtable.c
deleted file mode 100644
index b7baa31..0000000
--- a/dotfiles/system/.zsh/modules/Src/hashtable.c
+++ /dev/null
@@ -1,1617 +0,0 @@
-/*
- * hashtable.c - hash tables
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1997 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 "../config.h"
-
-#ifdef ZSH_HASH_DEBUG
-# define HASHTABLE_DEBUG_MEMBERS \
- /* Members of struct hashtable used for debugging hash tables */ \
- HashTable next, last; /* linked list of all hash tables */ \
- char *tablename; /* string containing name of the hash table */ \
- PrintTableStats printinfo; /* pointer to function to print table stats */
-#else /* !ZSH_HASH_DEBUG */
-# define HASHTABLE_DEBUG_MEMBERS
-#endif /* !ZSH_HASH_DEBUG */
-
-#define HASHTABLE_INTERNAL_MEMBERS \
- ScanStatus scan; /* status of a scan over this hashtable */ \
- HASHTABLE_DEBUG_MEMBERS
-
-typedef struct scanstatus *ScanStatus;
-
-#include "zsh.mdh"
-#include "hashtable.pro"
-
-/* Structure for recording status of a hashtable scan in progress. When a *
- * scan starts, the .scan member of the hashtable structure points to one *
- * of these. That member being non-NULL disables resizing of the *
- * hashtable (when adding elements). When elements are deleted, the *
- * contents of this structure is used to make sure the scan won't stumble *
- * into the deleted element. */
-
-struct scanstatus {
- int sorted;
- union {
- struct {
- HashNode *hashtab;
- int ct;
- } s;
- HashNode u;
- } u;
-};
-
-/********************************/
-/* Generic Hash Table functions */
-/********************************/
-
-#ifdef ZSH_HASH_DEBUG
-static HashTable firstht, lastht;
-#endif /* ZSH_HASH_DEBUG */
-
-/* Generic hash function */
-
-/**/
-mod_export unsigned
-hasher(const char *str)
-{
- unsigned hashval = 0, c;
-
- while ((c = *((unsigned char *) str++)))
- hashval += (hashval << 5) + c;
-
- return hashval;
-}
-
-/* Get a new hash table */
-
-/**/
-mod_export HashTable
-newhashtable(int size, UNUSED(char const *name), UNUSED(PrintTableStats printinfo))
-{
- HashTable ht;
-
- ht = (HashTable) zshcalloc(sizeof *ht);
-#ifdef ZSH_HASH_DEBUG
- ht->next = NULL;
- if(!firstht)
- firstht = ht;
- ht->last = lastht;
- if(lastht)
- lastht->next = ht;
- lastht = ht;
- ht->printinfo = printinfo ? printinfo : printhashtabinfo;
- ht->tablename = ztrdup(name);
-#endif /* ZSH_HASH_DEBUG */
- ht->nodes = (HashNode *) zshcalloc(size * sizeof(HashNode));
- ht->hsize = size;
- ht->ct = 0;
- ht->scan = NULL;
- ht->scantab = NULL;
- return ht;
-}
-
-/* Delete a hash table. After this function has been used, any *
- * existing pointers to the hash table are invalid. */
-
-/**/
-mod_export void
-deletehashtable(HashTable ht)
-{
- ht->emptytable(ht);
-#ifdef ZSH_HASH_DEBUG
- if(ht->next)
- ht->next->last = ht->last;
- else
- lastht = ht->last;
- if(ht->last)
- ht->last->next = ht->next;
- else
- firstht = ht->next;
- zsfree(ht->tablename);
-#endif /* ZSH_HASH_DEBUG */
- zfree(ht->nodes, ht->hsize * sizeof(HashNode));
- zfree(ht, sizeof(*ht));
-}
-
-/* Add a node to a hash table. *
- * nam is the key to use in hashing. nodeptr points *
- * 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. */
-
-/**/
-mod_export void
-addhashnode(HashTable ht, char *nam, void *nodeptr)
-{
- HashNode oldnode = addhashnode2(ht, nam, nodeptr);
- if (oldnode)
- ht->freenode(oldnode);
-}
-
-/* Add a node to a hash table, returning the old node on replacement. */
-
-/**/
-HashNode
-addhashnode2(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 && !ht->scan)
- expandhashtable(ht);
- return NULL;
- }
-
- /* else check if the first node contains the same key */
- if (ht->cmpnodes(hp->nam, hn->nam) == 0) {
- ht->nodes[hashval] = hn;
- replacing:
- hn->next = hp->next;
- if(ht->scan) {
- if(ht->scan->sorted) {
- HashNode *hashtab = ht->scan->u.s.hashtab;
- int i;
- for(i = ht->scan->u.s.ct; i--; )
- if(hashtab[i] == hp)
- hashtab[i] = hn;
- } else if(ht->scan->u.u == hp)
- ht->scan->u.u = hn;
- }
- return hp;
- }
-
- /* else run through the list and check all the keys */
- hq = hp;
- hp = hp->next;
- for (; hp; hq = hp, hp = hp->next) {
- if (ht->cmpnodes(hp->nam, hn->nam) == 0) {
- hq->next = hn;
- goto replacing;
- }
- }
-
- /* 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 && !ht->scan)
- expandhashtable(ht);
- return NULL;
-}
-
-/* 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 */
-
-/**/
-mod_export HashNode
-gethashnode(HashTable ht, const char *nam)
-{
- unsigned hashval;
- HashNode hp;
-
- hashval = ht->hash(nam) % ht->hsize;
- for (hp = ht->nodes[hashval]; hp; hp = hp->next) {
- if (ht->cmpnodes(hp->nam, nam) == 0) {
- 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. */
-
-/**/
-mod_export HashNode
-gethashnode2(HashTable ht, const char *nam)
-{
- unsigned hashval;
- HashNode hp;
-
- hashval = ht->hash(nam) % ht->hsize;
- for (hp = ht->nodes[hashval]; hp; hp = hp->next) {
- if (ht->cmpnodes(hp->nam, nam) == 0)
- 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 */
-
-/**/
-mod_export HashNode
-removehashnode(HashTable ht, const 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 (ht->cmpnodes(hp->nam, nam) == 0) {
- ht->nodes[hashval] = hp->next;
- gotit:
- ht->ct--;
- if(ht->scan) {
- if(ht->scan->sorted) {
- HashNode *hashtab = ht->scan->u.s.hashtab;
- int i;
- for(i = ht->scan->u.s.ct; i--; )
- if(hashtab[i] == hp)
- hashtab[i] = NULL;
- } else if(ht->scan->u.u == hp)
- ht->scan->u.u = hp->next;
- }
- 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 (ht->cmpnodes(hp->nam, nam) == 0) {
- hq->next = hp->next;
- goto gotit;
- }
- }
-
- /* else it is not in the list, so return NULL */
- return NULL;
-}
-
-/* Disable a node in a hash table */
-
-/**/
-void
-disablehashnode(HashNode hn, UNUSED(int flags))
-{
- hn->flags |= DISABLED;
-}
-
-/* Enable a node in a hash table */
-
-/**/
-void
-enablehashnode(HashNode hn, UNUSED(int flags))
-{
- hn->flags &= ~DISABLED;
-}
-
-/* Compare two hash table entries by name */
-
-/**/
-static int
-hnamcmp(const void *ap, const void *bp)
-{
- HashNode a = *(HashNode *)ap;
- HashNode b = *(HashNode *)bp;
- return ztrcmp(a->nam, 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 != 0, then sort entries of hash table before scanning.
- * If flags1 > 0, then execute scanfunc on a node only if at least one of
- * these flags is set.
- * If flags2 > 0, then execute scanfunc on a node only if all of
- * these flags are NOT set.
- * The conditions above for flags1/flags2 must both be true.
- *
- * It is safe to add, remove or replace hash table elements from within
- * the scanfunc. Replaced elements will appear in the scan exactly once,
- * the new version if it was not scanned before the replacement was made.
- * Added elements might or might not appear in the scan.
- *
- * pprog, if non-NULL, is a pattern that must match the name
- * of the node.
- *
- * The function returns the number of matches, as reduced by pprog, flags1
- * and flags2.
- */
-
-/**/
-mod_export int
-scanmatchtable(HashTable ht, Patprog pprog, int sorted,
- int flags1, int flags2, ScanFunc scanfunc, int scanflags)
-{
- int match = 0;
- struct scanstatus st;
-
- /*
- * scantab is currently only used by modules to scan
- * tables where the contents are generated on the fly from
- * other objects. Note the fact that in this case pprog,
- * sorted, flags1 and flags2 are ignore.
- */
- if (!pprog && ht->scantab) {
- ht->scantab(ht, scanfunc, scanflags);
- return ht->ct;
- }
- if (sorted) {
- int i, ct = ht->ct;
- VARARR(HashNode, hnsorttab, ct);
- HashNode *htp, hn;
-
- /*
- * Because the structure might change under our feet,
- * we can't apply the flags and the pattern before sorting,
- * tempting though that is.
- */
- for (htp = hnsorttab, i = 0; i < ht->hsize; i++)
- for (hn = ht->nodes[i]; hn; hn = hn->next)
- *htp++ = hn;
- qsort((void *)hnsorttab, ct, sizeof(HashNode), hnamcmp);
-
- st.sorted = 1;
- st.u.s.hashtab = hnsorttab;
- st.u.s.ct = ct;
- ht->scan = &st;
-
- for (htp = hnsorttab, i = 0; i < ct; i++, htp++) {
- if ((!flags1 || ((*htp)->flags & flags1)) &&
- !((*htp)->flags & flags2) &&
- (!pprog || pattry(pprog, (*htp)->nam))) {
- match++;
- scanfunc(*htp, scanflags);
- }
- }
-
- ht->scan = NULL;
- } else {
- int i, hsize = ht->hsize;
- HashNode *nodes = ht->nodes;
-
- st.sorted = 0;
- ht->scan = &st;
-
- for (i = 0; i < hsize; i++)
- for (st.u.u = nodes[i]; st.u.u; ) {
- HashNode hn = st.u.u;
- st.u.u = st.u.u->next;
- if ((!flags1 || (hn->flags & flags1)) && !(hn->flags & flags2)
- && (!pprog || pattry(pprog, hn->nam))) {
- match++;
- scanfunc(hn, scanflags);
- }
- }
-
- ht->scan = NULL;
- }
-
- return match;
-}
-
-
-/**/
-mod_export int
-scanhashtable(HashTable ht, int sorted, int flags1, int flags2,
- ScanFunc scanfunc, int scanflags)
-{
- return scanmatchtable(ht, NULL, sorted, flags1, flags2,
- scanfunc, scanflags);
-}
-
-/* Expand hash tables when they get too many entries. *
- * The new size is 4 times the previous size. */
-
-/**/
-static 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 *) zshcalloc(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 */
-
-/**/
-static void
-resizehashtable(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 *) zshcalloc(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;
-}
-
-/* Generic method to empty a hash table */
-
-/**/
-mod_export void
-emptyhashtable(HashTable ht)
-{
- resizehashtable(ht, ht->hsize);
-}
-
-/**/
-#ifdef ZSH_HASH_DEBUG
-
-/* Print info about hash table */
-
-#define MAXDEPTH 7
-
-/**/
-static 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);
-}
-
-/**/
-int
-bin_hashinfo(UNUSED(char *nam), UNUSED(char **args), UNUSED(Options ops), UNUSED(int func))
-{
- HashTable ht;
-
- printf("----------------------------------------------------\n");
- queue_signals();
- for(ht = firstht; ht; ht = ht->next) {
- ht->printinfo(ht);
- printf("----------------------------------------------------\n");
- }
- unqueue_signals();
- return 0;
-}
-
-/**/
-#endif /* ZSH_HASH_DEBUG */
-
-/********************************/
-/* Command Hash Table Functions */
-/********************************/
-
-/* hash table containing external commands */
-
-/**/
-mod_export HashTable cmdnamtab;
-
-/* how far we've hashed the PATH so far */
-
-/**/
-mod_export char **pathchecked;
-
-/* Create a new command hash table */
-
-/**/
-void
-createcmdnamtable(void)
-{
- cmdnamtab = newhashtable(201, "cmdnamtab", NULL);
-
- cmdnamtab->hash = hasher;
- cmdnamtab->emptytable = emptycmdnamtable;
- cmdnamtab->filltable = fillcmdnamtable;
- cmdnamtab->cmpnodes = strcmp;
- cmdnamtab->addnode = addhashnode;
- cmdnamtab->getnode = gethashnode2;
- cmdnamtab->getnode2 = gethashnode2;
- cmdnamtab->removenode = removehashnode;
- cmdnamtab->disablenode = NULL;
- cmdnamtab->enablenode = NULL;
- cmdnamtab->freenode = freecmdnamnode;
- cmdnamtab->printnode = printcmdnamnode;
-
- pathchecked = path;
-}
-
-/**/
-static void
-emptycmdnamtable(HashTable ht)
-{
- emptyhashtable(ht);
- pathchecked = path;
-}
-
-/* Add all commands in a given directory *
- * to the command hashtable. */
-
-/**/
-void
-hashdir(char **dirp)
-{
- Cmdnam cn;
- DIR *dir;
- char *fn, *unmetadir, *pathbuf, *pathptr;
- int dirlen;
-#if defined(_WIN32) || defined(__CYGWIN__)
- char *exe;
-#endif /* _WIN32 || _CYGWIN__ */
-
- if (isrelative(*dirp))
- return;
- unmetadir = unmeta(*dirp);
- if (!(dir = opendir(unmetadir)))
- return;
-
- dirlen = strlen(unmetadir);
- pathbuf = (char *)zalloc(dirlen + PATH_MAX + 2);
- sprintf(pathbuf, "%s/", unmetadir);
- pathptr = pathbuf + dirlen + 1;
-
- while ((fn = zreaddir(dir, 1))) {
- if (!cmdnamtab->getnode(cmdnamtab, fn)) {
- char *fname = ztrdup(fn);
- struct stat statbuf;
- int add = 0, dummylen;
-
- unmetafy(fn, &dummylen);
- if (strlen(fn) > PATH_MAX) {
- /* Too heavy to do all the allocation */
- add = 1;
- } else {
- strcpy(pathptr, fn);
- /*
- * This is the same test as for the glob qualifier for
- * executable plain files.
- */
- if (unset(HASHEXECUTABLESONLY) ||
- (access(pathbuf, X_OK) == 0 &&
- stat(pathbuf, &statbuf) == 0 &&
- S_ISREG(statbuf.st_mode) && (statbuf.st_mode & S_IXUGO)))
- add = 1;
- }
- if (add) {
- cn = (Cmdnam) zshcalloc(sizeof *cn);
- cn->node.flags = 0;
- cn->u.name = dirp;
- cmdnamtab->addnode(cmdnamtab, fname, cn);
- } else
- zsfree(fname);
- }
-#if defined(_WIN32) || defined(__CYGWIN__)
- /* Hash foo.exe as foo, since when no real foo exists, foo.exe
- will get executed by DOS automatically. This quiets
- spurious corrections when CORRECT or CORRECT_ALL is set. */
- if ((exe = strrchr(fn, '.')) &&
- (exe[1] == 'E' || exe[1] == 'e') &&
- (exe[2] == 'X' || exe[2] == 'x') &&
- (exe[3] == 'E' || exe[3] == 'e') && exe[4] == 0) {
- *exe = 0;
- if (!cmdnamtab->getnode(cmdnamtab, fn)) {
- cn = (Cmdnam) zshcalloc(sizeof *cn);
- cn->node.flags = 0;
- cn->u.name = dirp;
- cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
- }
- }
-#endif /* _WIN32 || __CYGWIN__ */
- }
- closedir(dir);
- zfree(pathbuf, dirlen + PATH_MAX + 2);
-}
-
-/* Go through user's PATH and add everything to *
- * the command hashtable. */
-
-/**/
-static void
-fillcmdnamtable(UNUSED(HashTable ht))
-{
- char **pq;
-
- for (pq = pathchecked; *pq; pq++)
- hashdir(pq);
-
- pathchecked = pq;
-}
-
-/**/
-static void
-freecmdnamnode(HashNode hn)
-{
- Cmdnam cn = (Cmdnam) hn;
-
- zsfree(cn->node.nam);
- if (cn->node.flags & HASHED)
- zsfree(cn->u.cmd);
-
- zfree(cn, sizeof(struct cmdnam));
-}
-
-/* Print an element of the cmdnamtab hash table (external command) */
-
-/**/
-static void
-printcmdnamnode(HashNode hn, int printflags)
-{
- Cmdnam cn = (Cmdnam) hn;
-
- if (printflags & PRINT_WHENCE_WORD) {
- printf("%s: %s\n", cn->node.nam, (cn->node.flags & HASHED) ?
- "hashed" : "command");
- return;
- }
-
- if ((printflags & PRINT_WHENCE_CSH) || (printflags & PRINT_WHENCE_SIMPLE)) {
- if (cn->node.flags & HASHED) {
- zputs(cn->u.cmd, stdout);
- putchar('\n');
- } else {
- zputs(*(cn->u.name), stdout);
- putchar('/');
- zputs(cn->node.nam, stdout);
- putchar('\n');
- }
- return;
- }
-
- if (printflags & PRINT_WHENCE_VERBOSE) {
- if (cn->node.flags & HASHED) {
- nicezputs(cn->node.nam, stdout);
- printf(" is hashed to ");
- nicezputs(cn->u.cmd, stdout);
- putchar('\n');
- } else {
- nicezputs(cn->node.nam, stdout);
- printf(" is ");
- nicezputs(*(cn->u.name), stdout);
- putchar('/');
- nicezputs(cn->node.nam, stdout);
- putchar('\n');
- }
- return;
- }
-
- if (printflags & PRINT_LIST) {
- printf("hash ");
-
- if(cn->node.nam[0] == '-')
- printf("-- ");
- }
-
- if (cn->node.flags & HASHED) {
- quotedzputs(cn->node.nam, stdout);
- putchar('=');
- quotedzputs(cn->u.cmd, stdout);
- putchar('\n');
- } else {
- quotedzputs(cn->node.nam, stdout);
- putchar('=');
- quotedzputs(*(cn->u.name), stdout);
- putchar('/');
- quotedzputs(cn->node.nam, stdout);
- putchar('\n');
- }
-}
-
-/***************************************/
-/* Shell Function Hash Table Functions */
-/***************************************/
-
-/* hash table containing the shell functions */
-
-/**/
-mod_export HashTable shfunctab;
-
-/**/
-void
-createshfunctable(void)
-{
- shfunctab = newhashtable(7, "shfunctab", NULL);
-
- shfunctab->hash = hasher;
- shfunctab->emptytable = NULL;
- shfunctab->filltable = NULL;
- shfunctab->cmpnodes = strcmp;
- shfunctab->addnode = addhashnode;
- shfunctab->getnode = gethashnode;
- shfunctab->getnode2 = gethashnode2;
- shfunctab->removenode = removeshfuncnode;
- shfunctab->disablenode = disableshfuncnode;
- shfunctab->enablenode = enableshfuncnode;
- shfunctab->freenode = freeshfuncnode;
- shfunctab->printnode = printshfuncnode;
-}
-
-/* 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. */
-
-/**/
-static HashNode
-removeshfuncnode(UNUSED(HashTable ht), const char *nam)
-{
- HashNode hn;
- int signum;
-
- if (!strncmp(nam, "TRAP", 4) && (signum = getsignum(nam + 4)) != -1)
- hn = removetrap(signum);
- else
- hn = removehashnode(shfunctab, nam);
-
- return hn;
-}
-
-/* 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. */
-
-/**/
-static void
-disableshfuncnode(HashNode hn, UNUSED(int flags))
-{
- hn->flags |= DISABLED;
- if (!strncmp(hn->nam, "TRAP", 4)) {
- int signum = getsignum(hn->nam + 4);
- if (signum != -1) {
- sigtrapped[signum] &= ~ZSIG_FUNC;
- 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. */
-
-/**/
-static void
-enableshfuncnode(HashNode hn, UNUSED(int flags))
-{
- Shfunc shf = (Shfunc) hn;
-
- shf->node.flags &= ~DISABLED;
- if (!strncmp(shf->node.nam, "TRAP", 4)) {
- int signum = getsignum(shf->node.nam + 4);
- if (signum != -1) {
- settrap(signum, NULL, ZSIG_FUNC);
- }
- }
-}
-
-/**/
-static void
-freeshfuncnode(HashNode hn)
-{
- Shfunc shf = (Shfunc) hn;
-
- zsfree(shf->node.nam);
- if (shf->funcdef)
- freeeprog(shf->funcdef);
- if (shf->redir)
- freeeprog(shf->redir);
- dircache_set(&shf->filename, NULL);
- if (shf->sticky) {
- if (shf->sticky->n_on_opts)
- zfree(shf->sticky->on_opts,
- shf->sticky->n_on_opts * sizeof(*shf->sticky->on_opts));
- if (shf->sticky->n_off_opts)
- zfree(shf->sticky->off_opts,
- shf->sticky->n_off_opts * sizeof(*shf->sticky->off_opts));
- zfree(shf->sticky, sizeof(*shf->sticky));
- }
- zfree(shf, sizeof(struct shfunc));
-}
-
-/* Print a shell function */
-
-/**/
-static void
-printshfuncnode(HashNode hn, int printflags)
-{
- Shfunc f = (Shfunc) hn;
- char *t = 0;
-
- if ((printflags & PRINT_NAMEONLY) ||
- ((printflags & PRINT_WHENCE_SIMPLE) &&
- !(printflags & PRINT_WHENCE_FUNCDEF))) {
- zputs(f->node.nam, stdout);
- putchar('\n');
- return;
- }
-
- if ((printflags & (PRINT_WHENCE_VERBOSE|PRINT_WHENCE_WORD)) &&
- !(printflags & PRINT_WHENCE_FUNCDEF)) {
- nicezputs(f->node.nam, stdout);
- printf((printflags & PRINT_WHENCE_WORD) ? ": function" :
- (f->node.flags & PM_UNDEFINED) ?
- " is an autoload shell function" :
- " is a shell function");
- if ((printflags & PRINT_WHENCE_VERBOSE) && f->filename) {
- printf(" from ");
- quotedzputs(f->filename, stdout);
- if (f->node.flags & PM_LOADDIR) {
- printf("/");
- quotedzputs(f->node.nam, stdout);
- }
- }
- putchar('\n');
- return;
- }
-
- quotedzputs(f->node.nam, stdout);
- if (f->funcdef || f->node.flags & PM_UNDEFINED) {
- printf(" () {\n");
- zoutputtab(stdout);
- if (f->node.flags & PM_UNDEFINED) {
- printf("%c undefined\n", hashchar);
- zoutputtab(stdout);
- } else
- t = getpermtext(f->funcdef, NULL, 1);
- if (f->node.flags & (PM_TAGGED|PM_TAGGED_LOCAL)) {
- printf("%c traced\n", hashchar);
- zoutputtab(stdout);
- }
- if (!t) {
- char *fopt = "UtTkzc";
- int flgs[] = {
- PM_UNALIASED, PM_TAGGED, PM_TAGGED_LOCAL,
- PM_KSHSTORED, PM_ZSHSTORED, PM_CUR_FPATH, 0
- };
- int fl;;
-
- zputs("builtin autoload -X", stdout);
- for (fl=0;fopt[fl];fl++)
- if (f->node.flags & flgs[fl]) putchar(fopt[fl]);
- if (f->filename && (f->node.flags & PM_LOADDIR)) {
- putchar(' ');
- zputs(f->filename, stdout);
- }
- } else {
- zputs(t, stdout);
- zsfree(t);
- if (f->funcdef->flags & EF_RUN) {
- printf("\n");
- zoutputtab(stdout);
- quotedzputs(f->node.nam, stdout);
- printf(" \"$@\"");
- }
- }
- printf("\n}");
- } else {
- printf(" () { }");
- }
- if (f->redir) {
- t = getpermtext(f->redir, NULL, 1);
- if (t) {
- zputs(t, stdout);
- zsfree(t);
- }
- }
-
- putchar('\n');
-}
-
-/*
- * Wrap scanmatchtable for shell functions with optional
- * expansion of leading tabs.
- * expand = 0 is standard: use hard tabs.
- * expand > 0 uses that many spaces.
- * expand < 0 uses no identation.
- *
- * Note this function and the following two are called with
- * interrupts queued, so saving and restoring text_expand_tabs
- * is safe.
- */
-
-/**/
-mod_export int
-scanmatchshfunc(Patprog pprog, int sorted, int flags1, int flags2,
- ScanFunc scanfunc, int scanflags, int expand)
-{
- int ret, save_expand;
-
- save_expand = text_expand_tabs;
- text_expand_tabs = expand;
- ret = scanmatchtable(shfunctab, pprog, sorted, flags1, flags2,
- scanfunc, scanflags);
- text_expand_tabs = save_expand;
-
- return ret;
-}
-
-/* Wrap scanhashtable to expand tabs for shell functions */
-
-/**/
-mod_export int
-scanshfunc(int sorted, int flags1, int flags2,
- ScanFunc scanfunc, int scanflags, int expand)
-{
- return scanmatchshfunc(NULL, sorted, flags1, flags2,
- scanfunc, scanflags, expand);
-}
-
-/* Wrap shfunctab->printnode to expand tabs */
-
-/**/
-mod_export void
-printshfuncexpand(HashNode hn, int printflags, int expand)
-{
- int save_expand;
-
- save_expand = text_expand_tabs;
- text_expand_tabs = expand;
- shfunctab->printnode(hn, printflags);
- text_expand_tabs = save_expand;
-}
-
-/*
- * Get a heap-duplicated name of the shell function, for
- * use in tracing.
- */
-
-/**/
-mod_export char *
-getshfuncfile(Shfunc shf)
-{
- if (shf->node.flags & PM_LOADDIR) {
- return zhtricat(shf->filename, "/", shf->node.nam);
- } else if (shf->filename) {
- return dupstring(shf->filename);
- } else {
- return NULL;
- }
-}
-
-/**************************************/
-/* Reserved Word Hash Table Functions */
-/**************************************/
-
-/* Nodes for reserved word hash table */
-
-static struct reswd reswds[] = {
- {{NULL, "!", 0}, BANG},
- {{NULL, "[[", 0}, DINBRACK},
- {{NULL, "{", 0}, INBRACE},
- {{NULL, "}", 0}, OUTBRACE},
- {{NULL, "case", 0}, CASE},
- {{NULL, "coproc", 0}, COPROC},
- {{NULL, "declare", 0}, TYPESET},
- {{NULL, "do", 0}, DOLOOP},
- {{NULL, "done", 0}, DONE},
- {{NULL, "elif", 0}, ELIF},
- {{NULL, "else", 0}, ELSE},
- {{NULL, "end", 0}, ZEND},
- {{NULL, "esac", 0}, ESAC},
- {{NULL, "export", 0}, TYPESET},
- {{NULL, "fi", 0}, FI},
- {{NULL, "float", 0}, TYPESET},
- {{NULL, "for", 0}, FOR},
- {{NULL, "foreach", 0}, FOREACH},
- {{NULL, "function", 0}, FUNC},
- {{NULL, "if", 0}, IF},
- {{NULL, "integer", 0}, TYPESET},
- {{NULL, "local", 0}, TYPESET},
- {{NULL, "nocorrect", 0}, NOCORRECT},
- {{NULL, "readonly", 0}, TYPESET},
- {{NULL, "repeat", 0}, REPEAT},
- {{NULL, "select", 0}, SELECT},
- {{NULL, "then", 0}, THEN},
- {{NULL, "time", 0}, TIME},
- {{NULL, "typeset", 0}, TYPESET},
- {{NULL, "until", 0}, UNTIL},
- {{NULL, "while", 0}, WHILE},
- {{NULL, NULL, 0}, 0}
-};
-
-/* hash table containing the reserved words */
-
-/**/
-mod_export HashTable reswdtab;
-
-/* Build the hash table containing zsh's reserved words. */
-
-/**/
-void
-createreswdtable(void)
-{
- Reswd rw;
-
- reswdtab = newhashtable(23, "reswdtab", NULL);
-
- reswdtab->hash = hasher;
- reswdtab->emptytable = NULL;
- reswdtab->filltable = NULL;
- reswdtab->cmpnodes = strcmp;
- reswdtab->addnode = addhashnode;
- reswdtab->getnode = gethashnode;
- reswdtab->getnode2 = gethashnode2;
- reswdtab->removenode = NULL;
- reswdtab->disablenode = disablehashnode;
- reswdtab->enablenode = enablehashnode;
- reswdtab->freenode = NULL;
- reswdtab->printnode = printreswdnode;
-
- for (rw = reswds; rw->node.nam; rw++)
- reswdtab->addnode(reswdtab, rw->node.nam, rw);
-}
-
-/* Print a reserved word */
-
-/**/
-static void
-printreswdnode(HashNode hn, int printflags)
-{
- Reswd rw = (Reswd) hn;
-
- if (printflags & PRINT_WHENCE_WORD) {
- printf("%s: reserved\n", rw->node.nam);
- return;
- }
-
- if (printflags & PRINT_WHENCE_CSH) {
- printf("%s: shell reserved word\n", rw->node.nam);
- return;
- }
-
- if (printflags & PRINT_WHENCE_VERBOSE) {
- printf("%s is a reserved word\n", rw->node.nam);
- return;
- }
-
- /* default is name only */
- printf("%s\n", rw->node.nam);
-}
-
-/********************************/
-/* Aliases Hash Table Functions */
-/********************************/
-
-/* hash table containing the aliases */
-
-/**/
-mod_export HashTable aliastab;
-
-/* has table containing suffix aliases */
-
-/**/
-mod_export HashTable sufaliastab;
-
-/* Create new hash tables for aliases */
-
-/**/
-void
-createaliastable(HashTable ht)
-{
- ht->hash = hasher;
- ht->emptytable = NULL;
- ht->filltable = NULL;
- ht->cmpnodes = strcmp;
- ht->addnode = addhashnode;
- ht->getnode = gethashnode;
- ht->getnode2 = gethashnode2;
- ht->removenode = removehashnode;
- ht->disablenode = disablehashnode;
- ht->enablenode = enablehashnode;
- ht->freenode = freealiasnode;
- ht->printnode = printaliasnode;
-}
-
-/**/
-void
-createaliastables(void)
-{
- /* Table for regular and global aliases */
-
- aliastab = newhashtable(23, "aliastab", NULL);
-
- createaliastable(aliastab);
-
- /* add the default aliases */
- aliastab->addnode(aliastab, ztrdup("run-help"), createaliasnode(ztrdup("man"), 0));
- aliastab->addnode(aliastab, ztrdup("which-command"), createaliasnode(ztrdup("whence"), 0));
-
-
- /* Table for suffix aliases --- make this smaller */
-
- sufaliastab = newhashtable(11, "sufaliastab", NULL);
-
- createaliastable(sufaliastab);
-}
-
-/* Create a new alias node */
-
-/**/
-mod_export Alias
-createaliasnode(char *txt, int flags)
-{
- Alias al;
-
- al = (Alias) zshcalloc(sizeof *al);
- al->node.flags = flags;
- al->text = txt;
- al->inuse = 0;
- return al;
-}
-
-/**/
-static void
-freealiasnode(HashNode hn)
-{
- Alias al = (Alias) hn;
-
- zsfree(al->node.nam);
- zsfree(al->text);
- zfree(al, sizeof(struct alias));
-}
-
-/* Print an alias */
-
-/**/
-static void
-printaliasnode(HashNode hn, int printflags)
-{
- Alias a = (Alias) hn;
-
- if (printflags & PRINT_NAMEONLY) {
- zputs(a->node.nam, stdout);
- putchar('\n');
- return;
- }
-
- if (printflags & PRINT_WHENCE_WORD) {
- if (a->node.flags & ALIAS_SUFFIX)
- printf("%s: suffix alias\n", a->node.nam);
- else if (a->node.flags & ALIAS_GLOBAL)
- printf("%s: global alias\n", a->node.nam);
- else
- printf("%s: alias\n", a->node.nam);
- return;
- }
-
- if (printflags & PRINT_WHENCE_SIMPLE) {
- zputs(a->text, stdout);
- putchar('\n');
- return;
- }
-
- if (printflags & PRINT_WHENCE_CSH) {
- nicezputs(a->node.nam, stdout);
- printf(": ");
- if (a->node.flags & ALIAS_SUFFIX)
- printf("suffix ");
- else if (a->node.flags & ALIAS_GLOBAL)
- printf("globally ");
- printf ("aliased to ");
- nicezputs(a->text, stdout);
- putchar('\n');
- return;
- }
-
- if (printflags & PRINT_WHENCE_VERBOSE) {
- nicezputs(a->node.nam, stdout);
- printf(" is a");
- if (a->node.flags & ALIAS_SUFFIX)
- printf(" suffix");
- else if (a->node.flags & ALIAS_GLOBAL)
- printf(" global");
- else
- printf("n");
- printf(" alias for ");
- nicezputs(a->text, stdout);
- putchar('\n');
- return;
- }
-
- if (printflags & PRINT_LIST) {
- /* Fast fail on unrepresentable values. */
- if (strchr(a->node.nam, '=')) {
- zwarn("invalid alias '%s' encountered while printing aliases",
- a->node.nam);
- /* ### TODO: Return an error status to the C caller */
- return;
- }
-
- /* Normal path. */
- printf("alias ");
- if (a->node.flags & ALIAS_SUFFIX)
- printf("-s ");
- else if (a->node.flags & ALIAS_GLOBAL)
- printf("-g ");
-
- /* If an alias begins with `-' or `+', then we must output `-- '
- * first, so that it is not interpreted as an option. */
- if(a->node.nam[0] == '-' || a->node.nam[0] == '+')
- printf("-- ");
- }
-
- quotedzputs(a->node.nam, stdout);
- putchar('=');
- quotedzputs(a->text, stdout);
-
- putchar('\n');
-}
-
-/*************************************/
-/* History Line Hash Table Functions */
-/*************************************/
-
-/**/
-void
-createhisttable(void)
-{
- histtab = newhashtable(599, "histtab", NULL);
-
- histtab->hash = histhasher;
- histtab->emptytable = emptyhisttable;
- histtab->filltable = NULL;
- histtab->cmpnodes = histstrcmp;
- histtab->addnode = addhistnode;
- histtab->getnode = gethashnode2;
- histtab->getnode2 = gethashnode2;
- histtab->removenode = removehashnode;
- histtab->disablenode = NULL;
- histtab->enablenode = NULL;
- histtab->freenode = freehistnode;
- histtab->printnode = NULL;
-}
-
-/**/
-unsigned
-histhasher(const char *str)
-{
- unsigned hashval = 0;
-
- while (inblank(*str)) str++;
-
- while (*str) {
- if (inblank(*str)) {
- do str++; while (inblank(*str));
- if (*str)
- hashval += (hashval << 5) + ' ';
- }
- else
- hashval += (hashval << 5) + *(unsigned char *)str++;
- }
- return hashval;
-}
-
-/**/
-void
-emptyhisttable(HashTable ht)
-{
- emptyhashtable(ht);
- if (hist_ring)
- histremovedups();
-}
-
-/* Compare two strings with normalized white-space */
-
-/**/
-int
-histstrcmp(const char *str1, const char *str2)
-{
- while (inblank(*str1)) str1++;
- while (inblank(*str2)) str2++;
- while (*str1 && *str2) {
- if (inblank(*str1)) {
- if (!inblank(*str2))
- break;
- do str1++; while (inblank(*str1));
- do str2++; while (inblank(*str2));
- }
- else {
- if (*str1 != *str2)
- break;
- str1++;
- str2++;
- }
- }
- return *str1 - *str2;
-}
-
-/**/
-void
-addhistnode(HashTable ht, char *nam, void *nodeptr)
-{
- HashNode oldnode = addhashnode2(ht, nam, nodeptr);
- Histent he = (Histent)nodeptr;
- if (oldnode && oldnode != (HashNode)nodeptr) {
- if (he->node.flags & HIST_MAKEUNIQUE
- || (he->node.flags & HIST_FOREIGN && (Histent)oldnode == he->up)) {
- (void) addhashnode2(ht, oldnode->nam, oldnode); /* restore hash */
- he->node.flags |= HIST_DUP;
- he->node.flags &= ~HIST_MAKEUNIQUE;
- }
- else {
- oldnode->flags |= HIST_DUP;
- if (hist_ignore_all_dups)
- freehistnode(oldnode); /* Remove the old dup */
- }
- }
- else
- he->node.flags &= ~HIST_MAKEUNIQUE;
-}
-
-/**/
-void
-freehistnode(HashNode nodeptr)
-{
- freehistdata((Histent)nodeptr, 1);
- zfree(nodeptr, sizeof (struct histent));
-}
-
-/**/
-void
-freehistdata(Histent he, int unlink)
-{
- if (!he)
- return;
-
- if (he == &curline)
- return;
-
- if (!(he->node.flags & (HIST_DUP | HIST_TMPSTORE)))
- removehashnode(histtab, he->node.nam);
-
- zsfree(he->node.nam);
- if (he->nwords)
- zfree(he->words, he->nwords*2*sizeof(short));
-
- if (unlink) {
- if (!--histlinect)
- hist_ring = NULL;
- else {
- if (he == hist_ring)
- hist_ring = hist_ring->up;
- he->up->down = he->down;
- he->down->up = he->up;
- }
- }
-}
-
-
-/***********************************************************************
- * Directory name cache mechanism
- *
- * The idea of this is that there are various shell structures,
- * notably functions, that record the directories with which they
- * are associated. Rather than store the full string each time,
- * we store a pointer to the same location and count the references.
- * This is optimised so that retrieval is quick at the expense of
- * searching the list when setting up the structure, which is a much
- * rarer operation.
- *
- * There is nothing special about the fact that the strings are
- * directories, except for the assumptions for efficiency that many
- * structures will point to the same one, and that there are not too
- * many different directories associated with the shell.
- **********************************************************************/
-
-struct dircache_entry
-{
- /* Name of directory in cache */
- char *name;
- /* Number of references to it */
- int refs;
-};
-
-/*
- * dircache is the cache, of length dircache_size.
- * dircache_lastentry is the last entry used, an optimisation
- * for multiple references to the same directory, e.g
- * "autoload /blah/blah/\*".
- */
-static struct dircache_entry *dircache, *dircache_lastentry;
-static int dircache_size;
-
-/*
- * Set *name to point to a cached version of value.
- * value is copied so may come from any source.
- *
- * If value is NULL, look for the existing value of *name (safe if this
- * too is NULL) and remove a reference to it from the cache. If it's
- * not found in the cache, it's assumed to be an allocated string and
- * freed --- this currently occurs for a shell function that's been
- * loaded as the filename is now a full path, not just a directory,
- * though we may one day optimise this to a cached directory plus a
- * name, too. Note --- the function does *not* otherwise check
- * if *name points to something already cached, so this is
- * necessary any time *name may already be in the cache.
- */
-
-/**/
-mod_export void
-dircache_set(char **name, char *value)
-{
- struct dircache_entry *dcptr, *dcnew;
-
- if (!value) {
- if (!*name)
- return;
- if (!dircache_size) {
- zsfree(*name);
- *name = NULL;
- return;
- }
-
- for (dcptr = dircache; dcptr < dircache + dircache_size; dcptr++)
- {
- /* Must be a pointer much, not a string match */
- if (*name == dcptr->name)
- {
- --dcptr->refs;
- if (!dcptr->refs) {
- ptrdiff_t ind = dcptr - dircache;
- zsfree(dcptr->name);
- --dircache_size;
-
- if (!dircache_size) {
- zfree(dircache, sizeof(*dircache));
- dircache = NULL;
- dircache_lastentry = NULL;
- *name = NULL;
- return;
- }
- dcnew = (struct dircache_entry *)
- zalloc(dircache_size * sizeof(*dcnew));
- if (ind)
- memcpy(dcnew, dircache, ind * sizeof(*dcnew));
- if (ind < dircache_size)
- memcpy(dcnew + ind, dcptr + 1,
- (dircache_size - ind) * sizeof(*dcnew));
- zfree(dircache, (dircache_size+1)*sizeof(*dcnew));
- dircache = dcnew;
- dircache_lastentry = NULL;
- }
- *name = NULL;
- return;
- }
- }
- zsfree(*name);
- *name = NULL;
- } else {
- /*
- * As the function path has been resolved to a particular
- * location, we'll store it as an absolute path.
- */
- if (*value != '/') {
- value = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP),
- "/", value);
- value = xsymlink(value, 1);
- }
- /*
- * We'll maintain the cache at exactly the right size rather
- * than overallocating. The rationale here is that typically
- * we'll get a lot of functions in a small number of directories
- * so the complexity overhead of maintaining a separate count
- * isn't really matched by the efficiency gain.
- */
- if (dircache_lastentry &&
- !strcmp(value, dircache_lastentry->name)) {
- *name = dircache_lastentry->name;
- ++dircache_lastentry->refs;
- return;
- } else if (!dircache_size) {
- dircache_size = 1;
- dcptr = dircache =
- (struct dircache_entry *)zalloc(sizeof(*dircache));
- } else {
- for (dcptr = dircache; dcptr < dircache + dircache_size; dcptr++)
- {
- if (!strcmp(value, dcptr->name)) {
- *name = dcptr->name;
- ++dcptr->refs;
- return;
- }
- }
- ++dircache_size;
- dircache = (struct dircache_entry *)
- zrealloc(dircache, sizeof(*dircache) * dircache_size);
- dcptr = dircache + dircache_size - 1;
- }
- dcptr->name = ztrdup(value);
- *name = dcptr->name;
- dcptr->refs = 1;
- dircache_lastentry = dcptr;
- }
-}