start developing mini shell for open fpga
This commit is contained in:
parent
16752b7e39
commit
acdb3818c2
|
@ -1,4 +1,5 @@
|
|||
# OpenFPGA-related libraries
|
||||
add_subdirectory(libini)
|
||||
add_subdirectory(libminishell)
|
||||
add_subdirectory(libarchopenfpga)
|
||||
add_subdirectory(libopenfpgautil)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
cmake_minimum_required(VERSION 3.9)
|
||||
|
||||
project("libminishell")
|
||||
|
||||
#file(GLOB_RECURSE EXEC_SOURCES test/main.cpp)
|
||||
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
|
||||
file(GLOB_RECURSE LIB_HEADERS src/*.h)
|
||||
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
|
||||
|
||||
#Remove test executable from library
|
||||
#list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES})
|
||||
|
||||
#Create the library
|
||||
add_library(libminishell STATIC
|
||||
${LIB_HEADERS}
|
||||
${LIB_SOURCES})
|
||||
target_include_directories(libminishell PUBLIC ${LIB_INCLUDE_DIRS})
|
||||
set_target_properties(libminishell PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
|
||||
|
||||
#Specify link-time dependancies
|
||||
target_link_libraries(libminishell
|
||||
libvtrutil)
|
||||
|
||||
#Create the test executable
|
||||
#add_executable(read_arch_openfpga ${EXEC_SOURCES})
|
||||
#target_link_libraries(read_arch_openfpga libarchopenfpga)
|
||||
|
||||
#Supress IPO link warnings if IPO is enabled
|
||||
#get_target_property(READ_ARCH_USES_IPO read_arch_openfpga INTERPROCEDURAL_OPTIMIZATION)
|
||||
#if (READ_ARCH_USES_IPO)
|
||||
# set_target_properties(read_arch_openfpga PROPERTIES LINK_FLAGS ${IPO_LINK_WARN_SUPRESS_FLAGS})
|
||||
#endif()
|
||||
|
||||
#install(TARGETS libarchopenfpga read_arch_openfpga DESTINATION bin)
|
|
@ -0,0 +1,172 @@
|
|||
/*********************************************************************
|
||||
* Member functions for class Command
|
||||
********************************************************************/
|
||||
#include "vtr_assert.h"
|
||||
#include "command.h"
|
||||
|
||||
/* Begin namespace minishell */
|
||||
namespace minishell {
|
||||
|
||||
/*********************************************************************
|
||||
* Public constructors
|
||||
********************************************************************/
|
||||
Command::Command(const std::string& name) {
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public Accessors : aggregates
|
||||
***********************************************************************/
|
||||
std::string Command::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
Command::command_option_range Command::options() const {
|
||||
return vtr::make_range(option_ids_.begin(), option_ids_.end());
|
||||
}
|
||||
|
||||
std::vector<CommandOptionId> Command::required_options() const {
|
||||
std::vector<CommandOptionId> opts;
|
||||
for (const CommandOptionId& opt : options()) {
|
||||
if (true == option_required(opt)) {
|
||||
opts.push_back(opt);
|
||||
}
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
std::vector<CommandOptionId> Command::require_value_options() const {
|
||||
std::vector<CommandOptionId> opts;
|
||||
for (const CommandOptionId& opt : options()) {
|
||||
if (true == option_require_value(opt)) {
|
||||
opts.push_back(opt);
|
||||
}
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
CommandOptionId Command::option(const std::string& name) const {
|
||||
/* Ensure that the name is unique in the option list */
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it = option_name2ids_.find(name);
|
||||
if (name_it != option_name2ids_.end()) {
|
||||
return CommandOptionId::INVALID();
|
||||
}
|
||||
return option_name2ids_.at(name);
|
||||
}
|
||||
|
||||
CommandOptionId Command::short_option(const std::string& name) const {
|
||||
/* Ensure that the name is unique in the option list */
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it = option_short_name2ids_.find(name);
|
||||
if (name_it != option_short_name2ids_.end()) {
|
||||
return CommandOptionId::INVALID();
|
||||
}
|
||||
return option_short_name2ids_.at(name);
|
||||
}
|
||||
|
||||
std::string Command::option_name(const CommandOptionId& option_id) const {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
return option_names_[option_id];
|
||||
}
|
||||
|
||||
std::string Command::option_short_name(const CommandOptionId& option_id) const {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
return option_short_names_[option_id];
|
||||
}
|
||||
|
||||
bool Command::option_required(const CommandOptionId& option_id) const {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
return option_required_[option_id];
|
||||
}
|
||||
|
||||
bool Command::option_require_value(const CommandOptionId& option_id) const {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
return NUM_OPT_VALUE_TYPES != option_require_value_types_[option_id];
|
||||
}
|
||||
|
||||
e_option_value_type Command::option_require_value_type(const CommandOptionId& option_id) const {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
return option_require_value_types_[option_id];
|
||||
}
|
||||
|
||||
std::string Command::option_description(const CommandOptionId& option_id) const {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
return option_description_[option_id];
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public mutators
|
||||
***********************************************************************/
|
||||
|
||||
/* Add an option without required values */
|
||||
CommandOptionId Command::add_option(const std::string& name,
|
||||
const bool& option_required,
|
||||
const std::string& description) {
|
||||
/* Ensure that the name is unique in the option list */
|
||||
std::map<std::string, CommandOptionId>::const_iterator name_it = option_name2ids_.find(name);
|
||||
if (name_it != option_name2ids_.end()) {
|
||||
return CommandOptionId::INVALID();
|
||||
}
|
||||
|
||||
/* This is a legal name. we can create a new id */
|
||||
CommandOptionId option = CommandOptionId(option_ids_.size());
|
||||
option_ids_.push_back(option);
|
||||
option_names_.push_back(name);
|
||||
option_short_names_.emplace_back();
|
||||
option_required_.push_back(option_required);
|
||||
option_require_value_types_.push_back(NUM_OPT_VALUE_TYPES);
|
||||
option_description_.push_back(description);
|
||||
|
||||
/* Register the name and short name in the name2id map */
|
||||
option_name2ids_[name] = option;
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
/* Add a short name to an option */
|
||||
bool Command::set_option_short_name(const CommandOptionId& option_id,
|
||||
const std::string& short_name) {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
|
||||
/* Short name is optional, so do the following only when it is not empty
|
||||
* Ensure that the short name is unique in the option list
|
||||
*/
|
||||
if (true == short_name.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<std::string, CommandOptionId>::const_iterator short_name_it = option_short_name2ids_.find(short_name);
|
||||
if (short_name_it != option_short_name2ids_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
option_short_names_[option_id] = short_name;
|
||||
|
||||
/* Short name is optional, so register it only when it is not empty */
|
||||
option_short_name2ids_[short_name] = option_id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Command::set_option_require_value(const CommandOptionId& option_id,
|
||||
const e_option_value_type& option_require_value_type) {
|
||||
/* Validate the option id */
|
||||
VTR_ASSERT(true == valid_option_id(option_id));
|
||||
|
||||
option_require_value_types_[option_id] = option_require_value_type;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Public invalidators/validators
|
||||
***********************************************************************/
|
||||
bool Command::valid_option_id(const CommandOptionId& option_id) const {
|
||||
return ( size_t(option_id) < option_ids_.size() ) && ( option_id == option_ids_[option_id] );
|
||||
}
|
||||
|
||||
} /* End namespace minshell */
|
|
@ -0,0 +1,111 @@
|
|||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
/*********************************************************************
|
||||
* This header file includes data structure for option reading
|
||||
* This is a cornerstone data structure of mini shell
|
||||
* which aims to store command-line options for parser
|
||||
*
|
||||
* This data structue is design to read-in the command line options
|
||||
* which are organized as follows:
|
||||
*
|
||||
* <command_name> --<command_option_1> <command_option_1_value>
|
||||
* --<command_option_2> ...
|
||||
*
|
||||
* This is not only used by each command available in the shell
|
||||
* but also the interface of the shell, such as interactive mode
|
||||
********************************************************************/
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "vtr_vector.h"
|
||||
#include "vtr_range.h"
|
||||
#include "command_fwd.h"
|
||||
|
||||
/* Begin namespace minishell */
|
||||
namespace minishell {
|
||||
|
||||
/*********************************************************************
|
||||
* Supported date types of value which is followed by a command-line option
|
||||
********************************************************************/
|
||||
enum e_option_value_type {
|
||||
OPT_INT,
|
||||
OPT_FLOAT,
|
||||
OPT_STRING,
|
||||
NUM_OPT_VALUE_TYPES
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
* Data structure to stores all the information related to a command
|
||||
* to be defined in the mini shell
|
||||
* This data structure should NOT contain any parsing results!
|
||||
* It should be a read-only once created!
|
||||
*
|
||||
* Note:
|
||||
* When adding an option name, please do NOT add any dash at the beginning!!!
|
||||
********************************************************************/
|
||||
class Command {
|
||||
public: /* Types */
|
||||
typedef vtr::vector<CommandOptionId, CommandOptionId>::const_iterator command_option_iterator;
|
||||
/* Create range */
|
||||
typedef vtr::Range<command_option_iterator> command_option_range;
|
||||
public: /* Constructor */
|
||||
Command(const std::string& name);
|
||||
public: /* Public accessors */
|
||||
std::string name() const;
|
||||
command_option_range options() const;
|
||||
/* Find all the options that are mandatory */
|
||||
std::vector<CommandOptionId> required_options() const;
|
||||
/* Find all the options that require a value */
|
||||
std::vector<CommandOptionId> require_value_options() const;
|
||||
CommandOptionId option(const std::string& name) const;
|
||||
CommandOptionId short_option(const std::string& name) const;
|
||||
std::string option_name(const CommandOptionId& option_id) const;
|
||||
std::string option_short_name(const CommandOptionId& option_id) const;
|
||||
bool option_required(const CommandOptionId& option_id) const;
|
||||
bool option_require_value(const CommandOptionId& option_id) const;
|
||||
e_option_value_type option_require_value_type(const CommandOptionId& option_id) const;
|
||||
std::string option_description(const CommandOptionId& option_id) const;
|
||||
public: /* Public mutators */
|
||||
CommandOptionId add_option(const std::string& name,
|
||||
const bool& option_required,
|
||||
const std::string& description);
|
||||
bool set_option_short_name(const CommandOptionId& option_id, const std::string& short_name);
|
||||
void set_option_require_value(const CommandOptionId& option_id,
|
||||
const e_option_value_type& option_require_value_type);
|
||||
public: /* Public validators */
|
||||
bool valid_option_id(const CommandOptionId& option_id) const;
|
||||
private: /* Internal data */
|
||||
/* The name of the command */
|
||||
std::string name_;
|
||||
|
||||
vtr::vector<CommandOptionId, CommandOptionId> option_ids_;
|
||||
|
||||
/* Information about the options available in this command */
|
||||
/* Name of command line option to appear in the user interface
|
||||
* Regular names are typically with a prefix of double dash '--'
|
||||
* Short names are typically with a prefix of single dash '-'
|
||||
*/
|
||||
vtr::vector<CommandOptionId, std::string> option_names_;
|
||||
vtr::vector<CommandOptionId, std::string> option_short_names_;
|
||||
|
||||
/* If the option is manadatory when parsing */
|
||||
vtr::vector<CommandOptionId, bool> option_required_;
|
||||
|
||||
/* Data type of the option values to be converted
|
||||
* If the option does NOT require a value, this will be an invalid type
|
||||
*/
|
||||
vtr::vector<CommandOptionId, e_option_value_type> option_require_value_types_;
|
||||
|
||||
/* Description of the option, this is going to be printed out in the help desk */
|
||||
vtr::vector<CommandOptionId, std::string> option_description_;
|
||||
|
||||
/* Fast name look-up */
|
||||
std::map<std::string, CommandOptionId> option_name2ids_;
|
||||
std::map<std::string, CommandOptionId> option_short_name2ids_;
|
||||
};
|
||||
|
||||
} /* End namespace minshell */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
/*********************************************************************
|
||||
* Member functions for class CommandContext
|
||||
********************************************************************/
|
||||
#include "vtr_assert.h"
|
||||
#include "command_context.h"
|
||||
|
||||
/* Begin namespace minishell */
|
||||
namespace minishell {
|
||||
|
||||
/*********************************************************************
|
||||
* Public constructor
|
||||
********************************************************************/
|
||||
CommandContext::CommandContext(const Command& command) {
|
||||
option_enabled_.resize(command.options().size(), false);
|
||||
option_values_.resize(command.options().size());
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* Public accessors
|
||||
********************************************************************/
|
||||
bool CommandContext::option_enable(const Command& command,
|
||||
const CommandOptionId& option_id) const {
|
||||
VTR_ASSERT(true == command.valid_option_id(option_id));
|
||||
return option_enabled_[option_id];
|
||||
}
|
||||
|
||||
std::string CommandContext::option_value(const Command& command,
|
||||
const CommandOptionId& option_id) const {
|
||||
VTR_ASSERT(true == command.valid_option_id(option_id));
|
||||
return option_values_[option_id];
|
||||
}
|
||||
|
||||
std::vector<CommandOptionId> CommandContext::check_required_options(const Command& command) const {
|
||||
std::vector<CommandOptionId> fail_options;
|
||||
for (const CommandOptionId& option_id : command.required_options()) {
|
||||
if (false == option_enabled_[option_id]) {
|
||||
fail_options.push_back(option_id);
|
||||
}
|
||||
}
|
||||
return fail_options;
|
||||
}
|
||||
|
||||
std::vector<CommandOptionId> CommandContext::check_required_option_values(const Command& command) const {
|
||||
std::vector<CommandOptionId> fail_options;
|
||||
for (const CommandOptionId& option_id : command.require_value_options()) {
|
||||
if (true == option_values_[option_id].empty()) {
|
||||
fail_options.push_back(option_id);
|
||||
}
|
||||
}
|
||||
return fail_options;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* Public mutators
|
||||
********************************************************************/
|
||||
void CommandContext::set_option(const Command& command,
|
||||
const CommandOptionId& option_id, const bool& status) {
|
||||
VTR_ASSERT(true == command.valid_option_id(option_id));
|
||||
option_enabled_[option_id] = status;
|
||||
}
|
||||
|
||||
void CommandContext::set_option_value(const Command& command,
|
||||
const CommandOptionId& option_id, const std::string& value) {
|
||||
VTR_ASSERT(true == command.valid_option_id(option_id));
|
||||
option_values_[option_id] = value;
|
||||
}
|
||||
|
||||
} /* End namespace minshell */
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef COMMAND_CONTEXT_H
|
||||
#define COMMAND_CONTEXT_H
|
||||
|
||||
#include <string>
|
||||
#include "vtr_vector.h"
|
||||
#include "command_fwd.h"
|
||||
#include "command.h"
|
||||
|
||||
/* Begin namespace minishell */
|
||||
namespace minishell {
|
||||
|
||||
/*********************************************************************
|
||||
* Data structure to stores parsing results for a command
|
||||
********************************************************************/
|
||||
class CommandContext {
|
||||
public: /* Public constructor */
|
||||
/* Build a context based on the command information
|
||||
* This will allocate the internal data structure and assign default values
|
||||
*/
|
||||
CommandContext(const Command& command);
|
||||
public: /* Public accessors */
|
||||
bool option_enable(const Command& command,
|
||||
const CommandOptionId& option_id) const;
|
||||
std::string option_value(const Command& command,
|
||||
const CommandOptionId& option_id) const;
|
||||
/* Check if all the required options have been enabled
|
||||
* Any thing wrong will be reported in the return vector
|
||||
*
|
||||
* Note:
|
||||
* This function is supposed to be called after parsing is completed
|
||||
*/
|
||||
std::vector<CommandOptionId> check_required_options(const Command& command) const;
|
||||
|
||||
/* Check all the values that are required by the options
|
||||
* Any thing wrong will be reported in the return vector
|
||||
*
|
||||
* Note:
|
||||
* This function is supposed to be called after parsing is completed
|
||||
*/
|
||||
std::vector<CommandOptionId> check_required_option_values(const Command& command) const;
|
||||
public: /* Public mutators */
|
||||
void set_option(const Command& command,
|
||||
const CommandOptionId& option_id, const bool& status);
|
||||
void set_option_value(const Command& command,
|
||||
const CommandOptionId& option_id, const std::string& value);
|
||||
private: /* Internal data */
|
||||
/* Identify if the option is enabled or not */
|
||||
vtr::vector<CommandOptionId, bool> option_enabled_;
|
||||
|
||||
/* All the follow-up value of each option is stored as string,
|
||||
* It will be converted the data types by outside function
|
||||
* according to the value types
|
||||
*/
|
||||
vtr::vector<CommandOptionId, std::string> option_values_;
|
||||
};
|
||||
|
||||
} /* End namespace minshell */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef COMMAND_FWD_H
|
||||
#define COMMAND_FWD_H
|
||||
|
||||
#include "vtr_strong_id.h"
|
||||
|
||||
/* Begin namespace minishell */
|
||||
namespace minishell {
|
||||
|
||||
/*********************************************************************
|
||||
* A strong id for the options used by a command
|
||||
********************************************************************/
|
||||
struct command_option_id_tag;
|
||||
|
||||
typedef vtr::StrongId<command_option_id_tag> CommandOptionId;
|
||||
|
||||
} /* End namespace minshell */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,157 @@
|
|||
/********************************************************************
|
||||
* This file includes parser(s) to convert user's input from
|
||||
* shell interface to a data structure CommandContext
|
||||
*
|
||||
* TODO: a strong dependency is that we use VTR logging system
|
||||
*******************************************************************/
|
||||
#include <cstring>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
#include "command_parser.h"
|
||||
|
||||
/* Begin namespace minishell */
|
||||
namespace minishell {
|
||||
|
||||
/********************************************************************
|
||||
* Try to find an option in the command and update the CommandContext if needed
|
||||
*******************************************************************/
|
||||
static
|
||||
CommandOptionId parse_option(const std::string& argv,
|
||||
const Command& cmd,
|
||||
CommandContext& cmd_context) {
|
||||
CommandOptionId option_id = cmd.option(argv);
|
||||
/* Not found, error out */
|
||||
if (CommandOptionId::INVALID() == option_id) {
|
||||
VTR_LOG("Detect unknown option '%s'!\n",
|
||||
argv.c_str());
|
||||
}
|
||||
/* Found, update the CommandContext */
|
||||
cmd_context.set_option(cmd, option_id, true);
|
||||
|
||||
return option_id;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Try to find a short option in the command
|
||||
* Update the CommandContext if needed
|
||||
*******************************************************************/
|
||||
static
|
||||
CommandOptionId parse_short_option(const std::string& argv,
|
||||
const Command& cmd,
|
||||
CommandContext& cmd_context) {
|
||||
CommandOptionId option_id = cmd.short_option(argv);
|
||||
/* Not found, error out */
|
||||
if (CommandOptionId::INVALID() == option_id) {
|
||||
VTR_LOG("Detect unknown option '%s'!\n",
|
||||
argv.c_str());
|
||||
}
|
||||
/* Found, update the CommandContext */
|
||||
cmd_context.set_option(cmd, option_id, true);
|
||||
|
||||
return option_id;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Main parser to convert user's input from
|
||||
* shell interface to a data structure CommandContext
|
||||
*******************************************************************/
|
||||
bool parse_command(const std::vector<std::string>& argv,
|
||||
const Command& cmd,
|
||||
CommandContext& cmd_context) {
|
||||
/* We at least expect 1 arguement, which is the command name itself */
|
||||
VTR_ASSERT(1 <= argv.size());
|
||||
|
||||
/* Validate that the command name matches argv[0] */
|
||||
if (argv[0] == cmd.name()) {
|
||||
VTR_LOG("Unexpected command name '%s'!",
|
||||
argv[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Start from argv[1], the 1st argv is programme name */
|
||||
for (size_t iarg = 1; iarg < argv.size(); ++iarg) {
|
||||
/* Option must start with dash */
|
||||
if (0 != strncmp("-", argv[iarg].c_str(), 1)) {
|
||||
VTR_LOG("Invalid option '%s'!",
|
||||
argv[iarg].c_str());
|
||||
return false;
|
||||
}
|
||||
/* First try to process a full option
|
||||
* which always starts with double dash '--'
|
||||
*/
|
||||
if (0 == strncmp("--", argv[iarg].c_str(), 2)) {
|
||||
/* See if there is a option defined in the command object
|
||||
* Note that the first two characters are skipped when searching the name
|
||||
*/
|
||||
CommandOptionId option_id = parse_option(argv[iarg].substr(2), cmd, cmd_context);
|
||||
|
||||
if (CommandOptionId::INVALID() == option_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the option requires a value, we visit the next argument */
|
||||
if (true == cmd.option_require_value(option_id)) {
|
||||
++iarg;
|
||||
/* If this is the last arugment, we finish */
|
||||
if (iarg == argv.size()) {
|
||||
break;
|
||||
}
|
||||
cmd_context.set_option_value(cmd, option_id, argv[iarg]);
|
||||
}
|
||||
/* Finish this iteration here, we found something */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Second try to process a short option
|
||||
* which always starts with double dash '-'
|
||||
*/
|
||||
if (0 == strncmp("-", argv[iarg].c_str(), 1)) {
|
||||
/* See if there is a option defined in the command object
|
||||
* Note that the first two characters are skipped when searching the name
|
||||
*/
|
||||
CommandOptionId option_id = parse_short_option(argv[iarg].substr(1), cmd, cmd_context);
|
||||
|
||||
if (CommandOptionId::INVALID() == option_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the option requires a value, we visit the next argument */
|
||||
if (true == cmd.option_require_value(option_id)) {
|
||||
++iarg;
|
||||
/* If this is the last arugment, we finish */
|
||||
if (iarg == argv.size()) {
|
||||
break;
|
||||
}
|
||||
cmd_context.set_option_value(cmd, option_id, argv[iarg]);
|
||||
}
|
||||
/* Finish this iteration here, we found something */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure that all the required options have been satisfied
|
||||
* If not, we echo the details about what are missing
|
||||
*/
|
||||
std::vector<CommandOptionId> missing_options = cmd_context.check_required_options(cmd);
|
||||
if (!missing_options.empty()) {
|
||||
for (const CommandOptionId& missing_opt : missing_options) {
|
||||
VTR_LOG("Required option '%s' is missing!",
|
||||
cmd.option_name(missing_opt));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<CommandOptionId> missing_value_options = cmd_context.check_required_option_values(cmd);
|
||||
if (!missing_value_options.empty()) {
|
||||
for (const CommandOptionId& missing_opt : missing_value_options) {
|
||||
VTR_LOG("Require value for option '%s' is missing!",
|
||||
cmd.option_name(missing_opt));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* End namespace minshell */
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef COMMAND_PARSER_H
|
||||
#define COMMAND_PARSER_H
|
||||
|
||||
#include <string>
|
||||
#include "command.h"
|
||||
#include "command_context.h"
|
||||
|
||||
/* Begin namespace minishell */
|
||||
namespace minishell {
|
||||
|
||||
bool parse_command(const std::vector<std::string>& argv,
|
||||
const Command& cmd,
|
||||
CommandContext& cmd_context);
|
||||
|
||||
} /* End namespace minshell */
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue