Exemple #1
0
static SQInteger thread_wakeup(HSQUIRRELVM v)
{
	SQObjectPtr o = stack_get(v,1);
	if(type(o) == OT_THREAD) {
		SQVM *thread = _thread(o);
		SQInteger state = sq_getvmstate(thread);
		if(state != SQ_VMSTATE_SUSPENDED) {
			switch(state) {
				case SQ_VMSTATE_IDLE:
					return sq_throwerror(v,_SC("cannot wakeup a idle thread"));
				break;
				case SQ_VMSTATE_RUNNING:
					return sq_throwerror(v,_SC("cannot wakeup a running thread"));
				break;
			}
		}
			
		SQInteger wakeupret = sq_gettop(v)>1?1:0;
		if(wakeupret) {
			sq_move(thread,v,2);
		}
		if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1,SQFalse))) {
			sq_move(v,thread,-1);
			sq_pop(thread,1);
			if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
				sq_pop(thread,1);
			}
			return 1;
		}
		return SQ_ERROR;
	}
	return sq_throwerror(v,_SC("wrong parameter"));
}
static SQInteger program_main(HSQUIRRELVM v)
{
	if(sq_gettop(v) != (1 + 3)){ //roottable, userpointer, co_cpu, co_ppu
		return sq_throwerror(v, wgT("argument number error"));
	}
	struct program_config *d;
	SQRESULT r =  qr_userpointer_get(v, (SQUserPointer) &d);
	if(SQ_FAILED(r)){
		return r;
	}
	HSQUIRRELVM co_cpu, co_ppu;
	if(SQ_FAILED(sq_getthread(v, 3, &co_cpu))){
		return sq_throwerror(v, wgT("thread error"));
	}
	if(SQ_FAILED(sq_getthread(v, 4, &co_ppu))){
		return sq_throwerror(v, wgT("thread error"));
	}
	SQInteger state_cpu = sq_getvmstate(co_cpu);
	SQInteger state_ppu = sq_getvmstate(co_ppu);
	const long sleepms = d->compare == true ? 6 : 2; //W29C040 で compare をすると、error が出るので出ない値に調整 (やっつけ対応)
	
	while((state_cpu != SQ_VMSTATE_IDLE) || (state_ppu != SQ_VMSTATE_IDLE)){
		uint8_t s[2];
		wait_msec(sleepms);
		d->control->flash_status(d->handle, s);
		if(state_cpu != SQ_VMSTATE_IDLE && s[0] == KAZZO_TASK_FLASH_IDLE){
			if(program_memoryarea(co_cpu, d->handle, &d->cpu, d->compare, &state_cpu, &d->log) == false){
				//sq_pushbool(v, SQFalse);
				return 0;
			}
		}
		if(state_ppu != SQ_VMSTATE_IDLE && s[1] == KAZZO_TASK_FLASH_IDLE){
			if(program_memoryarea(co_ppu, d->handle, &d->ppu, d->compare, &state_ppu, &d->log) == false){
				//sq_pushbool(v, SQFalse);
				return 0;
			}
		}
	}
	//sq_pushbool(v, SQTrue);
	return 0;
}
static bool program_memoryarea(HSQUIRRELVM co, const struct reader_handle *h, struct flash_memory_driver *t, bool compare, SQInteger *state, struct textcontrol *log)
{
	if(t->programming.length == 0){
		if(t->programming.offset != 0 && compare == true){
			if(program_compare(h, t) == false){
				log->append(log->object, wgT("%s memory compare failed, offset 0x%06x\n"), t->memory.name, t->programming.offset);
				return false;
			}
		}

		sq_wakeupvm(co, SQFalse, SQFalse, SQTrue, SQFalse);
		*state = sq_getvmstate(co);
	}else{
		program_execute(h, t);
	}
	return true;
}
Exemple #4
0
static SQInteger thread_getstatus(HSQUIRRELVM v)
{
	SQObjectPtr &o = stack_get(v,1);
	switch(sq_getvmstate(_thread(o))) {
		case SQ_VMSTATE_IDLE:
			sq_pushstring(v,_SC("idle"),-1);
		break;
		case SQ_VMSTATE_RUNNING:
			sq_pushstring(v,_SC("running"),-1);
		break;
		case SQ_VMSTATE_SUSPENDED:
			sq_pushstring(v,_SC("suspended"),-1);
		break;
		default:
			return sq_throwerror(v,_SC("internal VM error"));
	}
	return 1;
}
void compile_and_run(HSQUIRRELVM vm, std::istream& in,
                     const std::string& sourcename)
{
  compile_script(vm, in, sourcename);

  SQInteger oldtop = sq_gettop(vm);

  try {
    sq_pushroottable(vm);
    if(SQ_FAILED(sq_call(vm, 1, SQFalse, SQTrue)))
      throw SquirrelError(vm, "Couldn't start script");
  } catch(...) {
    sq_settop(vm, oldtop);
    throw;
  }

  // we can remove the closure in case the script was not suspended
  if(sq_getvmstate(vm) != SQ_VMSTATE_SUSPENDED) {
    sq_settop(vm, oldtop-1);
  }
}
Exemple #6
0
bool SquirrelThread::runScriptByFunctionName(const SQChar * sFunction)
{		
    m_oldTop = sq_gettop(m_thread);

    // Lookup the function in the roottable and put it on the stack
    sq_pushroottable(m_thread);
    sq_pushstring(m_thread, sFunction, -1);
    if (SQ_SUCCEEDED(sq_get(m_thread, -2))) {
        sq_pushroottable(m_thread);

        if (SQ_FAILED(sq_call(m_thread, 1, SQFalse, SQTrue))) {
            sq_settop(m_thread, m_oldTop);
            return false;
        } else {
            if(sq_getvmstate(m_thread) != SQ_VMSTATE_SUSPENDED) 
            { sq_settop(m_thread, m_oldTop); }
        }
    } else {
        sq_settop(m_thread, m_oldTop);
    }

    return true;
}
Exemple #7
0
int main (int argc, char** argv)
{
	ENABLE_LEAK_CHECK();

#if defined(SHELL_PLATFORM_WINDOWS)
	SetConsoleTitle("Squirrel Shell " SHELL_VERSION_STR " (" SHELL_CPUARCH ")");
#else
	stderrIsRedirected = !isatty(2);
#endif

	// Parse command line arguments.
	const char* fileName	= NULL;
	bool		interactive = argc == 1;
	int			firstArg	= 0,
				i;
	bool isDebug = false;
	int debuggerPort = 0;
	for (i = 1; argv[i]; ++i)
	{
		char* arg = argv[i];

		if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
		{
			printf("Squirrel Shell %s for %s on %s (" __DATE__ ")\n"
				   SHELL_VERSION_COPYRIGHT "\n"
				   "\n"
				   "This is free software, and comes WITHOUT ANY WARRANTY; without even the implied\n"
				   "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
				   "General Public License for more details.\n"
				   "\n"
				   "MD5 hash calculation code (c) Colin Plumb\n"
				   "PCRE (c) University of Cambridge\n"
				   "Squirrel (c) Alberto Demichelis\n"
				   "zlib (c) Jean-loup Gailly and Mark Adler\n"
				   "\n"
				   "Usage:\n"
				   "   squirrelsh [options] [script_file] [script_arguments]\n"
				   "\n"
				   "Options:\n"
				   "   -h, --help          Display this text\n"
				   "   -d<PORT>            Enable the debugger, in the specified port\n"
				   "   -i, --interactive   Run shell in interactive mode\n"
				   "                       If script file is specified, it will be executed before\n"
				   "                       entering this mode\n"
				   "   -s, --silent        Do not display error and warning messages\n"
				   "   -v, --version       Display shell version number\n"
				   "\n"
				   "Examples:\n"
				   "   squirrelsh                    Run shell in interactive mode\n"
				   "   squirrelsh foo.nut            Run foo.nut script without arguments\n"
				   "   squirrelsh -i foo.nut 1 2 3   Run foo.nut script with arguments \"1\", \"2\"\n"
				   "                                 and \"3\", and switch into interactive mode\n",
				   SHELL_VERSION_STR,
				   SHELL_PLATFORM,
				   SHELL_CPUARCH);

			return EXIT_SUCCESS;
		}
		else if (!strncmp(arg, "-d", 2))
		{
			// RVF +
			isDebug = true;
			debuggerPort = std::atoi(arg + 2);
			if (debuggerPort == 0)
			{
				printf("No debugger port specified\n");
				return EXIT_FAILURE;
			}
			// RVF -
		}
		else if (!strcmp(arg, "-i") || !strcmp(arg, "--interactive"))
			interactive = true;
		else if (!strcmp(arg, "-v") || !strcmp(arg, "--version"))
		{
			printf("%s\n", SHELL_VERSION_STR);
			return EXIT_SUCCESS;
		}
		else if (!strcmp(arg, "-s") || !strcmp(arg, "--silent"))
			silent = true;
		else
		{
			// First unreserved argument will be treated as script file name.
			fileName = arg;
			firstArg = i;
			break;
		}
	}

	if (!fileName && !interactive)
	{
		PrintError("ERROR: Script file not specified.\n");
		return EXIT_FAILURE;
	}

	// Initialize Squirrel.
	sqvm = sq_open(1024);
	if (!sqvm)
	{
		PrintError("ERROR: Failed to create Squirrel VM.\n");
		return EXIT_FAILURE;
	}

	sqstd_seterrorhandlers(sqvm);

	HSQREMOTEDBG rdbg = nullptr;
	if (isDebug)
	{
		rdbg = sq_rdbg_init(sqvm, debuggerPort, SQTrue);
		sq_enabledebuginfo(sqvm, SQTrue);

		//!! SUSPENDS THE APP UNTIL THE DEBUGGER CLIENT CONNECTS
		scprintf("Waiting for the debugger to connect...\n");
		if (!SQ_SUCCEEDED(sq_rdbg_waitforconnections(rdbg)))
		{
			PrintError("ERROR: Failed to connect to the debugger.\n");
			return EXIT_FAILURE;
		}
		scprintf(_SC("Connected to the debugger\n"));
	}


	//sq_setcompilererrorhandler(sqvm, SquirrelCompileError);

	_RPT0(_CRT_WARN, "--- Squirrel initialized\n");

	// Register some globals.
	SetSqString("SHELL_VERSION", SHELL_VERSION_STR, SQTrue);
	SetSqString("SQUIRREL_VERSION", SQUIRREL_VERSION_SHORT, SQTrue);
	SetSqString("PLATFORM", SHELL_PLATFORM, SQTrue);
	SetSqString("CPU_ARCH", SHELL_CPUARCH, SQTrue);

	// Initialize libraries.
	Init_Base();
	Init_IO();
	Init_File();
	Init_Math();
	Init_Util();
	Init_Hash();
	Init_RegExp();

	_RPT0(_CRT_WARN, "--- Libraries initialized\n");

	// Set up global variables...
	sq_pushroottable(sqvm);

	// RVF +
	// Initialize squirrel std libraries
	//sqstd_register_bloblib(sqvm);
	sqstd_register_iolib(sqvm); // We need this one because of the handy "dofile" function
	sqstd_register_stringfunctions(sqvm); // This registers only some string functions that are useful and don't clash with Squirrel Shell
	// NOTE: Not registering the other libraries, because there are name clashing between Squirrel Shell and SqStdLib
	//sqstd_register_systemlib(sqvm);
	//sqstd_register_mathlib(sqvm);
	//sqstd_register_stringlib(sqvm);
	// RVF -


	// ... number of command line arguments...
	sq_pushstring(sqvm, "__argc", -1);
	sq_pushinteger(sqvm, SQInteger(argc - firstArg));
	if (SQ_FAILED(sq_newslot(sqvm, -3, SQFalse)))
	{
		PrintError("ERROR: Failed to create \"__argc\" integer value.\n");
		Shutdown();
		return EXIT_FAILURE;
	}

	// ... and arguments themselves.
	sq_pushstring(sqvm, "__argv", -1);
	sq_newarray(sqvm, 0);
	for (i = firstArg; argv[i]; ++i)
	{
		sq_pushstring(sqvm, argv[i], -1);
		sq_arrayappend(sqvm, -2);
	}
	if (SQ_FAILED(sq_newslot(sqvm, -3, SQFalse)))
	{
		PrintError("ERROR: Failed to create \"__argv\" array.\n");
		Shutdown();
		return EXIT_FAILURE;
	}
	sq_pop(sqvm, 1);

	// Load and run script.
	SQInteger result = EXIT_SUCCESS;
	if (fileName && LoadScript(fileName))
	{
		sq_pushroottable(sqvm);
		if (SQ_FAILED(sq_call(sqvm, 1, SQTrue, isDebug ? SQTrue : SQFalse)))
		{
			if (!silent)
			{
				const SQChar* errMsg = "Unknown error.";
				sq_getlasterror(sqvm);
				if (sq_gettype(sqvm, -1) == OT_STRING)
					sq_getstring(sqvm, -1, &errMsg);

				PrintError("ERROR: %s\n", errMsg);
			}
			Shutdown();
			return EXIT_FAILURE;
		}

		// Get script execution result.
		if (sq_getvmstate(sqvm) == SQ_VMSTATE_SUSPENDED)
			result = retCode;
		else
		{
			if (sq_gettype(sqvm, -1) == OT_INTEGER)
				sq_getinteger(sqvm, -1, &result);
		}

		// Pop everything except root table.
		sq_settop(sqvm, 1);
	}

	// Enter interactive mode (if necessary).
	if (interactive)
	{
		SQChar cmd[MAX_CMD_LENGTH + 1];
		do
		{
#if defined(SHELL_PLATFORM_WINDOWS)
			GetCurrentDirectory(sizeof(cmd), cmd);
#else
			getcwd(cmd, sizeof(cmd));
#endif
			cmd[sizeof(cmd) - 1] = 0;

			printf("%s> ", ConvPath(cmd, SQFalse));
			fgets(cmd, MAX_CMD_LENGTH, stdin);
			if (SQ_FAILED(sq_compilebuffer(sqvm, cmd, SQInteger(strlen(cmd)), "", SQTrue)))
				continue;

			sq_pushroottable(sqvm);
			if (SQ_FAILED(sq_call(sqvm, 1, SQFalse, SQFalse)) && !silent)
			{
				const SQChar* errMsg = "Unknown error.";
				sq_getlasterror(sqvm);
				if (sq_gettype(sqvm, -1) == OT_STRING)
					sq_getstring(sqvm, -1, &errMsg);

				PrintError("ERROR: %s\n", errMsg);
			}
		} while(sq_getvmstate(sqvm) != SQ_VMSTATE_SUSPENDED);
		result = retCode;
	}

	if (isDebug)
	{
		sq_rdbg_shutdown(rdbg);
	}

	Shutdown();
	return int(result);
}
Exemple #8
0
bool SquirrelThread::loadScript(const String& code, const String& codeName)
{		
    m_oldTop = sq_gettop(m_thread);

    if (code.length() > 7 && 0 == wcsncmp((const wchar_t *)code.characters(), L"//#skip", 7))
        return true;
#if 0
    //int codeLen = wcslen(sCode);
    int codeLen = code.length();
    if (m_codeCache0.size() < (int)codeLen) {
        m_codeCache0.resize(codeLen * 2);
    }

    memset(&m_codeCache0[0], 0, m_codeCache0.size()*sizeof(UChar));

    if (EnumPBSuccess != SquirrelPrecompil(code, m_codeCache0)) {
        notImplemented();
        return false;
    }
    
    OutputDebugStringW((PWCHAR)m_codeCache0.data());

    const SQChar* codeNameString = codeName.charactersWithNullTermination();
    SQRESULT hr = sq_compilebuffer(m_thread, (const SQChar *)m_codeCache0.data(), 
        (int)wcslen((const wchar_t *)m_codeCache0.data()), codeNameString, SQTrue);
    if (SQ_FAILED(hr)) { 
        notImplemented();
        return false;
    }
#endif

#if 1
    String codeNameDummy = codeName;
    const SQChar* codeNameString = codeNameDummy.charactersWithNullTermination();
    SQRESULT hr = sq_compilebuffer(m_thread, (const SQChar *)code.characters(),
        code.length(), codeNameString, SQTrue);
    if (SQ_FAILED(hr)) {
        //raiseExceptionWhenLoadScript(m_thread, codeName, 14);
        //notImplemented();
        return false;
    }
#endif
    // start the script that was previously compiled
    sq_pushroottable(m_thread);
    if (SQ_FAILED(sq_call(m_thread, 1, SQFalse, SQTrue))) {
// 		if (isThrowSqException()) {
// 			raiseExceptionWhenLoadScript(m_thread, codeName, 15);
// 			notImplemented();
// 		}
        sq_pop(m_thread, 1); // pop the compiled closure
        return false;
    } else {
        if (sq_getvmstate(m_thread) != SQ_VMSTATE_IDLE) { 
            //raiseExceptionWhenLoadScript(m_thread, codeName, 16);
            //notImplemented();
            return false; 
        }

        sq_pop(m_thread, 1); // pop the compiled closure
    }
    
    return true;
}
Exemple #9
0
/**
 * スレッドのメイン処理
 * @param diff 経過時間
 * @return スレッド実行終了なら true
 */
