add macro function support to openfpga shell and update unit test
This commit is contained in:
parent
558f0bb1bd
commit
e983966a08
|
@ -61,6 +61,7 @@ class Shell {
|
||||||
STANDARD,
|
STANDARD,
|
||||||
SHORT,
|
SHORT,
|
||||||
BUILTIN,
|
BUILTIN,
|
||||||
|
MACRO,
|
||||||
NUM_EXEC_FUNC_TYPES
|
NUM_EXEC_FUNC_TYPES
|
||||||
};
|
};
|
||||||
public: /* Constructor */
|
public: /* Constructor */
|
||||||
|
@ -89,6 +90,7 @@ class Shell {
|
||||||
* 1. Standard function, including the data exchange <T> and commands
|
* 1. Standard function, including the data exchange <T> and commands
|
||||||
* 2. Short function, including only the data exchange <T>
|
* 2. Short function, including only the data exchange <T>
|
||||||
* 3. Built-in function, including only the shell envoriment variables
|
* 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
|
* Users just need to specify the function object and its type will be automatically inferred
|
||||||
*/
|
*/
|
||||||
void set_command_execute_function(const ShellCommandId& cmd_id,
|
void set_command_execute_function(const ShellCommandId& cmd_id,
|
||||||
|
@ -97,6 +99,8 @@ class Shell {
|
||||||
std::function<void(T&)> exec_func);
|
std::function<void(T&)> exec_func);
|
||||||
void set_command_execute_function(const ShellCommandId& cmd_id,
|
void set_command_execute_function(const ShellCommandId& cmd_id,
|
||||||
std::function<void()> exec_func);
|
std::function<void()> exec_func);
|
||||||
|
void set_command_execute_function(const ShellCommandId& cmd_id,
|
||||||
|
std::function<void(int, char**)> exec_func);
|
||||||
void set_command_dependency(const ShellCommandId& cmd_id,
|
void set_command_dependency(const ShellCommandId& cmd_id,
|
||||||
const std::vector<ShellCommandId> cmd_dependency);
|
const std::vector<ShellCommandId> cmd_dependency);
|
||||||
ShellCommandClassId add_command_class(const char* name);
|
ShellCommandClassId add_command_class(const char* name);
|
||||||
|
@ -150,10 +154,12 @@ class Shell {
|
||||||
* 1. Standard function, including the data exchange <T> and commands
|
* 1. Standard function, including the data exchange <T> and commands
|
||||||
* 2. Short function, including only the data exchange <T>
|
* 2. Short function, including only the data exchange <T>
|
||||||
* 3. Built-in function, including only the shell envoriment variables
|
* 3. Built-in function, including only the shell envoriment variables
|
||||||
|
* 4. Marco function, which directly call a macro function without command parsing
|
||||||
*/
|
*/
|
||||||
vtr::vector<ShellCommandId, std::function<void(T&, const Command&, const CommandContext&)>> command_standard_execute_functions_;
|
vtr::vector<ShellCommandId, std::function<void(T&, const Command&, const CommandContext&)>> command_standard_execute_functions_;
|
||||||
vtr::vector<ShellCommandId, std::function<void(T&)>> command_short_execute_functions_;
|
vtr::vector<ShellCommandId, std::function<void(T&)>> command_short_execute_functions_;
|
||||||
vtr::vector<ShellCommandId, std::function<void()>> command_builtin_execute_functions_;
|
vtr::vector<ShellCommandId, std::function<void()>> command_builtin_execute_functions_;
|
||||||
|
vtr::vector<ShellCommandId, std::function<void(int, char**)>> command_macro_execute_functions_;
|
||||||
|
|
||||||
/* Type of execute functions for each command.
|
/* Type of execute functions for each command.
|
||||||
* This is supposed to be an internal data ONLY
|
* This is supposed to be an internal data ONLY
|
||||||
|
|
|
@ -128,6 +128,7 @@ ShellCommandId Shell<T>::add_command(const Command& cmd, const char* descr) {
|
||||||
command_standard_execute_functions_.emplace_back();
|
command_standard_execute_functions_.emplace_back();
|
||||||
command_short_execute_functions_.emplace_back();
|
command_short_execute_functions_.emplace_back();
|
||||||
command_builtin_execute_functions_.emplace_back();
|
command_builtin_execute_functions_.emplace_back();
|
||||||
|
command_macro_execute_functions_.emplace_back();
|
||||||
command_dependencies_.emplace_back();
|
command_dependencies_.emplace_back();
|
||||||
|
|
||||||
/* Register the name in the name2id map */
|
/* Register the name in the name2id map */
|
||||||
|
@ -173,6 +174,14 @@ void Shell<T>::set_command_execute_function(const ShellCommandId& cmd_id,
|
||||||
command_builtin_execute_functions_[cmd_id] = exec_func;
|
command_builtin_execute_functions_[cmd_id] = exec_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Shell<T>::set_command_execute_function(const ShellCommandId& cmd_id,
|
||||||
|
std::function<void(int, char**)> 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<class T>
|
template<class T>
|
||||||
void Shell<T>::set_command_dependency(const ShellCommandId& cmd_id,
|
void Shell<T>::set_command_dependency(const ShellCommandId& cmd_id,
|
||||||
const std::vector<ShellCommandId> dependent_cmds) {
|
const std::vector<ShellCommandId> dependent_cmds) {
|
||||||
|
@ -337,7 +346,28 @@ void Shell<T>::execute_command(const char* cmd_line,
|
||||||
|
|
||||||
/* TODO: Check the dependency graph to see if all the prequistics have been met */
|
/* 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])) {
|
if (false == parse_command(tokens, commands_[cmd_id], command_contexts_[cmd_id])) {
|
||||||
/* Echo the command */
|
/* Echo the command */
|
||||||
print_command_options(commands_[cmd_id]);
|
print_command_options(commands_[cmd_id]);
|
||||||
|
@ -358,6 +388,7 @@ void Shell<T>::execute_command(const char* cmd_line,
|
||||||
case BUILTIN:
|
case BUILTIN:
|
||||||
command_builtin_execute_functions_[cmd_id]();
|
command_builtin_execute_functions_[cmd_id]();
|
||||||
break;
|
break;
|
||||||
|
/* MACRO should be executed eariler in this function. It should not appear here */
|
||||||
default:
|
default:
|
||||||
/* This is not allowed! Error out */
|
/* This is not allowed! Error out */
|
||||||
VTR_LOG("Invalid type of execute function for command '%s'!\n",
|
VTR_LOG("Invalid type of execute function for command '%s'!\n",
|
||||||
|
|
|
@ -27,6 +27,15 @@ void shell_execute_print(ShellContext& context) {
|
||||||
VTR_LOG("a=%d\n", context.a);
|
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) {
|
int main(int argc, char** argv) {
|
||||||
/* Create the command to launch shell in different modes */
|
/* Create the command to launch shell in different modes */
|
||||||
Command start_cmd("test_shell");
|
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_class(shell_cmd_print_id, arith_cmd_class);
|
||||||
shell.set_command_execute_function(shell_cmd_print_id, shell_execute_print);
|
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 */
|
/* Add a new class of commands */
|
||||||
ShellCommandClassId basic_cmd_class = shell.add_command_class("Basic");
|
ShellCommandClassId basic_cmd_class = shell.add_command_class("Basic");
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,7 @@ set --value 5
|
||||||
|
|
||||||
print # Print out the value
|
print # Print out the value
|
||||||
|
|
||||||
|
# Test macro arguments
|
||||||
|
print_macro arch blif
|
||||||
|
|
||||||
exit # Finish
|
exit # Finish
|
||||||
|
|
Loading…
Reference in New Issue