/** alias for record of charstring */
typedef PreGenRecordOf::PREGEN__RECORD__OF__CHARSTRING charstring_list;
-// forward declarations
+// debugger forward declarations
class TTCN3_Debug_Scope;
class TTCN3_Debug_Function;
+// other forward declarations
+class Module_Param;
+
//////////////////////////////////////////////////////
////////////////// TTCN3_Debugger ////////////////////
class TTCN3_Debugger {
public:
+ struct variable_t;
+
+ typedef CHARSTRING (*print_function_t)(const variable_t&);
+ typedef boolean (*set_function_t)(variable_t&, Module_Param&);
+
/** type for keeping track of a variable */
struct variable_t {
/** pointer to the variable object, not owned */
- const void* value;
+ union {
+ /** container for non-constant variable objects */
+ void* value;
+ /** container for constant variable objects */
+ const void* cvalue;
+ };
/** variable name (used for looking up variables), not owned */
const char* name;
/** name of the variable's type, not owned */
const char* type_name;
/** variable printing function (using the variable object's log() function) */
- CHARSTRING (*print_function)(const variable_t&);
+ print_function_t print_function;
+ /** variable setting (overwriting) function (using the variable object's
+ * set_param() function) - set to NULL for constant variables */
+ set_function_t set_function;
};
/** this type pairs a debug scope with a name, used for storing global and
TTCN3_Debug_Scope* scope;
};
+ /** type for storing a function call in the call stack */
+ struct function_call_t {
+ /** pointer to the debug function object */
+ TTCN3_Debug_Function* function;
+ /** TTCN-3 line number, where the function was called from */
+ int caller_line;
+ };
+
/** type for storing breakpoints */
struct breakpoint_t {
/** module name, owned */
char* module;
/** line number */
int line;
- // const char* batch_file;
+ /** batch file to be executed when the breakpoint is reached (optional) */
+ char* batch_file;
};
/** special breakpoint types, passed to breakpoint_entry() as the line parameter,
SBP_FAIL_VERDICT = -1
};
+ /** type for storing the settings of automatic breakpoints */
+ struct automatic_breakpoint_behavior_t {
+ /** indicates whether the breakpoint should be triggered by the associated event */
+ bool trigger;
+ /** batch file to be executed if the breakpoint is triggered (optional) */
+ char* batch_file;
+ };
+
+ /** stepping type */
+ enum stepping_t {
+ NOT_STEPPING,
+ STEP_OVER,
+ STEP_INTO,
+ STEP_OUT
+ };
+
private:
/** indicates whether the debugger has been activated, meaning that the debugger's
/** list of component scopes */
Vector<named_scope_t> component_scopes;
- /** pointers to debug function objects (resembling a call stack), elements are not owned
- * the current function is always the last element in the array (the top element in the stack) */
- Vector<TTCN3_Debug_Function*> call_stack;
+ /** pointers to debug function objects and the lines they were called from
+ * (resembling a call stack), the current function is always the last element
+ * in the array (the top element in the stack) */
+ Vector<function_call_t> call_stack;
/** list of breakpoints */
Vector<breakpoint_t> breakpoints;
/** current stack level (reset when test execution is halted or resumed) */
int stack_level;
- /** behavior triggered by setting the local verdict to FAIL
- * (a breakpoint is activated if set to true) */
- bool fail_behavior;
+ /** automatic breakpoint triggered by setting the local verdict to FAIL */
+ automatic_breakpoint_behavior_t fail_behavior;
- /** behavior triggered by setting the local verdict to ERROR
- * (a breakpoint is activated if set to true) */
- bool error_behavior;
+ /** automatic breakpoint triggered by setting the local verdict to ERROR */
+ automatic_breakpoint_behavior_t error_behavior;
- /** result of the last executed or currently executing command */
+ /** batch file executed automatically when test execution is halted
+ * NULL if switched off
+ * is overridden by breakpoint-specific batch files */
+ char* global_batch_file;
+
+ /** result of the currently executing command */
char* command_result;
+ /** result of the last D_LIST_VARIABLES command */
+ char* last_variable_list;
+
+ /** stores which stepping option was requested by the user (if any) */
+ stepping_t stepping_type;
+
+ /** stores the size of the call stack when the last stepping operation was
+ * initiated */
+ size_t stepping_stack_size;
+
+ /** temporary breakpoint set by the 'run to cursor' operation */
+ breakpoint_t temporary_breakpoint;
+
+ /** true if an 'exit all' command was issued
+ * switched to false when test execution is restarted */
+ bool exiting;
+
+ /** test execution is automatically halted at start if set to true */
+ bool halt_at_start;
+
+ /** batch file executed automatically at the start of test execution
+ * if not set to NULL (not owned) */
+ const char* initial_batch_file;
+
//////////////////////////////////////////////////////
///////////////// internal functions /////////////////
//////////////////////////////////////////////////////
* handles the D_SWITCH command */
void switch_state(const char* p_state_str);
- /** adds a new breakpoint at the specified module and line
+ /** adds a new breakpoint at the specified module and line with the specified
+ * batch file (if not NULL), or changes the batch file of an existing
+ * breakpoint
* handles the D_ADD_BREAKPOINT command */
- void add_breakpoint(const char* p_module, int p_line /*const char* batch_file*/);
+ void set_breakpoint(const char* p_module, int p_line, const char* batch_file);
/** removes the breakpoint from the specified module/line, if it exists
+ * can also be used to remove all breakpoints from the specified module or
+ * all breakpoints in all modules
* handles the D_REMOVE_BREAKPOINT command */
- void remove_breakpoint(const char* p_module, int p_line);
-
- /** sets the behavior of a special breakpoint type
- * @param p_state_str "yes" turns the special breakpoint on (as if it was an
- * actual breakpoint), "no" turns it off
- * handles the D_SET_ERROR_BEHAVIOR and D_SET_FAIL_BEHAVIOR commands */
- void set_special_breakpoint(special_breakpoint_t p_type, const char* p_state_str);
+ void remove_breakpoint(const char* p_module, const char* p_line);
+
+ /** switches an automatic breakpoint related to the specified event on or off
+ * and/or sets the batch file to run when the breakpoint is triggered
+ * @param p_event_str string representation of the event that triggers the
+ * breakpoint (either "error" or "fail")
+ * @param p_state_str "on" or "off", indicates the new state of the breakpoint
+ * @param p_batch_file name of the batch file to execute (NULL means don't
+ * execute anything)
+ * handles the D_SET_AUTOMATIC_BREAKPOINT command */
+ void set_automatic_breakpoint(const char* p_event_str, const char* p_state_str,
+ const char* p_batch_file);
/** prints the current call stack
* handles the D_PRINT_CALL_STACK command */
* handles the D_SET_STACK_LEVEL command */
void set_stack_level(int new_level);
- /** prints the specified variable
+ /** finds the variable with the specified name, and prints its value or an
+ * error message
* handles (one parameter of) the D_PRINT_VARIABLE command */
- void print_variable(const variable_t* p_var);
+ void print_variable(const char* p_var_name);
+
+ void overwrite_variable(const char* p_var_name, int p_value_element_count,
+ char** p_value_elements);
/** sets the debugger's output to the console and/or a text file
* handles the D_SET_OUTPUT command
* @param p_file_name output file name or NULL */
void set_output(const char* p_output_type, const char* p_file_name);
+ /** switches the global batch file on or off
+ * handles the D_SET_GLOBAL_BATCH_FILE command */
+ void set_global_batch_file(const char* p_state_str, const char* p_file_name);
+
+ /** resumes execution until the next breakpoint entry (in the stack levels
+ * specified by the stepping type arguments) is reached (or until test execution
+ * is halted for any other reason)
+ * handles the D_STEP_OVER, D_STEP_INTO and D_STEP_OUT commands */
+ void step(stepping_t p_stepping_type);
+
+ /** resumes execution until the specified location is reached
+ * (or until test execution is halted for any other reason)
+ * handles the D_RUN_TO_CURSOR command */
+ void run_to_cursor(const char* p_module, int p_line);
+
/** halts test execution, processing only debug commands
+ * @param p_batch_file batch file executed after the halt (if not NULL)
+ * @param p_run_global_batch indicates whether the global batch file should
+ * be executed after the halt (only if p_batch_file is NULL)
* handles the D_HALT command */
- void halt();
+ void halt(const char* p_batch_file, bool p_run_global_batch);
/** resumes the halted test execution
* handles the D_CONTINUE command */
/** handles metacharacters in the specified file name skeleton
* @return final file name (must be freed by caller) */
static char* finalize_file_name(const char* p_file_name_skeleton);
+
+ /** initialization function, called when the first function is added to the
+ * call stack */
+ void test_execution_started();
+
+ /** clean up function, called when the last function is removed from the
+ * call stack */
+ void test_execution_finished();
public:
/** constructor - called once per process (at the beginning) */
* the special parameter values (SBP_ERROR_VERDICT and SBP_FAIL_VERDICT) only
* trigger a breakpoint if their respective behaviors have been set to do so
* (does nothing if the debugger is switched off) */
- void breakpoint_entry(int p_line /*bool p_stepping_helper*/);
+ void breakpoint_entry(int p_line);
/** variable printing function for base types */
static CHARSTRING print_base_var(const variable_t& p_var);
+ /** variable setting function for base types */
+ static boolean set_base_var(variable_t& p_var, Module_Param& p_new_value);
+
/** variable printing function for value arrays */
template <typename T_type, unsigned int array_size, int index_offset>
static CHARSTRING print_value_array(const variable_t& p_var)
{
+ const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue;
TTCN_Logger::begin_event_log2str();
- ((VALUE_ARRAY<T_type, array_size, index_offset>*)p_var.value)->log();
+ ((VALUE_ARRAY<T_type, array_size, index_offset>*)ptr)->log();
return TTCN_Logger::end_event_log2str();
}
+ /** variable setting function for value arrays */
+ template <typename T_type, unsigned int array_size, int index_offset>
+ static boolean set_value_array(variable_t& p_var, Module_Param& p_new_value)
+ {
+ ((VALUE_ARRAY<T_type, array_size, index_offset>*)p_var.value)->set_param(p_new_value);
+ return TRUE;
+ }
+
/** variable printing function for template arrays */
template <typename T_value_type, typename T_template_type,
unsigned int array_size, int index_offset>
static CHARSTRING print_template_array(const variable_t& p_var)
{
+ const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue;
TTCN_Logger::begin_event_log2str();
((TEMPLATE_ARRAY<T_value_type, T_template_type, array_size,
- index_offset>*)p_var.value)->log();
+ index_offset>*)ptr)->log();
return TTCN_Logger::end_event_log2str();
}
+ /** variable setting function for template arrays */
+ template <typename T_value_type, typename T_template_type,
+ unsigned int array_size, int index_offset>
+ static boolean set_template_array(variable_t& p_var, Module_Param& p_new_value)
+ {
+ ((TEMPLATE_ARRAY<T_value_type, T_template_type, array_size,
+ index_offset>*)p_var.value)->set_param(p_new_value);
+ return TRUE;
+ }
+
/** variable printing function for port arrays */
template <typename T_type, unsigned int array_size, int index_offset>
static CHARSTRING print_port_array(const variable_t& p_var)
{
+ const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue;
TTCN_Logger::begin_event_log2str();
- ((PORT_ARRAY<T_type, array_size, index_offset>*)p_var.value)->log();
+ ((PORT_ARRAY<T_type, array_size, index_offset>*)ptr)->log();
return TTCN_Logger::end_event_log2str();
}
template <typename T_type, unsigned int array_size, int index_offset>
static CHARSTRING print_timer_array(const variable_t& p_var)
{
+ const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue;
TTCN_Logger::begin_event_log2str();
- ((TIMER_ARRAY<T_type, array_size, index_offset>*)p_var.value)->log();
+ ((TIMER_ARRAY<T_type, array_size, index_offset>*)ptr)->log();
return TTCN_Logger::end_event_log2str();
}
template <typename EXPR_TYPE>
static CHARSTRING print_lazy_param(const variable_t& p_var)
{
+ const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue;
TTCN_Logger::begin_event_log2str();
- ((Lazy_Param<EXPR_TYPE>*)p_var.value)->log();
+ ((Lazy_Param<EXPR_TYPE>*)ptr)->log();
return TTCN_Logger::end_event_log2str();
}
* (only if the call stack is not empty) */
void remove_scope(TTCN3_Debug_Scope* p_scope);
- /** finds or creates, and returns the variable entry specified by the parameters
+ /** finds or creates, and returns the constant variable entry specified by
+ * the parameters
*
* if the call stack is empty, an entry for a global or component variable is
* created and stored in the main debugger object (if it doesn't already exist);
* 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 */
- const variable_t* add_variable(const void* p_value, const char* p_name, const char* p_type,
- CHARSTRING (*p_print_function)(const variable_t&));
+ variable_t* add_variable(const void* p_value, const char* p_name, const char* p_type,
+ 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);
/** removes the variable entry for the specified local variable in the current
* function (only if the call stack is not empty) */
/** opens the debugger's output file for writing (if one has been set, but not
* opened, in the HC process) */
void open_output_file();
+
+ /** indicates whether an 'exit all' command has been issued
+ * (this causes the execution of tests in the current queue to stop) */
+ bool is_exiting() const { return exiting; }
+
+ /** sets the debugger to halt test execution at start (only in single mode) */
+ void set_halt_at_start() { halt_at_start = true; }
+
+ /** sets the specified batch file to be executed at the start of test execution
+ * (only in single mode) */
+ void set_initial_batch_file(const char* p_batch_file) {
+ initial_batch_file = p_batch_file;
+ }
};
/** the main debugger object */
/** list of pointers to local variable entries from the current function object or
* global or component variable entries from the main debugger object
* (the elements are not owned)*/
- Vector<const TTCN3_Debugger::variable_t*> variables;
+ Vector<TTCN3_Debugger::variable_t*> variables;
public:
//////////////////////////////////////////////////////
/** passes the parameters to the main debugger or current function object to
- * create and store a variable entry from them, and tracks this new variable
- * by storing a pointer to it
+ * create and store a (constant) variable entry from them, and tracks this new
+ * 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,
- CHARSTRING (*p_print_function)(const TTCN3_Debugger::variable_t&));
+ 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,
+ TTCN3_Debugger::set_function_t p_set_function);
//////////////////////////////////////////////////////
////// methods called by other debugger classes //////
bool has_variables() const { return !variables.empty(); }
/** returns the specified variable, if found, otherwise returns NULL */
- const TTCN3_Debugger::variable_t* find_variable(const char* p_name) const;
+ TTCN3_Debugger::variable_t* find_variable(const char* p_name) const;
/** prints the names of variables in this scope that match the specified
* @param p_posix_regexp the pattern converted into a POSIX regex structure
////// methods called from TITAN generated code //////
//////////////////////////////////////////////////////
- /** creates, stores and returns the variable entry of the local variable
+ /** creates, stores and returns the variable entry of the local (constant) variable
* specified by the parameters (only if the debugger is switched on) */
- const TTCN3_Debugger::variable_t* add_variable(const void* p_value, const char* p_name,
- const char* p_type, CHARSTRING (*p_print_function)(const TTCN3_Debugger::variable_t&));
+ 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);
+
+ /** 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,
+ TTCN3_Debugger::set_function_t p_set_function);
/** stores the string representation of the value returned by the function */
void set_return_value(const CHARSTRING& p_value);
/** searches for the variable entry with the specified name in the function's
* local variable list, the global scope (if any) and the component scope (if any),
* returns NULL, if the variable was not found */
- const TTCN3_Debugger::variable_t* find_variable(const char* p_name) const;
+ TTCN3_Debugger::variable_t* find_variable(const char* p_name) const;
/** prints the function's type, name and current values of parameters */
void print_function() const;
* - "all" - all variables visible in the function (i.e. all of the above)
* @param p_filter a pattern to filter variable names further */
void list_variables(const char* p_scope, const char* p_filter) const;
+
+ /** returns true if this instance belongs to a control part */
+ bool is_control_part() const;
+
+ /** returns true if this instance belongs to a test case */
+ bool is_test_case() const;
};
/** This macro stores a function's return value in the current function.