source: trunk/source/intercoms/src/G4UIcommand.cc @ 1202

Last change on this file since 1202 was 1016, checked in by garnier, 15 years ago

update

File size: 31.6 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer                                           *
4// *                                                                  *
5// * The  Geant4 software  is  copyright of the Copyright Holders  of *
6// * the Geant4 Collaboration.  It is provided  under  the terms  and *
7// * conditions of the Geant4 Software License,  included in the file *
8// * LICENSE and available at  http://cern.ch/geant4/license .  These *
9// * include a list of copyright holders.                             *
10// *                                                                  *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work  make  any representation or  warranty, express or implied, *
14// * regarding  this  software system or assume any liability for its *
15// * use.  Please see the license in the file  LICENSE  and URL above *
16// * for the full disclaimer and the limitation of liability.         *
17// *                                                                  *
18// * This  code  implementation is the result of  the  scientific and *
19// * technical work of the GEANT4 collaboration.                      *
20// * By using,  copying,  modifying or  distributing the software (or *
21// * any work based  on the software)  you  agree  to acknowledge its *
22// * use  in  resulting  scientific  publications,  and indicate your *
23// * acceptance of all terms of the Geant4 Software license.          *
24// ********************************************************************
25//
26//
27// $Id: G4UIcommand.cc,v 1.25 2006/06/29 19:08:56 gunter Exp $
28// GEANT4 tag $Name: geant4-09-02 $
29//
30//
31
32#include "G4UIcommand.hh"
33#include "G4UImessenger.hh"
34#include "G4UImanager.hh"
35#include "G4UIcommandStatus.hh"
36#include "G4StateManager.hh"
37#include "G4UnitsTable.hh"
38#include "G4Tokenizer.hh"
39#include "G4ios.hh"
40#include <sstream>
41
42G4UIcommand::G4UIcommand()
43:messenger(0),token(IDENTIFIER),paramERR(0)
44{;}
45
46G4UIcommand::G4UIcommand(const char * theCommandPath,
47                         G4UImessenger * theMessenger)
48:messenger(theMessenger),token(IDENTIFIER),paramERR(0)
49{
50  G4String comStr = theCommandPath;
51  if(!theMessenger)
52  { // this must be a directory
53    if(comStr(comStr.length()-1)!='/')
54    {
55      G4cerr << "G4UIcommand Warning : " << G4endl;
56      G4cerr << "  <" << theCommandPath << "> must be a directory." << G4endl;
57      G4cerr << "  '/' is appended." << G4endl;
58      comStr += "/";
59    }
60  }
61  G4UIcommandCommonConstructorCode (comStr);
62  G4String nullString;
63  availabelStateList.clear();
64  availabelStateList.push_back(G4State_PreInit);
65  availabelStateList.push_back(G4State_Init);
66  availabelStateList.push_back(G4State_Idle);
67  availabelStateList.push_back(G4State_GeomClosed);
68  availabelStateList.push_back(G4State_EventProc);
69  availabelStateList.push_back(G4State_Abort);
70}
71
72void G4UIcommand::G4UIcommandCommonConstructorCode
73(const char * theCommandPath)
74{ 
75  commandPath = theCommandPath;
76  commandName = theCommandPath;
77  G4int commandNameIndex = commandName.last('/');
78  commandName.remove(0,commandNameIndex+1);
79
80  G4UImanager::GetUIpointer()->AddNewCommand(this);
81}
82
83G4UIcommand::~G4UIcommand()
84{
85  G4UImanager* fUImanager = G4UImanager::GetUIpointer();
86  if(fUImanager) fUImanager->RemoveCommand(this);
87 
88  G4int n_parameterEntry = parameter.size();
89  for( G4int i_thParameter=0; i_thParameter < n_parameterEntry; i_thParameter++ )
90  { delete parameter[i_thParameter]; }
91  parameter.clear();
92}
93
94G4int G4UIcommand::operator==(const G4UIcommand &right) const
95{
96  return ( commandPath == right.GetCommandPath() );
97}
98
99G4int G4UIcommand::operator!=(const G4UIcommand &right) const
100{
101  return ( commandPath != right.GetCommandPath() );
102}
103
104G4int G4UIcommand::DoIt(G4String parameterList)
105{
106  G4String correctParameters;
107  G4int n_parameterEntry = parameter.size();
108  if( n_parameterEntry != 0 )
109  {
110    G4String aToken;
111    G4String correctToken;
112    G4Tokenizer parameterToken( parameterList );
113    for( G4int i_thParameter=0; i_thParameter<n_parameterEntry; i_thParameter++ )
114    {
115      if(i_thParameter > 0)
116      {
117        correctParameters.append(" ");
118      }
119      aToken = parameterToken();
120      if( aToken.length()>0 && aToken(0)=='"' )
121      {
122        while( aToken(aToken.length()-1) != '"'
123               || ( aToken.length()==1 && aToken(0)=='"' ))
124        {
125          G4String additionalToken = parameterToken();
126          if( additionalToken.isNull() )
127          { return fParameterUnreadable+i_thParameter; }
128          aToken += " ";
129          aToken += additionalToken;
130        }
131      }
132      else if(i_thParameter==n_parameterEntry-1 && parameter[i_thParameter]->GetParameterType()=='s')
133      {
134        G4String anotherToken;
135        while(!((anotherToken=parameterToken()).isNull()))
136        {
137          G4int idxs = anotherToken.index("#");
138          if(idxs==G4int(std::string::npos))
139          {
140            aToken += " ";
141            aToken += anotherToken;
142          }
143          else if(idxs>0)
144          {
145            aToken += " ";
146            aToken += anotherToken(0,idxs);
147            break;
148          }
149          else
150          { break; }
151        }
152      }
153
154      if( aToken.isNull() || aToken == "!" )
155      {
156        if(parameter[i_thParameter]->IsOmittable())
157        { 
158          if(parameter[i_thParameter]->GetCurrentAsDefault())
159          {
160            G4Tokenizer cvSt(messenger->GetCurrentValue(this));
161            G4String parVal;
162            for(G4int ii=0;ii<i_thParameter;ii++)
163            {
164              parVal = cvSt();
165              if (parVal(0)=='"')
166                {
167                  while( parVal(parVal.length()-1) != '"' )
168                    {
169                      G4String additionalToken = cvSt();
170                      if( additionalToken.isNull() )
171                        { return fParameterUnreadable+i_thParameter; }
172                      parVal += " ";
173                      parVal += additionalToken;
174                    }
175                }
176            }
177            G4String aCVToken = cvSt();
178            if (aCVToken(0)=='"')
179            {
180              while( aCVToken(aCVToken.length()-1) != '"' )
181              {
182                G4String additionalToken = cvSt();
183                if( additionalToken.isNull() )
184                { return fParameterUnreadable+i_thParameter; }
185                aCVToken += " ";
186                aCVToken += additionalToken;
187              }
188              // aCVToken.strip(G4String::both,'"');
189            }
190            correctParameters.append(aCVToken);
191          }
192          else
193          { correctParameters.append(parameter[i_thParameter]->GetDefaultValue()); }
194        }
195        else
196        { return fParameterUnreadable+i_thParameter; }
197      }
198      else
199      {
200        G4int stat = parameter[i_thParameter]->CheckNewValue( aToken );
201        if(stat) return stat+i_thParameter;
202        correctParameters.append(aToken);
203      }
204    }
205  }
206
207  if(CheckNewValue( correctParameters ))
208  { return fParameterOutOfRange+99; }
209
210  messenger->SetNewValue( this, correctParameters );
211  return 0;
212}
213
214G4String G4UIcommand::GetCurrentValue()
215{
216  return messenger->GetCurrentValue(this);
217}
218
219void G4UIcommand::AvailableForStates(G4ApplicationState s1)
220{
221  availabelStateList.clear();
222  availabelStateList.push_back(s1);
223}
224
225void G4UIcommand::AvailableForStates(G4ApplicationState s1,
226                                     G4ApplicationState s2)
227{
228  availabelStateList.clear();
229  availabelStateList.push_back(s1);
230  availabelStateList.push_back(s2);
231}
232
233void G4UIcommand::AvailableForStates(G4ApplicationState s1,
234                                     G4ApplicationState s2,
235                                     G4ApplicationState s3)
236{
237  availabelStateList.clear();
238  availabelStateList.push_back(s1);
239  availabelStateList.push_back(s2);
240  availabelStateList.push_back(s3);
241}
242
243void G4UIcommand::AvailableForStates(G4ApplicationState s1,
244                                     G4ApplicationState s2,
245                                     G4ApplicationState s3,
246                                     G4ApplicationState s4)
247{
248  availabelStateList.clear();
249  availabelStateList.push_back(s1);
250  availabelStateList.push_back(s2);
251  availabelStateList.push_back(s3);
252  availabelStateList.push_back(s4);
253}
254
255void G4UIcommand::AvailableForStates(G4ApplicationState s1,
256                                     G4ApplicationState s2,
257                                     G4ApplicationState s3,
258                                     G4ApplicationState s4,
259                                     G4ApplicationState s5)
260{
261  availabelStateList.clear();
262  availabelStateList.push_back(s1);
263  availabelStateList.push_back(s2);
264  availabelStateList.push_back(s3);
265  availabelStateList.push_back(s4);
266  availabelStateList.push_back(s5);
267}
268
269G4bool G4UIcommand::IsAvailable()
270{
271  G4bool av = false;
272  G4ApplicationState currentState
273   = G4StateManager::GetStateManager()->GetCurrentState();
274   
275  G4int nState = availabelStateList.size();
276  for(G4int i=0;i<nState;i++)
277  {
278        if(availabelStateList[i]==currentState)
279        {
280          av = true;
281          break;
282        }
283  }
284
285  return av;
286}
287
288G4double G4UIcommand::ValueOf(const char* unitName)
289{
290   G4double value = 0.;
291   value = G4UnitDefinition::GetValueOf(unitName);
292   return value;             
293}
294
295G4String G4UIcommand::CategoryOf(const char* unitName)
296{
297   return G4UnitDefinition::GetCategory(unitName);
298}
299
300G4String G4UIcommand::UnitsList(const char* unitCategory)
301{
302  G4String retStr;
303  G4UnitsTable& UTbl = G4UnitDefinition::GetUnitsTable();
304  size_t i;
305  for(i=0;i<UTbl.size();i++)
306  { if(UTbl[i]->GetName()==unitCategory) break; }
307  if(i==UTbl.size())
308  { 
309    G4cerr << "Unit category <" << unitCategory << "> is not defined." << G4endl;
310    return retStr;
311  }
312  G4UnitsContainer& UCnt = UTbl[i]->GetUnitsList();
313  retStr = UCnt[0]->GetSymbol();
314  G4int je = UCnt.size();
315  for(G4int j=1;j<je;j++)
316  {
317    retStr += " ";
318    retStr += UCnt[j]->GetSymbol();
319  }
320  for(G4int k=0;k<je;k++)
321  {
322    retStr += " ";
323    retStr += UCnt[k]->GetName();
324  }
325  return retStr;
326}
327 
328void G4UIcommand::List()
329{
330  G4cout << G4endl;
331  G4cout << G4endl;
332  if(commandPath(commandPath.length()-1)!='/')
333  { G4cout << "Command " << commandPath << G4endl; }
334  G4cout << "Guidance :" << G4endl;
335  G4int n_guidanceEntry = commandGuidance.size();
336  for( G4int i_thGuidance=0; i_thGuidance < n_guidanceEntry; i_thGuidance++ )
337  { G4cout << commandGuidance[i_thGuidance] << G4endl; }
338  if( ! rangeString.isNull() )
339  { G4cout << " Range of parameters : " << rangeString << G4endl; }
340  G4int n_parameterEntry = parameter.size();
341  if( n_parameterEntry > 0 )
342  {
343    for( G4int i_thParameter=0; i_thParameter<n_parameterEntry; i_thParameter++ )
344    { parameter[i_thParameter]->List(); }
345  }
346  G4cout << G4endl;
347}
348
349G4String G4UIcommand::ConvertToString(G4bool boolVal)
350{
351  G4String vl = "0";
352  if(boolVal) vl = "1";
353  return vl;
354}
355
356G4String G4UIcommand::ConvertToString(G4int intValue)
357{
358  std::ostringstream os;
359  os << intValue;
360  G4String vl = os.str();
361  return vl;
362}
363
364G4String G4UIcommand::ConvertToString(G4double doubleValue)
365{
366  std::ostringstream os;
367  os << doubleValue;
368  G4String vl = os.str();
369  return vl;
370}
371
372G4String G4UIcommand::ConvertToString(G4double doubleValue,const char* unitName)
373{
374  G4String unt = unitName;
375  G4double uv = ValueOf(unitName);
376
377  std::ostringstream os;
378  os << doubleValue/uv << " " << unitName;
379  G4String vl = os.str();
380  return vl;
381}
382
383G4String G4UIcommand::ConvertToString(G4ThreeVector vec)
384{
385  std::ostringstream os;
386  os << vec.x() << " " << vec.y() << " " << vec.z();
387  G4String vl = os.str();
388  return vl;
389}
390
391G4String G4UIcommand::ConvertToString(G4ThreeVector vec,const char* unitName)
392{
393  G4String unt = unitName;
394  G4double uv = ValueOf(unitName);
395
396  std::ostringstream os;
397  os << vec.x()/uv << " " << vec.y()/uv << " " << vec.z()/uv
398     << " " << unitName;
399  G4String vl = os.str();
400  return vl;
401}
402
403G4bool G4UIcommand::ConvertToBool(const char* st)
404{
405  G4String v = st;
406  v.toUpper();
407  G4bool vl = false;
408  if( v=="Y" || v=="YES" || v=="1" || v=="T" || v=="TRUE" )
409  { vl = true; }
410  return vl;
411}
412
413G4int G4UIcommand::ConvertToInt(const char* st)
414{
415  G4int vl;
416  std::istringstream is(st);
417  is >> vl;
418  return vl;
419}
420
421G4double G4UIcommand::ConvertToDouble(const char* st)
422{
423  G4double vl;
424  std::istringstream is(st);
425  is >> vl;
426  return vl;
427}
428
429G4double G4UIcommand::ConvertToDimensionedDouble(const char* st)
430{
431  G4double vl;
432  char unts[30];
433
434  std::istringstream is(st);
435  is >> vl >> unts;
436  G4String unt = unts;
437
438  return (vl*ValueOf(unt));
439}
440
441G4ThreeVector G4UIcommand::ConvertTo3Vector(const char* st)
442{
443  G4double vx;
444  G4double vy;
445  G4double vz;
446  std::istringstream is(st);
447  is >> vx >> vy >> vz;
448  return G4ThreeVector(vx,vy,vz);
449}
450
451G4ThreeVector G4UIcommand::ConvertToDimensioned3Vector(const char* st)
452{
453  G4double vx;
454  G4double vy;
455  G4double vz;
456  char unts[30];
457  std::istringstream is(st);
458  is >> vx >> vy >> vz >> unts;
459  G4String unt = unts;
460  G4double uv = ValueOf(unt);
461  return G4ThreeVector(vx*uv,vy*uv,vz*uv);
462}
463
464
465// ----- the following is used by CheckNewValue()  ------------
466
467
468#include <ctype.h>          // isalpha(), toupper()
469
470//#include "checkNewValue_debug.icc"
471//#define DEBUG 1
472
473G4int G4UIcommand::
474CheckNewValue(const char * newValue)
475{
476   yystype result;
477   // if( TypeCheck(newValue) == 0 ) return 1;
478   if( ! rangeString.isNull() )
479   { if( RangeCheck(newValue) == 0 ) return fParameterOutOfRange; }
480   return 0;  // succeeded
481}
482
483// ------------------ type check routines -------------------
484
485G4int G4UIcommand::
486TypeCheck(const char * t)
487{
488    G4String aNewValue;
489    char type;
490    std::istringstream is(t);
491    for (unsigned i=0; i< parameter.size(); i++) {
492        is >> aNewValue;
493        type = toupper(parameter[i]->GetParameterType());
494        switch ( type ) {
495            case 'D':
496                if( IsDouble(aNewValue)==0 ){
497                    G4cerr << aNewValue << ": double value expected."
498                         << G4endl;
499                    return 0;
500                } break;
501            case 'I':
502                if( IsInt(aNewValue,20)==0 ){
503                    G4cerr <<aNewValue<<": integer expected."
504                         <<G4endl;
505                     return 0;
506                } break;
507            case 'S':
508                break;
509            case 'B':
510                aNewValue.toUpper(); 
511                if (aNewValue == "Y"   || aNewValue == "N"
512                  ||aNewValue == "YES" || aNewValue == "NO"
513                  ||aNewValue == "1"   || aNewValue == "0"
514                  ||aNewValue == "T"   || aNewValue == "F"
515                  ||aNewValue == "TRUE" || aNewValue == "FALSE")
516                return 1;
517                else return 0; 
518                break;
519            default:  ;
520        }
521    }
522    return 1;
523}
524
525
526G4int G4UIcommand::
527IsInt(const char* buf, short maxDigits)
528{
529    const char* p= buf;
530    G4int length=0;
531    if( *p == '+' || *p == '-') { ++p; }
532    if( isdigit( (G4int)(*p) )) {
533        while( isdigit( (G4int)(*p) )) { ++p;  ++length; }
534        if( *p == '\0' ) {
535            if( length > maxDigits) {
536                G4cerr <<"digit length exceeds"<<G4endl;
537                return 0;
538            }
539            return 1;
540        } else {
541            // G4cerr <<"illegal character after int:"<<buf<<G4endl;
542        }
543    } else {
544        // G4cerr <<"illegal int:"<<buf<<G4endl;
545    }
546    return 0;
547}
548
549
550G4int G4UIcommand::
551ExpectExponent(const char* str)   // used only by IsDouble()
552{
553    G4int maxExplength;
554    if( IsInt( str, maxExplength=7 )) return 1;
555    else return 0;
556}
557
558
559G4int G4UIcommand::
560IsDouble(const char* buf)
561{
562    const char* p= buf;
563    switch( *p) {
564        case '+':  case '-': ++p;
565            if( isdigit(*p) ) {
566                 while( isdigit( (G4int)(*p) )) { ++p; }
567                 switch ( *p ) {
568                     case '\0':    return 1;
569                        // break;
570                     case 'E':  case 'e':
571                         return ExpectExponent(++p );
572                        // break;
573                     case '.':  ++p;
574                         if( *p == '\0' )  return 1;
575                         if( *p == 'e' || *p =='E' ) return ExpectExponent(++p );
576                         if( isdigit(*p) ) {
577                             while( isdigit( (G4int)(*p) )) { ++p; }
578                             if( *p == '\0' )  return 1;
579                             if( *p == 'e' || *p =='E') return ExpectExponent(++p);
580                         } else return 0;   break;
581                     default: return 0;
582                 }
583            }
584            if( *p == '.' ) { ++p;
585                 if( isdigit(*p) ) {
586                     while( isdigit( (G4int)(*p) )) { ++p; }
587                     if( *p == '\0' )  return 1;
588                     if( *p == 'e' || *p =='E')  return ExpectExponent(++p);
589                 }
590            }
591            break;
592        case '.':  ++p;
593            if( isdigit(*p) ) {
594                 while( isdigit( (G4int)(*p) )) { ++p; }
595                 if( *p == '\0' )  return 1;
596                 if( *p == 'e' || *p =='E' )  return ExpectExponent(++p);
597            }    break;
598        default: // digit is expected
599            if( isdigit(*p) ) {
600                 while( isdigit( (G4int)(*p) )) { ++p; }
601                 if( *p == '\0' )  return 1;
602                 if( *p == 'e' || *p =='E')  return ExpectExponent(++p);
603                 if( *p == '.' ) { ++p;
604                      if( *p == '\0' )  return 1;
605                      if( *p == 'e' || *p =='E')  return ExpectExponent(++p);
606                      if( isdigit(*p) ) {
607                          while( isdigit( (G4int)(*p) )) { ++p; }
608                          if( *p == '\0' )  return 1;
609                          if( *p == 'e' || *p =='E') return ExpectExponent(++p);
610                      }
611                 }
612            }
613     }
614     return 0;
615}
616
617
618// ------------------ range Check routines -------------------
619G4int G4UIcommand::
620RangeCheck(const char* t) {
621    yystype result;
622    char type;
623    bp = 0;                 // reset buffer pointer for G4UIpGetc()
624    std::istringstream is(t);
625    for (unsigned i=0; i< parameter.size(); i++) {
626        type= toupper(parameter[i]->GetParameterType());
627        switch ( type ) {
628            case 'D':  is >> newVal[i].D;  break;
629            case 'I':  is >> newVal[i].I;  break;
630            case 'S':
631            case 'B':
632            default:  ;
633        }
634   }
635   // PrintToken();          // Print tokens (consumes all tokens)
636   token= Yylex();
637   result = Expression();
638
639   if( paramERR == 1 ) return 0;
640   if( result.type != CONSTINT) {
641      G4cerr << "Illegal Expression in parameter range." << G4endl;
642      return 0;
643   }
644   if ( result.I ) return 1;
645   G4cerr << "parameter out of range: "<< rangeString << G4endl;
646   return 0;
647}
648
649// ------------------ syntax node functions  ------------------
650yystype G4UIcommand:: 
651Expression(void)
652{
653    yystype result;
654    #ifdef DEBUG
655        G4cerr << " Expression()" << G4endl;
656    #endif
657    result = LogicalORExpression();
658    return result;
659}
660
661yystype G4UIcommand:: 
662LogicalORExpression(void)
663{
664    yystype result;
665    yystype p;
666    p = LogicalANDExpression();
667    if( token != LOGICALOR)  return p;
668    if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
669        G4cerr << "Parameter range: illegal type at '||'" << G4endl;
670        paramERR = 1;
671    }
672    result.I = p.I;
673    while (token == LOGICALOR) 
674    { 
675        token = Yylex();
676        p = LogicalANDExpression();
677        if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
678            G4cerr << "Parameter range: illegal type at '||'" <<G4endl;
679            paramERR = 1;
680        }
681        switch (p.type) {
682            case CONSTINT: 
683                result.+= p.I; 
684                result.type = CONSTINT;      break;
685            case CONSTDOUBLE:
686                result.I += (p.D != 0.0); 
687                result.type = CONSTINT;      break;
688            default: 
689                G4cerr << "Parameter range: unknown type"<<G4endl; 
690                paramERR = 1;
691        } 
692    }
693    return result;
694}
695
696yystype G4UIcommand:: 
697LogicalANDExpression(void)
698{
699    yystype result;
700    yystype p;
701    p = EqualityExpression();
702    if( token != LOGICALAND)  return p;
703    if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
704        G4cerr << "Parameter range: illegal type at '&&'" << G4endl;
705        paramERR = 1;
706    }
707    result.I = p.I;
708    while (token == LOGICALAND)
709    {
710        token = Yylex();
711        p = EqualityExpression();
712        if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
713            G4cerr << "Parameter range: illegal type at '&&'" << G4endl;
714            paramERR = 1;
715        }
716        switch (p.type) {
717            case CONSTINT:
718                result.*= p.I;
719                result.type = CONSTINT;      break;
720            case CONSTDOUBLE:
721                result.I *= (p.D != 0.0);
722                result.type = CONSTINT;      break;
723            default:
724                G4cerr << "Parameter range: unknown type."<< G4endl;
725                paramERR = 1;
726        } 
727    }
728    return result;
729}
730
731
732yystype G4UIcommand:: 
733EqualityExpression(void)
734{ 
735    yystype  arg1, arg2;
736    G4int operat;
737    yystype result;
738    #ifdef DEBUG
739        G4cerr << " EqualityExpression()" <<G4endl;
740    #endif
741    result = RelationalExpression();
742    if( token==EQ || token==NE ) {
743        operat = token;
744        token =  Yylex();
745        arg1 = result;
746        arg2 = RelationalExpression();
747        result.I = Eval2( arg1, operat, arg2 );   // semantic action
748        result.type = CONSTINT;
749        #ifdef DEBUG
750            G4cerr << " return code of Eval2(): " << result.I <<G4endl;
751        #endif
752    } else {
753        if (result.type != CONSTINT && result.type != CONSTDOUBLE) { 
754            G4cerr << "Parameter range: error at EqualityExpression"
755                 << G4endl;
756            paramERR = 1;
757        }
758    }
759    return  result;
760}
761
762
763yystype G4UIcommand:: 
764RelationalExpression(void)
765{ 
766    yystype  arg1, arg2;
767    G4int operat;
768    yystype result;
769    #ifdef DEBUG
770        G4cerr << " RelationalExpression()" <<G4endl;
771    #endif
772
773    arg1 = AdditiveExpression();
774    if( token==GT || token==GE || token==LT || token==LE  ) {
775        operat = token;
776        token =  Yylex();
777        arg2 = AdditiveExpression();
778        result.I = Eval2( arg1, operat, arg2 );    // semantic action
779        result.type = CONSTINT;
780        #ifdef DEBUG
781            G4cerr << " return code of Eval2(): " << result.I << G4endl;
782        #endif
783    } else {
784              result = arg1;
785    }
786    #ifdef DEBUG
787       G4cerr <<" return RelationalExpression()"<< G4endl;
788    #endif
789    return  result;
790}
791
792yystype G4UIcommand::
793AdditiveExpression(void)
794{   yystype result;
795    result = MultiplicativeExpression();
796    if( token != '+' && token != '-' )  return result;
797    G4cerr << "Parameter range: operator " 
798         << (char)token
799         << " is not supported." << G4endl;
800    paramERR = 1;
801    return  result;
802}
803
804yystype G4UIcommand::
805MultiplicativeExpression(void)
806{   yystype result;
807    result = UnaryExpression();
808    if( token != '*' && token != '/' && token != '%' ) return result;
809    G4cerr << "Parameter range: operator "
810         << (char)token
811         << " is not supported." << G4endl;
812    paramERR = 1;
813    return  result;
814}
815
816yystype G4UIcommand::
817UnaryExpression(void)
818{
819    yystype result;
820    yystype p;
821    #ifdef DEBUG
822        G4cerr <<" UnaryExpression"<< G4endl;
823    #endif
824    switch(token) {
825        case '-':
826            token = Yylex();
827            p = UnaryExpression();
828            if (p.type == CONSTINT) {
829                result.I = - p.I;
830                result.type = CONSTINT;
831            }
832            if (p.type == CONSTDOUBLE) {
833                result.D = - p.D;
834                result.type = CONSTDOUBLE;
835            }                              break;
836        case '+':
837            token = Yylex();
838            result = UnaryExpression();   break;
839        case '!':
840            token = Yylex();
841            G4cerr << "Parameter range error: "
842                 << "operator '!' is not supported (sorry)."
843                 << G4endl;
844            paramERR = 1;
845            result = UnaryExpression();   break;
846        default:
847            result = PrimaryExpression();
848    }
849    return result;
850}
851
852
853yystype G4UIcommand:: 
854PrimaryExpression(void)
855{
856     yystype result;
857     #ifdef DEBUG
858         G4cerr <<" primary_exp"<<G4endl;
859     #endif
860     switch (token) {
861         case IDENTIFIER:
862              result.S = yylval.S;
863              result.type =  token;
864              token = Yylex();           break;
865         case CONSTINT:
866              result.I = yylval.I;
867              result.type =  token;
868              token= Yylex();            break;
869         case CONSTDOUBLE:
870              result.D = yylval.D;
871              result.type =  token;
872              token = Yylex();           break;
873         case '(' :
874              token= Yylex();
875              result = Expression();
876              if( token !=  ')'  ) {
877                  G4cerr << " ')' expected" << G4endl;
878                  paramERR = 1;
879              }
880              token = Yylex();
881                                         break;
882         default:
883         return result;
884    }
885    return result; // never executed
886}
887
888//---------------- semantic routines ---------------------------------
889
890G4int G4UIcommand::
891Eval2(yystype arg1, G4int op, yystype arg2)
892{
893    char newValtype;
894    if( (arg1.type != IDENTIFIER) && (arg2.type != IDENTIFIER)) {
895        G4cerr << commandName
896             << ": meaningless comparison"
897             << G4endl;
898        paramERR = 1;
899    }
900
901    if( arg1.type == IDENTIFIER) {
902        unsigned i = IndexOf( arg1.S );
903        newValtype = toupper(parameter[i]->GetParameterType());
904        switch ( newValtype ) {
905            case 'I': 
906                if( arg2.type == CONSTINT ) {
907                    return CompareInt( newVal[i].I, op, arg2.I );
908                } else {
909                    G4cerr << "integer operand expected for "
910                         <<  rangeString
911                         << '.' << G4endl;
912                } break;
913            case 'D':
914                if( arg2.type == CONSTDOUBLE ) {
915                    return CompareDouble( newVal[i].D, op, arg2.D );
916                } else
917                if ( arg2.type == CONSTINT ) {  // integral promotion
918                    return CompareDouble( newVal[i].D, op, arg2.I );
919                } break;
920            default: ;
921        }
922    }
923    if( arg2.type == IDENTIFIER) {
924        unsigned i = IndexOf( arg2.S );
925        newValtype = toupper(parameter[i]->GetParameterType());
926        switch ( newValtype ) {
927            case 'I': 
928                if( arg1.type == CONSTINT ) {
929                    return CompareInt( arg1.I, op, newVal[i].I );
930                } else {
931                    G4cerr << "integer operand expected for "
932                         <<  rangeString
933                         << '.' << G4endl;
934                } break;
935            case 'D':
936                if( arg1.type == CONSTDOUBLE ) {
937                    return CompareDouble( arg1.D, op, newVal[i].D );
938                } else
939                if ( arg1.type == CONSTINT ) {  // integral promotion
940                    return CompareDouble( arg1.I, op, newVal[i].D );
941                } break;
942            default: ;
943        }
944    }
945    return 0;
946}
947
948G4int G4UIcommand::
949CompareInt(G4int arg1, G4int op, G4int arg2)
950{   
951    G4int result=-1;
952    G4String opr;
953    switch (op) {
954       case GT:  result = ( arg1 >  arg2); opr= ">" ;  break;
955       case GE:  result = ( arg1 >= arg2); opr= ">=";  break;
956       case LT:  result = ( arg1 <  arg2); opr= "<" ;  break;
957       case LE:  result = ( arg1 <= arg2); opr= "<=";  break;
958       case EQ:  result = ( arg1 == arg2); opr= "==";  break;
959       case NE:  result = ( arg1 != arg2); opr= "!=";  break;
960       default: 
961           G4cerr << "Parameter range: error at CompareInt" << G4endl;
962           paramERR = 1;
963    }
964    #ifdef DEBUG
965        G4cerr << "CompareInt "
966             << arg1 << " " << opr << arg2
967             << " result: " << result
968             << G4endl;
969    #endif
970    return result;
971}
972
973G4int G4UIcommand::
974CompareDouble(G4double arg1, G4int op, G4double arg2)
975{   
976    G4int result=-1;
977    G4String opr;
978    switch (op) {
979        case GT:  result = ( arg1 >  arg2); opr= ">";   break;
980        case GE:  result = ( arg1 >= arg2); opr= ">=";  break;
981        case LT:  result = ( arg1 <  arg2); opr= "<";   break;
982        case LE:  result = ( arg1 <= arg2); opr= "<=";  break;
983        case EQ:  result = ( arg1 == arg2); opr= "==";  break;
984        case NE:  result = ( arg1 != arg2); opr= "!=";  break;
985        default:
986           G4cerr << "Parameter range: error at CompareDouble"
987                << G4endl;
988           paramERR = 1;
989    }
990    #ifdef DEBUG
991        G4cerr << "CompareDouble " 
992             << arg1 <<" " << opr << " "<< arg2
993             << " result: " << result
994             << G4endl;
995    #endif
996    return result;
997}
998
999unsigned G4UIcommand::
1000IndexOf(const char* nam)
1001{
1002    unsigned i;
1003    G4String pname;
1004    for( i=0;  i<parameter.size(); i++)
1005    {
1006        pname = parameter[i]-> GetParameterName();
1007        if( pname == nam ) {
1008            return i;
1009        }
1010    }
1011    paramERR = 1;
1012    G4cerr << "parameter name:"<<nam<<" not found."<< G4endl;
1013    return 0;
1014}
1015
1016
1017unsigned G4UIcommand::
1018IsParameter(const char* nam)
1019{
1020    G4String pname;
1021    for(unsigned i=0;  i<parameter.size(); i++) 
1022    {
1023        pname = parameter[i]-> GetParameterName();
1024        if( pname == nam ) return 1;
1025    }
1026    return 0;
1027}
1028
1029
1030// --------------------- utility functions --------------------------
1031
1032tokenNum G4UIcommand::
1033Yylex()         // reads input and returns token number, KR486
1034{               // (returns EOF)
1035    G4int c;             
1036    G4String buf;
1037
1038    while(( c= G4UIpGetc())==' '|| c=='\t' || c== '\n' )
1039        ;
1040    if (c== EOF)
1041        return (tokenNum)EOF;            // KR488
1042    buf= "";
1043    if (isdigit(c) || c== '.') {         // I or D
1044        do {
1045             buf += G4String((unsigned char)c);
1046             c=G4UIpGetc();
1047         }  while (c=='.' || isdigit(c) || 
1048                   c=='e' || c=='E' || c=='+' || c=='-');
1049         G4UIpUngetc(c);
1050         const char* t = buf;
1051         std::istringstream is(t);
1052         if ( IsInt(buf.data(),20) ) {
1053             is >> yylval.I;
1054             return  CONSTINT;
1055         } else 
1056         if ( IsDouble(buf.data()) ) {
1057             is >> yylval.D;
1058             return  CONSTDOUBLE;
1059         } else {
1060             G4cerr << buf<<": numeric format error."<<G4endl;
1061         }
1062    }
1063    buf="";
1064    if (isalpha(c)|| c=='_') {           // IDENTIFIER
1065        do {
1066            buf += G4String((unsigned char)c); 
1067        } while ((c=G4UIpGetc()) != EOF && (isalnum(c) || c=='_'));
1068        G4UIpUngetc(c);
1069        if( IsParameter(buf) ) {
1070            yylval.S =buf;
1071            return IDENTIFIER;
1072        } else {
1073            G4cerr << buf << " is not a parameter name."<< G4endl;
1074            paramERR = 1;
1075       }
1076    }
1077    switch (c) {
1078      case '>':   return (tokenNum) Follow('=', GE,        GT);
1079      case '<':   return (tokenNum) Follow('=', LE,        LT);
1080      case '=':   return (tokenNum) Follow('=', EQ,        '=');
1081      case '!':   return (tokenNum) Follow('=', NE,        '!');
1082      case '|':   return (tokenNum) Follow('|', LOGICALOR, '|');
1083      case '&':   return (tokenNum) Follow('&', LOGICALAND, '&');
1084      default:
1085          return (tokenNum) c;
1086    }
1087}
1088
1089
1090G4int G4UIcommand::
1091Follow(G4int expect, G4int ifyes, G4int ifno)
1092{
1093    G4int c = G4UIpGetc();
1094    if ( c== expect)
1095          return ifyes;
1096    G4UIpUngetc(c);
1097    return ifno;
1098}
1099
1100//------------------ low level routines -----------------------------
1101G4int G4UIcommand::
1102G4UIpGetc() {                        // emulation of getc()
1103    G4int length = rangeString.length();
1104    if( bp < length)
1105        return  rangeString(bp++);
1106    else 
1107        return EOF;
1108}
1109G4int G4UIcommand::
1110G4UIpUngetc(G4int c) {                 // emulation of ungetc()
1111    if (c<0) return -1;
1112    if (bp >0 && c == rangeString(bp-1)) {
1113         --bp;
1114    } else {
1115         G4cerr << "G4UIpUngetc() failed." << G4endl;
1116         G4cerr << "bp="<<bp <<" c="<<c
1117              << " pR(bp-1)=" << rangeString(bp-1)
1118              << G4endl;
1119         paramERR = 1;
1120         return -1;
1121    }
1122    return 0;
1123}
Note: See TracBrowser for help on using the repository browser.