//$Id: IVIOAppl.cpp,v 1.39 2004/11/04 16:31:19 markus Rel $ //PROJECT : libYGP //SUBSYSTEM : IVIOApplication //REFERENCES : //TODO : //BUGS : //REVISION : $Revision: 1.39 $ //AUTHOR : Markus Schwab //CREATED : 21.6.1999 //COPYRIGHT : Copyright (C) 1999 - 2004 // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // This program 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 Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include #include #include #include #include "YGP/Check.h" #include "YGP/File.h" #include "YGP/PathSrch.h" #include "YGP/Internal.h" #include "YGP/StackTrc.h" #include "YGP/IVIOAppl.h" namespace YGP { //----------------------------------------------------------------------------- /// Checks char if it starts an option /// \param ch: Character to check /// \returns \c bool: Result (true: char starts option) //----------------------------------------------------------------------------- static inline bool isOptionChar (const char ch) { #if SYSTEM == UNIX return ch == '-'; #else return (ch == '-') || (ch == '/'); #endif } //----------------------------------------------------------------------------- /// Constructor; the parameters specify the number of and an array with the /// program-arguments (as passed to the main-function) and a table to map the /// verbose long-options to their short equivalent. If the third parameter is /// NULL, no long options are used. /// \param argc: Number of arguments /// \param argv: Array of pointers to argumetns /// \param pOpt: Pointer to long-option-table //----------------------------------------------------------------------------- IVIOApplication::IVIOApplication (const int argc, const char* argv[], const longOptions* pOpt) : args (argc), ppArgs (argv), startArg (1), startOpt (1), pOptionParam (NULL) , longOpt (NULL), numLongOpt (0) { Check1 (args > 0); Check1 (ppArgs); signal (SIGSEGV, handleSignal); #ifdef HAVE_SIGBUS signal (SIGBUS, handleSignal); #endif if (pOpt) setLongOptions (pOpt); // Store the long-option-array (if passed) } //----------------------------------------------------------------------------- /// Destructor //----------------------------------------------------------------------------- IVIOApplication::~IVIOApplication () { signal (SIGSEGV, SIG_DFL); #ifdef HAVE_SIGBUS signal (SIGBUS, SIG_DFL); #endif } //----------------------------------------------------------------------------- /// Sets a table which maps options to a verbose version. This table must be /// terminated with an entry where the short option is '\\0' and the associated /// long options is NULL; the previous entries must not have lines with those /// values. /// \param pLongOpts: Pointer to an array of longOptions; terminated with a /// longOption with NULL as longVal /// \pre /// - \c pLongOpts not NULL /// - all long-entries not NULL /// - all short-entries not '\\0' /// - An entry with an { NULL, '\\0' } at the end //----------------------------------------------------------------------------- void IVIOApplication::setLongOptions (const longOptions* pLongOpts) { Check1 (pLongOpts); Check1 (pLongOpts->longVal); // At least one valid entry must exist longOpt = pLongOpts; while (pLongOpts->longVal != NULL) { Check3 (pLongOpts->shortVal != '\0'); ++numLongOpt; pLongOpts++; } // end-while Check3 (pLongOpts->shortVal == '\0'); // Last entry mustn't have a shortval } //----------------------------------------------------------------------------- /// Sets a table which maps options to a verbose version. This table must not /// contain entries with either '\\0' as short option or NULL as long option. /// \param pLongOpts: Pointer to an array of longOptions /// \param numLongOpts: Number of elements in the array /// \pre /// - \c pLongOpts not NULL /// - all long-entries not NULL /// - all short-entries not '\\0' //----------------------------------------------------------------------------- void IVIOApplication::setLongOptions (const longOptions* pLongOpts, unsigned int numLongOpts) { Check1 (numLongOpts); Check1 (pLongOpts); Check1 (pLongOpts->longVal); // At least one valid entry must exist numLongOpt = numLongOpts; longOpt = pLongOpts; #if Check > 2 while (numLongOpts--) { Check (pLongOpts->shortVal != '\0'); Check (pLongOpts++->longVal); } // end-while #endif } //----------------------------------------------------------------------------- /// Runs the application; first the method readINIFile() is called to read the /// data from an INI file. Then the options are checked. If an invalid or a /// help-option is passed, the help-screen is displayed, else the actual job /// of the application is performed. /// \returns \c int: Status //----------------------------------------------------------------------------- int IVIOApplication::run () { try { std::string inifile (PathSearch::expandNode (std::string (1, '~'))); Check1 (inifile.size ()); if (inifile[inifile.size () - 1] != File::DIRSEPARATOR) inifile += File::DIRSEPARATOR; #if SYSTEM == UNIX inifile += '.'; #endif inifile += name (); #if SYSTEM != UNIX inifile += ".ini"; #endif readINIFile (inifile.c_str ()); char ch; bool showHlp (false); while ((ch = getOption ()) != '\0') if ((ch == '?') || (ch == 'h') || !handleOption (ch)) { showHlp = true; break; } if (shallShowInfo ()) std::cout << name () << " V" << description () << "\n\n"; if (showHlp) { showHelp (); return -1; } return perform (args - startArg, &ppArgs[startArg]); } catch (std::exception& e) { std::cerr << name () << _("-warning: Unhandled exception (std::exception): ") << e.what (); } catch (std::string& e) { std::cerr << name () << _("-warning: Unhandled exception (std::string): ") << e; } catch (...) { std::cerr << name () << _("-warning: Unhandled exception!"); } return -2; } //----------------------------------------------------------------------------- /// Returns the value to the current option and increases the pointer the /// next option. These parameter are searched using the following algorithm: /// - The remaining characters in a list of simple options (e.g. if called /// for the option d in "-dlevel1" the method would return "level1") or /// the value behind the equal sign (=) if given in a long option. /// - The next argument of the application. /// - NULL /// \returns \c char*: Parameter for the option //----------------------------------------------------------------------------- const char* IVIOApplication::getOptionValue () { if (startOpt > startArg) moveOption (); const char* pHelp; if (pOptionParam && *pOptionParam) pHelp = pOptionParam; else { ++startArg; if (++startOpt == args) return NULL; pHelp = ppArgs[startOpt]; moveOption (); } ++startArg; ++startOpt; pOptionParam = NULL; return pHelp; } //----------------------------------------------------------------------------- /// Reads the options. It handles options in the form: /// -