diff options
Diffstat (limited to 'dotfiles/system/.zsh/modules/Src/hashtable.c')
| -rw-r--r-- | dotfiles/system/.zsh/modules/Src/hashtable.c | 1617 |
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; - } -} |
