// Handle filename/line number in string void CScriptDebugging::LogPCallError( lua_State* luaVM, const SString& strRes, bool bInitialCall ) { std::vector < SString > vecSplit; strRes.Split( ":", vecSplit ); if ( vecSplit.size() >= 3 ) { // File+line info present SString strFile = vecSplit[ 0 ]; int iLine = atoi( vecSplit[ 1 ] ); // Get the message string (we cannot use vecSplit here as the message itself could contain ':') auto pos = strRes.find ( ':', vecSplit[0].length () + vecSplit[1].length () ) ; SString strMsg = strRes.SubStr ( pos+2 ); if ( iLine == 0 && bInitialCall ) { // Location hint for compiled scripts LogError ( SLuaDebugInfo( strFile, iLine ), "(global scope) %s", *strMsg ); } else LogError ( SLuaDebugInfo( strFile, iLine ), "%s", *strMsg ); } else { // File+line info not present LogError( luaVM, "%s", strRes.c_str () ); } }
// Handle filename/line number in string void CScriptDebugging::LogPCallError( lua_State* luaVM, const SString& strRes, bool bInitialCall ) { std::vector < SString > vecSplit; strRes.Split( ":", vecSplit ); if ( vecSplit.size() >= 3 ) { // File+line info present SString strFile = vecSplit[ 0 ]; int iLine = atoi( vecSplit[ 1 ] ); SString strMsg = vecSplit[2].SubStr( 1 ); if ( iLine == 0 && bInitialCall ) { // Location hint for compiled scripts LogError ( SLuaDebugInfo( strFile, iLine ), "(global scope) %s", *strMsg ); } else LogError ( SLuaDebugInfo( strFile, iLine ), "%s", *strMsg ); } else { // File+line info not present LogError( luaVM, "%s", strRes.c_str () ); } }
void CLuaTimerManager::DoPulse ( CLuaMain* pLuaMain ) { assert ( m_ProcessQueue.empty () ); assert ( !m_pPendingDelete ); assert ( !m_pProcessingTimer ); CTickCount llCurrentTime = CTickCount::Now (); // Use a separate queue to avoid trouble // What kind of problems are we trying to avoid? Doing a copy each frame isn't quite efficient for ( CFastList < CLuaTimer* > ::const_iterator iter = m_TimerList.begin () ; iter != m_TimerList.end () ; ++iter ) m_ProcessQueue.push_back ( *iter ); while ( !m_ProcessQueue.empty () ) { m_pProcessingTimer = m_ProcessQueue.front (); m_ProcessQueue.pop_front (); CTickCount llStartTime = m_pProcessingTimer->GetStartTime (); CTickCount llDelay = m_pProcessingTimer->GetDelay (); unsigned int uiRepeats = m_pProcessingTimer->GetRepeats (); // Is the time up and is not being deleted if ( llCurrentTime >= ( llStartTime + llDelay ) ) { // Set our debug info g_pGame->GetScriptDebugging()->SaveLuaDebugInfo ( m_pProcessingTimer->GetLuaDebugInfo ( ) ); m_pProcessingTimer->ExecuteTimer ( pLuaMain ); // Reset g_pGame->GetScriptDebugging()->SaveLuaDebugInfo ( SLuaDebugInfo() ); // If this is the last repeat, remove if ( uiRepeats == 1 ) { RemoveTimer ( m_pProcessingTimer ); } else { // Decrease repeats if not infinite if ( uiRepeats != 0 ) m_pProcessingTimer->SetRepeats ( uiRepeats - 1 ); m_pProcessingTimer->SetStartTime ( llCurrentTime ); } } // Finally cleanup timer if it was removed during processing if ( m_pPendingDelete ) { assert ( m_pPendingDelete == m_pProcessingTimer ); m_pProcessingTimer = NULL; delete m_pPendingDelete; m_pPendingDelete = NULL; } else m_pProcessingTimer = NULL; } }
// // Get best debug info we possibly can from the relevent lua state // const SLuaDebugInfo& CScriptDebugging::GetLuaDebugInfo( lua_State * luaVM ) { static SLuaDebugInfo scriptDebugInfo; scriptDebugInfo = SLuaDebugInfo(); // Get a VM from somewhere if ( !luaVM && !m_LuaMainStack.empty () ) luaVM = m_LuaMainStack.back ()->GetVM (); // Lua oop found at level 4 added one just in case it somehow ends up deeper due to nested calls for ( int level = 1; level <= 5; level++ ) { lua_Debug debugInfo; if ( luaVM && lua_getstack ( luaVM, level, &debugInfo ) ) { lua_getinfo ( luaVM, "nlS", &debugInfo ); // Lua oop handlers get marked as "C", ignore these as the information we want is further up the stack (typically level 4+) if ( strcmp(debugInfo.source, "=[C]") != 0 ) { // Make sure this function isn't defined in a string (eg: from runcode) if ( debugInfo.source[0] == '@' ) { // Get and store the location of the debug message scriptDebugInfo.strFile = debugInfo.source + 1; scriptDebugInfo.iLine = debugInfo.currentline; scriptDebugInfo.infoType = DEBUG_INFO_FILE_AND_LINE; // Stop here as we now have the best info break; } else { scriptDebugInfo.strShortSrc = debugInfo.short_src; scriptDebugInfo.infoType = DEBUG_INFO_SHORT_SRC; // Try other levels to see if we can get the calling file } } } else { // Use saved info if set if ( m_SavedLuaDebugInfo.infoType != DEBUG_INFO_NONE ) { scriptDebugInfo = m_SavedLuaDebugInfo; } // No point in trying other levels as lua_getstack will fail break; } } return scriptDebugInfo; }