r9600: fixed the intermittent failures we were getting with ejs in the build
[sfrench/samba-autobuild/.git] / source / lib / appweb / ejs / ejsParser.c
index 452e7fde8f376b671fbf6c8b19470181c3c740dc..da7b544c90b89d95e03c9c99071c9bac17fd42bf 100644 (file)
@@ -48,6 +48,7 @@ static int            evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs);
 static int             evalFloatExpr(Ejs *ep, double l, int rel, double r);
 #endif 
 static int             evalBoolExpr(Ejs *ep, bool l, int rel, bool r);
+static int             evalPtrExpr(Ejs *ep, void *l, int rel, void *r);
 static int             evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r);
 static int             evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs);
 static int             evalFunction(Ejs *ep, MprVar *obj, int flags);
@@ -230,7 +231,7 @@ static int parseStmt(Ejs *ep, int state, int flags)
 
 #if BLD_DEBUG
                        fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, fullNameLen,
-                               0, ".", 0);
+                               0, ".", NULL);
 #endif
 
                        ep->currentProperty = vp;
@@ -266,7 +267,7 @@ static int parseStmt(Ejs *ep, int state, int flags)
                                 *      If not executing yet, id may not be known
                                 */
                                fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, 
-                                       fullNameLen, 0, "[", id, "]", 0);
+                                       fullNameLen, 0, "[", id, "]", NULL);
                        }
 #endif
 
@@ -1258,7 +1259,7 @@ static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName,
        *id = mprStrdup(ep->token);
 #if BLD_DEBUG
        *fullNameLen = mprReallocStrcat(fullName, MPR_MAX_VAR, *fullNameLen,
-               0, *id, 0);
+               0, *id, NULL);
 #endif
        if (ep->currentObj == 0) {
                ep->currentObj = ejsFindObj(ep, state, *id, flags);
@@ -1484,6 +1485,23 @@ static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs)
        return 0;
 }
 
+
+/*
+  return true if this string is a valid number
+*/
+static int string_is_number(const char *s)
+{
+       char *endptr = NULL;
+       if (s == NULL || *s == 0) {
+               return 0;
+       }
+       strtod(s, &endptr);
+       if (endptr != NULL && *endptr == 0) {
+               return 1;
+       }
+       return 0;
+}
+
 /******************************************************************************/
 /*
  *     Evaluate an operation. Returns with the result in ep->result. Returns -1
@@ -1532,6 +1550,24 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs)
                /* Nothing more can be done */
        }
 
+       /* undefined and null are special, in that they don't get promoted when
+          comparing */
+       if (rel == EJS_EXPR_EQ || rel == EJS_EXPR_NOTEQ) {
+               if (lhs->type == MPR_TYPE_UNDEFINED || rhs->type == MPR_TYPE_UNDEFINED) {
+                       return evalBoolExpr(ep, 
+                                                               lhs->type == MPR_TYPE_UNDEFINED, 
+                                                               rel, 
+                                                               rhs->type == MPR_TYPE_UNDEFINED);
+               }
+
+               if (lhs->type == MPR_TYPE_NULL || rhs->type == MPR_TYPE_NULL) {
+                       return evalBoolExpr(ep, 
+                                                               lhs->type == MPR_TYPE_NULL, 
+                                                               rel, 
+                                                               rhs->type == MPR_TYPE_NULL);
+               }
+       }
+
        /*
         *      From here on, lhs and rhs may contain allocated data (strings), so 
         *      we must always destroy before overwriting.
@@ -1555,7 +1591,7 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs)
         */
        if (lhs->type != rhs->type) {
                if (lhs->type == MPR_TYPE_STRING) {
-                       if (isdigit((int) lhs->string[0])) {
+                       if (string_is_number(lhs->string)) {
                                num = mprVarToNumber(lhs);
                                lhs->allocatedVar = 0;
                                mprDestroyVar(lhs);
@@ -1641,6 +1677,9 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs)
                case EJS_EXPR_NOTEQ:
                        lval = lhs->type != rhs->type;
                        break;
+               case EJS_EXPR_BOOL_COMP:
+                       lval =  ! mprVarToBool(rhs);
+                       break;
                default:
                        lval = 0;
                }
@@ -1667,8 +1706,8 @@ static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs)
                return 0;
 
        case MPR_TYPE_PTR:
-               mprCopyVarValue(&ep->result, mprCreateBoolVar(lhs->ptr == rhs->ptr), 0);
-               return 0;
+               rc = evalPtrExpr(ep, lhs->ptr, rel, rhs->ptr);
+               break;
 
        case MPR_TYPE_BOOL:
                rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean);
@@ -1803,6 +1842,28 @@ static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r)
        return 0;
 }
 
+static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r) 
+{
+       bool    lval;
+
+       switch (rel) {
+       case EJS_EXPR_EQ:
+               lval = l == r;
+               break;
+       case EJS_EXPR_NOTEQ:
+               lval = l != r;
+               break;
+       case EJS_EXPR_BOOL_COMP:
+               lval = (r == NULL) ? 1 : 0;
+               break;
+       default:
+               ejsError(ep, "Bad operator %d", rel);
+               return -1;
+       }
+       mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0);
+       return 0;
+}
+
 /******************************************************************************/
 /*
  *     Expressions with numeric operands
@@ -2003,10 +2064,11 @@ static int evalFunction(Ejs *ep, MprVar *obj, int flags)
 
        case MPR_TYPE_STRING_CFUNCTION:
                if (actualArgs->used > 0) {
-                       argBuf = mprMalloc(actualArgs->used * sizeof(char*));
+                       argBuf = mprMalloc((1+actualArgs->used) * sizeof(char*));
                        for (i = 0; i < actualArgs->used; i++) {
                                mprVarToString(&argBuf[i], MPR_MAX_STRING, 0, argValues[i]);
                        }
+                       argBuf[i] = NULL;
                } else {
                        argBuf = 0;
                }
@@ -2058,12 +2120,11 @@ static int evalFunction(Ejs *ep, MprVar *obj, int flags)
                formalArgs = prototype->function.args;
                argNames = (char**) formalArgs->handles;
 
-#if FUTURE
-               if (formalArgs->used != actualArgs->used) {
-                       ejsError(ep, "Bad number of args. Should be %d", formalArgs->used);
+               if (formalArgs->used > actualArgs->used) {
+                       ejsError(ep, "Bad number of args. Should be %d", 
+                                        formalArgs->used);
                        return -1;
                }
-#endif
 
                /*
                 *      Create the arguments and callee variables