Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] Adapt gdbm code to named references
- X-seq: zsh-workers 54482
- From: Philippe Altherr <philippe.altherr@xxxxxxxxx>
- To: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: [PATCH] Adapt gdbm code to named references
- Date: Wed, 6 May 2026 15:09:21 +0200
- Arc-authentication-results: i=1; mx.google.com; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:mime-version:dkim-signature; bh=xh5gTrMGQ+gqR9DoQ1CQccu2Xr7D8k94Zj6I1jN1La0=; fh=BgAYDYpL6Ne/A5nWEMVJiHiBtrz8Imz3uf26RDwgQX4=; b=cngH3Omo7krvscQJRlyEJaEW4gExoUB0iHAlFBzegMisK+B26DUWhOFers8RE21GOF 8Xt8DoOkRrngTU3y5tI9UwcDY8uJhrkReAWOnnQe0xRJCjt3kqf3Ei1BIoYSz36nBebx uRu/AsXvTwLtIWgRVGI7IkAnk3IUO8tR0vh+YqjdYHMU0HvoSPdU1X5GbGmr9UfdPf9s becWmrtKQTrbD5f0v9nEQzYzfhxqtiaiH8d+TlUsDSUpWBbTwY4RzM0MDcxxPsDPd2gS xu2+p2JLqYzb0pM0irOQYh0rPxk3raLcTfFLwOmKpzvTiF+W+d4hmxXsvo4AddxKClFd 9vqA==; darn=zsh.org
- Arc-seal: i=1; a=rsa-sha256; t=1778072974; cv=none; d=google.com; s=arc-20240605; b=WG1oRyL+OMiB4+urqOa5jcWSQwWfAm6uqVIEkACyPN6o+ly7ha3Shs0w6UhMT5AF4z egUYhpk1IpglNrtBZL0DXonRB81dUdmgmr8rru+vsHNoycRyfh9PAYRyWNz9kcW5qQSK +qZBHJlm1b2pdHutM+PYIszRwa26l6UwHArdi5wE5oDnWzphx33j97Dlspy/dswAIvvk wMWeZBmDM1DU/zMdi97+ZsoHElHYdZQPvs868Rqb1/+WC7i6NXJKJoi36Uq2H+zpnso5 Fw7pgiu4esr2YkaHhs5pkx8JsuokEBrA60tDM4CGuJAty21l1dfOPp47hpp1GUWJSoB4 MnBw==
- Archived-at: <https://zsh.org/workers/54482>
- List-id: <zsh-workers.zsh.org>
The patch below makes the gdbm code compatible with named references. If a named reference is given to ztie, it will tie the DB to the referred variable. This is similar to what typeset does (when invoked without -n). An alternative would be to ignore named references and always tie the DB to the given variable. I chose the current approach because of its similarity with what typeset does but I don't have a strong preference.
The patch slightly changes the scope of DBs tied to local parameters. The scope of such DBs used to be the scope in which ztie was invoked. The way this was implemented is not compatible with named references (when they refer to a hidden variable). With the patch, the scope of the DB becomes the scope of the local parameter, which arguably is also
what the current documentation suggests.
() { local dbase
() {
ztie -d db/gdbm -f sample.gdbm dbase
# …
# The DB used to be untied here, at the end of the scope in which ztie was called.
}
# …
# The DB is now untied here, at the end of the scope in which its variable was declared.
}
The patch also contains a few code cleanups. See the GitHub commits for more details.
Philippe
diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index 34f577e30..2625469e4 100644
--- a/Src/Modules/db_gdbm.c
+++ b/Src/Modules/db_gdbm.c
@@ -38,12 +38,6 @@
#define PM_UPTODATE PM_DONTIMPORT_SUID /* Safe PM_ bit to re-use */
#endif
-static Param createhash( char *name, int flags );
-static int append_tied_name( const char *name );
-static int remove_tied_name( const char *name );
-static char *unmetafy_zalloc(const char *to_copy, int *new_len);
-static void myfreeparamnode(HashNode hn);
-
static int no_database_action = 0;
/*
@@ -139,7 +133,7 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
resource_name = OPT_ARG(ops, 'f');
pmname = *args;
- if ((tied_param = (Param)paramtab->getnode(paramtab, pmname)) &&
+ if ((tied_param = (Param)realparamtab->getnode(realparamtab, pmname)) &&
!(tied_param->node.flags & PM_UNSET)) {
/*
* Unset any existing parameter. Note there's no implicit
@@ -165,7 +159,7 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
return 1;
}
- if (!(tied_param = createhash(pmname, pmflags))) {
+ if (!(tied_param = creategdbmhash(pmname, pmflags))) {
zwarnnam(nam, "cannot create the requested parameter %s", pmname);
gdbm_close(dbf);
return 1;
@@ -191,7 +185,7 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
dbf_carrier->dbfile_path = ztrdup(resource_name);
addmodulefd(gdbm_fdesc(dbf), FDT_INTERNAL);
- append_tied_name(pmname);
+ append_tied_name(tied_param->node.nam);
return 0;
}
@@ -205,7 +199,7 @@ bin_zuntie(char *nam, char **args, Options ops, UNUSED(int func))
int ret = 0;
for (pmname = *args; *args++; pmname = *args) {
- pm = (Param) paramtab->getnode(paramtab, pmname);
+ pm = (Param) realparamtab->getnode(realparamtab, pmname);
if(!pm) {
zwarnnam(nam, "cannot untie %s", pmname);
ret = 1;
@@ -245,7 +239,7 @@ bin_zgdbmpath(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
return 1;
}
- pm = (Param) paramtab->getnode(paramtab, pmname);
+ pm = (Param) realparamtab->getnode(realparamtab, pmname);
if(!pm) {
zwarnnam(nam, "no such parameter: %s", pmname);
return 1;
@@ -657,7 +651,8 @@ finish_(UNUSED(Module m))
* Utility functions *
*********************/
-static Param createhash( char *name, int flags ) {
+/**/
+static Param creategdbmhash( char *name, int flags ) {
Param pm;
HashTable ht;
@@ -666,20 +661,11 @@ static Param createhash( char *name, int flags ) {
return NULL;
}
- if (pm->old)
- pm->level = locallevel;
-
/* This creates standard hash. */
ht = pm->u.hash = newparamtable(17, name);
- if (!pm->u.hash) {
- paramtab->removenode(paramtab, name);
- paramtab->freenode(&pm->node);
- zwarnnam(name, "out of memory when allocating hash");
- return NULL;
- }
/* Does free Param (unsetfn is called) */
- ht->freenode = myfreeparamnode;
+ ht->freenode = freegdbmnode;
/* These provide special features */
ht->getnode = ht->getnode2 = getgdbmnode;
@@ -692,6 +678,7 @@ static Param createhash( char *name, int flags ) {
* Adds parameter name to `zgdbm_tied`
*/
+/**/
static int append_tied_name( const char *name ) {
int old_len = arrlen(zgdbm_tied);
char **new_zgdbm_tied = zshcalloc( (old_len+2) * sizeof(char *));
@@ -717,6 +704,7 @@ static int append_tied_name( const char *name ) {
* Removes parameter name from `zgdbm_tied`
*/
+/**/
static int remove_tied_name( const char *name ) {
int old_len = arrlen(zgdbm_tied);
int new_len;
@@ -772,6 +760,8 @@ static int remove_tied_name( const char *name ) {
* - does zalloc of exact size for the new string,
* - restores work buffer to original content, to restore strlen
*/
+
+/**/
static char *
unmetafy_zalloc(const char *to_copy, int *new_len) {
char *work, *to_return;
@@ -795,8 +785,9 @@ unmetafy_zalloc(const char *to_copy, int *new_len) {
return to_return;
}
+/**/
static void
-myfreeparamnode(HashNode hn)
+freegdbmnode(HashNode hn)
{
Param pm = (Param) hn;
diff --git a/Test/V11db_gdbm.ztst b/Test/V11db_gdbm.ztst
index 6d74cef2c..1ac9fc0c2 100644
--- a/Test/V11db_gdbm.ztst
+++ b/Test/V11db_gdbm.ztst
@@ -204,34 +204,67 @@
local -a dbase
dbase=( fromarray )
() {
- local -a dbase
+ local dbase
+ () {
ztie -d db/gdbm -f $dbfile dbase
- echo ${(t)dbase}
- zuntie dbase
+ echo "Connected:" $dbase[a]
+ }
+ echo "Still connected:" $dbase[a]
}
echo $dbase[1]
ztie -d db/gdbm -f $dbfile dbase2
echo "Can connect, so untie happened:" $dbase2[a]
zuntie dbase2
0:Test of automatic untie (use of local scope) and of scoping
->association-local-special
+>Connected: b
+>Still connected: b
>fromarray
>Can connect, so untie happened: b
+ local dbase
+ () {
+ local -n rbase=dbase
+ local dbase=not-a-dbase
+ ztie -d db/gdbm -f $dbfile rbase
+ echo $dbase
+ echo "Connected:" $rbase[a]
+ zuntie rbase
+ echo "Disconnected:" $rbase[a]
+ ztie -d db/gdbm -f $dbfile rbase
+ echo "Reconnected:" $rbase[a]
+ echo $dbase
+ }
+ echo "Still connected:" $dbase[a]
+ zuntie dbase
+0:Test of tie to hidden local via named reference
+>not-a-dbase
+>Connected: b
+>Disconnected:
+>Reconnected: b
+>not-a-dbase
+>Still connected: b
+
echo $zgdbm_tied ${#zgdbm_tied}
ztie -r -d db/gdbm -f $dbfile dbase
echo $zgdbm_tied ${#zgdbm_tied}
ztie -d db/gdbm -f ${dbfile}2 dbase2
echo $zgdbm_tied ${#zgdbm_tied}
+ local -n rbase3=dbase3
+ ztie -d db/gdbm -f ${dbfile}3 rbase3
+ echo $zgdbm_tied ${#zgdbm_tied}
zuntie -u dbase
echo $zgdbm_tied ${#zgdbm_tied}
zuntie dbase2
echo $zgdbm_tied ${#zgdbm_tied}
+ zuntie rbase3
+ echo $zgdbm_tied ${#zgdbm_tied}
0:zgdbm_tied parameter
>0
>dbase 1
>dbase dbase2 2
->dbase2 1
+>dbase dbase2 dbase3 3
+>dbase2 dbase3 2
+>dbase3 1
>0
unset zgdbm_tied 2>/dev/null
@@ -311,8 +344,14 @@
zgdbmpath dbase
[[ $REPLY = */Test/db.gdbm ]] && echo correct
zuntie -u dbase
+ local -n rbase=dbase
+ ztie -r -d db/gdbm -f $dbfile rbase
+ zgdbmpath rbase
+ [[ $REPLY = */Test/db.gdbm ]] && echo correct
+ zuntie -u rbase
0:zgdbmpath builtin
>correct
+>correct
>correct
ztie -d db/gdbm -f $dbfile dbase
Messages sorted by:
Reverse Date,
Date,
Thread,
Author