📄 ejs.c
字号:
mprFree(ep->fileName); ep->fileName = saveFileName; return rc;/* * Error return */error: mprClose(file); return -1;}/******************************************************************************//* * Create a new variable scope block. This pushes the old local frame down * the stack and creates a new local variables frame. */int ejsOpenBlock(Ejs *ep){ EjsProperty *pp; int fid; ep->local = ejsCreateSimpleObj(ep, "Object"); ejsSetVarName(ep, ep->local, "local"); if (ep->local == 0) { ejsMemoryError(ep); return -1; } if (ep->frames->length > EJS_MAX_FRAMES && !ep->gotException) { ejsError(ep, EJS_RANGE_ERROR, "Recursion too deep: Max depth %d", EJS_MAX_FRAMES); return -1; } /* * Must add to frames before ejsSetProperty which will make the object live */ fid = mprAddItem(ep->frames, ep->local); if (fid < 0) { ejsMemoryError(ep); return -1; } /* Self reference */ pp = ejsSetProperty(ep, ep->local, "local", ep->local); ejsMakePropertyEnumerable(pp, 0); return fid;}/******************************************************************************//* * Set a new variable scope block. This pushes the old local frame down * the stack and creates a new local variables frame. */int ejsSetBlock(Ejs *ep, EjsVar *local){ ep->local = ejsDupVar(ep, local, EJS_SHALLOW_COPY); ejsMakeObjPermanent(ep->local, 1); return mprAddItem(ep->frames, ep->local);}/******************************************************************************//* * Close a variable scope block opened via ejsOpenBlock. Pop back the old * local variables frame. */int ejsCloseBlock(Ejs *ep, int fid){ mprAssert(ep->local >= 0); mprAssert(fid >= 0); mprAssert(ep->local == (EjsVar*) mprGetItem(ep->frames, fid)); if (ep->local) { /* Allow GC */ ejsMakeObjPermanent(ep->local, 0); ejsFreeVar(ep, ep->local); } mprRemoveItemByIndex(ep->frames, fid); ep->local = (EjsVar*) mprGetItem(ep->frames, mprGetItemCount(ep->frames) - 1); return 0;}/******************************************************************************//* * Create a new variable scope block and evaluate a script. All frames * created during this context will be automatically deleted when complete. * vp is optional. i.e. created local variables will be discarded * when this routine returns. */int ejsEvalBlock(Ejs *ep, char *script, EjsVar *vp){ int rc, fid; mprAssert(script); fid = ejsOpenBlock(ep); if (fid < 0) { return fid; } rc = ejsEvalScript(ep, script, vp); ejsCloseBlock(ep, fid); return rc;}/******************************************************************************//* * Parse and evaluate a EJS. The script is evaluated at the current context. * Return the result in *vp. The result is "owned" by EJ and the caller * must not free it. Returns -1 on errors and zero for success. */int ejsEvalScript(Ejs *ep, const char *script, EjsVar *vp){ int state; ejsClearVar(ep, ep->result); ep->gotException = 0; if (script == 0) { return 0; } /* * Allocate a new evaluation block, and save the old one */ if (ejsLexOpenScript(ep, script) < 0) { return MPR_ERR_MEMORY; } /* * Do the actual parsing and evaluation */ ep->scriptStatus = 0; do { state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); if (state == EJS_STATE_RET) { state = EJS_STATE_EOF; } } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); ejsLexCloseScript(ep); if (state == EJS_STATE_ERR) { return -1; } if (vp) { /* Caller must not free. */ *vp = *ep->result; } return ep->scriptStatus;}/******************************************************************************/void ejsSetFileName(Ejs *ep, const char *fileName){ mprFree(ep->fileName); ep->fileName = mprStrdup(ep, fileName);}/******************************************************************************//* * Format the stack backtrace */char *ejsFormatStack(Ejs* ep){ EjsInput *ip; char *errbuf; int frame, len; mprAssert(ep); ip = ep->input; errbuf = 0; len = 0; frame = 0; while (ip && frame < EJS_MAX_BACKTRACE) { char *traceLine, *newErrbuf, *line; for (line = ip->line; *line && isspace(*line); line++) { ; } mprAllocSprintf(MPR_LOC_ARGS(ep), &traceLine, MPR_MAX_STRING, " [%02d] %s, %s, line %d -> %s\n", frame++, ip->fileName ? ip->fileName : "script", ip->procName ? ip->procName: "global", ip->lineNumber, line); if (traceLine == 0) { break; } newErrbuf = mprRealloc(ep, errbuf, len + strlen(traceLine) + 1); if (newErrbuf == NULL) { break; } errbuf = newErrbuf; memcpy(&errbuf[len], traceLine, strlen(traceLine) + 1); len += strlen(traceLine); mprFree(traceLine); ip = ip->next; } return errbuf;}/******************************************************************************//* * Internal use method to set the error message * * Error, ArgError, AssertError, IOError, MemoryError, RangeError, * ReferenceError, SyntaxError, TypeError, MemoryError */void ejsError(Ejs* ep, const char *errorType, const char* fmt, ...){ va_list fmtArgs; EjsVar *error; char *msg, *stack; va_start(fmtArgs, fmt); mprAllocVsprintf(MPR_LOC_ARGS(ep), &msg, MPR_MAX_STRING, fmt, fmtArgs); va_end(fmtArgs); /* * Create a new Error exception object. If bad error type, default to * "Error" */ if (ejsGetClass(ep, 0, errorType) == 0) { errorType = "Error"; } ep->gotException = 1; error = ejsCreateObj(ep, 0, errorType, msg); if (error == 0) { return; } mprFree(msg); stack = ejsFormatStack(ep); ejsSetPropertyToString(ep, error, "stack", stack); mprFree(stack); ejsWriteVar(ep, ep->result, error, EJS_SHALLOW_COPY); ejsFreeVar(ep, error);}/******************************************************************************/void ejsSyntaxError(Ejs *ep, const char *msg){ if (msg == 0) { msg = " "; } ejsError(ep, EJS_SYNTAX_ERROR, msg);}/******************************************************************************/void ejsMemoryError(Ejs *ep){ ejsError(ep, EJS_MEMORY_ERROR, "Memory allocation error");}/******************************************************************************/void ejsArgError(Ejs *ep, const char *msg){ mprAssert(msg && *msg); ejsError(ep, EJS_ARG_ERROR, msg);}/******************************************************************************/void ejsInternalError(Ejs *ep, const char *msg){ mprAssert(msg && *msg); ejsError(ep, EJS_INTERNAL_ERROR, msg);}/******************************************************************************//* * Public routine to set the error message. Caller MUST NOT free. */char *ejsGetErrorMsg(Ejs *ep){ EjsVar *error; const char *message, *stack, *name; char *buf; error = ep->result; if (! ejsVarIsObject(error)) { name = message = stack = 0; } else { name = ejsGetPropertyAsString(ep, error, "name"); message = ejsGetPropertyAsString(ep, error, "message"); stack = ejsGetPropertyAsString(ep, error, "stack"); } if (name == 0 || message == 0) { buf = mprStrdup(ep, "Unspecified execution error\n"); } else { mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, "%s Exception: %s\nStack:\n%s\n", name, message, stack ? stack : " " ); } mprFree(ep->errorMsg); ep->errorMsg = buf; return buf;}/******************************************************************************//* * Get the current line number */int ejsGetLineNumber(Ejs *ep){ if (ep->input == 0) { return -1; } return ep->input->lineNumber;}/******************************************************************************//* * Return the local object */EjsVar *ejsGetLocalObj(Ejs *ep){ return ep->local;}/******************************************************************************//* * Return the global object */EjsVar *ejsGetGlobalObj(Ejs *ep){ return ep->global;}/******************************************************************************//* * Set the expression return value */void ejsSetReturnValue(Ejs *ep, EjsVar *vp){ mprAssert(ep); mprAssert(vp); if (vp == 0) { return; } ejsWriteVar(ep, ep->result, vp, EJS_SHALLOW_COPY);}/******************************************************************************//* * Set the expression return value and free the arg. */void ejsSetReturnValueAndFree(Ejs *ep, EjsVar *vp){ mprAssert(ep); mprAssert(vp); ejsWriteVar(ep, ep->result, vp, EJS_SHALLOW_COPY); ejsFreeVar(ep, vp);}/******************************************************************************//* * Set the expression return value to a string value. */void ejsSetReturnValueToString(Ejs *ep, const char *value){ mprAssert(ep); mprAssert(value); ejsWriteVarAsString(ep, ep->result, value);}/******************************************************************************//* * Set the expression return value to a binary string value. */void ejsSetReturnValueToBinaryString(Ejs *ep, const uchar *value, int len){ mprAssert(ep); mprAssert(value); ejsWriteVarAsBinaryString(ep, ep->result, value, len);}/******************************************************************************//* * Set the expression return value to a integer value. */void ejsSetReturnValueToInteger(Ejs *ep, int value){ mprAssert(ep); ejsWriteVarAsInteger(ep, ep->result, value);}/******************************************************************************//* * Set the expression return value to an EjsNum value. */void ejsSetReturnValueToNumber(Ejs *ep, EjsNum value){ mprAssert(ep); ejsWriteVarAsNumber(ep, ep->result, value);}/******************************************************************************//* * Set the expression return value to a boolean value. */void ejsSetReturnValueToBoolean(Ejs *ep, int value){ mprAssert(ep); ejsWriteVarAsBoolean(ep, ep->result, value);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -