// // ******************************************************************** // * 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. * // ******************************************************************** // // // $Id: G4UIcommand.cc,v 1.25 2006/06/29 19:08:56 gunter Exp $ // GEANT4 tag $Name: geant4-09-03 $ // // #include "G4UIcommand.hh" #include "G4UImessenger.hh" #include "G4UImanager.hh" #include "G4UIcommandStatus.hh" #include "G4StateManager.hh" #include "G4UnitsTable.hh" #include "G4Tokenizer.hh" #include "G4ios.hh" #include G4UIcommand::G4UIcommand() :messenger(0),token(IDENTIFIER),paramERR(0) {;} G4UIcommand::G4UIcommand(const char * theCommandPath, G4UImessenger * theMessenger) :messenger(theMessenger),token(IDENTIFIER),paramERR(0) { G4String comStr = theCommandPath; if(!theMessenger) { // this must be a directory if(comStr(comStr.length()-1)!='/') { G4cerr << "G4UIcommand Warning : " << G4endl; G4cerr << " <" << theCommandPath << "> must be a directory." << G4endl; G4cerr << " '/' is appended." << G4endl; comStr += "/"; } } G4UIcommandCommonConstructorCode (comStr); G4String nullString; availabelStateList.clear(); availabelStateList.push_back(G4State_PreInit); availabelStateList.push_back(G4State_Init); availabelStateList.push_back(G4State_Idle); availabelStateList.push_back(G4State_GeomClosed); availabelStateList.push_back(G4State_EventProc); availabelStateList.push_back(G4State_Abort); } void G4UIcommand::G4UIcommandCommonConstructorCode (const char * theCommandPath) { commandPath = theCommandPath; commandName = theCommandPath; G4int commandNameIndex = commandName.last('/'); commandName.remove(0,commandNameIndex+1); G4UImanager::GetUIpointer()->AddNewCommand(this); } G4UIcommand::~G4UIcommand() { G4UImanager* fUImanager = G4UImanager::GetUIpointer(); if(fUImanager) fUImanager->RemoveCommand(this); G4int n_parameterEntry = parameter.size(); for( G4int i_thParameter=0; i_thParameter < n_parameterEntry; i_thParameter++ ) { delete parameter[i_thParameter]; } parameter.clear(); } G4int G4UIcommand::operator==(const G4UIcommand &right) const { return ( commandPath == right.GetCommandPath() ); } G4int G4UIcommand::operator!=(const G4UIcommand &right) const { return ( commandPath != right.GetCommandPath() ); } G4int G4UIcommand::DoIt(G4String parameterList) { G4String correctParameters; G4int n_parameterEntry = parameter.size(); if( n_parameterEntry != 0 ) { G4String aToken; G4String correctToken; G4Tokenizer parameterToken( parameterList ); for( G4int i_thParameter=0; i_thParameter 0) { correctParameters.append(" "); } aToken = parameterToken(); if( aToken.length()>0 && aToken(0)=='"' ) { while( aToken(aToken.length()-1) != '"' || ( aToken.length()==1 && aToken(0)=='"' )) { G4String additionalToken = parameterToken(); if( additionalToken.isNull() ) { return fParameterUnreadable+i_thParameter; } aToken += " "; aToken += additionalToken; } } else if(i_thParameter==n_parameterEntry-1 && parameter[i_thParameter]->GetParameterType()=='s') { G4String anotherToken; while(!((anotherToken=parameterToken()).isNull())) { G4int idxs = anotherToken.index("#"); if(idxs==G4int(std::string::npos)) { aToken += " "; aToken += anotherToken; } else if(idxs>0) { aToken += " "; aToken += anotherToken(0,idxs); break; } else { break; } } } if( aToken.isNull() || aToken == "!" ) { if(parameter[i_thParameter]->IsOmittable()) { if(parameter[i_thParameter]->GetCurrentAsDefault()) { G4Tokenizer cvSt(messenger->GetCurrentValue(this)); G4String parVal; for(G4int ii=0;iiGetDefaultValue()); } } else { return fParameterUnreadable+i_thParameter; } } else { G4int stat = parameter[i_thParameter]->CheckNewValue( aToken ); if(stat) return stat+i_thParameter; correctParameters.append(aToken); } } } if(CheckNewValue( correctParameters )) { return fParameterOutOfRange+99; } messenger->SetNewValue( this, correctParameters ); return 0; } G4String G4UIcommand::GetCurrentValue() { return messenger->GetCurrentValue(this); } void G4UIcommand::AvailableForStates(G4ApplicationState s1) { availabelStateList.clear(); availabelStateList.push_back(s1); } void G4UIcommand::AvailableForStates(G4ApplicationState s1, G4ApplicationState s2) { availabelStateList.clear(); availabelStateList.push_back(s1); availabelStateList.push_back(s2); } void G4UIcommand::AvailableForStates(G4ApplicationState s1, G4ApplicationState s2, G4ApplicationState s3) { availabelStateList.clear(); availabelStateList.push_back(s1); availabelStateList.push_back(s2); availabelStateList.push_back(s3); } void G4UIcommand::AvailableForStates(G4ApplicationState s1, G4ApplicationState s2, G4ApplicationState s3, G4ApplicationState s4) { availabelStateList.clear(); availabelStateList.push_back(s1); availabelStateList.push_back(s2); availabelStateList.push_back(s3); availabelStateList.push_back(s4); } void G4UIcommand::AvailableForStates(G4ApplicationState s1, G4ApplicationState s2, G4ApplicationState s3, G4ApplicationState s4, G4ApplicationState s5) { availabelStateList.clear(); availabelStateList.push_back(s1); availabelStateList.push_back(s2); availabelStateList.push_back(s3); availabelStateList.push_back(s4); availabelStateList.push_back(s5); } G4bool G4UIcommand::IsAvailable() { G4bool av = false; G4ApplicationState currentState = G4StateManager::GetStateManager()->GetCurrentState(); G4int nState = availabelStateList.size(); for(G4int i=0;iGetName()==unitCategory) break; } if(i==UTbl.size()) { G4cerr << "Unit category <" << unitCategory << "> is not defined." << G4endl; return retStr; } G4UnitsContainer& UCnt = UTbl[i]->GetUnitsList(); retStr = UCnt[0]->GetSymbol(); G4int je = UCnt.size(); for(G4int j=1;jGetSymbol(); } for(G4int k=0;kGetName(); } return retStr; } void G4UIcommand::List() { G4cout << G4endl; G4cout << G4endl; if(commandPath(commandPath.length()-1)!='/') { G4cout << "Command " << commandPath << G4endl; } G4cout << "Guidance :" << G4endl; G4int n_guidanceEntry = commandGuidance.size(); for( G4int i_thGuidance=0; i_thGuidance < n_guidanceEntry; i_thGuidance++ ) { G4cout << commandGuidance[i_thGuidance] << G4endl; } if( ! rangeString.isNull() ) { G4cout << " Range of parameters : " << rangeString << G4endl; } G4int n_parameterEntry = parameter.size(); if( n_parameterEntry > 0 ) { for( G4int i_thParameter=0; i_thParameterList(); } } G4cout << G4endl; } G4String G4UIcommand::ConvertToString(G4bool boolVal) { G4String vl = "0"; if(boolVal) vl = "1"; return vl; } G4String G4UIcommand::ConvertToString(G4int intValue) { std::ostringstream os; os << intValue; G4String vl = os.str(); return vl; } G4String G4UIcommand::ConvertToString(G4double doubleValue) { std::ostringstream os; os << doubleValue; G4String vl = os.str(); return vl; } G4String G4UIcommand::ConvertToString(G4double doubleValue,const char* unitName) { G4String unt = unitName; G4double uv = ValueOf(unitName); std::ostringstream os; os << doubleValue/uv << " " << unitName; G4String vl = os.str(); return vl; } G4String G4UIcommand::ConvertToString(G4ThreeVector vec) { std::ostringstream os; os << vec.x() << " " << vec.y() << " " << vec.z(); G4String vl = os.str(); return vl; } G4String G4UIcommand::ConvertToString(G4ThreeVector vec,const char* unitName) { G4String unt = unitName; G4double uv = ValueOf(unitName); std::ostringstream os; os << vec.x()/uv << " " << vec.y()/uv << " " << vec.z()/uv << " " << unitName; G4String vl = os.str(); return vl; } G4bool G4UIcommand::ConvertToBool(const char* st) { G4String v = st; v.toUpper(); G4bool vl = false; if( v=="Y" || v=="YES" || v=="1" || v=="T" || v=="TRUE" ) { vl = true; } return vl; } G4int G4UIcommand::ConvertToInt(const char* st) { G4int vl; std::istringstream is(st); is >> vl; return vl; } G4double G4UIcommand::ConvertToDouble(const char* st) { G4double vl; std::istringstream is(st); is >> vl; return vl; } G4double G4UIcommand::ConvertToDimensionedDouble(const char* st) { G4double vl; char unts[30]; std::istringstream is(st); is >> vl >> unts; G4String unt = unts; return (vl*ValueOf(unt)); } G4ThreeVector G4UIcommand::ConvertTo3Vector(const char* st) { G4double vx; G4double vy; G4double vz; std::istringstream is(st); is >> vx >> vy >> vz; return G4ThreeVector(vx,vy,vz); } G4ThreeVector G4UIcommand::ConvertToDimensioned3Vector(const char* st) { G4double vx; G4double vy; G4double vz; char unts[30]; std::istringstream is(st); is >> vx >> vy >> vz >> unts; G4String unt = unts; G4double uv = ValueOf(unt); return G4ThreeVector(vx*uv,vy*uv,vz*uv); } // ----- the following is used by CheckNewValue() ------------ #include // isalpha(), toupper() //#include "checkNewValue_debug.icc" //#define DEBUG 1 G4int G4UIcommand:: CheckNewValue(const char * newValue) { yystype result; // if( TypeCheck(newValue) == 0 ) return 1; if( ! rangeString.isNull() ) { if( RangeCheck(newValue) == 0 ) return fParameterOutOfRange; } return 0; // succeeded } // ------------------ type check routines ------------------- G4int G4UIcommand:: TypeCheck(const char * t) { G4String aNewValue; char type; std::istringstream is(t); for (unsigned i=0; i< parameter.size(); i++) { is >> aNewValue; type = toupper(parameter[i]->GetParameterType()); switch ( type ) { case 'D': if( IsDouble(aNewValue)==0 ){ G4cerr << aNewValue << ": double value expected." << G4endl; return 0; } break; case 'I': if( IsInt(aNewValue,20)==0 ){ G4cerr < maxDigits) { G4cerr <<"digit length exceeds"<GetParameterType()); switch ( type ) { case 'D': is >> newVal[i].D; break; case 'I': is >> newVal[i].I; break; case 'S': case 'B': default: ; } } // PrintToken(); // Print tokens (consumes all tokens) token= Yylex(); result = Expression(); if( paramERR == 1 ) return 0; if( result.type != CONSTINT) { G4cerr << "Illegal Expression in parameter range." << G4endl; return 0; } if ( result.I ) return 1; G4cerr << "parameter out of range: "<< rangeString << G4endl; return 0; } // ------------------ syntax node functions ------------------ yystype G4UIcommand:: Expression(void) { yystype result; #ifdef DEBUG G4cerr << " Expression()" << G4endl; #endif result = LogicalORExpression(); return result; } yystype G4UIcommand:: LogicalORExpression(void) { yystype result; yystype p; p = LogicalANDExpression(); if( token != LOGICALOR) return p; if( p.type == CONSTSTRING || p.type == IDENTIFIER ) { G4cerr << "Parameter range: illegal type at '||'" << G4endl; paramERR = 1; } result.I = p.I; while (token == LOGICALOR) { token = Yylex(); p = LogicalANDExpression(); if( p.type == CONSTSTRING || p.type == IDENTIFIER ) { G4cerr << "Parameter range: illegal type at '||'" <GetParameterType()); switch ( newValtype ) { case 'I': if( arg2.type == CONSTINT ) { return CompareInt( newVal[i].I, op, arg2.I ); } else { G4cerr << "integer operand expected for " << rangeString << '.' << G4endl; } break; case 'D': if( arg2.type == CONSTDOUBLE ) { return CompareDouble( newVal[i].D, op, arg2.D ); } else if ( arg2.type == CONSTINT ) { // integral promotion return CompareDouble( newVal[i].D, op, arg2.I ); } break; default: ; } } if( arg2.type == IDENTIFIER) { unsigned i = IndexOf( arg2.S ); newValtype = toupper(parameter[i]->GetParameterType()); switch ( newValtype ) { case 'I': if( arg1.type == CONSTINT ) { return CompareInt( arg1.I, op, newVal[i].I ); } else { G4cerr << "integer operand expected for " << rangeString << '.' << G4endl; } break; case 'D': if( arg1.type == CONSTDOUBLE ) { return CompareDouble( arg1.D, op, newVal[i].D ); } else if ( arg1.type == CONSTINT ) { // integral promotion return CompareDouble( arg1.I, op, newVal[i].D ); } break; default: ; } } return 0; } G4int G4UIcommand:: CompareInt(G4int arg1, G4int op, G4int arg2) { G4int result=-1; G4String opr; switch (op) { case GT: result = ( arg1 > arg2); opr= ">" ; break; case GE: result = ( arg1 >= arg2); opr= ">="; break; case LT: result = ( arg1 < arg2); opr= "<" ; break; case LE: result = ( arg1 <= arg2); opr= "<="; break; case EQ: result = ( arg1 == arg2); opr= "=="; break; case NE: result = ( arg1 != arg2); opr= "!="; break; default: G4cerr << "Parameter range: error at CompareInt" << G4endl; paramERR = 1; } #ifdef DEBUG G4cerr << "CompareInt " << arg1 << " " << opr << arg2 << " result: " << result << G4endl; #endif return result; } G4int G4UIcommand:: CompareDouble(G4double arg1, G4int op, G4double arg2) { G4int result=-1; G4String opr; switch (op) { case GT: result = ( arg1 > arg2); opr= ">"; break; case GE: result = ( arg1 >= arg2); opr= ">="; break; case LT: result = ( arg1 < arg2); opr= "<"; break; case LE: result = ( arg1 <= arg2); opr= "<="; break; case EQ: result = ( arg1 == arg2); opr= "=="; break; case NE: result = ( arg1 != arg2); opr= "!="; break; default: G4cerr << "Parameter range: error at CompareDouble" << G4endl; paramERR = 1; } #ifdef DEBUG G4cerr << "CompareDouble " << arg1 <<" " << opr << " "<< arg2 << " result: " << result << G4endl; #endif return result; } unsigned G4UIcommand:: IndexOf(const char* nam) { unsigned i; G4String pname; for( i=0; i GetParameterName(); if( pname == nam ) { return i; } } paramERR = 1; G4cerr << "parameter name:"< GetParameterName(); if( pname == nam ) return 1; } return 0; } // --------------------- utility functions -------------------------- tokenNum G4UIcommand:: Yylex() // reads input and returns token number, KR486 { // (returns EOF) G4int c; G4String buf; while(( c= G4UIpGetc())==' '|| c=='\t' || c== '\n' ) ; if (c== EOF) return (tokenNum)EOF; // KR488 buf= ""; if (isdigit(c) || c== '.') { // I or D do { buf += G4String((unsigned char)c); c=G4UIpGetc(); } while (c=='.' || isdigit(c) || c=='e' || c=='E' || c=='+' || c=='-'); G4UIpUngetc(c); const char* t = buf; std::istringstream is(t); if ( IsInt(buf.data(),20) ) { is >> yylval.I; return CONSTINT; } else if ( IsDouble(buf.data()) ) { is >> yylval.D; return CONSTDOUBLE; } else { G4cerr << buf<<": numeric format error."<': return (tokenNum) Follow('=', GE, GT); case '<': return (tokenNum) Follow('=', LE, LT); case '=': return (tokenNum) Follow('=', EQ, '='); case '!': return (tokenNum) Follow('=', NE, '!'); case '|': return (tokenNum) Follow('|', LOGICALOR, '|'); case '&': return (tokenNum) Follow('&', LOGICALAND, '&'); default: return (tokenNum) c; } } G4int G4UIcommand:: Follow(G4int expect, G4int ifyes, G4int ifno) { G4int c = G4UIpGetc(); if ( c== expect) return ifyes; G4UIpUngetc(c); return ifno; } //------------------ low level routines ----------------------------- G4int G4UIcommand:: G4UIpGetc() { // emulation of getc() G4int length = rangeString.length(); if( bp < length) return rangeString(bp++); else return EOF; } G4int G4UIcommand:: G4UIpUngetc(G4int c) { // emulation of ungetc() if (c<0) return -1; if (bp >0 && c == rangeString(bp-1)) { --bp; } else { G4cerr << "G4UIpUngetc() failed." << G4endl; G4cerr << "bp="<