/* $Id: CommandLine.cxx 15565 2013-01-07 14:27:05Z sloot $ $URL: https://ilk.uvt.nl/svn/trunk/sources/Timbl6/src/CommandLine.cxx $ Copyright (c) 1998 - 2013 ILK - Tilburg University CLiPS - University of Antwerp This file is part of timbl timbl 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 3 of the License, or (at your option) any later version. timbl 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, see . For questions and suggestions, see: http://ilk.uvt.nl/software.html or send mail to: timbl@uvt.nl */ #include #include #include #include #include #include #include "timbl/CommandLine.h" using namespace std; namespace Timbl { CL_Options::CL_Options( const int argc, const char * const *argv ){ Split_Command_Line( argc, argv ); } CL_Options::CL_Options( const string& args ){ const char *argstr = args.c_str(); Split_Command_Line( 0, &argstr ); } CL_Options::~CL_Options(){ } ostream& operator<<( ostream& os, const CL_item& it ){ if ( it.longOpt ){ os << "--" << it.opt_word; if ( !it.option.empty() ) os << "=" << it.option; } else os << (it.mood ? "+": "-" ) << it.opt_word << it.option; return os; } ostream& operator<<( ostream& os, const CL_Options& cl ){ list::const_iterator pos = cl.Opts.begin(); while ( pos != cl.Opts.end() ){ os << *pos << " "; ++pos; } return os; } bool CL_Options::Present( const char c ) const { list::const_iterator pos; for ( pos = Opts.begin(); pos != Opts.end(); ++pos ){ if ( pos->OptChar() == c ){ return true; } } return false; } bool CL_Options::Find( const char c, string &opt, bool& mood ) const { list::const_iterator pos; for ( pos = Opts.begin(); pos != Opts.end(); ++pos ){ if ( pos->isLong() ) continue; if ( pos->OptChar() == c ){ opt = pos->Option(); mood = pos->Mood(); return true; } } return false; } bool CL_Options::Find( const string& w, string &opt ) const { list::const_iterator pos; for ( pos = Opts.begin(); pos != Opts.end(); ++pos ){ if ( pos->OptWord() == w ){ opt = pos->Option(); return true; } } return false; } bool CL_Options::Delete( const char c, bool all ){ list::iterator pos; for ( pos = Opts.begin(); pos != Opts.end(); ){ if ( pos->OptChar() == c ){ pos = Opts.erase(pos); if ( !all ) return true; } ++pos; } return false; } bool CL_Options::Delete( const string& w ){ list::iterator pos; for ( pos = Opts.begin(); pos != Opts.end(); ++pos ){ if ( pos->OptWord() == w ){ Opts.erase(pos); return true; } } return false; } void CL_Options::Add( const string& s, const string& line ){ CL_item cl( s, line ); Opts.push_front( cl ); } void CL_Options::Add( const char c, const string& line, bool mood ){ CL_item cl( c, line, mood ); Opts.push_front( cl ); } inline bool p_or_m( char k ) { return ( k == '+' || k == '-' ); } inline int opt_split( const char *line, vector& new_argv ){ int k=0; const char *p = line; int argc = 0; while ( *p ){ if ( ( p_or_m(*p) && argc == 0 ) || ( isspace(*p++) && p_or_m(*p) ) ){ argc++; } } string res; if ( argc != 0 ){ new_argv.reserve(argc); p = line; while ( isspace( *p ) ){ p++; }; while ( *p ){ int skip = 0; while ( isspace( *p ) ){ p++; skip++; }; if ( !*p ) break; if ( skip != 0 && p_or_m(*p) && k != 1 ){ new_argv.push_back( res ); k = 0; res = ""; } res += *p++; } new_argv.push_back( res ); } return argc; } void CL_Options::Split_Command_Line( const int Argc, const char * const *Argv ){ Opts.clear(); int local_argc = 0; vector local_argv; char Optchar; string Optword; string Option; bool Mood = false; if ( Argc == 0 ) if ( Argv != 0 && Argv[0] != 0 ){ local_argc = opt_split( Argv[0], local_argv ); } else return; else { local_argc = Argc-1; for( int i=1; i < Argc; ++i ){ // start at 1 to skip the program name local_argv.push_back( Argv[i] ); } } for ( int arg_ind=0; arg_ind < local_argc; ++arg_ind ){ bool longOpt = false; Option = local_argv[arg_ind]; if ( !p_or_m(Option[0]) ){ Optchar = '?'; Optword = Option; Mood = false; } else { Mood = Option[0] == '+'; if ( Option.size() > 1 ){ longOpt = Option[1] == '-'; if ( longOpt ){ if ( Mood ) throw std::runtime_error("invalid option: " + Option ); string::size_type pos = Option.find( "=" ); if ( pos == string::npos ){ Optword = Option.erase(0,2); Option = ""; } else { Optword = Option.substr( 2, pos-2 ); Option = Option.substr( pos+1 ); } Optchar = Optword[0]; } else { Optchar = Option[1]; Optword = Optchar; Option = Option.erase(0,2); } } else { Optchar = 0; Optword = Option; Option = Option.erase(0,1); } if ( (!Optchar || Option.empty() ) && arg_ind+1 < local_argc ) { string tmpOption = local_argv[arg_ind+1]; if ( !p_or_m(tmpOption[0]) ){ Option = tmpOption; ++arg_ind; if ( !Optchar ){ Optchar = Optword[0]; } } } } if ( longOpt ){ CL_item cl( Optword, Option ); Opts.push_front( cl ); } else { CL_item cl( Optchar, Option, Mood ); Opts.push_front( cl ); } } } }