debugger: switched advanded UI off by default, and implemented certain changes asked...
authorBotond Baranyi <botond.baranyi@ericsson.com>
Tue, 21 Jun 2016 11:09:37 +0000 (13:09 +0200)
committerBotond Baranyi <botond.baranyi@ericsson.com>
Tue, 21 Jun 2016 11:41:03 +0000 (13:41 +0200)
Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com>
Makefile.cfg
compiler2/DebuggerStuff.cc
core/DebugCommands.hh
core/Debugger.cc
core/Debugger.hh
core/DebuggerUI.cc
mctr2/cli/Cli.cc
mctr2/mctr/MainController.cc

index 53425f351f20bc5aa3d1167497914415778b9feb..de4fe1f9a07c2c70f1dad08890c1acb71d9fd6d5 100644 (file)
@@ -61,7 +61,7 @@ COVERAGE := no
 # 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).
index 72de2f91af3c8ddcc8159a8d3284df25018bc123..955f462bdac7eac540fa318007cbab09653f353f 100644 (file)
@@ -319,7 +319,17 @@ char* generate_code_debugger_add_var(char* str, Common::Assignment* var_ass,
     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,
@@ -331,6 +341,7 @@ char* generate_code_debugger_add_var(char* str, Common::Assignment* var_ass,
     // 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)
index a2ed895dede3199370f9549814e16638a7da260b..96bc6ec915093a024a2adbf4dc12d3c3cf55e2e5 100644 (file)
 #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",
@@ -60,7 +62,9 @@
 #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"
index 97a8643e470bbdce9f132399f81e1770f021c9db..fb5da1538237355c560e9f158444c9b8b9a8b962 100644 (file)
@@ -250,11 +250,53 @@ void TTCN3_Debugger::set_automatic_breakpoint(const char* p_event_str,
   *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");
     }
@@ -279,14 +321,13 @@ void TTCN3_Debugger::set_stack_level(int new_level)
   }
 }
 
-#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);
@@ -1121,6 +1162,7 @@ void TTCN3_Debugger::remove_scope(TTCN3_Debug_Scope* p_scope)
 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()) {
@@ -1131,6 +1173,7 @@ TTCN3_Debugger::variable_t* TTCN3_Debugger::add_variable(const void* p_value,
       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);
@@ -1140,7 +1183,7 @@ TTCN3_Debugger::variable_t* TTCN3_Debugger::add_variable(const void* p_value,
   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;
 }
@@ -1148,6 +1191,7 @@ TTCN3_Debugger::variable_t* TTCN3_Debugger::add_variable(const void* p_value,
 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)
 {
@@ -1159,6 +1203,7 @@ TTCN3_Debugger::variable_t* TTCN3_Debugger::add_variable(void* p_value,
       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);
@@ -1168,7 +1213,7 @@ TTCN3_Debugger::variable_t* TTCN3_Debugger::add_variable(void* p_value,
   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;
 }
@@ -1296,10 +1341,9 @@ void TTCN3_Debugger::execute_command(int p_command, int p_argument_count,
     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)
@@ -1479,9 +1523,11 @@ TTCN3_Debug_Scope::~TTCN3_Debug_Scope()
 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);
   }
@@ -1490,11 +1536,12 @@ void TTCN3_Debug_Scope::add_variable(const void* p_value,
 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);
   }
@@ -1503,19 +1550,35 @@ void TTCN3_Debug_Scope::add_variable(void* p_value,
 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;
     }
   }
@@ -1582,6 +1645,7 @@ TTCN3_Debug_Function::~TTCN3_Debug_Function()
 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()) {
@@ -1589,6 +1653,7 @@ TTCN3_Debugger::variable_t* TTCN3_Debug_Function::add_variable(const void* p_val
     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);
@@ -1600,6 +1665,7 @@ TTCN3_Debugger::variable_t* TTCN3_Debug_Function::add_variable(const void* p_val
 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)
 {
@@ -1608,6 +1674,7 @@ TTCN3_Debugger::variable_t* TTCN3_Debug_Function::add_variable(void* p_value,
     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);
@@ -1759,10 +1826,10 @@ void TTCN3_Debug_Function::list_variables(const char* p_scope, const char* p_fil
     }
   }
   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.");
index be101ea0bd4c4c71477b30727c03f8bfbf7d9d4b..6b253b65fea67b09f1e2dbcc1164ec097df89411 100644 (file)
@@ -64,6 +64,9 @@ public:
     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
@@ -243,6 +246,10 @@ private:
   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();
@@ -477,11 +484,12 @@ public:
     * 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) */
@@ -559,11 +567,11 @@ public:
     * 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);
   
   //////////////////////////////////////////////////////
@@ -573,13 +581,19 @@ public:
   /** 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;
 };
 
 
@@ -653,11 +667,13 @@ public:
   /** 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 */
index 37b75e7c0bd30e1e8440264c46c25a255ccbf120..aa583b25fff3b8901854a5c24a09075fbf53345e 100644 (file)
@@ -48,9 +48,8 @@ const TTCN_Debugger_UI::command_t TTCN_Debugger_UI::debug_command_list[] = {
     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>",
index bf10cfb2f0c8e49819d9590618f8f7f8f88a0a91..d76a83c076e33cc7568255f0a8dd35190e034b62 100644 (file)
@@ -135,8 +135,12 @@ static const DebugCommand debug_command_list[] = {
     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." },
index 64f0dfe6fb6c0b7520b8b02ad61c86c25167e4bc..c869353d5c6041961f93173f692fac4561ff7d4a 100644 (file)
@@ -5618,6 +5618,28 @@ void MainController::process_debug_return_value(Text_Buf& text_buf, char* log_so
   }
 }
 
+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
@@ -5626,7 +5648,7 @@ void MainController::process_debug_broadcast_req(component_struct* tc, int comma
   }
   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, "");
     }
   }
@@ -6483,36 +6505,72 @@ void MainController::debug_command(int commandID, char* arguments)
   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:
@@ -6521,12 +6579,9 @@ void MainController::debug_command(int commandID, char* arguments)
     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;
@@ -6544,17 +6599,32 @@ void MainController::debug_command(int commandID, char* arguments)
       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);
         }
       }
This page took 0.035026 seconds and 5 git commands to generate.