diff --git a/src/Actor.cpp b/src/Actor.cpp index 5ab0620f28..2883260c8d 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -1154,9 +1154,8 @@ void Actor::RunCommands( const LuaReference& cmds, const LuaReference *pParamTab pParamTable->PushSelf( L ); // call function with 2 arguments and 0 results - RString sError; - if( !LuaHelpers::RunScriptOnStack(L, sError, 2, 0) ) - LOG->Warn( "Error playing command: %s", sError.c_str() ); + RString Error= "Error playing command: "; + LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); LUA->Release(L); } diff --git a/src/ActorFrame.cpp b/src/ActorFrame.cpp index 3f17a94056..ac614d1fdd 100644 --- a/src/ActorFrame.cpp +++ b/src/ActorFrame.cpp @@ -242,9 +242,8 @@ void ActorFrame::DrawPrimitives() return; } this->PushSelf( L ); - RString sError; - if( !LuaHelpers::RunScriptOnStack(L, sError, 1, 0) ) // 1 arg, 0 results - LOG->Warn( "Error running DrawFunction: %s", sError.c_str() ); + RString Error= "Error running DrawFunction: "; + LuaHelpers::RunScriptOnStack(L, Error, 1, 0, true); // 1 arg, 0 results LUA->Release(L); return; } @@ -302,6 +301,8 @@ static int IdenticalChildrenSingleApplier(lua_State* L) lua_pushvalue(L, lua_upvalueindex(1)); // stack: table, obj, args, func lua_insert(L, 2); // stack: table, func, obj, args int args_count= lua_gettop(L) - 2; + // Not using RunScriptOnStack because we're inside a lua call already and + // we want an error to propagate up. lua_call(L, args_count, LUA_MULTRET); // stack: table, return_values return lua_gettop(L) - 1; } @@ -482,10 +483,8 @@ void ActorFrame::UpdateInternal( float fDeltaTime ) } this->PushSelf( L ); lua_pushnumber( L, fDeltaTime ); - RString sError; - - if( !LuaHelpers::RunScriptOnStack(L, sError, 2, 0) ) // 1 args, 0 results - LOG->Warn( "Error running m_UpdateFunction: %s", sError.c_str() ); + RString Error= "Error running UpdateFunction: "; + LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); // 1 args, 0 results LUA->Release(L); } } diff --git a/src/ActorUtil.cpp b/src/ActorUtil.cpp index 29046e9f19..fd98f53002 100644 --- a/src/ActorUtil.cpp +++ b/src/ActorUtil.cpp @@ -268,12 +268,11 @@ bool ActorUtil::LoadTableFromStackShowErrors( Lua *L ) lua_pushvalue( L, -1 ); func.SetFromStack( L ); - RString sError; - if( !LuaHelpers::RunScriptOnStack(L, sError, 0, 1) ) + RString Error= "Lua runtime error: "; + if( !LuaHelpers::RunScriptOnStack(L, Error, 0, 1, true) ) { lua_pop( L, 1 ); - sError = ssprintf( "Lua runtime error: %s", sError.c_str() ); - Dialog::OK( sError, "LUA_ERROR" ); + Dialog::OK( Error, "LUA_ERROR" ); return false; } @@ -285,9 +284,9 @@ bool ActorUtil::LoadTableFromStackShowErrors( Lua *L ) lua_Debug debug; lua_getinfo( L, ">nS", &debug ); - sError = ssprintf( "%s: must return a table", debug.short_src ); + Error = ssprintf( "%s: must return a table", debug.short_src ); - Dialog::OK( sError, "LUA_ERROR" ); + Dialog::OK( Error, "LUA_ERROR" ); return false; } return true; diff --git a/src/DynamicActorScroller.cpp b/src/DynamicActorScroller.cpp index ba877146de..2cf6ead5af 100644 --- a/src/DynamicActorScroller.cpp +++ b/src/DynamicActorScroller.cpp @@ -44,9 +44,8 @@ void DynamicActorScroller::LoadFromNode( const XNode *pNode ) lua_pushnil( L ); lua_pushnil( L ); - RString sError; - if( !LuaHelpers::RunScriptOnStack(L, sError, 2, 1) ) // 2 args, 1 result - LOG->Warn( "Error running LoadFunction: %s", sError.c_str() ); + RString Error= "Error running LoadFunction: "; + LuaHelpers::RunScriptOnStack(L, Error, 2, 1, true); // 2 args, 1 result m_iNumItems = (int) luaL_checknumber( L, -1 ); lua_pop( L, 1 ); @@ -119,9 +118,8 @@ void DynamicActorScroller::ConfigureActor( Actor *pActor, int iItem ) pActor->PushSelf( L ); LuaHelpers::Push( L, iItem ); - RString sError; - if( !LuaHelpers::RunScriptOnStack(L, sError, 2, 0) ) // 2 args, 0 results - LOG->Warn( "Error running LoadFunction: %s", sError.c_str() ); + RString Error= "Error running LoadFunction: "; + LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); // 2 args, 0 results LUA->Release(L); } diff --git a/src/GameCommand.cpp b/src/GameCommand.cpp index cf399ad2ef..43dde86c2d 100644 --- a/src/GameCommand.cpp +++ b/src/GameCommand.cpp @@ -235,7 +235,10 @@ void GameCommand::LoadOne( const Command& cmd ) else if( sName == "lua" ) { m_LuaFunction.SetFromExpression( sValue ); - ASSERT_M( !m_LuaFunction.IsNil(), ssprintf("\"%s\" evaluated to nil", sValue.c_str()) ); + if(m_LuaFunction.IsNil()) + { + LuaHelpers::ReportScriptError("Lua error in game command: \"" + sValue + "\" evaluated to nil"); + } } else if( sName == "screen" ) @@ -693,7 +696,7 @@ void GameCommand::ApplySelf( const vector &vpns ) const if( m_sStageModifiers != "" ) FOREACH_CONST( PlayerNumber, vpns, pn ) GAMESTATE->ApplyStageModifiers( *pn, m_sStageModifiers ); - if( m_LuaFunction.IsSet() ) + if( m_LuaFunction.IsSet() && !m_LuaFunction.IsNil() ) { Lua *L = LUA->Get(); FOREACH_CONST( PlayerNumber, vpns, pn ) @@ -702,7 +705,8 @@ void GameCommand::ApplySelf( const vector &vpns ) const ASSERT( !lua_isnil(L, -1) ); lua_pushnumber( L, *pn ); // 1st parameter - lua_call( L, 1, 0 ); // call function with 1 argument and 0 results + RString error= "Lua GameCommand error: "; + LuaHelpers::RunScriptOnStack(L, error, 1, 0, true); } LUA->Release(L); } diff --git a/src/LuaExpressionTransform.cpp b/src/LuaExpressionTransform.cpp index f8da8d936e..7ddeb91d56 100644 --- a/src/LuaExpressionTransform.cpp +++ b/src/LuaExpressionTransform.cpp @@ -26,7 +26,8 @@ void LuaExpressionTransform::TransformItemDirect( Actor &a, float fPositionOffse LuaHelpers::Push( L, fPositionOffsetFromCenter ); LuaHelpers::Push( L, iItemIndex ); LuaHelpers::Push( L, iNumItems ); - lua_call( L, 4, 0 ); // 4 args, 0 results + RString error= "Lua error in Transform function: "; + LuaHelpers::RunScriptOnStack(L, error, 4, 0, true); LUA->Release(L); } diff --git a/src/LuaManager.cpp b/src/LuaManager.cpp index 550109848f..ff8b9c0923 100644 --- a/src/LuaManager.cpp +++ b/src/LuaManager.cpp @@ -9,7 +9,9 @@ #include "arch/Dialog/Dialog.h" #include "XmlFile.h" #include "Command.h" +#include "RageLog.h" #include "RageTypes.h" +#include "ScreenManager.h" #include // conversion for lua functions. #include @@ -787,43 +789,75 @@ bool LuaHelpers::LoadScript( Lua *L, const RString &sScript, const RString &sNam return true; } -bool LuaHelpers::RunScriptOnStack( Lua *L, RString &sError, int iArgs, int iReturnValues ) +void LuaHelpers::ReportScriptError(RString const& Error) +{ + size_t line_break_pos= Error.find('\n'); + RString short_error; + if(line_break_pos == RString::npos) + { + short_error= Error; + } + else + { + short_error= Error.substr(0, line_break_pos); + } + SCREENMAN->SystemMessage(short_error); + LOG->Warn(Error.c_str()); +} + +bool LuaHelpers::RunScriptOnStack( Lua *L, RString &Error, int Args, int ReturnValues, bool ReportError ) { lua_pushcfunction( L, GetLuaStack ); // move the error function above the function and params - int iErrFunc = lua_gettop(L) - iArgs - 1; - lua_insert( L, iErrFunc ); + int ErrFunc = lua_gettop(L) - Args - 1; + lua_insert( L, ErrFunc ); // evaluate - int ret = lua_pcall( L, iArgs, iReturnValues, iErrFunc ); + int ret = lua_pcall( L, Args, ReturnValues, ErrFunc ); if( ret ) { - LuaHelpers::Pop( L, sError ); - lua_remove( L, iErrFunc ); - for( int i = 0; i < iReturnValues; ++i ) + if(ReportError) + { + RString lerror; + LuaHelpers::Pop( L, lerror ); + Error+= lerror; + ReportScriptError(Error); + } + else + { + LuaHelpers::Pop( L, Error ); + } + lua_remove( L, ErrFunc ); + for( int i = 0; i < ReturnValues; ++i ) lua_pushnil( L ); return false; } - lua_remove( L, iErrFunc ); + lua_remove( L, ErrFunc ); return true; } -bool LuaHelpers::RunScript( Lua *L, const RString &sScript, const RString &sName, RString &sError, int iArgs, int iReturnValues ) +bool LuaHelpers::RunScript( Lua *L, const RString &Script, const RString &Name, RString &Error, int Args, int ReturnValues, bool ReportError ) { - if( !LoadScript(L, sScript, sName, sError) ) + RString lerror; + if( !LoadScript(L, Script, Name, lerror) ) { - lua_pop( L, iArgs ); - for( int i = 0; i < iReturnValues; ++i ) + Error+= lerror; + if(ReportError) + { + ReportScriptError(Error); + } + lua_pop( L, Args ); + for( int i = 0; i < ReturnValues; ++i ) lua_pushnil( L ); return false; } // move the function above the params - lua_insert( L, lua_gettop(L) - iArgs ); + lua_insert( L, lua_gettop(L) - Args ); - return LuaHelpers::RunScriptOnStack( L, sError, iArgs, iReturnValues ); + return LuaHelpers::RunScriptOnStack( L, Error, Args, ReturnValues, ReportError ); } bool LuaHelpers::RunExpression( Lua *L, const RString &sExpression, const RString &sName ) diff --git a/src/LuaManager.h b/src/LuaManager.h index 1dce0a906b..19ce04a377 100644 --- a/src/LuaManager.h +++ b/src/LuaManager.h @@ -58,15 +58,22 @@ namespace LuaHelpers * and the stack is unchanged. */ bool LoadScript( Lua *L, const RString &sScript, const RString &sName, RString &sError ); + /* Report the error through the log and on the screen. */ + void ReportScriptError(RString const& Error); + /* Run the function with arguments at the top of the stack, with the given * number of arguments. The specified number of return values are left on * the Lua stack. On error, nils are left on the stack, sError is set and - * false is returned. */ - bool RunScriptOnStack( Lua *L, RString &sError, int iArgs = 0, int iReturnValues = 0 ); + * false is returned. + * If ReportError is true, Error should contain the string to prepend + * when reporting. The error is reported through LOG->Warn and + * SCREENMAN->SystemMessage. + */ + bool RunScriptOnStack( Lua *L, RString &Error, int Args = 0, int ReturnValues = 0, bool ReportError = false ); /* LoadScript the given script, and RunScriptOnStack it. * iArgs arguments are at the top of the stack. */ - bool RunScript( Lua *L, const RString &sScript, const RString &sName, RString &sError, int iArgs = 0, int iReturnValues = 0 ); + bool RunScript( Lua *L, const RString &Script, const RString &Name, RString &Error, int Args = 0, int ReturnValues = 0, bool ReportError = false ); /* Run the given expression, returning a single value, and leave the return * value on the stack. On error, push nil. */ diff --git a/src/MenuTimer.cpp b/src/MenuTimer.cpp index 066b593e29..5115544399 100644 --- a/src/MenuTimer.cpp +++ b/src/MenuTimer.cpp @@ -183,9 +183,9 @@ void MenuTimer::SetText( float fSeconds ) LuaHelpers::Push( L, fSeconds ); // call function with 1 argument and 1 result - RString sError; - if( !LuaHelpers::RunScriptOnStack(L, sError, 1, 1) ) - LOG->Warn( "Error running Text%iFormatFunction: %s", i+1, sError.c_str() ); + RString Error= "Error running Text" + (i+1); + Error+= "FormatFunction: "; + LuaHelpers::RunScriptOnStack(L, Error, 1, 1, true); RString sText; LuaHelpers::Pop( L, sText ); diff --git a/src/NoteSkinManager.cpp b/src/NoteSkinManager.cpp index a810dc6708..9194574f50 100644 --- a/src/NoteSkinManager.cpp +++ b/src/NoteSkinManager.cpp @@ -169,11 +169,10 @@ void NoteSkinManager::LoadNoteSkinDataRecursive( const RString &sNoteSkinName_, LOG->Trace( "Load script \"%s\"", sFile.c_str() ); Lua *L = LUA->Get(); - RString sError; + RString Error= "Error running " + sFile + ": "; refScript.PushSelf( L ); - if( !LuaHelpers::RunScript(L, sScript, "@" + sFile, sError, 1, 1) ) + if( !LuaHelpers::RunScript(L, sScript, "@" + sFile, Error, 1, 1, true) ) { - LOG->Trace( "Error running %s: %s", sFile.c_str(), sError.c_str() ); lua_pop( L, 1 ); } else diff --git a/src/OptionRowHandler.cpp b/src/OptionRowHandler.cpp index dcab098562..e24665cddc 100644 --- a/src/OptionRowHandler.cpp +++ b/src/OptionRowHandler.cpp @@ -877,7 +877,8 @@ public: return false; } m_pLuaTable->PushSelf( L ); - lua_call( L, 1, 1 ); // call function with 1 argument and 1 result + RString error= RowName + " \"EnabledForPlayers\": "; + LuaHelpers::RunScriptOnStack(L, error, 1, 1, true); if(!lua_istable(L, -1)) { LOG->Warn("LUA_ERROR: \"%s\" \"EnabledForPlayers\" did not return a table.", RowName.c_str()); @@ -960,7 +961,8 @@ public: // Argument 1 (self): m_pLuaTable->PushSelf( L ); - lua_call( L, 1, 1 ); // call function with 1 argument and 1 result + RString error= "EnabledForPlayers: "; + LuaHelpers::RunScriptOnStack( L, error, 1, 1, true ); m_Def.m_vEnabledForPlayers.clear(); // and fill in with supplied PlayerNumbers below lua_pushnil( L ); @@ -1135,7 +1137,8 @@ public: ASSERT( lua_gettop(L) == 6 ); // vbSelectedOut, m_iLuaTable, function, self, arg, arg - lua_call( L, 3, 0 ); // call function with 3 arguments and 0 results + RString error= "LoadSelections: "; + LuaHelpers::RunScriptOnStack( L, error, 3, 0, true ); ASSERT( lua_gettop(L) == 2 ); lua_pop( L, 1 ); // pop option table @@ -1190,7 +1193,8 @@ public: ASSERT( lua_gettop(L) == 6 ); // vbSelectedOut, m_iLuaTable, function, self, arg, arg - lua_call( L, 3, 0 ); // call function with 3 arguments and 0 results + RString error= "SaveSelections: "; + LuaHelpers::RunScriptOnStack( L, error, 3, 0, true ); ASSERT( lua_gettop(L) == 2 ); lua_pop( L, 1 ); // pop option table @@ -1221,7 +1225,8 @@ public: LuaHelpers::Push(L, pn); // Convert choice to a lua index so it matches up with the Choices table. lua_pushinteger(L, choice+1); - lua_call(L, 3, 1); + RString error= "NotifyOfSelection: "; + LuaHelpers::RunScriptOnStack(L, error, 3, 1, true); if(lua_toboolean(L, -1)) { lua_pop(L, 1); diff --git a/src/PercentageDisplay.cpp b/src/PercentageDisplay.cpp index e932844e3f..28eec2fa7e 100644 --- a/src/PercentageDisplay.cpp +++ b/src/PercentageDisplay.cpp @@ -42,8 +42,15 @@ void PercentageDisplay::LoadFromNode( const XNode* pNode ) const XNode *pChild = pNode->GetChild( "Percent" ); if( pChild == NULL ) - RageException::Throw( "%s: PercentageDisplay: missing the node \"Percent\"", ActorUtil::GetWhere(pNode).c_str() ); - m_textPercent.LoadFromNode( pChild ); + { + LuaHelpers::ReportScriptError(ActorUtil::GetWhere(pNode) + ": PercentageDisplay: missing the node \"Percent\""); + // Make a BitmapText just so we don't crash. + m_textPercent.LoadFromFont(THEME->GetPathF("", "Common Normal")); + } + else + { + m_textPercent.LoadFromNode( pChild ); + } this->AddChild( &m_textPercent ); pChild = pNode->GetChild( "PercentRemainder" ); @@ -154,9 +161,8 @@ void PercentageDisplay::Refresh() m_FormatPercentScore.PushSelf( L ); ASSERT( !lua_isnil(L, -1) ); LuaHelpers::Push( L, fPercentDancePoints ); - RString sError; - if( !LuaHelpers::RunScriptOnStack(L, sError, 1, 1) ) // 1 arg, 1 result - LOG->Warn( "Error running FormatPercentScore: %s", sError.c_str() ); + RString Error= "Error running FormatPercentScore: "; + LuaHelpers::RunScriptOnStack(L, Error, 1, 1, true); // 1 arg, 1 result LuaHelpers::Pop( L, sNumToDisplay ); LUA->Release(L); diff --git a/src/Profile.cpp b/src/Profile.cpp index c6f72606a2..c8b17cd1af 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -846,9 +846,8 @@ void Profile::LoadCustomFunction( RString sDir ) LuaHelpers::Push(L, sDir); // Run it - RString sError; - if (!LuaHelpers::RunScriptOnStack(L, sError, 2, 0)) - LOG->Warn("Error running CustomLoadFunction: %s", sError.c_str()); + RString Error= "Error running CustomLoadFunction: "; + LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); LUA->Release(L); } @@ -1029,9 +1028,8 @@ bool Profile::SaveAllToDir( RString sDir, bool bSignData ) const LuaHelpers::Push(L, sDir); // Run it - RString sError; - if (!LuaHelpers::RunScriptOnStack(L, sError, 2, 0)) - LOG->Warn("Error running CustomSaveFunction: %s", sError.c_str()); + RString Error= "Error running CustomSaveFunction: "; + LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); LUA->Release(L); diff --git a/src/Screen.cpp b/src/Screen.cpp index 758c163732..7e4c0b4f84 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -337,11 +337,8 @@ bool Screen::PassInputToLua(const InputEventPlus& input) { callback->second.PushSelf(L); lua_pushvalue(L, -2); - RString error; - if(!LuaHelpers::RunScriptOnStack(L, error, 1, 1)) - { - LOG->Warn("Error running input callback: %s", error.c_str()); - } + RString error= "Error running input callback: "; + LuaHelpers::RunScriptOnStack(L, error, 1, 1, true); handled= lua_toboolean(L, -1); lua_pop(L, 1); } diff --git a/src/ScreenTextEntry.cpp b/src/ScreenTextEntry.cpp index 9cfd7e5233..79c37c8b37 100644 --- a/src/ScreenTextEntry.cpp +++ b/src/ScreenTextEntry.cpp @@ -376,7 +376,10 @@ void ScreenTextEntry::TextEntrySettings::FromStack( lua_State *L ) lua_getfield( L, iTab, "Question" ); pStr = lua_tostring( L, -1 ); if( pStr == NULL ) - RageException::Throw( "\"Question\" entry is not a string." ); + { + LuaHelpers::ReportScriptError("ScreenTextEntry \"Question\" entry is not a string."); + pStr= ""; + } sQuestion = pStr; lua_settop( L, iTab ); @@ -398,53 +401,34 @@ void ScreenTextEntry::TextEntrySettings::FromStack( lua_State *L ) bPassword = !!lua_toboolean( L, -1 ); lua_settop( L, iTab ); - // and now the hard part, the functions. - // Validate - lua_getfield( L, iTab, "Validate" ); - if( !lua_isfunction( L, -1 ) && !lua_isnil( L, -1 ) ) - RageException::Throw( "\"Validate\" is not a function." ); - Validate.SetFromStack( L ); - lua_settop( L, iTab ); +#define SET_FUNCTION_MEMBER(memname) \ + lua_getfield(L, iTab, #memname); \ + if(lua_isfunction(L, -1)) \ + { \ + memname.SetFromStack(L); \ + } \ + else if(!lua_isnil(L, -1)) \ + { \ + LuaHelpers::ReportScriptError("ScreenTextEntry \"" #memname "\" is not a function."); \ + } \ + lua_settop(L, iTab); - // OnOK - lua_getfield( L, iTab, "OnOK" ); - if( !lua_isfunction( L, -1 ) && !lua_isnil( L, -1 ) ) - RageException::Throw( "\"OnOK\" is not a function." ); - OnOK.SetFromStack( L ); - lua_settop( L, iTab ); - - // OnCancel - lua_getfield( L, iTab, "OnCancel" ); - if( !lua_isfunction( L, -1 ) && !lua_isnil( L, -1 ) ) - RageException::Throw( "\"OnCancel\" is not a function." ); - OnCancel.SetFromStack( L ); - lua_settop( L, iTab ); - - // ValidateAppend - lua_getfield( L, iTab, "ValidateAppend" ); - if( !lua_isfunction( L, -1 ) && !lua_isnil( L, -1 ) ) - RageException::Throw( "\"ValidateAppend\" is not a function." ); - ValidateAppend.SetFromStack( L ); - lua_settop( L, iTab ); - - // FormatAnswerForDisplay - lua_getfield( L, iTab, "FormatAnswerForDisplay" ); - if( !lua_isfunction( L, -1 ) && !lua_isnil( L, -1 ) ) - RageException::Throw( "\"FormatAnswerForDisplay\" is not a function." ); - FormatAnswerForDisplay.SetFromStack( L ); - lua_settop( L, iTab ); + SET_FUNCTION_MEMBER(Validate); + SET_FUNCTION_MEMBER(OnOK); + SET_FUNCTION_MEMBER(OnCancel); + SET_FUNCTION_MEMBER(ValidateAppend); + SET_FUNCTION_MEMBER(FormatAnswerForDisplay); +#undef SET_FUNCTION_MEMBER } // Lua bridges static bool ValidateFromLua( const RString &sAnswer, RString &sErrorOut ) { - Lua *L = LUA->Get(); - - if( g_ValidateFunc.IsNil() ) + if(g_ValidateFunc.IsNil() || !g_ValidateFunc.IsSet()) { - LUA->Release(L); return true; } + Lua *L = LUA->Get(); g_ValidateFunc.PushSelf( L ); @@ -454,69 +438,70 @@ static bool ValidateFromLua( const RString &sAnswer, RString &sErrorOut ) // Argument 2 (error out): lua_pushstring( L, sErrorOut ); - lua_call( L, 2, 2 ); // call function with 2 arguments and 2 results - - if( !lua_isstring(L, -1) ) - RageException::Throw( "\"Validate\" did not return a string." ); - - if( !lua_isboolean(L, -2) ) - RageException::Throw( "\"Validate\" did not return a boolean." ); - - RString sErrorFromLua; - LuaHelpers::Pop( L, sErrorFromLua ); - if( !sErrorFromLua.empty() ) - sErrorOut = sErrorFromLua; - - bool bValidate; - LuaHelpers::Pop( L, bValidate ); + bool valid= false; + RString error= "Lua error in ScreenTextEntry Validate: "; + if(LuaHelpers::RunScriptOnStack(L, error, 2, 2, true)) + { + if(!lua_isstring(L, -1) || !lua_isboolean(L, -2)) + { + LuaHelpers::ReportScriptError("Lua error: ScreenTextEntry Validate did not return 'bool, string'."); + } + else + { + RString ErrorFromLua; + LuaHelpers::Pop( L, ErrorFromLua ); + if( !ErrorFromLua.empty() ) + { + sErrorOut = ErrorFromLua; + } + LuaHelpers::Pop( L, valid ); + } + } + lua_settop(L, 0); LUA->Release(L); - return bValidate; + return valid; } static void OnOKFromLua( const RString &sAnswer ) { - Lua *L = LUA->Get(); - - if( g_OnOKFunc.IsNil() ) + if(g_OnOKFunc.IsNil() || !g_OnOKFunc.IsSet()) { - LUA->Release(L); return; } + Lua *L = LUA->Get(); g_OnOKFunc.PushSelf( L ); // Argument 1 (answer): lua_pushstring( L, sAnswer ); - lua_call( L, 1, 0 ); // call function with 1 argument and 0 results + RString error= "Lua error in ScreenTextEntry OnOK: "; + LuaHelpers::RunScriptOnStack(L, error, 1, 0, true); LUA->Release(L); } static void OnCancelFromLua() { - Lua *L = LUA->Get(); - - if( g_OnCancelFunc.IsNil() ) + if(g_OnCancelFunc.IsNil() || !g_OnCancelFunc.IsSet()) { - LUA->Release(L); return; } + Lua *L = LUA->Get(); g_OnCancelFunc.PushSelf( L ); - lua_call( L, 0, 0 ); // call function with 0 arguments and 0 results + RString error= "Lua error in ScreenTextEntry OnCancel: "; + LuaHelpers::RunScriptOnStack(L, error, 0, 0, true); LUA->Release(L); } static bool ValidateAppendFromLua( const RString &sAnswerBeforeChar, RString &sAppend ) { - Lua *L = LUA->Get(); - - if( g_ValidateAppendFunc.IsNil() ) + if(g_ValidateAppendFunc.IsNil() || !g_ValidateAppendFunc.IsSet()) { - LUA->Release(L); return true; } + Lua *L = LUA->Get(); g_ValidateAppendFunc.PushSelf( L ); @@ -525,41 +510,54 @@ static bool ValidateAppendFromLua( const RString &sAnswerBeforeChar, RString &sA // Argument 2 (Append): lua_pushstring( L, sAppend ); - lua_call( L, 2, 1 ); // call function with 2 arguments and 1 result - if( !lua_isboolean(L, -1) ) - RageException::Throw( "\"ValidateAppend\" did not return a boolean." ); - - bool bAppend; - LuaHelpers::Pop( L, bAppend ); + bool append= false; + RString error= "Lua error in ScreenTextEntry ValidateAppend: "; + if(LuaHelpers::RunScriptOnStack(L, error, 2, 1, true)) + { + if( !lua_isboolean(L, -1) ) + { + LuaHelpers::ReportScriptError("\"ValidateAppend\" did not return a boolean."); + } + else + { + LuaHelpers::Pop( L, append ); + } + } + lua_settop(L, 0); LUA->Release(L); - return bAppend; + return append; } static RString FormatAnswerForDisplayFromLua( const RString &sAnswer ) { - Lua *L = LUA->Get(); - - if( g_FormatAnswerForDisplayFunc.IsNil() ) + if(g_FormatAnswerForDisplayFunc.IsNil() || !g_FormatAnswerForDisplayFunc.IsSet()) { - LUA->Release(L); return sAnswer; } + Lua *L = LUA->Get(); g_FormatAnswerForDisplayFunc.PushSelf( L ); // Argument 1 (Answer): lua_pushstring( L, sAnswer ); - lua_call( L, 1, 1 ); // call function with 1 argument and 1 result - - if( !lua_isstring(L, -1) ) - RageException::Throw( "\"FormatAnswerForDisplay\" did not return a string." ); - - RString sAnswerFromLua; - LuaHelpers::Pop( L, sAnswerFromLua ); + RString answer; + RString error= "Lua error in ScreenTextEntry FormatAnswerForDisplay: "; + if(LuaHelpers::RunScriptOnStack(L, error, 1, 1, true)) + { + if( !lua_isstring(L, -1) ) + { + LuaHelpers::ReportScriptError("\"FormatAnswerForDisplay\" did not return a string."); + } + else + { + LuaHelpers::Pop(L, answer); + } + } + lua_settop(L, 0); LUA->Release(L); - return sAnswerFromLua; + return answer; } void ScreenTextEntry::LoadFromTextEntrySettings( const TextEntrySettings &settings ) diff --git a/src/ScreenWithMenuElements.cpp b/src/ScreenWithMenuElements.cpp index 78f99d77c1..e9304ac070 100644 --- a/src/ScreenWithMenuElements.cpp +++ b/src/ScreenWithMenuElements.cpp @@ -194,17 +194,16 @@ void ScreenWithMenuElements::StartPlayingMusic() */ if( ft == FT_Lua ) { - RString sScript; - RString sError; - if( GetFileContents(m_sPathToMusic, sScript) ) + RString Script; + RString Error= "Lua runtime error: "; + if( GetFileContents(m_sPathToMusic, Script) ) { Lua *L = LUA->Get(); - if( !LuaHelpers::RunScript(L, sScript, "@"+m_sPathToMusic, sError, 0, 1) ) + if( !LuaHelpers::RunScript(L, Script, "@"+m_sPathToMusic, Error, 0, 1, true) ) { LUA->Release( L ); - sError = ssprintf( "Lua runtime error: %s", sError.c_str() ); - Dialog::OK( sError, "LUA_ERROR" ); + Dialog::OK( Error, "LUA_ERROR" ); return; } else diff --git a/src/ThemeMetric.h b/src/ThemeMetric.h index a4073ffa1a..41ac59667e 100644 --- a/src/ThemeMetric.h +++ b/src/ThemeMetric.h @@ -146,9 +146,16 @@ public: // call function with 0 arguments and 1 result m_Value.PushSelf( L ); - lua_call(L, 0, 1); - ASSERT( !lua_isnil(L, -1) ); - LuaHelpers::Pop( L, m_currentValue ); + RString error= m_sGroup + ": " + m_sName + ": "; + LuaHelpers::RunScriptOnStack(L, error, 0, 1, true); + if(!lua_isnil(L, -1)) + { + LuaHelpers::Pop( L, m_currentValue ); + } + else + { + lua_pop(L, 1); + } LUA->Release(L); } diff --git a/src/UnlockManager.cpp b/src/UnlockManager.cpp index cba162190d..ae77104499 100644 --- a/src/UnlockManager.cpp +++ b/src/UnlockManager.cpp @@ -502,7 +502,8 @@ void UnlockManager::Load() current.PushSelf( L ); // call function with 1 argument and 0 results - lua_call( L, 1, 0 ); + RString error= "Lua error in command: "; + LuaHelpers::RunScriptOnStack(L, error, 1, 0, true); if( current.m_bRoulette ) m_RouletteCodes.insert( current.m_sEntryID );