BRAT 2.4.5
Class index
Full class index
brahmlib
BRAHMS
ROOT page
//
// Command line option manager
//

//
// $Id: BrAppOptionManager.cxx,v 1.8 2002/04/23 15:18:30 hagel Exp $
// $Author: hagel $
// $Date: 2002/04/23 15:18:30 $
// $Copyright: BRAHMS Collaboration 2000
// 
#include <cstring>
#include <cstdlib>
#include <BrIostream.h>
#include <TString.h>
#include <TObject.h>
#include <TObjArray.h>
#include <THashTable.h>
#include <THashList.h>
#include <TSystem.h>
#include <BrAppOption.h>
#include <BrAppOptionManager.h>
#ifdef BR_USE_EXCEPTIONS    
#undef BR_USE_EXCEPTIONS
#endif
#ifdef BR_USE_EXCEPTIONS    
#include <BrException.h>
#endif

//_____________________________________________________________________
ClassImp(BrAppOptionManager); // Options class

BrAppOptionManager* BrAppOptionManager::fgInstance = 0;

//_____________________________________________________________________
 BrAppOptionManager::BrAppOptionManager() 
{
  // Constructor. 
  // First two arguments are the major and version of this
  // application. third is the version string, and fourth is the help
  // string. 

  // Set the default values 
  SetHelp();
  SetVersion();
  fArgv      = 0;
  fArgc      = 0;
  fIsOk      = kTRUE;
  fHasParsed = kFALSE;
  // initialize internal table
  fTable         = new THashList(10);

  // AddOption(fHelpOption);
  // AddOption(fVersionOption);
}

//_____________________________________________________________________
 BrAppOptionManager* BrAppOptionManager::Instance() 
{
  if (!fgInstance) {
    fgInstance = new BrAppOptionManager;
    fgInstance->AddHelpVersion();
  }
  return fgInstance;
}

//_____________________________________________________________________
 void BrAppOptionManager::AddHelpVersion() 
{
  // Set the two default otptions
  fHelpOption    = new BrAppBoolOption('h', "help", 
				       "Show this help",kFALSE);
  fVersionOption = new BrAppBoolOption('V', "version", 
				       "Version number",kFALSE);
}

//_____________________________________________________________________
 void BrAppOptionManager::AddOption(BrAppOption* option, Bool_t internal)
{
  // Add an option to the manager
  if (!internal) {
    Warning("AddOption", 
	    "options now add them selves to the manager, "
	    "please remove the message BrAppOptionManager::AddOption "
	    "from your script or program.  This method will soon "
	    "become private, and should not be used."); 
    return;
  }
  
  fTable->Add(option);
}

//_____________________________________________________________________
 void BrAppOptionManager::SetCommandLine(Int_t& argc, Char_t** argv)
{
  // 
  if (fArgv) {
    Error("SetCommandLine", 
	  "you can only set the command line once");
    return;
  }
  
  fArgc = &argc; 
  fArgv = argv; 
}

//_____________________________________________________________________
 void BrAppOptionManager::SetHelp(const Char_t* helpString) 
{
  // Set the help string 
  // Set help string
  if (!helpString)
    fHelpString = "n";
  else 
    fHelpString = helpString;
}

//_____________________________________________________________________
 void BrAppOptionManager::SetVersion(Int_t major, Int_t minor, 
			       const Char_t* versionString) 
{
  // Set the help string
  fMajorVersion = major;
  fMinorVersion = minor;  
  if (versionString)
    fVersionString = versionString;
  else 
    fVersionString = "";
}

  
//_____________________________________________________________________
 BrAppOption* BrAppOptionManager::GetOption(Char_t option) 
{
  // Get the BrAppOption with short name 'option'
  TIter next(fTable);
  BrAppOption* opt;
  while ((opt = (BrAppOption*)next())) {
    if (opt->GetShortName() == option)
      return opt;
  }
  return 0;
}

