LCOV - code coverage report
Current view: top level - ugbase/bindings/lua - lua_debug.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 3.9 % 181 7
Test Date: 2025-09-21 23:31:46 Functions: 4.8 % 21 1

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2012-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Martin Rupp
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : //////////////////////////////////////////////////////////////////////////////////////////////////////
      34              : //extern libraries
      35              : #include <cassert>
      36              : #include <cstring>
      37              : #include <string>
      38              : #include <stack>
      39              : 
      40              : //////////////////////////////////////////////////////////////////////////////////////////////////////
      41              : // ug libraries
      42              : #include "ug.h"
      43              : #include "lua_util.h"
      44              : #include "common/util/file_util.h"
      45              : #include "bindings_lua.h"
      46              : #include "bridge/bridge.h"
      47              : #include "registry/class_helper.h"
      48              : #ifdef UG_DISC
      49              :         #include "lua_user_data.h"
      50              : #endif
      51              : #include "registry/registry.h"
      52              : #include "info_commands.h"
      53              : #include "lua_debug.h"
      54              : #include "common/profiler/runtime_profile_info.h"
      55              : #include "common/util/string_util.h"
      56              : 
      57              : #ifndef USE_LUAJIT
      58              : extern "C" { // lua default
      59              : #include "externals/lua/lstate.h"
      60              : }
      61              : #else
      62              : #include <lua.h>
      63              : #endif
      64              : //////////////////////////////////////////////////////////////////////////////////////////////////////
      65              : 
      66              : using namespace std;
      67              : 
      68              : namespace ug
      69              : {
      70              : 
      71              : namespace script
      72              : {
      73              : 
      74              : //////////////////////////////////////////////////////////////////////////////////////////////////////
      75              : // globals
      76              : 
      77              : 
      78              : static bool bDebugging = false;
      79              : static int debugMode  = DEBUG_CONTINUE;
      80              : static bool bProfiling = false;
      81              : static std::map<std::string, std::map<int, bool> > breakpoints;
      82              : static debug_return (*pDebugShell)() = NULL;
      83              : static std::string lastsource;
      84              : static int lastline = -1;
      85              : static int currentDepth = -1;
      86              : #ifdef UG_PROFILER
      87              : static bool bStartProfiling=false;
      88              : static bool bEndProfiling=false;
      89              : static int profilingEndDepth=0;
      90              : static std::map<const char*, std::map<int, pRuntimeProfileInfo> >pis;
      91              : static std::stack<pRuntimeProfileInfo> pisStack;
      92              : #endif
      93              : 
      94            0 : bool IsLUADebug()
      95              : {
      96            0 :         return bProfiling;
      97              : }
      98              : int curHookMask = 0;
      99              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     100              : 
     101              : extern stack<string> stkPathes;
     102              : 
     103              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     104              : void LuaCallHook(lua_State *L, lua_Debug *ar);
     105              : 
     106              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     107              : 
     108            0 : void FinalizeLUADebug()
     109              : {
     110              :         breakpoints.clear();
     111              : #ifdef UG_PROFILER
     112              :         pis.clear();
     113              : #endif
     114              :         lastsource.clear();
     115            0 : }
     116              : 
     117            0 : int SetDebugShell(debug_return (*s)())
     118              : {
     119            0 :         pDebugShell=s;
     120            0 :         return 0;
     121              : }
     122              : 
     123            0 : void CheckHook()
     124              : {
     125            0 :         if(bDebugging == false && bProfiling == false)
     126              :         {
     127            0 :                 if(curHookMask)
     128              :                 {
     129            0 :                         lua_sethook (GetDefaultLuaState(), NULL, 0, 0);
     130            0 :                         curHookMask=0;
     131              :                 }
     132              :         }
     133              :         else
     134              :         {
     135              :                 const int DEBUG_HOOK_MASK = LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE;
     136              :                 const int PROFILER_HOOK_MASK = LUA_MASKCALL | LUA_MASKRET;
     137              :                 
     138            0 :                 if(bDebugging && curHookMask != DEBUG_HOOK_MASK)
     139              :                 {
     140            0 :                         lua_sethook (GetDefaultLuaState(), LuaCallHook, DEBUG_HOOK_MASK, 0);
     141            0 :                         curHookMask = DEBUG_HOOK_MASK;
     142              :                 }
     143            0 :                 else if(bProfiling && curHookMask != PROFILER_HOOK_MASK)
     144              :                 {
     145            0 :                         lua_sethook (GetDefaultLuaState(), LuaCallHook, PROFILER_HOOK_MASK, 0);
     146            0 :                         curHookMask = PROFILER_HOOK_MASK;
     147              :                 }
     148              :         }
     149              : 
     150            0 : }
     151              : 
     152              : 
     153            0 : void AddBreakpoint(const char*source, int line)
     154              : {
     155            0 :         if(pDebugShell==NULL)
     156              :         {
     157              :                 UG_LOG("No Debug Shell set!\n");
     158            0 :                 return;
     159              :         }
     160              :         const char *s=NULL;
     161              : 
     162            0 :         string relativeFilename=source;
     163              :         string absoluteFilename;
     164              : 
     165            0 :         if(GetAbsoluteUGScriptFilename(relativeFilename, absoluteFilename))
     166              :         {
     167            0 :                 breakpoints[s][line]=true;
     168            0 :                 bDebugging = true;
     169            0 :                 CheckHook();
     170            0 :                 UG_LOG("breakpoint at " << s << ":" << line << "\n")
     171              :         }
     172              :         else
     173              :         {
     174            0 :                 UG_LOG("file " << s << " not found\n");
     175              :         }
     176              : 
     177              : }
     178              : 
     179              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     180            0 : void PrintBreakpoints()
     181              : {
     182              :         std::map<std::string, std::map<int, bool> >::iterator it1;
     183              :         std::map<int, bool>::iterator it2;
     184            0 :         for(it1 = breakpoints.begin(); it1 != breakpoints.end(); ++it1)
     185              :         {
     186              :                 std::map<int, bool> &m = (*it1).second;
     187            0 :                 for(it2 = m.begin(); it2 != m.end(); ++it2)
     188              :                 {
     189            0 :                         UG_LOG((*it1).first << ":" << (*it2).first << ((*it2).second?" enabled":" disabled") << "\n")
     190              :                 }
     191              :         }
     192            0 : }
     193              : 
     194            0 : void DebugHold()
     195              : {
     196              :         lastsource="";
     197            0 :         debugMode=DEBUG_STEP;
     198            0 :         bDebugging=true;
     199            0 :         CheckHook();
     200            0 : }
     201              : 
     202              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     203            0 : void breakpoint()
     204              : {
     205            0 :         if(pDebugShell==NULL)
     206              :         {
     207              :                 UG_LOG("Breakpoint reached, no Debug Shell set.\n");
     208            0 :                 return;
     209              :         }
     210            0 :         debug_return r=pDebugShell();
     211            0 :         if(r == DEBUG_EXIT)
     212            0 :                 UGForceExit();
     213            0 :         else if(r == DEBUG_CONTINUE)
     214              :         {
     215            0 :                 debugMode = DEBUG_CONTINUE;
     216            0 :                 bDebugging = breakpoints.size() > 0;
     217            0 :                 CheckHook();
     218            0 :                 return;
     219              :         }
     220            0 :         else if(r == DEBUG_NEXT || r == DEBUG_STEP || r == DEBUG_FINISH)
     221              :         {
     222            0 :                 debugMode=r;
     223            0 :                 bDebugging=true;
     224            0 :                 CheckHook();
     225            0 :                 return;
     226              :         }
     227              : }
     228              : 
     229            0 : int getDepth()
     230              : {
     231            0 :         lua_State *L = GetDefaultLuaState();
     232              :         int depth=0;
     233              :         lua_Debug entry;
     234            0 :         for(int i = 0; lua_getstack(L, i, &entry); i++)
     235              :         {
     236            0 :                 lua_getinfo(L, "Sln", &entry);
     237            0 :                 if(entry.currentline >= 0)
     238            0 :                         depth++;
     239              :         }
     240            0 :         return depth;
     241              : }
     242              : 
     243            0 : void breakpoint_in_script()
     244              : {
     245              :         lua_Debug entry;
     246            0 :         lua_State *L = GetDefaultLuaState();
     247            0 :         currentDepth =getDepth();
     248            0 :         for(int depth = 0; lua_getstack(L, depth, &entry); depth++)
     249              :         {
     250            0 :                 lua_getinfo(L, "Sln", &entry);
     251            0 :                 if(entry.currentline >= 0)
     252              :                 {
     253            0 :                         lastsource = entry.source+1;
     254            0 :                         lastline = entry.currentline;
     255            0 :                         breakpoint();
     256            0 :                         return;
     257              :                 }
     258              :         }
     259              : 
     260            0 :         breakpoint();
     261              : }
     262              : 
     263              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     264            0 : void luaDebug(lua_State *L, const char *source, int line)
     265              : {
     266            0 :         if(source == NULL || line < 0 || pDebugShell==NULL) return;
     267            0 :         if(source[0]=='@') source++;
     268              : 
     269              :         bool bfound=false;
     270            0 :         if(debugMode == DEBUG_NEXT || debugMode == DEBUG_FINISH)
     271              :         {
     272            0 :                 int d = getDepth();
     273            0 :                 if( ((debugMode == DEBUG_NEXT && d <= currentDepth)
     274            0 :                                 || (debugMode == DEBUG_FINISH && d < currentDepth))
     275            0 :                                 && (lastsource.compare(source)==0 && lastline == line) == false)
     276              :                 {
     277              :                         lastsource = source;
     278            0 :                         lastline = line;
     279            0 :                         currentDepth = d;
     280              :                         bfound =true;
     281              :                 }
     282              :         }
     283            0 :         else if(debugMode == DEBUG_STEP)
     284              :         {
     285            0 :                 if((lastsource.compare(source)==0 && lastline == line) == false)
     286              :                 {
     287              :                         lastsource = source;
     288            0 :                         lastline = line;
     289            0 :                         currentDepth = getDepth();
     290              :                         bfound =true;
     291              :                 }
     292              :         }
     293              : 
     294              : 
     295            0 :         if(!bfound && breakpoints.size() > 0)
     296              :         {
     297              :                 lua_Debug entry;
     298            0 :                 for(int depth = 0; lua_getstack(L, depth, &entry); depth++)
     299              :                 {
     300            0 :                         lua_getinfo(L, "Sln", &entry);
     301            0 :                         if(entry.currentline >= 0)
     302              :                         {
     303            0 :                                 std::map<int, bool> &m = breakpoints[entry.source+1];
     304              :                                 std::map<int, bool>::iterator it = m.find(entry.currentline);
     305              :                                 //UG_LOG(entry.source+1 << ":" << entry.currentline << "\n");
     306            0 :                                 if(it != m.end() && (*it).second == true &&
     307            0 :                                                 (lastline != entry.currentline || lastsource.compare(entry.source+1)!=0))
     308              :                                 {
     309            0 :                                         lastsource = entry.source+1;
     310            0 :                                         lastline = entry.currentline;
     311              :                                         bfound=true;
     312            0 :                                         currentDepth = getDepth();
     313              :                                         break;
     314              :                                 }
     315              :                         }
     316              :                         if(bfound) break;
     317              :                 }
     318              : 
     319              : 
     320              :         }
     321              : 
     322            0 :         if(!bfound) return;
     323              : 
     324            0 :         breakpoint();
     325              : }
     326              : 
     327              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     328            0 : void LuaCallHook(lua_State *L, lua_Debug *ar)
     329              : {
     330              : #if 0
     331              :         {
     332              :         UG_LOG("------------------------\n");
     333              :         {
     334              :                 if(ar->event == LUA_HOOKCALL) UG_LOG("HOOKCALL\n");
     335              :                 if(ar->event == LUA_HOOKLINE) UG_LOG("HOOKLINE\n");
     336              :                 if(ar->event == LUA_HOOKRET) UG_LOG("HOOKRET\n");
     337              :             lua_Debug entry;
     338              :             for(int depth = 0; lua_getstack(L, depth, &entry); depth++)
     339              :                 {
     340              :                 int status = lua_getinfo(L, "Sln", &entry);
     341              :                 //if(entry.currentline <0) continue;
     342              :                 if(entry.short_src && entry.currentline>0)
     343              :                         UG_LOG(entry.short_src << ":" << entry.currentline);
     344              :                 if(entry.what)
     345              :                 {
     346              :                         UG_LOG(" what=" << entry.what);
     347              :                 }
     348              :                 if(entry.name)
     349              :                 {
     350              :                         UG_LOG(" entry.name=" << entry.name);
     351              :                 }
     352              :                 UG_LOG("\n");
     353              :             }
     354              :         }
     355              :         }
     356              : #endif
     357            0 :         if(bDebugging)
     358              :         {                       
     359            0 :                 if(ar->event == LUA_HOOKCALL || ar->event ==LUA_HOOKLINE)
     360              :                 {
     361              :                         
     362            0 :                         lua_getinfo(L, "Sln", ar);
     363              :                         const char *source = "unknown";
     364              :                         int line = 0;
     365            0 :                         if(ar->currentline < 0)
     366              :                         {
     367              :                                 lua_Debug entry;
     368            0 :                                 for(int depth = 0; lua_getstack(L, depth, &entry); depth++)
     369              :                                 {
     370            0 :                                         lua_getinfo(L, "Sln", &entry);
     371            0 :                                         if(entry.currentline >= 0)
     372              :                                         {
     373            0 :                                                 source = entry.source;
     374              :                                                 line = entry.currentline;
     375            0 :                                                 break;
     376              :                                         }
     377              :                                 }
     378              :                         }
     379              :                         else
     380              :                         {
     381            0 :                                 source = ar->source;
     382              :                                 line = ar->currentline;
     383              :                         }
     384            0 :                         luaDebug(L, source, line);
     385              :                 }
     386              :         }
     387              : #if UG_PROFILER 
     388              :         const static bool bDebugLuaProfiler = false;
     389              : 
     390              :         // Lua profiling is done the following way:
     391              :         // We only want to profile those lines, that actually do something and not
     392              :         // all lines, since they may be in inner loops and cause significant overhead.
     393              :         // Therefore, we only react on lua-calls and returns. In addition, we don't
     394              :         // want to profile lua-callbacks that are invoked from the C++ code, since
     395              :         // those are commonly used in the very inner loops - this would be to much
     396              :         // profiling overhead.
     397              :         //
     398              :         // NOTE: we currently use a map with const char* identifier. This will
     399              :         //               only work if lua does not change the strings in between. It this
     400              :         //               is observed we must change that to std::string
     401              :         if(bProfiling)
     402              :         {       
     403              :                 if(ar->event == LUA_HOOKLINE || ar->event == LUA_HOOKCOUNT){
     404              :                         return; // nothing to do: but may be enabled for debugging
     405              :                 }
     406              : 
     407              :                 // profileDepthInCcall is used to distinguish where a function call/return
     408              :                 // is executed. We only want to profile those calls that are done within
     409              :                 // lua, but not from C++ to Lua. If a call is to a C-function, the
     410              :                 // depth will be initialized with 1 and no profiling is performed until
     411              :                 // the depth is back to zero (i.e. when the C-call returns). It may however
     412              :                 // happen, that several events happen, since lua code is executed from
     413              :                 // C. In order to detect, if the hook-return is due to a lua-return or
     414              :                 // from the initalizing C-call, we count the depth.
     415              :                 static int profileDepthInCcall = 0;
     416              : 
     417              :                 // check if within a c-call
     418              :                 if(profileDepthInCcall != 0)
     419              :                 {               
     420              :                         // if another call, this must be inside lua but invoked from c
     421              :                         if(ar->event == LUA_HOOKCALL) {
     422              :                                 profileDepthInCcall++; return;
     423              :                         }
     424              :                         // if a return, reduce depth. If depth == 0, we also have to
     425              :                         // finish the current profile node, since this must be the return
     426              :                         // from the original c-call
     427              :                         else if(ar->event == LUA_HOOKRET || ar->event == LUA_HOOKTAILRET){
     428              :                                 if(--profileDepthInCcall != 0) return;
     429              :                         }
     430              :                         else{
     431              :                                 UG_LOG("WARNING: LuaProfiling: Wrong hook event passed (" << ar->event << ")\n");
     432              :                         }
     433              :                 }
     434              :                 
     435              :                 // if a call is given, but end profiling requested, we can leave
     436              :                 if(bEndProfiling == true && ar->event == LUA_HOOKCALL)
     437              :                         return;
     438              : 
     439              :                 // fill information about the event
     440              :                 lua_getinfo(L, "Sln", ar);
     441              : 
     442              :                 // this is the call/ret invoked, however not the called !
     443              :                 if(bDebugLuaProfiler){
     444              :                         std::string type = "call";
     445              :                         if(ar->event == LUA_HOOKRET) type = "ret ";
     446              :                         else if(ar->event == LUA_HOOKTAILRET) type = "tailret ";
     447              :                         UG_LOG(repeat(' ', pisStack.size()) << "## lua profile: source: "<<ar->source<<", line: "
     448              :                                <<ar->currentline<<" "<<type<<" " << ar->what);
     449              :                 }
     450              : 
     451              : 
     452              :                 // we are only interested in 'Lua' or 'C' call/return events
     453              :                 if(ar->what[0] != 'L' && ar->what[0] != 'C' && ar->what[0] != 't')
     454              :                 {
     455              :                         if(bDebugLuaProfiler){ UG_LOG("\n"); }
     456              :                         return;
     457              :                 }
     458              : 
     459              :                 // we get the debug info of the calling file and line
     460              :                 lua_Debug entry;
     461              :                 if(lua_getstack(L, 1, &entry) == 0)
     462              :                         UG_THROW("LuaProfiling: Cannot get debug info from stack.")
     463              :                 if(lua_getinfo(L, "Sln", &entry) == 0)
     464              :                         UG_THROW("LuaProfiling: Cannot read debug info.")
     465              : 
     466              :                 // get source an line of the event
     467              :                 const char* source = entry.source;
     468              :                 int line = entry.currentline;
     469              : 
     470              :                 if(bDebugLuaProfiler){
     471              :                         std::string type = "call";
     472              :                         if(entry.event == LUA_HOOKRET) type = "ret ";
     473              :                         else if(entry.event == LUA_HOOKTAILRET) type = "tailret ";
     474              :                         UG_LOG(",  corr: source: "<<source<<", line: "<<line<<" "<<type<<" " << entry.what << "\n");
     475              :                 }
     476              : 
     477              : 
     478              : 
     479              : 
     480              :                 // may still be unavailable, then we ignore this issue
     481              :                 //if(line < 0) return;
     482              : 
     483              :                 // a call
     484              :                 //UG_LOG("ar->event  = " << ar->event  << endl)
     485              :                 if(ar->event == LUA_HOOKCALL)
     486              :                 {                               
     487              :                          // get info from map
     488              :                          pRuntimeProfileInfo &pi = pis[source][line];
     489              : 
     490              :                          // if not yet initialized, create new node
     491              :                          if(pi == NULL){
     492              :                                  char buf[1024];
     493              :                                  if(source[0]=='@') source++;
     494              :                                  if(strncmp(source, "./../scripts/", 13)==0)
     495              :                                          sprintf(buf, "!%s:%d ", source+13, line);
     496              :                                  else
     497              :                                          sprintf(buf, "@%s:%d ", source, line);
     498              : 
     499              :                                  pi = new RuntimeProfileInfo(buf, true, "lua", false, source, true, line);
     500              :                          }
     501              : 
     502              :                          if(bDebugLuaProfiler){UG_LOG(repeat(' ', pisStack.size()) << "PUSH " << *pi << "\n");}
     503              :                          // start profiling
     504              :                          pi->beginNode();
     505              :                          pisStack.push(pi);
     506              : 
     507              :                          // if this is a call to C, we disable all successive call-event
     508              :                          // tracings until this call returns. This is done by setting
     509              :                          // profileDepthInCcall > 1. The only exception is the call to
     510              :                          // 'ug_load_script', that is a c-call but should be profiled
     511              :                          //     also internally since it just loads other lua-scripts
     512              :                          if(ar->name != NULL && strcmp(ar->name, "ug_load_script") == 0)
     513              :                                  return;
     514              :                          if(ar->what[0] == 'C')
     515              :                                          profileDepthInCcall = 1;
     516              :                 }
     517              : 
     518              :                 // a return
     519              :                 else if(ar->event == LUA_HOOKRET || ar->event == LUA_HOOKTAILRET)
     520              :                 {               
     521              :                          // if only starting the profiling, do not react on returns
     522              :                          if(bStartProfiling) { bStartProfiling = false; return; }
     523              : 
     524              :                          // if profiling is to be ended, so something (what?)
     525              :                          if(profilingEndDepth > 0) {
     526              :                                  profilingEndDepth--;
     527              :                          }
     528              :                          else
     529              :                          {
     530              :                                  // get profile node
     531              :                                  pRuntimeProfileInfo pi;
     532              :                                  if(line < 0 || ar->event == LUA_HOOKTAILRET)
     533              :                                          pi = pisStack.top();
     534              :                                  else
     535              :                                  {
     536              :                                          pRuntimeProfileInfo p2 = pis[source][line];
     537              :                                          pi = pisStack.top();
     538              :                                          if(pi != p2) {UG_LOG("\nPIs not matching.\n"); UG_ASSERT(0, "lua debug bug."); }
     539              :                                  }
     540              :                                  pisStack.pop();
     541              : 
     542              :                                  // release the node
     543              :                                  // if this part causes trouble, the std::map should be used
     544              :                                  // with std::string identifier, since I don't know if the
     545              :                                  // lua const char* are persistent
     546              :                                  pi->endNode();
     547              :                                  if(bDebugLuaProfiler){UG_LOG(repeat(' ', pisStack.size()) << "POP  " << *pi << "\n"); }
     548              :                                  // if we are ending profiling we have to check if we are in
     549              :                                  // a c call
     550              :                                  if(bEndProfiling && profileDepthInCcall == 0)
     551              :                                  {
     552              :                                          UG_LOG("Profiling ended.\n");
     553              :                                          bProfiling=false;
     554              :                                          bEndProfiling=false;
     555              :                                          CheckHook();
     556              :                                  }
     557              :                          }
     558              :                 }
     559              :                 else{
     560              :                         UG_ASSERT(0, "wrong event already parsed: " << ar->event);
     561              :                 }
     562              : 
     563              :         }
     564              : #endif
     565              : 
     566            0 : }
     567              : 
     568              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     569            0 : void ProfileLUA(bool b)
     570              : {
     571              : #ifdef UG_PROFILER
     572              :         if(bProfiling==false && b==true)
     573              :         {       
     574              :                 bStartProfiling=true;
     575              :                 bEndProfiling=false;
     576              :                 bProfiling=true;
     577              :                 CheckHook();
     578              :                 
     579              :         }
     580              :         else if(bProfiling == true && b==false)
     581              :         {
     582              :                 bEndProfiling=true;
     583              :         }
     584              : #else
     585              :         UG_LOG("No profiler available.\n");
     586              : #endif
     587            0 : }
     588              : 
     589            0 : void DebugList()
     590              : {
     591              :         lua_Debug entry;
     592            0 :         int depth=getDepth();
     593            0 :         lua_State *L = GetDefaultLuaState();
     594            0 :         for(int i = 0; lua_getstack(L, i, &entry); i++)
     595              :         {
     596            0 :                 lua_getinfo(L, "Sln", &entry);
     597            0 :                 if(entry.currentline <0) continue;
     598            0 :                 if(depth==currentDepth)
     599              :                 {
     600            0 :                         lastsource = entry.source+1;
     601            0 :                         lastline = entry.currentline;
     602            0 :                         UG_LOG(entry.source+1 << ":" << entry.currentline << "\n");
     603            0 :                         if(entry.currentline-3<0)
     604            0 :                                 {UG_LOG(GetFileLines(entry.source+1, 0, entry.currentline+5, true) << "\n");}
     605              :                         else
     606            0 :                                 {UG_LOG(GetFileLines(entry.source+1, entry.currentline-3, entry.currentline+5, true) << "\n");}
     607              :                         UG_LOG("\n");
     608              :                 }
     609            0 :                 depth--;
     610              :         }
     611              :         // todo
     612            0 : }
     613            0 : void DebugBacktrace(int fromLevel)
     614              : {
     615            0 :         ug::bridge::LuaStackTrace(fromLevel);
     616            0 : }
     617              : 
     618              : 
     619              : 
     620            0 : void UpdateDepth()
     621              : {
     622              :         lua_Debug entry;
     623            0 :         int depth=getDepth();
     624            0 :         lua_State *L = GetDefaultLuaState();
     625            0 :         for(int i = 0; lua_getstack(L, i, &entry); i++)
     626              :         {
     627            0 :                 lua_getinfo(L, "Sln", &entry);
     628            0 :                 if(entry.currentline <0) continue;
     629            0 :                 if(depth==currentDepth)
     630              :                 {
     631            0 :                         lastsource = entry.source+1;
     632            0 :                         lastline = entry.currentline;
     633            0 :                         UG_LOG(entry.source+1 << ":" << entry.currentline);
     634            0 :                         UG_LOG(" " << GetFileLine(entry.short_src, entry.currentline));
     635              :                         UG_LOG("\n");
     636              :                 }
     637            0 :                 depth--;
     638              :         }
     639            0 : }
     640            0 : void DebugUp()
     641              : {
     642            0 :         if(currentDepth>0)
     643              :         {
     644            0 :                 currentDepth--;
     645            0 :                 UpdateDepth();
     646              :         }
     647              :         else
     648              :                 {UG_LOG("already at base level.\n");}
     649            0 : }
     650            0 : void DebugDown()
     651              : {
     652            0 :         if(currentDepth < getDepth())
     653              :         {
     654            0 :                 currentDepth++;
     655            0 :                 UpdateDepth();
     656              :         }
     657              :         else
     658              :         {UG_LOG("already at max level.\n");}
     659            0 : }
     660              : 
     661              : //////////////////////////////////////////////////////////////////////////////////////////////////////
     662            1 : bool RegisterLuaDebug(ug::bridge::Registry &reg)
     663              : {
     664            2 :         reg.add_function("breakpoint", &AddBreakpoint, "/ug4/lua");
     665            2 :         reg.add_function("breakpoint", &breakpoint_in_script, "/ug4/lua");
     666            2 :         reg.add_function("print_breakpoints", &PrintBreakpoints, "/ug4/lua");
     667            2 :         reg.add_function("DebugBacktrace", &DebugBacktrace, "/ug4/lua");
     668              : 
     669            2 :         reg.add_function("ProfileLUA", &ProfileLUA, "/ug4/lua");
     670            1 :         return true;
     671              : }
     672              : 
     673              : 
     674              : 
     675            0 : void SetLuaDebug(lua_State* L, string id)
     676              : {
     677              :         string name = id;
     678              :         string rest = name;
     679            0 :         string pre = "";
     680              : 
     681              :         while(1)
     682              :         {
     683            0 :                 int dotPos = rest.find(".");
     684            0 :                 if(dotPos == -1) break;
     685            0 :                 string sub = rest.substr(0, dotPos);
     686            0 :                 rest = rest.substr(dotPos+1, rest.size());
     687              : 
     688              :                 //ug::bridge::SetLuaNamespace(pre+sub+".group", pre+sub+".*");
     689              :                 //string p = std::string("") + "debugID." + pre+sub + " = " + "debugID." + pre+sub + " or {}\n" + "function debugID." + pre+sub + ".set_group_level(level) GetLogAssistant():set_debug_level(\"" + pre+sub + ".*\", level) end\n";
     690            0 :                 string p = std::string("") + "debugID." + pre+sub + " = " + "debugID." + pre+sub + " or {}\n" + "debugID." + pre+sub + ".id = \"" + pre+sub + "\"\n";
     691              :                 //UG_LOGN(p);
     692            0 :                 script::ParseAndExecuteBuffer(p.c_str(), "SetLuaDebug");
     693            0 :                 pre = pre+sub+".";
     694              : 
     695            0 :         }
     696              : 
     697              :         //ug::bridge::SetLuaNamespace(pre+rest+".id", pre+rest);
     698              : //      string p = std::string("") + "debugID." + name + " = " + "debugID." + name + " or {}\n" + "function debugID." + name + ".set_level(level) GetLogAssistant():set_debug_level(\"" + name + "\", level) end\n";
     699            0 :         string p = std::string("") + "debugID." + name + " = " + "debugID." + name + " or {}\n" + "debugID." + name + ".id = \"" + name + "\"\n";
     700              :         //UG_LOGN(p);
     701            0 :         script::ParseAndExecuteBuffer(p.c_str(), "SetLuaDebug");
     702            0 : }
     703              : 
     704            0 : void SetLuaDebugIDs(lua_State* L)
     705              : {
     706            0 :         script::ParseAndExecuteBuffer(
     707              :                         "debugID = {}\n"
     708              :                         "function SetDebugLevel(did, level)\n"
     709              :                         "if(did == nil) then\n"
     710              :                         "print(\"ERROR: Debug Node not existing. Perhaps you did not include the plugin?\")\n"
     711              :                         "DebugBacktrace(0)"
     712              :                         "else GetLogAssistant():set_debug_level((did.id) ..\"*\", level) end end",
     713              :                         "SetLuaDebugIDs");
     714            0 :         const vector<string> &s = DebugIDManager::instance().get_registered_debug_IDs_arr();
     715            0 :         for(size_t i=0; i<s.size(); i++)
     716            0 :                 SetLuaDebug(L, s[i]);
     717            0 : }
     718              : 
     719              : 
     720              : }
     721              : }
        

Generated by: LCOV version 2.0-1