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 + -
显示快捷键?