/**************************************************************************** PROJECT: FlowerSoft C++ library FILE : options.cc --*/ #include "quote.h" #include "options.h" #include "getoptin.h" /**************************************************************************** class Option --*/ Option::Option( const char c ) : name( c ) { } Option::~Option() { } //Option::operator const char*() const const char* Option::short_option() const { // return &name; static char s[ 2 ]; s[ 0 ] = name; s[ 1 ] = 0; return s; } const char* Option::argument() const { error( "member `argument\' called for non-argument option", __FILE__, __LINE__); return 0; } void Option::printOn( ostream& os ) const { os << name; } //-- class Option // /**************************************************************************** class Switch_option --*/ Switch_option::Switch_option( const char name, const int s ) : Option( name ) { sw_tch = s; } Switch_option::~Switch_option() { } Switch_option::operator int() const { return sw_tch; } void Switch_option::printOn( ostream& os ) const { os << (Option&)*this; os << ( sw_tch ? "ON" : "OFF" ); } //-- class Switch_option // /**************************************************************************** class String_option --*/ String_option::String_option( const char name, const char* s ) : Option( name ) { string = s; } String_option::~String_option() { } String_option::operator int() const { return ( string != 0 ); } const char* String_option::short_option() const { #if 0 return String( Option::short_option() ) + ':'; #else static char s[ 3 ]; s[ 0 ] = *Option::short_option(); s[ 1 ] = ':'; s[ 2 ] = 0; return s; #endif } const char* String_option::argument() const { return string; } void String_option::printOn( ostream& os ) const { Option::printOn( os ); os << string; } //-- class String_option // /**************************************************************************** class Option_list --*/ Option_list::Option_list() : GENERIC( Option, List )(), non_option_list(), non_option_list_iterator( non_option_list ) { } Option_list::~Option_list() { } Option_list::operator int() const { return non_option_list_iterator; } const char* Option_list::operator ()() { return non_option_list_iterator(); } const char* Option_list::operator ++( POSTFIX_INT ) { return non_option_list_iterator++; } Switch_option null_switch( 0, 0 ); Option& Option_list::get( const char name ) { Option& option = firstOption( Option::compare_name, (void*)&name ); // protect for type conversion of NOOBJECT return ( option != NOOBJECT ? option : (Option&)null_switch ); } void Option_list::parse( const int argc, char* const argv[] ) { opterr = 0; // don't print error message int c; String short_options; GENERIC( Option, ListIterator ) options( *this ); while ( options ) short_options += String( options++.short_option() ); // while ( ( c = getopt( argc, argv, short_options ) ) != EOF ) while ( ( c = gnuGetopt( argc, argv, short_options ) ) != EOF ) switch( c ) { case '?' : case ':' : error( quoteChar( "invalid option", c ), __FILE__, __LINE__ ); break; default : Option& option = get( c ); // if ( option == NOOBJECT ) if ( option == null_switch ) error( quoteChar( "invalid option", c ), __FILE__, __LINE__ ); if ( optarg ) { if ( ( optarg[ 0 ] == '-' ) && optarg[ 1 ] ) error( quoteString( "invalid argument", argv[ optind - 1 ] ), __FILE__, __LINE__ ); else ( (String_option&)option ).string = optarg; } else ( (Switch_option&)option ).sw_tch = 1; } while ( optind < argc ) { if ( ( argv[ optind ][ 0 ] == '-' ) && argv[ optind ][ 1 ] ) error( quoteString( "invalid file name", argv[ optind ] ), __FILE__, __LINE__ ); non_option_list.put( *new String( argv[ optind++ ] ) ); } non_option_list_iterator.reset(); } int Option_list::put( Option& option ) { if ( *option.short_option() // && ( get( *option.short_option() ) != NOOBJECT ) ) && ( get( *option.short_option() ) != null_switch ) ) error( quoteString( "option defined before", option.short_option() ), __FILE__, __LINE__ ); return GENERIC( Option, List )::put( option ); } //-- class Option_list // #ifdef TEST int main( const int argc, char* const argv[] ) { Option_list option_list; option_list.put( *new Switch_option( 'h' ) ); option_list.put( *new Switch_option( 'v' ) ); option_list.put( *new String_option( 'o' ) ); option_list.parse( argc, argv ); if ( (int)option_list.get( 'h' ) ) error( "print help", 0, 0 ); if ( (int)option_list.get( 'v' ) ) cout << "verbose mode" << endl; if ( option_list.get( 'o' ) ) { Option& out_name = option_list.get( 'o' ); cout << "output file name: " << out_name.argument() << endl; } #if 0 if ( !option_list.non_option_list.empty() ) { cout << "list of files:" << endl; GENERIC( String, ListIterator ) files( option_list.non_option_list ); while ( files ) cout << files++ << endl; } #else if ( option_list ) { cout << "list of files:" << endl; while( option_list ) cout << option_list++ << endl; } #endif return 0; } #endif // TEST //