Console: Refactor config file parser into several classes
[senf.git] / 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
32 //#include "ProgramOptions.mpp"
33 #define prefix_
34 ///////////////////////////////cc.p////////////////////////////////////////
35
36 ///////////////////////////////////////////////////////////////////////////
37 // senf::console::detail::ProgramOptionsSource
38
39 prefix_ void senf::console::detail::ProgramOptionsSource::v_parse(RestrictedExecutor & executor)
40 {
41     char ** argp (argv_);
42     int n (argc_);
43     for (; n; --n, ++argp) {
44         std::string arg (*argp);
45         if (boost::algorithm::starts_with(arg, std::string("--")))
46             parseLongOption(arg.substr(2), executor);
47         else
48             parseNonOption(arg, executor);
49     }
50 }
51
52 namespace {
53     struct MakeWordToken
54     {
55         typedef senf::console::Token result_type;
56         template <class Range>
57         result_type operator()(Range const & r) const
58             { return senf::console::WordToken(std::string(boost::begin(r), boost::end(r))); }
59     };
60 }
61
62 prefix_ void
63 senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const & arg,
64                                                              RestrictedExecutor & executor)
65 {
66     std::string::size_type ix (arg.find('='));
67     std::string name (arg.substr(0,ix));
68     std::string value (ix==std::string::npos ? std::string() : arg.substr(ix+1));
69
70     typedef std::vector<Token> Path;
71
72     ParseCommandInfo cmd;
73     Path path;
74     
75     DirectoryNode::ptr cwd (executor.root().thisptr());
76     std::string::size_type b (0);
77     while (b < name.size()) {
78         std::string::size_type e (name.size());
79         for (;e != std::string::npos && e > b; e = name.rfind('-', e)) {
80             DirectoryNode::ChildrenRange completions (cwd->completions(name.substr(b,e-b)));
81             if (completions.size() == 1) {
82                 path.push_back(WordToken(completions.begin()->first));
83                 if (e < name.size())
84                     cwd = cwd->getDirectory(completions.begin()->first).thisptr();
85                 b = e+1;
86                 e = b+1;
87                 break;
88             }
89         }
90         if (e == std::string::npos || e <= b) {
91             // This will produce a correct error message later
92             path.push_back(WordToken(name.substr(b)));
93             b = name.size();
94         }
95     }
96     
97     cmd.command(path);
98     parser_.parseArguments(value, cmd);
99     executor(std::cerr, cmd);
100 }
101
102 prefix_ void
103 senf::console::detail::ProgramOptionsSource::parseNonOption(std::string const & arg,
104                                                             RestrictedExecutor & executor)
105 {}
106
107 ///////////////////////////////////////////////////////////////////////////
108
109 prefix_ void senf::console::parseOptions(int argc, char ** argv, DirectoryNode & root)
110 {
111     ProgramOptions opts (argc, argv, root);
112     opts.parse();
113 }
114
115 ///////////////////////////////cc.e////////////////////////////////////////
116 #undef prefix_
117 //#include "ProgramOptions.mpp"
118
119 \f
120 // Local Variables:
121 // mode: c++
122 // fill-column: 100
123 // comment-column: 40
124 // c-file-style: "senf"
125 // indent-tabs-mode: nil
126 // ispell-local-dictionary: "american"
127 // compile-command: "scons -u test"
128 // End: