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 Executor non-inline non-template implementation */
26 #include "Executor.hh"
27 //#include "Executor.ih"
30 #include <boost/utility.hpp>
31 #include "../Utils/senfassert.hh"
33 //#include "Executor.mpp"
35 ///////////////////////////////cc.p////////////////////////////////////////
39 struct TraverseTokens {
40 typedef std::string const & result_type;
41 result_type operator()(senf::console::Token const & token) const {
48 ///////////////////////////////////////////////////////////////////////////
49 // senf::console::Executor
51 prefix_ senf::console::DirectoryNode & senf::console::Executor::cwd()
54 SENF_ASSERT( ! cwd_.empty() );
55 while (cwd_.size()>1 && (cwd_.back().expired() || ! cwd_.back().lock()->active()))
57 return * cwd_.back().lock();
60 prefix_ void senf::console::Executor::execute(std::ostream & output,
61 ParseCommandInfo const & command)
63 SENF_LOG(( "Executing: " << command ));
66 (void) cwd(); // Prune the cwd path of expired entries
69 switch(command.builtin()) {
70 case ParseCommandInfo::NoBuiltin :
73 exec(output, command);
76 case ParseCommandInfo::BuiltinCD :
80 // The parser ensures, we have exactly one argument
81 cd(*command.arguments().begin());
83 catch (IgnoreCommandException &) {
84 throw SyntaxErrorException(
85 "'cd' cannot be skipped (don't use 'cd' in conf-files)");
89 case ParseCommandInfo::BuiltinLS :
92 // The parser ensures, we have either one or no argument
94 command.tokens().empty() ? command.tokens() : *command.arguments().begin() );
97 case ParseCommandInfo::BuiltinPUSHD :
98 // The parser ensures, we have exactly one argument
99 pushd( *command.arguments().begin() );
102 case ParseCommandInfo::BuiltinPOPD :
103 // The parser ensures, we have no arguments
107 case ParseCommandInfo::BuiltinEXIT :
110 // The parser ensures, we have no arguments
114 case ParseCommandInfo::BuiltinHELP :
117 // The parser ensures, we have either one or no arguments
119 command.tokens().empty() ? command.tokens() : *command.arguments().begin() );
124 catch (InvalidPathException &) {
125 output << "invalid path" << std::endl;
127 catch (InvalidDirectoryException &) {
128 output << "invalid directory" << std::endl;
130 catch (InvalidCommandException &) {
131 output << "invalid command" << std::endl;
133 catch (IgnoreCommandException &) {}
136 prefix_ void senf::console::Executor::exec(std::ostream & output,
137 ParseCommandInfo const & command)
139 GenericNode & node ( traverseNode(command.commandPath()) );
140 DirectoryNode * dir ( dynamic_cast<DirectoryNode*>(&node) );
142 if (autocd_ && command.tokens().empty()) {
143 cd( boost::make_iterator_range(
144 command.commandPath().begin(),
145 command.commandPath().end()) );
147 throw InvalidCommandException();
149 dynamic_cast<CommandNode &>(node)(output, command);
154 prefix_ void senf::console::Executor::cd(ParseCommandInfo::TokensRange dir)
156 if (dir.size() == 1 && *dir.begin() == WordToken("-")) {
158 (void) cwd(); // Prune any expired items
161 // We need to use a temporary so an error somewhere while traversing the dir does not cause
162 // the current directory to change.
164 traverseDirectory(dir, newDir);
170 prefix_ void senf::console::Executor::ls(std::ostream & output,
171 ParseCommandInfo::TokensRange path)
174 traverseDirectory(path, dir);
175 DirectoryNode & node (*dir.back().lock());
176 DirectoryNode::child_iterator i (node.children().begin());
177 DirectoryNode::child_iterator const i_end (node.children().end());
178 for (; i != i_end; ++i) {
180 if (boost::dynamic_pointer_cast<DirectoryNode>(i->second))
186 prefix_ void senf::console::Executor::pushd(ParseCommandInfo::TokensRange dir)
191 traverseDirectory(dir, newDir);
193 catch (IgnoreCommandException &) {
197 dirstack_.push_back(Path());
198 dirstack_.back().swap(cwd_);
202 prefix_ void senf::console::Executor::popd()
204 if (! dirstack_.empty()) {
205 cwd_.swap(dirstack_.back());
206 dirstack_.pop_back();
210 prefix_ void senf::console::Executor::exit()
212 throw ExitException();
215 prefix_ void senf::console::Executor::help(std::ostream & output,
216 ParseCommandInfo::TokensRange path)
218 GenericNode const & node (traverseNode(path));
219 output << prettyName(typeid(node)) << " at " << node.path() << "\n\n";
221 output << std::flush;
224 prefix_ senf::console::GenericNode &
225 senf::console::Executor::traverseNode(ParseCommandInfo::TokensRange const & path)
228 return *cwd_.back().lock();
231 traverseDirectory(boost::make_iterator_range(
233 boost::prior(path.end())),
235 DirectoryNode & base (*dir.back().lock());
236 std::string const & name (boost::prior(path.end())->value());
238 policy_( base, name );
239 return dir.back().lock()->get(name);
241 catch (UnknownNodeNameException &) {
242 throw InvalidPathException();
247 senf::console::Executor::traverseDirectory(ParseCommandInfo::TokensRange const & path,
251 ParseCommandInfo::TokensRange::const_iterator i (path.begin());
252 ParseCommandInfo::TokensRange::const_iterator const i_end (path.end());
253 for (; i != i_end; ++i) {
254 if (*i == NoneToken()) {
255 if (i == path.begin()) {
257 dir.push_back(root_);
260 else if (*i == WordToken("..")) {
264 else if (*i == WordToken("."))
267 DirectoryNode & base (*dir.back().lock());
269 policy_( base, i->value() );
270 dir.push_back(base[i->value()].thisptr());
274 catch (std::bad_cast &) {
275 throw InvalidDirectoryException();
277 catch (UnknownNodeNameException &) {
278 throw InvalidDirectoryException();
282 ///////////////////////////////cc.e////////////////////////////////////////
284 //#include "Executor.mpp"
290 // comment-column: 40
291 // c-file-style: "senf"
292 // indent-tabs-mode: nil
293 // ispell-local-dictionary: "american"
294 // compile-command: "scons -u test"