*
* Contributors:
* Balasko, Jeno
+ * Baranyi, Botond
* Bene, Tamas
* Beres, Szabolcs
* Delic, Adam
#define SHELL_TEXT "!"
#define EXIT_TEXT "quit"
#define EXIT_TEXT2 "exit"
+#define BATCH_TEXT "batch"
#define SHELL_ESCAPE '!'
#define TTCN3_HISTORY_FILENAME ".ttcn3_history"
"Execute commands in subshell." },
{ EXIT_TEXT, &Cli::exitCallback, EXIT_TEXT, "Exit Main Controller." },
{ EXIT_TEXT2, &Cli::exitCallback, EXIT_TEXT2, "Exit Main Controller." },
+ { BATCH_TEXT, &Cli::executeBatchFile, BATCH_TEXT " <batch_file>",
+ "Run commands from batch file." },
{ NULL, NULL, NULL, NULL }
};
static const DebugCommand debug_command_list[] = {
{ D_SWITCH_TEXT, D_SWITCH, D_SWITCH_TEXT " on|off",
"Switch the debugger on or off." },
- { D_ADD_BREAKPOINT_TEXT, D_ADD_BREAKPOINT,
- D_ADD_BREAKPOINT_TEXT " <module> <line>",
- "Add breakpoint at specified location." },
+ { D_SET_BREAKPOINT_TEXT, D_SET_BREAKPOINT,
+ D_SET_BREAKPOINT_TEXT " <module> <line>|<function> [<batch_file>]",
+ "Add a breakpoint at the specified location, or change the batch file of "
+ "an existing breakpoint." },
{ D_REMOVE_BREAKPOINT_TEXT, D_REMOVE_BREAKPOINT,
- D_REMOVE_BREAKPOINT_TEXT " <module> <line>",
- "Remove breakpoint from specified location." },
- { D_SET_ERROR_BEHAVIOR_TEXT, D_SET_ERROR_BEHAVIOR,
- D_SET_ERROR_BEHAVIOR_TEXT " yes|no",
- "Set whether to halt test execution when component verdict is set to 'error'." },
- { D_SET_FAIL_BEHAVIOR_TEXT, D_SET_FAIL_BEHAVIOR,
- D_SET_FAIL_BEHAVIOR_TEXT " yes|no",
- "Set whether to halt test execution when component verdict is set to 'fail'." },
+ D_REMOVE_BREAKPOINT_TEXT " all|<module> [all|<line>|<function>]",
+ "Remove a breakpoint, or all breakpoints from a module, or all breakpoints "
+ "from all modules." },
+ { D_SET_AUTOMATIC_BREAKPOINT_TEXT, D_SET_AUTOMATIC_BREAKPOINT,
+ D_SET_AUTOMATIC_BREAKPOINT_TEXT " error|fail on|off [<batch_file>]",
+ "Switch an automatic breakpoint (truggered by an event) on or off, and/or "
+ "change its batch file." },
{ D_SET_OUTPUT_TEXT, D_SET_OUTPUT,
D_SET_OUTPUT_TEXT " console|file|both [file_name]",
"Set the output of the debugger." },
+ { D_SET_GLOBAL_BATCH_FILE_TEXT, D_SET_GLOBAL_BATCH_FILE,
+ 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_FUNCTION_CALL_CONFIG_TEXT, D_FUNCTION_CALL_CONFIG,
+ D_FUNCTION_CALL_CONFIG_TEXT " file|<limit>|all [<file_name>]",
+ "Configure the storing of function call data." },
+ { 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." },
{ D_SET_STACK_LEVEL_TEXT, D_SET_STACK_LEVEL, D_SET_STACK_LEVEL_TEXT " <level>",
"Set the stack level to print debug information from." },
{ D_LIST_VARIABLES_TEXT, D_LIST_VARIABLES,
- D_LIST_VARIABLES_TEXT " local|global|comp|all [pattern]",
+ D_LIST_VARIABLES_TEXT " [local|global|comp|all] [pattern]",
"List variable names." },
{ D_PRINT_VARIABLE_TEXT, D_PRINT_VARIABLE,
- D_PRINT_VARIABLE_TEXT " <variable_name>[{ <variable_name>}]",
- "Print current value of one or more variables." },
+ D_PRINT_VARIABLE_TEXT " <variable_name>|$ [{ <variable_name>|$}]",
+ "Print current value of one or more variables ('$' is substituted with the "
+ "result of the last " D_LIST_VARIABLES_TEXT " command)." },
{ D_OVERWRITE_VARIABLE_TEXT, D_OVERWRITE_VARIABLE,
D_OVERWRITE_VARIABLE_TEXT " <variable_name> <value>",
"Overwrite the current value of a variable." },
- { D_PRINT_SNAPSHOTS_TEXT, D_PRINT_SNAPSHOTS, D_PRINT_SNAPSHOTS_TEXT,
- "Print snapshots of function calls until this point." },
- // D_SET_SNAPSHOT_BEHAVIOR_TEXT
+ { D_PRINT_FUNCTION_CALLS_TEXT, D_PRINT_FUNCTION_CALLS,
+ D_PRINT_FUNCTION_CALLS_TEXT " [all|<amount>]",
+ "Print function call data." },
{ D_STEP_OVER_TEXT, D_STEP_OVER, D_STEP_OVER_TEXT,
"Resume test execution until the next line of code (in this function or the "
"caller function)." },
"Resume test execution until the next line of code (on any stack level)." },
{ D_STEP_OUT_TEXT, D_STEP_OUT, D_STEP_OUT_TEXT,
"Resume test execution until the next line of code in the caller function." },
- { D_RUN_TO_CURSOR_TEXT, D_RUN_TO_CURSOR, D_RUN_TO_CURSOR_TEXT " <module> <line>",
+ { D_RUN_TO_CURSOR_TEXT, D_RUN_TO_CURSOR,
+ D_RUN_TO_CURSOR_TEXT " <module> <line>|<function>",
"Resume test execution until the specified location." },
{ D_HALT_TEXT, D_HALT, D_HALT_TEXT, "Halt test execution." },
{ D_CONTINUE_TEXT, D_CONTINUE, D_CONTINUE_TEXT, "Resume halted test execution." },
{ D_EXIT_TEXT, D_EXIT, D_EXIT_TEXT " test|all",
"Exit the current test or the execution of all tests." },
- { D_BATCH_TEXT, D_BATCH, D_BATCH_TEXT " <batch_file_name>",
- "Run commands from batch file." },
- { D_SET_HALTING_BATCH_FILE_TEXT, D_SET_HALTING_BATCH_FILE,
- D_SET_HALTING_BATCH_FILE_TEXT " yes|no [batch_file_name]",
- "Set whether a batch file should be executed automatically when test execution "
- "is halted by the debugger." },
{ NULL, D_ERROR, NULL, NULL }
};
perror("Cli::Cli: pthread_cond_init failed.");
exit(EXIT_FAILURE);
}
+ cfg_file_name = NULL;
}
Cli::~Cli()
{
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
+ Free(cfg_file_name);
}
//----------------------------------------------------------------------------
printWelcome();
if (argc == 2) {
- printf("Using configuration file: %s\n", argv[1]);
- if (process_config_read_file(argv[1], &mycfg)) {
+ cfg_file_name = mcopystr(argv[1]);
+ printf("Using configuration file: %s\n", cfg_file_name);
+ if (process_config_read_file(cfg_file_name, &mycfg)) {
puts("Error was found in the configuration file. Exiting.");
cleanUp();
return EXIT_FAILURE;
memset(line_read, ' ', command_name_len);
stripLWS(line_read);
MainController::debug_command(command->commandID, line_read);
+ if (waitState == WAIT_EXECUTE_LIST && command->commandID == D_EXIT &&
+ !strcmp(line_read, "all")) {
+ // stop executing the list from the config file
+ waitState = WAIT_NOTHING;
+ }
return;
}
}
void Cli::reconfCallback(const char *arguments)
{
- if(*arguments == 0) { // reconf called without its optional argument
- puts("Reconfiguration of MC and HCs using original configuration "
- "data\n -- not supported, yet.");
- } else { // reconf called with config_file argument
- puts("Reconfiguration of MC and HCs using configuration file"
- "specified in\ncommand line argument -- not supported, yet.");
+ if (!MainController::start_reconfiguring()) {
+ return;
+ }
+ if (*arguments != 0) {
+ Free(cfg_file_name);
+ cfg_file_name = mcopystr(arguments);
+ }
+
+ printf("Using configuration file: %s\n", cfg_file_name);
+ if (process_config_read_file(cfg_file_name, &mycfg)) {
+ puts("Error was found in the configuration file. Exiting.");
+ cleanUp();
+ puts("exit");
+ exitCallback("");
+ }
+ else {
+ MainController::set_kill_timer(mycfg.kill_timer);
+
+ for (int i = 0; i < mycfg.group_list_len; ++i) {
+ MainController::add_host(mycfg.group_list[i].group_name,
+ mycfg.group_list[i].host_name);
+ }
+
+ for (int i = 0; i < mycfg.component_list_len; ++i) {
+ MainController::assign_component(mycfg.component_list[i].host_or_group,
+ mycfg.component_list[i].component);
+ }
+
+ if (MainController::get_state() == mctr::MC_RECONFIGURING) {
+ MainController::configure(mycfg.config_read_buffer);
+ }
}
}
puts("Help is available for the following commands:");
for (const Command *command = command_list;
command->name != NULL; command++) {
- printf(" %s", command->name);
+ printf("%s ", command->name);
}
for (const DebugCommand *command = debug_command_list;
command->name != NULL; command++) {
- printf(" %s", command->name);
+ printf("%s ", command->name);
}
putchar('\n');
} else {
if (*arguments == 0) {
switch (MainController::get_state()) {
case mctr::MC_READY:
+ case mctr::MC_RECONFIGURING:
MainController::exit_mtc();
waitMCState(WAIT_MTC_TERMINATED);
case mctr::MC_LISTENING:
}
}
+void Cli::executeBatchFile(const char* filename)
+{
+ FILE* fp = fopen(filename, "r");
+ if (fp == NULL) {
+ printf("Failed to open file '%s' for reading.\n", filename);
+ return;
+ }
+ else {
+ printf("Executing batch file '%s'.\n", filename);
+ }
+ char line[1024];
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ size_t len = strlen(line);
+ if (line[len - 1] == '\n') {
+ line[len - 1] = '\0';
+ --len;
+ }
+ if (len != 0) {
+ printf("%s\n", line);
+ processCommand(line);
+ }
+ }
+ if (!feof(fp)) {
+ printf("Error occurred while reading batch file '%s' (error code: %d).\n",
+ filename, ferror(fp));
+ }
+ fclose(fp);
+}
+
//----------------------------------------------------------------------------
// PRIVATE
// Command completion function implementation for readline() library.