G4UIcommand.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // 
00030 
00031 #include "G4UIcommand.hh"
00032 #include "G4UImessenger.hh"
00033 #include "G4UImanager.hh"
00034 #include "G4UIcommandStatus.hh"
00035 #include "G4StateManager.hh"
00036 #include "G4UnitsTable.hh"
00037 #include "G4Tokenizer.hh"
00038 #include "G4ios.hh"
00039 #include <sstream>
00040 
00041 G4UIcommand::G4UIcommand()
00042   : messenger(0), bp(0), token(IDENTIFIER), paramERR(0)
00043 {
00044 }
00045 
00046 G4UIcommand::G4UIcommand(const char * theCommandPath,
00047                          G4UImessenger * theMessenger)
00048 :messenger(theMessenger),token(IDENTIFIER),paramERR(0)
00049 {
00050   G4String comStr = theCommandPath;
00051   if(!theMessenger)
00052   { // this must be a directory
00053     if(comStr(comStr.length()-1)!='/')
00054     {
00055       G4cerr << "G4UIcommand Warning : " << G4endl;
00056       G4cerr << "  <" << theCommandPath << "> must be a directory." << G4endl;
00057       G4cerr << "  '/' is appended." << G4endl;
00058       comStr += "/";
00059     }
00060   }
00061   G4UIcommandCommonConstructorCode (comStr);
00062   G4String nullString;
00063   availabelStateList.clear();
00064   availabelStateList.push_back(G4State_PreInit);
00065   availabelStateList.push_back(G4State_Init);
00066   availabelStateList.push_back(G4State_Idle);
00067   availabelStateList.push_back(G4State_GeomClosed);
00068   availabelStateList.push_back(G4State_EventProc);
00069   availabelStateList.push_back(G4State_Abort);
00070 }
00071 
00072 void G4UIcommand::G4UIcommandCommonConstructorCode
00073 (const char * theCommandPath)
00074 { 
00075   commandPath = theCommandPath;
00076   commandName = theCommandPath;
00077   G4int commandNameIndex = commandName.last('/');
00078   commandName.remove(0,commandNameIndex+1);
00079 
00080   G4UImanager::GetUIpointer()->AddNewCommand(this);
00081 }
00082 
00083 G4UIcommand::~G4UIcommand()
00084 {
00085   G4UImanager* fUImanager = G4UImanager::GetUIpointer();
00086   if(fUImanager) fUImanager->RemoveCommand(this);
00087   
00088   G4int n_parameterEntry = parameter.size();
00089   for( G4int i_thParameter=0; i_thParameter < n_parameterEntry; i_thParameter++ )
00090   { delete parameter[i_thParameter]; }
00091   parameter.clear();
00092 }
00093 
00094 G4int G4UIcommand::operator==(const G4UIcommand &right) const
00095 {
00096   return ( commandPath == right.GetCommandPath() );
00097 }
00098 
00099 G4int G4UIcommand::operator!=(const G4UIcommand &right) const
00100 {
00101   return ( commandPath != right.GetCommandPath() );
00102 }
00103 
00104 G4int G4UIcommand::DoIt(G4String parameterList)
00105 {
00106   G4String correctParameters;
00107   G4int n_parameterEntry = parameter.size();
00108   if( n_parameterEntry != 0 )
00109   {
00110     G4String aToken;
00111     G4String correctToken;
00112     G4Tokenizer parameterToken( parameterList );
00113     for( G4int i_thParameter=0; i_thParameter<n_parameterEntry; i_thParameter++ )
00114     {
00115       if(i_thParameter > 0)
00116       {
00117         correctParameters.append(" ");
00118       }
00119       aToken = parameterToken();
00120       if( aToken.length()>0 && aToken(0)=='"' )
00121       {
00122         while( aToken(aToken.length()-1) != '"'
00123                || ( aToken.length()==1 && aToken(0)=='"' ))
00124         {
00125           G4String additionalToken = parameterToken();
00126           if( additionalToken.isNull() )
00127           { return fParameterUnreadable+i_thParameter; }
00128           aToken += " ";
00129           aToken += additionalToken;
00130         }
00131       }
00132       else if(i_thParameter==n_parameterEntry-1 && parameter[i_thParameter]->GetParameterType()=='s')
00133       {
00134         G4String anotherToken;
00135         while(!((anotherToken=parameterToken()).isNull()))
00136         {
00137           G4int idxs = anotherToken.index("#");
00138           if(idxs==G4int(std::string::npos))
00139           {
00140             aToken += " ";
00141             aToken += anotherToken;
00142           }
00143           else if(idxs>0)
00144           {
00145             aToken += " ";
00146             aToken += anotherToken(0,idxs);
00147             break;
00148           }
00149           else
00150           { break; }
00151         }
00152       }
00153 
00154       if( aToken.isNull() || aToken == "!" )
00155       {
00156         if(parameter[i_thParameter]->IsOmittable())
00157         { 
00158           if(parameter[i_thParameter]->GetCurrentAsDefault())
00159           {
00160             G4Tokenizer cvSt(messenger->GetCurrentValue(this));
00161             G4String parVal;
00162             for(G4int ii=0;ii<i_thParameter;ii++)
00163             {
00164               parVal = cvSt();
00165               if (parVal(0)=='"')
00166                 {
00167                   while( parVal(parVal.length()-1) != '"' )
00168                     {
00169                       G4String additionalToken = cvSt();
00170                       if( additionalToken.isNull() )
00171                         { return fParameterUnreadable+i_thParameter; }
00172                       parVal += " ";
00173                       parVal += additionalToken;
00174                     }
00175                 }
00176             }
00177             G4String aCVToken = cvSt();
00178             if (aCVToken(0)=='"')
00179             {
00180               while( aCVToken(aCVToken.length()-1) != '"' )
00181               {
00182                 G4String additionalToken = cvSt();
00183                 if( additionalToken.isNull() )
00184                 { return fParameterUnreadable+i_thParameter; }
00185                 aCVToken += " ";
00186                 aCVToken += additionalToken;
00187               }
00188               // aCVToken.strip(G4String::both,'"');
00189             }
00190             correctParameters.append(aCVToken);
00191           }
00192           else
00193           { correctParameters.append(parameter[i_thParameter]->GetDefaultValue()); }
00194         }
00195         else
00196         { return fParameterUnreadable+i_thParameter; }
00197       }
00198       else
00199       {
00200         G4int stat = parameter[i_thParameter]->CheckNewValue( aToken );
00201         if(stat) return stat+i_thParameter;
00202         correctParameters.append(aToken);
00203       }
00204     }
00205   }
00206 
00207   if(CheckNewValue( correctParameters ))
00208   { return fParameterOutOfRange+99; }
00209 
00210   messenger->SetNewValue( this, correctParameters );
00211   return 0;
00212 }
00213 
00214 G4String G4UIcommand::GetCurrentValue()
00215 {
00216   return messenger->GetCurrentValue(this);
00217 }
00218 
00219 void G4UIcommand::AvailableForStates(G4ApplicationState s1)
00220 {
00221   availabelStateList.clear();
00222   availabelStateList.push_back(s1);
00223 }
00224 
00225 void G4UIcommand::AvailableForStates(G4ApplicationState s1,
00226                                      G4ApplicationState s2)
00227 {
00228   availabelStateList.clear();
00229   availabelStateList.push_back(s1);
00230   availabelStateList.push_back(s2);
00231 }
00232 
00233 void G4UIcommand::AvailableForStates(G4ApplicationState s1,
00234                                      G4ApplicationState s2,
00235                                      G4ApplicationState s3)
00236 {
00237   availabelStateList.clear();
00238   availabelStateList.push_back(s1);
00239   availabelStateList.push_back(s2);
00240   availabelStateList.push_back(s3);
00241 }
00242 
00243 void G4UIcommand::AvailableForStates(G4ApplicationState s1,
00244                                      G4ApplicationState s2,
00245                                      G4ApplicationState s3,
00246                                      G4ApplicationState s4)
00247 {
00248   availabelStateList.clear();
00249   availabelStateList.push_back(s1);
00250   availabelStateList.push_back(s2);
00251   availabelStateList.push_back(s3);
00252   availabelStateList.push_back(s4);
00253 }
00254 
00255 void G4UIcommand::AvailableForStates(G4ApplicationState s1,
00256                                      G4ApplicationState s2,
00257                                      G4ApplicationState s3,
00258                                      G4ApplicationState s4,
00259                                      G4ApplicationState s5)
00260 {
00261   availabelStateList.clear();
00262   availabelStateList.push_back(s1);
00263   availabelStateList.push_back(s2);
00264   availabelStateList.push_back(s3);
00265   availabelStateList.push_back(s4);
00266   availabelStateList.push_back(s5);
00267 }
00268 
00269 G4bool G4UIcommand::IsAvailable()
00270 {
00271   G4bool av = false;
00272   G4ApplicationState currentState 
00273    = G4StateManager::GetStateManager()->GetCurrentState();
00274    
00275   G4int nState = availabelStateList.size();
00276   for(G4int i=0;i<nState;i++)
00277   {
00278         if(availabelStateList[i]==currentState)
00279         {
00280           av = true;
00281           break;
00282         }
00283   }
00284 
00285   return av;
00286 }
00287 
00288 G4double G4UIcommand::ValueOf(const char* unitName)
00289 {
00290    G4double value = 0.;
00291    value = G4UnitDefinition::GetValueOf(unitName);
00292    return value;              
00293 }
00294 
00295 G4String G4UIcommand::CategoryOf(const char* unitName)
00296 {
00297    return G4UnitDefinition::GetCategory(unitName);
00298 }
00299 
00300 G4String G4UIcommand::UnitsList(const char* unitCategory)
00301 {
00302   G4String retStr;
00303   G4UnitsTable& UTbl = G4UnitDefinition::GetUnitsTable();
00304   size_t i;
00305   for(i=0;i<UTbl.size();i++)
00306   { if(UTbl[i]->GetName()==unitCategory) break; }
00307   if(i==UTbl.size())
00308   { 
00309     G4cerr << "Unit category <" << unitCategory << "> is not defined." << G4endl;
00310     return retStr;
00311   }
00312   G4UnitsContainer& UCnt = UTbl[i]->GetUnitsList();
00313   retStr = UCnt[0]->GetSymbol();
00314   G4int je = UCnt.size();
00315   for(G4int j=1;j<je;j++)
00316   {
00317     retStr += " ";
00318     retStr += UCnt[j]->GetSymbol();
00319   }
00320   for(G4int k=0;k<je;k++)
00321   {
00322     retStr += " ";
00323     retStr += UCnt[k]->GetName();
00324   }
00325   return retStr;
00326 }
00327   
00328 void G4UIcommand::List()
00329 {
00330   G4cout << G4endl;
00331   G4cout << G4endl;
00332   if(commandPath(commandPath.length()-1)!='/')
00333   { G4cout << "Command " << commandPath << G4endl; }
00334   G4cout << "Guidance :" << G4endl;
00335   G4int n_guidanceEntry = commandGuidance.size();
00336   for( G4int i_thGuidance=0; i_thGuidance < n_guidanceEntry; i_thGuidance++ )
00337   { G4cout << commandGuidance[i_thGuidance] << G4endl; }
00338   if( ! rangeString.isNull() )
00339   { G4cout << " Range of parameters : " << rangeString << G4endl; }
00340   G4int n_parameterEntry = parameter.size();
00341   if( n_parameterEntry > 0 )
00342   {
00343     for( G4int i_thParameter=0; i_thParameter<n_parameterEntry; i_thParameter++ )
00344     { parameter[i_thParameter]->List(); }
00345   }
00346   G4cout << G4endl;
00347 }
00348 
00349 G4String G4UIcommand::ConvertToString(G4bool boolVal)
00350 {
00351   G4String vl = "0";
00352   if(boolVal) vl = "1";
00353   return vl;
00354 }
00355 
00356 G4String G4UIcommand::ConvertToString(G4int intValue)
00357 {
00358   std::ostringstream os;
00359   os << intValue;
00360   G4String vl = os.str();
00361   return vl;
00362 }
00363 
00364 G4String G4UIcommand::ConvertToString(G4double doubleValue)
00365 {
00366   std::ostringstream os;
00367   os << doubleValue;
00368   G4String vl = os.str();
00369   return vl;
00370 }
00371 
00372 G4String G4UIcommand::ConvertToString(G4double doubleValue,const char* unitName)
00373 {
00374   G4String unt = unitName;
00375   G4double uv = ValueOf(unitName);
00376 
00377   std::ostringstream os;
00378   os << doubleValue/uv << " " << unitName;
00379   G4String vl = os.str();
00380   return vl;
00381 }
00382 
00383 G4String G4UIcommand::ConvertToString(G4ThreeVector vec)
00384 {
00385   std::ostringstream os;
00386   os << vec.x() << " " << vec.y() << " " << vec.z();
00387   G4String vl = os.str();
00388   return vl;
00389 }
00390 
00391 G4String G4UIcommand::ConvertToString(G4ThreeVector vec,const char* unitName)
00392 {
00393   G4String unt = unitName;
00394   G4double uv = ValueOf(unitName);
00395 
00396   std::ostringstream os;
00397   os << vec.x()/uv << " " << vec.y()/uv << " " << vec.z()/uv
00398      << " " << unitName;
00399   G4String vl = os.str();
00400   return vl;
00401 }
00402 
00403 G4bool G4UIcommand::ConvertToBool(const char* st)
00404 {
00405   G4String v = st;
00406   v.toUpper();
00407   G4bool vl = false;
00408   if( v=="Y" || v=="YES" || v=="1" || v=="T" || v=="TRUE" )
00409   { vl = true; }
00410   return vl;
00411 }
00412 
00413 G4int G4UIcommand::ConvertToInt(const char* st)
00414 {
00415   G4int vl;
00416   std::istringstream is(st);
00417   is >> vl;
00418   return vl;
00419 }
00420 
00421 G4double G4UIcommand::ConvertToDouble(const char* st)
00422 {
00423   G4double vl;
00424   std::istringstream is(st);
00425   is >> vl;
00426   return vl;
00427 }
00428 
00429 G4double G4UIcommand::ConvertToDimensionedDouble(const char* st)
00430 {
00431   G4double vl;
00432   char unts[30];
00433 
00434   std::istringstream is(st);
00435   is >> vl >> unts;
00436   G4String unt = unts;
00437 
00438   return (vl*ValueOf(unt));
00439 }
00440 
00441 G4ThreeVector G4UIcommand::ConvertTo3Vector(const char* st)
00442 {
00443   G4double vx;
00444   G4double vy;
00445   G4double vz;
00446   std::istringstream is(st);
00447   is >> vx >> vy >> vz;
00448   return G4ThreeVector(vx,vy,vz);
00449 }
00450 
00451 G4ThreeVector G4UIcommand::ConvertToDimensioned3Vector(const char* st)
00452 {
00453   G4double vx;
00454   G4double vy;
00455   G4double vz;
00456   char unts[30];
00457   std::istringstream is(st);
00458   is >> vx >> vy >> vz >> unts;
00459   G4String unt = unts;
00460   G4double uv = ValueOf(unt);
00461   return G4ThreeVector(vx*uv,vy*uv,vz*uv);
00462 }
00463 
00464 
00465 // ----- the following is used by CheckNewValue()  ------------
00466 
00467 
00468 #include <ctype.h>          // isalpha(), toupper()
00469 
00470 //#include "checkNewValue_debug.icc"
00471 //#define DEBUG 1
00472 
00473 G4int G4UIcommand::
00474 CheckNewValue(const char * newValue)
00475 {
00476    yystype result;
00477    // if( TypeCheck(newValue) == 0 ) return 1;
00478    if( ! rangeString.isNull() )
00479    { if( RangeCheck(newValue) == 0 ) return fParameterOutOfRange; }
00480    return 0;  // succeeded
00481 }
00482 
00483 // ------------------ type check routines -------------------
00484 
00485 G4int G4UIcommand::
00486 TypeCheck(const char * t)
00487 {
00488     G4String aNewValue;
00489     char type;
00490     std::istringstream is(t);
00491     for (unsigned i=0; i< parameter.size(); i++) {
00492         is >> aNewValue;
00493         type = toupper(parameter[i]->GetParameterType());
00494         switch ( type ) {
00495             case 'D':
00496                 if( IsDouble(aNewValue)==0 ){
00497                     G4cerr << aNewValue << ": double value expected."
00498                          << G4endl;
00499                     return 0;
00500                 } break;
00501             case 'I':
00502                 if( IsInt(aNewValue,20)==0 ){
00503                     G4cerr <<aNewValue<<": integer expected."
00504                          <<G4endl;
00505                      return 0;
00506                 } break;
00507             case 'S':
00508                 break;
00509             case 'B':
00510                 aNewValue.toUpper(); 
00511                 if (aNewValue == "Y"   || aNewValue == "N"
00512                   ||aNewValue == "YES" || aNewValue == "NO"
00513                   ||aNewValue == "1"   || aNewValue == "0"
00514                   ||aNewValue == "T"   || aNewValue == "F"
00515                   ||aNewValue == "TRUE" || aNewValue == "FALSE")
00516                 return 1;
00517                 else return 0; 
00518                 break;
00519             default:  ;
00520         }
00521     }
00522     return 1;
00523 }
00524 
00525 
00526 G4int G4UIcommand::
00527 IsInt(const char* buf, short maxDigits)
00528 {
00529     const char* p= buf;
00530     G4int length=0;
00531     if( *p == '+' || *p == '-') { ++p; }
00532     if( isdigit( (G4int)(*p) )) {
00533         while( isdigit( (G4int)(*p) )) { ++p;  ++length; }
00534         if( *p == '\0' ) {
00535             if( length > maxDigits) {
00536                 G4cerr <<"digit length exceeds"<<G4endl;
00537                 return 0;
00538             }
00539             return 1;
00540         } else {
00541             // G4cerr <<"illegal character after int:"<<buf<<G4endl;
00542         }
00543     } else {
00544         // G4cerr <<"illegal int:"<<buf<<G4endl;
00545     }
00546     return 0;
00547 }
00548 
00549 
00550 G4int G4UIcommand::
00551 ExpectExponent(const char* str)   // used only by IsDouble()
00552 {
00553     G4int maxExplength;
00554     if( IsInt( str, maxExplength=7 )) return 1;
00555     else return 0;
00556 }
00557 
00558 
00559 G4int G4UIcommand::
00560 IsDouble(const char* buf)
00561 {
00562     const char* p= buf;
00563     switch( *p) {
00564         case '+':  case '-': ++p;
00565             if( isdigit(*p) ) {
00566                  while( isdigit( (G4int)(*p) )) { ++p; }
00567                  switch ( *p ) {
00568                      case '\0':    return 1;
00569                         // break;
00570                      case 'E':  case 'e':
00571                          return ExpectExponent(++p );
00572                         // break;
00573                      case '.':  ++p;
00574                          if( *p == '\0' )  return 1;
00575                          if( *p == 'e' || *p =='E' ) return ExpectExponent(++p );
00576                          if( isdigit(*p) ) {
00577                              while( isdigit( (G4int)(*p) )) { ++p; }
00578                              if( *p == '\0' )  return 1;
00579                              if( *p == 'e' || *p =='E') return ExpectExponent(++p);
00580                          } else return 0;   break;
00581                      default: return 0;
00582                  }
00583             }
00584             if( *p == '.' ) { ++p;
00585                  if( isdigit(*p) ) {
00586                      while( isdigit( (G4int)(*p) )) { ++p; }
00587                      if( *p == '\0' )  return 1;
00588                      if( *p == 'e' || *p =='E')  return ExpectExponent(++p);
00589                  }
00590             }
00591             break;
00592         case '.':  ++p;
00593             if( isdigit(*p) ) {
00594                  while( isdigit( (G4int)(*p) )) { ++p; }
00595                  if( *p == '\0' )  return 1;
00596                  if( *p == 'e' || *p =='E' )  return ExpectExponent(++p);
00597             }    break;
00598         default: // digit is expected
00599             if( isdigit(*p) ) {
00600                  while( isdigit( (G4int)(*p) )) { ++p; }
00601                  if( *p == '\0' )  return 1;
00602                  if( *p == 'e' || *p =='E')  return ExpectExponent(++p);
00603                  if( *p == '.' ) { ++p;
00604                       if( *p == '\0' )  return 1;
00605                       if( *p == 'e' || *p =='E')  return ExpectExponent(++p);
00606                       if( isdigit(*p) ) {
00607                           while( isdigit( (G4int)(*p) )) { ++p; }
00608                           if( *p == '\0' )  return 1;
00609                           if( *p == 'e' || *p =='E') return ExpectExponent(++p);
00610                       }
00611                  }
00612             }
00613      }
00614      return 0;
00615 }
00616 
00617 
00618 // ------------------ range Check routines -------------------
00619 G4int G4UIcommand::
00620 RangeCheck(const char* t) {
00621     yystype result;
00622     char type;
00623     bp = 0;                 // reset buffer pointer for G4UIpGetc()
00624     std::istringstream is(t);
00625     for (unsigned i=0; i< parameter.size(); i++) {
00626         type= toupper(parameter[i]->GetParameterType());
00627         switch ( type ) {
00628             case 'D':  is >> newVal[i].D;  break;
00629             case 'I':  is >> newVal[i].I;  break;
00630             case 'S':
00631             case 'B':
00632             default:  ;
00633         }
00634    }
00635    // PrintToken();          // Print tokens (consumes all tokens)
00636    token= Yylex();
00637    result = Expression();
00638 
00639    if( paramERR == 1 ) return 0;
00640    if( result.type != CONSTINT) {
00641       G4cerr << "Illegal Expression in parameter range." << G4endl;
00642       return 0;
00643    }
00644    if ( result.I ) return 1;
00645    G4cerr << "parameter out of range: "<< rangeString << G4endl;
00646    return 0;
00647 }
00648 
00649 // ------------------ syntax node functions  ------------------
00650 yystype G4UIcommand:: 
00651 Expression(void)
00652 {
00653     yystype result;
00654     #ifdef DEBUG
00655         G4cerr << " Expression()" << G4endl;
00656     #endif
00657     result = LogicalORExpression();
00658     return result;
00659 }
00660 
00661 yystype G4UIcommand:: 
00662 LogicalORExpression(void)
00663 {
00664     yystype result;
00665     yystype p;
00666     p = LogicalANDExpression();
00667     if( token != LOGICALOR)  return p;
00668     if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
00669         G4cerr << "Parameter range: illegal type at '||'" << G4endl;
00670         paramERR = 1;
00671     }
00672     result.I = p.I;
00673     while (token == LOGICALOR) 
00674     {  
00675         token = Yylex();
00676         p = LogicalANDExpression();
00677         if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
00678             G4cerr << "Parameter range: illegal type at '||'" <<G4endl;
00679             paramERR = 1;
00680         }
00681         switch (p.type) {
00682             case CONSTINT: 
00683                 result.I  += p.I; 
00684                 result.type = CONSTINT;      break;
00685             case CONSTDOUBLE:
00686                 result.I += (p.D != 0.0); 
00687                 result.type = CONSTINT;      break;
00688             default: 
00689                 G4cerr << "Parameter range: unknown type"<<G4endl; 
00690                 paramERR = 1;
00691         } 
00692     }
00693     return result;
00694 }
00695 
00696 yystype G4UIcommand:: 
00697 LogicalANDExpression(void)
00698 {
00699     yystype result;
00700     yystype p;
00701     p = EqualityExpression();
00702     if( token != LOGICALAND)  return p;
00703     if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
00704         G4cerr << "Parameter range: illegal type at '&&'" << G4endl;
00705         paramERR = 1;
00706     }
00707     result.I = p.I;
00708     while (token == LOGICALAND)
00709     {
00710         token = Yylex();
00711         p = EqualityExpression();
00712         if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
00713             G4cerr << "Parameter range: illegal type at '&&'" << G4endl;
00714             paramERR = 1;
00715         }
00716         switch (p.type) {
00717             case CONSTINT:
00718                 result.I  *= p.I;
00719                 result.type = CONSTINT;      break;
00720             case CONSTDOUBLE:
00721                 result.I *= (p.D != 0.0);
00722                 result.type = CONSTINT;      break;
00723             default:
00724                 G4cerr << "Parameter range: unknown type."<< G4endl;
00725                 paramERR = 1;
00726         } 
00727     }
00728     return result;
00729 }
00730 
00731 
00732 yystype G4UIcommand:: 
00733 EqualityExpression(void)
00734 { 
00735     yystype  arg1, arg2;
00736     G4int operat;
00737     yystype result;
00738     #ifdef DEBUG
00739         G4cerr << " EqualityExpression()" <<G4endl;
00740     #endif
00741     result = RelationalExpression();
00742     if( token==EQ || token==NE ) {
00743         operat = token;
00744         token =  Yylex();
00745         arg1 = result;
00746         arg2 = RelationalExpression();
00747         result.I = Eval2( arg1, operat, arg2 );   // semantic action
00748         result.type = CONSTINT;
00749         #ifdef DEBUG
00750             G4cerr << " return code of Eval2(): " << result.I <<G4endl;
00751         #endif
00752     } else {
00753         if (result.type != CONSTINT && result.type != CONSTDOUBLE) {  
00754             G4cerr << "Parameter range: error at EqualityExpression"
00755                  << G4endl;
00756             paramERR = 1;
00757         }
00758     }
00759     return  result;
00760 }
00761 
00762 
00763 yystype G4UIcommand:: 
00764 RelationalExpression(void)
00765 { 
00766     yystype  arg1, arg2;
00767     G4int operat;
00768     yystype result;
00769     #ifdef DEBUG
00770         G4cerr << " RelationalExpression()" <<G4endl;
00771     #endif
00772 
00773     arg1 = AdditiveExpression();
00774     if( token==GT || token==GE || token==LT || token==LE  ) {
00775         operat = token;
00776         token =  Yylex();
00777         arg2 = AdditiveExpression();
00778         result.I = Eval2( arg1, operat, arg2 );    // semantic action
00779         result.type = CONSTINT;
00780         #ifdef DEBUG
00781             G4cerr << " return code of Eval2(): " << result.I << G4endl;
00782         #endif
00783     } else {
00784               result = arg1;
00785     }
00786     #ifdef DEBUG
00787        G4cerr <<" return RelationalExpression()"<< G4endl;
00788     #endif
00789     return  result;
00790 }
00791 
00792 yystype G4UIcommand::
00793 AdditiveExpression(void)
00794 {   yystype result;
00795     result = MultiplicativeExpression();
00796     if( token != '+' && token != '-' )  return result;
00797     G4cerr << "Parameter range: operator " 
00798          << (char)token 
00799          << " is not supported." << G4endl;
00800     paramERR = 1;
00801     return  result;
00802 }
00803 
00804 yystype G4UIcommand::
00805 MultiplicativeExpression(void)
00806 {   yystype result;
00807     result = UnaryExpression();
00808     if( token != '*' && token != '/' && token != '%' ) return result;
00809     G4cerr << "Parameter range: operator "
00810          << (char)token
00811          << " is not supported." << G4endl;
00812     paramERR = 1;
00813     return  result;
00814 }
00815 
00816 yystype G4UIcommand::
00817 UnaryExpression(void)
00818 {
00819     yystype result;
00820     yystype p;
00821     #ifdef DEBUG
00822         G4cerr <<" UnaryExpression"<< G4endl;
00823     #endif
00824     switch(token) {
00825         case '-':
00826             token = Yylex();
00827             p = UnaryExpression();
00828             if (p.type == CONSTINT) {
00829                 result.I = - p.I;
00830                 result.type = CONSTINT;
00831             }
00832             if (p.type == CONSTDOUBLE) {
00833                 result.D = - p.D;
00834                 result.type = CONSTDOUBLE;
00835             }                              break;
00836         case '+':
00837             token = Yylex();
00838             result = UnaryExpression();   break;
00839         case '!':
00840             token = Yylex();
00841             G4cerr << "Parameter range error: "
00842                  << "operator '!' is not supported (sorry)."
00843                  << G4endl;
00844             paramERR = 1;
00845             result = UnaryExpression();   break;
00846         default:
00847             result = PrimaryExpression();
00848     }
00849     return result;
00850 }
00851 
00852 
00853 yystype G4UIcommand:: 
00854 PrimaryExpression(void)
00855 {
00856      yystype result;
00857      #ifdef DEBUG
00858          G4cerr <<" primary_exp"<<G4endl;
00859      #endif
00860      switch (token) {
00861          case IDENTIFIER:
00862               result.S = yylval.S;
00863               result.type =  token;
00864               token = Yylex();           break;
00865          case CONSTINT:
00866               result.I = yylval.I;
00867               result.type =  token;
00868               token= Yylex();            break;
00869          case CONSTDOUBLE:
00870               result.D = yylval.D;
00871               result.type =  token;
00872               token = Yylex();           break;
00873          case '(' :
00874               token= Yylex();
00875               result = Expression();
00876               if( token !=  ')'  ) {
00877                   G4cerr << " ')' expected" << G4endl;
00878                   paramERR = 1;
00879               }
00880               token = Yylex();
00881                                          break;
00882          default:
00883          return result;
00884     }
00885     return result; // never executed
00886 }
00887 
00888 //---------------- semantic routines ---------------------------------
00889 
00890 G4int G4UIcommand::
00891 Eval2(yystype arg1, G4int op, yystype arg2)
00892 {
00893     char newValtype;
00894     if( (arg1.type != IDENTIFIER) && (arg2.type != IDENTIFIER)) {
00895         G4cerr << commandName
00896              << ": meaningless comparison"
00897              << G4endl;
00898         paramERR = 1;
00899     }
00900 
00901     if( arg1.type == IDENTIFIER) {
00902         unsigned i = IndexOf( arg1.S );
00903         newValtype = toupper(parameter[i]->GetParameterType());
00904         switch ( newValtype ) {
00905             case 'I': 
00906                 if( arg2.type == CONSTINT ) {
00907                     return CompareInt( newVal[i].I, op, arg2.I );
00908                 } else {
00909                     G4cerr << "integer operand expected for "
00910                          <<  rangeString 
00911                          << '.' << G4endl;
00912                 } break;
00913             case 'D':
00914                 if( arg2.type == CONSTDOUBLE ) {
00915                     return CompareDouble( newVal[i].D, op, arg2.D );
00916                 } else
00917                 if ( arg2.type == CONSTINT ) {  // integral promotion
00918                     return CompareDouble( newVal[i].D, op, arg2.I );
00919                 } break;
00920             default: ;
00921         }
00922     }
00923     if( arg2.type == IDENTIFIER) {
00924         unsigned i = IndexOf( arg2.S );
00925         newValtype = toupper(parameter[i]->GetParameterType());
00926         switch ( newValtype ) {
00927             case 'I': 
00928                 if( arg1.type == CONSTINT ) {
00929                     return CompareInt( arg1.I, op, newVal[i].I );
00930                 } else {
00931                     G4cerr << "integer operand expected for "
00932                          <<  rangeString
00933                          << '.' << G4endl;
00934                 } break;
00935             case 'D':
00936                 if( arg1.type == CONSTDOUBLE ) {
00937                     return CompareDouble( arg1.D, op, newVal[i].D );
00938                 } else
00939                 if ( arg1.type == CONSTINT ) {  // integral promotion
00940                     return CompareDouble( arg1.I, op, newVal[i].D );
00941                 } break;
00942             default: ;
00943         }
00944     }
00945     return 0;
00946 }
00947 
00948 G4int G4UIcommand::
00949 CompareInt(G4int arg1, G4int op, G4int arg2)
00950 {   
00951     G4int result=-1;
00952     G4String opr;
00953     switch (op) {
00954        case GT:  result = ( arg1 >  arg2); opr= ">" ;  break;
00955        case GE:  result = ( arg1 >= arg2); opr= ">=";  break;
00956        case LT:  result = ( arg1 <  arg2); opr= "<" ;  break;
00957        case LE:  result = ( arg1 <= arg2); opr= "<=";  break;
00958        case EQ:  result = ( arg1 == arg2); opr= "==";  break;
00959        case NE:  result = ( arg1 != arg2); opr= "!=";  break;
00960        default: 
00961            G4cerr << "Parameter range: error at CompareInt" << G4endl;
00962            paramERR = 1;
00963     }
00964     #ifdef DEBUG
00965         G4cerr << "CompareInt "
00966              << arg1 << " " << opr << arg2 
00967              << " result: " << result
00968              << G4endl;
00969     #endif
00970     return result;
00971 }
00972 
00973 G4int G4UIcommand::
00974 CompareDouble(G4double arg1, G4int op, G4double arg2)
00975 {   
00976     G4int result=-1;
00977     G4String opr;
00978     switch (op) {
00979         case GT:  result = ( arg1 >  arg2); opr= ">";   break;
00980         case GE:  result = ( arg1 >= arg2); opr= ">=";  break;
00981         case LT:  result = ( arg1 <  arg2); opr= "<";   break;
00982         case LE:  result = ( arg1 <= arg2); opr= "<=";  break;
00983         case EQ:  result = ( arg1 == arg2); opr= "==";  break;
00984         case NE:  result = ( arg1 != arg2); opr= "!=";  break;
00985         default:
00986            G4cerr << "Parameter range: error at CompareDouble"
00987                 << G4endl;
00988            paramERR = 1;
00989     }
00990     #ifdef DEBUG
00991         G4cerr << "CompareDouble " 
00992              << arg1 <<" " << opr << " "<< arg2
00993              << " result: " << result
00994              << G4endl;
00995     #endif
00996     return result;
00997 }
00998 
00999 unsigned G4UIcommand::
01000 IndexOf(const char* nam)
01001 {
01002     unsigned i;
01003     G4String pname;
01004     for( i=0;  i<parameter.size(); i++)
01005     {
01006         pname = parameter[i]-> GetParameterName();
01007         if( pname == nam ) {
01008             return i;
01009         }
01010     }
01011     paramERR = 1;
01012     G4cerr << "parameter name:"<<nam<<" not found."<< G4endl;
01013     return 0;
01014 }
01015 
01016 
01017 unsigned G4UIcommand::
01018 IsParameter(const char* nam)
01019 {
01020     G4String pname;
01021     for(unsigned i=0;  i<parameter.size(); i++)  
01022     {
01023         pname = parameter[i]-> GetParameterName();
01024         if( pname == nam ) return 1;
01025     }
01026     return 0;
01027 }
01028 
01029 
01030 // --------------------- utility functions --------------------------
01031 
01032 tokenNum G4UIcommand::
01033 Yylex()         // reads input and returns token number, KR486
01034 {               // (returns EOF)
01035     G4int c;             
01036     G4String buf;
01037 
01038     while(( c= G4UIpGetc())==' '|| c=='\t' || c== '\n' )
01039         ;
01040     if (c== EOF)
01041         return (tokenNum)EOF;            // KR488 
01042     buf= "";
01043     if (isdigit(c) || c== '.') {         // I or D
01044         do {
01045              buf += G4String((unsigned char)c);
01046              c=G4UIpGetc();
01047          }  while (c=='.' || isdigit(c) || 
01048                    c=='e' || c=='E' || c=='+' || c=='-');
01049          G4UIpUngetc(c);
01050          const char* t = buf;
01051          std::istringstream is(t);
01052          if ( IsInt(buf.data(),20) ) {
01053              is >> yylval.I;
01054              return  CONSTINT;
01055          } else 
01056          if ( IsDouble(buf.data()) ) {
01057              is >> yylval.D;
01058              return  CONSTDOUBLE;
01059          } else {
01060              G4cerr << buf<<": numeric format error."<<G4endl;
01061          }
01062     }
01063     buf="";
01064     if (isalpha(c)|| c=='_') {           // IDENTIFIER
01065         do {
01066             buf += G4String((unsigned char)c); 
01067         } while ((c=G4UIpGetc()) != EOF && (isalnum(c) || c=='_'));
01068         G4UIpUngetc(c);
01069         if( IsParameter(buf) ) {
01070             yylval.S =buf;
01071             return IDENTIFIER;
01072         } else {
01073             G4cerr << buf << " is not a parameter name."<< G4endl;
01074             paramERR = 1;
01075        }
01076     }
01077     switch (c) {
01078       case '>':   return (tokenNum) Follow('=', GE,        GT);
01079       case '<':   return (tokenNum) Follow('=', LE,        LT);
01080       case '=':   return (tokenNum) Follow('=', EQ,        '=');
01081       case '!':   return (tokenNum) Follow('=', NE,        '!');
01082       case '|':   return (tokenNum) Follow('|', LOGICALOR, '|');
01083       case '&':   return (tokenNum) Follow('&', LOGICALAND, '&');
01084       default:
01085           return (tokenNum) c;
01086     }
01087 }
01088 
01089 
01090 G4int G4UIcommand::
01091 Follow(G4int expect, G4int ifyes, G4int ifno)
01092 {
01093     G4int c = G4UIpGetc();
01094     if ( c== expect)
01095           return ifyes;
01096     G4UIpUngetc(c);
01097     return ifno;
01098 }
01099 
01100 //------------------ low level routines -----------------------------
01101 G4int G4UIcommand::
01102 G4UIpGetc() {                        // emulation of getc() 
01103     G4int length = rangeString.length();
01104     if( bp < length)
01105         return  rangeString(bp++);
01106     else 
01107         return EOF;
01108 }
01109 G4int G4UIcommand::
01110 G4UIpUngetc(G4int c) {                 // emulation of ungetc() 
01111     if (c<0) return -1;
01112     if (bp >0 && c == rangeString(bp-1)) {
01113          --bp;
01114     } else {
01115          G4cerr << "G4UIpUngetc() failed." << G4endl;
01116          G4cerr << "bp="<<bp <<" c="<<c
01117               << " pR(bp-1)=" << rangeString(bp-1)
01118               << G4endl;
01119          paramERR = 1;
01120          return -1;
01121     }
01122     return 0;
01123 }

Generated on Mon May 27 17:50:05 2013 for Geant4 by  doxygen 1.4.7