/**************************************************************************** PROJECT: FlowerSoft C++ library FILE : loptions.cc --*/ #include "quote.h" #include "loptions.h" //#define TEST /**************************************************************************** class Long_option --*/ Long_option::Long_option( const char* long_name, const char short_name ) : Option( short_name ) { #if __STDC__ info.name = long_name; #else info.name = (char*)long_name; #endif info.has_arg = 0; info.flag = 0; info.val = 0; } Long_option::~Long_option() { } const char* Long_option::long_option() const { return info.name; } void Long_option::printOn( ostream& os ) const { os << info.name; } //-- class Long_option // /**************************************************************************** class Long_switch_option --*/ Long_switch_option::Long_switch_option( const char* name, const char short_name, const int s ) : Long_option( name, short_name ) { sw_tch = s; } Long_switch_option::~Long_switch_option() { } Long_switch_option::operator int() const { return sw_tch; } void Long_switch_option::printOn( ostream& os ) const { Long_option::printOn( os ); os << ( sw_tch ? "ON" : "OFF" ); } //-- class Long_switch_option // /**************************************************************************** class Long_string_option --*/ Long_string_option::Long_string_option( const char* name, const char short_name, const char* s ) : Long_option( name, short_name ) { info.has_arg = 1; string = s; } Long_string_option::~Long_string_option() { } Long_string_option::operator int() const { return ( string != 0 ); } const char* Long_string_option::long_option() const { return String( Long_option::long_option() ) + '='; } const char* Long_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* Long_string_option::argument() const { return string; } void Long_string_option::printOn( ostream& os ) const { Long_option::printOn( os ); os << string; } //-- class Long_string_option // /**************************************************************************** class Long_option_list --*/ Long_option_list::Long_option_list() : Option_list() { } Long_option_list::~Long_option_list() { } Long_switch_option null_long_switch( "", 0, 0 ); Long_option& Long_option_list::get( const char* name ) { Long_option& option = (Long_option&) firstOption( Long_option::compare_name, (void*)name ); // protect for type conversion of NOOBJECT return ( option != NOOBJECT ? option : (Long_option&)null_long_switch ); } void Long_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 += *new String( options++.short_option() ); } int option_index = 0; struct option* long_options = new struct option[ count() + 1 ]; options.reset(); // memberwise copy of info structs for ( int i = 0; i < count(); i++ ) //, long_option++ ) long_options[ i ] = ( (Long_option&)options++ ).info; // long_options[ i ] = { 0, 0, 0, 0 }; struct option nul_option = { 0, 0, 0, 0 }; long_options[ count() ] = nul_option; // while ( ( c = getopt_long( argc, argv, short_options, // extern int gnuMy_Getopt( int argc, char* const argv[], const char* shortopts ); while ( ( c = gnuGetoptLong( argc, argv, short_options, long_options, &option_index ) ) != EOF ) { switch( c ) { case 0 : // long_option { Long_option& long_option = get( long_options[ option_index ].name ); // if ( long_option == NOOBJECT ) if ( long_option == null_long_switch ) error( quoteString( "invalid option", long_options[ option_index ].name ), __FILE__, __LINE__ ); if ( optarg ) { if ( ( optarg[ 0 ] == '-' ) && optarg[ 1 ] ) error( quoteChar( "invalid option", c ), __FILE__, __LINE__ ); else ( (Long_string_option&)long_option ).string = optarg; } else ( (Long_switch_option&)long_option ).sw_tch = 1; break; } case '?' : case ':' : error( quoteString( "invalid option", argv[ optind - 1 ] ), __FILE__, __LINE__ ); break; default : { Option& option = Option_list::get( c ); // if ( option == NOOBJECT ) if ( option == null_switch ) error( "invalid option", __FILE__, __LINE__ ); if ( optarg ) { if ( ( optarg[ 0 ] == '-' ) && optarg[ 1 ] ) error( quoteString( "invalid argument", argv[ optind - 1 ] ), __FILE__, __LINE__ ); else ( (Long_string_option&)option ).string = optarg; } else ( (Long_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 Long_option_list::put( Option& ) { error( "need long option", __FILE__, __LINE__ ); return 1; } int Long_option_list::put( Long_option& long_option ) { return Option_list::put( long_option ); } //-- class Long_option_list // #ifdef TEST int main( const int argc, char* const argv[] ) { Long_option_list option_list; option_list.put( *new Long_switch_option( "help", 'h' ) ); option_list.put( *new Long_switch_option( "verbose", 'v' ) ); option_list.put( *new Long_string_option( "outfile", 'o' ) ); option_list.parse( argc, argv ); if ( option_list.get( "help" ) ) error( "print help", 0, 0 ); if ( option_list.get( "verbose" ) ) cout << "verbose mode" << endl; if ( option_list.get( "outfile" ) ) { Long_option& out_name = option_list.get( "outfile" ); cout << "output file name: " << out_name.argument() << endl; } if ( option_list ) { cout << "list of files:" << endl; while( option_list ) cout << option_list++ << endl; } return 0; } #endif // TEST //