about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2015-01-26 18:10:39 +0000
committerPeter Stephenson <pws@zsh.org>2015-01-26 18:10:39 +0000
commit513662859905e132d29bb82ba4fe5c1ea8de0a44 (patch)
tree45c2a2a23cc0e6f9fb9d940ada63d7e253420f82 /Src
parent494c251cb0b0af70ac940b42df1d6c9940e469c8 (diff)
downloadzsh-513662859905e132d29bb82ba4fe5c1ea8de0a44.tar.gz
zsh-513662859905e132d29bb82ba4fe5c1ea8de0a44.tar.xz
zsh-513662859905e132d29bb82ba4fe5c1ea8de0a44.zip
Unsetting gdbm tied variable basically works.
Allows variables in nested scope.

However, explicitly untying a variable doesn't properly expose
the scope above.
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/db_gdbm.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index f079094c0..d75af980b 100644
--- a/Src/Modules/db_gdbm.c
+++ b/Src/Modules/db_gdbm.c
@@ -43,6 +43,9 @@ static char *backtype = "db/gdbm";
 
 static const struct gsu_scalar gdbm_gsu =
 { gdbmgetfn, gdbmsetfn, gdbmunsetfn };
+/**/
+static const struct gsu_hash gdbm_hash_gsu =
+{ hashgetfn, hashsetfn, gdbmhashunsetfn };
 
 static struct builtin bintab[] = {
     BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:", NULL),
@@ -84,12 +87,14 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
 	return 1;
     }
 
-    if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys, 0))) {
+    if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys,
+					 PM_REMOVABLE))) {
         zwarnnam(nam, "cannot create the requested parameter %s", pmname);
 	gdbm_close(dbf);
 	return 1;
     }
 
+    tied_param->gsu.h = &gdbm_hash_gsu;
     tied_param->u.hash->tmpdata = (void *)dbf;
 
     return 0;
@@ -225,6 +230,25 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags)
 
 }
 
+/**/
+static void
+gdbmhashunsetfn(Param pm, UNUSED(int exp))
+{
+    GDBM_FILE dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
+
+    if (!dbf) /* paranoia */
+	return;
+
+    gdbm_close(dbf);
+    pm->u.hash->tmpdata = NULL;
+
+    /* hash table is now normal, so proceed normally... */
+    pm->node.flags &= ~PM_SPECIAL;
+    pm->gsu.h = &stdhash_gsu;
+    pm->gsu.h->setfn(pm, NULL);
+    pm->node.flags |= PM_UNSET;
+}
+
 #else
 # error no gdbm
 #endif /* have gdbm */