226 lines
10 KiB
C++
226 lines
10 KiB
C++
#ifndef SHELL_H
|
|
#define SHELL_H
|
|
|
|
#include <string>
|
|
#include <map>
|
|
#include <vector>
|
|
#include <functional>
|
|
#include <ctime>
|
|
|
|
#include "vtr_vector.h"
|
|
#include "vtr_range.h"
|
|
#include "command.h"
|
|
#include "command_context.h"
|
|
#include "command_exit_codes.h"
|
|
#include "shell_fwd.h"
|
|
|
|
/* Begin namespace openfpga */
|
|
namespace openfpga {
|
|
|
|
/*********************************************************************
|
|
* Data structure to define a working environment of a mini shell
|
|
*
|
|
* An example of how to use
|
|
* -----------------------
|
|
* // Create a new shell with a name of 'OpenFPGA' which use data structure OpenfpgaContext for data exchange
|
|
* Shell<OpenfpgaContext> shell("OpenFPGA");
|
|
*
|
|
* // Add a command 'read_arch' with a description
|
|
* ShellCommandId cmd_read_arch = shell.add_command("read_arch", "Command to read an architecture");
|
|
* // Create a new category and classify the command to it
|
|
* ShellCommandCategoryId cmd_category = shell.add_command_category("io");
|
|
* shell.set_command_category(cmd_read_arch, cmd_category);
|
|
*
|
|
* // Add options to the command 'read_arch'
|
|
* const Command* cmd_read_arch_obj = shell.command(cmd_read_arch);
|
|
* // Detailed examples can be found in Command.h
|
|
* ...
|
|
*
|
|
* // Add execute function to the command 'read_arch'
|
|
* // This is the function to be called when the command is used
|
|
* // Assume that you have a function read_arch() which does the job of read architecture
|
|
* // Note that the function read_arch() should return a void with only three arguments
|
|
* // void read_arch(T, const Command&, const CommandContext&);
|
|
* // The first argument is the template type you set when define the shell
|
|
* // The second argument is a read-only object storing the options for the command
|
|
* // The third argument is a read-only object storing the parsing results for the command
|
|
* shell.set_command_execute_function(cmd_read_arch, &read_arch);
|
|
*
|
|
* // Run a shell
|
|
* shell.run();
|
|
*
|
|
********************************************************************/
|
|
template<class T>
|
|
class Shell {
|
|
public: /* Types */
|
|
typedef vtr::vector<ShellCommandId, ShellCommandId>::const_iterator shell_command_iterator;
|
|
/* Create range */
|
|
typedef vtr::Range<shell_command_iterator> shell_command_range;
|
|
/* Enumeration of command types in a shell
|
|
* Built-in commands have their own execute functions inside the shell
|
|
*/
|
|
enum e_exec_func_type {
|
|
CONST_STANDARD,
|
|
STANDARD,
|
|
CONST_SHORT,
|
|
SHORT,
|
|
BUILTIN,
|
|
MACRO,
|
|
NUM_EXEC_FUNC_TYPES
|
|
};
|
|
public: /* Constructor */
|
|
Shell<T>(const char* name);
|
|
public: /* Public accessors */
|
|
std::string name() const;
|
|
std::string title() const;
|
|
shell_command_range commands() const;
|
|
ShellCommandId command(const std::string& name) const;
|
|
std::string command_description(const ShellCommandId& cmd_id) const;
|
|
ShellCommandClassId command_class(const ShellCommandId& cmd_id) const;
|
|
std::string command_class_name(const ShellCommandClassId& cmd_class_id) const;
|
|
/* We force a read-only return objects for command and command context
|
|
* because users should NOT modify any of them!
|
|
*/
|
|
const Command& command(const ShellCommandId& cmd_id) const;
|
|
const CommandContext& command_context(const ShellCommandId& cmd_id) const;
|
|
std::vector<ShellCommandId> command_dependency(const ShellCommandId& cmd_id) const;
|
|
std::vector<ShellCommandId> commands_by_class(const ShellCommandClassId& cmd_class_id) const;
|
|
public: /* Public mutators */
|
|
void add_title(const char* title);
|
|
ShellCommandId add_command(const Command& cmd, const char* descr);
|
|
void set_command_class(const ShellCommandId& cmd_id, const ShellCommandClassId& cmd_class_id);
|
|
/* Link the execute function to a command
|
|
* We support here different types of functions to be executed in the shell
|
|
* Users just need to specify the function object and its type will be automatically inferred
|
|
*
|
|
* Note that all the function should return exit codes complying to the shell_exit_code.h
|
|
* execept the internal functions
|
|
*/
|
|
|
|
/* Standard function, including the data exchange <T> and commands
|
|
* This function requires the data exchange <T> to be constant
|
|
* This is designed for outputting functions requiring external data than the <T>
|
|
*/
|
|
void set_command_const_execute_function(const ShellCommandId& cmd_id,
|
|
std::function<int(const T&, const Command&, const CommandContext&)> exec_func);
|
|
|
|
/* Standard function, including the data exchange <T> and commands
|
|
* This function allows modification to the data exchange <T>
|
|
* This is designed for implementing functions requiring external data than the <T>
|
|
*/
|
|
void set_command_execute_function(const ShellCommandId& cmd_id,
|
|
std::function<int(T&, const Command&, const CommandContext&)> exec_func);
|
|
|
|
/* Short function, including only the data exchange <T>
|
|
* This function requires the data exchange <T> to be constant
|
|
* This is designed for outputting functions without external data than the <T>
|
|
*/
|
|
void set_command_const_execute_function(const ShellCommandId& cmd_id,
|
|
std::function<int(const T&)> exec_func);
|
|
|
|
/* Short function, including only the data exchange <T>
|
|
* This function allows modification to the data exchange <T>
|
|
* This is designed for internal implementing functions without external data than the <T>
|
|
*/
|
|
void set_command_execute_function(const ShellCommandId& cmd_id,
|
|
std::function<int(T&)> exec_func);
|
|
|
|
/* Built-in function, including only the shell envoriment variables */
|
|
void set_command_execute_function(const ShellCommandId& cmd_id,
|
|
std::function<void()> exec_func);
|
|
|
|
/* Marco function, which directly call a macro function without command parsing */
|
|
void set_command_execute_function(const ShellCommandId& cmd_id,
|
|
std::function<int(int, char**)> exec_func);
|
|
|
|
void set_command_dependency(const ShellCommandId& cmd_id,
|
|
const std::vector<ShellCommandId>& cmd_dependency);
|
|
ShellCommandClassId add_command_class(const char* name);
|
|
public: /* Public validators */
|
|
bool valid_command_id(const ShellCommandId& cmd_id) const;
|
|
bool valid_command_class_id(const ShellCommandClassId& cmd_class_id) const;
|
|
public: /* Public executors */
|
|
/* Start the interactive mode, where users will type-in command by command */
|
|
void run_interactive_mode(T& context, const bool& quiet_mode = false);
|
|
/* Start the script mode, where users provide a file which includes all the commands to run */
|
|
void run_script_mode(const char* script_file_name, T& context);
|
|
/* Print all the commands by their classes. This is actually the help desk */
|
|
void print_commands() const;
|
|
/* Quit the shell */
|
|
void exit() const;
|
|
private: /* Private executors */
|
|
/* Execute a command, the command line is the user's input to launch a command
|
|
* The common_context is the data structure to exchange data between commands
|
|
*/
|
|
int execute_command(const char* cmd_line, T& common_context);
|
|
private: /* Internal data */
|
|
/* Name of the shell, this will appear in the interactive mode */
|
|
std::string name_;
|
|
|
|
/* Title of the shell, this will appear in the interactive mode as an introduction */
|
|
std::string title_;
|
|
|
|
/* Unique ids for each class of command */
|
|
vtr::vector<ShellCommandClassId, ShellCommandClassId> command_class_ids_;
|
|
|
|
/* Names for each class of command */
|
|
vtr::vector<ShellCommandClassId, std::string> command_class_names_;
|
|
|
|
/* Unique ids for each command */
|
|
vtr::vector<ShellCommandId, ShellCommandId> command_ids_;
|
|
|
|
/* Objects for each command */
|
|
vtr::vector<ShellCommandId, Command> commands_;
|
|
|
|
/* Parsing results for each command */
|
|
vtr::vector<ShellCommandId, CommandContext> command_contexts_;
|
|
|
|
/* Description of the command, this is going to be printed out in the help desk */
|
|
vtr::vector<ShellCommandId, std::string> command_description_;
|
|
|
|
/* Class ids for each command */
|
|
vtr::vector<ShellCommandId, ShellCommandClassId> command_classes_;
|
|
|
|
/* Function pointers to execute each command
|
|
* We support here three types of functions to be executed in the shell
|
|
* 1. Standard function, including the data exchange <T> and commands
|
|
* 2. Short function, including only the data exchange <T>
|
|
* 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<int(const T&, const Command&, const CommandContext&)>> command_const_execute_functions_;
|
|
vtr::vector<ShellCommandId, std::function<int(T&, const Command&, const CommandContext&)>> command_standard_execute_functions_;
|
|
vtr::vector<ShellCommandId, std::function<int(const T&)>> command_short_const_execute_functions_;
|
|
vtr::vector<ShellCommandId, std::function<int(T&)>> command_short_execute_functions_;
|
|
vtr::vector<ShellCommandId, std::function<void()>> command_builtin_execute_functions_;
|
|
vtr::vector<ShellCommandId, std::function<int(int, char**)>> command_macro_execute_functions_;
|
|
|
|
/* Type of execute functions for each command.
|
|
* This is supposed to be an internal data ONLY
|
|
*/
|
|
vtr::vector<ShellCommandId, e_exec_func_type> command_execute_function_types_;
|
|
|
|
/* A flag to indicate if the command has been executed */
|
|
vtr::vector<ShellCommandId, int> command_status_;
|
|
|
|
/* Dependency graph for different commands,
|
|
* This helps the shell interface to check if a command need other commands to be run before its execution
|
|
*/
|
|
vtr::vector<ShellCommandId, std::vector<ShellCommandId>> command_dependencies_;
|
|
|
|
/* Fast name look-up */
|
|
std::map<std::string, ShellCommandId> command_name2ids_;
|
|
std::map<std::string, ShellCommandClassId> command_class2ids_;
|
|
vtr::vector<ShellCommandClassId, std::vector<ShellCommandId>> commands_by_classes_;
|
|
|
|
/* Timer */
|
|
std::clock_t time_start_;
|
|
};
|
|
|
|
} /* End namespace openfpga */
|
|
|
|
/* Include the template implementation functions in the header file */
|
|
#include "shell.tpp"
|
|
|
|
#endif
|