//_____________________________________________________________________
 BrAppOption* BrAppOptionManager::GetOption(Char_t* option) 
{
  // Get the BrAppOption with long name "option"
  // TIter next(fTable);
  // BrAppOption* opt;
  // while ((opt = (BrAppOption*)next())) {
  //   if (strcmp(opt->GetLongName(),option) == 0)
  //     return opt;
  // }
  return (BrAppOption*)fTable->FindObject(option);
}

//_____________________________________________________________________
 void BrAppOptionManager::SetOptionValue(Char_t  option, 
					Char_t* value)
{
  // Set the value of the option with short name 'option'
  BrAppOption* opt = GetOption(option);
  if (!opt) {
#ifdef BR_USE_EXCEPTIONS    
    throw new BrError("BrAppOptionManager::SetOptionValue",
		      "No such option: -%c", option);
#else 
    Error("SetOptionValue", "No such option: -%c", option);
    return;
#endif
  }
  
  opt->SetValue(value);
}

//_____________________________________________________________________
 void BrAppOptionManager::SetOptionValue(Char_t* option, 
					Char_t* value)
{
  // Set the value of the option with long name "option"
  BrAppOption* opt = GetOption(option);
  if (!opt) {
#ifdef BR_USE_EXCEPTIONS    
    throw new BrError("BrAppOptionManager::SetOptionValue",
		      "No such option: --%s", option);
#else 
    Error("SetOptionValue", "No such option: -%c", option);
    return;
#endif
  }

  opt->SetValue(value);
}

//_____________________________________________________________________
 Bool_t BrAppOptionManager::ProcessCommandLine() 
{
  // Process command line parameters. If this class was compiled with
  // exceptions enabled, then a BrException is thrown in case of
  // errors. If it wasn't compiled with exceptions enabled, it returns
  // kFALSE in case of errors. 
  if (!fArgc) {
    Error("ProcessCommandLine", "command line not set");
    return kFALSE;
  }
  
  fProgName = gSystem->BaseName(fArgv[0]);

  // Sort hash list 
  fTable->Sort();

  // Assume success 
  fIsOk = kTRUE;

  // Flag the manager as having done it's stuff
  fHasParsed = kFALSE;

  // Needed for Micros**t Visual C++ non-ANSI behaviour - God that is
  // soooo annoying 
  Int_t i = 0;
  Int_t j = 0;
  for (i = 1; i < *fArgc; i++) {

    // See if we got an option
    if (fArgv[i][0] == '-') {
      // See if we got a long option 
      Bool_t killNext = kFALSE;
      if (!fArgv[i][1] || fArgv[i][1] == '0')
	continue;
      if (fArgv[i][1] == '-') {
	if (!ProcessLongOption(fArgv[i]+2))
	  fIsOk = kFALSE;
      }
      else {
	Int_t len = strlen(fArgv[i]);
	for (Int_t j = 1; j < len; j++) {
	  // if we got a short option, get the option
	  if (!ProcessShortOption(fArgv[i][j],killNext, fArgv[i+1])) {
	    fIsOk = kFALSE;
	    break;
	  }	  
	  if (killNext) {
	    if (fArgv[i][j+1] != '0') {	      
#ifdef BR_USE_EXCEPTIONS    
	      throw new
		BrError("BrAppOptionManager::ProcessCommandLine",
			"Option -%c need an argument. Try\n\t%s --help",
			fArgv[i][j],fProgName.Data());
#else 
	      Error("ProcessCommandLine",
		    "short options can not follow option -%c that "
		    "need an argument.", fArgv[i][j]);
	      fIsOk = kFALSE;
	      break;
#endif
	    } // if (fArgv[i][j+1] != '\0')
	    break;
	  } // if (killNext)
	} // for (j = 1; j < len; j++)	
      } // if (fArgv[i][1] == '-') ... else 
      
      // Set the command line argument to zero, so that it's ignored
      // hereafter 
      fArgv[i] = 0;
      if (killNext)
	fArgv[++i] = 0;
    } // if (fArgv[i][0] == '-')
    if (!fIsOk) 
      break; 

  } // for (i = 1; i < *fArgc; i++)
  
  
  for (i = 0; i < *fArgc; i++) {
    if (fArgv[i])
      fArgv[j++] = fArgv[i];
  }
  
  
  
  *fArgc = j;
  fArgv[*fArgc] = 0;
  
  return fIsOk;
}

