From 363ab382e5a77814f7c8fa235f1732068e3b9227 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 21 Jan 2020 17:24:49 -0700 Subject: [PATCH] add shell data structure --- libopenfpga/libminishell/src/command.h | 2 +- libopenfpga/libminishell/src/shell.cpp | 76 +++++++++++++++++++ libopenfpga/libminishell/src/shell.h | 96 ++++++++++++++++++++++++ libopenfpga/libminishell/src/shell_fwd.h | 18 +++++ 4 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 libopenfpga/libminishell/src/shell.cpp create mode 100644 libopenfpga/libminishell/src/shell.h create mode 100644 libopenfpga/libminishell/src/shell_fwd.h diff --git a/libopenfpga/libminishell/src/command.h b/libopenfpga/libminishell/src/command.h index 5a35b393f..c4a1b9869 100644 --- a/libopenfpga/libminishell/src/command.h +++ b/libopenfpga/libminishell/src/command.h @@ -42,7 +42,7 @@ enum e_option_value_type { * This data structure should NOT contain any parsing results! * It should be a read-only once created! * - * An exampe of how to use + * An example of how to use * ----------------------- * // Create a new command with a name of 'read_file' * // This command can be called as diff --git a/libopenfpga/libminishell/src/shell.cpp b/libopenfpga/libminishell/src/shell.cpp new file mode 100644 index 000000000..401a606c7 --- /dev/null +++ b/libopenfpga/libminishell/src/shell.cpp @@ -0,0 +1,76 @@ +/********************************************************************* + * Member functions for class Shell + ********************************************************************/ +#include "vtr_assert.h" +#include "shell.h" + +/* Begin namespace minishell */ +namespace minishell { + +/********************************************************************* + * Public constructors + ********************************************************************/ +template +Shell::Shell(const char* name) { + name_ = std::string(name); +} + +/************************************************************************ + * Public Accessors : aggregates + ***********************************************************************/ +template +std::string Shell::name() const { + return name_; +} + +template +typename Shell::shell_command_range Shell::commands() const { + return vtr::make_range(command_ids_.begin(), command_ids_.end()); +} + +template +ShellCommandId Shell::command(const std::string& name) const { + /* Ensure that the name is unique in the command list */ + std::map::const_iterator name_it = command_name2ids_.find(name); + if (name_it == command_name2ids_.end()) { + return ShellCommandId::INVALID(); + } + return command_name2ids_.at(name); +} + +/************************************************************************ + * Public mutators + ***********************************************************************/ +/* Add a command with it description */ +template +ShellCommandId Shell::add_command(const Command& cmd, const char* descr) { + /* Ensure that the name is unique in the command list */ + std::map::const_iterator name_it = command_name2ids_.find(std::string(cmd.name())); + if (name_it != command_name2ids_.end()) { + return ShellCommandId::INVALID(); + } + + /* This is a legal name. we can create a new id */ + ShellCommandId shell_cmd = ShellCommandId(command_ids_.size()); + command_ids_.push_back(shell_cmd); + commands_.emplace_back(cmd); + command_contexts_.push_back(CommandContext(cmd)); + command_description_.push_back(descr); + command_execute_functions_.emplace_back(); + command_dependencies_.emplace_back(); + + /* Register the name in the name2id map */ + command_name2ids_[std::string(name)] = cmd.name(); + + return shell_cmd; +} + +/************************************************************************ + * Public invalidators/validators + ***********************************************************************/ +template +bool Shell::valid_command_id(const ShellCommandId& cmd_id) const { + return ( size_t(cmd_id) < command_ids_.size() ) && ( cmd_id == command_ids_[cmd_id] ); +} + +} /* End namespace minshell */ diff --git a/libopenfpga/libminishell/src/shell.h b/libopenfpga/libminishell/src/shell.h new file mode 100644 index 000000000..aff707650 --- /dev/null +++ b/libopenfpga/libminishell/src/shell.h @@ -0,0 +1,96 @@ +#ifndef SHELL_H +#define SHELL_H + +#include +#include +#include +#include + +#include "vtr_vector.h" +#include "vtr_range.h" +#include "command.h" +#include "command_context.h" +#include "shell_fwd.h" + +/* Begin namespace minishell */ +namespace minishell { + +/********************************************************************* + * 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 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 two arguments + * // void read_arch(T, 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 parsing results for the command + * shell.set_command_execute_function(cmd_read_arch, &read_arch); + * + * // Run a shell + * shell.run(); + * + ********************************************************************/ +template +class Shell { + public: /* Types */ + typedef vtr::vector::const_iterator shell_command_iterator; + /* Create range */ + typedef vtr::Range shell_command_range; + public: /* Constructor */ + Shell(const char* name); + public: /* Public accessors */ + std::string name() const; + shell_command_range commands() const; + ShellCommandId command(const std::string& name) const; + public: /* Public mutators */ + ShellCommandId add_command(const Command& cmd, const char* descr); + public: /* Public validators */ + bool valid_command_id(const ShellCommandId& cmd_id) const; + private: /* Internal data */ + /* The name of the shell*/ + std::string name_; + + /* Unique ids for each command */ + vtr::vector command_ids_; + + /* Objects for each command */ + vtr::vector commands_; + + /* Parsing results for each command */ + vtr::vector command_contexts_; + + /* Description of the command, this is going to be printed out in the help desk */ + vtr::vector command_description_; + + /* Function pointers to execute each command */ + vtr::vector> command_execute_functions_; + + /* 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> command_dependencies_; + + /* Fast name look-up */ + std::map command_name2ids_; +}; + +} /* End namespace minshell */ + +#endif diff --git a/libopenfpga/libminishell/src/shell_fwd.h b/libopenfpga/libminishell/src/shell_fwd.h new file mode 100644 index 000000000..56a441644 --- /dev/null +++ b/libopenfpga/libminishell/src/shell_fwd.h @@ -0,0 +1,18 @@ +#ifndef SHELL_FWD_H +#define SHELL_FWD_H + +#include "vtr_strong_id.h" + +/* Begin namespace minishell */ +namespace minishell { + +/********************************************************************* + * A strong id for the options used by a command + ********************************************************************/ +struct shell_command_id_tag; + +typedef vtr::StrongId ShellCommandId; + +} /* End namespace minshell */ + +#endif