On Sun, 5 Jan 2014, Joe Mistachkin wrote:

> Sergei Gavrikov wrote:
> >
> > It seems this was introduced with Th_ExistsVar()
> >
> http://fossil-scm.org/index.html/artifact/a561c58c237b3eb43eaf55e6f9cc6a9b8a
> 26e5d1?ln=1154-1159
> > (check-in http://fossil-scm.org/index.html/info/4f8c8975bc). As I could
> > see Th_ExistsVar() does miss a test for pValue->zData as Th_GetVar() does
> >
> http://fossil-scm.org/index.html/artifact/a561c58c237b3eb43eaf55e6f9cc6a9b8a
> 26e5d1?ln=1142-1149.
> > Right? Could you, please, fix that?
> >
>
> Sergei Gavrikov also wrote:
> >
> > Th_UnsetVar() creates (creatok=1), then unset variable. So, unset never
> > raise an error. It is okay?
> >
>
> Thanks for the report(s).  Fixed here:
>
>       https://www.fossil-scm.org/index.html/info/7164f52baa
>
> And here:
>
>       https://www.fossil-scm.org/index.html/info/99bdfa0b95

Thank you for the fixes! I'm sorry, but, I found yet another issue with
Th_ExistsVar(). If a variable is not exists, Th_ExistsVar() does clear
TH stack trace:

  # Expect {foo}, but get nothing {}.
  "catch foo; info exists bar; set ::th_stack_trace"

Call path: Th_ExistsVar() -> thFindValue() -> Th_ErrorMessage() -> ...
    Th_SetVar(interp, (char *)"::th_stack_trace", -1, 0, 0);

Unfortunately, there is no way to fix this without changing an interface
function thFindVal(). As I could see thFindValue() cannot silent return
0 (not found, no care) it always calls Th_ErrorMeesage() on "fails".

I tested some workaround, it does not change default behavior and other
Th_*Var() are happy, please, look on a draft patch (original comments
have not been fixed). Could we expand 'arrayok' flag to a bitfield flag
or that is ugly thing?

Thank you for your time.

Sergei
Index: src/th.c
==================================================================
--- src/th.c
+++ src/th.c
@@ -1042,10 +1042,16 @@
   *pnInner = nInner;
   *pisGlobal = isGlobal;
   return TH_OK;
 }

+#define FV_ArrayOk        0x0001
+#define FV_NoError        0x8000
+
+#define FIND_ARRAYOK      0x0001
+#define FIND_NOERROR      0x8000
+
 /*
 ** Input string (zVar, nVar) contains a variable name. This function locates
 ** the Th_Variable structure associated with the named variable. The
 ** variable name may be a global or local scalar or array variable
 **
@@ -1060,11 +1066,11 @@
 static Th_Variable *thFindValue(
   Th_Interp *interp,
   const char *zVar,     /* Pointer to variable name */
   int nVar,              /* Number of bytes at nVar */
   int create,            /* If true, create the variable if not found */
-  int arrayok            /* If true, an array is Ok. Otherwise array==error */
+  int flags
 ){
   const char *zOuter;
   int nOuter;
   const char *zInner;
   int nInner;
@@ -1114,20 +1120,22 @@
       pValue = Th_Malloc(interp, sizeof(Th_Variable));
       pValue->nRef = 1;
       pEntry->pData = (void *)pValue;
     }
   }else{
-    if( pValue->pHash && !arrayok ){
+    if( pValue->pHash && (flags&FV_ArrayOk)!=FIND_ARRAYOK ){
       Th_ErrorMessage(interp, "variable is an array:", zOuter, nOuter);
       return 0;
     }
   }

   return pValue;

 no_such_var:
-  Th_ErrorMessage(interp, "no such variable:", zVar, nVar);
+  if( (flags&FV_NoError)!=FIND_NOERROR ){
+    Th_ErrorMessage(interp, "no such variable:", zVar, nVar);
+  }
   return 0;
 }

 /*
 ** String (zVar, nVar) must contain the name of a scalar variable or
@@ -1154,11 +1162,11 @@

 /*
 ** Return true if variable (zVar, nVar) exists.
 */
 int Th_ExistsVar(Th_Interp *interp, const char *zVar, int nVar){
-  Th_Variable *pValue = thFindValue(interp, zVar, nVar, 0, 0);
+  Th_Variable *pValue = thFindValue(interp, zVar, nVar, 0, FIND_NOERROR);
   return pValue && pValue->zData;
 }

 /*
 ** String (zVar, nVar) must contain the name of a scalar variable or

Index: test/th1.test
==================================================================
--- test/th1.test
+++ test/th1.test
@@ -132,10 +132,15 @@

 ###############################################################################

 fossil test-th-eval "set var 1; unset var; expr {\$var+0}"
 test th1-info-exists-5 {$RESULT eq {TH_ERROR: no such variable: var}}
+
+###############################################################################
+
+fossil test-th-eval "catch foo; info exists bar; set ::th_stack_trace"
+test th1-info-exists-6 {$RESULT eq {foo}}

 ###############################################################################

 fossil test-th-eval "set var 1; unset var"
 test th1-unset-1 {$RESULT eq {var}}

_______________________________________________
fossil-users mailing list
fossil-users@lists.fossil-scm.org
http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users

Reply via email to