// This code implementation is the intellectual property of // the GEANT4 collaboration. // // By copying, distributing or modifying the Program (or any work // based on the Program) you indicate your acceptance of this statement, // and all its terms. // // $Id: G4UIcommand.cc,v 1.5 1999/12/15 14:50:41 gunter Exp $ // GEANT4 tag $Name: geant4-03-00 $ // // #include "G4UIcommand.hh" #include "G4UImessenger.hh" #include "G4UImanager.hh" #include "G4UIcommandStatus.hh" #include "G4StateManager.hh" #include "G4UnitsTable.hh" #include "g4rw/ctoken.h" #include "G4ios.hh" G4UIcommand::G4UIcommand():paramERR(0) { } G4UIcommand::G4UIcommand(const char * theCommandPath, G4UImessenger * theMessenger) :messenger(theMessenger), 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.insert(PreInit); availabelStateList.insert(Init); availabelStateList.insert(Idle); availabelStateList.insert(GeomClosed); availabelStateList.insert(EventProc); } void G4UIcommand::G4UIcommandCommonConstructorCode (const char * theCommandPath) { commandPath = theCommandPath; commandName = theCommandPath; int commandNameIndex = commandName.last('/'); commandName.remove(0,commandNameIndex+1); G4UImanager::GetUIpointer()->AddNewCommand(this); } G4UIcommand::~G4UIcommand() { G4UImanager* fUImanager = G4UImanager::GetUIpointer(); if(fUImanager) fUImanager->RemoveCommand(this); int n_parameterEntry = parameter.entries(); for( int i_thParameter=0; i_thParameter < n_parameterEntry; i_thParameter++ ) { delete parameter[i_thParameter]; } } int G4UIcommand::operator==(const G4UIcommand &right) const { return ( commandPath == right.GetCommandPath() ); } int G4UIcommand::operator!=(const G4UIcommand &right) const { return ( commandPath != right.GetCommandPath() ); } G4int G4UIcommand::DoIt(G4String parameterList) { G4String correctParameters; int n_parameterEntry = parameter.entries(); if( n_parameterEntry != 0 ) { G4String aToken; G4String correctToken; G4Tokenizer parameterToken( parameterList ); for( int i_thParameter=0; i_thParameter 0) { correctParameters.append(" "); } aToken = parameterToken(); if( aToken.length()>0 && aToken(0)=='"' ) { while( aToken(aToken.length()-1) != '"' ) { G4String additionalToken = parameterToken(); if( additionalToken.isNull() ) { return fParameterUnreadable+i_thParameter; } aToken += " "; aToken += additionalToken; } // aToken.strip(G4String::both,'"'); } if( aToken.isNull() || aToken == "!" ) { if(parameter[i_thParameter]->IsOmittable()) { if(parameter[i_thParameter]->GetCurrentAsDefault()) { G4Tokenizer cvt(messenger->GetCurrentValue(this)); G4String parVal; for(int ii=0;iiGetDefaultValue()); } } else { return fParameterUnreadable+i_thParameter; } } else { int 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.insert(s1); } void G4UIcommand::AvailableForStates(G4ApplicationState s1, G4ApplicationState s2) { availabelStateList.clear(); availabelStateList.insert(s1); availabelStateList.insert(s2); } void G4UIcommand::AvailableForStates(G4ApplicationState s1, G4ApplicationState s2, G4ApplicationState s3) { availabelStateList.clear(); availabelStateList.insert(s1); availabelStateList.insert(s2); availabelStateList.insert(s3); } void G4UIcommand::AvailableForStates(G4ApplicationState s1, G4ApplicationState s2, G4ApplicationState s3, G4ApplicationState s4) { availabelStateList.clear(); availabelStateList.insert(s1); availabelStateList.insert(s2); availabelStateList.insert(s3); availabelStateList.insert(s4); } void G4UIcommand::AvailableForStates(G4ApplicationState s1, G4ApplicationState s2, G4ApplicationState s3, G4ApplicationState s4, G4ApplicationState s5) { availabelStateList.clear(); availabelStateList.insert(s1); availabelStateList.insert(s2); availabelStateList.insert(s3); availabelStateList.insert(s4); availabelStateList.insert(s5); } G4bool G4UIcommand::IsAvailable() { G4bool av = false; G4ApplicationState currentState = G4StateManager::GetStateManager()->GetCurrentState(); int nState = availabelStateList.entries(); for(int i=0;iGetName()==unitCategory) break; } if(i==UTbl.entries()) { G4cerr << "Unit category <" << unitCategory << "> is not defined." << G4endl; return retStr; } G4UnitsContainer& UCnt = UTbl[i]->GetUnitsList(); retStr = UCnt[0]->GetSymbol(); G4int je = UCnt.entries(); for(int j=1;jGetSymbol(); } for(int k=0;kGetName(); } return retStr; } void G4UIcommand::List() { G4cout << G4endl; G4cout << G4endl; if(commandPath(commandPath.length()-1)!='/') { G4cout << "Command " << commandPath << G4endl; } G4cout << "Guidance :" << G4endl; int n_guidanceEntry = commandGuidance.entries(); for( int i_thGuidance=0; i_thGuidance < n_guidanceEntry; i_thGuidance++ ) { G4cout << commandGuidance[i_thGuidance] << G4endl; } if( ! rangeString.isNull() ) { G4cout << " Range of parameters : " << rangeString << G4endl; } int n_parameterEntry = parameter.entries(); if( n_parameterEntry > 0 ) { for( int i_thParameter=0; i_thParameterList(); } } G4cout << G4endl; } // ----- the following is used by CheckNewValue() ------------ #include // isalpha(), toupper() #include "g4std/strstream" //#include "checkNewValue_debug.icc" //#define DEBUG 1 int G4UIcommand:: CheckNewValue(G4String newValue) { yystype result; // if( TypeCheck(newValue) == 0 ) return 1; if( ! rangeString.isNull() ) { if( RangeCheck(newValue) == 0 ) return fParameterOutOfRange; } return 0; // succeeded } // ------------------ type check routines ------------------- int G4UIcommand:: TypeCheck(G4String newValues) { G4String aNewValue; char type; const char* t = newValues; G4std::istrstream is((char*)t); for (unsigned i=0; i< parameter.entries(); 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; } int G4UIcommand:: CompareInt(int arg1, int op, int arg2) { int result; 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; } int G4UIcommand:: CompareDouble(double arg1, int op, double arg2) { int result; 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( G4String 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) int 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; G4std::istrstream is((char*)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; } } int G4UIcommand:: Follow(int expect, int ifyes, int ifno) { int c = G4UIpGetc(); if ( c== expect) return ifyes; G4UIpUngetc(c); return ifno; } //------------------ low level routines ----------------------------- int G4UIcommand:: G4UIpGetc() { // emulation of getc() int length = rangeString.length(); if( bp < length) return rangeString(bp++); else return EOF; } int G4UIcommand:: G4UIpUngetc(int c) { // emulation of ungetc() if (c<0) return -1; if (bp >0 && c == rangeString(bp-1)) { --bp; } else { G4cerr << "G4UIpUngetc() failed." << G4endl; G4cerr << "bp="<