# Set it to 'yes' to enable extra features for the debugger UI in single mode
# (this requires an extra library when linking the generated code).
# Set it to 'no' to use a simplified debugger UI.
-ADVANCED_DEBUGGER_UI := yes
+ADVANCED_DEBUGGER_UI := no
# Your platform. Allowed values: SOLARIS, SOLARIS8, LINUX, FREEBSD,
# WIN32. Decided automagically if not defined (recommended).
print_function += ">";
}
- return mputprintf(str, "%s%s_scope%sadd_variable(&%s, \"%s\", \"%s\", %s%s%s);\n",
+ string module_str;
+ if (scope_name != NULL && !strcmp(scope_name, "global")) {
+ // only store the module name for global variables
+ module_str = string("\"") +
+ var_ass->get_my_scope()->get_scope_mod()->get_modid().get_ttcnname() + string("\"");
+ }
+ else {
+ module_str = "NULL";
+ }
+
+ return mputprintf(str, "%s%s_scope%sadd_variable(&%s, \"%s\", \"%s\", %s, %s%s%s);\n",
scope_name != NULL ? " " : "", // add indenting for global variables
scope_name != NULL ? scope_name : "debug", // the prefix of the debugger scope:
// ("global" for global variables, "debug" for local variables,
// so the lazy parameter evaluation code is not generated)
var_ass->get_id().get_ttcnname().c_str(), // variable name in TTCN-3
type_name.c_str(), // variable type in TTCN-3, with a suffix if it's a template
+ module_str.c_str(), // module name, where the variable was defined
print_function.c_str(), // variable printing function
is_constant ? "" : ", ", is_constant ? "" : set_function.c_str());
// variable overwriting function (not generated for constants)
#define D_SET_AUTOMATIC_BREAKPOINT 4 // 2-3, "error" or "fail", + "off", or "on" + optional batch file name
#define D_SET_OUTPUT 5 // 1-2, "console", or "file" or "both", + file name
#define D_SET_GLOBAL_BATCH_FILE 6 // 1-2, "off", or "on" + batch file name
+#define D_PRINT_SETTINGS 7 // 0
// printing and overwriting data
-#define D_SET_COMPONENT 7 // 1, "mtc" or component reference
-#define D_PRINT_CALL_STACK 8 // 0
-#define D_SET_STACK_LEVEL 9 // 1, stack level
-#define D_LIST_VARIABLES 10 // 1-2, "local", "global", "comp" or "all", + optional filter (pattern)
-#define D_PRINT_VARIABLE 11 // 1+, list of variable names
-#define D_OVERWRITE_VARIABLE 12 // 2, variable name, new value (in module parameter syntax)
-#define D_PRINT_SNAPSHOTS 13 // 0
-#define D_SET_SNAPSHOT_BEHAVIOR 14 // TBD
+#define D_LIST_COMPONENTS 8 // 0
+#define D_SET_COMPONENT 9 // 1, "mtc" or component reference
+#define D_PRINT_CALL_STACK 10 // 0
+#define D_SET_STACK_LEVEL 11 // 1, stack level
+#define D_LIST_VARIABLES 12 // 1-2, "local", "global", "comp" or "all", + optional filter (pattern)
+#define D_PRINT_VARIABLE 13 // 1+, list of variable names
+#define D_OVERWRITE_VARIABLE 14 // 2, variable name, new value (in module parameter syntax)
+#define D_PRINT_SNAPSHOTS 15 // 0
+#define D_SET_SNAPSHOT_BEHAVIOR 16 // TBD
// stepping
-#define D_STEP_OVER 15 // 0
-#define D_STEP_INTO 16 // 0
-#define D_STEP_OUT 17 // 0
-#define D_RUN_TO_CURSOR 18 // 2, module name and line number
+#define D_STEP_OVER 17 // 0
+#define D_STEP_INTO 18 // 0
+#define D_STEP_OUT 19 // 0
+#define D_RUN_TO_CURSOR 20 // 2, module name and line number
// the halted state
-#define D_HALT 19 // 0
-#define D_CONTINUE 20 // 0
-#define D_EXIT 21 // 1, "test" or "all"
+#define D_HALT 21 // 0
+#define D_CONTINUE 22 // 0
+#define D_EXIT 23 // 1, "test" or "all"
// initialization
-#define D_SETUP 22 // 9+:
+#define D_SETUP 24 // 9+:
// 1 argument for D_SWITCH,
// 2 arguments for D_SET_OUTPUT,
// 2 arguments (2nd and 3rd) for D_SET_AUTOMATIC_BREAKPOINT, where the first argument is "error",
#define D_SET_AUTOMATIC_BREAKPOINT_TEXT "dautobp"
#define D_SET_OUTPUT_TEXT "doutput"
#define D_SET_GLOBAL_BATCH_FILE_TEXT "dglobbatch"
-#define D_SET_COMPONENT_TEXT "dcomp"
+#define D_PRINT_SETTINGS_TEXT "dsettings"
+#define D_LIST_COMPONENTS_TEXT "dlistcomp"
+#define D_SET_COMPONENT_TEXT "dsetcomp"
#define D_PRINT_CALL_STACK_TEXT "dprintstack"
#define D_SET_STACK_LEVEL_TEXT "dstacklevel"
#define D_LIST_VARIABLES_TEXT "dlistvar"
*old_batch_file_ptr = p_batch_file != NULL ? mcopystr(p_batch_file) : NULL;
}
+void TTCN3_Debugger::print_settings()
+{
+ // on/off switch
+ add_to_result("Debugger is switched %s.\n", active ? "on" : "off");
+ // output
+ char* final_file_name = finalize_file_name(output_file_name);
+ char* file_str = output_file != NULL ? mprintf("file '%s'", final_file_name) : NULL;
+ Free(final_file_name);
+ add_to_result("Output is printed to %s%s%s.\n",
+ send_to_console ? "the console" : "",
+ (send_to_console && output_file != NULL) ? " and to " : "",
+ output_file != NULL ? file_str : "");
+ Free(file_str);
+ // global batch file
+ add_to_result("Global batch file%s%s.\n", global_batch_file != NULL ? ": " : "",
+ global_batch_file != NULL ? global_batch_file : " not set");
+ // user breakpoints
+ if (breakpoints.empty()) {
+ add_to_result("No user breakpoints.\n");
+ }
+ else {
+ add_to_result("User breakpoints:\n");
+ for (size_t i = 0; i < breakpoints.size(); ++i) {
+ const breakpoint_t& bp = breakpoints[i];
+ add_to_result("%s %d %s\n", bp.module, bp.line,
+ bp.batch_file != NULL ? bp.batch_file : "");
+ }
+ }
+ // automatic breakpoints
+ add_to_result("Automatic breakpoints:\nerror %s %s\nfail %s %s",
+ error_behavior.trigger ? "on" : "off",
+ error_behavior.batch_file != NULL ? error_behavior.batch_file : "",
+ fail_behavior.trigger ? "on" : "off",
+ fail_behavior.batch_file != NULL ? fail_behavior.batch_file : "");
+}
+
+#define STACK_LEVEL (stack_level >= 0) ? (size_t)stack_level : (call_stack.size() - 1)
+
void TTCN3_Debugger::print_call_stack()
{
for (size_t i = call_stack.size(); i != 0; --i) {
add_to_result("%d.\t", (int)call_stack.size() - (int)i + 1);
call_stack[i - 1].function->print_function();
+ if (i - 1 == (STACK_LEVEL)) {
+ // mark the active stack level with an asterisk
+ add_to_result("*");
+ }
if (i != 1) {
add_to_result("\n");
}
}
}
-#define STACK_LEVEL (stack_level >= 0) ? (size_t)stack_level : (call_stack.size() - 1)
-
void TTCN3_Debugger::print_variable(const char* p_var_name)
{
const variable_t* var = call_stack[STACK_LEVEL].function->find_variable(p_var_name);
if (var != NULL) {
- add_to_result("[%s] %s := %s", var->type_name, var->name,
- (const char*)var->print_function(*var));
+ add_to_result("[%s] %s%s%s := %s", var->type_name,
+ var->module != NULL ? var->module : "", var->module != NULL ? "." : "",
+ var->name, (const char*)var->print_function(*var));
}
else {
add_to_result("Variable '%s' not found.", p_var_name);
TTCN3_Debugger::variable_t* TTCN3_Debugger::add_variable(const void* p_value,
const char* p_name,
const char* p_type,
+ const char* p_module,
TTCN3_Debugger::print_function_t p_print_function)
{
if (call_stack.empty()) {
var->cvalue = p_value;
var->name = p_name;
var->type_name = p_type;
+ var->module = p_module;
var->print_function = p_print_function;
var->set_function = NULL;
variables.push_back(var);
else if (active) {
// it's a local variable for the top-most function
return call_stack[call_stack.size() - 1].function->add_variable(
- p_value, p_name, p_type, p_print_function);
+ p_value, p_name, p_type, p_module, p_print_function);
}
return NULL;
}
TTCN3_Debugger::variable_t* TTCN3_Debugger::add_variable(void* p_value,
const char* p_name,
const char* p_type,
+ const char* p_module,
TTCN3_Debugger::print_function_t p_print_function,
TTCN3_Debugger::set_function_t p_set_function)
{
var->value = p_value;
var->name = p_name;
var->type_name = p_type;
+ var->module = p_module;
var->print_function = p_print_function;
var->set_function = p_set_function;
variables.push_back(var);
else if (active) {
// it's a local variable for the top-most function
return call_stack[call_stack.size() - 1].function->add_variable(
- p_value, p_name, p_type, p_print_function);
+ p_value, p_name, p_type, p_module, p_print_function, p_set_function);
}
return NULL;
}
CHECK_NOF_ARGUMENTS_RANGE(1, 2)
set_global_batch_file(p_arguments[0], (p_argument_count == 2) ? p_arguments[1] : NULL);
break;
- case D_SET_COMPONENT:
- print(DRET_NOTIFICATION, "Command " D_SET_COMPONENT_TEXT " %s.",
- TTCN_Runtime::is_single() ? "is not available in single mode" :
- "should have been sent to the Main Controller");
+ case D_PRINT_SETTINGS:
+ CHECK_NOF_ARGUMENTS(0)
+ print_settings();
break;
case D_PRINT_CALL_STACK:
CHECK_CALL_STACK(true)
void TTCN3_Debug_Scope::add_variable(const void* p_value,
const char* p_name,
const char* p_type,
+ const char* p_module,
TTCN3_Debugger::print_function_t p_print_function)
{
- TTCN3_Debugger::variable_t* var = ttcn3_debugger.add_variable(p_value, p_name, p_type, p_print_function);
+ TTCN3_Debugger::variable_t* var = ttcn3_debugger.add_variable(p_value, p_name,
+ p_type, p_module, p_print_function);
if (var != NULL) {
variables.push_back(var);
}
void TTCN3_Debug_Scope::add_variable(void* p_value,
const char* p_name,
const char* p_type,
+ const char* p_module,
TTCN3_Debugger::print_function_t p_print_function,
TTCN3_Debugger::set_function_t p_set_function)
{
TTCN3_Debugger::variable_t* var = ttcn3_debugger.add_variable(p_value, p_name,
- p_type, p_print_function, p_set_function);
+ p_type, p_module, p_print_function, p_set_function);
if (var != NULL) {
variables.push_back(var);
}
TTCN3_Debugger::variable_t* TTCN3_Debug_Scope::find_variable(const char* p_name) const
{
for (size_t i = 0; i < variables.size(); ++i) {
- if (strcmp(variables[i]->name, p_name) == 0) {
- return variables[i];
+ TTCN3_Debugger::variable_t* var = variables[i];
+ if (strcmp(var->name, p_name) == 0) {
+ // the string matches the variable's name
+ return var;
+ }
+ else if (var->module != NULL) {
+ size_t name_len = strlen(var->name);
+ size_t mod_len = strlen(var->module);
+ size_t len = strlen(p_name);
+ if (len == mod_len + name_len + 1 && p_name[mod_len] == '.' &&
+ strncmp(p_name, var->module, mod_len) == 0 &&
+ strncmp(p_name + mod_len + 1, var->name, name_len) == 0) {
+ // the string matches the variable's name prefixed by its module name
+ return var;
+ }
}
}
return NULL;
}
-void TTCN3_Debug_Scope::list_variables(regex_t* p_posix_regexp, bool& p_first) const
+void TTCN3_Debug_Scope::list_variables(regex_t* p_posix_regexp, bool& p_first,
+ const char* p_module) const
{
for (size_t i = 0; i < variables.size(); ++i) {
if (p_posix_regexp == NULL ||
regexec(p_posix_regexp, variables[i]->name, 0, NULL, 0) == 0) {
- ttcn3_debugger.add_to_result("%s%s", p_first ? "" : " ", variables[i]->name);
+ bool imported = p_module != NULL && strcmp(p_module, variables[i]->module) != 0;
+ ttcn3_debugger.add_to_result("%s%s%s%s", p_first ? "" : " ",
+ imported ? variables[i]->module : "", imported ? "." : "", variables[i]->name);
p_first = false;
}
}
TTCN3_Debugger::variable_t* TTCN3_Debug_Function::add_variable(const void* p_value,
const char* p_name,
const char* p_type,
+ const char* p_module,
TTCN3_Debugger::print_function_t p_print_function)
{
if (ttcn3_debugger.is_on()) {
var->cvalue = p_value;
var->name = p_name;
var->type_name = p_type;
+ var->module = p_module;
var->print_function = p_print_function;
var->set_function = NULL;
variables.push_back(var);
TTCN3_Debugger::variable_t* TTCN3_Debug_Function::add_variable(void* p_value,
const char* p_name,
const char* p_type,
+ const char* p_module,
TTCN3_Debugger::print_function_t p_print_function,
TTCN3_Debugger::set_function_t p_set_function)
{
var->value = p_value;
var->name = p_name;
var->type_name = p_type;
+ var->module = p_module;
var->print_function = p_print_function;
var->set_function = p_set_function;
variables.push_back(var);
}
}
if (list_global && global_scope != NULL && global_scope->has_variables()) {
- global_scope->list_variables(posix_regexp, first);
+ global_scope->list_variables(posix_regexp, first, module_name);
}
if (list_comp && component_scope != NULL && component_scope->has_variables()) {
- component_scope->list_variables(posix_regexp, first);
+ component_scope->list_variables(posix_regexp, first, NULL);
}
if (first) {
ttcn3_debugger.print(DRET_NOTIFICATION, "No variables found.");
const char* name;
/** name of the variable's type, not owned */
const char* type_name;
+ /** name of the module the variable was declared in (only set for global
+ * variables, otherwise NULL), not owned */
+ const char* module;
/** variable printing function (using the variable object's log() function) */
print_function_t print_function;
/** variable setting (overwriting) function (using the variable object's
void set_automatic_breakpoint(const char* p_event_str, const char* p_state_str,
const char* p_batch_file);
+ /** prints the debugger's settings
+ * handles the D_PRINT_SETTINGS command */
+ void print_settings();
+
/** prints the current call stack
* handles the D_PRINT_CALL_STACK command */
void print_call_stack();
* if the call stack is not empty (and if the debugger is switched on), the
* variable entry for a local variable is created and stored by the current function */
variable_t* add_variable(const void* p_value, const char* p_name, const char* p_type,
- print_function_t p_print_function);
+ const char* p_module, print_function_t p_print_function);
/** same as before, but for non-constant variables */
variable_t* add_variable(void* p_value, const char* p_name, const char* p_type,
- print_function_t p_print_function, set_function_t p_set_function);
+ const char* p_module, print_function_t p_print_function,
+ set_function_t p_set_function);
/** removes the variable entry for the specified local variable in the current
* function (only if the call stack is not empty) */
* variable by storing a pointer to it
* (local variables are only created and stored if the debugger is switched on) */
void add_variable(const void* p_value, const char* p_name, const char* p_type,
- TTCN3_Debugger::print_function_t p_print_function);
+ const char* p_module, TTCN3_Debugger::print_function_t p_print_function);
/** same as before, but for non-constant variables */
void add_variable(void* p_value, const char* p_name, const char* p_type,
- TTCN3_Debugger::print_function_t p_print_function,
+ const char* p_module, TTCN3_Debugger::print_function_t p_print_function,
TTCN3_Debugger::set_function_t p_set_function);
//////////////////////////////////////////////////////
/** returns true if there is at least one variable in the scope object */
bool has_variables() const { return !variables.empty(); }
- /** returns the specified variable, if found, otherwise returns NULL */
+ /** returns the specified variable, if found, otherwise returns NULL
+ * (the name searched for can also be prefixed with the module name in
+ * case of global variables) */
TTCN3_Debugger::variable_t* find_variable(const char* p_name) const;
- /** prints the names of variables in this scope that match the specified
+ /** prints the names of variables in this scope that match the specified;
+ * names of imported global variables are prefixed with their module's name
* @param p_posix_regexp the pattern converted into a POSIX regex structure
- * @param p_first true if no variables have been printed yet */
- void list_variables(regex_t* p_posix_regexp, bool& p_first) const;
+ * @param p_first true if no variables have been printed yet
+ * @param p_module name of the current module, if it's a global scope,
+ * otherwise NULL */
+ void list_variables(regex_t* p_posix_regexp, bool& p_first,
+ const char* p_module) const;
};
/** creates, stores and returns the variable entry of the local (constant) variable
* specified by the parameters (only if the debugger is switched on) */
TTCN3_Debugger::variable_t* add_variable(const void* p_value, const char* p_name,
- const char* p_type, TTCN3_Debugger::print_function_t p_print_function);
+ const char* p_type, const char* p_module,
+ TTCN3_Debugger::print_function_t p_print_function);
/** same as before, but for non-constant variables */
TTCN3_Debugger::variable_t* add_variable(void* p_value, const char* p_name,
- const char* p_type, TTCN3_Debugger::print_function_t p_print_function,
+ const char* p_type, const char* p_module,
+ TTCN3_Debugger::print_function_t p_print_function,
TTCN3_Debugger::set_function_t p_set_function);
/** stores the string representation of the value returned by the function */
D_SET_GLOBAL_BATCH_FILE_TEXT " on|off [batch_file_name]",
"Set whether a batch file should be executed automatically when test execution "
"is halted (breakpoint-specific batch files override this setting)." },
- { D_SET_COMPONENT_TEXT, D_SET_COMPONENT,
- D_SET_COMPONENT_TEXT " mtc|<component_reference>", "Set the test component "
- "to print debug information from (not available in single mode)." },
+ { D_PRINT_SETTINGS_TEXT, D_PRINT_SETTINGS, D_PRINT_SETTINGS_TEXT,
+ "Prints the debugger's settings." },
{ D_PRINT_CALL_STACK_TEXT, D_PRINT_CALL_STACK, D_PRINT_CALL_STACK_TEXT,
"Print call stack." },
{ D_SET_STACK_LEVEL_TEXT, D_SET_STACK_LEVEL, D_SET_STACK_LEVEL_TEXT " <level>",
D_SET_GLOBAL_BATCH_FILE_TEXT " on|off [batch_file_name]",
"Set whether a batch file should be executed automatically when test execution "
"is halted (breakpoint-specific batch files override this setting)." },
+ { D_PRINT_SETTINGS_TEXT, D_PRINT_SETTINGS, D_PRINT_SETTINGS_TEXT,
+ "Prints the debugger's settings." },
+ { D_LIST_COMPONENTS_TEXT, D_LIST_COMPONENTS, D_LIST_COMPONENTS_TEXT,
+ "List the test components currently running debuggable code." },
{ D_SET_COMPONENT_TEXT, D_SET_COMPONENT,
- D_SET_COMPONENT_TEXT " mtc|<component_reference>",
+ D_SET_COMPONENT_TEXT " <component name>|<component_reference>",
"Set the test component to print debug information from." },
{ D_PRINT_CALL_STACK_TEXT, D_PRINT_CALL_STACK, D_PRINT_CALL_STACK_TEXT,
"Print call stack." },
}
}
+static bool is_tc_debuggable(const component_struct* tc)
+{
+ if (tc->comp_ref == MTC_COMPREF || tc->comp_ref == SYSTEM_COMPREF) {
+ return true; // let these pass, they are checked later
+ }
+ switch (tc->tc_state) {
+ case TC_CREATE:
+ case TC_START:
+ case TC_STOP:
+ case TC_KILL:
+ case TC_CONNECT:
+ case TC_DISCONNECT:
+ case TC_MAP:
+ case TC_UNMAP:
+ case PTC_FUNCTION:
+ case PTC_STARTING:
+ return true;
+ default:
+ return false;
+ }
+}
+
void MainController::process_debug_broadcast_req(component_struct* tc, int commandID)
{
// don't send the command back to the requesting component
}
for (component i = tc_first_comp_ref; i < n_components; ++i) {
component_struct* comp = components[i];
- if (tc != comp && comp->tc_state != PTC_STALE && comp->tc_state != TC_EXITED) {
+ if (tc != comp && is_tc_debuggable(comp)) {
send_debug_command(comp->tc_fd, commandID, "");
}
}
lock();
if (mtc != NULL) {
switch (commandID) {
- case D_SET_COMPONENT: // handled by the MC
- if (!strcmp(arguments, "mtc")) {
- notify("Debugger %sset to print data from the MTC.",
- debugger_active_tc == mtc ? "was already " : "");
- debugger_active_tc = mtc;
+ case D_LIST_COMPONENTS: // handled by the MC
+ if (*arguments != 0) {
+ notify("Invalid number of arguments, expected 0.");
}
else {
- size_t len = strlen(arguments);
- for (size_t i = 0; i < len; ++i) {
- if (arguments[i] < '0' || arguments[i] > '9') {
- notify("Argument 1 is invalid. Expected 'mtc' or integer value "
- "(component reference).");
- unlock();
- return;
+ // the active component is marked with an asterisk
+ char* result = mprintf("%s(%d)%s", mtc->comp_name, mtc->comp_ref,
+ debugger_active_tc == mtc ? "*" : "");
+ for (component i = FIRST_PTC_COMPREF; i < n_components; ++i) {
+ component_struct* comp = components[i];
+ if (comp != NULL && is_tc_debuggable(comp)) {
+ if (comp->comp_name != NULL) {
+ result = mputprintf(result, " %s(%d)%s", comp->comp_name, comp->comp_ref,
+ debugger_active_tc == comp ? "*" : "");
+ }
+ else {
+ result = mputprintf(result, " %d%s", comp->comp_ref,
+ debugger_active_tc == comp ? "*" : "");
+ }
}
}
- const component_struct* tc = lookup_component(strtol(arguments, NULL, 10));
- if (tc == NULL || tc->tc_state == PTC_STALE || tc->tc_state == TC_EXITED) {
- notify("Invalid component reference %s.", arguments);
+ notify("%s", result);
+ Free(result);
+ }
+ break;
+ case D_SET_COMPONENT: { // handled by the MC
+ bool number = true;
+ size_t len = strlen(arguments);
+ for (size_t i = 0; i < len; ++i) {
+ if (arguments[i] < '0' || arguments[i] > '9') {
+ number = false;
+ break;
}
- else {
- notify("Debugger %sset to print data from PTC %s%s%d%s.",
- debugger_active_tc == tc ? "was already " : "",
- tc->comp_name != NULL ? tc->comp_name : "",
- tc->comp_name != NULL ? "(" : "", tc->comp_ref,
- tc->comp_name != NULL ? ")" : "");
- debugger_active_tc = tc;
+ }
+ component_struct* tc = NULL;
+ if (number) { // component reference
+ tc = lookup_component(strtol(arguments, NULL, 10));
+ }
+ else { // component name
+ for (component i = 1; i < n_components; ++i) {
+ component_struct *comp = components[i];
+ if (comp != NULL && comp->comp_name != NULL && is_tc_debuggable(comp)
+ && !strcmp(comp->comp_name, arguments)) {
+ tc = comp;
+ break;
+ }
}
}
- break;
+ if (tc == system) {
+ notify("Debugging is not available on %s(%d).", tc->comp_name, tc->comp_ref);
+ }
+ else if (tc == NULL || !is_tc_debuggable(tc)) {
+ notify("Component with %s %s does not exist or is not running anything.",
+ number ? "reference" : "name", arguments);
+ }
+ else {
+ notify("Debugger %sset to print data from %s %s%s%d%s.",
+ debugger_active_tc == tc ? "was already " : "",
+ tc == mtc ? "the" : "PTC",
+ tc->comp_name != NULL ? tc->comp_name : "",
+ tc->comp_name != NULL ? "(" : "", tc->comp_ref,
+ tc->comp_name != NULL ? ")" : "");
+ debugger_active_tc = tc;
+ }
+ break; }
+ case D_PRINT_SETTINGS:
case D_PRINT_CALL_STACK:
case D_SET_STACK_LEVEL:
case D_LIST_VARIABLES:
case D_PRINT_SNAPSHOTS:
case D_STEP_OVER:
case D_STEP_INTO:
- case D_STEP_OUT:
- // it's a data printing or stepping command, needs to be sent to the
- // active component
- if (debugger_active_tc == NULL ||
- debugger_active_tc->tc_state == PTC_STALE ||
- debugger_active_tc->tc_state == TC_EXITED) {
+ case D_STEP_OUT:
+ // it's a printing or stepping command, needs to be sent to the active component
+ if (debugger_active_tc == NULL || !is_tc_debuggable(debugger_active_tc)) {
// set the MTC as active in the beginning or if the active PTC has
// finished executing
debugger_active_tc = mtc;
last_debug_command.command = commandID;
Free(last_debug_command.arguments);
last_debug_command.arguments = mcopystr(arguments);
- // no break
+ // needs to be sent to all HCs and TCs
+ send_debug_command(mtc->tc_fd, commandID, arguments);
+ for (component i = FIRST_PTC_COMPREF; i < n_components; ++i) {
+ component_struct* comp = components[i];
+ if (comp != NULL && comp->tc_state != PTC_STALE && comp->tc_state != TC_EXITED) {
+ send_debug_command(comp->tc_fd, commandID, arguments);
+ }
+ }
+ for (int i = 0; i < n_hosts; i++) {
+ host_struct* host = hosts[i];
+ if (host->hc_state != HC_DOWN) {
+ send_debug_command(host->hc_fd, commandID, arguments);
+ }
+ }
+ break;
case D_RUN_TO_CURSOR:
case D_HALT:
case D_CONTINUE:
case D_EXIT:
- // it's a global setting, a 'run to' command or a command related to the
+ // a 'run to' command or a command related to the
// halted state, needs to be sent to all HCs and TCs
send_debug_command(mtc->tc_fd, commandID, arguments);
for (component i = FIRST_PTC_COMPREF; i < n_components; ++i) {
component_struct* comp = components[i];
- if (comp != NULL && comp->tc_state != PTC_STALE && comp->tc_state != TC_EXITED) {
+ // only send it to the PTC if it is actually running something
+ if (comp != NULL && is_tc_debuggable(comp)) {
send_debug_command(comp->tc_fd, commandID, arguments);
}
}