diff --git a/libopenfpga/libopenfpgashell/src/shell.h b/libopenfpga/libopenfpgashell/src/shell.h index 0f83b4e46..0d746f931 100644 --- a/libopenfpga/libopenfpgashell/src/shell.h +++ b/libopenfpga/libopenfpgashell/src/shell.h @@ -61,6 +61,7 @@ class Shell { STANDARD, SHORT, BUILTIN, + MACRO, NUM_EXEC_FUNC_TYPES }; public: /* Constructor */ @@ -89,6 +90,7 @@ class Shell { * 1. Standard function, including the data exchange and commands * 2. Short function, including only the data exchange * 3. Built-in function, including only the shell envoriment variables + * 4. Marco function, which directly call a macro function without command parsing * Users just need to specify the function object and its type will be automatically inferred */ void set_command_execute_function(const ShellCommandId& cmd_id, @@ -97,6 +99,8 @@ class Shell { std::function exec_func); void set_command_execute_function(const ShellCommandId& cmd_id, std::function exec_func); + void set_command_execute_function(const ShellCommandId& cmd_id, + std::function exec_func); void set_command_dependency(const ShellCommandId& cmd_id, const std::vector cmd_dependency); ShellCommandClassId add_command_class(const char* name); @@ -150,10 +154,12 @@ class Shell { * 1. Standard function, including the data exchange and commands * 2. Short function, including only the data exchange * 3. Built-in function, including only the shell envoriment variables + * 4. Marco function, which directly call a macro function without command parsing */ vtr::vector> command_standard_execute_functions_; vtr::vector> command_short_execute_functions_; vtr::vector> command_builtin_execute_functions_; + vtr::vector> command_macro_execute_functions_; /* Type of execute functions for each command. * This is supposed to be an internal data ONLY diff --git a/libopenfpga/libopenfpgashell/src/shell.tpp b/libopenfpga/libopenfpgashell/src/shell.tpp index ac1621029..65843afc8 100644 --- a/libopenfpga/libopenfpgashell/src/shell.tpp +++ b/libopenfpga/libopenfpgashell/src/shell.tpp @@ -128,6 +128,7 @@ ShellCommandId Shell::add_command(const Command& cmd, const char* descr) { command_standard_execute_functions_.emplace_back(); command_short_execute_functions_.emplace_back(); command_builtin_execute_functions_.emplace_back(); + command_macro_execute_functions_.emplace_back(); command_dependencies_.emplace_back(); /* Register the name in the name2id map */ @@ -173,6 +174,14 @@ void Shell::set_command_execute_function(const ShellCommandId& cmd_id, command_builtin_execute_functions_[cmd_id] = exec_func; } +template +void Shell::set_command_execute_function(const ShellCommandId& cmd_id, + std::function exec_func) { + VTR_ASSERT(true == valid_command_id(cmd_id)); + command_execute_function_types_[cmd_id] = MACRO; + command_macro_execute_functions_[cmd_id] = exec_func; +} + template void Shell::set_command_dependency(const ShellCommandId& cmd_id, const std::vector dependent_cmds) { @@ -337,7 +346,28 @@ void Shell::execute_command(const char* cmd_line, /* TODO: Check the dependency graph to see if all the prequistics have been met */ - /* Find the command! Parse the options */ + /* Find the command! Parse the options + * Note: + * Macro command will not be parsed! It will be directly executed + */ + if (MACRO == command_execute_function_types_[cmd_id]) { + /* Convert the tokens from string to char */ + char** argv = (char**)malloc(tokens.size() * sizeof(char*)); + for (size_t itok = 0; itok < tokens.size(); ++itok) { + argv[itok] = (char*)malloc((tokens[itok].length() + 1) * sizeof(char)); + strcpy(argv[itok], tokens[itok].c_str()); + } + /* Execute the marco function */ + command_macro_execute_functions_[cmd_id](tokens.size(), argv); + /* Free the argv */ + for (size_t itok = 0; itok < tokens.size(); ++itok) { + free(argv[itok]); + } + free(argv); + /* Finish for macro command, return */ + return; + } + if (false == parse_command(tokens, commands_[cmd_id], command_contexts_[cmd_id])) { /* Echo the command */ print_command_options(commands_[cmd_id]); @@ -358,6 +388,7 @@ void Shell::execute_command(const char* cmd_line, case BUILTIN: command_builtin_execute_functions_[cmd_id](); break; + /* MACRO should be executed eariler in this function. It should not appear here */ default: /* This is not allowed! Error out */ VTR_LOG("Invalid type of execute function for command '%s'!\n", diff --git a/libopenfpga/libopenfpgashell/test/test_shell.cpp b/libopenfpga/libopenfpgashell/test/test_shell.cpp index 8fc00f055..f84a910d5 100644 --- a/libopenfpga/libopenfpgashell/test/test_shell.cpp +++ b/libopenfpga/libopenfpgashell/test/test_shell.cpp @@ -27,6 +27,15 @@ void shell_execute_print(ShellContext& context) { VTR_LOG("a=%d\n", context.a); } +static +void shell_execute_print_macro(int argc, char** argv) { + VTR_LOG("Number of arguments: %d\n", argc); + VTR_LOG("Detailed arguments:\n"); + for (int iarg = 0; iarg < argc; ++iarg) { + VTR_LOG("\t[%d]: %s\n", iarg, argv[iarg]); + } +} + int main(int argc, char** argv) { /* Create the command to launch shell in different modes */ Command start_cmd("test_shell"); @@ -97,6 +106,15 @@ int main(int argc, char** argv) { shell.set_command_class(shell_cmd_print_id, arith_cmd_class); shell.set_command_execute_function(shell_cmd_print_id, shell_execute_print); + /* Create a macro command of 'print_macro' + * This function will print the value of an internal variable of ShellContext + */ + Command shell_cmd_print_macro("print_macro"); + ShellCommandId shell_cmd_print_macro_id = shell.add_command(shell_cmd_print_macro, "A macro function to print arguments"); + shell.set_command_class(shell_cmd_print_macro_id, arith_cmd_class); + shell.set_command_execute_function(shell_cmd_print_macro_id, shell_execute_print_macro); + + /* Add a new class of commands */ ShellCommandClassId basic_cmd_class = shell.add_command_class("Basic"); diff --git a/libopenfpga/libopenfpgashell/test_script/test.openfpga b/libopenfpga/libopenfpgashell/test_script/test.openfpga index 992001a7e..8122e2a17 100644 --- a/libopenfpga/libopenfpgashell/test_script/test.openfpga +++ b/libopenfpga/libopenfpgashell/test_script/test.openfpga @@ -6,4 +6,7 @@ set --value 5 print # Print out the value +# Test macro arguments +print_macro arch blif + exit # Finish