The Battle for Wesnoth  1.15.0-dev
debugger.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2018 by Yurii Chernyi <terraninfo@terraninfo.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Formula debugger - implementation
18  * */
19 
20 
21 #include "formula/debugger.hpp"
22 #include "formula/formula.hpp"
23 #include "formula/function.hpp"
24 #include "game_display.hpp"
25 #include "log.hpp"
27 #include "gui/widgets/settings.hpp"
28 
29 static lg::log_domain log_formula_debugger("scripting/formula/debug");
30 #define DBG_FDB LOG_STREAM(debug, log_formula_debugger)
31 #define LOG_FDB LOG_STREAM(info, log_formula_debugger)
32 #define WRN_FDB LOG_STREAM(warn, log_formula_debugger)
33 #define ERR_FDB LOG_STREAM(err, log_formula_debugger)
34 
35 namespace wfl {
36 
37 
38 debug_info::debug_info(int arg_number, int counter, int level, const std::string &name, const std::string &str, const variant &value, bool evaluated)
39  : arg_number_(arg_number), counter_(counter), level_(level), name_(name), str_(str), value_(value), evaluated_(evaluated)
40 {
41 }
42 
43 
45 {
46 }
47 
48 
49 int debug_info::level() const
50 {
51  return level_;
52 }
53 
54 const std::string& debug_info::name() const
55 {
56  return name_;
57 }
58 
59 
61 {
62  return counter_;
63 }
64 
65 
66 const variant& debug_info::value() const
67 {
68  return value_;
69 }
70 
71 
73 {
74  value_ = value;
75 }
76 
77 
79 {
80  return evaluated_;
81 }
82 
83 
85 {
87 }
88 
89 
90 const std::string& debug_info::str() const
91 {
92  return str_;
93 }
94 
95 
97  : call_stack_(), counter_(0), current_breakpoint_(), breakpoints_(), execution_trace_(),arg_number_extra_debug_info(-1), f_name_extra_debug_info("")
98 {
101 }
102 
103 
105 {
106 }
107 
108 
109 static void msg(const char *act, debug_info &i, const char *to="", const char *result = "")
110 {
111  DBG_FDB << "#" << i.counter() << act << std::endl <<" \""<< i.name() << "\"='" << i.str() << "' " << to << result << std::endl;
112 }
113 
114 
115 void formula_debugger::add_debug_info(int arg_number, const std::string& f_name)
116 {
117  arg_number_extra_debug_info = arg_number;
118  f_name_extra_debug_info = f_name;
119 }
120 
121 
122 const std::list<debug_info>& formula_debugger::get_call_stack() const
123 {
124  return call_stack_;
125 }
126 
127 
129 {
130  return current_breakpoint_;
131 }
132 
133 const std::list<debug_info>& formula_debugger::get_execution_trace() const
134 {
135  return execution_trace_;
136 }
137 
139 {
140  for(std::list<breakpoint_ptr>::iterator b = breakpoints_.begin(); b != breakpoints_.end(); ++b) {
141  if ((*b)->is_break_now()){
142  current_breakpoint_ = (*b);
143  show_gui();
145  if ((*b)->is_one_time_only()) {
146  b = breakpoints_.erase(b);
147  }
148  break;
149  }
150  }
151 }
152 
154 {
155  if (game_display::get_singleton() == nullptr) {
156  WRN_FDB << "do not showing debug window due to nullptr gui" << std::endl;
157  return;
158  }
159  if (game_config::debug) {
160  gui2::dialogs::formula_debugger::display(*this);
161  } else {
162  WRN_FDB << "do not showing debug window due to disabled --new-widgets"<< std::endl;
163  }
164 }
165 
166 void formula_debugger::call_stack_push(const std::string &str)
167 {
171  execution_trace_.push_back(call_stack_.back());
172 }
173 
174 
176 {
177  execution_trace_.push_back(call_stack_.back());
178  call_stack_.pop_back();
179 }
180 
181 
183 {
184  call_stack_.back().set_evaluated(evaluated);
185 }
186 
188 {
189  call_stack_.back().set_value(v);
190 }
191 
193 {
194  call_stack_push(expression.str());
196  msg(" evaluating expression: ",call_stack_.back());
197  variant v = expression.execute(variables,this);
200  msg(" evaluated expression: ",call_stack_.back()," to ",v.to_debug_string(true).c_str());
202  call_stack_pop();
203  return v;
204 }
205 
206 
208 {
209  call_stack_push(f.str());
211  msg(" evaluating formula: ",call_stack_.back());
212  variant v = f.execute(variables,this);
215  msg(" evaluated formula: ",call_stack_.back()," to ",v.to_debug_string(true).c_str());
217  call_stack_pop();
218  return v;
219 }
220 
221 
223 {
224  call_stack_push(f.str());
226  msg(" evaluating formula without variables: ",call_stack_.back());
227  variant v = f.execute(this);
230  msg(" evaluated formula without variables: ",call_stack_.back()," to ",v.to_debug_string(true).c_str());
232  call_stack_pop();
233  return v;
234 }
235 
236 
237 base_breakpoint::base_breakpoint(formula_debugger &fdb, const std::string &name, bool one_time_only)
238  : fdb_(fdb), name_(name), one_time_only_(one_time_only)
239 {
240 
241 }
242 
243 
245 {
246 }
247 
248 
250 {
251  return one_time_only_;
252 }
253 
254 
255 const std::string& base_breakpoint::name() const
256 {
257  return name_;
258 }
259 
261 public:
263  : base_breakpoint(fdb,"End", true)
264  {
265  }
266 
267  virtual ~end_breakpoint()
268  {
269  }
270 
271  virtual bool is_break_now() const
272  {
273  const std::list<debug_info> &call_stack = fdb_.get_call_stack();
274  if ((call_stack.size() == 1) && (call_stack.front().evaluated()) ) {
275  return true;
276  }
277  return false;
278  }
279 };
280 
281 
283 public:
285  : base_breakpoint(fdb,"Step",true)
286  {
287  }
288 
290  {
291  }
292 
293  virtual bool is_break_now() const
294  {
295  const std::list<debug_info> &call_stack = fdb_.get_call_stack();
296  if (call_stack.empty() || call_stack.back().evaluated()) {
297  return false;
298  }
299 
300  return true;
301  }
302 };
303 
304 
306 public:
308  : base_breakpoint(fdb,"Step out",true), level_(fdb.get_call_stack().size()-1)
309  {
310  }
311 
313  {
314  }
315 
316  virtual bool is_break_now() const
317  {
318  const std::list<debug_info> &call_stack = fdb_.get_call_stack();
319  if (call_stack.empty() || call_stack.back().evaluated()) {
320  return false;
321  }
322 
323  if (call_stack.size() == level_) {
324  return true;
325  }
326  return false;
327  }
328 private:
329  std::size_t level_;
330 };
331 
332 
334 public:
336  : base_breakpoint(fdb,"Next",true), level_(fdb.get_call_stack().size())
337  {
338  }
339 
341  {
342  }
343 
344  virtual bool is_break_now() const
345  {
346  const std::list<debug_info> &call_stack = fdb_.get_call_stack();
347  if (call_stack.empty() || call_stack.back().evaluated()) {
348  return false;
349  }
350  if (call_stack.size() == level_) {
351  return true;
352  }
353  return false;
354  }
355 private:
356  std::size_t level_;
357 };
358 
359 
361 {
362  breakpoints_.emplace_back(new end_breakpoint(*this));
363  LOG_FDB << "added 'end' breakpoint"<< std::endl;
364 }
365 
366 
368 {
369  breakpoints_.emplace_back(new step_in_breakpoint(*this));
370  LOG_FDB << "added 'step into' breakpoint"<< std::endl;
371 }
372 
373 
375 {
376  breakpoints_.emplace_back(new step_out_breakpoint(*this));
377  LOG_FDB << "added 'step out' breakpoint"<< std::endl;
378 }
379 
380 
382 {
383  breakpoints_.emplace_back(new next_breakpoint(*this));
384  LOG_FDB << "added 'next' breakpoint"<< std::endl;
385 }
386 
387 
388 } // end of namespace wfl
int level() const
Definition: debugger.cpp:49
virtual ~next_breakpoint()
Definition: debugger.cpp:340
virtual ~step_in_breakpoint()
Definition: debugger.cpp:289
virtual bool is_break_now() const
Definition: debugger.cpp:316
virtual std::string str() const =0
void add_debug_info(int arg_number, const std::string &f_name)
Definition: debugger.cpp:115
void add_breakpoint_step_out()
Definition: debugger.cpp:374
Formula AI debugger.
void call_stack_push(const std::string &str)
Definition: debugger.cpp:166
std::list< debug_info > call_stack_
Definition: debugger.hpp:144
debug_info(int arg_number, int counter, int level, const std::string &name, const std::string &str, const variant &value, bool evaluated)
Definition: debugger.cpp:38
const std::string & str() const
Definition: formula.hpp:72
variant value_
Definition: debugger.hpp:53
std::list< breakpoint_ptr > breakpoints_
Definition: debugger.hpp:147
void set_evaluated(bool evaluated)
Definition: debugger.cpp:84
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::size_t level_
Definition: debugger.cpp:356
formula_debugger & fdb_
Definition: debugger.hpp:66
const std::string & name() const
Definition: debugger.cpp:255
std::shared_ptr< base_breakpoint > breakpoint_ptr
#define b
breakpoint_ptr current_breakpoint_
Definition: debugger.hpp:146
const breakpoint_ptr get_current_breakpoint() const
Definition: debugger.cpp:128
virtual ~base_breakpoint()
Definition: debugger.cpp:244
variant evaluate_arg_callback(const formula_expression &expression, const formula_callable &variables)
Definition: debugger.cpp:192
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
This file contains the settings handling of the widget library.
std::string f_name_extra_debug_info
Definition: debugger.hpp:150
#define WRN_FDB
Definition: debugger.cpp:32
step_in_breakpoint(formula_debugger &fdb)
Definition: debugger.cpp:284
virtual ~end_breakpoint()
Definition: debugger.cpp:267
virtual ~step_out_breakpoint()
Definition: debugger.cpp:312
void set_value(const variant &value)
Definition: debugger.cpp:72
virtual ~debug_info()
Definition: debugger.cpp:44
const variant & value() const
Definition: debugger.cpp:66
static lg::log_domain log_formula_debugger("scripting/formula/debug")
int counter() const
Definition: debugger.cpp:60
std::list< debug_info > execution_trace_
Definition: debugger.hpp:148
std::string str_
Definition: debugger.hpp:52
std::string name_
Definition: debugger.hpp:51
variant evaluate_formula_callback(const formula &f, const formula_callable &variables)
Definition: debugger.cpp:207
std::string name_
Definition: debugger.hpp:67
std::size_t i
Definition: function.cpp:933
virtual bool is_break_now() const
Definition: debugger.cpp:271
virtual bool is_break_now() const
Definition: debugger.cpp:293
next_breakpoint(formula_debugger &fdb)
Definition: debugger.cpp:335
#define LOG_FDB
Definition: debugger.cpp:31
void call_stack_set_value(const variant &v)
Definition: debugger.cpp:187
bool evaluated() const
Definition: debugger.cpp:78
#define DBG_FDB
Definition: debugger.cpp:30
const bool & debug
bool is_one_time_only() const
Definition: debugger.cpp:249
virtual ~formula_debugger()
Definition: debugger.cpp:104
void add_breakpoint_continue_to_end()
Definition: debugger.cpp:360
const std::list< debug_info > & get_call_stack() const
Definition: debugger.cpp:122
#define f
Definition: contexts.hpp:43
const std::string & str() const
Definition: debugger.cpp:90
const std::string & name() const
Definition: debugger.cpp:54
Standard logging facilities (interface).
base_breakpoint(formula_debugger &fdb, const std::string &name, bool one_time_only)
Definition: debugger.cpp:237
variant execute(const formula_callable &variables, formula_debugger *fdb=nullptr) const
Definition: formula.cpp:261
void add_breakpoint_step_into()
Definition: debugger.cpp:367
virtual bool is_break_now() const
Definition: debugger.cpp:344
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
static std::deque< std::string > call_stack
Definition: function.cpp:39
step_out_breakpoint(formula_debugger &fdb)
Definition: debugger.cpp:307
void call_stack_set_evaluated(bool evaluated)
Definition: debugger.cpp:182
const std::list< debug_info > & get_execution_trace() const
Definition: debugger.cpp:133
virtual variant execute(const formula_callable &variables, formula_debugger *fdb=nullptr) const =0
static game_display * get_singleton()
end_breakpoint(formula_debugger &fdb)
Definition: debugger.cpp:262