* Bugs #9838,9839,10196 fixed: evstr(strarray) 2.3 x faster + more robust against... 33/19033/12
Samuel GOUGEON [Thu, 2 Feb 2017 21:49:35 +0000 (22:49 +0100)]
 * evstr() code improved:
   - 2.3x faster: bench_mark string bench_evstr
   - more consistent and resilient: when an instruction has a void or
     empty output, the answer is now always the same: a default value
     set accordingly with the type of the overall result.
   - ascii(10) and ascii(13) are now supported in both scalar or array inputs

 * test_run string   passes

 *  evstr("// component without output")  yielded an error:
    http://bugzilla.scilab.org/9838

 * evstr(["%pi" ascii(10) ; "3" "%i"]) yielded an error:
   http://bugzilla.scilab.org/9839
   Support to included ascii(10) and ascii(13) added.

 * http://bugzilla.scilab.org/10196 :
   //a)
   t = ["%pi" "[]" "%eps"]; r = evstr(t);
   "[]" shifted output components by 1 place: r(2) == evstr(t(3))
   // b)
   evstr("whereami()") yielded an error (because whereami() has no output)

Change-Id: I267229dce2a13de204af804409279bea0f477b74

scilab/CHANGES.md
scilab/modules/string/macros/evstr.sci
scilab/modules/string/tests/nonreg_tests/bug_10196.tst [new file with mode: 0644]
scilab/modules/string/tests/nonreg_tests/bug_9838.dia.ref [deleted file]
scilab/modules/string/tests/nonreg_tests/bug_9838.tst
scilab/modules/string/tests/nonreg_tests/bug_9839.tst [new file with mode: 0644]
scilab/modules/string/tests/unit_tests/evstr.dia.ref [deleted file]
scilab/modules/string/tests/unit_tests/evstr.tst

index 925cdce..8ee5d73 100644 (file)
@@ -224,6 +224,8 @@ bounds selected out of the axes areas is now restored, after the Scilab 5.4 regr
   - It can now be used for builtin functions.
   - When the same function name is registered in several libraries, `whereis` now returns all of them instead of only the last loaded one.
   - For unregistered user-defined macros, `"script"` is now returned instead of `[]`.
+* `evstr` now support inputs including `ascii(10)`, `ascii(13)`, only a comment or/and
+   spaces or/and `"[]"`, only spaces, being `""`, or instructions returning nothing.
 
 
 Help pages:
@@ -460,11 +462,14 @@ the [development mailing list](dev@lists.scilab.org) for a particular toolbox.
 * [#9288](http://bugzilla.scilab.org/show_bug.cgi?id=9288): No palette dynamically built with the most used blocks was available
 * [#9451](http://bugzilla.scilab.org/show_bug.cgi?id=9451): `test_run` output did not clearly distinguish heading lines of modules and tests lines
 * [#9825](http://bugzilla.scilab.org/show_bug.cgi?id=9825): `assert_computedigits` returns too much digits
+* [#9838](http://bugzilla.scilab.org/show_bug.cgi?id=9838):  `evstr` froze on text components having some comments but no result.
+* [#9839](http://bugzilla.scilab.org/show_bug.cgi?id=9839):  `evstr` failed when some text components include `ascii(10)` or/and `ascii(13)` linebreak characters.
 * [#9865](http://bugzilla.scilab.org/show_bug.cgi?id=9865): When making a plot with `point`(no line), no symbol was shown in the legend.
 * [#9876](http://bugzilla.scilab.org/show_bug.cgi?id=9876): Creating a complex structure with multiple hierarchy level and size failed.
 * [#9912](http://bugzilla.scilab.org/show_bug.cgi?id=9912): In case of missing translated help page, its default `en_US` version was sometimes ignored
 * [#10116](http://bugzilla.scilab.org/show_bug.cgi?id=10116): `for h = H, .., end` could not be used when H is a vector of graphic handles
 * [#10195](http://bugzilla.scilab.org/show_bug.cgi?id=10195): `execstr` interpreted ascii(0) to ascii(31) characters as the power `^` operator.
+* [#10196](http://bugzilla.scilab.org/show_bug.cgi?id=10196): a) `evstr("whereami()")` yielded an error (instead of []) because `whereami()` has no output argument. b) `evstr(["%pi" "[]" "%i"])` returned a vector with only 2 components instead of 3. c) `evstr(["%pi" "[]" ; "3" "%i"])` yielded an error.
 * [#10326](http://bugzilla.scilab.org/show_bug.cgi?id=10326): The palette browser didn't have any search engine.
 * [#10981](http://bugzilla.scilab.org/show_bug.cgi?id=10981): It was possible to rotate a 2D axes, and hard to get it back to a 2D view.
 * [#11375](http://bugzilla.scilab.org/show_bug.cgi?id=11375): When a localized help subdirectory has only a `CHAPTER` file specifying the section title, this one was ignored.
index 5f801af..7395445 100644 (file)
@@ -1,6 +1,7 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) INRIA
 // Copyright (C) DIGITEO - 2010 - Allan CORNET
+// Copyright (C) 2017 - Samuel GOUGEON
 //
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
 //
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
-
 function [%val, %ierr] = evstr(%str)
+// HELP:
+// * assignment forbidden
+// * If a vector or matrix of strings is provided:
+//   A single instruction per cell: no "," or ";" instruction separator
 
     [lhs, rhs] = argn(0);
     %val = [];
-    select type(%str)
+    %ierr =  0;
 
+    select type(%str)
     case 10 then
         // matrix of character strings
         if isempty(%str) then
-            %val = [];
-            %ierr =  0;
-            return;
+            return
         end
 
         // bug 7003
-        if ~isdef("Nan") then
-            Nan = %nan;
-        end
-        if ~isdef("NaN") then
-            NaN = %nan;
+        vars = ["Nan"  "NaN"  "Inf"  "INF"]
+        vals = ["%nan" "%nan" "%inf" "%inf"]
+        tmp = ~isdef(vars)
+        if tmp~=[]
+            execstr(vars(tmp)+"="+vals(tmp))
         end
 
-        if ~isdef("Inf") then
-            Inf = %inf;
+        // Bug 9839: support to included ascii(10) or ascii(13) characters:
+        //  If the input is scalar: we replace them with ";"
+        //  Otherwise:
+        //    For every component including some ascii(10) or ascii(13),
+        //    we replace the component with only its head up to the first ascii(10)
+        //    or ascii(13) met (excluded).
+        if size(%str,"*")==1
+            %str = strsubst(%str, ascii(10), ";");
+            %str = strsubst(%str, ascii(13), ";");
+        else
+            tmp = grep(%str, [ascii(10) ascii(13)]);
+            if tmp~=[]
+                tmp2 = strcspn(%str(tmp), ascii(10)+ascii(13));
+                %str(tmp) = strncpy(%str(tmp), tmp2);
+            end
         end
 
-        if ~isdef("INF") then
-            INF = %inf;
+        // Bug 10196.b: only one component with an instruction returning nothing => [] returned
+        serialized_input = %f
+        if size(%str,"*")==1
+            %ierr = execstr("%val=["+%str(1)+"]", "errcatch");
+            if %ierr~=0
+                %val = []
+                return
+            end
+            if or(type(%val)==[11 13])
+                return
+            end
+            serialized_input = size(%val,"*")>1
         end
 
-        %t1 = strcat(%str, ",", "c")+";"
-        %t1(1) = "%val=[" + %t1(1);
-        %t1($) = part(%t1($), 1:length(%t1($)) - 1)+";";
-        %t1($+1)="]";
-        if lhs == 2 then
-            %ierr = execstr(%t1, "errcatch");
+        // input strings with possible "," and ";" separators
+        // or column of strings with possible "," and ending ";"
+        // -----------------------------------------------------
+        if serialized_input | ..
+           grep(%str(1),"/^\s*\[/","r")~=[] & grep(%str($),"/\]\s*/","r")~=[]
+            %t1 = strcat(%str, ",", "c") + ";"
+            %t1(1) = "%val=[" + %t1(1);
+            %t1($) = part(%t1($), 1:length(%t1($)) - 1)+";";
+            %t1($+1)="]";
+            if lhs == 2 then
+                %ierr = execstr(%t1, "errcatch");
+            else
+                execstr(%t1)
+            end
+
+        // We assume: one %str component = only one instruction
+        // ----------------------------------------------------
         else
-            execstr(%t1)
+            // Bugs 9838 & 10196.a:
+            // Are considered as empty instructions
+            //  - a blank or empty string
+            //  - a string containing only "[ ]" and blanks
+            //  - a string starting with possible spaces + "//" being a comment
+            //  - a string like "  [ ]  // bla bla "
+            // If at least one component is detected to be so, then
+            //  * its evaluation returning nothing will be replaced with the "neutral" default,
+            //    that depends on the overall result type.
+            //  * So we search this type: it is the type returend by the evaluation of first
+            //    non-empty component
+            //  * We set the default: "" for texts, %nan for decimal and complex numbers, etc
+            void = grep(%str, "/^(\s*\[\s*\]\s*|\s*|\s*\/\/.*|\s*\[\s*\]\s*\/\/.*)$/", "r")
+
+            if void~=[]
+                // The default replacement depends on the type of the output
+                // It is set by the first expected valid output:
+                tmp = setdiff(1:size(%str,"*"), void) // indices of valid expressions
+                if tmp~=[]
+                    execstr("tmp = "+%str(tmp(1))) // We get the result of the first one
+                else  // none not-empty valid output is expected
+                    return
+                end
+            else
+                execstr("tmp = "+%str(1)) // result of the first component
+            end
+            // We test its type to set the default result according to its type:
+            if or(type(tmp)==[1 2 5])
+                default = "%nan"
+            elseif type(tmp)==4
+                default = "%F"
+            elseif type(tmp)==10
+                default = """"""
+            elseif type(tmp)==8
+                default = typeof(tmp)+"(0)"
+            elseif type(tmp)==9
+                default = "gdf()"
+            elseif or(type(tmp)==[11 13])
+                deff("voidF()","")  // Does not survive when leaving evstr(). Never mind
+                default = "voidF"
+            end
+            // Substitution void => default
+            if void~=[] then
+                %str(void) = default
+            end
+
+            if or(type(tmp)==[1 2 4 8 9 10])    // matrix() supported
+                // We optimize the matrix size:
+                // The closer to a square matrix the faster is execstr()
+                S = size(%str)
+                s = size(%str,"*")
+                n = ceil(sqrt(s))
+                %str = [%str(:) ; repmat(default, n*n-s,1)]
+                %str = matrix(%str, n, n);
+            end
+            %t1 = strcat(%str, ",", "c") + ";"
+            %t1(1) = "%val=[" + %t1(1);
+            %t1($) = part(%t1($), 1:length(%t1($)) - 1)+";";
+            %t1($+1)="]";
+            if lhs == 2 then
+                %ierr = execstr(%t1, "errcatch");
+            else
+                execstr(%t1)
+            end
+            if or(type(tmp)==[1 2 4 8 9 10])    // Reshaping the result
+                %val = matrix(%val(1:s), S)
+            end
         end
 
     case 15 then
@@ -79,9 +182,12 @@ function [%val, %ierr] = evstr(%str)
         %val = %str;
         %ierr = 0;
     else
-        error(msprintf(gettext("%s: Wrong type for input argument #%d: Real or Complex matrix, Matrix of character strings or list expected.\n"), "evstr", 1));
+        msg = _("%s: Wrong type for input argument #%d: Real or Complex matrix, Matrix of character strings or list expected.\n")
+        error(msprintf(msg, "evstr", 1));
     end
     if exists("%val", "local") == 0 then
-        error(msprintf(gettext("%s: Given expression has no value.\n"), "evstr"));
+        msg = _("%s: Given expression has no value.\n")
+        error(msprintf(msg, "evstr"));
     end
 endfunction
+
diff --git a/scilab/modules/string/tests/nonreg_tests/bug_10196.tst b/scilab/modules/string/tests/nonreg_tests/bug_10196.tst
new file mode 100644 (file)
index 0000000..e75ee84
--- /dev/null
@@ -0,0 +1,58 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2017 - Samuel GOUGEON
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 10196 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/10196
+//
+// <-- Short Description -->
+// evstr(s):
+//  a) when s is scalar and its result is void, an error occured
+//  b) when s is a vector and one of its components is void or empty, this one
+//     was not returned and next components were shifted.
+//  c) when s is a matrix and one of its components is void or empty,
+//     an error occured
+
+assert_checkequal(execstr("evstr(""rand()"")", "errcatch"),0); // normal
+assert_checkequal(evstr("1 2"), [1 2]);                        // normal
+assert_checkequal(evstr("1;2"), [1; 2]);                       // normal
+assert_checktrue(execstr("evstr(''whereami()'')", "errcatch") == 0); // debugged
+assert_checkequal(evstr("whereami()"), []);     // debugged
+
+//
+assert_checkequal(evstr(["%pi" "[]"   "%i" "%eps"]), [%pi %nan   %i %eps]);
+assert_checkequal(evstr(["%pi" "[]" ; "%i" "%eps"]), [%pi %nan ; %i %eps]);
+assert_checkequal(evstr(["%t" "[]"   "%f" "%T"]), [%t %f   %f %t]);
+assert_checkequal(evstr(["%t" "[]" ; "%f" "%T"]), [%t %f ; %f %t]);
+assert_checkequal(evstr(["""A""" "[]"   """B""" """C"""]), ["A" ""   "B" "C"]);
+assert_checkequal(evstr(["""A""" "[]" ; """B""" """C"""]), ["A" "" ; "B" "C"]);
+t = ["int8(3)" "[]" ; "int8(4)" "int8(5)"];
+assert_checkequal(evstr(t(:)'), int8([3 4 0 5]));
+assert_checkequal(evstr(t),    int8([3 0 ; 4 5]));
+
+assert_checkequal(evstr(["%pi" ""   "%i" "%eps"]), [%pi %nan   %i %eps]);
+assert_checkequal(evstr(["%pi" "" ; "%i" "%eps"]), [%pi %nan ; %i %eps]);
+assert_checkequal(evstr(["%t"  ""    "%f" "%T"]),  [%t %f   %f %t]);
+assert_checkequal(evstr(["%t"  ""   ; "%f" "%T"]), [%t %f ; %f %t]);
+assert_checkequal(evstr(["""A""" ""   """B""" """C"""]), ["A" ""   "B" "C"]);
+assert_checkequal(evstr(["""A""" "" ; """B""" """C"""]), ["A" "" ; "B" "C"]);
+t = ["int8(3)" "" ; "int8(4)" "int8(5)"];
+assert_checkequal(evstr(t(:)'), int8([3 4 0 5]));
+assert_checkequal(evstr(t),    int8([3 0 ; 4 5]));
+
+assert_checkequal(evstr(["%pi" " // nothing"   "%i" "%eps"]), [%pi %nan   %i %eps]);
+assert_checkequal(evstr(["%pi" " // nothing" ; "%i" "%eps"]), [%pi %nan ; %i %eps]);
+assert_checkequal(evstr(["%t"  " // nothing"    "%f" "%T"]),  [%t %f   %f %t]);
+assert_checkequal(evstr(["%t"  " // nothing"   ; "%f" "%T"]), [%t %f ; %f %t]);
+assert_checkequal(evstr(["""A""" " // nothing"   """B""" """C"""]), ["A" ""   "B" "C"]);
+assert_checkequal(evstr(["""A""" " // nothing" ; """B""" """C"""]), ["A" "" ; "B" "C"]);
+t = ["int8(3)" " // nothing" ; "int8(4)" "int8(5)"];
+assert_checkequal(evstr(t(:)'), int8([3 4 0 5]));
+assert_checkequal(evstr(t),    int8([3 0 ; 4 5]));
diff --git a/scilab/modules/string/tests/nonreg_tests/bug_9838.dia.ref b/scilab/modules/string/tests/nonreg_tests/bug_9838.dia.ref
deleted file mode 100644 (file)
index 869b325..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) 2011 - INRIA - Serge Steer
-//
-//  This file is distributed under the same license as the Scilab package.
-// =============================================================================
-// <-- CLI SHELL MODE -->
-//
-// <-- Non-regression test for bug 9838 -->
-//
-// <-- Bugzilla URL -->
-// http://bugzilla.scilab.org/show_bug.cgi?id=9838
-//
-// <-- Short Description -->
-// evstr freezes on some specific string
-//
-assert_checkequal(evstr('//xxx'),[]);
-t=["1";
-   "2";
-   "//xxx"];
-assert_checkequal(evstr(t),[1;2]);
index 1ad3a39..6f1d318 100644 (file)
@@ -1,21 +1,34 @@
 // =============================================================================
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) 2011 - INRIA - Serge Steer
+// Copyright (C) 2017 - Samuel GOUGEON
 //
 //  This file is distributed under the same license as the Scilab package.
 // =============================================================================
 // <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
 //
 // <-- Non-regression test for bug 9838 -->
 //
 // <-- Bugzilla URL -->
-// http://bugzilla.scilab.org/show_bug.cgi?id=9838
+// http://bugzilla.scilab.org/9838
 //
 // <-- Short Description -->
-// evstr freezes on some specific string
+// evstr() froze on text components having some comments but no result
 //
-assert_checkequal(evstr('//xxx'),[]);
-t=["1";
-   "2";
-   "//xxx"];
-assert_checkequal(evstr(t),[1;2]); 
+ni = "// no instruction";
+assert_checkequal(evstr(ni),[]);
+assert_checkequal(evstr([ni ni]),[]);
+assert_checkequal(evstr([ni ni]'),[]);
+t = [ni, " "+ni, "[] "+ni, "[] "+ni, " [] "+ni];
+assert_checkequal(evstr(t), []);
+t = [ t "3"];
+assert_checkequal(evstr(t),  [%nan %nan %nan %nan %nan 3]);
+assert_checkequal(evstr(t'), [%nan %nan %nan %nan %nan 3]');
+t($) = "%t";
+assert_checkequal(evstr(t),[%f %f %f %f %f %t]);
+t($) = """AbCd""";
+assert_checkequal(evstr(t),["" "" "" "" "" "AbCd"]);
+t($) = "int8(37)";
+assert_checkequal(evstr(t),int8([0 0 0 0 0 37]));
+
diff --git a/scilab/modules/string/tests/nonreg_tests/bug_9839.tst b/scilab/modules/string/tests/nonreg_tests/bug_9839.tst
new file mode 100644 (file)
index 0000000..ccb63a0
--- /dev/null
@@ -0,0 +1,35 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2017 - Samuel GOUGEON
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 9839 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/9839
+//
+// <-- Short Description -->
+// evstr() failed when some components include ascii(10) or/and ascii(13) 
+//         linebreak characters
+
+a10 = ascii(10);
+assert_checkequal(evstr(a10+"4"), []);
+assert_checkequal(evstr([a10+"4" "5"]), [%nan 5]);
+assert_checkequal(evstr([a10+"4" ; "5"]), [%nan ; 5]);
+assert_checkequal(evstr(["3"+a10+"4" "5"]), [3 5]);
+assert_checkequal(evstr(["3"+a10+"4" ; "5"]), [3 ; 5]);
+assert_checkequal(evstr(["%i"+a10+"4" "5"]), [%i 5]);
+assert_checkequal(evstr(["%i"+a10+"4" ; "5"]), [%i ; 5]);
+
+a13 = ascii(13);
+assert_checkequal(evstr(a13+"4"), []);
+assert_checkequal(evstr([a13+"4" "5"]), [%nan 5]);
+assert_checkequal(evstr([a13+"4" ; "5"]), [%nan ; 5]);
+assert_checkequal(evstr(["3"+a13+"4" "5"]), [3 5]);
+assert_checkequal(evstr(["3"+a13+"4" ; "5"]), [3 ; 5]);
+assert_checkequal(evstr(["%i"+a13+"4" "5"]), [%i 5]);
+assert_checkequal(evstr(["%i"+a13+"4" ; "5"]), [%i ; 5]);
diff --git a/scilab/modules/string/tests/unit_tests/evstr.dia.ref b/scilab/modules/string/tests/unit_tests/evstr.dia.ref
deleted file mode 100644 (file)
index f78dece..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) 2010 - DIGITEO - Allan CORNET
-//
-//  This file is distributed under the same license as the Scilab package.
-// =============================================================================
-//
-// <-- CLI SHELL MODE -->
-//
-// =============================================================================
-// unit tests evstr
-// =============================================================================
-a = 1;
-b = 2;
-Z = ["a","b"];
-res = evstr(Z);
-assert_checkequal(res(1), a);
-assert_checkequal(res(2), b);
-// =============================================================================
-a = 1;
-b = 2;
-Z = list(["%(1)","%(1)-%(2)"], ["a+1","b+1"]);
-res = evstr(Z);
-assert_checkequal(res, [2 -1]);
-// =============================================================================
-assert_checktrue(isnan(evstr(%nan)));
-assert_checktrue(isinf(evstr(%inf)));
-assert_checktrue(isnan(evstr("%nan")));
-assert_checktrue(isinf(evstr("%inf")));
-assert_checktrue(isnan(evstr("Nan")));
-assert_checktrue(isinf(evstr("Inf")));
-assert_checktrue(isnan(evstr("NaN")));
-assert_checktrue(isinf(evstr(-%inf)));
-assert_checktrue(isinf(evstr("-%inf")));
-assert_checktrue(isinf(evstr("-Inf")));
-// =============================================================================
-Scilab_value = 3;
-assert_checkequal(Scilab_value, evstr("Scilab_value"));
-// =============================================================================
-clear toto;
-assert_checkfalse(execstr("evstr(''toto'')", "errcatch") == 0);
-assert_checkfalse(execstr("evstr(toto)", "errcatch") == 0);
-// =============================================================================
-s = rand(3,3,3);
-assert_checkequal(execstr("evstr(s)", "errcatch"), 0);
-// =============================================================================
-function foo(), endfunction
-assert_checkequal(execstr("evstr(''foo'')", "errcatch"), 0);
-// =============================================================================
-assert_checkequal(evstr(""), []);
-// =============================================================================
index f78dece..e44d051 100644 (file)
@@ -6,6 +6,7 @@
 // =============================================================================
 //
 // <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
 //
 // =============================================================================
 // unit tests evstr
@@ -16,6 +17,9 @@ Z = ["a","b"];
 res = evstr(Z);
 assert_checkequal(res(1), a);
 assert_checkequal(res(2), b);
+assert_checkequal(evstr("cos(a)"), cos(a));
+assert_checkequal(evstr("cos(a), sin(a)"), [cos(a), sin(a)]);
+assert_checkequal(evstr("cos(a); sin(a)"), [cos(a); sin(a)]);
 // =============================================================================
 a = 1;
 b = 2;
@@ -38,7 +42,7 @@ Scilab_value = 3;
 assert_checkequal(Scilab_value, evstr("Scilab_value"));
 // =============================================================================
 clear toto;
-assert_checkfalse(execstr("evstr(''toto'')", "errcatch") == 0);
+assert_checkequal(evstr('toto'),[]);
 assert_checkfalse(execstr("evstr(toto)", "errcatch") == 0);
 // =============================================================================
 s = rand(3,3,3);
@@ -46,6 +50,8 @@ assert_checkequal(execstr("evstr(s)", "errcatch"), 0);
 // =============================================================================
 function foo(), endfunction
 assert_checkequal(execstr("evstr(''foo'')", "errcatch"), 0);
+// assert_checkequal(evstr('foo'), foo); // assert_checkequal() upgrade needed
+assert_checkequal(evstr('foo()'), []);
 // =============================================================================
 assert_checkequal(evstr(""), []);
 // =============================================================================