400 lines
11 KiB
C++
400 lines
11 KiB
C++
//
|
|
// ********************************************************************
|
|
// * License and Disclaimer *
|
|
// * *
|
|
// * The Geant4 software is copyright of the Copyright Holders of *
|
|
// * the Geant4 Collaboration. It is provided under the terms and *
|
|
// * conditions of the Geant4 Software License, included in the file *
|
|
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
|
// * include a list of copyright holders. *
|
|
// * *
|
|
// * Neither the authors of this software system, nor their employing *
|
|
// * institutes,nor the agencies providing financial support for this *
|
|
// * work make any representation or warranty, express or implied, *
|
|
// * regarding this software system or assume any liability for its *
|
|
// * use. Please see the license in the file LICENSE and URL above *
|
|
// * for the full disclaimer and the limitation of liability. *
|
|
// * *
|
|
// * This code implementation is the result of the scientific and *
|
|
// * technical work of the GEANT4 collaboration. *
|
|
// * By using, copying, modifying or distributing the software (or *
|
|
// * any work based on the software) you agree to acknowledge its *
|
|
// * use in resulting scientific publications, and indicate your *
|
|
// * acceptance of all terms of the Geant4 Software license. *
|
|
// ********************************************************************
|
|
//
|
|
// This example is provided by the Geant4-DNA collaboration
|
|
// Any report or published results obtained using the Geant4-DNA software
|
|
// shall cite the following Geant4-DNA collaboration publication:
|
|
// Med. Phys. 37 (2010) 4692-4708
|
|
// J. Comput. Phys. 274 (2014) 841-882
|
|
// The Geant4-DNA web site is available at http://geant4-dna.org
|
|
//
|
|
// Author: Mathieu Karamitros
|
|
//
|
|
//
|
|
/// \file CommandLineParser.cc
|
|
/// \brief Implementation of the CommandLineParser class
|
|
|
|
#include <iomanip>
|
|
#include "CommandLineParser.hh"
|
|
|
|
using namespace std;
|
|
using namespace G4DNAPARSER;
|
|
|
|
CommandLineParser* CommandLineParser::fpInstance(0);
|
|
G4String Command::fNoOption = "NoOption";
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
inline bool MATCH(const char *a, const char *b)
|
|
{
|
|
return strcmp(a, b) == 0;
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
CommandLineParser::CommandLineParser()
|
|
{
|
|
// G4cout << "############ NEW PARSE ##########" << G4endl;
|
|
fpInstance = this;
|
|
fOptionsWereSetup = false;
|
|
fMaxMarkerLength = 0;
|
|
fMaxOptionNameLength = 0;
|
|
AddCommand("--help", Command::WithoutOption, "Print this help");
|
|
AddCommand("-h", Command::WithoutOption, "Print this help");
|
|
AddCommand("&", Command::WithoutOption);
|
|
|
|
fVerbose = 0;
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
CommandLineParser* CommandLineParser::GetParser()
|
|
{
|
|
if (!fpInstance) new CommandLineParser;
|
|
return fpInstance;
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
CommandLineParser::~CommandLineParser()
|
|
{
|
|
std::map<G4String, Command*>::iterator it = fCommandMap.begin();
|
|
for (; it != fCommandMap.end(); it++)
|
|
{
|
|
if (it->second) delete it->second;
|
|
}
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
void CommandLineParser::DeleteInstance()
|
|
{
|
|
if (fpInstance)
|
|
{
|
|
delete fpInstance;
|
|
fpInstance = 0;
|
|
}
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
Command::Command(Command::Type commandType,
|
|
const G4String& description)
|
|
{
|
|
fType = commandType;
|
|
fDescription = description;
|
|
fActive = false;
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
CommandWithOption::CommandWithOption(Command::Type commandType,
|
|
const G4String& description,
|
|
const G4String& defaultOption,
|
|
const G4String& optionName) :
|
|
Command(commandType, description)
|
|
{
|
|
fDefaultOption = defaultOption;
|
|
fOptionName = optionName;
|
|
fOption = "";
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
int CommandLineParser::Parse(int& argc, char **argv)
|
|
{
|
|
// G4cout << "Parse " << G4endl;
|
|
static char null[1] = { "" };
|
|
int firstArgc = argc;
|
|
|
|
for (int i = 1; i < firstArgc; i++)
|
|
{
|
|
Command* command = FindCommand(argv[i]);
|
|
if (command == 0) continue;
|
|
|
|
if (fVerbose) G4cout << "Command : " << argv[i] << G4endl;
|
|
|
|
fOptionsWereSetup = true;
|
|
command->fActive = true;
|
|
|
|
G4String marker(argv[i]);
|
|
|
|
if (strcmp(argv[i], "-h") != 0 && strcmp(argv[i], "--help") != 0)
|
|
{
|
|
argv[i] = null;
|
|
}
|
|
|
|
if (command->fType == Command::WithOption)
|
|
{
|
|
if (fVerbose) G4cout << "WithOption" << G4endl;
|
|
|
|
if(i+1 > firstArgc || argv[i+1]==0 || argv[i+1][0]=='-')
|
|
{
|
|
G4cerr << "An command line option is missing for "
|
|
<< marker << G4endl;
|
|
abort();
|
|
}
|
|
|
|
command->SetOption( (const char*) strdup(argv[i+1]) );
|
|
argv[i+1] = null;
|
|
i++;
|
|
}
|
|
else if(command->fType == Command::OptionNotCompulsory)
|
|
{
|
|
if(fVerbose)
|
|
G4cout <<"OptionNotCompulsory"<<G4endl;
|
|
|
|
if(i+1 < firstArgc)
|
|
{
|
|
G4String buffer = (const char*) strdup(argv[i+1]);
|
|
|
|
if(buffer.empty() == false)
|
|
{
|
|
if(buffer.at(0) != '-'
|
|
&& buffer.at(0) != '&'
|
|
&& buffer.at(0) != '>'
|
|
&& buffer.at(0) != '|')
|
|
{
|
|
if(fVerbose)
|
|
{
|
|
G4cout << "facultative option is : " << buffer << G4endl;
|
|
}
|
|
|
|
command->SetOption( (const char*) strdup(argv[i+1]) );
|
|
argv[i+1] = null;
|
|
i++;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(fVerbose)
|
|
G4cout << "Option not set" << G4endl;
|
|
|
|
command->SetOption("");
|
|
}
|
|
}
|
|
CorrectRemainingOptions(argc, argv);
|
|
|
|
Command* commandLine(0);
|
|
if ((commandLine = GetCommandIfActive("--help")) || (commandLine =
|
|
GetCommandIfActive("-h")))
|
|
{
|
|
G4cout << "Usage : " << argv[0] << " [OPTIONS]" << G4endl;
|
|
PrintHelp();
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
void CommandLineParser::PrintHelp()
|
|
{
|
|
std::map<G4String, Command*>::iterator it;
|
|
|
|
int maxFieldLength = fMaxMarkerLength + fMaxOptionNameLength + 4;
|
|
|
|
G4cout << "Options: " << G4endl;
|
|
|
|
for (it = fCommandMap.begin(); it != fCommandMap.end(); it++)
|
|
{
|
|
Command* command = it->second;
|
|
if (command)
|
|
{
|
|
G4cout << setw(maxFieldLength) << left;
|
|
|
|
G4String toPrint = it->first;
|
|
|
|
if (toPrint == "&")
|
|
{
|
|
continue;
|
|
}
|
|
else if (toPrint == "-h") continue;
|
|
else if (toPrint == "--help")
|
|
{
|
|
toPrint += ", -h";
|
|
}
|
|
|
|
if (command->GetDefaultOption() != "")
|
|
{
|
|
toPrint += " \"" + command->GetDefaultOption() + "\"";
|
|
}
|
|
|
|
G4cout << toPrint;
|
|
|
|
G4cout << command->GetDescription() << G4endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
void CommandLineParser::CorrectRemainingOptions(int& argc, char **argv)
|
|
{
|
|
// remove handled arguments from argument array
|
|
int j = 0;
|
|
for (int i = 0; i < argc; i++)
|
|
{
|
|
if (strcmp(argv[i], ""))
|
|
{
|
|
argv[j] = argv[i];
|
|
j++;
|
|
}
|
|
}
|
|
argc = j;
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
void CommandLineParser::AddCommand(const G4String& marker,
|
|
Command::Type type,
|
|
const G4String& description,
|
|
const G4String& defaultOption,
|
|
const G4String& optionName)
|
|
{
|
|
// G4cout << "Add command : "<< marker << G4endl;
|
|
|
|
Command* command = 0;
|
|
switch(type)
|
|
{
|
|
case Command::WithoutOption:
|
|
command = new Command(type, description);
|
|
break;
|
|
|
|
default:
|
|
command = new CommandWithOption(type,
|
|
description,
|
|
defaultOption,
|
|
optionName);
|
|
if ((int) defaultOption.length() > fMaxOptionNameLength)
|
|
fMaxOptionNameLength = defaultOption.length();
|
|
break;
|
|
}
|
|
|
|
if ((int) marker.length() > fMaxMarkerLength) fMaxMarkerLength =
|
|
marker.length();
|
|
fCommandMap.insert(make_pair(marker, command));
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
/*
|
|
// Add one command but multiple markers
|
|
void Parser::AddCommand(vector<G4String> markers,
|
|
CommandType type,
|
|
const G4String& description,
|
|
const G4String& optionName)
|
|
{
|
|
// G4cout << "Add command : "<< marker << G4endl;
|
|
Command* command = new Command(type, description, optionName);
|
|
|
|
for (size_t i = 0; i < markers.size; i++)
|
|
{
|
|
G4String marker = markers[i];
|
|
if ((int) marker.length() > fMaxMarkerLength)
|
|
{
|
|
fMaxMarkerLength = marker.length();
|
|
}
|
|
if ((int) optionName.length() > fMaxOptionNameLength)
|
|
{
|
|
fMaxOptionNameLength = optionName.length();
|
|
}
|
|
fCommandMap.insert(make_pair(marker, command));
|
|
}
|
|
}
|
|
*/
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
Command* CommandLineParser::FindCommand(const G4String& marker)
|
|
{
|
|
std::map<G4String, Command*>::iterator it = fCommandMap.find(marker);
|
|
if (it == fCommandMap.end())
|
|
{
|
|
// G4cerr << "command not found" << G4endl;
|
|
return 0;
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
Command* CommandLineParser::GetCommandIfActive(const G4String &marker)
|
|
{
|
|
Command* command = FindCommand(marker);
|
|
if (command)
|
|
{
|
|
// G4cout << "Command found : "<< marker << G4endl;
|
|
|
|
if (command->fActive)
|
|
{
|
|
// G4cout << "Command Active" << G4endl;
|
|
return command;
|
|
}
|
|
// else
|
|
// G4cout <<"Command not active" << G4endl;
|
|
}
|
|
else
|
|
{
|
|
G4ExceptionDescription description;
|
|
description << "You try to retrieve a command that was not registered : "
|
|
<< marker << G4endl;
|
|
G4Exception("CommandLineParser::GetCommandIfActive",
|
|
"COMMAND LINE NOT DEFINED", FatalException, description, "");
|
|
// If you are using this class outside of Geant4, use exit(-1) instead
|
|
//exit(-1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
bool CommandLineParser::CheckIfNotHandledOptionsExists(int& argc, char** argv)
|
|
{
|
|
if (argc > 0)
|
|
{
|
|
G4bool kill = false;
|
|
for (G4int i = 1; i < argc; i++)
|
|
{
|
|
if (strcmp(argv[i], ""))
|
|
{
|
|
kill = true;
|
|
G4cerr << "Unknown argument : " << argv[i] << "\n";
|
|
}
|
|
}
|
|
if (kill)
|
|
{
|
|
G4cerr << "The option " << argv[0]
|
|
<< " is not handled this programme." << G4endl;
|
|
G4cout << "Usage : " << argv[0] << " [OPTIONS]" << G4endl;
|
|
PrintHelp();
|
|
return true; // KILL APPLICATION
|
|
}
|
|
}
|
|
return false;
|
|
}
|