anyoption.cpp 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  1. /*
  2. * AnyOption 1.1
  3. *
  4. * kishan at hackorama dot com www.hackorama.com JULY 2001
  5. *
  6. * + Acts as a common facade class for reading
  7. * commandline options as well as options from
  8. * an optionfile with delimited type value pairs
  9. *
  10. * + Handles the POSIX style single character options ( -w )
  11. * as well as the newer GNU long options ( --width )
  12. *
  13. * + The option file assumes the traditional format of
  14. * first character based comment lines and type value
  15. * pairs with a delimiter , and flags which are not pairs
  16. *
  17. * # this is a coment
  18. * # next line is an option value pair
  19. * width : 100
  20. * # next line is a flag
  21. * noimages
  22. *
  23. * + Supports printing out Help and Usage
  24. *
  25. * + Why not just use getopt() ?
  26. *
  27. * getopt() Its a POSIX standard not part of ANSI-C.
  28. * So it may not be available on platforms like Windows.
  29. *
  30. * + Why it is so long ?
  31. *
  32. * The actual code which does command line parsing
  33. * and option file parsing are done in few methods.
  34. * Most of the extra code are for providing a flexible
  35. * common public interface to both a resourcefile and
  36. * and command line supporting POSIX style and
  37. * GNU long option as well as mixing of both.
  38. *
  39. * + Please see "anyoption.h" for public method descriptions
  40. *
  41. */
  42. /* Updated Auguest 2004 by Michael D Peters (mpeters at sandia.gov)
  43. * to remove static local variables, allowing multiple instantiations
  44. * of the reader (for using multiple configuration files). There is
  45. * an error in the destructor when using multiple instances, so you
  46. * cannot delete your objects (it will crash), but not calling the
  47. * destructor only introduces a small memory leak, so I
  48. * have not bothered tracking it down.
  49. *
  50. * Also updated to use modern C++ style headers, rather than
  51. * depricated iostream.h (it was causing my compiler problems)
  52. */
  53. #include "anyoption.h"
  54. using namespace std;
  55. AnyOption::AnyOption()
  56. {
  57. init();
  58. }
  59. AnyOption::AnyOption(int maxopt)
  60. {
  61. init( maxopt , maxopt );
  62. }
  63. AnyOption::AnyOption(int maxopt, int maxcharopt)
  64. {
  65. init( maxopt , maxcharopt );
  66. }
  67. AnyOption::~AnyOption()
  68. {
  69. if( mem_allocated )
  70. cleanup();
  71. }
  72. void
  73. AnyOption::init()
  74. {
  75. init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS );
  76. }
  77. void
  78. AnyOption::init(int maxopt, int maxcharopt )
  79. {
  80. max_options = maxopt;
  81. max_char_options = maxcharopt;
  82. max_usage_lines = DEFAULT_MAXUSAGE;
  83. print_usage = true;
  84. usage_lines = 0 ;
  85. argc = 0;
  86. argv = NULL;
  87. posix_style = true;
  88. verbose = false;
  89. filename = NULL;
  90. appname = NULL;
  91. option_counter = 0;
  92. optchar_counter = 0;
  93. new_argv = NULL;
  94. new_argc = 0 ;
  95. max_legal_args = 0 ;
  96. command_set = false;
  97. file_set = false;
  98. values = NULL;
  99. g_value_counter = 0;
  100. mem_allocated = false;
  101. command_set = false;
  102. file_set = false;
  103. opt_prefix_char = '-';
  104. file_delimiter_char = ':';
  105. file_comment_char = '#';
  106. equalsign = '=';
  107. comment = '#' ;
  108. delimiter = ':' ;
  109. endofline = '\n';
  110. whitespace = ' ' ;
  111. nullterminate = '\0';
  112. set = false;
  113. once = true;
  114. strcpy( long_opt_prefix , "--" );
  115. if( alloc() == false ){
  116. cout << endl << "OPTIONS ERROR : Failed allocating memory" ;
  117. cout << endl ;
  118. cout << "Exiting." << endl ;
  119. exit (0);
  120. }
  121. }
  122. bool
  123. AnyOption::alloc()
  124. {
  125. int i = 0 ;
  126. int size = 0 ;
  127. if( mem_allocated )
  128. return true;
  129. size = (max_options+1) * sizeof(const char*);
  130. options = (const char**)malloc( size );
  131. optiontype = (int*) malloc( (max_options+1)*sizeof(int) );
  132. optionindex = (int*) malloc( (max_options+1)*sizeof(int) );
  133. if( options == NULL || optiontype == NULL || optionindex == NULL )
  134. return false;
  135. else
  136. mem_allocated = true;
  137. for( i = 0 ; i < max_options ; i++ ){
  138. options[i] = NULL;
  139. optiontype[i] = 0 ;
  140. optionindex[i] = -1 ;
  141. }
  142. optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) );
  143. optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) );
  144. optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) );
  145. if( optionchars == NULL ||
  146. optchartype == NULL ||
  147. optcharindex == NULL )
  148. {
  149. mem_allocated = false;
  150. return false;
  151. }
  152. for( i = 0 ; i < max_char_options ; i++ ){
  153. optionchars[i] = '0';
  154. optchartype[i] = 0 ;
  155. optcharindex[i] = -1 ;
  156. }
  157. size = (max_usage_lines+1) * sizeof(const char*) ;
  158. usage = (const char**) malloc( size );
  159. if( usage == NULL ){
  160. mem_allocated = false;
  161. return false;
  162. }
  163. for( i = 0 ; i < max_usage_lines ; i++ )
  164. usage[i] = NULL;
  165. return true;
  166. }
  167. bool
  168. AnyOption::doubleOptStorage()
  169. {
  170. options = (const char**)realloc( options,
  171. ((2*max_options)+1) * sizeof( const char*) );
  172. optiontype = (int*) realloc( optiontype ,
  173. ((2 * max_options)+1)* sizeof(int) );
  174. optionindex = (int*) realloc( optionindex,
  175. ((2 * max_options)+1) * sizeof(int) );
  176. if( options == NULL || optiontype == NULL || optionindex == NULL )
  177. return false;
  178. /* init new storage */
  179. for( int i = max_options ; i < 2*max_options ; i++ ){
  180. options[i] = NULL;
  181. optiontype[i] = 0 ;
  182. optionindex[i] = -1 ;
  183. }
  184. max_options = 2 * max_options ;
  185. return true;
  186. }
  187. bool
  188. AnyOption::doubleCharStorage()
  189. {
  190. optionchars = (char*) realloc( optionchars,
  191. ((2*max_char_options)+1)*sizeof(char) );
  192. optchartype = (int*) realloc( optchartype,
  193. ((2*max_char_options)+1)*sizeof(int) );
  194. optcharindex = (int*) realloc( optcharindex,
  195. ((2*max_char_options)+1)*sizeof(int) );
  196. if( optionchars == NULL ||
  197. optchartype == NULL ||
  198. optcharindex == NULL )
  199. return false;
  200. /* init new storage */
  201. for( int i = max_char_options ; i < 2*max_char_options ; i++ ){
  202. optionchars[i] = '0';
  203. optchartype[i] = 0 ;
  204. optcharindex[i] = -1 ;
  205. }
  206. max_char_options = 2 * max_char_options;
  207. return true;
  208. }
  209. bool
  210. AnyOption::doubleUsageStorage()
  211. {
  212. usage = (const char**)realloc( usage,
  213. ((2*max_usage_lines)+1) * sizeof( const char*) );
  214. if ( usage == NULL )
  215. return false;
  216. for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ )
  217. usage[i] = NULL;
  218. max_usage_lines = 2 * max_usage_lines ;
  219. return true;
  220. }
  221. void
  222. AnyOption::cleanup()
  223. {
  224. free (options);
  225. free (optiontype);
  226. free (optionindex);
  227. free (optionchars);
  228. free (optchartype);
  229. free (optcharindex);
  230. free (usage);
  231. if( values != NULL )
  232. free (values);
  233. if( new_argv != NULL )
  234. free (new_argv);
  235. }
  236. void
  237. AnyOption::setCommandPrefixChar( char _prefix )
  238. {
  239. opt_prefix_char = _prefix;
  240. }
  241. void
  242. AnyOption::setCommandLongPrefix( char *_prefix )
  243. {
  244. if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){
  245. *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0';
  246. }
  247. strcpy (long_opt_prefix, _prefix);
  248. }
  249. void
  250. AnyOption::setFileCommentChar( char _comment )
  251. {
  252. file_delimiter_char = _comment;
  253. }
  254. void
  255. AnyOption::setFileDelimiterChar( char _delimiter )
  256. {
  257. file_comment_char = _delimiter ;
  258. }
  259. bool
  260. AnyOption::CommandSet()
  261. {
  262. return( command_set );
  263. }
  264. bool
  265. AnyOption::FileSet()
  266. {
  267. return( file_set );
  268. }
  269. void
  270. AnyOption::noPOSIX()
  271. {
  272. posix_style = false;
  273. }
  274. bool
  275. AnyOption::POSIX()
  276. {
  277. return posix_style;
  278. }
  279. void
  280. AnyOption::setVerbose()
  281. {
  282. verbose = true ;
  283. }
  284. void
  285. AnyOption::printVerbose()
  286. {
  287. if( verbose )
  288. cout << endl ;
  289. }
  290. void
  291. AnyOption::printVerbose( const char *msg )
  292. {
  293. if( verbose )
  294. cout << msg ;
  295. }
  296. void
  297. AnyOption::printVerbose( char *msg )
  298. {
  299. if( verbose )
  300. cout << msg ;
  301. }
  302. void
  303. AnyOption::printVerbose( char ch )
  304. {
  305. if( verbose )
  306. cout << ch ;
  307. }
  308. void
  309. AnyOption::useCommandArgs( int _argc, char **_argv )
  310. {
  311. argc = _argc;
  312. argv = _argv;
  313. command_set = true;
  314. appname = argv[0];
  315. }
  316. void
  317. AnyOption::useFileName( const char *_filename )
  318. {
  319. filename = _filename;
  320. file_set = true;
  321. }
  322. /*
  323. * set methods for options
  324. */
  325. void
  326. AnyOption::setCommandOption( const char *opt )
  327. {
  328. addOption( opt , COMMAND_OPT );
  329. g_value_counter++;
  330. }
  331. void
  332. AnyOption::setCommandOption( char opt )
  333. {
  334. addOption( opt , COMMAND_OPT );
  335. g_value_counter++;
  336. }
  337. void
  338. AnyOption::setCommandOption( const char *opt , char optchar )
  339. {
  340. addOption( opt , COMMAND_OPT );
  341. addOption( optchar , COMMAND_OPT );
  342. g_value_counter++;
  343. }
  344. void
  345. AnyOption::setCommandFlag( const char *opt )
  346. {
  347. addOption( opt , COMMAND_FLAG );
  348. g_value_counter++;
  349. }
  350. void
  351. AnyOption::setCommandFlag( char opt )
  352. {
  353. addOption( opt , COMMAND_FLAG );
  354. g_value_counter++;
  355. }
  356. void
  357. AnyOption::setCommandFlag( const char *opt , char optchar )
  358. {
  359. addOption( opt , COMMAND_FLAG );
  360. addOption( optchar , COMMAND_FLAG );
  361. g_value_counter++;
  362. }
  363. void
  364. AnyOption::setFileOption( const char *opt )
  365. {
  366. addOption( opt , FILE_OPT );
  367. g_value_counter++;
  368. }
  369. void
  370. AnyOption::setFileOption( char opt )
  371. {
  372. addOption( opt , FILE_OPT );
  373. g_value_counter++;
  374. }
  375. void
  376. AnyOption::setFileOption( const char *opt , char optchar )
  377. {
  378. addOption( opt , FILE_OPT );
  379. addOption( optchar, FILE_OPT );
  380. g_value_counter++;
  381. }
  382. void
  383. AnyOption::setFileFlag( const char *opt )
  384. {
  385. addOption( opt , FILE_FLAG );
  386. g_value_counter++;
  387. }
  388. void
  389. AnyOption::setFileFlag( char opt )
  390. {
  391. addOption( opt , FILE_FLAG );
  392. g_value_counter++;
  393. }
  394. void
  395. AnyOption::setFileFlag( const char *opt , char optchar )
  396. {
  397. addOption( opt , FILE_FLAG );
  398. addOption( optchar , FILE_FLAG );
  399. g_value_counter++;
  400. }
  401. void
  402. AnyOption::setOption( const char *opt )
  403. {
  404. addOption( opt , COMMON_OPT );
  405. g_value_counter++;
  406. }
  407. void
  408. AnyOption::setOption( char opt )
  409. {
  410. addOption( opt , COMMON_OPT );
  411. g_value_counter++;
  412. }
  413. void
  414. AnyOption::setOption( const char *opt , char optchar )
  415. {
  416. addOption( opt , COMMON_OPT );
  417. addOption( optchar , COMMON_OPT );
  418. g_value_counter++;
  419. }
  420. void
  421. AnyOption::setFlag( const char *opt )
  422. {
  423. addOption( opt , COMMON_FLAG );
  424. g_value_counter++;
  425. }
  426. void
  427. AnyOption::setFlag( const char opt )
  428. {
  429. addOption( opt , COMMON_FLAG );
  430. g_value_counter++;
  431. }
  432. void
  433. AnyOption::setFlag( const char *opt , char optchar )
  434. {
  435. addOption( opt , COMMON_FLAG );
  436. addOption( optchar , COMMON_FLAG );
  437. g_value_counter++;
  438. }
  439. void
  440. AnyOption::addOption( const char *opt, int type )
  441. {
  442. if( option_counter >= max_options ){
  443. if( doubleOptStorage() == false ){
  444. addOptionError( opt );
  445. return;
  446. }
  447. }
  448. options[ option_counter ] = opt ;
  449. optiontype[ option_counter ] = type ;
  450. optionindex[ option_counter ] = g_value_counter;
  451. option_counter++;
  452. }
  453. void
  454. AnyOption::addOption( char opt, int type )
  455. {
  456. if( !POSIX() ){
  457. printVerbose("Ignoring the option character \"");
  458. printVerbose( opt );
  459. printVerbose( "\" ( POSIX options are turned off )" );
  460. printVerbose();
  461. return;
  462. }
  463. if( optchar_counter >= max_char_options ){
  464. if( doubleCharStorage() == false ){
  465. addOptionError( opt );
  466. return;
  467. }
  468. }
  469. optionchars[ optchar_counter ] = opt ;
  470. optchartype[ optchar_counter ] = type ;
  471. optcharindex[ optchar_counter ] = g_value_counter;
  472. optchar_counter++;
  473. }
  474. void
  475. AnyOption::addOptionError( const char *opt )
  476. {
  477. cout << endl ;
  478. cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
  479. cout << "While adding the option : \""<< opt << "\"" << endl;
  480. cout << "Exiting." << endl ;
  481. cout << endl ;
  482. exit(0);
  483. }
  484. void
  485. AnyOption::addOptionError( char opt )
  486. {
  487. cout << endl ;
  488. cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
  489. cout << "While adding the option: \""<< opt << "\"" << endl;
  490. cout << "Exiting." << endl ;
  491. cout << endl ;
  492. exit(0);
  493. }
  494. void
  495. AnyOption::processOptions()
  496. {
  497. if( ! valueStoreOK() )
  498. return;
  499. }
  500. void
  501. AnyOption::processCommandArgs(int max_args)
  502. {
  503. max_legal_args = max_args;
  504. processCommandArgs();
  505. }
  506. void
  507. AnyOption::processCommandArgs( int _argc, char **_argv, int max_args )
  508. {
  509. max_legal_args = max_args;
  510. processCommandArgs( _argc, _argv );
  511. }
  512. void
  513. AnyOption::processCommandArgs( int _argc, char **_argv )
  514. {
  515. useCommandArgs( _argc, _argv );
  516. processCommandArgs();
  517. }
  518. void
  519. AnyOption::processCommandArgs()
  520. {
  521. if( ! ( valueStoreOK() && CommandSet() ) )
  522. return;
  523. if( max_legal_args == 0 )
  524. max_legal_args = argc;
  525. new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) );
  526. for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */
  527. if( argv[i][0] == long_opt_prefix[0] &&
  528. argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */
  529. int match_at = parseGNU( argv[i]+2 ); /* skip -- */
  530. if( match_at >= 0 && i < argc-1 ) /* found match */
  531. setValue( options[match_at] , argv[++i] );
  532. }else if( argv[i][0] == opt_prefix_char ) { /* POSIX char */
  533. if( POSIX() ){
  534. char ch = parsePOSIX( argv[i]+1 );/* skip - */
  535. if( ch != '0' && i < argc-1 ) /* matching char */
  536. setValue( ch , argv[++i] );
  537. } else { /* treat it as GNU option with a - */
  538. int match_at = parseGNU( argv[i]+1 ); /* skip - */
  539. if( match_at >= 0 && i < argc-1 ) /* found match */
  540. setValue( options[match_at] , argv[++i] );
  541. }
  542. }else { /* not option but an argument keep index */
  543. if( new_argc < max_legal_args ){
  544. new_argv[ new_argc ] = i ;
  545. new_argc++;
  546. }else{ /* ignore extra arguments */
  547. printVerbose( "Ignoring extra argument: " );
  548. printVerbose( argv[i] );
  549. printVerbose( );
  550. printUsage();
  551. }
  552. printVerbose( "Unknown command argument option : " );
  553. printVerbose( argv[i] );
  554. printVerbose( );
  555. printUsage();
  556. }
  557. }
  558. }
  559. char
  560. AnyOption::parsePOSIX( char* arg )
  561. {
  562. for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
  563. char ch = arg[i] ;
  564. if( matchChar(ch) ) { /* keep matching flags till an option */
  565. /*if last char argv[++i] is the value */
  566. if( i == strlen(arg)-1 ){
  567. return ch;
  568. }else{/* else the rest of arg is the value */
  569. i++; /* skip any '=' and ' ' */
  570. while( arg[i] == whitespace
  571. || arg[i] == equalsign )
  572. i++;
  573. setValue( ch , arg+i );
  574. return '0';
  575. }
  576. }
  577. }
  578. printVerbose( "Unknown command argument option : " );
  579. printVerbose( arg );
  580. printVerbose( );
  581. printUsage();
  582. return '0';
  583. }
  584. int
  585. AnyOption::parseGNU( char *arg )
  586. {
  587. int split_at = 0;
  588. /* if has a '=' sign get value */
  589. for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
  590. if(arg[i] == equalsign ){
  591. split_at = i ; /* store index */
  592. i = strlen(arg); /* get out of loop */
  593. }
  594. }
  595. if( split_at > 0 ){ /* it is an option value pair */
  596. char* tmp = (char*) malloc( (split_at+1)*sizeof(char) );
  597. for( int i = 0 ; i < split_at ; i++ )
  598. tmp[i] = arg[i];
  599. tmp[split_at] = '\0';
  600. if ( matchOpt( tmp ) >= 0 ){
  601. setValue( options[matchOpt(tmp)] , arg+split_at+1 );
  602. free (tmp);
  603. }else{
  604. printVerbose( "Unknown command argument option : " );
  605. printVerbose( arg );
  606. printVerbose( );
  607. printUsage();
  608. free (tmp);
  609. return -1;
  610. }
  611. }else{ /* regular options with no '=' sign */
  612. return matchOpt(arg);
  613. }
  614. return -1;
  615. }
  616. int
  617. AnyOption::matchOpt( char *opt )
  618. {
  619. for( int i = 0 ; i < option_counter ; i++ ){
  620. if( strcmp( options[i], opt ) == 0 ){
  621. if( optiontype[i] == COMMON_OPT ||
  622. optiontype[i] == COMMAND_OPT )
  623. { /* found option return index */
  624. return i;
  625. }else if( optiontype[i] == COMMON_FLAG ||
  626. optiontype[i] == COMMAND_FLAG )
  627. { /* found flag, set it */
  628. setFlagOn( opt );
  629. return -1;
  630. }
  631. }
  632. }
  633. printVerbose( "Unknown command argument option : " );
  634. printVerbose( opt ) ;
  635. printVerbose( );
  636. printUsage();
  637. return -1;
  638. }
  639. bool
  640. AnyOption::matchChar( char c )
  641. {
  642. for( int i = 0 ; i < optchar_counter ; i++ ){
  643. if( optionchars[i] == c ) { /* found match */
  644. if(optchartype[i] == COMMON_OPT ||
  645. optchartype[i] == COMMAND_OPT )
  646. { /* an option store and stop scanning */
  647. return true;
  648. }else if( optchartype[i] == COMMON_FLAG ||
  649. optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */
  650. setFlagOn( c );
  651. return false;
  652. }
  653. }
  654. }
  655. printVerbose( "Unknown command argument option : " );
  656. printVerbose( c ) ;
  657. printVerbose( );
  658. printUsage();
  659. return false;
  660. }
  661. bool
  662. AnyOption::valueStoreOK( )
  663. {
  664. int size= 0;
  665. if( !set ){
  666. if( g_value_counter > 0 ){
  667. size = g_value_counter * sizeof(char*);
  668. values = (char**)malloc( size );
  669. for( int i = 0 ; i < g_value_counter ; i++)
  670. values[i] = NULL;
  671. set = true;
  672. }
  673. }
  674. return set;
  675. }
  676. /*
  677. * public get methods
  678. */
  679. char*
  680. AnyOption::getValue( const char *option )
  681. {
  682. if( !valueStoreOK() )
  683. return NULL;
  684. for( int i = 0 ; i < option_counter ; i++ ){
  685. if( strcmp( options[i], option ) == 0 )
  686. return values[ optionindex[i] ];
  687. }
  688. return NULL;
  689. }
  690. bool
  691. AnyOption::getFlag( const char *option )
  692. {
  693. if( !valueStoreOK() )
  694. return false;
  695. for( int i = 0 ; i < option_counter ; i++ ){
  696. if( strcmp( options[i], option ) == 0 )
  697. return findFlag( values[ optionindex[i] ] );
  698. }
  699. return false;
  700. }
  701. char*
  702. AnyOption::getValue( char option )
  703. {
  704. if( !valueStoreOK() )
  705. return NULL;
  706. for( int i = 0 ; i < optchar_counter ; i++ ){
  707. if( optionchars[i] == option )
  708. return values[ optcharindex[i] ];
  709. }
  710. return NULL;
  711. }
  712. bool
  713. AnyOption::getFlag( char option )
  714. {
  715. if( !valueStoreOK() )
  716. return false;
  717. for( int i = 0 ; i < optchar_counter ; i++ ){
  718. if( optionchars[i] == option )
  719. return findFlag( values[ optcharindex[i] ] ) ;
  720. }
  721. return false;
  722. }
  723. bool
  724. AnyOption::findFlag( char* val )
  725. {
  726. if( val == NULL )
  727. return false;
  728. if( strcmp( TRUE_FLAG , val ) == 0 )
  729. return true;
  730. return false;
  731. }
  732. /*
  733. * private set methods
  734. */
  735. bool
  736. AnyOption::setValue( const char *option , char *value )
  737. {
  738. if( !valueStoreOK() )
  739. return false;
  740. for( int i = 0 ; i < option_counter ; i++ ){
  741. if( strcmp( options[i], option ) == 0 ){
  742. values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
  743. strcpy( values[ optionindex[i] ], value );
  744. return true;
  745. }
  746. }
  747. return false;
  748. }
  749. bool
  750. AnyOption::setFlagOn( const char *option )
  751. {
  752. if( !valueStoreOK() )
  753. return false;
  754. for( int i = 0 ; i < option_counter ; i++ ){
  755. if( strcmp( options[i], option ) == 0 ){
  756. values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
  757. strcpy( values[ optionindex[i] ] , TRUE_FLAG );
  758. return true;
  759. }
  760. }
  761. return false;
  762. }
  763. bool
  764. AnyOption::setValue( char option , char *value )
  765. {
  766. if( !valueStoreOK() )
  767. return false;
  768. for( int i = 0 ; i < optchar_counter ; i++ ){
  769. if( optionchars[i] == option ){
  770. values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
  771. strcpy( values[ optcharindex[i] ], value );
  772. return true;
  773. }
  774. }
  775. return false;
  776. }
  777. bool
  778. AnyOption::setFlagOn( char option )
  779. {
  780. if( !valueStoreOK() )
  781. return false;
  782. for( int i = 0 ; i < optchar_counter ; i++ ){
  783. if( optionchars[i] == option ){
  784. values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
  785. strcpy( values[ optcharindex[i] ] , TRUE_FLAG );
  786. return true;
  787. }
  788. }
  789. return false;
  790. }
  791. int
  792. AnyOption::getArgc( )
  793. {
  794. return new_argc;
  795. }
  796. char*
  797. AnyOption::getArgv( int index )
  798. {
  799. if( index < new_argc ){
  800. return ( argv[ new_argv[ index ] ] );
  801. }
  802. return NULL;
  803. }
  804. /* dotfile sub routines */
  805. bool
  806. AnyOption::processFile()
  807. {
  808. if( ! (valueStoreOK() && FileSet()) )
  809. return false;
  810. return ( consumeFile(readFile()) );
  811. }
  812. bool
  813. AnyOption::processFile( const char *filename )
  814. {
  815. useFileName(filename );
  816. return ( processFile() );
  817. }
  818. char*
  819. AnyOption::readFile()
  820. {
  821. return ( readFile(filename) );
  822. }
  823. /*
  824. * read the file contents to a character buffer
  825. */
  826. char*
  827. AnyOption::readFile( const char* fname )
  828. {
  829. int length;
  830. char *buffer;
  831. ifstream is;
  832. is.open ( fname , ifstream::in );
  833. if( ! is.good() ){
  834. is.close();
  835. return NULL;
  836. }
  837. is.seekg (0, ios::end);
  838. length = is.tellg();
  839. is.seekg (0, ios::beg);
  840. buffer = (char*) malloc(length*sizeof(char));
  841. is.read (buffer,length);
  842. is.close();
  843. return buffer;
  844. }
  845. /*
  846. * scans a char* buffer for lines that does not
  847. * start with the specified comment character.
  848. */
  849. bool
  850. AnyOption::consumeFile( char *buffer )
  851. {
  852. if( buffer == NULL )
  853. return false;
  854. char *cursor = buffer;/* preserve the ptr */
  855. char *pline = NULL ;
  856. int linelength = 0;
  857. bool newline = true;
  858. for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){
  859. if( *cursor == endofline ) { /* end of line */
  860. if( pline != NULL ) /* valid line */
  861. processLine( pline, linelength );
  862. pline = NULL;
  863. newline = true;
  864. }else if( newline ){ /* start of line */
  865. newline = false;
  866. if( (*cursor != comment ) ){ /* not a comment */
  867. pline = cursor ;
  868. linelength = 0 ;
  869. }
  870. }
  871. cursor++; /* keep moving */
  872. linelength++;
  873. }
  874. free (buffer);
  875. return true;
  876. }
  877. /*
  878. * find a valid type value pair separated by a delimiter
  879. * character and pass it to valuePairs()
  880. * any line which is not valid will be considered a value
  881. * and will get passed on to justValue()
  882. *
  883. * assuming delimiter is ':' the behaviour will be,
  884. *
  885. * width:10 - valid pair valuePairs( width, 10 );
  886. * width : 10 - valid pair valuepairs( width, 10 );
  887. *
  888. * :::: - not valid
  889. * width - not valid
  890. * :10 - not valid
  891. * width: - not valid
  892. * :: - not valid
  893. * : - not valid
  894. *
  895. */
  896. void
  897. AnyOption::processLine( char *theline, int length )
  898. {
  899. bool found = false;
  900. char *pline = (char*) malloc( (length+1)*sizeof(char) );
  901. for( int i = 0 ; i < length ; i ++ )
  902. pline[i]= *(theline++);
  903. pline[length] = nullterminate;
  904. char *cursor = pline ; /* preserve the ptr */
  905. if( *cursor == delimiter || *(cursor+length-1) == delimiter ){
  906. justValue( pline );/* line with start/end delimiter */
  907. }else{
  908. for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */
  909. if( *cursor == delimiter ){
  910. *(cursor-1) = nullterminate; /* two strings */
  911. found = true;
  912. valuePairs( pline , cursor+1 );
  913. }
  914. cursor++;
  915. }
  916. cursor++;
  917. if( !found ) /* not a pair */
  918. justValue( pline );
  919. }
  920. free (pline);
  921. }
  922. /*
  923. * removes trailing and preceeding whitespaces from a string
  924. */
  925. char*
  926. AnyOption::chomp( char *str )
  927. {
  928. while( *str == whitespace )
  929. str++;
  930. char *end = str+strlen(str)-1;
  931. while( *end == whitespace )
  932. end--;
  933. *(end+1) = nullterminate;
  934. return str;
  935. }
  936. void
  937. AnyOption::valuePairs( char *type, char *value )
  938. {
  939. if ( strlen(chomp(type)) == 1 ){ /* this is a char option */
  940. for( int i = 0 ; i < optchar_counter ; i++ ){
  941. if( optionchars[i] == type[0] ){ /* match */
  942. if( optchartype[i] == COMMON_OPT ||
  943. optchartype[i] == FILE_OPT )
  944. {
  945. setValue( type[0] , chomp(value) );
  946. return;
  947. }
  948. }
  949. }
  950. }
  951. /* if no char options matched */
  952. for( int i = 0 ; i < option_counter ; i++ ){
  953. if( strcmp( options[i], type ) == 0 ){ /* match */
  954. if( optiontype[i] == COMMON_OPT ||
  955. optiontype[i] == FILE_OPT )
  956. {
  957. setValue( type , chomp(value) );
  958. return;
  959. }
  960. }
  961. }
  962. printVerbose( "Unknown option in resourcefile : " );
  963. printVerbose( type );
  964. printVerbose( );
  965. }
  966. void
  967. AnyOption::justValue( char *type )
  968. {
  969. if ( strlen(chomp(type)) == 1 ){ /* this is a char option */
  970. for( int i = 0 ; i < optchar_counter ; i++ ){
  971. if( optionchars[i] == type[0] ){ /* match */
  972. if( optchartype[i] == COMMON_FLAG ||
  973. optchartype[i] == FILE_FLAG )
  974. {
  975. setFlagOn( type[0] );
  976. return;
  977. }
  978. }
  979. }
  980. }
  981. /* if no char options matched */
  982. for( int i = 0 ; i < option_counter ; i++ ){
  983. if( strcmp( options[i], type ) == 0 ){ /* match */
  984. if( optiontype[i] == COMMON_FLAG ||
  985. optiontype[i] == FILE_FLAG )
  986. {
  987. setFlagOn( type );
  988. return;
  989. }
  990. }
  991. }
  992. printVerbose( "Unknown option in resourcefile : " );
  993. printVerbose( type );
  994. printVerbose( );
  995. }
  996. /*
  997. * usage and help
  998. */
  999. bool
  1000. AnyOption::USAGE()
  1001. {
  1002. return print_usage;
  1003. }
  1004. void
  1005. AnyOption::noUsage()
  1006. {
  1007. print_usage = false;
  1008. }
  1009. void
  1010. AnyOption::printUsage()
  1011. {
  1012. if( !USAGE() )
  1013. return;
  1014. if( once ) {
  1015. once = false ;
  1016. cout << endl ;
  1017. for( int i = 0 ; i < usage_lines ; i++ )
  1018. cout << usage[i] << endl ;
  1019. cout << endl ;
  1020. }
  1021. }
  1022. void
  1023. AnyOption::addUsage( const char *line )
  1024. {
  1025. if( usage_lines >= max_usage_lines ){
  1026. if( doubleUsageStorage() == false ){
  1027. addUsageError( line );
  1028. exit(1);
  1029. }
  1030. }
  1031. usage[ usage_lines ] = line ;
  1032. usage_lines++;
  1033. }
  1034. void
  1035. AnyOption::addUsageError( const char *line )
  1036. {
  1037. cout << endl ;
  1038. cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
  1039. cout << "While adding the usage/help : \""<< line << "\"" << endl;
  1040. cout << "Exiting." << endl ;
  1041. cout << endl ;
  1042. exit(0);
  1043. }