4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief ProgramOptions non-inline non-template implementation */
26 #include "ProgramOptions.hh"
27 #include "ProgramOptions.ih"
30 #include <boost/algorithm/string/predicate.hpp>
31 #include <boost/format.hpp>
32 #include "../../Utils/range.hh"
34 //#include "ProgramOptions.mpp"
36 ///////////////////////////////cc.p////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////
39 // senf::console::detail::ProgramOptionsSource::NonOptionContainer
41 prefix_ senf::console::detail::ProgramOptionsSource::NonOptionContainer::~NonOptionContainer()
44 ///////////////////////////////////////////////////////////////////////////
45 // senf::console::detail::ProgramOptionsSource
47 prefix_ void senf::console::detail::ProgramOptionsSource::v_parse(RestrictedExecutor & executor)
53 char const ** argp (argv_+1);
55 for (; n; --n, ++argp) {
56 std::string arg (*argp);
58 for (; n; --n, ++argp)
59 parseNonOption(arg, executor);
62 else if (boost::algorithm::starts_with(arg, std::string("--")) && arg.size() > 2)
63 parseLongOption(arg.substr(2), executor);
64 else if (boost::algorithm::starts_with(arg, std::string("-")) && arg.size() > 1) {
65 for (std::string::size_type i (1); i<arg.size(); ++i) {
67 ShortOptions::iterator j (shortOptions_.find(opt));
68 if (j == shortOptions_.end())
69 throw SyntaxErrorException(
70 (boost::format("invalid short option '%c'") % opt).str());
72 if (j->second.withArg) {
73 if (i >= arg.size()-1) {
80 param = arg.substr(i+1);
83 std::string longOpt (j->second.longOpt);
84 if (! param.empty() ) {
88 if (boost::algorithm::starts_with(longOpt, std::string("--")))
89 longOpt = longOpt.substr(2);
90 parseLongOption(longOpt, executor);
94 parseNonOption(arg, executor);
99 senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const & arg,
100 RestrictedExecutor & executor)
102 std::string::size_type ix (arg.find('='));
103 std::string name (arg.substr(0,ix));
104 std::string value (ix==std::string::npos ? std::string() : arg.substr(ix+1));
106 typedef std::vector<Token> Path;
108 ParseCommandInfo cmd;
111 DirectoryNode::ptr cwd (executor.root().thisptr());
112 std::string::size_type b (0);
113 while (b < name.size()) {
114 std::string::size_type e (name.size());
115 for (;e != std::string::npos && e > b; e = name.rfind('-', e)) {
116 std::string key (name.substr(b,e-b));
117 if (! cwd->hasChild(key)) {
118 DirectoryNode::ChildrenRange completions (cwd->completions(key));
119 if (has_one_elt(completions))
120 key = completions.begin()->first;
124 path.push_back(WordToken(key));
126 cwd = cwd->getDirectory(key).thisptr();
131 if (e == std::string::npos || e <= b) {
132 // This will produce a correct error message later or will skip the node,
133 // if parsing is restricted to a subtree
134 path.push_back(WordToken(name.substr(b)));
140 parser_.parseArguments(value, cmd);
141 executor(std::cerr, cmd);
145 senf::console::detail::ProgramOptionsSource::parseNonOption(std::string const & arg,
146 RestrictedExecutor & executor)
149 throw SyntaxErrorException("invalid non-option argument");
150 nonOptions_->push_back(arg);
153 ///////////////////////////////////////////////////////////////////////////
155 prefix_ void senf::console::parseOptions(int argc, char const ** argv, DirectoryNode & root)
157 ProgramOptions opts (argc, argv, root);
161 ///////////////////////////////cc.e////////////////////////////////////////
163 //#include "ProgramOptions.mpp"
169 // comment-column: 40
170 // c-file-style: "senf"
171 // indent-tabs-mode: nil
172 // ispell-local-dictionary: "american"
173 // compile-command: "scons -u test"