00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 #include "ProgramOptions.hh"
00027 #include "ProgramOptions.ih"
00028
00029
00030 #include <boost/algorithm/string/predicate.hpp>
00031 #include <boost/format.hpp>
00032 #include <senf/Utils/Range.hh>
00033 #include "OverloadedCommand.hh"
00034
00035
00036 #define prefix_
00037
00038
00039
00040
00041
00042 prefix_ senf::console::detail::ProgramOptionsSource::NonOptionContainer::~NonOptionContainer()
00043 {}
00044
00045
00046
00047
00048 prefix_ void senf::console::detail::ProgramOptionsSource::v_parse(RestrictedExecutor & executor)
00049 {
00050 if (nonOptions_)
00051 nonOptions_->clear();
00052 if (argc_ <= 1)
00053 return;
00054 char const ** argp (argv_+1);
00055 int n (argc_-1);
00056 for (; n; --n, ++argp) {
00057 std::string arg (*argp);
00058 if (arg == "--") {
00059 for (; n; --n, ++argp)
00060 parseNonOption(arg, executor);
00061 break;
00062 }
00063 else if (boost::algorithm::starts_with(arg, std::string("--")) && arg.size() > 2)
00064 try {
00065 parseLongOption(arg.substr(2), executor);
00066 }
00067 catch (senf::ExceptionMixin & e) {
00068 e << "\nwhile parsing command line option: " << arg;
00069 throw;
00070 }
00071 else if (boost::algorithm::starts_with(arg, std::string("-")) && arg.size() > 1) {
00072 for (std::string::size_type i (1); i<arg.size(); ++i) {
00073 char opt (arg[i]);
00074 ShortOptions::iterator j (shortOptions_.find(opt));
00075 if (j == shortOptions_.end())
00076 throw SyntaxErrorException(
00077 (boost::format("invalid short option '%c'") % opt).str());
00078 std::string param;
00079 if (j->second.withArg) {
00080 if (i >= arg.size()-1) {
00081 if (n > 0) {
00082 param = *(++argp);
00083 --n;
00084 }
00085 }
00086 else
00087 param = arg.substr(i+1);
00088 i = arg.size();
00089 }
00090 std::string longOpt (j->second.longOpt);
00091 if (! param.empty() ) {
00092 longOpt += "=";
00093 longOpt += param;
00094 }
00095 if (boost::algorithm::starts_with(longOpt, std::string("--")))
00096 longOpt = longOpt.substr(2);
00097 try {
00098 parseLongOption(longOpt, executor);
00099 }
00100 catch (senf::ExceptionMixin & e) {
00101 e << "\nwhile parsing command line option: -" << opt << ' ' << param;
00102 throw;
00103 }
00104 }
00105 }
00106 else
00107 parseNonOption(arg, executor);
00108 }
00109 }
00110
00111 prefix_ void
00112 senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const & arg,
00113 RestrictedExecutor & executor)
00114 {
00115 std::string::size_type ix (arg.find('='));
00116 std::string name (arg.substr(0,ix));
00117 std::string value (ix==std::string::npos ? std::string() : arg.substr(ix+1));
00118
00119 typedef std::vector<Token> Path;
00120
00121 ParseCommandInfo cmd;
00122 Path path;
00123
00124 DirectoryNode::ptr cwd (executor.root().thisptr());
00125 std::string::size_type b (0);
00126 while (b < name.size()) {
00127 std::string::size_type e (name.size());
00128 for (;e != std::string::npos && e > b; e = name.rfind('-', e)) {
00129 std::string key (name.substr(b,e-b));
00130 if (! cwd->hasChild(key)) {
00131 DirectoryNode::ChildrenRange completions (cwd->completions(key));
00132 if (has_one_elt(completions))
00133 key = completions.begin()->first;
00134 else {
00135 e -= 1;
00136 continue;
00137 }
00138 }
00139 path.push_back(WordToken(key));
00140 if (e < name.size())
00141 cwd = cwd->getDirectory(key).thisptr();
00142 b = e+1;
00143 e = b+1;
00144 break;
00145 }
00146 if (e == std::string::npos || e <= b) {
00147
00148
00149 path.push_back(WordToken(name.substr(b)));
00150 b = name.size();
00151 }
00152 }
00153
00154 cmd.command(path);
00155
00156
00157
00158
00159
00160
00161
00162 try {
00163 GenericNode const & node (executor.getNode(cmd));
00164 OverloadedCommandNode const * cmdnode (dynamic_cast<OverloadedCommandNode const *>(&node));
00165 if (cmdnode && cmdnode->overloads().size() == 1) {
00166 CommandOverload const & overload (**cmdnode->overloads().begin());
00167 if (overload.numArguments() == 1) {
00168 ArgumentDoc argdoc;
00169 argdoc.singleToken = false;
00170 overload.argumentDoc(0, argdoc);
00171 if (argdoc.singleToken) {
00172 cmd.addToken(WordToken(value));
00173 goto execute;
00174 }
00175 }
00176 } {
00177 parser_.parseArguments(value, cmd);
00178 }
00179 execute:
00180 executor(executor.stream(), cmd);
00181 }
00182 catch (Executor::IgnoreCommandException &)
00183 {}
00184 }
00185
00186 prefix_ void
00187 senf::console::detail::ProgramOptionsSource::parseNonOption(std::string const & arg,
00188 RestrictedExecutor & executor)
00189 {
00190 if (! nonOptions_)
00191 throw SyntaxErrorException("invalid non-option argument");
00192 nonOptions_->push_back(arg);
00193 }
00194
00195
00196
00197 prefix_ void senf::console::parseOptions(int argc, char const ** argv, DirectoryNode & root)
00198 {
00199 ProgramOptions opts (argc, argv, root);
00200 opts.parse();
00201 }
00202
00203
00204 #undef prefix_
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216