bool
Thread::_main(long diff)
{
	// スレッドとして動作できてない場合は即終了
	if (_status == THREAD_NONE) {
		return true;
	}

	if (_status == THREAD_LOADING_FILE) {
		// ファイル読み込み処理
		const char *dataAddr;
		int dataSize;
		if (sqobjCheckFile(_fileHandler, &dataAddr, &dataSize)) {
			_init();
			SQRESULT ret = sqstd_loadmemory(_thread, dataAddr, dataSize, _scriptName.getString(), SQTrue);
			sqobjCloseFile(_fileHandler);
			_fileHandler = NULL;
			if (SQ_SUCCEEDED(ret)) {
				_status = THREAD_RUN;
			} else {
				// exit相当
				printError();
				_exit();
				return true;
			}
		} else {
			// 読み込み完了待ち
			return false;
		}
	} else if (_status == THREAD_LOADING_FUNC) {
		// スクリプト読み込み処理
		_init();
		_func.push(_thread);
		_func.clear();
		_status = THREAD_RUN;
	}

	_currentTick += diff;
	
	// タイムアウト処理
	if (_waitTimeout >= 0) {
		_waitTimeout -= diff;
		if (_waitTimeout < 0) {
			_clearWait();
		}
	}
		
	// スレッド実行
	if (!isWait() && _status == THREAD_RUN) {
		SQRESULT result;
		if (sq_getvmstate(_thread) == SQ_VMSTATE_SUSPENDED) {
			_waitResult.push(_thread);
			_waitResult.clear();
			result = sq_wakeupvm(_thread, SQTrue, SQTrue, SQTrue, SQFalse);
		} else {
			sq_pushroottable(_thread);
			SQInteger n = _args.pushArray(_thread) + 1;
			_args.clear();
			result = sq_call(_thread, n, SQTrue, SQTrue);
		}
		if (SQ_FAILED(result)) {
			// スレッドがエラー終了
			printError();
			_exit();
		} else {
			// 終了コード取得。return/suspend の値が格納される
			_exitCode.getStack(_thread, -1);
			sq_pop(_thread, 1);
			if (sq_getvmstate(_thread) == SQ_VMSTATE_IDLE) {
				// スレッドが終了
				_exit();
			}
		}
	}
	
	return _status == THREAD_NONE;
}