Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[PATCH] Adapt gdbm code to named references



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.
}

Adapt gdbm code to named references

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