ejsparser.c
来自「samba最新软件」· C语言 代码 · 共 2,437 行 · 第 1/4 页
C
2,437 行
lval = l == r; break; case EJS_EXPR_NOTEQ: lval = l != r; break; case EJS_EXPR_BOOL_COMP: lval = (r == 0) ? 1 : 0; break; default: ejsError(ep, "Bad operator %d", rel); return -1; } mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); 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 */static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r) { MprNum lval; bool logical; lval = 0; logical = 0; switch (rel) { case EJS_EXPR_PLUS: lval = l + r; break; case EJS_EXPR_INC: lval = l + 1; break; case EJS_EXPR_MINUS: lval = l - r; break; case EJS_EXPR_DEC: lval = l - 1; break; case EJS_EXPR_MUL: lval = l * r; break; case EJS_EXPR_DIV: if (r != 0) { lval = l / r; } else { ejsError(ep, "Divide by zero"); return -1; } break; case EJS_EXPR_MOD: if (r != 0) { lval = l % r; } else { ejsError(ep, "Modulo zero"); return -1; } break; case EJS_EXPR_LSHIFT: lval = l << r; break; case EJS_EXPR_RSHIFT: lval = l >> r; break; default: logical++; break; } /* * Logical operators */ if (logical) { switch (rel) { case EJS_EXPR_EQ: lval = l == r; break; case EJS_EXPR_NOTEQ: lval = l != r; break; case EJS_EXPR_LESS: lval = (l < r) ? 1 : 0; break; case EJS_EXPR_LESSEQ: lval = (l <= r) ? 1 : 0; break; case EJS_EXPR_GREATER: lval = (l > r) ? 1 : 0; break; case EJS_EXPR_GREATEREQ: lval = (l >= r) ? 1 : 0; break; case EJS_EXPR_BOOL_COMP: lval = (r == 0) ? 1 : 0; break; default: ejsError(ep, "Bad operator %d", rel); return -1; } mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); } else { mprCopyVarValue(&ep->result, mprCreateNumberVar(lval), 0); } return 0;}/******************************************************************************//* * Expressions with string operands */static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs){ int lval; mprAssert(ep); mprAssert(lhs); mprAssert(rhs); switch (rel) { case EJS_EXPR_LESS: lval = strcmp(lhs->string, rhs->string) < 0; break; case EJS_EXPR_LESSEQ: lval = strcmp(lhs->string, rhs->string) <= 0; break; case EJS_EXPR_GREATER: lval = strcmp(lhs->string, rhs->string) > 0; break; case EJS_EXPR_GREATEREQ: lval = strcmp(lhs->string, rhs->string) >= 0; break; case EJS_EXPR_EQ: lval = strcmp(lhs->string, rhs->string) == 0; break; case EJS_EXPR_NOTEQ: lval = strcmp(lhs->string, rhs->string) != 0; break; case EJS_EXPR_PLUS: /* * This differs from all the above operations. We append rhs to lhs. */ mprDestroyVar(&ep->result); appendValue(&ep->result, lhs); appendValue(&ep->result, rhs); return 0; case EJS_EXPR_INC: case EJS_EXPR_DEC: case EJS_EXPR_MINUS: case EJS_EXPR_DIV: case EJS_EXPR_MOD: case EJS_EXPR_LSHIFT: case EJS_EXPR_RSHIFT: default: ejsError(ep, "Bad operator"); return -1; } mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); return 0;}/******************************************************************************//* * Evaluate a function. obj is set to the current object if a function is being * run. */static int evalFunction(Ejs *ep, MprVar *obj, int flags){ EjsProc *proc; MprVar arguments, callee, thisObject, *prototype, **argValues; MprArray *formalArgs, *actualArgs; char buf[16], **argNames, **argBuf; int i, rc, fid; mprAssert(ep); mprAssert(ejsPtr(ep->eid)); rc = -1; proc = ep->proc; prototype = proc->fn; actualArgs = proc->args; argValues = (MprVar**) actualArgs->handles; /* * Create a new variable stack frame. ie. new local variables. */ fid = ejsOpenBlock(ep->eid); if (flags & EJS_FLAGS_NEW) { /* * Create a new bare object and pass it into the constructor as the * "this" local variable. */ thisObject = ejsCreateObj("this", EJS_OBJ_HASH_SIZE); mprCreatePropertyValue(ep->local, "this", thisObject); } else if (obj) { mprCreateProperty(ep->local, "this", obj); } switch (prototype->type) { default: mprAssert(0); break; case MPR_TYPE_STRING_CFUNCTION: if (actualArgs->used > 0) { 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; } /* * Call the function depending on the various handle flags */ ep->thisPtr = prototype->cFunctionWithStrings.thisPtr; if (prototype->flags & MPR_VAR_ALT_HANDLE) { rc = ((EjsAltStringCFunction) prototype->cFunctionWithStrings.fn) (ep->eid, ep->altHandle, actualArgs->used, argBuf); } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { rc = (prototype->cFunctionWithStrings.fn)(ep->eid, actualArgs->used, argBuf); } else { rc = (prototype->cFunctionWithStrings.fn)(ep->primaryHandle, actualArgs->used, argBuf); } if (actualArgs->used > 0) { for (i = 0; i < actualArgs->used; i++) { mprFree(argBuf[i]); } mprFree(argBuf); } ep->thisPtr = 0; break; case MPR_TYPE_CFUNCTION: /* * Call the function depending on the various handle flags */ ep->thisPtr = prototype->cFunction.thisPtr; if (prototype->flags & MPR_VAR_ALT_HANDLE) { rc = ((EjsAltCFunction) prototype->cFunction.fn) (ep->eid, ep->altHandle, actualArgs->used, argValues); } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { rc = (prototype->cFunction.fn)(ep->eid, actualArgs->used, argValues); } else { rc = (prototype->cFunction.fn)(ep->primaryHandle, actualArgs->used, argValues); } ep->thisPtr = 0; break; case MPR_TYPE_FUNCTION: formalArgs = prototype->function.args; argNames = (char**) formalArgs->handles; if (formalArgs->used > actualArgs->used) { ejsError(ep, "Bad number of args. Should be %d", formalArgs->used); return -1; } /* * Create the arguments and callee variables */ arguments = ejsCreateObj("arguments", EJS_SMALL_OBJ_HASH_SIZE); callee = ejsCreateObj("callee", EJS_SMALL_OBJ_HASH_SIZE); /* * Overwrite the length property */ mprCreatePropertyValue(&arguments, "length", mprCreateIntegerVar(actualArgs->used)); mprCreatePropertyValue(&callee, "length", mprCreateIntegerVar(formalArgs->used)); /* * Define all the agruments to be set to the actual parameters */ for (i = 0; i < formalArgs->used; i++) { mprCreateProperty(ep->local, argNames[i], argValues[i]); } for (i = 0; i < actualArgs->used; i++) { mprItoa(i, buf, sizeof(buf)); mprCreateProperty(&arguments, buf, argValues[i]); } mprCreateProperty(&arguments, "callee", &callee); mprCreateProperty(ep->local, "arguments", &arguments); /* * Can destroy our variables here as they are now referenced via * "local" */ mprDestroyVar(&callee); mprDestroyVar(&arguments); /* * Actually run the function */ rc = ejsEvalScript(ep->eid, prototype->function.body, 0, 0); break; } ejsCloseBlock(ep->eid, fid); /* * New statements return the newly created object as the result of the * command */ if (flags & EJS_FLAGS_NEW) { mprDestroyVar(&ep->result); /* * Don't copy, we want to assign the actual object into result. * (mprCopyVar would inc the refCount to 2). */ ep->result = thisObject; } return rc;}/******************************************************************************//* * Run a function */int ejsRunFunction(int eid, MprVar *obj, const char *functionName, MprArray *args){ EjsProc proc, *saveProc; Ejs *ep; int rc; mprAssert(obj); mprAssert(functionName && *functionName); if ((ep = ejsPtr(eid)) == NULL) { mprAssert(ep); return MPR_ERR_NOT_FOUND; } saveProc = ep->proc; ep->proc = &proc; memset(&proc, 0, sizeof(EjsProc)); mprDestroyVar(&ep->result); proc.fn = mprGetProperty(obj, functionName, 0); if (proc.fn == 0 || proc.fn->type == MPR_TYPE_UNDEFINED) { ep->proc = saveProc; return MPR_ERR_NOT_FOUND; } proc.procName = mprStrdup(functionName); if (args == 0) { proc.args = mprCreateArray(); rc = evalFunction(ep, obj, 0); } else { proc.args = args; rc = evalFunction(ep, obj, 0); proc.args = 0; } freeProc(&proc); ep->proc = saveProc; return rc;}/******************************************************************************//* * Find which object contains the property given the current context. * Only used for top level properties. */MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags){ MprVar *obj; mprAssert(ep); mprAssert(property && *property); if (flags & EJS_FLAGS_GLOBAL) { obj = ep->global; } else if (state == EJS_STATE_DEC || flags & EJS_FLAGS_LOCAL) { obj = ep->local; } else { /* First look local, then look global */ if (mprGetProperty(ep->local, property, 0)) { obj = ep->local; } else { obj = ep->global; } } return obj;}/******************************************************************************//* * Find an object property given a object and a property name. We * intelligently look in the local and global namespaces depending on * our state. If not found in local or global, try base classes for function * names only. Returns the property or NULL. */MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, char *property, int flags){ MprVar *vp; mprAssert(ep); if (flags & EJS_FLAGS_EXE) { mprAssert(property && *property); } if (obj != 0) {#if FUTURE && MB op = obj; do { vp = mprGetProperty(op, property, 0); if (vp != 0) { if (op != obj && mprVarIsFunction(vp->type)) { } break; } op = op->baseObj; } while (op);#endif vp = mprGetProperty(obj, property, 0); } else { if (state == EJS_STATE_DEC) { vp = mprGetProperty(ep->local, property, 0); } else { /* Look local first, then global */ vp = mprGetProperty(ep->local, property, 0); if (vp == NULL) { vp = mprGetProperty(ep->global, property, 0); } } } return vp;}/******************************************************************************//* * Update result */static void updateResult(Ejs *ep, int state, int flags, MprVar *vp){ if (flags & EJS_FLAGS_EXE && state != EJS_STATE_DEC) { mprDestroyVar(&ep->result); if (vp) { mprCopyProperty(&ep->result, vp, MPR_SHALLOW_COPY); } }}/******************************************************************************//* * Append to the pointer value */static void appendValue(MprVar *dest, MprVar *src){ char *value, *oldBuf, *buf; int len, oldLen; mprAssert(dest); mprVarToString(&value, MPR_MAX_STRING, 0, src); if (mprVarIsValid(dest)) { len = strlen(value); oldBuf = dest->string; oldLen = strlen(oldBuf); buf = mprRealloc(oldBuf, (len + oldLen + 1) * sizeof(char)); dest->string = buf; strcpy(&buf[oldLen], value); } else { *dest = mprCreateStringVar(value, 1); } mprFree(value);}/******************************************************************************//* * Exit with status */void ejsSetExitStatus(int eid, int status){ Ejs *ep; if ((ep = ejsPtr(eid)) == NULL) { mprAssert(ep); return; } ep->exitStatus = status; ep->flags |= EJS_FLAGS_EXIT;}/******************************************************************************//* * Free an argument list */static void freeProc(EjsProc *proc){ MprVar **argValues; int i; if (proc->args) { argValues = (MprVar**) proc->args->handles; for (i = 0; i < proc->args->max; i++) { if (argValues[i]) { mprDestroyVar(argValues[i]); mprFree(argValues[i]); mprRemoveFromArray(proc->args, i); } } mprDestroyArray(proc->args); } if (proc->procName) { mprFree(proc->procName); proc->procName = NULL; }}/******************************************************************************//* * This function removes any new lines. Used for else cases, etc. */static void removeNewlines(Ejs *ep, int state){ int tid; do { tid = ejsLexGetToken(ep, state); } while (tid == EJS_TOK_NEWLINE); ejsLexPutbackToken(ep, tid, ep->token);}/******************************************************************************/#elsevoid ejsParserDummy() {}/******************************************************************************/#endif /* BLD_FEATURE_EJS *//* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim:tw=78 * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?