6eb3107230a882ea6d1204386d0cc7acad170f22
[senf.git] / Scheduler / Console / ProgramOptions.cc
1 // $Id$
2 //
3 // Copyright (C) 2008 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \file
24     \brief ProgramOptions non-inline non-template implementation */
25
26 #include "ProgramOptions.hh"
27 #include "ProgramOptions.ih"
28
29 // Custom includes
30 #include <boost/algorithm/string/predicate.hpp>
31 #include <boost/format.hpp>
32
33 //#include "ProgramOptions.mpp"
34 #define prefix_
35 ///////////////////////////////cc.p////////////////////////////////////////
36
37 ///////////////////////////////////////////////////////////////////////////
38 // senf::console::detail::ProgramOptionsSource::NonOptionContainer
39
40 prefix_ senf::console::detail::ProgramOptionsSource::NonOptionContainer::~NonOptionContainer()
41 {}
42
43 ///////////////////////////////////////////////////////////////////////////
44 // senf::console::detail::ProgramOptionsSource
45
46 prefix_ void senf::console::detail::ProgramOptionsSource::v_parse(RestrictedExecutor & executor)
47 {
48     if (nonOptions_)
49         nonOptions_->clear();
50     if (argc_ <= 1)
51         return;
52     char ** argp (argv_+1);
53     int n (argc_-1);
54     for (; n; --n, ++argp) {
55         std::string arg (*argp);
56         if (arg == "--") {
57             for (; n; --n, ++argp)
58                 parseNonOption(arg, executor);
59             break;
60         }
61         else if (boost::algorithm::starts_with(arg, std::string("--")) && arg.size() > 2)
62             parseLongOption(arg.substr(2), executor);
63         else if (boost::algorithm::starts_with(arg, std::string("-")) && arg.size() > 1) {
64             for (std::string::size_type i (1); i<arg.size(); ++i) {
65                 char opt (arg[i]);
66                 ShortOptions::iterator j (shortOptions_.find(opt));
67                 if (j == shortOptions_.end())
68                     throw SyntaxErrorException(
69                         (boost::format("invalid short option '%c'") % opt).str());
70                 std::string param;
71                 if (j->second.withArg) {
72                     if (i >= arg.size()-1) {
73                         if (n > 0) {
74                             param = *(++argp);
75                             --n;
76                         }
77                     }
78                     else 
79                         param = arg.substr(i+1);
80                     i = arg.size();
81                 }
82                 std::string longOpt (j->second.longOpt);
83                 if (! param.empty() ) {
84                     longOpt += "=";
85                     longOpt += param;
86                 }
87                 if (boost::algorithm::starts_with(longOpt, std::string("--")))
88                     longOpt = longOpt.substr(2);
89                 parseLongOption(longOpt, executor);
90             }
91         }
92         else
93             parseNonOption(arg, executor);
94     }
95 }
96
97 prefix_ void
98 senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const & arg,
99                                                              RestrictedExecutor & executor)
100 {
101     std::string::size_type ix (arg.find('='));
102     std::string name (arg.substr(0,ix));
103     std::string value (ix==std::string::npos ? std::string() : arg.substr(ix+1));
104
105     typedef std::vector<Token> Path;
106
107     ParseCommandInfo cmd;
108     Path path;
109     
110     DirectoryNode::ptr cwd (executor.root().thisptr());
111     std::string::size_type b (0);
112     while (b < name.size()) {
113         std::string::size_type e (name.size());
114         for (;e != std::string::npos && e > b; e = name.rfind('-', e)) {
115             std::string key (name.substr(b,e-b));
116             if (! cwd->hasChild(key)) {
117                 DirectoryNode::ChildrenRange completions (cwd->completions(key));
118                 if (completions.size() == 1)
119                     key = completions.begin()->first;
120                 else
121                     continue;
122             }
123             path.push_back(WordToken(key));
124             if (e < name.size())
125                 cwd = cwd->getDirectory(key).thisptr();
126             b = e+1;
127             e = b+1;
128             break;
129         }
130         if (e == std::string::npos || e <= b) {
131             // This will produce a correct error message later or will skip the node,
132             // if parsing is restricted to a subtree
133             path.push_back(WordToken(name.substr(b)));
134             b = name.size();
135         }
136     }
137     
138     cmd.command(path);
139     parser_.parseArguments(value, cmd);
140     executor(std::cerr, cmd);
141 }
142
143 prefix_ void
144 senf::console::detail::ProgramOptionsSource::parseNonOption(std::string const & arg,
145                                                             RestrictedExecutor & executor)
146 {
147     if (! nonOptions_)
148         throw SyntaxErrorException("invalid non-option argument");
149     nonOptions_->push_back(arg);
150 }
151
152 ///////////////////////////////////////////////////////////////////////////
153
154 prefix_ void senf::console::parseOptions(int argc, char ** argv, DirectoryNode & root)
155 {
156     ProgramOptions opts (argc, argv, root);
157     opts.parse();
158 }
159
160 ///////////////////////////////cc.e////////////////////////////////////////
161 #undef prefix_
162 //#include "ProgramOptions.mpp"
163
164 \f
165 // Local Variables:
166 // mode: c++
167 // fill-column: 100
168 // comment-column: 40
169 // c-file-style: "senf"
170 // indent-tabs-mode: nil
171 // ispell-local-dictionary: "american"
172 // compile-command: "scons -u test"
173 // End: