Convert "isany" to short-circuit evaluation.

This commit is contained in:
Dianne Skoll
2024-06-07 15:55:12 -04:00
parent 4454613d00
commit 60ca5d45e3
2 changed files with 69 additions and 29 deletions

View File

@@ -60,6 +60,9 @@
#define RetVal (info->retval) #define RetVal (info->retval)
#define DBG(x) do { if (DebugFlag & DB_PRTEXPR) { x; } } while(0) #define DBG(x) do { if (DebugFlag & DB_PRTEXPR) { x; } } while(0)
/* Debugging helpers for "choose()", "iif(), etc. */
#define PUT(x) DBufPuts(&DebugBuf, x)
#define OUT() do { fprintf(ErrFp, "%s\n", DBufValue(&DebugBuf)); DBufFree(&DebugBuf); } while(0)
static int static int
solstice_equinox_for_year(int y, int which); solstice_equinox_for_year(int y, int which);
@@ -104,7 +107,7 @@ static int FHtmlEscape (func_info *);
static int FHtmlStriptags (func_info *); static int FHtmlStriptags (func_info *);
static int FIif (expr_node *, Value *, Value *, int *); static int FIif (expr_node *, Value *, Value *, int *);
static int FIndex (func_info *); static int FIndex (func_info *);
static int FIsAny (func_info *); static int FIsAny (expr_node *, Value *, Value *, int *);
static int FIsdst (func_info *); static int FIsdst (func_info *);
static int FIsleap (func_info *); static int FIsleap (func_info *);
static int FIsomitted (func_info *); static int FIsomitted (func_info *);
@@ -263,7 +266,7 @@ BuiltinFunc Func[] = {
{ "htmlstriptags",1, 1, 1, FHtmlStriptags, NULL }, { "htmlstriptags",1, 1, 1, FHtmlStriptags, NULL },
{ "iif", 1, NO_MAX, 1, NULL, FIif }, /*NEW-STYLE*/ { "iif", 1, NO_MAX, 1, NULL, FIif }, /*NEW-STYLE*/
{ "index", 2, 3, 1, FIndex, NULL }, { "index", 2, 3, 1, FIndex, NULL },
{ "isany", 1, NO_MAX, 1, FIsAny, NULL }, { "isany", 1, NO_MAX, 1, NULL, FIsAny }, /*NEW-STYLE*/
{ "isdst", 0, 2, 0, FIsdst, NULL }, { "isdst", 0, 2, 0, FIsdst, NULL },
{ "isleap", 1, 1, 1, FIsleap, NULL }, { "isleap", 1, 1, 1, FIsleap, NULL },
{ "isomitted", 1, 1, 0, FIsomitted, NULL }, { "isomitted", 1, 1, 0, FIsomitted, NULL },
@@ -376,10 +379,9 @@ static int RetStrVal(char const *s, func_info *info)
/***************************************************************/ /***************************************************************/
static int FStrlen(func_info *info) static int FStrlen(func_info *info)
{ {
Value *v = &ARG(0); ASSERT_TYPE(0, STR_TYPE);
if (v->type != STR_TYPE) return E_BAD_TYPE;
RetVal.type = INT_TYPE; RetVal.type = INT_TYPE;
size_t l = strlen(v->v.str); size_t l = strlen(ARGSTR(0));
if (l > INT_MAX) return E_2HIGH; if (l > INT_MAX) return E_2HIGH;
RETVAL = (int) l; RETVAL = (int) l;
return OK; return OK;
@@ -1034,8 +1036,8 @@ static int FOrd(func_info *info)
/* */ /* */
/* FPad - Pad a string to min length */ /* FPad - Pad a string to min length */
/* */ /* */
/* pad("1", "0", 4) --> "0004" */ /* pad("1", "0", 4) --> "0001" */
/* pad("1", "0", 4, 1) --> "4000" */ /* pad("1", "0", 4, 1) --> "1000" */
/* pad("foo", "bar", 7) -> "barbfoo" */ /* pad("foo", "bar", 7) -> "barbfoo" */
/* */ /* */
/***************************************************************/ /***************************************************************/
@@ -1159,32 +1161,70 @@ static int FPlural(func_info *info)
/* otherwise. */ /* otherwise. */
/* */ /* */
/***************************************************************/ /***************************************************************/
static int FIsAny(func_info *info) static int FIsAny(expr_node *node, Value *locals, Value *ans, int *nonconst)
{ {
int i; DynamicBuffer DebugBuf;
RetVal.type = INT_TYPE; expr_node *cur;
RETVAL = 0; int r;
for (i=1; i<Nargs; i++) {
if (ARG(0).type == ARG(i).type) { Value v;
if (ARG(0).type == STR_TYPE) { Value candidate;
if (!strcmp(ARGSTR(0), ARGSTR(i))) {
RETVAL = 1; ans->type = INT_TYPE;
return OK; ans->v.val = 0;
}
} else { DBG(DBufInit(&DebugBuf));
if (ARGV(0) == ARGV(i)) { DBG(PUT("isany("));
RETVAL = 1;
return OK; cur = node->child;
} r = evaluate_expr_node(cur, locals, &v, nonconst);
if (r != OK) {
DBG(DBufFree(&DebugBuf));
return r;
}
DBG(PUT(PrintValue(&v, NULL)));
while(cur->sibling) {
cur = cur->sibling;
r = evaluate_expr_node(cur, locals, &candidate, nonconst);
if (r != OK) {
DestroyValue(v);
DBG(DBufFree(&DebugBuf));
return r;
}
DBG(PUT(", "));
DBG(PUT(PrintValue(&candidate, NULL)));
if (candidate.type != v.type) {
DestroyValue(candidate);
continue;
}
if (v.type == STR_TYPE) {
if (strcmp(v.v.str, candidate.v.str)) {
DestroyValue(candidate);
continue;
}
} else {
if (v.v.val != candidate.v.val) {
DestroyValue(candidate);
continue;
} }
} }
DestroyValue(candidate);
ans->v.val = 1;
break;
}
DestroyValue(v);
if (DebugFlag & DB_PRTEXPR) {
while(cur->sibling) {
cur = cur->sibling;
PUT(", ?");
}
PUT(") => ");
PUT(PrintValue(ans, NULL));
OUT();
} }
return OK; return OK;
} }
/* Debugging helpers for "choose()" and "iif() */
#define PUT(x) DBufPuts(&DebugBuf, x)
#define OUT() do { fprintf(ErrFp, "%s\n", DBufValue(&DebugBuf)); DBufFree(&DebugBuf); } while(0)
/***************************************************************/ /***************************************************************/
/* */ /* */
/* FChoose */ /* FChoose */
@@ -1200,7 +1240,7 @@ static int FChoose(expr_node *node, Value *locals, Value *ans, int *nonconst)
int r; int r;
int n; int n;
int nargs = node->num_kids; int nargs = node->num_kids;
Value(v); Value v;
DBG(DBufInit(&DebugBuf)); DBG(DBufInit(&DebugBuf));
DBG(PUT("choose(")); DBG(PUT("choose("));

View File

@@ -3779,11 +3779,11 @@ isany("foo", 2) => 0
set a isany(1:00, 2) set a isany(1:00, 2)
isany(01:00, 2) => 0 isany(01:00, 2) => 0
set a isany(1, 2, 1, 3) set a isany(1, 2, 1, 3)
isany(1, 2, 1, 3) => 1 isany(1, 2, 1, ?) => 1
set a isany("foo", 2, 3, "foo") set a isany("foo", 2, 3, "foo")
isany("foo", 2, 3, "foo") => 1 isany("foo", 2, 3, "foo") => 1
set a isany(1:00, 2, "foo", 2:00, 1:00, 9:00) set a isany(1:00, 2, "foo", 2:00, 1:00, 9:00)
isany(01:00, 2, "foo", 02:00, 01:00, 09:00) => 1 isany(01:00, 2, "foo", 02:00, 01:00, ?) => 1
# Shellescape # Shellescape
set a shellescape(" !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~") set a shellescape(" !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")