//_____________________________________________________________________
 Bool_t BrAppOptionManager::ProcessLongOption(Char_t* argument) 
{
  // Deal  with long options of the form "--<option>=<value>". For
  // Boolean typed options, the form is "--<option>" 

  // Put the full long argument into a string object. 
  TString* arg = new TString(argument);
  if (!arg) {
#ifdef BR_USE_EXCEPTIONS    
    throw new BrError("BrAppOptionManager::ProcessLongOption",
		     "Unknown option --%s. Try\n\t%s --help",  
		      argument, fProgName.Data()); 
#else 
    Error("ProcessLongOption",
	  "Unknown option --%s. Try\n\t%s --help",  
	  argument, fProgName.Data()); 
    return kFALSE;
#endif
  }
  
  // Find the equal sign 
  Ssiz_t eqPos = arg->Index("=");

  // Get the option name 
  TString* opt = 0;
  if (eqPos == kNPOS)
    opt = arg;
  else 
    opt = new TString(arg->Data(),eqPos);

  if (!opt || opt->IsNull()) {
#ifdef BR_USE_EXCEPTIONS    
    throw new BrError("BrAppOptionManager::ProcessLongOption",
		     "Invalid option --%s. Try\n\t%s --help", 
		     arg->Data(), fProgName.Data()); 
#else
    Error("ProcessLongOption",
	  "Invalid option --%s. Try\n\t%s --help", 
	  arg->Data(), fProgName.Data()); 
    return kFALSE;
#endif 
  }
  
  // Get the option 
  BrAppOption* option = GetOption((Char_t*)opt->Data());
  if (!option) {
#ifdef BR_USE_EXCEPTIONS    
    throw new BrError("BrAppOptionManager::ProcessLongOption",
		      "Unknown option --%s. Try\n\t%s --help", 
		      opt->Data(), fProgName.Data()); 
#else 
    Error("ProcessLongOption",
	  "Unknown option --%s. Try\n\t%s --help", 
	  arg->Data(), fProgName.Data()); 
    return kFALSE;
#endif
  }
  
  // Figure out the value passed 
  if (option->NeedValue() && eqPos == kNPOS)  {
#ifdef BR_USE_EXCEPTIONS    
    throw new BrError("BrAppOptionManager::ProcessLongOption",
		      "Option --%s need an argument. Try\n\t%s --help",
		      opt->Data(), fProgName.Data());
#else 
    Error("ProcessLongOption",
	  "Option --%s need an argument. Try\n\t%s --help",
	  opt->Data(), fProgName.Data());
    return kFALSE;
#endif
  }
  
  TString* val = new TString((*arg)(eqPos+1,256));

  // Finally, set the option to value. 
  return option->SetValue((Char_t*)val->Data());
}

//_____________________________________________________________________
 Bool_t BrAppOptionManager::ProcessShortOption(Char_t  option,
					      Bool_t& killNext,
					      Char_t* value) 
{
  // Process short options. These are of the form "-<option> <val>" or
  // in the case of boolean flags "-<option>"

  // Get the option 
  BrAppOption* opt = GetOption(option);
  if (!opt) {
#ifdef BR_USE_EXCEPTIONS
    throw new BrWarning("BrAppOptionManager::ProcessShortOption",
			"Unknown option %c. Try\n\t%s --help", 
			option, fProgName.Data());
#else 
    Error("ProcessShortOption",
	  "Unknown option %c. Try\n\t%s --help", 
	  option, fProgName.Data());
    return kFALSE;
#endif 
  }
  if (!opt->SetValue(value))
    return kFALSE;

  if (opt->NeedValue()) {
    // We need to remove the next argument
    killNext = kTRUE;
  }
  
  return kTRUE;
}

