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 ®)
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 : }
|