From ac65c06e22a6a99007703bdc79efe8a45c30e0f0 Mon Sep 17 00:00:00 2001 From: Thomas Moulard <thomas.moulard@gmail.com> Date: Fri, 31 Dec 2010 20:25:48 +0100 Subject: [PATCH] Enhance dg-shell. --- src/dgraph/import.cpp | 6 +- tools/dg-shell.cpp | 246 +++++++++++++++++++++++++----------------- 2 files changed, 152 insertions(+), 100 deletions(-) diff --git a/src/dgraph/import.cpp b/src/dgraph/import.cpp index 24421db..f895abe 100644 --- a/src/dgraph/import.cpp +++ b/src/dgraph/import.cpp @@ -141,13 +141,11 @@ namespace dynamicgraph pathPlugin.replace_extension (SHARED_LIBRARY_EXT); if (boost::filesystem::exists (pathPlugin) - && (boost::filesystem::is_regular_file (pathPlugin) - || boost::filesystem::is_symlink (pathPlugin))) + && !boost::filesystem::is_directory (pathPlugin)) return pathPlugin; if (boost::filesystem::exists (path) - && (boost::filesystem::is_regular_file (path) - || boost::filesystem::is_symlink (path))) + && !boost::filesystem::is_directory (path)) return path; } diff --git a/tools/dg-shell.cpp b/tools/dg-shell.cpp index 07907a5..d93fe0d 100644 --- a/tools/dg-shell.cpp +++ b/tools/dg-shell.cpp @@ -1,126 +1,180 @@ -/* - * Copyright 2010, - * François Bleibel, - * Olivier Stasse, - * - * CNRS/AIST - * - * This file is part of dynamic-graph. - * dynamic-graph is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * dynamic-graph is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. You should - * have received a copy of the GNU Lesser General Public License along - * with dynamic-graph. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * Copyright 2010, - * François Bleibel, - * Olivier Stasse, - * - * CNRS/AIST - * - * This file is part of dynamic-graph. - * dynamic-graph is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * dynamic-graph is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. You should - * have received a copy of the GNU Lesser General Public License along - * with dynamic-graph. If not, see <http://www.gnu.org/licenses/>. - */ - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * Copyright Projet JRL-JAPAN, Tsukuba, 2007 - *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * - * File: test_shell.cc - * Project: DYNAMIC-GRAPH - * Author: Nicolas Mansard - * - * Version control - * =============== - * - * $Id$ - * - * Description - * ============ - * - * - * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ - -/* -------------------------------------------------------------------------- */ -/* --- INCLUDES ------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ +// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse, +// JRL, CNRS/AIST. +// +// This file is part of dynamic-graph. +// dynamic-graph is free software: you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// dynamic-graph is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Lesser Public License for more details. You should have +// received a copy of the GNU Lesser General Public License along with +// dynamic-graph. If not, see <http://www.gnu.org/licenses/>. + +#include <sstream> +#include <string> +#include <vector> + +#include <boost/filesystem.hpp> +#include <boost/foreach.hpp> +#include <boost/format.hpp> +#include <boost/program_options.hpp> #include <dynamic-graph/entity.h> #include <dynamic-graph/plugin-loader.h> #include <dynamic-graph/interpreter.h> #include <dynamic-graph/debug.h> -#include <sstream> -using namespace std; -using namespace dynamicgraph; - - extern std::ofstream debugfile; -int main( int argc,char** argv ) +// Factorize exception catching code. +#define CATCH_EXCEPTIONS() \ + catch (std::exception& e) \ + { \ + std::cout \ + << errorPrefix \ + << e.what () << std::endl; \ + if (options.noninteractive) \ + return 1; \ + } \ + catch (const char* str) \ + { \ + std::cout << errorPrefix \ + << "Unknown exception " << str << std::endl; \ + if (options.noninteractive) \ + return 1; \ + } \ + catch (...) \ + { \ + dgDEBUG(5) << errorPrefix << " Unknown exception " << std::endl; \ + if (options.noninteractive) \ + return 1; \ + } \ + struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n + +struct Options { - dgDEBUGIN(15); + /// \brief Should we provide a shell to the user or end the program + /// directly? + bool noninteractive; + /// \brief Prologue path (a prologue is a script implicitly + /// evaluated at start-up). + std::string prologue; + /// \brief Files to be evaluated at start-up (left to right order). + std::vector<std::string> inputs; +}; + +std::string defaultPrologue () +{ + char* home = getenv ("HOME"); + boost::filesystem::path path (home); + path/= ".dg-shellrc"; + return path.file_string (); +} - dgDEBUG(5) << " Loading..." << endl; - PluginLoader pl; - g_shell.referencePluginLoader( &pl ); +int main (int argc, char** argv) +{ + dgDEBUGIN(15); - int fileIdx; + dgDEBUG(5) << " Loading..." << std::endl; + dynamicgraph::PluginLoader pl; + dynamicgraph::g_shell.referencePluginLoader (&pl); + + Options options; + + // Parse options. + namespace po = boost::program_options; + po::options_description desc ("Allowed options"); + desc.add_options () + ("input,i", + po::value<std::vector<std::string> >(&options.inputs), + "file(s) evaluated at start-up") + ("noninteractive,n", + "enable non-interactive behavior") + ("prologue,p", + po::value<std::string>(&options.prologue)->default_value (defaultPrologue ()), + "override default prologue") + ("help,h", "produce help message") + ; + + po::variables_map vm; try { - for( fileIdx=1;fileIdx<argc;++fileIdx ) + po::store (po::parse_command_line (argc, argv, desc), vm); + po::notify (vm); + + if (vm.count ("help")) { - std::istringstream script( argv[fileIdx] ); - cout << "Run "<< argv[fileIdx] << endl; - g_shell.cmd( "run",script,cout ); + std::cout << "Usage: " << argv[0] << " [options]" << std::endl + << desc << std::endl + << "Report bugs to <hpp@laas.fr>" << std::endl; + return 1; } + options.noninteractive = vm.count ("noninteractive"); + } + catch (po::error& error) + { + std::cerr << "Error while parsing argument: " + << error.what () << std::endl; + return 1; } - catch( exception& e ) + + std::list<std::string> inputs (options.inputs.begin (), + options.inputs.end ()); + + // First, evaluate the prologue. + boost::filesystem::path prologuePath (options.prologue); + if (!prologuePath.empty ()) { - cout << "!! In file <" << argv[fileIdx] << "> : " << e.what() <<endl; + if (boost::filesystem::exists (prologuePath) + && !boost::filesystem::is_directory (prologuePath)) + inputs.push_front (prologuePath.file_string ()); + else + { + boost::format fmt ("Failed to load prologue: \"%s\"."); + fmt % prologuePath.file_string (); + std::cerr << fmt.str () << std::endl; + } } - catch ( const char* str ) { - cout << "!! In file <" << argv[fileIdx] << "> : " - << "Unknown exception " << str << endl; - } - catch( ... ){ dgDEBUG(5) << "!! Unknown! " <<endl ; } - while(1) + // Load all input files. + BOOST_FOREACH (const std::string& pathStr, inputs) { + boost::filesystem::path path (pathStr); + + std::stringstream ss; + ss << "!! In file <" << path.file_string () << "> : "; + std::string errorPrefix = ss.str (); + try { - dgDEBUG(5) << "Run shell." << endl; - g_shell.shell(cin,cout); - dgDEBUG(5) << "Shell over." << endl; - if( cin.eof() ) break; + std::istringstream script (path.file_string ()); + std::cout << "Run " << path.file_string () << std::endl; + dynamicgraph::g_shell.cmd ("run", script, std::cout); } - catch( exception& e ) + CATCH_EXCEPTIONS (); + } + + // Interactive loop. + if (options.noninteractive) + return 0; + std::string errorPrefix = ""; + while (1) + { + try { - cout << "!! " << e.what() <<endl; + dgDEBUG(5) << "Run shell." << std::endl; + dynamicgraph::g_shell.shell (std::cin, std::cout); + dgDEBUG(5) << "Shell over." << std::endl; + if (std::cin.eof ()) + break; } - catch( ... ){ dgDEBUG(5) << "!! Unknown! " <<endl ; } + CATCH_EXCEPTIONS (); } dgDEBUGOUT(15); return 0; } - - - - -- GitLab