Commit | Line | Data |
---|---|---|
7329404e BB |
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 | |
016a1a93 | 25 | #include <regex.h> |
7329404e BB |
26 | |
27 | /** alias for record of charstring */ | |
28 | typedef PreGenRecordOf::PREGEN__RECORD__OF__CHARSTRING charstring_list; | |
29 | ||
f08ff9ca | 30 | // debugger forward declarations |
7329404e BB |
31 | class TTCN3_Debug_Scope; |
32 | class TTCN3_Debug_Function; | |
33 | ||
f08ff9ca BB |
34 | // other forward declarations |
35 | class Module_Param; | |
36 | ||
7329404e BB |
37 | |
38 | ////////////////////////////////////////////////////// | |
39 | ////////////////// TTCN3_Debugger //////////////////// | |
40 | ////////////////////////////////////////////////////// | |
41 | ||
42 | /** main debugger class | |
43 | * | |
44 | * instantiated once per process at the beginning of the current process, | |
45 | * destroyed at the end of the current process */ | |
46 | class TTCN3_Debugger { | |
47 | public: | |
48 | ||
f08ff9ca BB |
49 | struct variable_t; |
50 | ||
51 | typedef CHARSTRING (*print_function_t)(const variable_t&); | |
52 | typedef boolean (*set_function_t)(variable_t&, Module_Param&); | |
53 | ||
7329404e BB |
54 | /** type for keeping track of a variable */ |
55 | struct variable_t { | |
56 | /** pointer to the variable object, not owned */ | |
f08ff9ca BB |
57 | union { |
58 | /** container for non-constant variable objects */ | |
59 | void* value; | |
60 | /** container for constant variable objects */ | |
61 | const void* cvalue; | |
62 | }; | |
7329404e BB |
63 | /** variable name (used for looking up variables), not owned */ |
64 | const char* name; | |
65 | /** name of the variable's type, not owned */ | |
66 | const char* type_name; | |
1cb5b229 BB |
67 | /** name of the module the variable was declared in (only set for global |
68 | * variables, otherwise NULL), not owned */ | |
69 | const char* module; | |
7329404e | 70 | /** variable printing function (using the variable object's log() function) */ |
f08ff9ca BB |
71 | print_function_t print_function; |
72 | /** variable setting (overwriting) function (using the variable object's | |
73 | * set_param() function) - set to NULL for constant variables */ | |
74 | set_function_t set_function; | |
7329404e BB |
75 | }; |
76 | ||
77 | /** this type pairs a debug scope with a name, used for storing global and | |
78 | * component scopes */ | |
79 | struct named_scope_t { | |
80 | /** scope name (module name for global scopes, or component type name for | |
016a1a93 | 81 | * component scopes), not owned */ |
7329404e BB |
82 | const char* name; |
83 | /** scope pointer, owned */ | |
84 | TTCN3_Debug_Scope* scope; | |
85 | }; | |
86 | ||
f08ff9ca BB |
87 | /** type for storing a function call in the call stack */ |
88 | struct function_call_t { | |
89 | /** pointer to the debug function object */ | |
90 | TTCN3_Debug_Function* function; | |
91 | /** TTCN-3 line number, where the function was called from */ | |
92 | int caller_line; | |
93 | }; | |
94 | ||
7329404e BB |
95 | /** type for storing breakpoints */ |
96 | struct breakpoint_t { | |
97 | /** module name, owned */ | |
98 | char* module; | |
cf2b6056 | 99 | /** line number (if it's a line breakpoint, otherwise 0) */ |
7329404e | 100 | int line; |
cf2b6056 BB |
101 | /** function name (if it's a function breakpoint, otherwise NULL), owned */ |
102 | char* function; | |
103 | /** batch file to be executed when the breakpoint is reached (optional), owned */ | |
f08ff9ca | 104 | char* batch_file; |
7329404e BB |
105 | }; |
106 | ||
cf2b6056 BB |
107 | /** type for storing data related to a breakpoint entry */ |
108 | struct breakpoint_entry_t { | |
109 | /** module name, not owned */ | |
110 | const char* module; | |
111 | /** line number */ | |
112 | int line; | |
113 | /** size of the call stack */ | |
114 | size_t stack_size; | |
115 | }; | |
116 | ||
7329404e BB |
117 | /** special breakpoint types, passed to breakpoint_entry() as the line parameter, |
118 | * so these need to be 0 or negative, to never conflict with any line number */ | |
119 | enum special_breakpoint_t { | |
120 | /** triggered when the local verdict is set to ERROR (by dynamic test case errors) */ | |
121 | SBP_ERROR_VERDICT = 0, | |
122 | /** triggered when the local verdict is set to FAIL (by the user) */ | |
123 | SBP_FAIL_VERDICT = -1 | |
124 | }; | |
125 | ||
f08ff9ca BB |
126 | /** type for storing the settings of automatic breakpoints */ |
127 | struct automatic_breakpoint_behavior_t { | |
128 | /** indicates whether the breakpoint should be triggered by the associated event */ | |
129 | bool trigger; | |
cf2b6056 | 130 | /** batch file to be executed if the breakpoint is triggered (optional), owned */ |
f08ff9ca BB |
131 | char* batch_file; |
132 | }; | |
133 | ||
cf2b6056 BB |
134 | /** possible function call data handling configurations */ |
135 | enum function_call_data_config_t { | |
136 | /** function call data is printed directly to file and not stored by the | |
137 | * debugger */ | |
138 | CALLS_TO_FILE, | |
139 | /** function call data is stored in a ring buffer of a set size | |
140 | * (i.e. when the buffer is full, adding a new function call automatically | |
141 | * deletes the oldest function call) | |
142 | * the buffer size can be zero, in which case no calls are stored */ | |
143 | CALLS_RING_BUFFER, | |
144 | /** function call data is stored in a buffer of variable length (i.e. when | |
145 | * the buffer is full, its size is increased) */ | |
146 | CALLS_STORE_ALL | |
147 | }; | |
148 | ||
149 | /** structure containing the function call data and information related to | |
150 | * their handling */ | |
151 | struct function_call_data_t { | |
152 | /** current function call data configuration (this also indicates which | |
153 | * field of the following union is selected) */ | |
154 | function_call_data_config_t cfg; | |
155 | union { | |
156 | /** information related to the file, that function calls are printed to | |
157 | * (in case of CALLS_TO_FILE) */ | |
158 | struct { | |
159 | /** name of the target file (may contain metacharacters), owned */ | |
160 | char* name; | |
161 | /** the target file's handler, owned */ | |
162 | FILE* ptr; | |
163 | } file; | |
164 | /** information related to the storing of function calls | |
165 | * (in case of CALLS_RING_BUFFER or CALLS_STORE_ALL) */ | |
166 | struct { | |
167 | /** size of the buffer used for storing function calls (this value is | |
168 | * fixed in case of CALLS_RING_BUFFER and dynamic in case of CALLS_STORE_ALL) */ | |
169 | int size; | |
170 | /** stores the index of the first function call in the buffer | |
171 | * (is always 0 in case of CALLS_STORE_ALL) */ | |
172 | int start; | |
173 | /** stores the index of the last function call in the buffer | |
174 | * (its value is -1 if no function calls are currently stored) */ | |
175 | int end; | |
176 | /** buffer containing the function call data, owned */ | |
177 | char** ptr; | |
178 | } buffer; | |
179 | }; | |
180 | }; | |
181 | ||
f08ff9ca BB |
182 | /** stepping type */ |
183 | enum stepping_t { | |
184 | NOT_STEPPING, | |
185 | STEP_OVER, | |
186 | STEP_INTO, | |
187 | STEP_OUT | |
188 | }; | |
189 | ||
7329404e BB |
190 | private: |
191 | ||
016a1a93 BB |
192 | /** indicates whether the debugger has been activated, meaning that the debugger's |
193 | * command line option (-n) was used during the build (switched automatically | |
194 | * by generated code) */ | |
195 | bool enabled; | |
196 | ||
197 | /** the debugger's on/off switch (switched by the user) */ | |
7329404e BB |
198 | bool active; |
199 | ||
016a1a93 BB |
200 | /** true if test execution has been halted (by a breakpoint or by the user) */ |
201 | bool halted; | |
202 | ||
203 | /** the debugger's output file handler (NULL if the debugger's output is only | |
cf2b6056 | 204 | * sent to the console); owned */ |
016a1a93 BB |
205 | FILE* output_file; |
206 | ||
207 | /** name of the debugger's output file (NULL if the debugger's output is only | |
cf2b6056 | 208 | * sent to the console); may contain metacharacters; owned */ |
016a1a93 BB |
209 | char* output_file_name; |
210 | ||
211 | /** indicates whether the debugger's output should be sent to the console */ | |
212 | bool send_to_console; | |
7329404e BB |
213 | |
214 | /** list of all global and component variables, elements are owned */ | |
215 | Vector<variable_t*> variables; | |
216 | ||
217 | /** list of global scopes */ | |
218 | Vector<named_scope_t> global_scopes; | |
219 | ||
220 | /** list of component scopes */ | |
221 | Vector<named_scope_t> component_scopes; | |
222 | ||
f08ff9ca BB |
223 | /** pointers to debug function objects and the lines they were called from |
224 | * (resembling a call stack), the current function is always the last element | |
225 | * in the array (the top element in the stack) */ | |
226 | Vector<function_call_t> call_stack; | |
7329404e BB |
227 | |
228 | /** list of breakpoints */ | |
229 | Vector<breakpoint_t> breakpoints; | |
230 | ||
cf2b6056 BB |
231 | /** structure containing function call data */ |
232 | function_call_data_t function_calls; | |
7329404e BB |
233 | |
234 | /** stores the last line hit by breakpoint_entry() */ | |
cf2b6056 | 235 | breakpoint_entry_t last_breakpoint_entry; |
7329404e | 236 | |
016a1a93 | 237 | /** current stack level (reset when test execution is halted or resumed) */ |
7329404e BB |
238 | int stack_level; |
239 | ||
f08ff9ca BB |
240 | /** automatic breakpoint triggered by setting the local verdict to FAIL */ |
241 | automatic_breakpoint_behavior_t fail_behavior; | |
7329404e | 242 | |
f08ff9ca BB |
243 | /** automatic breakpoint triggered by setting the local verdict to ERROR */ |
244 | automatic_breakpoint_behavior_t error_behavior; | |
7329404e | 245 | |
f08ff9ca | 246 | /** batch file executed automatically when test execution is halted |
cf2b6056 | 247 | * NULL if switched off (owned) |
f08ff9ca BB |
248 | * is overridden by breakpoint-specific batch files */ |
249 | char* global_batch_file; | |
250 | ||
cf2b6056 | 251 | /** result of the currently executing command, owned */ |
016a1a93 BB |
252 | char* command_result; |
253 | ||
cf2b6056 | 254 | /** result of the last D_LIST_VARIABLES command, owned */ |
f08ff9ca BB |
255 | char* last_variable_list; |
256 | ||
257 | /** stores which stepping option was requested by the user (if any) */ | |
258 | stepping_t stepping_type; | |
259 | ||
260 | /** stores the size of the call stack when the last stepping operation was | |
261 | * initiated */ | |
262 | size_t stepping_stack_size; | |
263 | ||
264 | /** temporary breakpoint set by the 'run to cursor' operation */ | |
265 | breakpoint_t temporary_breakpoint; | |
266 | ||
267 | /** true if an 'exit all' command was issued | |
268 | * switched to false when test execution is restarted */ | |
269 | bool exiting; | |
270 | ||
271 | /** test execution is automatically halted at start if set to true */ | |
272 | bool halt_at_start; | |
273 | ||
274 | /** batch file executed automatically at the start of test execution | |
275 | * if not set to NULL (not owned) */ | |
276 | const char* initial_batch_file; | |
277 | ||
7329404e BB |
278 | ////////////////////////////////////////////////////// |
279 | ///////////////// internal functions ///////////////// | |
280 | ////////////////////////////////////////////////////// | |
281 | ||
016a1a93 BB |
282 | /** switches the debugger on or off |
283 | * handles the D_SWITCH command */ | |
284 | void switch_state(const char* p_state_str); | |
7329404e | 285 | |
cf2b6056 BB |
286 | /** adds a new breakpoint at the specified location (line or function) with the |
287 | * specified batch file (if not NULL), or changes the batch file of an existing | |
f08ff9ca | 288 | * breakpoint |
f57971fe | 289 | * handles the D_SET_BREAKPOINT command */ |
cf2b6056 BB |
290 | void set_breakpoint(const char* p_module, const char* p_location, |
291 | const char* batch_file); | |
7329404e | 292 | |
cf2b6056 | 293 | /** removes the breakpoint from the specified location, if it exists |
f08ff9ca BB |
294 | * can also be used to remove all breakpoints from the specified module or |
295 | * all breakpoints in all modules | |
f57971fe | 296 | * handles the D_REMOVE_BREAKPOINT command */ |
cf2b6056 | 297 | void remove_breakpoint(const char* p_module, const char* p_location); |
f08ff9ca BB |
298 | |
299 | /** switches an automatic breakpoint related to the specified event on or off | |
300 | * and/or sets the batch file to run when the breakpoint is triggered | |
301 | * @param p_event_str string representation of the event that triggers the | |
302 | * breakpoint (either "error" or "fail") | |
303 | * @param p_state_str "on" or "off", indicates the new state of the breakpoint | |
304 | * @param p_batch_file name of the batch file to execute (NULL means don't | |
305 | * execute anything) | |
306 | * handles the D_SET_AUTOMATIC_BREAKPOINT command */ | |
307 | void set_automatic_breakpoint(const char* p_event_str, const char* p_state_str, | |
308 | const char* p_batch_file); | |
7329404e | 309 | |
1cb5b229 BB |
310 | /** prints the debugger's settings |
311 | * handles the D_PRINT_SETTINGS command */ | |
312 | void print_settings(); | |
313 | ||
7329404e BB |
314 | /** prints the current call stack |
315 | * handles the D_PRINT_CALL_STACK command */ | |
316 | void print_call_stack(); | |
317 | ||
016a1a93 | 318 | /** sets the current stack level to the specified value |
7329404e BB |
319 | * handles the D_SET_STACK_LEVEL command */ |
320 | void set_stack_level(int new_level); | |
321 | ||
f08ff9ca BB |
322 | /** finds the variable with the specified name, and prints its value or an |
323 | * error message | |
f57971fe | 324 | * the variable's value is printed using its log() function |
7329404e | 325 | * handles (one parameter of) the D_PRINT_VARIABLE command */ |
f08ff9ca BB |
326 | void print_variable(const char* p_var_name); |
327 | ||
f57971fe BB |
328 | /** finds the variable with the specified name, and overwrites its value or |
329 | * displays an error message | |
330 | * the new value is received in a string array; this is concatenated into one | |
331 | * string (with one space separating each string element); then it is passed | |
332 | * to the module parameter parser, which creates a Module_Param object from it | |
333 | * (if its syntax is correct) | |
334 | * the variable's value is overwritten by passing the Module_Param object to | |
335 | * its set_param() function | |
336 | * handles the D_OVERWRITE_VARIABLE command */ | |
f08ff9ca BB |
337 | void overwrite_variable(const char* p_var_name, int p_value_element_count, |
338 | char** p_value_elements); | |
7329404e | 339 | |
cf2b6056 BB |
340 | /** frees all resources related to the handling of function call data */ |
341 | void clean_up_function_calls(); | |
342 | ||
343 | /** changes the method of handling function call data | |
344 | * handles the D_FUNCTION_CALL_CONFIG command */ | |
345 | void configure_function_calls(const char* p_config, const char* p_file_name); | |
346 | ||
347 | /** prints the last stored function calls | |
348 | * handles the D_PRINT_FUNCTION_CALLS command | |
349 | * @param p_amount amount of function calls to print or "all" */ | |
350 | void print_function_calls(const char* p_amount); | |
351 | ||
016a1a93 | 352 | /** sets the debugger's output to the console and/or a text file |
7329404e | 353 | * handles the D_SET_OUTPUT command |
016a1a93 BB |
354 | * @param p_output_type "console", "file" or "both" |
355 | * @param p_file_name output file name or NULL */ | |
7329404e BB |
356 | void set_output(const char* p_output_type, const char* p_file_name); |
357 | ||
f08ff9ca BB |
358 | /** switches the global batch file on or off |
359 | * handles the D_SET_GLOBAL_BATCH_FILE command */ | |
360 | void set_global_batch_file(const char* p_state_str, const char* p_file_name); | |
361 | ||
362 | /** resumes execution until the next breakpoint entry (in the stack levels | |
363 | * specified by the stepping type arguments) is reached (or until test execution | |
364 | * is halted for any other reason) | |
365 | * handles the D_STEP_OVER, D_STEP_INTO and D_STEP_OUT commands */ | |
366 | void step(stepping_t p_stepping_type); | |
367 | ||
cf2b6056 | 368 | /** resumes execution until the specified location (line or function) is reached |
f08ff9ca BB |
369 | * (or until test execution is halted for any other reason) |
370 | * handles the D_RUN_TO_CURSOR command */ | |
cf2b6056 | 371 | void run_to_cursor(const char* p_module, const char* p_location); |
f08ff9ca | 372 | |
016a1a93 | 373 | /** halts test execution, processing only debug commands |
f08ff9ca BB |
374 | * @param p_batch_file batch file executed after the halt (if not NULL) |
375 | * @param p_run_global_batch indicates whether the global batch file should | |
376 | * be executed after the halt (only if p_batch_file is NULL) | |
016a1a93 | 377 | * handles the D_HALT command */ |
f08ff9ca | 378 | void halt(const char* p_batch_file, bool p_run_global_batch); |
016a1a93 BB |
379 | |
380 | /** resumes the halted test execution | |
381 | * handles the D_CONTINUE command */ | |
382 | void resume(); | |
383 | ||
384 | /** exits the current test or the execution of all tests | |
385 | * handles the D_EXIT command */ | |
386 | void exit_(const char* p_what); | |
387 | ||
7329404e BB |
388 | /** returns the index of the specified breakpoint, if found, |
389 | * otherwise returns breakpoints.size() */ | |
cf2b6056 BB |
390 | size_t find_breakpoint(const char* p_module, int p_line, |
391 | const char* p_function) const; | |
7329404e BB |
392 | |
393 | /** returns the specified variable, if found, otherwise returns NULL */ | |
394 | TTCN3_Debugger::variable_t* find_variable(const void* p_value) const; | |
016a1a93 BB |
395 | |
396 | /** handles metacharacters in the specified file name skeleton | |
397 | * @return final file name (must be freed by caller) */ | |
398 | static char* finalize_file_name(const char* p_file_name_skeleton); | |
f08ff9ca BB |
399 | |
400 | /** initialization function, called when the first function is added to the | |
401 | * call stack */ | |
402 | void test_execution_started(); | |
403 | ||
404 | /** clean up function, called when the last function is removed from the | |
405 | * call stack */ | |
406 | void test_execution_finished(); | |
7329404e BB |
407 | |
408 | public: | |
409 | /** constructor - called once per process (at the beginning) */ | |
410 | TTCN3_Debugger(); | |
411 | ||
412 | /** destructor - called once per process (at the end) */ | |
413 | ~TTCN3_Debugger(); | |
414 | ||
415 | ////////////////////////////////////////////////////// | |
416 | ////// methods called from TITAN generated code ////// | |
417 | ////////////////////////////////////////////////////// | |
418 | ||
016a1a93 BB |
419 | /** activates the debugger */ |
420 | void activate() { enabled = true; } | |
421 | ||
422 | /** creates, stores and returns a new global scope for the specified module | |
423 | * (this scope contains all global variables visible in the module) */ | |
7329404e BB |
424 | TTCN3_Debug_Scope* add_global_scope(const char* p_module); |
425 | ||
016a1a93 BB |
426 | /** creates, stores and returns a new component scope for the specified component |
427 | * type (this scope contains all variables declared in the component type) */ | |
7329404e BB |
428 | TTCN3_Debug_Scope* add_component_scope(const char* p_component); |
429 | ||
430 | /** stores the string representation of the current function's return value | |
431 | * (only if the debugger is switched on) */ | |
432 | void set_return_value(const CHARSTRING& p_value); | |
433 | ||
434 | /** activates a breakpoint if the specified line and the current function's module | |
435 | * match any of the breakpoints stored in the debugger | |
436 | * the special parameter values (SBP_ERROR_VERDICT and SBP_FAIL_VERDICT) only | |
437 | * trigger a breakpoint if their respective behaviors have been set to do so | |
438 | * (does nothing if the debugger is switched off) */ | |
f08ff9ca | 439 | void breakpoint_entry(int p_line); |
7329404e BB |
440 | |
441 | /** variable printing function for base types */ | |
442 | static CHARSTRING print_base_var(const variable_t& p_var); | |
443 | ||
f08ff9ca BB |
444 | /** variable setting function for base types */ |
445 | static boolean set_base_var(variable_t& p_var, Module_Param& p_new_value); | |
446 | ||
7329404e BB |
447 | /** variable printing function for value arrays */ |
448 | template <typename T_type, unsigned int array_size, int index_offset> | |
449 | static CHARSTRING print_value_array(const variable_t& p_var) | |
450 | { | |
f08ff9ca | 451 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e | 452 | TTCN_Logger::begin_event_log2str(); |
f08ff9ca | 453 | ((VALUE_ARRAY<T_type, array_size, index_offset>*)ptr)->log(); |
7329404e BB |
454 | return TTCN_Logger::end_event_log2str(); |
455 | } | |
456 | ||
f08ff9ca BB |
457 | /** variable setting function for value arrays */ |
458 | template <typename T_type, unsigned int array_size, int index_offset> | |
459 | static boolean set_value_array(variable_t& p_var, Module_Param& p_new_value) | |
460 | { | |
461 | ((VALUE_ARRAY<T_type, array_size, index_offset>*)p_var.value)->set_param(p_new_value); | |
462 | return TRUE; | |
463 | } | |
464 | ||
7329404e BB |
465 | /** variable printing function for template arrays */ |
466 | template <typename T_value_type, typename T_template_type, | |
467 | unsigned int array_size, int index_offset> | |
468 | static CHARSTRING print_template_array(const variable_t& p_var) | |
469 | { | |
f08ff9ca | 470 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e BB |
471 | TTCN_Logger::begin_event_log2str(); |
472 | ((TEMPLATE_ARRAY<T_value_type, T_template_type, array_size, | |
f08ff9ca | 473 | index_offset>*)ptr)->log(); |
7329404e BB |
474 | return TTCN_Logger::end_event_log2str(); |
475 | } | |
476 | ||
f08ff9ca BB |
477 | /** variable setting function for template arrays */ |
478 | template <typename T_value_type, typename T_template_type, | |
479 | unsigned int array_size, int index_offset> | |
480 | static boolean set_template_array(variable_t& p_var, Module_Param& p_new_value) | |
481 | { | |
482 | ((TEMPLATE_ARRAY<T_value_type, T_template_type, array_size, | |
483 | index_offset>*)p_var.value)->set_param(p_new_value); | |
484 | return TRUE; | |
485 | } | |
486 | ||
7329404e BB |
487 | /** variable printing function for port arrays */ |
488 | template <typename T_type, unsigned int array_size, int index_offset> | |
489 | static CHARSTRING print_port_array(const variable_t& p_var) | |
490 | { | |
f08ff9ca | 491 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e | 492 | TTCN_Logger::begin_event_log2str(); |
f08ff9ca | 493 | ((PORT_ARRAY<T_type, array_size, index_offset>*)ptr)->log(); |
7329404e BB |
494 | return TTCN_Logger::end_event_log2str(); |
495 | } | |
496 | ||
497 | /** variable printing function for timer arrays */ | |
498 | template <typename T_type, unsigned int array_size, int index_offset> | |
499 | static CHARSTRING print_timer_array(const variable_t& p_var) | |
500 | { | |
f08ff9ca | 501 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e | 502 | TTCN_Logger::begin_event_log2str(); |
f08ff9ca | 503 | ((TIMER_ARRAY<T_type, array_size, index_offset>*)ptr)->log(); |
7329404e BB |
504 | return TTCN_Logger::end_event_log2str(); |
505 | } | |
506 | ||
507 | /** variable printing function for lazy parameters */ | |
508 | template <typename EXPR_TYPE> | |
509 | static CHARSTRING print_lazy_param(const variable_t& p_var) | |
510 | { | |
f08ff9ca | 511 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e | 512 | TTCN_Logger::begin_event_log2str(); |
f08ff9ca | 513 | ((Lazy_Param<EXPR_TYPE>*)ptr)->log(); |
7329404e BB |
514 | return TTCN_Logger::end_event_log2str(); |
515 | } | |
516 | ||
517 | ////////////////////////////////////////////////////// | |
518 | ////// methods called by other debugger classes ////// | |
519 | ////////////////////////////////////////////////////// | |
520 | ||
016a1a93 BB |
521 | /** returns true if the debugger is activated (through the compiler switch) */ |
522 | bool is_activated() const { return enabled; } | |
523 | ||
7329404e BB |
524 | /** returns true if the debugger is switched on */ |
525 | bool is_on() const { return active; } | |
526 | ||
016a1a93 BB |
527 | /** returns true if test execution has been halted by the debugger */ |
528 | bool is_halted() const { return halted; } | |
529 | ||
530 | /** prints the formatted string to the console and/or output file | |
531 | * (used for printing notifications or error messages) */ | |
532 | void print(int return_type, const char* fmt, ...) const; | |
533 | ||
534 | /** adds the formatted string to the currently executed command's result string */ | |
535 | void add_to_result(const char* fmt, ...); | |
7329404e BB |
536 | |
537 | /** adds the specified function object pointer to the call stack | |
538 | * (only if the debugger is switched on) */ | |
539 | void add_function(TTCN3_Debug_Function* p_function); | |
540 | ||
541 | /** adds the specified scope object pointer to the current function's scope list | |
542 | * (only if the debugger is switched on and the call stack is not empty) */ | |
543 | void add_scope(TTCN3_Debug_Scope* p_scope); | |
544 | ||
545 | /** removes the specified function object pointer from the call stack, if it is | |
546 | * the function at the top of the stack */ | |
547 | void remove_function(TTCN3_Debug_Function* p_function); | |
548 | ||
549 | /** removes the specified scope object pointer from the current function's scope list | |
550 | * (only if the call stack is not empty) */ | |
551 | void remove_scope(TTCN3_Debug_Scope* p_scope); | |
552 | ||
f08ff9ca BB |
553 | /** finds or creates, and returns the constant variable entry specified by |
554 | * the parameters | |
7329404e BB |
555 | * |
556 | * if the call stack is empty, an entry for a global or component variable is | |
557 | * created and stored in the main debugger object (if it doesn't already exist); | |
558 | * if the call stack is not empty (and if the debugger is switched on), the | |
016a1a93 | 559 | * variable entry for a local variable is created and stored by the current function */ |
f08ff9ca | 560 | variable_t* add_variable(const void* p_value, const char* p_name, const char* p_type, |
1cb5b229 | 561 | const char* p_module, print_function_t p_print_function); |
f08ff9ca BB |
562 | |
563 | /** same as before, but for non-constant variables */ | |
564 | variable_t* add_variable(void* p_value, const char* p_name, const char* p_type, | |
1cb5b229 BB |
565 | const char* p_module, print_function_t p_print_function, |
566 | set_function_t p_set_function); | |
7329404e BB |
567 | |
568 | /** removes the variable entry for the specified local variable in the current | |
569 | * function (only if the call stack is not empty) */ | |
570 | void remove_variable(const variable_t* p_var); | |
571 | ||
572 | /** returns the global scope object associated with the specified module */ | |
573 | const TTCN3_Debug_Scope* get_global_scope(const char* p_module) const; | |
574 | ||
575 | /** returns the component scope object associated with the specified component type */ | |
576 | const TTCN3_Debug_Scope* get_component_scope(const char* p_component) const; | |
577 | ||
cf2b6056 BB |
578 | /** stores the specified snapshot of a function call, together with a time stamp |
579 | * (the debugger is responsible for freeing the string parameter) */ | |
580 | void store_function_call(char* p_snapshot); | |
7329404e BB |
581 | |
582 | /** executes a command received from the user interface */ | |
016a1a93 BB |
583 | void execute_command(int p_command, int p_argument_count, char** p_arguments); |
584 | ||
cf2b6056 BB |
585 | /** called when a PTC is forked from the HC process |
586 | * contains supplementary initializations (i.e. opening of file pointers and | |
587 | * allocations of buffers) that the HC's debugger does not perform, but are | |
588 | * needed by the PTC's debugger */ | |
589 | void init_PTC_settings(); | |
f08ff9ca BB |
590 | |
591 | /** indicates whether an 'exit all' command has been issued | |
592 | * (this causes the execution of tests in the current queue to stop) */ | |
593 | bool is_exiting() const { return exiting; } | |
594 | ||
595 | /** sets the debugger to halt test execution at start (only in single mode) */ | |
596 | void set_halt_at_start() { halt_at_start = true; } | |
597 | ||
598 | /** sets the specified batch file to be executed at the start of test execution | |
599 | * (only in single mode) */ | |
600 | void set_initial_batch_file(const char* p_batch_file) { | |
601 | initial_batch_file = p_batch_file; | |
602 | } | |
7329404e BB |
603 | }; |
604 | ||
605 | /** the main debugger object */ | |
606 | extern TTCN3_Debugger ttcn3_debugger; | |
607 | ||
608 | ||
609 | ////////////////////////////////////////////////////// | |
610 | //////////////// TTCN3_Debug_Scope /////////////////// | |
611 | ////////////////////////////////////////////////////// | |
612 | ||
613 | /** debugger scope class | |
614 | * | |
615 | * instantiated at the beginning of every code block in the TTCN-3 code (except | |
616 | * for the code blocks of functions), plus one (global scope) instance is created | |
617 | * for every module and one (component scope) for every component type | |
618 | * | |
619 | * the class' main purpose is to track which local variables were created in the | |
620 | * current code block or to track which of the main debugger object's variables | |
621 | * belong to which global or component scope */ | |
622 | class TTCN3_Debug_Scope { | |
623 | ||
624 | /** list of pointers to local variable entries from the current function object or | |
625 | * global or component variable entries from the main debugger object | |
626 | * (the elements are not owned)*/ | |
f08ff9ca | 627 | Vector<TTCN3_Debugger::variable_t*> variables; |
7329404e BB |
628 | |
629 | public: | |
630 | ||
631 | /** constructor - lets the current function know of this new scope */ | |
632 | TTCN3_Debug_Scope(); | |
633 | ||
634 | /** destructor - tells the current function to delete the variable entries listed | |
635 | * in this instance */ | |
636 | ~TTCN3_Debug_Scope(); | |
637 | ||
638 | ////////////////////////////////////////////////////// | |
639 | ////// methods called from TITAN generated code ////// | |
640 | ////////////////////////////////////////////////////// | |
641 | ||
642 | /** passes the parameters to the main debugger or current function object to | |
f08ff9ca BB |
643 | * create and store a (constant) variable entry from them, and tracks this new |
644 | * variable by storing a pointer to it | |
7329404e BB |
645 | * (local variables are only created and stored if the debugger is switched on) */ |
646 | void add_variable(const void* p_value, const char* p_name, const char* p_type, | |
1cb5b229 | 647 | const char* p_module, TTCN3_Debugger::print_function_t p_print_function); |
f08ff9ca BB |
648 | |
649 | /** same as before, but for non-constant variables */ | |
650 | void add_variable(void* p_value, const char* p_name, const char* p_type, | |
1cb5b229 | 651 | const char* p_module, TTCN3_Debugger::print_function_t p_print_function, |
f08ff9ca | 652 | TTCN3_Debugger::set_function_t p_set_function); |
7329404e BB |
653 | |
654 | ////////////////////////////////////////////////////// | |
655 | ////// methods called by other debugger classes ////// | |
656 | ////////////////////////////////////////////////////// | |
657 | ||
658 | /** returns true if there is at least one variable in the scope object */ | |
659 | bool has_variables() const { return !variables.empty(); } | |
660 | ||
1cb5b229 BB |
661 | /** returns the specified variable, if found, otherwise returns NULL |
662 | * (the name searched for can also be prefixed with the module name in | |
663 | * case of global variables) */ | |
f08ff9ca | 664 | TTCN3_Debugger::variable_t* find_variable(const char* p_name) const; |
7329404e | 665 | |
1cb5b229 BB |
666 | /** prints the names of variables in this scope that match the specified; |
667 | * names of imported global variables are prefixed with their module's name | |
016a1a93 | 668 | * @param p_posix_regexp the pattern converted into a POSIX regex structure |
1cb5b229 BB |
669 | * @param p_first true if no variables have been printed yet |
670 | * @param p_module name of the current module, if it's a global scope, | |
671 | * otherwise NULL */ | |
672 | void list_variables(regex_t* p_posix_regexp, bool& p_first, | |
673 | const char* p_module) const; | |
7329404e BB |
674 | }; |
675 | ||
676 | ||
677 | ////////////////////////////////////////////////////// | |
678 | /////////////// TTCN3_Debug_Function ///////////////// | |
679 | ////////////////////////////////////////////////////// | |
680 | ||
681 | /** debugger function class | |
682 | * | |
683 | * instantiated at the beginning of every function, destroyed when function execution ends | |
684 | * | |
685 | * tracks all variables created during the function's execution (local variables), | |
686 | * including the function's parameters, and stores the function's return value */ | |
687 | class TTCN3_Debug_Function { | |
688 | ||
689 | /** name of the function, not owned */ | |
690 | const char* function_name; | |
691 | ||
692 | /** the TTCN-3 keyword(s) used to define the function ("function", "testcase", | |
693 | * "altstep", "template" or "external function"), not owned */ | |
694 | const char* function_type; | |
695 | ||
696 | /** name of the module this function is defined in, not owned */ | |
697 | const char* module_name; | |
698 | ||
699 | /** names of the function's parameters (in the order of their declaration), owned */ | |
700 | charstring_list* parameter_names; | |
701 | ||
702 | /** types (directions) of the function's parameters ("in", "inout" or "out"), owned */ | |
703 | charstring_list* parameter_types; | |
704 | ||
705 | /** list of local variables tracked by this object, the array elements are owned */ | |
706 | Vector<TTCN3_Debugger::variable_t*> variables; | |
707 | ||
708 | /** list of pointers to the scope objects of code blocks in the function, | |
709 | * the elements are not owned | |
710 | * (currently not used for anything) */ | |
711 | Vector<TTCN3_Debug_Scope*> scopes; | |
712 | ||
713 | /** pointer to the global scope object, not owned | |
714 | * (may be NULL, if the module's global scope is empty) */ | |
715 | const TTCN3_Debug_Scope* global_scope; | |
716 | ||
717 | /** pointer to the runs-on component's scope object, not owned | |
718 | * (may be NULL, if the component's scope is empty or if the function has no runs-on clause) */ | |
719 | const TTCN3_Debug_Scope* component_scope; | |
720 | ||
721 | /** the function's return value (unbound if the return value has not been set yet, | |
722 | * or if the function doesn't return anything) | |
723 | * | |
724 | * since this is only set right before the function ends, it is only accessible | |
725 | * from the destructor */ | |
726 | CHARSTRING return_value; | |
727 | ||
728 | public: | |
729 | ||
730 | /** constructor - initializes the instance with the specified parameters, | |
731 | * retrieves the global scope and component scope from the main debugger object */ | |
732 | TTCN3_Debug_Function(const char* p_name, const char* p_type, const char* p_module, | |
733 | const charstring_list& p_parameter_names, const charstring_list& p_parameter_types, const char* p_component_name); | |
734 | ||
735 | /** destructor - frees resources and saves the function's ending snapshot | |
736 | * (including the values of 'out' and 'inout' parameters and the return value) | |
737 | * in the main debugger object (only if the debugger is switched on) */ | |
738 | ~TTCN3_Debug_Function(); | |
739 | ||
740 | ////////////////////////////////////////////////////// | |
741 | ////// methods called from TITAN generated code ////// | |
742 | ////////////////////////////////////////////////////// | |
743 | ||
f08ff9ca | 744 | /** creates, stores and returns the variable entry of the local (constant) variable |
7329404e | 745 | * specified by the parameters (only if the debugger is switched on) */ |
f08ff9ca | 746 | TTCN3_Debugger::variable_t* add_variable(const void* p_value, const char* p_name, |
1cb5b229 BB |
747 | const char* p_type, const char* p_module, |
748 | TTCN3_Debugger::print_function_t p_print_function); | |
f08ff9ca BB |
749 | |
750 | /** same as before, but for non-constant variables */ | |
751 | TTCN3_Debugger::variable_t* add_variable(void* p_value, const char* p_name, | |
1cb5b229 BB |
752 | const char* p_type, const char* p_module, |
753 | TTCN3_Debugger::print_function_t p_print_function, | |
f08ff9ca | 754 | TTCN3_Debugger::set_function_t p_set_function); |
7329404e BB |
755 | |
756 | /** stores the string representation of the value returned by the function */ | |
757 | void set_return_value(const CHARSTRING& p_value); | |
758 | ||
016a1a93 | 759 | /** saves the function's initial snapshot (including the values of 'in' and |
7329404e BB |
760 | * 'inout' parameters) in the main debugger object |
761 | * (only if the debugger is switched on) */ | |
762 | void initial_snapshot() const; | |
763 | ||
764 | ////////////////////////////////////////////////////// | |
765 | ////// methods called by other debugger classes ////// | |
766 | ////////////////////////////////////////////////////// | |
767 | ||
768 | /** adds the specified scope object pointer to the function's scope list */ | |
769 | void add_scope(TTCN3_Debug_Scope* p_scope); | |
770 | ||
771 | /** removes the specified scope object pointer from the function's scope list, | |
772 | * if it is the last scope in the list */ | |
773 | void remove_scope(TTCN3_Debug_Scope* p_scope); | |
774 | ||
775 | /** removes the specified variable from the variable list */ | |
776 | void remove_variable(const TTCN3_Debugger::variable_t* p_var); | |
777 | ||
778 | /** searches for the variable entry with the specified name in the function's | |
779 | * local variable list, the global scope (if any) and the component scope (if any), | |
780 | * returns NULL, if the variable was not found */ | |
f08ff9ca | 781 | TTCN3_Debugger::variable_t* find_variable(const char* p_name) const; |
7329404e BB |
782 | |
783 | /** prints the function's type, name and current values of parameters */ | |
784 | void print_function() const; | |
785 | ||
cf2b6056 BB |
786 | /** returns the name of the function */ |
787 | const char* get_function_name() const { return function_name; } | |
788 | ||
7329404e BB |
789 | /** returns the name of the module the function was defined in */ |
790 | const char* get_module_name() const { return module_name; } | |
791 | ||
792 | /** prints the names of variables specified by the parameters (separated by spaces) | |
793 | * handles the D_LIST_VARIABLES debugger command | |
794 | * @param p_scope specifies which scope to print variables from: | |
795 | * - "local" - the function's local variables (including variables in code blocks) | |
796 | * - "global" - variables in the module's global scope | |
797 | * - "comp" or "component" - variables in the function's runs-on component scope | |
798 | * - "all" - all variables visible in the function (i.e. all of the above) | |
799 | * @param p_filter a pattern to filter variable names further */ | |
800 | void list_variables(const char* p_scope, const char* p_filter) const; | |
f08ff9ca BB |
801 | |
802 | /** returns true if this instance belongs to a control part */ | |
803 | bool is_control_part() const; | |
804 | ||
805 | /** returns true if this instance belongs to a test case */ | |
806 | bool is_test_case() const; | |
7329404e BB |
807 | }; |
808 | ||
809 | /** This macro stores a function's return value in the current function. | |
810 | * The returned value might be an expression, so it is copied to a temporary first, | |
811 | * to avoid being evaluated twice. */ | |
812 | #define DEBUGGER_STORE_RETURN_VALUE(tmp, ret_val) \ | |
813 | (tmp = (ret_val), \ | |
814 | ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), \ | |
815 | tmp.log(), \ | |
816 | TTCN_Logger::end_event_log2str())), \ | |
817 | tmp) | |
818 | ||
819 | #endif /* DEBUGGER_HH */ | |
820 |