42271c68fa72dfeb0b17c69505a9622d116c71a3
[deliverable/titan.core.git] / core / Debugger.hh
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *
10 * Baranyi, Botond – initial implementation
11 *
12 ******************************************************************************/
13
14 #ifndef DEBUGGER_HH
15 #define DEBUGGER_HH
16
17 #include "Vector.hh"
18 #include "Basetype.hh"
19 #include "Charstring.hh"
20 #ifdef TITAN_RUNTIME_2
21 #include "RT2/PreGenRecordOf.hh"
22 #else
23 #include "RT1/PreGenRecordOf.hh"
24 #endif
25
26 /** alias for record of charstring */
27 typedef PreGenRecordOf::PREGEN__RECORD__OF__CHARSTRING charstring_list;
28
29 // forward declarations
30 class TTCN3_Debug_Scope;
31 class TTCN3_Debug_Function;
32
33
34 //////////////////////////////////////////////////////
35 ////////////////// TTCN3_Debugger ////////////////////
36 //////////////////////////////////////////////////////
37
38 /** main debugger class
39 *
40 * instantiated once per process at the beginning of the current process,
41 * destroyed at the end of the current process */
42 class TTCN3_Debugger {
43 public:
44
45 /** type for keeping track of a variable */
46 struct variable_t {
47 /** pointer to the variable object, not owned */
48 const void* value;
49 /** variable name (used for looking up variables), not owned */
50 const char* name;
51 /** name of the variable's type, not owned */
52 const char* type_name;
53 /** variable printing function (using the variable object's log() function) */
54 CHARSTRING (*print_function)(const variable_t&);
55 };
56
57 /** this type pairs a debug scope with a name, used for storing global and
58 * component scopes */
59 struct named_scope_t {
60 /** scope name (module name for global scopes, or component type name for
61 * component scopes), not owned*/
62 const char* name;
63 /** scope pointer, owned */
64 TTCN3_Debug_Scope* scope;
65 };
66
67 /** type for storing breakpoints */
68 struct breakpoint_t {
69 /** module name, owned */
70 char* module;
71 /** line number */
72 int line;
73 // const char* batch_file;
74 };
75
76 /** list of commands coming from the user interface (parameters listed in comments) */
77 enum debug_command_t {
78 // on/off switch
79 D_SWITCH_OFF, // 0
80 D_SWITCH_ON, // 0
81 // breakpoints
82 D_ADD_BREAKPOINT, // 2, module name and line number
83 D_REMOVE_BREAKPOINT, // 2, module name and line number
84 D_SET_ERROR_BEHAVIOR, // 1, "yes" or "no"
85 D_SET_FAIL_BEHAVIOR, // 1, "yes" or "no"
86 // printing and overwriting data
87 D_SET_OUTPUT, // 1-2, "stdout", "stderr" or "file" + file name
88 D_SET_PROCESS, // 1, 'mtc' or component reference
89 D_PRINT_CALL_STACK, // 0
90 D_SET_STACK_LEVEL, // 1, stack level
91 D_LIST_VARIABLES, // 1-2, "local", "global", "comp", "component" or "all", + optional filter (pattern)
92 D_PRINT_VARIABLE, // 1+, list of variable names
93 D_OVERWRITE_VARIABLE, // 2, variable name, new value (in module parameter syntax)
94 D_PRINT_SNAPSHOTS, // 0
95 D_SET_SNAPSHOT_BEHAVIOR, // TBD
96 // stepping
97 D_STEP_OVER, // 0
98 D_STEP_INTO, // 0
99 D_STEP_OUT, // 0
100 D_RUN_TO_CURSOR, // 2, module name and line number
101 // ending the halted state
102 D_CONTINUE, // 0
103 D_EXIT, // 0
104 // batch files
105 D_SET_HALTING_BATCH_FILE // TBD
106 };
107
108 /** special breakpoint types, passed to breakpoint_entry() as the line parameter,
109 * so these need to be 0 or negative, to never conflict with any line number */
110 enum special_breakpoint_t {
111 /** triggered when the local verdict is set to ERROR (by dynamic test case errors) */
112 SBP_ERROR_VERDICT = 0,
113 /** triggered when the local verdict is set to FAIL (by the user) */
114 SBP_FAIL_VERDICT = -1
115 };
116
117 private:
118
119 /** the debugger's on/off switch */
120 bool active;
121
122 /** the debugger's output file handler */
123 FILE* output;
124
125 /** list of all global and component variables, elements are owned */
126 Vector<variable_t*> variables;
127
128 /** list of global scopes */
129 Vector<named_scope_t> global_scopes;
130
131 /** list of component scopes */
132 Vector<named_scope_t> component_scopes;
133
134 /** pointers to debug function objects (resembling a call stack), elements are not owned
135 * the current function is always the last element in the array (the top element in the stack) */
136 Vector<TTCN3_Debug_Function*> call_stack;
137
138 /** list of breakpoints */
139 Vector<breakpoint_t> breakpoints;
140
141 /** string containing function call snapshots, owned */
142 char* snapshots;
143
144 /** stores the last line hit by breakpoint_entry() */
145 breakpoint_t last_breakpoint_entry;
146
147 /** current stack level (reset whenever a breakpoint is reached) */
148 int stack_level;
149
150 /** behavior triggered by setting the local verdict to FAIL
151 * (a breakpoint is activated if set to true) */
152 bool fail_behavior;
153
154 /** behavior triggered by setting the local verdict to ERROR
155 * (a breakpoint is activated if set to true) */
156 bool error_behavior;
157
158 //////////////////////////////////////////////////////
159 ///////////////// internal functions /////////////////
160 //////////////////////////////////////////////////////
161
162 /** switches the debugger off
163 * handles the D_SWITCH_OFF command */
164 void switch_off();
165
166 /** switches the debugger on
167 * handles the D_SWITCH_ON command */
168 void switch_on();
169
170 /** adds a new breakpoint at the specified module and line
171 * handles the D_ADD_BREAKPOINT command */
172 void add_breakpoint(const char* p_module, int p_line /*const char* batch_file*/);
173
174 /** removes the breakpoint from the specified module/line, if it exists
175 * handles the D_REMOVE_BREAKPOINT command */
176 void remove_breakpoint(const char* p_module, int p_line);
177
178 /** sets the behavior of a special breakpoint type
179 * @param p_state_str "yes" turns the special breakpoint on (as if it was an
180 * actual breakpoint), "no" turns it off
181 * handles the D_SET_ERROR_BEHAVIOR and D_SET_FAIL_BEHAVIOR commands */
182 void set_special_breakpoint(special_breakpoint_t p_type, const char* p_state_str);
183
184 /** prints the current call stack
185 * handles the D_PRINT_CALL_STACK command */
186 void print_call_stack();
187
188 /** sets the current stack level to the specified level
189 * handles the D_SET_STACK_LEVEL command */
190 void set_stack_level(int new_level);
191
192 /** prints the specified variable
193 * handles (one parameter of) the D_PRINT_VARIABLE command */
194 void print_variable(const variable_t* p_var) const;
195
196 /** sets the debugger's output to a different stream
197 * handles the D_SET_OUTPUT command
198 * @param p_output_type "stdout", "stderr" or "file"
199 * @param p_file_name output file name, if the output is a file, or NULL */
200 void set_output(const char* p_output_type, const char* p_file_name);
201
202 /** returns the index of the specified breakpoint, if found,
203 * otherwise returns breakpoints.size() */
204 size_t find_breakpoint(const char* p_module, int p_line) const;
205
206 /** returns the specified variable, if found, otherwise returns NULL */
207 TTCN3_Debugger::variable_t* find_variable(const void* p_value) const;
208
209 public:
210 /** constructor - called once per process (at the beginning) */
211 TTCN3_Debugger();
212
213 /** destructor - called once per process (at the end) */
214 ~TTCN3_Debugger();
215
216 //////////////////////////////////////////////////////
217 ////// methods called from TITAN generated code //////
218 //////////////////////////////////////////////////////
219
220 /** creates, stores and returns a new global scope for the specified module */
221 TTCN3_Debug_Scope* add_global_scope(const char* p_module);
222
223 /** creates, stores and returns a new global scope for the specified module */
224 TTCN3_Debug_Scope* add_component_scope(const char* p_component);
225
226 /** stores the string representation of the current function's return value
227 * (only if the debugger is switched on) */
228 void set_return_value(const CHARSTRING& p_value);
229
230 /** activates a breakpoint if the specified line and the current function's module
231 * match any of the breakpoints stored in the debugger
232 * the special parameter values (SBP_ERROR_VERDICT and SBP_FAIL_VERDICT) only
233 * trigger a breakpoint if their respective behaviors have been set to do so
234 * (does nothing if the debugger is switched off) */
235 void breakpoint_entry(int p_line /*bool p_stepping_helper*/);
236
237 /** variable printing function for base types */
238 static CHARSTRING print_base_var(const variable_t& p_var);
239
240 /** variable printing function for value arrays */
241 template <typename T_type, unsigned int array_size, int index_offset>
242 static CHARSTRING print_value_array(const variable_t& p_var)
243 {
244 TTCN_Logger::begin_event_log2str();
245 ((VALUE_ARRAY<T_type, array_size, index_offset>*)p_var.value)->log();
246 return TTCN_Logger::end_event_log2str();
247 }
248
249 /** variable printing function for template arrays */
250 template <typename T_value_type, typename T_template_type,
251 unsigned int array_size, int index_offset>
252 static CHARSTRING print_template_array(const variable_t& p_var)
253 {
254 TTCN_Logger::begin_event_log2str();
255 ((TEMPLATE_ARRAY<T_value_type, T_template_type, array_size,
256 index_offset>*)p_var.value)->log();
257 return TTCN_Logger::end_event_log2str();
258 }
259
260 /** variable printing function for port arrays */
261 template <typename T_type, unsigned int array_size, int index_offset>
262 static CHARSTRING print_port_array(const variable_t& p_var)
263 {
264 TTCN_Logger::begin_event_log2str();
265 ((PORT_ARRAY<T_type, array_size, index_offset>*)p_var.value)->log();
266 return TTCN_Logger::end_event_log2str();
267 }
268
269 /** variable printing function for timer arrays */
270 template <typename T_type, unsigned int array_size, int index_offset>
271 static CHARSTRING print_timer_array(const variable_t& p_var)
272 {
273 TTCN_Logger::begin_event_log2str();
274 ((TIMER_ARRAY<T_type, array_size, index_offset>*)p_var.value)->log();
275 return TTCN_Logger::end_event_log2str();
276 }
277
278 /** variable printing function for lazy parameters */
279 template <typename EXPR_TYPE>
280 static CHARSTRING print_lazy_param(const variable_t& p_var)
281 {
282 TTCN_Logger::begin_event_log2str();
283 ((Lazy_Param<EXPR_TYPE>*)p_var.value)->log();
284 return TTCN_Logger::end_event_log2str();
285 }
286
287 //////////////////////////////////////////////////////
288 ////// methods called by other debugger classes //////
289 //////////////////////////////////////////////////////
290
291 /** returns true if the debugger is switched on */
292 bool is_on() const { return active; }
293
294 /** prints formatted string to the debugger's output stream */
295 void print(const char* fmt, ...) const;
296
297 /** adds the specified function object pointer to the call stack
298 * (only if the debugger is switched on) */
299 void add_function(TTCN3_Debug_Function* p_function);
300
301 /** adds the specified scope object pointer to the current function's scope list
302 * (only if the debugger is switched on and the call stack is not empty) */
303 void add_scope(TTCN3_Debug_Scope* p_scope);
304
305 /** removes the specified function object pointer from the call stack, if it is
306 * the function at the top of the stack */
307 void remove_function(TTCN3_Debug_Function* p_function);
308
309 /** removes the specified scope object pointer from the current function's scope list
310 * (only if the call stack is not empty) */
311 void remove_scope(TTCN3_Debug_Scope* p_scope);
312
313 /** finds or creates, and returns the variable entry specified by the parameters
314 *
315 * if the call stack is empty, an entry for a global or component variable is
316 * created and stored in the main debugger object (if it doesn't already exist);
317 * if the call stack is not empty (and if the debugger is switched on), the
318 * variable entry for a local variable is created and stored by the current function*/
319 const variable_t* add_variable(const void* p_value, const char* p_name, const char* p_type,
320 CHARSTRING (*p_print_function)(const variable_t&));
321
322 /** removes the variable entry for the specified local variable in the current
323 * function (only if the call stack is not empty) */
324 void remove_variable(const variable_t* p_var);
325
326 /** returns the global scope object associated with the specified module */
327 const TTCN3_Debug_Scope* get_global_scope(const char* p_module) const;
328
329 /** returns the component scope object associated with the specified component type */
330 const TTCN3_Debug_Scope* get_component_scope(const char* p_component) const;
331
332 /** appends the specified function call snapshot to the end of the snapshot string */
333 void add_snapshot(const char* p_snapshot);
334
335 /** executes a command received from the user interface */
336 void execute_command(debug_command_t p_command, const charstring_list& p_arguments);
337 };
338
339 /** the main debugger object */
340 extern TTCN3_Debugger ttcn3_debugger;
341
342
343 //////////////////////////////////////////////////////
344 //////////////// TTCN3_Debug_Scope ///////////////////
345 //////////////////////////////////////////////////////
346
347 /** debugger scope class
348 *
349 * instantiated at the beginning of every code block in the TTCN-3 code (except
350 * for the code blocks of functions), plus one (global scope) instance is created
351 * for every module and one (component scope) for every component type
352 *
353 * the class' main purpose is to track which local variables were created in the
354 * current code block or to track which of the main debugger object's variables
355 * belong to which global or component scope */
356 class TTCN3_Debug_Scope {
357
358 /** list of pointers to local variable entries from the current function object or
359 * global or component variable entries from the main debugger object
360 * (the elements are not owned)*/
361 Vector<const TTCN3_Debugger::variable_t*> variables;
362
363 public:
364
365 /** constructor - lets the current function know of this new scope */
366 TTCN3_Debug_Scope();
367
368 /** destructor - tells the current function to delete the variable entries listed
369 * in this instance */
370 ~TTCN3_Debug_Scope();
371
372 //////////////////////////////////////////////////////
373 ////// methods called from TITAN generated code //////
374 //////////////////////////////////////////////////////
375
376 /** passes the parameters to the main debugger or current function object to
377 * create and store a variable entry from them, and tracks this new variable
378 * by storing a pointer to it
379 * (local variables are only created and stored if the debugger is switched on) */
380 void add_variable(const void* p_value, const char* p_name, const char* p_type,
381 CHARSTRING (*p_print_function)(const TTCN3_Debugger::variable_t&));
382
383 //////////////////////////////////////////////////////
384 ////// methods called by other debugger classes //////
385 //////////////////////////////////////////////////////
386
387 /** returns true if there is at least one variable in the scope object */
388 bool has_variables() const { return !variables.empty(); }
389
390 /** returns the specified variable, if found, otherwise returns NULL */
391 const TTCN3_Debugger::variable_t* find_variable(const char* p_name) const;
392
393 /** prints the names of variables in this scope that match the specified pattern
394 * @param p_filter the mentioned pattern
395 * @param p_first true if no variables have been printed yet */
396 void list_variables(const char* p_filter, bool& p_first) const;
397 };
398
399
400 //////////////////////////////////////////////////////
401 /////////////// TTCN3_Debug_Function /////////////////
402 //////////////////////////////////////////////////////
403
404 /** debugger function class
405 *
406 * instantiated at the beginning of every function, destroyed when function execution ends
407 *
408 * tracks all variables created during the function's execution (local variables),
409 * including the function's parameters, and stores the function's return value */
410 class TTCN3_Debug_Function {
411
412 /** name of the function, not owned */
413 const char* function_name;
414
415 /** the TTCN-3 keyword(s) used to define the function ("function", "testcase",
416 * "altstep", "template" or "external function"), not owned */
417 const char* function_type;
418
419 /** name of the module this function is defined in, not owned */
420 const char* module_name;
421
422 /** names of the function's parameters (in the order of their declaration), owned */
423 charstring_list* parameter_names;
424
425 /** types (directions) of the function's parameters ("in", "inout" or "out"), owned */
426 charstring_list* parameter_types;
427
428 /** list of local variables tracked by this object, the array elements are owned */
429 Vector<TTCN3_Debugger::variable_t*> variables;
430
431 /** list of pointers to the scope objects of code blocks in the function,
432 * the elements are not owned
433 * (currently not used for anything) */
434 Vector<TTCN3_Debug_Scope*> scopes;
435
436 /** pointer to the global scope object, not owned
437 * (may be NULL, if the module's global scope is empty) */
438 const TTCN3_Debug_Scope* global_scope;
439
440 /** pointer to the runs-on component's scope object, not owned
441 * (may be NULL, if the component's scope is empty or if the function has no runs-on clause) */
442 const TTCN3_Debug_Scope* component_scope;
443
444 /** the function's return value (unbound if the return value has not been set yet,
445 * or if the function doesn't return anything)
446 *
447 * since this is only set right before the function ends, it is only accessible
448 * from the destructor */
449 CHARSTRING return_value;
450
451 public:
452
453 /** constructor - initializes the instance with the specified parameters,
454 * retrieves the global scope and component scope from the main debugger object */
455 TTCN3_Debug_Function(const char* p_name, const char* p_type, const char* p_module,
456 const charstring_list& p_parameter_names, const charstring_list& p_parameter_types, const char* p_component_name);
457
458 /** destructor - frees resources and saves the function's ending snapshot
459 * (including the values of 'out' and 'inout' parameters and the return value)
460 * in the main debugger object (only if the debugger is switched on) */
461 ~TTCN3_Debug_Function();
462
463 //////////////////////////////////////////////////////
464 ////// methods called from TITAN generated code //////
465 //////////////////////////////////////////////////////
466
467 /** creates, stores and returns the variable entry of the local variable
468 * specified by the parameters (only if the debugger is switched on) */
469 const TTCN3_Debugger::variable_t* add_variable(const void* p_value, const char* p_name,
470 const char* p_type, CHARSTRING (*p_print_function)(const TTCN3_Debugger::variable_t&));
471
472 /** stores the string representation of the value returned by the function */
473 void set_return_value(const CHARSTRING& p_value);
474
475 /** saves the function's initial snapshot (including the values on 'in' and
476 * 'inout' parameters) in the main debugger object
477 * (only if the debugger is switched on) */
478 void initial_snapshot() const;
479
480 //////////////////////////////////////////////////////
481 ////// methods called by other debugger classes //////
482 //////////////////////////////////////////////////////
483
484 /** adds the specified scope object pointer to the function's scope list */
485 void add_scope(TTCN3_Debug_Scope* p_scope);
486
487 /** removes the specified scope object pointer from the function's scope list,
488 * if it is the last scope in the list */
489 void remove_scope(TTCN3_Debug_Scope* p_scope);
490
491 /** removes the specified variable from the variable list */
492 void remove_variable(const TTCN3_Debugger::variable_t* p_var);
493
494 /** searches for the variable entry with the specified name in the function's
495 * local variable list, the global scope (if any) and the component scope (if any),
496 * returns NULL, if the variable was not found */
497 const TTCN3_Debugger::variable_t* find_variable(const char* p_name) const;
498
499 /** prints the function's type, name and current values of parameters */
500 void print_function() const;
501
502 /** returns the name of the module the function was defined in */
503 const char* get_module_name() const { return module_name; }
504
505 /** prints the names of variables specified by the parameters (separated by spaces)
506 * handles the D_LIST_VARIABLES debugger command
507 * @param p_scope specifies which scope to print variables from:
508 * - "local" - the function's local variables (including variables in code blocks)
509 * - "global" - variables in the module's global scope
510 * - "comp" or "component" - variables in the function's runs-on component scope
511 * - "all" - all variables visible in the function (i.e. all of the above)
512 * @param p_filter a pattern to filter variable names further */
513 void list_variables(const char* p_scope, const char* p_filter) const;
514 };
515
516 /** This macro stores a function's return value in the current function.
517 * The returned value might be an expression, so it is copied to a temporary first,
518 * to avoid being evaluated twice. */
519 #define DEBUGGER_STORE_RETURN_VALUE(tmp, ret_val) \
520 (tmp = (ret_val), \
521 ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), \
522 tmp.log(), \
523 TTCN_Logger::end_event_log2str())), \
524 tmp)
525
526 #endif /* DEBUGGER_HH */
527
This page took 0.041206 seconds and 4 git commands to generate.