about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/subst.c4
-rw-r--r--Src/utils.c78
2 files changed, 63 insertions, 19 deletions
diff --git a/Src/subst.c b/Src/subst.c
index 37d63cabe..9b3699a47 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -579,7 +579,6 @@ filesubstr(char **namptr, int assign)
     char *str = *namptr;
 
     if (*str == Tilde && str[1] != '=' && str[1] != Equals) {
-	Shfunc dirfunc;
 	char *ptr, *tmp, *res, *ptr2;
 	int val;
 
@@ -594,12 +593,11 @@ filesubstr(char **namptr, int assign)
 	    *namptr = dyncat((tmp = oldpwd) ? tmp : pwd, str + 2);
 	    return 1;
 	} else if (str[1] == Inbrack &&
-		   (dirfunc = getshfunc("zsh_directory_name")) &&
 		   (ptr2 = strchr(str+2, Outbrack))) {
 	    char **arr;
 	    untokenize(tmp = dupstrpfx(str+2, ptr2 - (str+2)));
 	    remnulargs(tmp);
-	    arr = subst_string_by_func(dirfunc, "n", tmp);
+	    arr = subst_string_by_hook("zsh_directory_name", "n", tmp);
 	    res = arr ? *arr : NULL;
 	    if (res) {
 		*namptr = dyncat(res, ptr2+1);
diff --git a/Src/utils.c b/Src/utils.c
index 844a43e1b..9857303bb 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -890,7 +890,8 @@ finddir(char *s)
 {
     static struct nameddir homenode = { {NULL, "", 0}, NULL, 0 };
     static int ffsz;
-    Shfunc func = getshfunc("zsh_directory_name");
+    char **ares;
+    int len;
 
     /* Invalidate directory cache if argument is NULL.  This is called *
      * whenever a node is added to or removed from the hash table, and *
@@ -906,9 +907,16 @@ finddir(char *s)
 	return finddir_last = NULL;
     }
 
-    /* It's not safe to use the cache while we have function transformations.*/
-    if(!func && !strcmp(s, finddir_full) && *finddir_full)
+#if 0
+    /*
+     * It's not safe to use the cache while we have function
+     * transformations, and it's not clear it's worth the
+     * complexity of guessing here whether subst_string_by_hook
+     * is going to turn up the goods.
+     */
+    if (!strcmp(s, finddir_full) && *finddir_full)
 	return finddir_last;
+#endif
 
     if ((int)strlen(s) >= ffsz) {
 	free(finddir_full);
@@ -920,18 +928,15 @@ finddir(char *s)
     finddir_scan(&homenode.node, 0);
     scanhashtable(nameddirtab, 0, 0, 0, finddir_scan, 0);
 
-    if (func) {
-	char **ares = subst_string_by_func(func, "d", finddir_full);
-	int len;
-	if (ares && arrlen(ares) >= 2 &&
-	    (len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) {
-	    /* better duplicate this string since it's come from REPLY */
-	    finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir));
-	    finddir_last->node.nam = zhtricat("[", dupstring(ares[0]), "]");
-	    finddir_last->dir = dupstrpfx(finddir_full, len);
-	    finddir_last->diff = len - strlen(finddir_last->node.nam);
-	    finddir_best = len;
-	}
+    ares = subst_string_by_hook("zsh_directory_name", "d", finddir_full);
+    if (ares && arrlen(ares) >= 2 &&
+	(len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) {
+	/* better duplicate this string since it's come from REPLY */
+	finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir));
+	finddir_last->node.nam = zhtricat("[", dupstring(ares[0]), "]");
+	finddir_last->dir = dupstrpfx(finddir_full, len);
+	finddir_last->diff = len - strlen(finddir_last->node.nam);
+	finddir_best = len;
     }
 
     return finddir_last;
@@ -3212,7 +3217,7 @@ getshfunc(char *nam)
 char **
 subst_string_by_func(Shfunc func, char *arg1, char *orig)
 {
-    int osc = sfcontext;
+    int osc = sfcontext, osm = stopmsg;
     LinkList l = newlinklist();
     char **ret;
 
@@ -3228,6 +3233,47 @@ subst_string_by_func(Shfunc func, char *arg1, char *orig)
 	ret = getaparam("reply");
 
     sfcontext = osc;
+    stopmsg = osm;
+    return ret;
+}
+
+/**
+ * Front end to subst_string_by_func to use hook-like logic.
+ * name can refer to a function, and name + "_hook" can refer
+ * to an array containing a list of functions.  The functions
+ * are tried in order until one returns success.
+ */
+/**/
+char **
+subst_string_by_hook(char *name, char *arg1, char *orig)
+{
+    Shfunc func;
+    char **ret = NULL;
+
+    if ((func = getshfunc(name))) {
+	ret = subst_string_by_func(func, arg1, orig);
+    }
+
+    if (!ret) {
+	char **arrptr;
+	int namlen = strlen(name);
+	VARARR(char, arrnam, namlen + HOOK_SUFFIX_LEN);
+	memcpy(arrnam, name, namlen);
+	memcpy(arrnam + namlen, HOOK_SUFFIX, HOOK_SUFFIX_LEN);
+
+	if ((arrptr = getaparam(arrnam))) {
+	    /* Guard against internal modification of the array */
+	    arrptr = arrdup(arrptr);
+	    for (; *arrptr; arrptr++) {
+		if ((func = getshfunc(*arrptr))) {
+		    ret = subst_string_by_func(func, arg1, orig);
+		    if (ret)
+			break;
+		}
+	    }
+	}
+    }
+
     return ret;
 }