Exemplo n.º 1
0
/*
 * error function
 */
void sq_errorfunc(HSQUIRRELVM v, const SQChar *s,...) {
    char str[4096];
    
	va_list args;
    va_start(args, s);
    vsnprintf(str, 4096, s, args);    
    
    // check if the error was called from emo::onError
    // because error inside onError causes infinite loop.
    bool fromOnError = false;
    SQInteger level = 1;
    SQStackInfos si;
    while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si))) {
        const SQChar *fn = _SC("unknown");
        if (si.funcname) fn = si.funcname;
        level++;
        if (strcmp(fn, "_onError") == 0 || strcmp(fn, "onError") == 0) {
            fromOnError = true;
            break;
        }
    }
    
    if (!fromOnError) {
        callSqFunction_Bool_String(v, EMO_NAMESPACE, EMO_FUNC_ONERROR, str, SQFalse);
    }
    
    LOGE(str);
    va_end(args);
}
Exemplo n.º 2
0
SQInteger SquirrelStd::require(HSQUIRRELVM vm)
{
	SQInteger top = sq_gettop(vm);
	const SQChar *filename;
	SQChar *real_filename;

	sq_getstring(vm, 2, &filename);

	/* Get the script-name of the current file, so we can work relative from it */
	SQStackInfos si;
	sq_stackinfos(vm, 1, &si);
	if (si.source == NULL) {
		DEBUG(misc, 0, "[squirrel] Couldn't detect the script-name of the 'require'-caller; this should never happen!");
		return SQ_ERROR;
	}
	real_filename = scstrdup(si.source);
	/* Keep the dir, remove the rest */
	SQChar *s = scstrrchr(real_filename, PATHSEPCHAR);
	if (s != NULL) {
		/* Keep the PATHSEPCHAR there, remove the rest */
		s++;
		*s = '\0';
	}
	/* And now we concat, so we are relative from the current script
	 * First, we have to make sure we have enough space for the full path */
	real_filename = ReallocT(real_filename, scstrlen(real_filename) + scstrlen(filename) + 1);
	scstrcat(real_filename, filename);
	/* Tars dislike opening files with '/' on Windows.. so convert it to '\\' ;) */
	char *filen = strdup(SQ2OTTD(real_filename));
#if (PATHSEPCHAR != '/')
	for (char *n = filen; *n != '\0'; n++) if (*n == '/') *n = PATHSEPCHAR;
#endif

	bool ret = Squirrel::LoadScript(vm, filen);

	/* Reset the top, so the stack stays correct */
	sq_settop(vm, top);
	free(real_filename);
	free(filen);

	return ret ? 0 : SQ_ERROR;
}
Exemplo n.º 3
0
static SQInteger base_getstackinfos(HSQUIRRELVM v)
{
	SQInteger level;
	SQStackInfos si;
	SQInteger seq = 0;
	const SQChar *name = NULL;
	sq_getinteger(v, -1, &level);
	if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
	{
		const SQChar *fn = _SC("unknown");
		const SQChar *src = _SC("unknown");
		if(si.funcname)fn = si.funcname;
		if(si.source)src = si.source;
		sq_newtable(v);
		sq_pushstring(v, _SC("func"), -1);
		sq_pushstring(v, fn, -1);
		sq_createslot(v, -3);
		sq_pushstring(v, _SC("src"), -1);
		sq_pushstring(v, src, -1);
		sq_createslot(v, -3);
		sq_pushstring(v, _SC("line"), -1);
		sq_pushinteger(v, si.line);
		sq_createslot(v, -3);
		sq_pushstring(v, _SC("locals"), -1);
		sq_newtable(v);
		seq=0;
		while ((name = sq_getlocal(v, level, seq))) {
			sq_pushstring(v, name, -1);
			sq_push(v, -2);
			sq_createslot(v, -4);
			sq_pop(v, 1);
			seq++;
		}
		sq_createslot(v, -3);
		return 1;
	}

	return 0;
}
Exemplo n.º 4
0
void PrintCallStack(HSQUIRRELVM v)
{
	SQPRINTFUNCTION pf = sq_geterrorfunc(v);
	if(pf) {
		SQStackInfos si;
		SQInteger i;
		SQFloat f;
		const SQChar *s;
		SQInteger level=1; //1 is to skip this function that is level 0
		const SQChar *name=0; 
		SQInteger seq=0;
		pf(v,_SC("\nCALLSTACK\n"));
		while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
		{
			const SQChar *fn=_SC("unknown");
			const SQChar *src=_SC("unknown");
			if(si.funcname)fn=si.funcname;
			if(si.source)src=si.source;
			pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line);
			level++;
		}

		return;
		level=0;
		pf(v,_SC("\nLOCALS\n"));

		for(level=0;level<10;level++){
			seq=0;
			while((name = sq_getlocal(v,level,seq)))
			{
				seq++;
				switch(sq_gettype(v,-1))
				{
				case OT_NULL:
					pf(v,_SC("[%s] NULL\n"),name);
					break;
				case OT_INTEGER:
					sq_getinteger(v,-1,&i);
					pf(v,_SC("[%s] %d\n"),name,i);
					break;
				case OT_FLOAT:
					sq_getfloat(v,-1,&f);
					pf(v,_SC("[%s] %.14g\n"),name,f);
					break;
				case OT_USERPOINTER:
					pf(v,_SC("[%s] USERPOINTER\n"),name);
					break;
				case OT_STRING:
					sq_getstring(v,-1,&s);
					pf(v,_SC("[%s] \"%s\"\n"),name,s);
					break;
				case OT_TABLE:
					pf(v,_SC("[%s] TABLE\n"),name);
					break;
				case OT_ARRAY:
					pf(v,_SC("[%s] ARRAY\n"),name);
					break;
				case OT_CLOSURE:
					pf(v,_SC("[%s] CLOSURE\n"),name);
					break;
				case OT_NATIVECLOSURE:
					pf(v,_SC("[%s] NATIVECLOSURE\n"),name);
					break;
				case OT_GENERATOR:
					pf(v,_SC("[%s] GENERATOR\n"),name);
					break;
				case OT_USERDATA:
					pf(v,_SC("[%s] USERDATA\n"),name);
					break;
				case OT_THREAD:
					pf(v,_SC("[%s] THREAD\n"),name);
					break;
				case OT_CLASS:
					pf(v,_SC("[%s] CLASS\n"),name);
					break;
				case OT_INSTANCE:
					pf(v,_SC("[%s] INSTANCE\n"),name);
					break;
				case OT_WEAKREF:
					pf(v,_SC("[%s] WEAKREF\n"),name);
					break;
				case OT_BOOL:{
					sq_getinteger(v,-1,&i);
					pf(v,_SC("[%s] %s\n"),name,i?_SC("true"):_SC("false"));
								}
					break;
				default: ROCKETSQUIRREL_ASSERT(0); break;
				}
				sq_pop(v,1);
			}
		}
	}
}
Exemplo n.º 5
0
SQInteger CSquirrel::PrintErrorFunction(SQVM * pVM)
{
	if(sq_gettop(pVM) >= 1)
	{
		const SQChar * szError = NULL;
		sq_getstring(pVM, 2, &szError);
				
		ErrorInfo info;
		info.strError = szError;

		SQStackInfos si;
		SQInteger level = 1; // 1 is to skip this function that is level 0
		const SQChar *name = 0; 
		SQInteger seq = 0;

		while(SQ_SUCCEEDED(sq_stackinfos(pVM, level, &si)))
		{
			const SQChar * fn = _SC("unknown");
			const SQChar * src = _SC("unknown");
			if(si.funcname) fn = si.funcname;
			if(si.source) src = si.source;
			info.callstack.push_back(ErrorCallstackPair(fn, ErrorSourcePair(src, si.line)));
			level++;
		}

		for(level = 0; level < 10; level++)
		{
			seq = 0;

			while((name = sq_getlocal(pVM, level, seq)))
			{
				seq++;
				CSquirrelArgument arg;
				arg.pushFromStack(pVM, -1);
				info.locals.push_back(ErrorLocalPair(name, arg));
				sq_pop(pVM, 1);
			}
		}

		CSquirrel * pScript = CScriptingManager::GetInstance()->Get(pVM);

		if(pScript)
		{
			CSquirrelArguments arguments;
			CSquirrelArguments tempArray;
			CSquirrelArguments callstackTable;
			CSquirrelArguments localsTable;
			arguments.push(info.strError);

			for(ErrorCallstackList::iterator iter = info.callstack.begin(); iter != info.callstack.end(); iter++)
			{
				String strFunction = iter->first;
				String strSource = iter->second.first;
				int iLine = iter->second.second;
				callstackTable.push(strFunction);
				tempArray.reset();
				tempArray.push(strSource);
				tempArray.push(iLine);
				callstackTable.push(tempArray, true);
			}

			arguments.push(callstackTable, false);

			for(ErrorLocalsList::iterator iter = info.locals.begin(); iter != info.locals.end(); iter++)
			{
				String strName = iter->first;
				CSquirrelArgument arg = iter->second;
				localsTable.push(strName);
				localsTable.push(arg);
			}

			arguments.push(localsTable, false);

			if(CEvents::GetInstance()->Call("scriptError", &arguments, pScript).GetInteger() == 1)
			{
				CLogFile::Printf("<Error (%s)>", info.strError.Get());

				CLogFile::Printf("<Callstack>");
				for(ErrorCallstackList::iterator iter = info.callstack.begin(); iter != info.callstack.end(); iter++)
				{
					String strFunction = iter->first;
					String strSource = iter->second.first;
					int iLine = iter->second.second;
					CLogFile::Printf("<%s (%s, %d)>", strFunction.Get(), strSource.Get(), iLine);
				}
				CLogFile::Printf("</Callstack>");

				CLogFile::Printf("<Locals>");
				for(ErrorLocalsList::iterator iter = info.locals.begin(); iter != info.locals.end(); iter++)
				{
					String strName = iter->first;
					CSquirrelArgument arg = iter->second;
					CLogFile::Printf("<%s (%s)>", strName.Get(), arg.GetTypeString().Get());
				}
				CLogFile::Printf("</Locals>");

				CLogFile::Printf("</Error>");
			}
		}
	}

	return 0;
}
Exemplo n.º 6
0
static void RaiseScriptError(HSQUIRRELVM v, int errorCode)
{
	SQStackInfos si = {0};
	SQInteger level = 1; //1 is to skip this function that is level 0
	const SQChar* name = 0;
	char funcName[15*4] = {0};
	char funcName2[15*4] = {0};
	char* srcA = (char*)malloc(1001);
	SQInteger line = 0;
	SQInteger line2 = 0;
	char* recordParams = (char*)malloc(1001);
	memset(recordParams, 0, 1001);
	memset(srcA, 0, 1001);

	const SQChar* sErr = 0;
	if(!SQ_SUCCEEDED(sq_getstring(v, 2, &sErr)))
		sErr = 0;
	WTF::String sErrA(sErr);

	SQRESULT result = sq_stackinfos(v, level, &si);
	if (SQ_SUCCEEDED(result) || -2 == result) {
		const SQChar* fn = _SC("unknown");
		const SQChar* src = _SC("unknown");
		if(si.funcname) 
			fn = si.funcname;
		if(si.source) 
			src = si.source;

		SQInteger nLen = (SQInteger)wcslen(fn);
		for (SQInteger i = 0; i < nLen && i < 15*4 - 1; ++i)
			funcName[i] = (char)fn[i];

		nLen = (SQInteger)wcslen(src);
		for (SQInteger i = 0; i < nLen && i < 1000; ++i)
			srcA[i] = (char)src[i];
		const int nSaveLen = 20;
		if (nLen > nSaveLen) {
			memmove(srcA, srcA + nLen - nSaveLen, nSaveLen);
			srcA[nSaveLen] = 0;
		}

		line = si.line;

		if (SQ_SUCCEEDED(sq_stackinfos(v, 2, &si))) {
			fn = _SC("unknown");
			src = _SC("unknown");
			if(si.funcname) 
				fn = si.funcname;

			nLen = (SQInteger)wcslen(fn);
			for (SQInteger i = 0; i < nLen && i < 15*4 - 1; ++i)
				funcName2[i] = (char)fn[i];
			line2 = si.line;
		}
		sprintf_s(recordParams, 1000, "%d %s %d %s %d %s %s", errorCode, funcName, line, funcName2, line2, srcA, sErrA.utf8().data());
	}

	OutputDebugStringA(recordParams);

	ReportError(L"script", recordParams, 0);

	//MyRaiseException(recordParams, KKdGetCallStackInfo(v));
	//::RaiseException(EXCEPTION_BREAKPOINT, EXCEPTION_NONCONTINUABLE, 15, (ULONG_PTR *)recordParams);
	free(recordParams);
	free(srcA);
	if (IsDebuggerPresent())
		DebugBreak();
}
static SQInteger squirrel_errorhandler(HSQUIRRELVM v) {
  /* Detect whether this error is just propagating through, or it originated
   * here. To do so, we store the last error we saw in the registry and compare
   * it to the current error. If they are the equal, we've already handled this
   * error.
   *
   * Without this check, we'll call the error handler for every transition
   * between the Squirrel and Wasm VMs. */
  /* TODO(binji): It seems like there should be a better way to handle this */
  SQInteger top = sq_gettop(v);
  WasmBool is_new_error = WASM_TRUE;
  /* get the last error we saw */
  sq_pushregistrytable(v);
  sq_pushstring(v, WASM_LAST_ERROR_NAME, -1);
  if (SQ_SUCCEEDED(sq_get(v, -2))) {
    /* STACK: error registry_table last_error */
    sq_push(v, -3);

    HSQOBJECT last_error;
    HSQOBJECT error;
    if (SQ_SUCCEEDED(sq_getstackobj(v, -1, &error)) &&
        SQ_SUCCEEDED(sq_getstackobj(v, -2, &last_error))) {
      /* we don't want to use cmp here, because it will throw if the values are
       * unordered, and because it performs value equality */
      if (squirrel_objects_are_equal_raw(last_error, error))
        is_new_error = WASM_FALSE;
    }

    /* set the last_error in the registry to the new error. */
    /* STACK: registry_table last_error error */
    sq_remove(v, -2);
    sq_pushstring(v, WASM_LAST_ERROR_NAME, -1);
    sq_push(v, -2);
    /* STACK: registry_table error WASM_LAST_ERROR_NAME error */
    SQRESULT r = sq_set(v, -4);
    WASM_USE(r);
    assert(r == SQ_OK);
  }
  sq_settop(v, top);

  if (is_new_error) {
    const char* error_msg = "unknown";
    if (sq_gettop(v) >= 1)
      sq_getstring(v, -1, &error_msg);
    squirrel_error(v, "error: %s\n", error_msg);
    squirrel_error(v, "callstack:\n");
    SQStackInfos stack_info;
    SQInteger depth;
    for (depth = 1; SQ_SUCCEEDED(sq_stackinfos(v, depth, &stack_info));
         depth++) {
      const char* source = stack_info.source ? stack_info.source : "unknown";
      const char* funcname =
          stack_info.funcname ? stack_info.funcname : "unknown";
      SQInteger line = stack_info.line;
      squirrel_error(v,
                     "  #"_PRINT_INT_FMT
                     ": %s:"_PRINT_INT_FMT
                     ": %s()\n",
                     depth, source, line, funcname);
    }
  }
  return 0;
}
Exemplo n.º 8
0
void sqstd_printcallstack(HSQUIRRELVM v)
{
	SQPRINTFUNCTION pf = sq_getprintfunc(v);
	if(pf) {
		SQStackInfos si;
		SQInteger i;
		SQBool b;
		SQFloat f;
		const SQChar *s;
		SQInteger level=1; //1 is to skip this function that is level 0
		const SQChar *name=0;
		SQInteger seq=0;
		pf(v,_SC("\nCALLSTACK\n"));
		while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
		{
			const SQChar *fn=_SC("unknown");
			const SQChar *src=_SC("unknown");
			if(si.funcname)fn=si.funcname;
			if(si.source) {
				/* We don't want to bother users with absolute paths to all AI files.
				 * Since the path only reaches NoAI code in a formatted string we have
				 * to strip it here. Let's hope nobody installs openttd in a subdirectory
				 * of a directory named /ai/. */
				src = scstrstr(si.source, _SC("\\ai\\"));
				if (!src) src = scstrstr(si.source, _SC("/ai/"));
				if (src) {
					src += 4;
				} else {
					src = si.source;
				}
			}
			pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line);
			level++;
		}
		level=0;
		pf(v,_SC("\nLOCALS\n"));

		for(level=0;level<10;level++){
			seq=0;
			while((name = sq_getlocal(v,level,seq)))
			{
				seq++;
				switch(sq_gettype(v,-1))
				{
				case OT_NULL:
					pf(v,_SC("[%s] NULL\n"),name);
					break;
				case OT_INTEGER:
					sq_getinteger(v,-1,&i);
					pf(v,_SC("[%s] %d\n"),name,i);
					break;
				case OT_FLOAT:
					sq_getfloat(v,-1,&f);
					pf(v,_SC("[%s] %.14g\n"),name,f);
					break;
				case OT_USERPOINTER:
					pf(v,_SC("[%s] USERPOINTER\n"),name);
					break;
				case OT_STRING:
					sq_getstring(v,-1,&s);
					pf(v,_SC("[%s] \"%s\"\n"),name,s);
					break;
				case OT_TABLE:
					pf(v,_SC("[%s] TABLE\n"),name);
					break;
				case OT_ARRAY:
					pf(v,_SC("[%s] ARRAY\n"),name);
					break;
				case OT_CLOSURE:
					pf(v,_SC("[%s] CLOSURE\n"),name);
					break;
				case OT_NATIVECLOSURE:
					pf(v,_SC("[%s] NATIVECLOSURE\n"),name);
					break;
				case OT_GENERATOR:
					pf(v,_SC("[%s] GENERATOR\n"),name);
					break;
				case OT_USERDATA:
					pf(v,_SC("[%s] USERDATA\n"),name);
					break;
				case OT_THREAD:
					pf(v,_SC("[%s] THREAD\n"),name);
					break;
				case OT_CLASS:
					pf(v,_SC("[%s] CLASS\n"),name);
					break;
				case OT_INSTANCE:
					pf(v,_SC("[%s] INSTANCE\n"),name);
					break;
				case OT_WEAKREF:
					pf(v,_SC("[%s] WEAKREF\n"),name);
					break;
				case OT_BOOL:{
					sq_getbool(v,-1,&b);
					pf(v,_SC("[%s] %s\n"),name,b?_SC("true"):_SC("false"));
							 }
					break;
				default: assert(0); break;
				}
				sq_pop(v,1);
			}
		}
	}
}