//_____________________________________________________________________
 void BrAppOptionManager::Print(Option_t* option="") const 
{
  // Print the list of options 
  TIter next(fTable);
  BrAppOption* opt;

  while ((opt = (BrAppOption*)next()))
    opt->Print();
}

//_____________________________________________________________________
 Bool_t BrAppOptionManager::ShowHelp(void)
{
  // Show the help screen if either "-h" or "--help" was on the
  // command line. Return true if so, otherwise false 
 
  if (!fHelpOption->operator Bool_t())
    return kFALSE;

  cout << "Usage: " << fProgName.Data() << " [options] " 
       << fHelpString.Data() << endl
       << "Options:" << endl;
  
  TIter next(fTable);
  BrAppOption* opt;

  cout.setf(ios::left);
  while ((opt = (BrAppOption*)next()))
    opt->Print();

  return kTRUE;  
}

//_____________________________________________________________________
 Bool_t BrAppOptionManager::ShowVersion(void)
{
  // Show the version screen if either "-V" or "--version" was on the 
  // command line. Return true if so, otherwise false 
 
  if (!fVersionOption->operator Bool_t())
    return kFALSE;
  
  cout << fProgName.Data() 
       << " Version " << fMajorVersion 
       << "." << fMinorVersion  << " " 
       << fVersionString.Data() << endl;
  
  return kTRUE;
}
  
// $Log: BrAppOptionManager.cxx,v $
// Revision 1.8  2002/04/23 15:18:30  hagel
// Add return to BrAppStringOption::SetValue
//
// Revision 1.7  2001/12/14 15:28:19  cholm
// BrAppOption sublcasses now adds them selves to BrAppOptionManager
// automatically.   Also, the int, float, and string option class can now
// hold multiple values.  It's all fairly well documented in 'The Guide'.
//
// Revision 1.6  2001/08/21 14:25:24  cholm
// Added member fHasParsed, so that we can check if we've parsed the
// commandline.  Not really needed now, but I left it in anyway. No real
// harm in that.
//
// Revision 1.5  2001/07/30 19:28:29  cholm
// Made a fix that allows scripts using no options to perform anyway.
//
// Revision 1.4  2001/07/29 15:08:00  cholm
// Fixed problem with negative numbers parsed to a short option.
//
// Revision 1.3  2001/07/29 14:39:40  cholm
// Removed Djamel's "fix" which made it impossible to use long options.
// That was very VERY bad, since the CRS software ONLY uses the long form
// of command line options.  I'm looking into the problem he reported
// now.  In the mean time, do not use BRAT-2-0-16 on the farm since it'll
// not work!
//
// Revision 1.2  2001/07/27 10:20:23  ouerdane
// Added a check in ProcessCommandLine in the case you want to pass negative
// numbers (eg. -p -4.5) since so far, it was confused with an option because
// of the negative sign.
//
// Revision 1.1.1.1  2001/06/21 14:55:15  hagel
// Initial revision of brat2
//
// Revision 1.4  2001/03/07 12:15:41  cholm
// * Defined standard BrModule methods in BrIOModule.
// * Add the (simple) class BrHistIOModule.
// * BrAppOptionManager and BrAppOption classes changed to not use
//   BrExceptions.
// * Added the method Int_t BrMainModule::Main() to do EVERYTHING.
// * Made the method BrModule::Info() const obsolete in favour of
//   BrModule::Print(Option_t* option="B") const. Impact on other classes.
//
// Revision 1.3  2000/09/04 13:38:33  videbaek
// Use BrIostream.h to facilitate different iostream conventions.
//
// Revision 1.2  2000/06/13 17:12:21  alv
// ProcessCommandLine
//   Added argv[argc]=0
//
// Revision 1.1  2000/04/06 20:17:43  cholm
// Added the classes BrAppOption, BrAppOptionManager, and
// BrDetectorList. The first two are for command line processing,
// the third for easy detector list, can be used for many purposes.
//
//

This page automatically generated by script docBrat by Christian Holm

Copyright ; 2002 BRAHMS Collaboration <brahmlib@rcf.rhic.bnl.gov>
Last Update on by

Validate HTML
Validate CSS