Ejemplo n.º 1
0
bool ScScript::executeInstruction() {
	bool ret = STATUS_OK;

	uint32 dw;
	const char *str = nullptr;

	//ScValue* op = new ScValue(_gameRef);
	_operand->cleanup();

	ScValue *op1;
	ScValue *op2;

	uint32 inst = getDWORD();
	switch (inst) {

	case II_DEF_VAR:
		_operand->setNULL();
		dw = getDWORD();
		if (_scopeStack->_sP < 0) {
			_globals->setProp(_symbols[dw], _operand);
		} else {
			_scopeStack->getTop()->setProp(_symbols[dw], _operand);
		}

		break;

	case II_DEF_GLOB_VAR:
	case II_DEF_CONST_VAR: {
		dw = getDWORD();
		/*      char *temp = _symbols[dw]; // TODO delete */
		// only create global var if it doesn't exist
		if (!_engine->_globals->propExists(_symbols[dw])) {
			_operand->setNULL();
			_engine->_globals->setProp(_symbols[dw], _operand, false, inst == II_DEF_CONST_VAR);
		}
		break;
	}

	case II_RET:
		if (_scopeStack->_sP >= 0 && _callStack->_sP >= 0) {
			_scopeStack->pop();
			_iP = (uint32)_callStack->pop()->getInt();
		} else {
			if (_thread) {
				_state = SCRIPT_THREAD_FINISHED;
			} else {
				if (_numEvents == 0 && _numMethods == 0) {
					_state = SCRIPT_FINISHED;
				} else {
					_state = SCRIPT_PERSISTENT;
				}
			}
		}

		break;

	case II_RET_EVENT:
		_state = SCRIPT_FINISHED;
		break;


	case II_CALL:
		dw = getDWORD();

		_operand->setInt(_iP);
		_callStack->push(_operand);

		_iP = dw;

		break;

	case II_CALL_BY_EXP: {
		// push var
		// push string
		str = _stack->pop()->getString();
		char *methodName = new char[strlen(str) + 1];
		strcpy(methodName, str);

		ScValue *var = _stack->pop();
		if (var->_type == VAL_VARIABLE_REF) {
			var = var->_valRef;
		}

		bool res = STATUS_FAILED;
		bool triedNative = false;

		// we are already calling this method, try native
		if (_thread && _methodThread && strcmp(methodName, _threadEvent) == 0 && var->_type == VAL_NATIVE && _owner == var->getNative()) {
			triedNative = true;
			res = var->_valNative->scCallMethod(this, _stack, _thisStack, methodName);
		}

		if (DID_FAIL(res)) {
			if (var->isNative() && var->getNative()->canHandleMethod(methodName)) {
				if (!_unbreakable) {
					_waitScript = var->getNative()->invokeMethodThread(methodName);
					if (!_waitScript) {
						_stack->correctParams(0);
						runtimeError("Error invoking method '%s'.", methodName);
						_stack->pushNULL();
					} else {
						_state = SCRIPT_WAITING_SCRIPT;
						_waitScript->copyParameters(_stack);
					}
				} else {
					// can call methods in unbreakable mode
					_stack->correctParams(0);
					runtimeError("Cannot call method '%s'. Ignored.", methodName);
					_stack->pushNULL();
				}
				delete[] methodName;
				break;
			}
			/*
			ScValue* val = var->getProp(MethodName);
			if (val) {
			    dw = GetFuncPos(val->getString());
			    if (dw==0) {
			        TExternalFunction* f = GetExternal(val->getString());
			        if (f) {
			            ExternalCall(_stack, _thisStack, f);
			        }
			        else{
			            // not an internal nor external, try for native function
			            _gameRef->ExternalCall(this, _stack, _thisStack, val->getString());
			        }
			    }
			    else{
			        _operand->setInt(_iP);
			        _callStack->Push(_operand);
			        _iP = dw;
			    }
			}
			*/
			else {
				res = STATUS_FAILED;
				if (var->_type == VAL_NATIVE && !triedNative) {
					res = var->_valNative->scCallMethod(this, _stack, _thisStack, methodName);
				}

				if (DID_FAIL(res)) {
					_stack->correctParams(0);
					runtimeError("Call to undefined method '%s'. Ignored.", methodName);
					_stack->pushNULL();
				}
			}
		}
		delete[] methodName;
	}
	break;

	case II_EXTERNAL_CALL: {
		uint32 symbolIndex = getDWORD();

		TExternalFunction *f = getExternal(_symbols[symbolIndex]);
		if (f) {
			externalCall(_stack, _thisStack, f);
		} else {
			_gameRef->externalCall(this, _stack, _thisStack, _symbols[symbolIndex]);
		}

		break;
	}
	case II_SCOPE:
		_operand->setNULL();
		_scopeStack->push(_operand);
		break;

	case II_CORRECT_STACK:
		dw = getDWORD(); // params expected
		_stack->correctParams(dw);
		break;

	case II_CREATE_OBJECT:
		_operand->setObject();
		_stack->push(_operand);
		break;

	case II_POP_EMPTY:
		_stack->pop();
		break;

	case II_PUSH_VAR: {
		ScValue *var = getVar(_symbols[getDWORD()]);
		if (false && /*var->_type==VAL_OBJECT ||*/ var->_type == VAL_NATIVE) {
			_operand->setReference(var);
			_stack->push(_operand);
		} else {
			_stack->push(var);
		}
		break;
	}

	case II_PUSH_VAR_REF: {
		ScValue *var = getVar(_symbols[getDWORD()]);
		_operand->setReference(var);
		_stack->push(_operand);
		break;
	}

	case II_POP_VAR: {
		char *varName = _symbols[getDWORD()];
		ScValue *var = getVar(varName);
		if (var) {
			ScValue *val = _stack->pop();
			if (!val) {
				runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum.");
				var->setNULL();
			} else {
				if (val->getType() == VAL_VARIABLE_REF) {
					val = val->_valRef;
				}
				if (val->_type == VAL_NATIVE) {
					var->setValue(val);
				} else {
					var->copy(val);
				}
			}
		}

		break;
	}

	case II_PUSH_VAR_THIS:
		_stack->push(_thisStack->getTop());
		break;

	case II_PUSH_INT:
		_stack->pushInt((int)getDWORD());
		break;

	case II_PUSH_FLOAT:
		_stack->pushFloat(getFloat());
		break;


	case II_PUSH_BOOL:
		_stack->pushBool(getDWORD() != 0);

		break;

	case II_PUSH_STRING:
		_stack->pushString(getString());
		break;

	case II_PUSH_NULL:
		_stack->pushNULL();
		break;

	case II_PUSH_THIS_FROM_STACK:
		_operand->setReference(_stack->getTop());
		_thisStack->push(_operand);
		break;

	case II_PUSH_THIS:
		_operand->setReference(getVar(_symbols[getDWORD()]));
		_thisStack->push(_operand);
		break;

	case II_POP_THIS:
		_thisStack->pop();
		break;

	case II_PUSH_BY_EXP: {
		str = _stack->pop()->getString();
		ScValue *val = _stack->pop()->getProp(str);
		if (val) {
			_stack->push(val);
		} else {
			_stack->pushNULL();
		}

		break;
	}

	case II_POP_BY_EXP: {
		str = _stack->pop()->getString();
		ScValue *var = _stack->pop();
		ScValue *val = _stack->pop();

		if (val == nullptr) {
			runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum.");
			var->setNULL();
		} else {
			var->setProp(str, val);
		}

		break;
	}

	case II_PUSH_REG1:
		_stack->push(_reg1);
		break;

	case II_POP_REG1:
		_reg1->copy(_stack->pop());
		break;

	case II_JMP:
		_iP = getDWORD();
		break;

	case II_JMP_FALSE: {
		dw = getDWORD();
		//if (!_stack->pop()->getBool()) _iP = dw;
		ScValue *val = _stack->pop();
		if (!val) {
			runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
		} else {
			if (!val->getBool()) {
				_iP = dw;
			}
		}
		break;
	}

	case II_ADD:
		op2 = _stack->pop();
		op1 = _stack->pop();

		if (op1->isNULL() || op2->isNULL()) {
			_operand->setNULL();
		} else if (op1->getType() == VAL_STRING || op2->getType() == VAL_STRING) {
			char *tempStr = new char [strlen(op1->getString()) + strlen(op2->getString()) + 1];
			strcpy(tempStr, op1->getString());
			strcat(tempStr, op2->getString());
			_operand->setString(tempStr);
			delete[] tempStr;
		} else if (op1->getType() == VAL_INT && op2->getType() == VAL_INT) {
			_operand->setInt(op1->getInt() + op2->getInt());
		} else {
			_operand->setFloat(op1->getFloat() + op2->getFloat());
		}

		_stack->push(_operand);

		break;

	case II_SUB:
		op2 = _stack->pop();
		op1 = _stack->pop();

		if (op1->isNULL() || op2->isNULL()) {
			_operand->setNULL();
		} else if (op1->getType() == VAL_INT && op2->getType() == VAL_INT) {
			_operand->setInt(op1->getInt() - op2->getInt());
		} else {
			_operand->setFloat(op1->getFloat() - op2->getFloat());
		}

		_stack->push(_operand);

		break;

	case II_MUL:
		op2 = _stack->pop();
		op1 = _stack->pop();

		if (op1->isNULL() || op2->isNULL()) {
			_operand->setNULL();
		} else if (op1->getType() == VAL_INT && op2->getType() == VAL_INT) {
			_operand->setInt(op1->getInt() * op2->getInt());
		} else {
			_operand->setFloat(op1->getFloat() * op2->getFloat());
		}

		_stack->push(_operand);

		break;

	case II_DIV:
		op2 = _stack->pop();
		op1 = _stack->pop();

		if (op2->getFloat() == 0.0f) {
			runtimeError("Division by zero.");
		}

		if (op1->isNULL() || op2->isNULL() || op2->getFloat() == 0.0f) {
			_operand->setNULL();
		} else {
			_operand->setFloat(op1->getFloat() / op2->getFloat());
		}

		_stack->push(_operand);

		break;

	case II_MODULO:
		op2 = _stack->pop();
		op1 = _stack->pop();

		if (op2->getInt() == 0) {
			runtimeError("Division by zero.");
		}

		if (op1->isNULL() || op2->isNULL() || op2->getInt() == 0) {
			_operand->setNULL();
		} else {
			_operand->setInt(op1->getInt() % op2->getInt());
		}

		_stack->push(_operand);

		break;

	case II_NOT:
		op1 = _stack->pop();
		//if (op1->isNULL()) _operand->setNULL();
		if (op1->isNULL()) {
			_operand->setBool(true);
		} else {
			_operand->setBool(!op1->getBool());
		}
		_stack->push(_operand);

		break;

	case II_AND:
		op2 = _stack->pop();
		op1 = _stack->pop();
		if (op1 == nullptr || op2 == nullptr) {
			runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
			_operand->setBool(false);
		} else {
			_operand->setBool(op1->getBool() && op2->getBool());
		}
		_stack->push(_operand);
		break;

	case II_OR:
		op2 = _stack->pop();
		op1 = _stack->pop();
		if (op1 == nullptr || op2 == nullptr) {
			runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
			_operand->setBool(false);
		} else {
			_operand->setBool(op1->getBool() || op2->getBool());
		}
		_stack->push(_operand);
		break;

	case II_CMP_EQ:
		op2 = _stack->pop();
		op1 = _stack->pop();

		/*
		if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(false);
		else if (op1->isNative() && op2->isNative()) {
		    _operand->setBool(op1->getNative() == op2->getNative());
		}
		else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING) {
		    _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())==0);
		}
		else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) {
		    _operand->setBool(op1->getFloat() == op2->getFloat());
		}
		else{
		    _operand->setBool(op1->getInt() == op2->getInt());
		}
		*/

		_operand->setBool(ScValue::compare(op1, op2) == 0);
		_stack->push(_operand);
		break;

	case II_CMP_NE:
		op2 = _stack->pop();
		op1 = _stack->pop();

		/*
		if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(true);
		else if (op1->isNative() && op2->isNative()) {
		    _operand->setBool(op1->getNative() != op2->getNative());
		}
		else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING) {
		    _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())!=0);
		}
		else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) {
		    _operand->setBool(op1->getFloat() != op2->getFloat());
		}
		else{
		    _operand->setBool(op1->getInt() != op2->getInt());
		}
		*/

		_operand->setBool(ScValue::compare(op1, op2) != 0);
		_stack->push(_operand);
		break;

	case II_CMP_L:
		op2 = _stack->pop();
		op1 = _stack->pop();

		/*
		if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) {
		    _operand->setBool(op1->getFloat() < op2->getFloat());
		}
		else _operand->setBool(op1->getInt() < op2->getInt());
		*/

		_operand->setBool(ScValue::compare(op1, op2) < 0);
		_stack->push(_operand);
		break;

	case II_CMP_G:
		op2 = _stack->pop();
		op1 = _stack->pop();

		/*
		if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) {
		    _operand->setBool(op1->getFloat() > op2->getFloat());
		}
		else _operand->setBool(op1->getInt() > op2->getInt());
		*/

		_operand->setBool(ScValue::compare(op1, op2) > 0);
		_stack->push(_operand);
		break;

	case II_CMP_LE:
		op2 = _stack->pop();
		op1 = _stack->pop();

		/*
		if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) {
		    _operand->setBool(op1->getFloat() <= op2->getFloat());
		}
		else _operand->setBool(op1->getInt() <= op2->getInt());
		*/

		_operand->setBool(ScValue::compare(op1, op2) <= 0);
		_stack->push(_operand);
		break;

	case II_CMP_GE:
		op2 = _stack->pop();
		op1 = _stack->pop();

		/*
		if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT) {
		    _operand->setBool(op1->getFloat() >= op2->getFloat());
		}
		else _operand->setBool(op1->getInt() >= op2->getInt());
		*/

		_operand->setBool(ScValue::compare(op1, op2) >= 0);
		_stack->push(_operand);
		break;

	case II_CMP_STRICT_EQ:
		op2 = _stack->pop();
		op1 = _stack->pop();

		//_operand->setBool(op1->getType()==op2->getType() && op1->getFloat()==op2->getFloat());
		_operand->setBool(ScValue::compareStrict(op1, op2) == 0);
		_stack->push(_operand);

		break;

	case II_CMP_STRICT_NE:
		op2 = _stack->pop();
		op1 = _stack->pop();

		//_operand->setBool(op1->getType()!=op2->getType() || op1->getFloat()!=op2->getFloat());
		_operand->setBool(ScValue::compareStrict(op1, op2) != 0);
		_stack->push(_operand);
		break;

	case II_DBG_LINE: {
		int newLine = getDWORD();
		if (newLine != _currentLine) {
			_currentLine = newLine;
		}
		break;

	}
	default:
		_gameRef->LOG(0, "Fatal: Invalid instruction %d ('%s', line %d, IP:0x%x)\n", inst, _filename, _currentLine, _iP - sizeof(uint32));
		_state = SCRIPT_FINISHED;
		ret = STATUS_FAILED;
	} // switch(instruction)

	//delete op;

	return ret;
}
Ejemplo n.º 2
0
/*BEGIN main driver function*/
int main(int argc, char **argv){
	
	/*BEGIN variable declarations*/
	char buf[MAX_BUFFER];		//line buffer
	char *args[MAX_ARGS];		//pointers to arg strings
	char **arg;			//working pointer thru args
	int noPrompt = 0;
	/*END variable declarations*/

	/*Register the signal handler function*/
	if (signal(SIGINT, sigHandler) == SIG_ERR)
		printf("\nSomething went wrong; can't catch SIGINT\n");

	/*Set the prompt.  Also puts a value in cwd that is used in several other operations*/
	setPrompt();
	
	//set the literal path for the readme file
	readme = (char*)malloc(sizeof(char) * (strlen(cwd) + 8));
	strcat(readme, cwd);
	strcat(readme, "/readme");

	/*Set the SHELL environment variable*/
	shell= (char *)malloc(sizeof(char) * (strlen(cwd)+strlen(argv[0])+8));
	strcat(shell, "SHELL=");
	strcat(shell, cwd);
	strcat(shell, "/");
	strcat(shell, argv[0]);
	putenv(shell);

	/*Set the initial call to the shell.  Used in setting PARENT environment variable for child processes*/
	initCall = (char *)malloc(sizeof(char) * (strlen(cwd) + strlen(argv[0]) + 2));
	strcat(initCall, cwd);
	strcat(initCall, "/");
	strcat(initCall, argv[0]);

	/*check for arguments to program, assume first argument after program name is batchfile, ignore all others(for now)*/
	if(argc > 1){
		/*Check for existance of file*/
		if(access(argv[1], F_OK)==-1){
			puts("Bad filename or path");
		}else
			/*Check for read/execute access to file(commands being executed = execute access should be honored)*/
			if((access(argv[1], R_OK)==0)&&(access(argv[1], X_OK)==0)){
				freopen(argv[1], "r", stdin);
				noPrompt = 1;
			}else
				puts("Cannot open that file, you may not have access permissions to it.");
	}

	/*BEGIN infinite loop*///Looped input reading code based on strtokeg.c
	while(!feof(stdin))
	{
		/*display current PID if debug is set*/
		if(DEBUG)
			printf("Process: %d \n", (int)getpid());

		/*get user input unless batchfile used*/
		if(!noPrompt)
			fputs(prompt, stdout);
	


		if(fgets(buf, MAX_BUFFER, stdin))	//read a line
		{
			noWait = 0;	//reset background flag in case it was used in last command
			/*tokenize input into args array*/

			arg = args;
			*arg++ = strtok(buf, DELIMITERS);	//tokenize first argument
			while((*arg++ = strtok(NULL, DELIMITERS)));	//last entry will be null and loop will exit
			

			//alias implementation needs an alias list and a way to push aliased commands to args[]


			if(args[0])
			{
				
				debug("First Arg:");
				debug(args[0]);
				if(!strcmp(args[0],"clr")){
					if(clr(args) == -1)
						debug("Clear error");
				}else{	//else1
				if(!strcmp(args[0], "cd")){
					if(cd(args) == -1)
						debug("Cd error");
				}else{	//else2
				if(!strcmp(args[0], "dir")){
					if(dir(args) == -1)
						debug("Dir error");
				}else{	//else3
				if(!strcmp(args[0], "environ")){
					if(envrn(args) == -1)
						debug("Env error");
				}else{	//else4
				if(!strcmp(args[0], "echo")){
					if(echo(args) == -1)
						debug("Echo error");
				}else{	//else5
				if(!strcmp(args[0], "help")){
					if(help(args) == -1)
						debug("Help error");
				}else{	//else6
				if(!strcmp(args[0], "pause")){
					if(pauseShell(args) == -1)
						debug("Pause error");
				}else{	//else7
				if(!strcmp(args[0], "quit")){
					if(quit(args) == -1)
						debug("Quit error");
				}else{  //else8
				if(!strcmp(args[0], "alias")){
					fputs("Sorry, alias has not yet been implemented\n", stdout);
					debug("alias not implemented yet");
				}else{	//else9
				if(externalCall(args)== -1)
					debug("Externalcall error");
				}//else9
				}//else8
				}//else7
				}//else6
				}//else5
				}//else4
				}//else3
				}//else2
				}//else1
				
			}//if(args[0])
		}//if(fgets(buf, MAX_BUFFER, stdin))
	}
	/*END infinite loop*/
	return -1;	//this point should not be reachable
}