anyoption.cpp

Go to the documentation of this file.
00001 /*
00002  * AnyOption 1.3  
00003  *
00004  * kishan at hackorama dot com  www.hackorama.com JULY 2001 
00005  *
00006  * + Acts as a common facade class for reading 
00007  *   commandline options as well as options from
00008  *   an optionfile with delimited type value pairs 
00009  *
00010  * + Handles the POSIX style single character options ( -w )
00011  *   as well as the newer GNU long options ( --width )
00012  * 
00013  * + The option file assumes the traditional format of
00014  *   first character based comment lines and type value
00015  *   pairs with a delimiter , and flags which are not pairs
00016  * 
00017  *      # this is a coment
00018  *      # next line is an option value pair
00019  *      width : 100
00020  *      # next line is a flag 
00021  *      noimages   
00022  * 
00023  * + Supports printing out Help and Usage  
00024  * 
00025  * + Why not just use getopt() ? 
00026  *
00027  *   getopt() Its a POSIX standard not part of ANSI-C. 
00028  *   So it may not be available on platforms like Windows.
00029  *
00030  * + Why it is so long ?
00031  *
00032  *   The actual code which does command line parsing 
00033  *   and option file parsing are done in  few methods. 
00034  *   Most of the extra code are for providing a flexible
00035  *   common public interface to both a resourcefile and
00036  *   and command line supporting POSIX style and  
00037  *   GNU long option as well as mixing of both. 
00038  * 
00039  * + Please see "anyoption.h" for public method descriptions 
00040  *   
00041  */
00042 
00043 /* Updated Auguest 2004 
00044  * Fix from  Michael D Peters (mpeters at sandia.gov) 
00045  * to remove static local variables, allowing multiple instantiations 
00046  * of the reader (for using multiple configuration files).  There is
00047  * an error in the destructor when using multiple instances, so you
00048  * cannot delete your objects (it will crash), but not calling the 
00049  * destructor only introduces a small memory leak, so I
00050  * have not bothered tracking it down.
00051  *
00052  * Also updated to use modern C++ style headers, rather than
00053  * depricated iostream.h (it was causing my compiler problems)
00054 */
00055 
00056 /* 
00057  * Updated September 2006  
00058  * Fix from Boyan Asenov for a bug in mixing up option indexes 
00059  * leading to exception when mixing different options types
00060  */
00061 
00062 #include "anyoption.h"
00063 #include <cstring>
00064 
00065 AnyOption::AnyOption()
00066 {
00067     init();
00068 }
00069 
00070 AnyOption::AnyOption(int maxopt)
00071 {
00072     init( maxopt , maxopt );
00073 }
00074 
00075 AnyOption::AnyOption(int maxopt, int maxcharopt)
00076 {
00077     init( maxopt , maxcharopt );
00078 }
00079 
00080 AnyOption::~AnyOption()
00081 {
00082     if( mem_allocated )
00083         cleanup();
00084 }
00085 
00086 void
00087 AnyOption::init()
00088 {
00089     init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS );
00090 }
00091 
00092 void
00093 AnyOption::init(int maxopt, int maxcharopt )
00094 {
00095 
00096     max_options     = maxopt;
00097     max_char_options = maxcharopt;
00098     max_usage_lines = DEFAULT_MAXUSAGE;
00099     usage_lines = 0 ;
00100     argc        = 0;
00101     argv        = NULL;
00102     posix_style = true;
00103     verbose     = false;
00104     filename    = NULL;
00105     appname     = NULL; 
00106     option_counter  = 0;
00107     optchar_counter = 0;
00108     new_argv    = NULL;
00109     new_argc    = 0 ;
00110     max_legal_args  = 0 ;
00111     command_set     = false;
00112     file_set    = false;
00113     values      = NULL; 
00114     g_value_counter = 0;
00115     mem_allocated   = false;
00116     command_set     = false;
00117     file_set    = false;
00118     opt_prefix_char     = '-';
00119     file_delimiter_char = ':';
00120     file_comment_char   = '#';
00121     equalsign   = '=';
00122     comment       = '#' ;
00123     delimiter     = ':' ;
00124     endofline     = '\n';
00125     whitespace    = ' ' ;
00126     nullterminate = '\0';
00127     set = false;
00128     once = true;
00129     hasoptions = false;
00130     autousage = false;
00131 
00132     strcpy( long_opt_prefix , "--" );
00133 
00134     if( alloc() == false ){
00135         cout << endl << "OPTIONS ERROR : Failed allocating memory" ;
00136         cout << endl ;
00137         cout << "Exiting." << endl ;
00138         exit (0);
00139     }
00140 }
00141 
00142 bool
00143 AnyOption::alloc()
00144 {
00145     int i = 0 ;
00146     int size = 0 ;
00147 
00148     if( mem_allocated )
00149         return true;
00150 
00151     size = (max_options+1) * sizeof(const char*);
00152     options = (const char**)malloc( size ); 
00153     optiontype = (int*) malloc( (max_options+1)*sizeof(int) );  
00154     optionindex = (int*) malloc( (max_options+1)*sizeof(int) ); 
00155     if( options == NULL || optiontype == NULL || optionindex == NULL )
00156         return false;
00157     else
00158         mem_allocated  = true;
00159     for( i = 0 ; i < max_options ; i++ ){
00160         options[i] = NULL;
00161         optiontype[i] = 0 ;
00162         optionindex[i] = -1 ;
00163     }
00164     optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) );
00165     optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) );    
00166     optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) );   
00167     if( optionchars == NULL || 
00168             optchartype == NULL || 
00169             optcharindex == NULL )
00170         {
00171         mem_allocated = false;
00172         return false;
00173     }
00174     for( i = 0 ; i < max_char_options ; i++ ){
00175         optionchars[i] = '0';
00176         optchartype[i] = 0 ;
00177         optcharindex[i] = -1 ;
00178     }
00179 
00180     size = (max_usage_lines+1) * sizeof(const char*) ;
00181     usage = (const char**) malloc( size );
00182 
00183     if( usage == NULL  ){
00184         mem_allocated = false;
00185         return false;
00186     }
00187     for( i = 0 ; i < max_usage_lines ; i++ )
00188         usage[i] = NULL;
00189 
00190     return true;
00191 }
00192 
00193 bool
00194 AnyOption::doubleOptStorage()
00195 {
00196     options = (const char**)realloc( options,  
00197             ((2*max_options)+1) * sizeof( const char*) );
00198     optiontype = (int*) realloc(  optiontype ,  
00199             ((2 * max_options)+1)* sizeof(int) );   
00200     optionindex = (int*) realloc(  optionindex,  
00201             ((2 * max_options)+1) * sizeof(int) );  
00202     if( options == NULL || optiontype == NULL || optionindex == NULL )
00203         return false;
00204     /* init new storage */
00205     for( int i = max_options ; i < 2*max_options ; i++ ){
00206         options[i] = NULL;
00207         optiontype[i] = 0 ;
00208         optionindex[i] = -1 ;
00209     }
00210     max_options = 2 * max_options ;
00211     return true;
00212 }
00213 
00214 bool
00215 AnyOption::doubleCharStorage()
00216 {
00217     optionchars = (char*) realloc( optionchars,  
00218             ((2*max_char_options)+1)*sizeof(char) );
00219     optchartype = (int*) realloc( optchartype,  
00220             ((2*max_char_options)+1)*sizeof(int) ); 
00221     optcharindex = (int*) realloc( optcharindex,  
00222             ((2*max_char_options)+1)*sizeof(int) ); 
00223     if( optionchars == NULL || 
00224         optchartype == NULL || 
00225         optcharindex == NULL )
00226         return false;
00227     /* init new storage */
00228     for( int i = max_char_options ; i < 2*max_char_options ; i++ ){
00229         optionchars[i] = '0';
00230         optchartype[i] = 0 ;
00231         optcharindex[i] = -1 ;
00232     }
00233     max_char_options = 2 * max_char_options;    
00234     return true;
00235 }
00236 
00237 bool
00238 AnyOption::doubleUsageStorage()
00239 {
00240     usage = (const char**)realloc( usage,  
00241             ((2*max_usage_lines)+1) * sizeof( const char*) );
00242     if ( usage == NULL )
00243         return false;
00244     for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ )
00245         usage[i] = NULL;
00246     max_usage_lines = 2 * max_usage_lines ;
00247     return true;
00248 
00249 }
00250 
00251 
00252 void
00253 AnyOption::cleanup()
00254 {
00255     free (options);
00256     free (optiontype);
00257     free (optionindex); 
00258     free (optionchars);
00259     free (optchartype);
00260     free (optcharindex);
00261     free (usage);
00262     if( values != NULL )
00263         free (values);
00264     if( new_argv != NULL )
00265         free (new_argv);
00266 }
00267 
00268 void
00269 AnyOption::setCommandPrefixChar( char _prefix )
00270 {
00271     opt_prefix_char = _prefix;
00272 }
00273 
00274 void
00275 AnyOption::setCommandLongPrefix( char *_prefix )
00276 {
00277     if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){
00278         *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0'; 
00279     }
00280 
00281     strcpy (long_opt_prefix,  _prefix);
00282 }
00283 
00284 void
00285 AnyOption::setFileCommentChar( char _comment )
00286 {
00287     file_delimiter_char = _comment;
00288 }
00289 
00290 
00291 void
00292 AnyOption::setFileDelimiterChar( char _delimiter )
00293 {
00294     file_comment_char = _delimiter ;
00295 }
00296 
00297 bool
00298 AnyOption::CommandSet()
00299 {
00300     return( command_set );
00301 }
00302 
00303 bool
00304 AnyOption::FileSet()
00305 {
00306     return( file_set );
00307 }
00308 
00309 void
00310 AnyOption::noPOSIX()
00311 {
00312     posix_style = false;
00313 }
00314 
00315 bool
00316 AnyOption::POSIX()
00317 {
00318     return posix_style;
00319 }
00320 
00321 
00322 void
00323 AnyOption::setVerbose()
00324 {
00325     verbose = true ;
00326 }
00327 
00328 void
00329 AnyOption::printVerbose()
00330 {
00331     if( verbose )
00332         cout << endl  ;
00333 }
00334 void
00335 AnyOption::printVerbose( const char *msg )
00336 {
00337     if( verbose )
00338         cout << msg  ;
00339 }
00340 
00341 void
00342 AnyOption::printVerbose( char *msg )
00343 {
00344     if( verbose )
00345         cout << msg  ;
00346 }
00347 
00348 void
00349 AnyOption::printVerbose( char ch )
00350 {
00351     if( verbose )
00352         cout << ch ;
00353 }
00354 
00355 bool
00356 AnyOption::hasOptions()
00357 {
00358     return hasoptions;
00359 }
00360 
00361 void
00362 AnyOption::autoUsagePrint(bool _autousage)
00363 {
00364     autousage = _autousage;
00365 }
00366 
00367 void
00368 AnyOption::useCommandArgs( int _argc, char **_argv )
00369 {
00370     argc = _argc;
00371     argv = _argv;
00372     command_set = true;
00373     appname = argv[0];
00374     if(argc > 1) hasoptions = true;
00375 }
00376 
00377 void
00378 AnyOption::useFiileName( const char *_filename )
00379 {
00380     filename = _filename;
00381     file_set = true;
00382 }
00383 
00384 /*
00385  * set methods for options 
00386  */
00387 
00388 void
00389 AnyOption::setCommandOption( const char *opt )
00390 {
00391     addOption( opt , COMMAND_OPT );
00392     g_value_counter++;
00393 }
00394 
00395 void
00396 AnyOption::setCommandOption( char opt )
00397 {
00398     addOption( opt , COMMAND_OPT );
00399     g_value_counter++;
00400 }
00401 
00402 void
00403 AnyOption::setCommandOption( const char *opt , char optchar )
00404 {
00405     addOption( opt , COMMAND_OPT );
00406     addOption( optchar , COMMAND_OPT );
00407     g_value_counter++;
00408 }
00409 
00410 void
00411 AnyOption::setCommandFlag( const char *opt )
00412 {
00413     addOption( opt , COMMAND_FLAG );
00414     g_value_counter++;
00415 }
00416 
00417 void
00418 AnyOption::setCommandFlag( char opt )
00419 {
00420     addOption( opt , COMMAND_FLAG );
00421     g_value_counter++;
00422 }
00423 
00424 void
00425 AnyOption::setCommandFlag( const char *opt , char optchar )
00426 {
00427     addOption( opt , COMMAND_FLAG );
00428     addOption( optchar , COMMAND_FLAG );
00429     g_value_counter++;
00430 }
00431 
00432 void
00433 AnyOption::setFileOption( const char *opt )
00434 {
00435     addOption( opt , FILE_OPT );
00436     g_value_counter++;
00437 }
00438 
00439 void
00440 AnyOption::setFileOption( char opt )
00441 {
00442     addOption( opt , FILE_OPT );
00443     g_value_counter++;
00444 }
00445 
00446 void
00447 AnyOption::setFileOption( const char *opt , char optchar )
00448 {
00449     addOption( opt , FILE_OPT );
00450     addOption( optchar, FILE_OPT  );
00451     g_value_counter++;
00452 }
00453 
00454 void
00455 AnyOption::setFileFlag( const char *opt )
00456 {
00457     addOption( opt , FILE_FLAG );
00458     g_value_counter++;
00459 }
00460 
00461 void
00462 AnyOption::setFileFlag( char opt )
00463 {
00464     addOption( opt , FILE_FLAG );
00465     g_value_counter++;
00466 }
00467 
00468 void
00469 AnyOption::setFileFlag( const char *opt , char optchar )
00470 {
00471     addOption( opt , FILE_FLAG );
00472     addOption( optchar , FILE_FLAG );
00473     g_value_counter++;
00474 }
00475 
00476 void
00477 AnyOption::setOption( const char *opt )
00478 {
00479     addOption( opt , COMMON_OPT );
00480     g_value_counter++;
00481 }
00482 
00483 void
00484 AnyOption::setOption( char opt )
00485 {
00486     addOption( opt , COMMON_OPT );
00487     g_value_counter++;
00488 }
00489 
00490 void
00491 AnyOption::setOption( const char *opt , char optchar )
00492 {
00493     addOption( opt , COMMON_OPT );
00494     addOption( optchar , COMMON_OPT );
00495     g_value_counter++;
00496 }
00497 
00498 void
00499 AnyOption::setFlag( const char *opt )
00500 {
00501     addOption( opt , COMMON_FLAG );
00502     g_value_counter++;
00503 }
00504 
00505 void
00506 AnyOption::setFlag( const char opt )
00507 {
00508     addOption( opt , COMMON_FLAG );
00509     g_value_counter++;
00510 }
00511 
00512 void
00513 AnyOption::setFlag( const char *opt , char optchar )
00514 {
00515     addOption( opt , COMMON_FLAG );
00516     addOption( optchar , COMMON_FLAG );
00517     g_value_counter++;
00518 }
00519 
00520 void
00521 AnyOption::addOption( const char *opt, int type )
00522 {
00523     if( option_counter >= max_options ){
00524         if( doubleOptStorage() == false ){
00525             addOptionError( opt );
00526             return;
00527         }
00528     }
00529     options[ option_counter ] = opt ;
00530     optiontype[ option_counter ] =  type ;
00531     optionindex[ option_counter ] = g_value_counter; 
00532     option_counter++;
00533 }
00534 
00535 void
00536 AnyOption::addOption( char opt, int type )
00537 {
00538     if( !POSIX() ){
00539         printVerbose("Ignoring the option character \"");
00540         printVerbose(  opt );
00541         printVerbose( "\" ( POSIX options are turned off )" );
00542         printVerbose();
00543         return;
00544     }
00545 
00546 
00547     if( optchar_counter >= max_char_options ){
00548         if( doubleCharStorage() == false ){
00549             addOptionError( opt );
00550             return;
00551         }
00552     }
00553     optionchars[ optchar_counter ] =  opt ;
00554     optchartype[ optchar_counter ] =  type ;
00555     optcharindex[ optchar_counter ] = g_value_counter; 
00556     optchar_counter++;
00557 }
00558 
00559 void
00560 AnyOption::addOptionError( const char *opt )
00561 {
00562     cout << endl ;
00563     cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
00564     cout << "While adding the option : \""<< opt << "\"" << endl;
00565     cout << "Exiting." << endl ;
00566     cout << endl ;
00567     exit(0);
00568 }
00569 
00570 void
00571 AnyOption::addOptionError( char opt )
00572 {
00573     cout << endl ;
00574     cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
00575     cout << "While adding the option: \""<< opt << "\"" << endl;
00576     cout << "Exiting." << endl ;
00577     cout << endl ;
00578     exit(0);
00579 }
00580 
00581 void
00582 AnyOption::processOptions()
00583 {
00584     if( ! valueStoreOK() )
00585         return;
00586 }
00587 
00588 void 
00589 AnyOption::processCommandArgs(int max_args)
00590 {
00591     max_legal_args = max_args;
00592     processCommandArgs();
00593 }
00594  
00595 void
00596 AnyOption::processCommandArgs( int _argc, char **_argv, int max_args )
00597 {
00598     max_legal_args = max_args;
00599     processCommandArgs(  _argc, _argv );
00600 }
00601 
00602 void
00603 AnyOption::processCommandArgs( int _argc, char **_argv )
00604 {
00605     useCommandArgs( _argc, _argv );
00606     processCommandArgs();
00607 }
00608 
00609 void
00610 AnyOption::processCommandArgs()
00611 {
00612     if( ! ( valueStoreOK() && CommandSet() )  )
00613        return;
00614        
00615     if( max_legal_args == 0 )
00616         max_legal_args = argc;
00617     new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) );
00618     for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */
00619         if(  argv[i][0] == long_opt_prefix[0] && 
00620                      argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */
00621             int match_at = parseGNU( argv[i]+2 ); /* skip -- */
00622             if( match_at >= 0 && i < argc-1 ) /* found match */
00623                 setValue( options[match_at] , argv[++i] );
00624         }else if(  argv[i][0] ==  opt_prefix_char ) { /* POSIX char */
00625             if( POSIX() ){ 
00626                 char ch =  parsePOSIX( argv[i]+1 );/* skip - */ 
00627                 if( ch != '0' && i < argc-1 ) /* matching char */
00628                     setValue( ch ,  argv[++i] );
00629             } else { /* treat it as GNU option with a - */
00630                 int match_at = parseGNU( argv[i]+1 ); /* skip - */
00631                 if( match_at >= 0 && i < argc-1 ) /* found match */
00632                     setValue( options[match_at] , argv[++i] );
00633             }
00634         }else { /* not option but an argument keep index */
00635             if( new_argc < max_legal_args ){
00636                                 new_argv[ new_argc ] = i ;
00637                                 new_argc++;
00638                         }else{ /* ignore extra arguments */
00639                                 printVerbose( "Ignoring extra argument: " );
00640                 printVerbose( argv[i] );
00641                 printVerbose( );
00642                 printAutoUsage();
00643                         }
00644             printVerbose( "Unknown command argument option : " );
00645             printVerbose( argv[i] );
00646             printVerbose( );
00647             printAutoUsage();
00648         }
00649     }
00650 }
00651 
00652 char 
00653 AnyOption::parsePOSIX( char* arg )
00654 {
00655 
00656     for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ 
00657         char ch = arg[i] ;
00658         if( matchChar(ch) ) { /* keep matching flags till an option */
00659             /*if last char argv[++i] is the value */
00660             if( i == strlen(arg)-1 ){ 
00661                 return ch;
00662             }else{/* else the rest of arg is the value */
00663                 i++; /* skip any '=' and ' ' */
00664                 while( arg[i] == whitespace 
00665                         || arg[i] == equalsign )
00666                     i++;    
00667                 setValue( ch , arg+i );
00668                 return '0';
00669             }
00670         }
00671     }
00672     printVerbose( "Unknown command argument option : " );
00673     printVerbose( arg );
00674     printVerbose( );
00675     printAutoUsage();
00676     return '0';
00677 }
00678 
00679 int
00680 AnyOption::parseGNU( char *arg )
00681 {
00682     int split_at = 0;
00683     /* if has a '=' sign get value */
00684     for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
00685         if(arg[i] ==  equalsign ){
00686             split_at = i ; /* store index */
00687             i = strlen(arg); /* get out of loop */
00688         }
00689     }
00690     if( split_at > 0 ){ /* it is an option value pair */
00691         char* tmp = (char*) malloc(  (split_at+1)*sizeof(char) );
00692         for( int i = 0 ; i < split_at ; i++ )
00693             tmp[i] = arg[i];
00694         tmp[split_at] = '\0';
00695 
00696         if ( matchOpt( tmp ) >= 0 ){
00697             setValue( options[matchOpt(tmp)] , arg+split_at+1 );
00698             free (tmp);
00699         }else{
00700             printVerbose( "Unknown command argument option : " );
00701             printVerbose( arg );
00702             printVerbose( );
00703             printAutoUsage();
00704             free (tmp);
00705             return -1;
00706         }
00707     }else{ /* regular options with no '=' sign  */
00708         return  matchOpt(arg);
00709     }
00710     return -1;
00711 }
00712 
00713 
00714 int 
00715 AnyOption::matchOpt( char *opt )
00716 {
00717     for( int i = 0 ; i < option_counter ; i++ ){
00718         if( strcmp( options[i], opt ) == 0 ){
00719             if( optiontype[i] ==  COMMON_OPT ||
00720                 optiontype[i] ==  COMMAND_OPT ) 
00721             { /* found option return index */
00722                 return i;
00723             }else if( optiontype[i] == COMMON_FLAG ||
00724                    optiontype[i] == COMMAND_FLAG )
00725             { /* found flag, set it */ 
00726                 setFlagOn( opt );
00727                 return -1;
00728             }
00729         }
00730     }
00731     printVerbose( "Unknown command argument option : " );
00732     printVerbose( opt  ) ;
00733     printVerbose( );
00734     printAutoUsage();
00735     return  -1; 
00736 }
00737 bool
00738 AnyOption::matchChar( char c )
00739 {
00740     for( int i = 0 ; i < optchar_counter ; i++ ){
00741         if( optionchars[i] == c ) { /* found match */
00742             if(optchartype[i] == COMMON_OPT ||
00743                  optchartype[i] == COMMAND_OPT )
00744             { /* an option store and stop scanning */
00745                 return true;    
00746             }else if( optchartype[i] == COMMON_FLAG || 
00747                   optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */
00748                 setFlagOn( c );
00749                 return false;
00750             }
00751         }
00752     }
00753     printVerbose( "Unknown command argument option : " );
00754     printVerbose( c ) ;
00755     printVerbose( );
00756     printAutoUsage();
00757     return false;
00758 }
00759 
00760 bool
00761 AnyOption::valueStoreOK( )
00762 {
00763     int size= 0;
00764     if( !set ){
00765         if( g_value_counter > 0 ){
00766             size = g_value_counter * sizeof(char*);
00767             values = (char**)malloc( size );    
00768             for( int i = 0 ; i < g_value_counter ; i++)
00769                 values[i] = NULL;
00770             set = true;
00771         }
00772     }
00773     return  set;
00774 }
00775 
00776 /*
00777  * public get methods 
00778  */
00779 char*
00780 AnyOption::getValue( const char *option )
00781 {
00782     if( !valueStoreOK() )
00783         return NULL;
00784 
00785     for( int i = 0 ; i < option_counter ; i++ ){
00786         if( strcmp( options[i], option ) == 0 )
00787             return values[ optionindex[i] ];
00788     }
00789     return NULL;
00790 }
00791 
00792 bool
00793 AnyOption::getFlag( const char *option )
00794 {
00795     if( !valueStoreOK() )
00796         return false;
00797     for( int i = 0 ; i < option_counter ; i++ ){
00798         if( strcmp( options[i], option ) == 0 )
00799             return findFlag( values[ optionindex[i] ] );
00800     }
00801     return false;
00802 }
00803 
00804 char*
00805 AnyOption::getValue( char option )
00806 {
00807     if( !valueStoreOK() )
00808         return NULL;
00809     for( int i = 0 ; i < optchar_counter ; i++ ){
00810         if( optionchars[i] == option )
00811             return values[ optcharindex[i] ];
00812     }
00813     return NULL;
00814 }
00815 
00816 bool
00817 AnyOption::getFlag( char option )
00818 {
00819     if( !valueStoreOK() )
00820         return false;
00821     for( int i = 0 ; i < optchar_counter ; i++ ){
00822         if( optionchars[i] == option )
00823             return findFlag( values[ optcharindex[i] ] ) ;
00824     }
00825     return false;
00826 }
00827 
00828 bool
00829 AnyOption::findFlag( char* val )
00830 {
00831     if( val == NULL )
00832         return false;
00833 
00834     if( strcmp( TRUE_FLAG , val ) == 0 )
00835         return true;
00836 
00837     return false;
00838 }
00839 
00840 /*
00841  * private set methods 
00842  */
00843 bool
00844 AnyOption::setValue( const char *option , char *value )
00845 {
00846     if( !valueStoreOK() )
00847         return false;
00848         for( int i = 0 ; i < option_counter ; i++ ){
00849                 if( strcmp( options[i], option ) == 0 ){
00850                         values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
00851                         strcpy( values[ optionindex[i] ], value );
00852             return true;
00853         }
00854         }
00855         return false;
00856 }
00857 
00858 bool
00859 AnyOption::setFlagOn( const char *option )
00860 {
00861     if( !valueStoreOK() )
00862         return false;
00863         for( int i = 0 ; i < option_counter ; i++ ){
00864                 if( strcmp( options[i], option ) == 0 ){
00865                         values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
00866                         strcpy( values[ optionindex[i] ]  ,  TRUE_FLAG );
00867             return true;
00868         }
00869         }
00870         return false;
00871 }
00872 
00873 bool
00874 AnyOption::setValue( char option , char *value )
00875 {
00876     if( !valueStoreOK() )
00877         return false;
00878         for( int i = 0 ; i < optchar_counter ; i++ ){
00879                 if( optionchars[i] == option ){
00880                         values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
00881                         strcpy( values[ optcharindex[i] ],  value );
00882             return true;
00883         }
00884         }
00885         return false;
00886 }
00887 
00888 bool
00889 AnyOption::setFlagOn( char option )
00890 {
00891     if( !valueStoreOK() )
00892         return false;
00893         for( int i = 0 ; i < optchar_counter ; i++ ){
00894                 if( optionchars[i] == option ){
00895                         values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
00896             strcpy( values[ optcharindex[i] ] , TRUE_FLAG );
00897             return true;
00898         }
00899         }
00900         return false;
00901 }
00902 
00903 
00904 int
00905 AnyOption::getArgc( )
00906 {
00907     return new_argc;
00908 }
00909 
00910 char* 
00911 AnyOption::getArgv( int index )
00912 {
00913     if( index < new_argc ){
00914         return ( argv[ new_argv[ index ] ] );
00915     }
00916     return NULL;
00917 }
00918 
00919 /* dotfile sub routines */
00920 
00921 bool
00922 AnyOption::processFile()
00923 {
00924     if( ! (valueStoreOK() && FileSet())  )
00925         return false;
00926     return  ( consumeFile(readFile()) );
00927 }
00928 
00929 bool
00930 AnyOption::processFile( const char *filename )
00931 {
00932     useFiileName(filename );
00933     return ( processFile() );
00934 }
00935 
00936 char*
00937 AnyOption::readFile()
00938 {
00939     return ( readFile(filename) );
00940 }
00941 
00942 /*
00943  * read the file contents to a character buffer 
00944  */
00945 
00946 char*
00947 AnyOption::readFile( const char* fname )
00948 {
00949         int length;
00950         char *buffer;
00951         ifstream is;
00952         is.open ( fname , ifstream::in );
00953         if( ! is.good() ){
00954                 is.close();
00955                 return NULL;
00956         }
00957         is.seekg (0, ios::end);
00958         length = is.tellg();
00959         is.seekg (0, ios::beg);
00960         buffer = (char*) malloc(length*sizeof(char));
00961         is.read (buffer,length);
00962         is.close();
00963         return buffer;
00964 }
00965 
00966 /*
00967  * scans a char* buffer for lines that does not 
00968  * start with the specified comment character.
00969  */
00970 bool
00971 AnyOption::consumeFile( char *buffer )
00972 {
00973 
00974         if( buffer == NULL ) 
00975         return false;
00976 
00977         char *cursor = buffer;/* preserve the ptr */
00978         char *pline = NULL ;
00979         int linelength = 0;
00980         bool newline = true;
00981         for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){
00982         if( *cursor == endofline ) { /* end of line */
00983             if( pline != NULL ) /* valid line */
00984                     processLine( pline, linelength );
00985                     pline = NULL;
00986                     newline = true;
00987             }else if( newline ){ /* start of line */
00988                     newline = false;
00989                     if( (*cursor != comment ) ){ /* not a comment */
00990                     pline = cursor ;
00991                             linelength = 0 ;
00992                     }
00993                 }
00994                 cursor++; /* keep moving */
00995                 linelength++;
00996         }
00997         free (buffer);
00998     return true;
00999 }
01000 
01001 
01002 /*
01003  *  find a valid type value pair separated by a delimiter 
01004  *  character and pass it to valuePairs()
01005  *  any line which is not valid will be considered a value
01006  *  and will get passed on to justValue()
01007  *
01008  *  assuming delimiter is ':' the behaviour will be,
01009  *
01010  *  width:10    - valid pair valuePairs( width, 10 );
01011  *  width : 10  - valid pair valuepairs( width, 10 );
01012  *
01013  *  ::::        - not valid 
01014  *  width       - not valid
01015  *  :10         - not valid 
01016  *  width:      - not valid  
01017  *  ::          - not valid 
01018  *  :           - not valid 
01019  *  
01020  */
01021 
01022 void
01023 AnyOption::processLine( char *theline, int length  )
01024 {
01025         bool found = false;
01026         char *pline = (char*) malloc( (length+1)*sizeof(char) );
01027         for( int i = 0 ; i < length ; i ++ )
01028                 pline[i]= *(theline++);
01029         pline[length] = nullterminate;
01030         char *cursor = pline ; /* preserve the ptr */
01031         if( *cursor == delimiter || *(cursor+length-1) == delimiter ){
01032                 justValue( pline );/* line with start/end delimiter */
01033         }else{
01034                 for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */
01035                         if( *cursor == delimiter ){
01036                                 *(cursor-1) = nullterminate; /* two strings */
01037                                 found = true;
01038                                 valuePairs( pline , cursor+1 );
01039                         }
01040                         cursor++;
01041                 }
01042                 cursor++;
01043                 if( !found ) /* not a pair */
01044                         justValue( pline );
01045         }
01046         free (pline);
01047 }
01048 
01049 /*
01050  * removes trailing and preceeding whitespaces from a string
01051  */
01052 char*
01053 AnyOption::chomp( char *str )
01054 {
01055         while( *str == whitespace )
01056                 str++;
01057         char *end = str+strlen(str)-1;
01058         while( *end == whitespace )
01059                 end--;
01060         *(end+1) = nullterminate;
01061         return str;
01062 }
01063 
01064 void
01065 AnyOption::valuePairs( char *type, char *value )
01066 {
01067     if ( strlen(chomp(type)) == 1  ){ /* this is a char option */
01068         for( int i = 0 ; i < optchar_counter ; i++ ){
01069             if(  optionchars[i] == type[0]  ){ /* match */
01070                 if( optchartype[i] == COMMON_OPT ||
01071                     optchartype[i] == FILE_OPT )
01072                 {
01073                     setValue( type[0] , chomp(value) );
01074                     return;
01075                 }
01076             }
01077         }
01078     }   
01079     /* if no char options matched */
01080     for( int i = 0 ; i < option_counter ; i++ ){
01081         if( strcmp( options[i], type ) == 0 ){ /* match */
01082             if( optiontype[i] == COMMON_OPT ||
01083                 optiontype[i] == FILE_OPT )
01084             {
01085                 setValue( type , chomp(value) );
01086                 return;
01087             }
01088         }
01089     }
01090         printVerbose( "Unknown option in resourcefile : " );
01091     printVerbose( type );
01092     printVerbose( );
01093 }
01094 
01095 void
01096 AnyOption::justValue( char *type )
01097 {
01098 
01099     if ( strlen(chomp(type)) == 1  ){ /* this is a char option */
01100         for( int i = 0 ; i < optchar_counter ; i++ ){
01101             if(  optionchars[i] == type[0]  ){ /* match */
01102                 if( optchartype[i] == COMMON_FLAG ||
01103                     optchartype[i] == FILE_FLAG )
01104                 {
01105                     setFlagOn( type[0] );
01106                     return;
01107                 }
01108             }
01109         }
01110     }   
01111     /* if no char options matched */
01112     for( int i = 0 ; i < option_counter ; i++ ){
01113         if( strcmp( options[i], type ) == 0 ){ /* match */
01114             if( optiontype[i] == COMMON_FLAG ||
01115                 optiontype[i] == FILE_FLAG )
01116             {
01117                 setFlagOn( type );
01118                 return;
01119             }
01120         }
01121     }
01122         printVerbose( "Unknown option in resourcefile : " );
01123     printVerbose( type  );
01124     printVerbose( );
01125 }
01126 
01127 /*
01128  * usage and help 
01129  */
01130 
01131 
01132 void
01133 AnyOption::printAutoUsage()
01134 {
01135     if( autousage ) printUsage();
01136 }
01137 
01138 void
01139 AnyOption::printUsage()
01140 {
01141     
01142     if( once ) {
01143         once = false ;
01144         cout << endl ;
01145         for( int i = 0 ; i < usage_lines ; i++ )
01146             cout << usage[i] << endl ;  
01147         cout << endl ;
01148     }
01149 }
01150     
01151     
01152 void
01153 AnyOption::addUsage( const char *line )
01154 {
01155     if( usage_lines >= max_usage_lines ){
01156         if( doubleUsageStorage() == false ){
01157             addUsageError( line );
01158             exit(1);
01159         }
01160     }
01161     usage[ usage_lines ] = line ;   
01162     usage_lines++;
01163 }
01164 
01165 void
01166 AnyOption::addUsageError( const char *line )
01167 {
01168     cout << endl ;
01169     cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
01170     cout << "While adding the usage/help  : \""<< line << "\"" << endl;
01171     cout << "Exiting." << endl ;
01172     cout << endl ;
01173     exit(0);
01174 
01175 }