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
10 * Baranyi, Botond – initial implementation
12 ******************************************************************************/
14 #include "Debugger.hh"
16 //////////////////////////////////////////////////////
17 ////////////////// TTCN3_Debugger ////////////////////
18 //////////////////////////////////////////////////////
20 TTCN3_Debugger ttcn3_debugger
;
22 void TTCN3_Debugger::switch_off()
25 print("The debugger is already switched off.\n");
28 print("Debugger switched off.\n");
33 void TTCN3_Debugger::switch_on()
36 print("The debugger is already switched on.\n");
39 print("Debugger switched on.\n");
44 void TTCN3_Debugger::add_breakpoint(const char* p_module
, int p_line
/*const char* batch_file*/)
46 if (find_breakpoint(p_module
, p_line
) == breakpoints
.size()) {
48 bp
.module
= mcopystr(p_module
);
50 breakpoints
.push_back(bp
);
51 print("Breakpoint added in module '%s' at line %d.\n", p_module
, p_line
);
54 print("Breakpoint already set in module '%s' at line %d.\n", p_module
, p_line
);
58 void TTCN3_Debugger::remove_breakpoint(const char* p_module
, int p_line
)
60 size_t pos
= find_breakpoint(p_module
, p_line
);
61 if (pos
!= breakpoints
.size()) {
62 Free(breakpoints
[pos
].module
);
63 breakpoints
.erase_at(pos
);
64 print("Breakpoint removed in module '%s' from line %d.\n", p_module
, p_line
);
67 print("No breakpoint found in module '%s' at line %d.\n", p_module
, p_line
);
71 void TTCN3_Debugger::set_special_breakpoint(special_breakpoint_t p_type
, const char* p_state_str
)
74 if (!strcmp(p_state_str
, "yes")) {
77 else if(!strcmp(p_state_str
, "no")) {
82 print("Argument 1 is invalid.\n");
85 const char* sbp_type_str
;
88 case SBP_FAIL_VERDICT
:
89 state_changed
= (fail_behavior
!= new_state
);
90 fail_behavior
= new_state
;
91 sbp_type_str
= "Fail";
93 case SBP_ERROR_VERDICT
:
94 state_changed
= (error_behavior
!= new_state
);
95 error_behavior
= new_state
;
96 sbp_type_str
= "Error";
99 // should never happen
102 print("%s verdict behavior %sset to %s.\n", sbp_type_str
,
103 state_changed
? "" : "was already ",
104 new_state
? "halt the program" : "do nothing");
107 void TTCN3_Debugger::print_call_stack()
109 for (size_t i
= call_stack
.size(); i
!= 0; --i
) {
110 print("%d.\t", (int)call_stack
.size() - (int)i
+ 1);
111 call_stack
[i
- 1]->print_function();
115 void TTCN3_Debugger::set_stack_level(int new_level
)
117 if (new_level
< 0 || (size_t)new_level
> call_stack
.size()) {
118 print("Invalid new stack level.\n");
121 stack_level
= new_level
;
125 void TTCN3_Debugger::print_variable(const TTCN3_Debugger::variable_t
* p_var
) const
127 print("%s := %s\n", p_var
->name
, (const char*)p_var
->print_function(*p_var
));
130 void TTCN3_Debugger::set_output(const char* p_output_type
, const char* p_file_name
)
133 if (!strcmp(p_output_type
, "stdout")) {
136 else if (!strcmp(p_output_type
, "stderr")) {
139 else if (!strcmp(p_output_type
, "file")) {
140 if (p_file_name
== NULL
) {
141 print("Missing output file name.\n");
144 new_fp
= fopen(p_file_name
, "w");
145 if (new_fp
== NULL
) {
146 print("Failed to open file '%s' for writing.\n");
151 print("Argument 1 is invalid.\n");
154 // don't close the previous file, if the command's parameters are invalid
155 if (output
!= stdout
&& output
!= stderr
) {
161 size_t TTCN3_Debugger::find_breakpoint(const char* p_module
, int p_line
) const
163 for (size_t i
= 0; i
< breakpoints
.size(); ++i
) {
164 if (!strcmp(breakpoints
[i
].module
, p_module
) && breakpoints
[i
].line
== p_line
) {
168 return breakpoints
.size();
171 TTCN3_Debugger::variable_t
* TTCN3_Debugger::find_variable(const void* p_value
) const
173 for (size_t i
= 0; i
< variables
.size(); ++i
) {
174 if (variables
[i
]->value
== p_value
) {
181 TTCN3_Debugger::TTCN3_Debugger()
186 last_breakpoint_entry
.module
= NULL
;
187 last_breakpoint_entry
.line
= 0;
189 fail_behavior
= false;
190 error_behavior
= false;
193 TTCN3_Debugger::~TTCN3_Debugger()
195 if (output
!= stdout
&& output
!= stderr
) {
198 for (size_t i
= 0; i
< breakpoints
.size(); ++i
) {
199 Free(breakpoints
[i
].module
);
201 for (size_t i
= 0; i
< global_scopes
.size(); ++i
) {
202 delete global_scopes
[i
].scope
;
204 for (size_t i
= 0; i
< component_scopes
.size(); ++i
) {
205 delete component_scopes
[i
].scope
;
207 for (size_t i
= 0; i
< variables
.size(); ++i
) {
213 TTCN3_Debug_Scope
* TTCN3_Debugger::add_global_scope(const char* p_module
)
215 named_scope_t global_scope
;
216 global_scope
.name
= p_module
;
217 global_scope
.scope
= new TTCN3_Debug_Scope();
218 global_scopes
.push_back(global_scope
);
219 return global_scope
.scope
;
222 TTCN3_Debug_Scope
* TTCN3_Debugger::add_component_scope(const char* p_component
)
224 named_scope_t component_scope
;
225 component_scope
.name
= p_component
;
226 component_scope
.scope
= new TTCN3_Debug_Scope();
227 component_scopes
.push_back(component_scope
);
228 return component_scope
.scope
;
231 void TTCN3_Debugger::set_return_value(const CHARSTRING
& p_value
)
234 call_stack
[call_stack
.size() - 1]->set_return_value(p_value
);
238 void TTCN3_Debugger::breakpoint_entry(int p_line
/*bool p_stepping_helper*/)
240 if (active
&& !call_stack
.empty()) {
241 const char* module_name
= call_stack
[call_stack
.size() - 1]->get_module_name();
242 bool trigger
= false;
243 const char* trigger_type
;
246 case SBP_FAIL_VERDICT
:
247 trigger
= fail_behavior
;
248 trigger_type
= "Fail verdict";
249 actual_line
= last_breakpoint_entry
.line
;
251 case SBP_ERROR_VERDICT
:
252 trigger
= error_behavior
;
253 trigger_type
= "Error verdict";
254 actual_line
= last_breakpoint_entry
.line
;
258 trigger
= (last_breakpoint_entry
.line
== 0 || p_line
!= last_breakpoint_entry
.line
||
259 module_name
!= last_breakpoint_entry
.module
) &&
260 find_breakpoint(module_name
, p_line
) != breakpoints
.size();
261 trigger_type
= "Breakpoint";
262 actual_line
= p_line
;
265 // make sure it's not the same breakpoint entry as last time
267 stack_level
= call_stack
.size() - 1;
268 print("%s reached in module '%s' at line %d.\n", trigger_type
,
269 module_name
, actual_line
);
270 ///////////////////////////////////////////////////////////////////////////////////
271 /*print("##################################################\n");
272 print("Call stack:\n");
273 charstring_list params = NULL_VALUE;
274 execute_command(D_PRINT_CALL_STACK, params);
275 print("##################################################\n");
276 print("Variables: ");
277 params[0] = "global";
278 execute_command(D_LIST_VARIABLES, params);
281 const TTCN3_Debug_Scope* glob_scope = get_global_scope(module_name);
282 for (size_t i = 0; i < variables.size(); ++i) {
283 if (glob_scope->find_variable(variables[i]->name) != NULL) {
284 params[idx++] = variables[i]->name;
287 execute_command(D_PRINT_VARIABLE, params);
288 print("##################################################\n");
289 print("Function call snapshots:\n");
291 execute_command(D_PRINT_SNAPSHOTS, params);*/
292 ///////////////////////////////////////////////////////////////////////////////////
294 last_breakpoint_entry
.module
= (char*)module_name
;
295 last_breakpoint_entry
.line
= p_line
;
299 CHARSTRING
TTCN3_Debugger::print_base_var(const TTCN3_Debugger::variable_t
& p_var
)
301 TTCN_Logger::begin_event_log2str();
302 if (!strcmp(p_var
.type_name
, "bitstring")) {
303 ((const BITSTRING
*)p_var
.value
)->log();
305 else if (!strcmp(p_var
.type_name
, "bitstring template")) {
306 ((const BITSTRING_template
*)p_var
.value
)->log();
308 else if (!strcmp(p_var
.type_name
, "boolean")) {
309 ((const BOOLEAN
*)p_var
.value
)->log();
311 else if (!strcmp(p_var
.type_name
, "boolean template")) {
312 ((const BOOLEAN_template
*)p_var
.value
)->log();
314 else if (!strcmp(p_var
.type_name
, "charstring")) {
315 ((const CHARSTRING
*)p_var
.value
)->log();
317 else if (!strcmp(p_var
.type_name
, "charstring template")) {
318 ((const CHARSTRING_template
*)p_var
.value
)->log();
320 else if (!strcmp(p_var
.type_name
, "float")) {
321 ((const FLOAT
*)p_var
.value
)->log();
323 else if (!strcmp(p_var
.type_name
, "float template")) {
324 ((const FLOAT_template
*)p_var
.value
)->log();
326 else if (!strcmp(p_var
.type_name
, "hexstring")) {
327 ((const HEXSTRING
*)p_var
.value
)->log();
329 else if (!strcmp(p_var
.type_name
, "hexstring template")) {
330 ((const HEXSTRING_template
*)p_var
.value
)->log();
332 else if (!strcmp(p_var
.type_name
, "integer")) {
333 ((const INTEGER
*)p_var
.value
)->log();
335 else if (!strcmp(p_var
.type_name
, "integer template")) {
336 ((const INTEGER_template
*)p_var
.value
)->log();
338 else if (!strcmp(p_var
.type_name
, "objid")) {
339 ((const OBJID
*)p_var
.value
)->log();
341 else if (!strcmp(p_var
.type_name
, "objid template")) {
342 ((const OBJID_template
*)p_var
.value
)->log();
344 else if (!strcmp(p_var
.type_name
, "octetstring")) {
345 ((const OCTETSTRING
*)p_var
.value
)->log();
347 else if (!strcmp(p_var
.type_name
, "octetstring template")) {
348 ((const OCTETSTRING_template
*)p_var
.value
)->log();
350 else if (!strcmp(p_var
.type_name
, "universal charstring")) {
351 ((const UNIVERSAL_CHARSTRING
*)p_var
.value
)->log();
353 else if (!strcmp(p_var
.type_name
, "universal charstring template")) {
354 ((const UNIVERSAL_CHARSTRING_template
*)p_var
.value
)->log();
356 else if (!strcmp(p_var
.type_name
, "verdicttype")) {
357 ((const VERDICTTYPE
*)p_var
.value
)->log();
359 else if (!strcmp(p_var
.type_name
, "verdicttype template")) {
360 ((const VERDICTTYPE_template
*)p_var
.value
)->log();
362 else if (!strcmp(p_var
.type_name
, "component")) {
363 ((const COMPONENT
*)p_var
.value
)->log();
365 else if (!strcmp(p_var
.type_name
, "component template")) {
366 ((const COMPONENT_template
*)p_var
.value
)->log();
368 else if (!strcmp(p_var
.type_name
, "default")) {
369 ((const DEFAULT
*)p_var
.value
)->log();
371 else if (!strcmp(p_var
.type_name
, "default template")) {
372 ((const DEFAULT_template
*)p_var
.value
)->log();
374 else if (!strcmp(p_var
.type_name
, "timer")) {
375 ((const TIMER
*)p_var
.value
)->log();
377 else if (!strcmp(p_var
.type_name
, "NULL")) {
378 ((const ASN_NULL
*)p_var
.value
)->log();
380 else if (!strcmp(p_var
.type_name
, "NULL template")) {
381 ((const ASN_NULL_template
*)p_var
.value
)->log();
383 else if (!strcmp(p_var
.type_name
, "CHARACTER STRING")) {
384 ((const CHARACTER_STRING
*)p_var
.value
)->log();
386 else if (!strcmp(p_var
.type_name
, "CHARACTER STRING template")) {
387 ((const CHARACTER_STRING_template
*)p_var
.value
)->log();
389 else if (!strcmp(p_var
.type_name
, "EMBEDDED PDV")) {
390 ((const EMBEDDED_PDV
*)p_var
.value
)->log();
392 else if (!strcmp(p_var
.type_name
, "EMBEDDED PDV template")) {
393 ((const EMBEDDED_PDV_template
*)p_var
.value
)->log();
395 else if (!strcmp(p_var
.type_name
, "EXTERNAL")) {
396 ((const EXTERNAL
*)p_var
.value
)->log();
398 else if (!strcmp(p_var
.type_name
, "EXTERNAL template")) {
399 ((const EXTERNAL_template
*)p_var
.value
)->log();
402 TTCN_Logger::log_event_str("<unrecognized value or template>");
404 return TTCN_Logger::end_event_log2str();
407 void TTCN3_Debugger::print(const char* fmt
, ...) const
410 va_start(parameters
, fmt
);
411 vfprintf(output
, fmt
, parameters
);
416 void TTCN3_Debugger::add_function(TTCN3_Debug_Function
* p_function
)
419 call_stack
.push_back(p_function
);
423 void TTCN3_Debugger::add_scope(TTCN3_Debug_Scope
* p_scope
)
425 if (active
&& !call_stack
.empty()) {
426 call_stack
[call_stack
.size() - 1]->add_scope(p_scope
);
430 void TTCN3_Debugger::remove_function(TTCN3_Debug_Function
* p_function
)
432 if (!call_stack
.empty() && call_stack
[call_stack
.size() - 1] == p_function
) {
433 call_stack
.erase_at(call_stack
.size() - 1);
437 void TTCN3_Debugger::remove_scope(TTCN3_Debug_Scope
* p_scope
)
439 if (!call_stack
.empty()) {
440 call_stack
[call_stack
.size() - 1]->remove_scope(p_scope
);
444 const TTCN3_Debugger::variable_t
* TTCN3_Debugger::add_variable(const void* p_value
,
447 CHARSTRING (*p_print_function
)(const TTCN3_Debugger::variable_t
&))
450 if (call_stack
.empty()) {
451 // no call stack yet, so this is a global or component variable
452 variable_t
* var
= find_variable(p_value
);
454 var
= new TTCN3_Debugger::variable_t
;
455 var
->value
= p_value
;
457 var
->type_name
= p_type
;
458 var
->print_function
= p_print_function
;
459 variables
.push_back(var
);
464 // it's a local variable for the top-most function
465 return call_stack
[call_stack
.size() - 1]->add_variable(p_value
, p_name
, p_type
, p_print_function
);
470 void TTCN3_Debugger::remove_variable(const variable_t
* p_var
)
472 if (active
&& !call_stack
.empty()) {
473 call_stack
[call_stack
.size() - 1]->remove_variable(p_var
);
477 const TTCN3_Debug_Scope
* TTCN3_Debugger::get_global_scope(const char* p_module
) const
479 for (size_t i
= 0; i
< global_scopes
.size(); ++i
) {
480 if (strcmp(global_scopes
[i
].name
, p_module
) == 0) {
481 return global_scopes
[i
].scope
;
487 const TTCN3_Debug_Scope
* TTCN3_Debugger::get_component_scope(const char* p_component
) const
489 for (size_t i
= 0; i
< component_scopes
.size(); ++i
) {
490 if (strcmp(component_scopes
[i
].name
, p_component
) == 0) {
491 return component_scopes
[i
].scope
;
497 void TTCN3_Debugger::add_snapshot(const char* p_snapshot
)
499 snapshots
= mputstr(snapshots
, p_snapshot
);
502 #define CHECK_NOF_ARGUMENTS(exp_num) \
503 if (exp_num != p_arguments.size_of()) { \
504 print("Invalid number of arguments. Expected %d, got %d.\n", \
505 (int)exp_num, (int)p_arguments.size_of()); \
509 #define CHECK_NOF_ARGUMENTS_RANGE(min, max) \
510 if ((int)min > p_arguments.size_of() || (int)max < p_arguments.size_of()) { \
511 print("Invalid number of arguments. Expected at least %d and at most %d, got %d.\n", \
512 (int)min, (int)max, p_arguments.size_of()); \
516 #define CHECK_NOF_ARGUMENTS_MIN(min) \
517 if ((int)min > p_arguments.size_of()) { \
518 print("Invalid number of arguments. Expected at least %d, got %d.\n", \
519 (int)min, p_arguments.size_of()); \
523 #define CHECK_INT_ARGUMENT(arg_idx) \
525 const char* str = (const char*)p_arguments[arg_idx]; \
526 for (int i = 0; i < p_arguments[arg_idx].lengthof(); ++i) { \
527 if (str[i] < '0' || str[i] > '9') { \
528 print("Argument %d is not an integer.\n", (int)(arg_idx + 1)); \
534 #define CHECK_CALL_STACK \
535 if (call_stack.empty()) { \
536 print("This command can only be executed when the program is running.\n"); \
540 void TTCN3_Debugger::execute_command(TTCN3_Debugger::debug_command_t p_command
,
541 const charstring_list
& p_arguments
)
543 if (!active
&& p_command
!= D_SWITCH_ON
&& p_command
!= D_SWITCH_OFF
) {
544 print("Cannot run debug commands while the debugger is switched off.\n");
547 for (int i
= 0; i
< p_arguments
.size_of(); ++i
) {
548 if (!p_arguments
[i
].is_bound()) {
549 print("Argument %d is unbound.\n", i
+ 1);
555 CHECK_NOF_ARGUMENTS(0)
559 CHECK_NOF_ARGUMENTS(0)
562 case D_ADD_BREAKPOINT
:
563 CHECK_NOF_ARGUMENTS(2)
564 CHECK_INT_ARGUMENT(1)
565 add_breakpoint(p_arguments
[0], str2int(p_arguments
[1]));
567 case D_REMOVE_BREAKPOINT
:
568 CHECK_NOF_ARGUMENTS(2)
569 CHECK_INT_ARGUMENT(1)
570 remove_breakpoint(p_arguments
[0], str2int(p_arguments
[1]));
572 case D_SET_ERROR_BEHAVIOR
:
573 CHECK_NOF_ARGUMENTS(1)
574 set_special_breakpoint(SBP_ERROR_VERDICT
, p_arguments
[0]);
576 case D_SET_FAIL_BEHAVIOR
:
577 CHECK_NOF_ARGUMENTS(1)
578 set_special_breakpoint(SBP_FAIL_VERDICT
, p_arguments
[0]);
582 CHECK_NOF_ARGUMENTS_RANGE(1, 2)
583 set_output(p_arguments
[0], (p_arguments
.size_of() == 2) ? (const char*)p_arguments
[1] : NULL
);
586 case D_PRINT_CALL_STACK
:
588 CHECK_NOF_ARGUMENTS(0)
591 case D_SET_STACK_LEVEL
:
593 CHECK_NOF_ARGUMENTS(1)
594 CHECK_INT_ARGUMENT(0)
595 set_stack_level(str2int(p_arguments
[0]));
597 case D_LIST_VARIABLES
:
599 CHECK_NOF_ARGUMENTS_RANGE(1, 2)
600 call_stack
[stack_level
]->list_variables(p_arguments
[0],
601 (p_arguments
.size_of() == 2) ? (const char*)p_arguments
[1] : NULL
);
603 case D_PRINT_VARIABLE
:
605 CHECK_NOF_ARGUMENTS_MIN(1)
606 for (int i
= 0; i
< p_arguments
.size_of(); ++i
) {
607 const variable_t
* var
= call_stack
[stack_level
]->find_variable(p_arguments
[i
]);
612 print("Variable '%s' not found.\n", (const char*)p_arguments
[i
]);
617 case D_PRINT_SNAPSHOTS
:
618 CHECK_NOF_ARGUMENTS(0)
619 print("%s", snapshots
);
623 print("Command not implemented.\n");
628 //////////////////////////////////////////////////////
629 //////////////// TTCN3_Debug_Scope ///////////////////
630 //////////////////////////////////////////////////////
632 TTCN3_Debug_Scope::TTCN3_Debug_Scope()
634 ttcn3_debugger
.add_scope(this);
637 TTCN3_Debug_Scope::~TTCN3_Debug_Scope()
639 for (size_t i
= 0; i
< variables
.size(); ++i
) {
640 ttcn3_debugger
.remove_variable(variables
[i
]);
642 ttcn3_debugger
.remove_scope(this);
645 void TTCN3_Debug_Scope::add_variable(const void* p_value
,
648 CHARSTRING (*p_print_function
)(const TTCN3_Debugger::variable_t
&))
650 const TTCN3_Debugger::variable_t
* var
= ttcn3_debugger
.add_variable(p_value
, p_name
, p_type
, p_print_function
);
652 variables
.push_back(var
);
656 const TTCN3_Debugger::variable_t
* TTCN3_Debug_Scope::find_variable(const char* p_name
) const
658 for (size_t i
= 0; i
< variables
.size(); ++i
) {
659 if (strcmp(variables
[i
]->name
, p_name
) == 0) {
666 void TTCN3_Debug_Scope::list_variables(const char* p_filter
, bool& p_first
) const
668 for (size_t i
= 0; i
< variables
.size(); ++i
) {
669 // the filter is currently ignored
670 ttcn3_debugger
.print("%s%s", p_first
? "" : " ", variables
[i
]->name
);
675 //////////////////////////////////////////////////////
676 /////////////// TTCN3_Debug_Function /////////////////
677 //////////////////////////////////////////////////////
679 TTCN3_Debug_Function::TTCN3_Debug_Function(const char* p_name
,
681 const char* p_module
,
682 const charstring_list
& p_parameter_names
,
683 const charstring_list
& p_parameter_types
,
684 const char* p_component_name
)
685 : function_name(p_name
), function_type(p_type
), module_name(p_module
)
686 , parameter_names(new charstring_list(p_parameter_names
))
687 , parameter_types(new charstring_list(p_parameter_types
))
689 ttcn3_debugger
.add_function(this);
690 global_scope
= ttcn3_debugger
.get_global_scope(p_module
);
691 component_scope
= (p_component_name
!= NULL
) ?
692 ttcn3_debugger
.get_component_scope(p_component_name
) : NULL
;
693 if (function_name
== NULL
) {
694 function_name
= p_module
; // for control parts
698 TTCN3_Debug_Function::~TTCN3_Debug_Function()
700 if (ttcn3_debugger
.is_on()) {
701 char* snapshot
= mprintf("[%s]\tfinished\t%s(", function_type
, function_name
);
702 if (parameter_names
->size_of() > 0) {
703 for (int i
= 0; i
< parameter_names
->size_of(); ++i
) {
705 snapshot
= mputstr(snapshot
, ", ");
707 snapshot
= mputprintf(snapshot
, "[%s] %s := ", (const char*)((*parameter_types
)[i
]),
708 (const char*)((*parameter_names
)[i
]));
709 if ((*parameter_types
)[i
] == "out" || (*parameter_types
)[i
] == "inout") {
710 const TTCN3_Debugger::variable_t
* parameter
= find_variable((*parameter_names
)[i
]);
711 snapshot
= mputstr(snapshot
, parameter
->print_function(*parameter
));
714 snapshot
= mputc(snapshot
, '-');
718 snapshot
= mputc(snapshot
, ')');
719 if (return_value
.is_bound()) {
720 snapshot
= mputprintf(snapshot
, " returned %s", (const char*)return_value
);
722 snapshot
= mputc(snapshot
, '\n');
723 ttcn3_debugger
.add_snapshot(snapshot
);
726 for (size_t i
= 0; i
< variables
.size(); ++i
) {
729 delete parameter_names
;
730 delete parameter_types
;
731 ttcn3_debugger
.remove_function(this);
734 const TTCN3_Debugger::variable_t
* TTCN3_Debug_Function::add_variable(const void* p_value
,
737 CHARSTRING (*p_print_function
)(const TTCN3_Debugger::variable_t
&))
739 if (ttcn3_debugger
.is_on()) {
740 TTCN3_Debugger::variable_t
* var
= new TTCN3_Debugger::variable_t
;
741 var
->value
= p_value
;
743 var
->type_name
= p_type
;
744 var
->print_function
= p_print_function
;
745 variables
.push_back(var
);
751 void TTCN3_Debug_Function::set_return_value(const CHARSTRING
& p_value
)
753 return_value
= p_value
;
756 void TTCN3_Debug_Function::initial_snapshot() const
758 if (ttcn3_debugger
.is_on()) {
759 char* snapshot
= mprintf("[%s]\tstarted \t%s(", function_type
, function_name
);
760 if (parameter_names
->size_of() > 0) {
761 for (int i
= 0; i
< parameter_names
->size_of(); ++i
) {
763 snapshot
= mputstr(snapshot
, ", ");
765 snapshot
= mputprintf(snapshot
, "[%s] %s := ", (const char*)((*parameter_types
)[i
]),
766 (const char*)((*parameter_names
)[i
]));
767 if ((*parameter_types
)[i
] == "in" || (*parameter_types
)[i
] == "inout") {
768 const TTCN3_Debugger::variable_t
* parameter
= find_variable((*parameter_names
)[i
]);
769 snapshot
= mputstr(snapshot
, parameter
->print_function(*parameter
));
772 snapshot
= mputc(snapshot
, '-');
776 snapshot
= mputstr(snapshot
, ")\n");
777 ttcn3_debugger
.add_snapshot(snapshot
);
782 void TTCN3_Debug_Function::add_scope(TTCN3_Debug_Scope
* p_scope
)
784 scopes
.push_back(p_scope
);
787 void TTCN3_Debug_Function::remove_scope(TTCN3_Debug_Scope
* p_scope
)
789 if (scopes
[scopes
.size() - 1] == p_scope
) {
790 scopes
.erase_at(scopes
.size() - 1);
794 void TTCN3_Debug_Function::remove_variable(const TTCN3_Debugger::variable_t
* p_var
)
796 for (size_t i
= 0; i
< variables
.size(); ++i
) {
797 if (variables
[i
] == p_var
) {
798 variables
.erase_at(i
);
805 const TTCN3_Debugger::variable_t
* TTCN3_Debug_Function::find_variable(const char* p_name
) const
807 for (size_t i
= 0; i
< variables
.size(); ++i
) {
808 if (strcmp(variables
[i
]->name
, p_name
) == 0) {
812 // it's not a local variable, it might still be a global or component variable
813 if (component_scope
!= NULL
) {
814 const TTCN3_Debugger::variable_t
* res
= component_scope
->find_variable(p_name
);
819 return (global_scope
!= NULL
) ? global_scope
->find_variable(p_name
) : NULL
;
822 void TTCN3_Debug_Function::print_function() const
824 ttcn3_debugger
.print("[%s]\t%s(", function_type
, function_name
);
825 if (parameter_names
->size_of() > 0) {
826 for (int i
= 0; i
< parameter_names
->size_of(); ++i
) {
828 ttcn3_debugger
.print(", ");
830 const TTCN3_Debugger::variable_t
* parameter
= find_variable((*parameter_names
)[i
]);
831 ttcn3_debugger
.print("[%s] %s := %s", (const char*)(*parameter_types
)[i
],
832 (const char*)(*parameter_names
)[i
], (const char*)parameter
->print_function(*parameter
));
835 ttcn3_debugger
.print(")\n");
838 void TTCN3_Debug_Function::list_variables(const char* p_scope
, const char* p_filter
) const
841 bool list_local
= false;
842 bool list_global
= false;
843 bool list_comp
= false;
844 if (!strcmp(p_scope
, "local")) {
847 else if (!strcmp(p_scope
, "global")) {
850 else if (!strcmp(p_scope
, "comp") || !strcmp(p_scope
, "component")) {
854 if (strcmp(p_scope
, "all")) {
855 ttcn3_debugger
.print("Invalid scope. Listing variables in all scopes.\n");
862 for (size_t i
= 0; i
< variables
.size(); ++i
) {
863 ttcn3_debugger
.print("%s%s", first
? "" : " ", variables
[i
]->name
);
867 if (list_global
&& global_scope
!= NULL
&& global_scope
->has_variables()) {
868 global_scope
->list_variables(p_filter
, first
);
870 if (list_comp
&& component_scope
!= NULL
&& component_scope
->has_variables()) {
871 component_scope
->list_variables(p_filter
, first
);
874 ttcn3_debugger
.print("No variables found.");
876 ttcn3_debugger
.print("\n");