diff options
author | Andrew <forkk@forkk.net> | 2013-12-09 12:04:05 -0600 |
---|---|---|
committer | Andrew <forkk@forkk.net> | 2013-12-09 12:04:05 -0600 |
commit | 7f52bed9e3f559adcbcf3f3c1c7ac2251964db8c (patch) | |
tree | 52097b57dc7d18ec4e35ef3a8e554af2d91545e8 /mmc_updater/depends/AnyOption/anyoption.cpp | |
parent | 9410dd042ea62224fa3e0eb3b525abbdf0c316ee (diff) | |
parent | 220e07aef4a34dca9f31ae0c5bb994e5c594125d (diff) | |
download | MultiMC-7f52bed9e3f559adcbcf3f3c1c7ac2251964db8c.tar MultiMC-7f52bed9e3f559adcbcf3f3c1c7ac2251964db8c.tar.gz MultiMC-7f52bed9e3f559adcbcf3f3c1c7ac2251964db8c.tar.lz MultiMC-7f52bed9e3f559adcbcf3f3c1c7ac2251964db8c.tar.xz MultiMC-7f52bed9e3f559adcbcf3f3c1c7ac2251964db8c.zip |
Merge branch 'feature_updater' into develop
Diffstat (limited to 'mmc_updater/depends/AnyOption/anyoption.cpp')
-rw-r--r-- | mmc_updater/depends/AnyOption/anyoption.cpp | 1176 |
1 files changed, 1176 insertions, 0 deletions
diff --git a/mmc_updater/depends/AnyOption/anyoption.cpp b/mmc_updater/depends/AnyOption/anyoption.cpp new file mode 100644 index 00000000..6792fe3e --- /dev/null +++ b/mmc_updater/depends/AnyOption/anyoption.cpp @@ -0,0 +1,1176 @@ +/* + * AnyOption 1.3 + * + * kishan at hackorama dot com www.hackorama.com JULY 2001 + * + * + Acts as a common facade class for reading + * commandline options as well as options from + * an optionfile with delimited type value pairs + * + * + Handles the POSIX style single character options ( -w ) + * as well as the newer GNU long options ( --width ) + * + * + The option file assumes the traditional format of + * first character based comment lines and type value + * pairs with a delimiter , and flags which are not pairs + * + * # this is a coment + * # next line is an option value pair + * width : 100 + * # next line is a flag + * noimages + * + * + Supports printing out Help and Usage + * + * + Why not just use getopt() ? + * + * getopt() Its a POSIX standard not part of ANSI-C. + * So it may not be available on platforms like Windows. + * + * + Why it is so long ? + * + * The actual code which does command line parsing + * and option file parsing are done in few methods. + * Most of the extra code are for providing a flexible + * common public interface to both a resourcefile and + * and command line supporting POSIX style and + * GNU long option as well as mixing of both. + * + * + Please see "anyoption.h" for public method descriptions + * + */ + +/* Updated Auguest 2004 + * Fix from Michael D Peters (mpeters at sandia.gov) + * to remove static local variables, allowing multiple instantiations + * of the reader (for using multiple configuration files). There is + * an error in the destructor when using multiple instances, so you + * cannot delete your objects (it will crash), but not calling the + * destructor only introduces a small memory leak, so I + * have not bothered tracking it down. + * + * Also updated to use modern C++ style headers, rather than + * depricated iostream.h (it was causing my compiler problems) +*/ + +/* + * Updated September 2006 + * Fix from Boyan Asenov for a bug in mixing up option indexes + * leading to exception when mixing different options types + */ + +#include "anyoption.h" + +#include <string.h> + +AnyOption::AnyOption() +{ + init(); +} + +AnyOption::AnyOption(int maxopt) +{ + init( maxopt , maxopt ); +} + +AnyOption::AnyOption(int maxopt, int maxcharopt) +{ + init( maxopt , maxcharopt ); +} + +AnyOption::~AnyOption() +{ + if( mem_allocated ) + cleanup(); +} + +void +AnyOption::init() +{ + init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS ); +} + +void +AnyOption::init(int maxopt, int maxcharopt ) +{ + + max_options = maxopt; + max_char_options = maxcharopt; + max_usage_lines = DEFAULT_MAXUSAGE; + usage_lines = 0 ; + argc = 0; + argv = NULL; + posix_style = true; + verbose = false; + filename = NULL; + appname = NULL; + option_counter = 0; + optchar_counter = 0; + new_argv = NULL; + new_argc = 0 ; + max_legal_args = 0 ; + command_set = false; + file_set = false; + values = NULL; + g_value_counter = 0; + mem_allocated = false; + command_set = false; + file_set = false; + opt_prefix_char = '-'; + file_delimiter_char = ':'; + file_comment_char = '#'; + equalsign = '='; + comment = '#' ; + delimiter = ':' ; + endofline = '\n'; + whitespace = ' ' ; + nullterminate = '\0'; + set = false; + once = true; + hasoptions = false; + autousage = false; + + strcpy( long_opt_prefix , "--" ); + + if( alloc() == false ){ + cout << endl << "OPTIONS ERROR : Failed allocating memory" ; + cout << endl ; + cout << "Exiting." << endl ; + exit (0); + } +} + +bool +AnyOption::alloc() +{ + int i = 0 ; + int size = 0 ; + + if( mem_allocated ) + return true; + + size = (max_options+1) * sizeof(const char*); + options = (const char**)malloc( size ); + optiontype = (int*) malloc( (max_options+1)*sizeof(int) ); + optionindex = (int*) malloc( (max_options+1)*sizeof(int) ); + if( options == NULL || optiontype == NULL || optionindex == NULL ) + return false; + else + mem_allocated = true; + for( i = 0 ; i < max_options ; i++ ){ + options[i] = NULL; + optiontype[i] = 0 ; + optionindex[i] = -1 ; + } + optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) ); + optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) ); + optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) ); + if( optionchars == NULL || + optchartype == NULL || + optcharindex == NULL ) + { + mem_allocated = false; + return false; + } + for( i = 0 ; i < max_char_options ; i++ ){ + optionchars[i] = '0'; + optchartype[i] = 0 ; + optcharindex[i] = -1 ; + } + + size = (max_usage_lines+1) * sizeof(const char*) ; + usage = (const char**) malloc( size ); + + if( usage == NULL ){ + mem_allocated = false; + return false; + } + for( i = 0 ; i < max_usage_lines ; i++ ) + usage[i] = NULL; + + return true; +} + +bool +AnyOption::doubleOptStorage() +{ + options = (const char**)realloc( options, + ((2*max_options)+1) * sizeof( const char*) ); + optiontype = (int*) realloc( optiontype , + ((2 * max_options)+1)* sizeof(int) ); + optionindex = (int*) realloc( optionindex, + ((2 * max_options)+1) * sizeof(int) ); + if( options == NULL || optiontype == NULL || optionindex == NULL ) + return false; + /* init new storage */ + for( int i = max_options ; i < 2*max_options ; i++ ){ + options[i] = NULL; + optiontype[i] = 0 ; + optionindex[i] = -1 ; + } + max_options = 2 * max_options ; + return true; +} + +bool +AnyOption::doubleCharStorage() +{ + optionchars = (char*) realloc( optionchars, + ((2*max_char_options)+1)*sizeof(char) ); + optchartype = (int*) realloc( optchartype, + ((2*max_char_options)+1)*sizeof(int) ); + optcharindex = (int*) realloc( optcharindex, + ((2*max_char_options)+1)*sizeof(int) ); + if( optionchars == NULL || + optchartype == NULL || + optcharindex == NULL ) + return false; + /* init new storage */ + for( int i = max_char_options ; i < 2*max_char_options ; i++ ){ + optionchars[i] = '0'; + optchartype[i] = 0 ; + optcharindex[i] = -1 ; + } + max_char_options = 2 * max_char_options; + return true; +} + +bool +AnyOption::doubleUsageStorage() +{ + usage = (const char**)realloc( usage, + ((2*max_usage_lines)+1) * sizeof( const char*) ); + if ( usage == NULL ) + return false; + for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ ) + usage[i] = NULL; + max_usage_lines = 2 * max_usage_lines ; + return true; + +} + + +void +AnyOption::cleanup() +{ + free (options); + free (optiontype); + free (optionindex); + free (optionchars); + free (optchartype); + free (optcharindex); + free (usage); + if( values != NULL ) + free (values); + if( new_argv != NULL ) + free (new_argv); +} + +void +AnyOption::setCommandPrefixChar( char _prefix ) +{ + opt_prefix_char = _prefix; +} + +void +AnyOption::setCommandLongPrefix( char *_prefix ) +{ + if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){ + *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0'; + } + + strcpy (long_opt_prefix, _prefix); +} + +void +AnyOption::setFileCommentChar( char _comment ) +{ + file_delimiter_char = _comment; +} + + +void +AnyOption::setFileDelimiterChar( char _delimiter ) +{ + file_comment_char = _delimiter ; +} + +bool +AnyOption::CommandSet() +{ + return( command_set ); +} + +bool +AnyOption::FileSet() +{ + return( file_set ); +} + +void +AnyOption::noPOSIX() +{ + posix_style = false; +} + +bool +AnyOption::POSIX() +{ + return posix_style; +} + + +void +AnyOption::setVerbose() +{ + verbose = true ; +} + +void +AnyOption::printVerbose() +{ + if( verbose ) + cout << endl ; +} +void +AnyOption::printVerbose( const char *msg ) +{ + if( verbose ) + cout << msg ; +} + +void +AnyOption::printVerbose( char *msg ) +{ + if( verbose ) + cout << msg ; +} + +void +AnyOption::printVerbose( char ch ) +{ + if( verbose ) + cout << ch ; +} + +bool +AnyOption::hasOptions() +{ + return hasoptions; +} + +void +AnyOption::autoUsagePrint(bool _autousage) +{ + autousage = _autousage; +} + +void +AnyOption::useCommandArgs( int _argc, char **_argv ) +{ + argc = _argc; + argv = _argv; + command_set = true; + appname = argv[0]; + if(argc > 1) hasoptions = true; +} + +void +AnyOption::useFiileName( const char *_filename ) +{ + filename = _filename; + file_set = true; +} + +/* + * set methods for options + */ + +void +AnyOption::setCommandOption( const char *opt ) +{ + addOption( opt , COMMAND_OPT ); + g_value_counter++; +} + +void +AnyOption::setCommandOption( char opt ) +{ + addOption( opt , COMMAND_OPT ); + g_value_counter++; +} + +void +AnyOption::setCommandOption( const char *opt , char optchar ) +{ + addOption( opt , COMMAND_OPT ); + addOption( optchar , COMMAND_OPT ); + g_value_counter++; +} + +void +AnyOption::setCommandFlag( const char *opt ) +{ + addOption( opt , COMMAND_FLAG ); + g_value_counter++; +} + +void +AnyOption::setCommandFlag( char opt ) +{ + addOption( opt , COMMAND_FLAG ); + g_value_counter++; +} + +void +AnyOption::setCommandFlag( const char *opt , char optchar ) +{ + addOption( opt , COMMAND_FLAG ); + addOption( optchar , COMMAND_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFileOption( const char *opt ) +{ + addOption( opt , FILE_OPT ); + g_value_counter++; +} + +void +AnyOption::setFileOption( char opt ) +{ + addOption( opt , FILE_OPT ); + g_value_counter++; +} + +void +AnyOption::setFileOption( const char *opt , char optchar ) +{ + addOption( opt , FILE_OPT ); + addOption( optchar, FILE_OPT ); + g_value_counter++; +} + +void +AnyOption::setFileFlag( const char *opt ) +{ + addOption( opt , FILE_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFileFlag( char opt ) +{ + addOption( opt , FILE_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFileFlag( const char *opt , char optchar ) +{ + addOption( opt , FILE_FLAG ); + addOption( optchar , FILE_FLAG ); + g_value_counter++; +} + +void +AnyOption::setOption( const char *opt ) +{ + addOption( opt , COMMON_OPT ); + g_value_counter++; +} + +void +AnyOption::setOption( char opt ) +{ + addOption( opt , COMMON_OPT ); + g_value_counter++; +} + +void +AnyOption::setOption( const char *opt , char optchar ) +{ + addOption( opt , COMMON_OPT ); + addOption( optchar , COMMON_OPT ); + g_value_counter++; +} + +void +AnyOption::setFlag( const char *opt ) +{ + addOption( opt , COMMON_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFlag( const char opt ) +{ + addOption( opt , COMMON_FLAG ); + g_value_counter++; +} + +void +AnyOption::setFlag( const char *opt , char optchar ) +{ + addOption( opt , COMMON_FLAG ); + addOption( optchar , COMMON_FLAG ); + g_value_counter++; +} + +void +AnyOption::addOption( const char *opt, int type ) +{ + if( option_counter >= max_options ){ + if( doubleOptStorage() == false ){ + addOptionError( opt ); + return; + } + } + options[ option_counter ] = opt ; + optiontype[ option_counter ] = type ; + optionindex[ option_counter ] = g_value_counter; + option_counter++; +} + +void +AnyOption::addOption( char opt, int type ) +{ + if( !POSIX() ){ + printVerbose("Ignoring the option character \""); + printVerbose( opt ); + printVerbose( "\" ( POSIX options are turned off )" ); + printVerbose(); + return; + } + + + if( optchar_counter >= max_char_options ){ + if( doubleCharStorage() == false ){ + addOptionError( opt ); + return; + } + } + optionchars[ optchar_counter ] = opt ; + optchartype[ optchar_counter ] = type ; + optcharindex[ optchar_counter ] = g_value_counter; + optchar_counter++; +} + +void +AnyOption::addOptionError( const char *opt ) +{ + cout << endl ; + cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; + cout << "While adding the option : \""<< opt << "\"" << endl; + cout << "Exiting." << endl ; + cout << endl ; + exit(0); +} + +void +AnyOption::addOptionError( char opt ) +{ + cout << endl ; + cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; + cout << "While adding the option: \""<< opt << "\"" << endl; + cout << "Exiting." << endl ; + cout << endl ; + exit(0); +} + +void +AnyOption::processOptions() +{ + if( ! valueStoreOK() ) + return; +} + +void +AnyOption::processCommandArgs(int max_args) +{ + max_legal_args = max_args; + processCommandArgs(); +} + +void +AnyOption::processCommandArgs( int _argc, char **_argv, int max_args ) +{ + max_legal_args = max_args; + processCommandArgs( _argc, _argv ); +} + +void +AnyOption::processCommandArgs( int _argc, char **_argv ) +{ + useCommandArgs( _argc, _argv ); + processCommandArgs(); +} + +void +AnyOption::processCommandArgs() +{ + if( ! ( valueStoreOK() && CommandSet() ) ) + return; + + if( max_legal_args == 0 ) + max_legal_args = argc; + new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) ); + for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */ + if( argv[i][0] == long_opt_prefix[0] && + argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */ + int match_at = parseGNU( argv[i]+2 ); /* skip -- */ + if( match_at >= 0 && i < argc-1 ) /* found match */ + setValue( options[match_at] , argv[++i] ); + }else if( argv[i][0] == opt_prefix_char ) { /* POSIX char */ + if( POSIX() ){ + char ch = parsePOSIX( argv[i]+1 );/* skip - */ + if( ch != '0' && i < argc-1 ) /* matching char */ + setValue( ch , argv[++i] ); + } else { /* treat it as GNU option with a - */ + int match_at = parseGNU( argv[i]+1 ); /* skip - */ + if( match_at >= 0 && i < argc-1 ) /* found match */ + setValue( options[match_at] , argv[++i] ); + } + }else { /* not option but an argument keep index */ + if( new_argc < max_legal_args ){ + new_argv[ new_argc ] = i ; + new_argc++; + }else{ /* ignore extra arguments */ + printVerbose( "Ignoring extra argument: " ); + printVerbose( argv[i] ); + printVerbose( ); + printAutoUsage(); + } + printVerbose( "Unknown command argument option : " ); + printVerbose( argv[i] ); + printVerbose( ); + printAutoUsage(); + } + } +} + +char +AnyOption::parsePOSIX( char* arg ) +{ + + for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ + char ch = arg[i] ; + if( matchChar(ch) ) { /* keep matching flags till an option */ + /*if last char argv[++i] is the value */ + if( i == strlen(arg)-1 ){ + return ch; + }else{/* else the rest of arg is the value */ + i++; /* skip any '=' and ' ' */ + while( arg[i] == whitespace + || arg[i] == equalsign ) + i++; + setValue( ch , arg+i ); + return '0'; + } + } + } + printVerbose( "Unknown command argument option : " ); + printVerbose( arg ); + printVerbose( ); + printAutoUsage(); + return '0'; +} + +int +AnyOption::parseGNU( char *arg ) +{ + int split_at = 0; + /* if has a '=' sign get value */ + for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ + if(arg[i] == equalsign ){ + split_at = i ; /* store index */ + i = strlen(arg); /* get out of loop */ + } + } + if( split_at > 0 ){ /* it is an option value pair */ + char* tmp = (char*) malloc( (split_at+1)*sizeof(char) ); + for( int i = 0 ; i < split_at ; i++ ) + tmp[i] = arg[i]; + tmp[split_at] = '\0'; + + if ( matchOpt( tmp ) >= 0 ){ + setValue( options[matchOpt(tmp)] , arg+split_at+1 ); + free (tmp); + }else{ + printVerbose( "Unknown command argument option : " ); + printVerbose( arg ); + printVerbose( ); + printAutoUsage(); + free (tmp); + return -1; + } + }else{ /* regular options with no '=' sign */ + return matchOpt(arg); + } + return -1; +} + + +int +AnyOption::matchOpt( char *opt ) +{ + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], opt ) == 0 ){ + if( optiontype[i] == COMMON_OPT || + optiontype[i] == COMMAND_OPT ) + { /* found option return index */ + return i; + }else if( optiontype[i] == COMMON_FLAG || + optiontype[i] == COMMAND_FLAG ) + { /* found flag, set it */ + setFlagOn( opt ); + return -1; + } + } + } + printVerbose( "Unknown command argument option : " ); + printVerbose( opt ) ; + printVerbose( ); + printAutoUsage(); + return -1; +} +bool +AnyOption::matchChar( char c ) +{ + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == c ) { /* found match */ + if(optchartype[i] == COMMON_OPT || + optchartype[i] == COMMAND_OPT ) + { /* an option store and stop scanning */ + return true; + }else if( optchartype[i] == COMMON_FLAG || + optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */ + setFlagOn( c ); + return false; + } + } + } + printVerbose( "Unknown command argument option : " ); + printVerbose( c ) ; + printVerbose( ); + printAutoUsage(); + return false; +} + +bool +AnyOption::valueStoreOK( ) +{ + int size= 0; + if( !set ){ + if( g_value_counter > 0 ){ + size = g_value_counter * sizeof(char*); + values = (char**)malloc( size ); + for( int i = 0 ; i < g_value_counter ; i++) + values[i] = NULL; + set = true; + } + } + return set; +} + +/* + * public get methods + */ +char* +AnyOption::getValue( const char *option ) +{ + if( !valueStoreOK() ) + return NULL; + + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], option ) == 0 ) + return values[ optionindex[i] ]; + } + return NULL; +} + +bool +AnyOption::getFlag( const char *option ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], option ) == 0 ) + return findFlag( values[ optionindex[i] ] ); + } + return false; +} + +char* +AnyOption::getValue( char option ) +{ + if( !valueStoreOK() ) + return NULL; + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == option ) + return values[ optcharindex[i] ]; + } + return NULL; +} + +bool +AnyOption::getFlag( char option ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == option ) + return findFlag( values[ optcharindex[i] ] ) ; + } + return false; +} + +bool +AnyOption::findFlag( char* val ) +{ + if( val == NULL ) + return false; + + if( strcmp( TRUE_FLAG , val ) == 0 ) + return true; + + return false; +} + +/* + * private set methods + */ +bool +AnyOption::setValue( const char *option , char *value ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], option ) == 0 ){ + values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char)); + strcpy( values[ optionindex[i] ], value ); + return true; + } + } + return false; +} + +bool +AnyOption::setFlagOn( const char *option ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], option ) == 0 ){ + values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char)); + strcpy( values[ optionindex[i] ] , TRUE_FLAG ); + return true; + } + } + return false; +} + +bool +AnyOption::setValue( char option , char *value ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == option ){ + values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char)); + strcpy( values[ optcharindex[i] ], value ); + return true; + } + } + return false; +} + +bool +AnyOption::setFlagOn( char option ) +{ + if( !valueStoreOK() ) + return false; + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == option ){ + values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char)); + strcpy( values[ optcharindex[i] ] , TRUE_FLAG ); + return true; + } + } + return false; +} + + +int +AnyOption::getArgc( ) +{ + return new_argc; +} + +char* +AnyOption::getArgv( int index ) +{ + if( index < new_argc ){ + return ( argv[ new_argv[ index ] ] ); + } + return NULL; +} + +/* dotfile sub routines */ + +bool +AnyOption::processFile() +{ + if( ! (valueStoreOK() && FileSet()) ) + return false; + return ( consumeFile(readFile()) ); +} + +bool +AnyOption::processFile( const char *filename ) +{ + useFiileName(filename ); + return ( processFile() ); +} + +char* +AnyOption::readFile() +{ + return ( readFile(filename) ); +} + +/* + * read the file contents to a character buffer + */ + +char* +AnyOption::readFile( const char* fname ) +{ + int length; + char *buffer; + ifstream is; + is.open ( fname , ifstream::in ); + if( ! is.good() ){ + is.close(); + return NULL; + } + is.seekg (0, ios::end); + length = is.tellg(); + is.seekg (0, ios::beg); + buffer = (char*) malloc(length*sizeof(char)); + is.read (buffer,length); + is.close(); + return buffer; +} + +/* + * scans a char* buffer for lines that does not + * start with the specified comment character. + */ +bool +AnyOption::consumeFile( char *buffer ) +{ + + if( buffer == NULL ) + return false; + + char *cursor = buffer;/* preserve the ptr */ + char *pline = NULL ; + int linelength = 0; + bool newline = true; + for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){ + if( *cursor == endofline ) { /* end of line */ + if( pline != NULL ) /* valid line */ + processLine( pline, linelength ); + pline = NULL; + newline = true; + }else if( newline ){ /* start of line */ + newline = false; + if( (*cursor != comment ) ){ /* not a comment */ + pline = cursor ; + linelength = 0 ; + } + } + cursor++; /* keep moving */ + linelength++; + } + free (buffer); + return true; +} + + +/* + * find a valid type value pair separated by a delimiter + * character and pass it to valuePairs() + * any line which is not valid will be considered a value + * and will get passed on to justValue() + * + * assuming delimiter is ':' the behaviour will be, + * + * width:10 - valid pair valuePairs( width, 10 ); + * width : 10 - valid pair valuepairs( width, 10 ); + * + * :::: - not valid + * width - not valid + * :10 - not valid + * width: - not valid + * :: - not valid + * : - not valid + * + */ + +void +AnyOption::processLine( char *theline, int length ) +{ + bool found = false; + char *pline = (char*) malloc( (length+1)*sizeof(char) ); + for( int i = 0 ; i < length ; i ++ ) + pline[i]= *(theline++); + pline[length] = nullterminate; + char *cursor = pline ; /* preserve the ptr */ + if( *cursor == delimiter || *(cursor+length-1) == delimiter ){ + justValue( pline );/* line with start/end delimiter */ + }else{ + for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */ + if( *cursor == delimiter ){ + *(cursor-1) = nullterminate; /* two strings */ + found = true; + valuePairs( pline , cursor+1 ); + } + cursor++; + } + cursor++; + if( !found ) /* not a pair */ + justValue( pline ); + } + free (pline); +} + +/* + * removes trailing and preceeding whitespaces from a string + */ +char* +AnyOption::chomp( char *str ) +{ + while( *str == whitespace ) + str++; + char *end = str+strlen(str)-1; + while( *end == whitespace ) + end--; + *(end+1) = nullterminate; + return str; +} + +void +AnyOption::valuePairs( char *type, char *value ) +{ + if ( strlen(chomp(type)) == 1 ){ /* this is a char option */ + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == type[0] ){ /* match */ + if( optchartype[i] == COMMON_OPT || + optchartype[i] == FILE_OPT ) + { + setValue( type[0] , chomp(value) ); + return; + } + } + } + } + /* if no char options matched */ + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], type ) == 0 ){ /* match */ + if( optiontype[i] == COMMON_OPT || + optiontype[i] == FILE_OPT ) + { + setValue( type , chomp(value) ); + return; + } + } + } + printVerbose( "Unknown option in resourcefile : " ); + printVerbose( type ); + printVerbose( ); +} + +void +AnyOption::justValue( char *type ) +{ + + if ( strlen(chomp(type)) == 1 ){ /* this is a char option */ + for( int i = 0 ; i < optchar_counter ; i++ ){ + if( optionchars[i] == type[0] ){ /* match */ + if( optchartype[i] == COMMON_FLAG || + optchartype[i] == FILE_FLAG ) + { + setFlagOn( type[0] ); + return; + } + } + } + } + /* if no char options matched */ + for( int i = 0 ; i < option_counter ; i++ ){ + if( strcmp( options[i], type ) == 0 ){ /* match */ + if( optiontype[i] == COMMON_FLAG || + optiontype[i] == FILE_FLAG ) + { + setFlagOn( type ); + return; + } + } + } + printVerbose( "Unknown option in resourcefile : " ); + printVerbose( type ); + printVerbose( ); +} + +/* + * usage and help + */ + + +void +AnyOption::printAutoUsage() +{ + if( autousage ) printUsage(); +} + +void +AnyOption::printUsage() +{ + + if( once ) { + once = false ; + cout << endl ; + for( int i = 0 ; i < usage_lines ; i++ ) + cout << usage[i] << endl ; + cout << endl ; + } +} + + +void +AnyOption::addUsage( const char *line ) +{ + if( usage_lines >= max_usage_lines ){ + if( doubleUsageStorage() == false ){ + addUsageError( line ); + exit(1); + } + } + usage[ usage_lines ] = line ; + usage_lines++; +} + +void +AnyOption::addUsageError( const char *line ) +{ + cout << endl ; + cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; + cout << "While adding the usage/help : \""<< line << "\"" << endl; + cout << "Exiting." << endl ; + cout << endl ; + exit(0); + +} |