Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4UIcommand.cc
Go to the documentation of this file.
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$
28 //
29 //
30 
31 #include "G4UIcommand.hh"
32 #include "G4UImessenger.hh"
33 #include "G4UImanager.hh"
34 #include "G4UIcommandStatus.hh"
35 #include "G4StateManager.hh"
36 #include "G4UnitsTable.hh"
37 #include "G4Tokenizer.hh"
38 #include "G4ios.hh"
39 #include <sstream>
40 
42  : messenger(0), bp(0), token(IDENTIFIER), paramERR(0)
43 {
44 }
45 
46 G4UIcommand::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 
72 void 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 
81 }
82 
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 
95 {
96  return ( commandPath == right.GetCommandPath() );
97 }
98 
100 {
101  return ( commandPath != right.GetCommandPath() );
102 }
103 
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 
215 {
216  return messenger->GetCurrentValue(this);
217 }
218 
220 {
221  availabelStateList.clear();
222  availabelStateList.push_back(s1);
223 }
224 
227 {
228  availabelStateList.clear();
229  availabelStateList.push_back(s1);
230  availabelStateList.push_back(s2);
231 }
232 
236 {
237  availabelStateList.clear();
238  availabelStateList.push_back(s1);
239  availabelStateList.push_back(s2);
240  availabelStateList.push_back(s3);
241 }
242 
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 
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 
270 {
271  G4bool av = false;
272  G4ApplicationState currentState
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 
288 G4double G4UIcommand::ValueOf(const char* unitName)
289 {
290  G4double value = 0.;
291  value = G4UnitDefinition::GetValueOf(unitName);
292  return value;
293 }
294 
295 G4String G4UIcommand::CategoryOf(const char* unitName)
296 {
297  return G4UnitDefinition::GetCategory(unitName);
298 }
299 
300 G4String G4UIcommand::UnitsList(const char* unitCategory)
301 {
302  G4String retStr;
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 
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 
350 {
351  G4String vl = "0";
352  if(boolVal) vl = "1";
353  return vl;
354 }
355 
357 {
358  std::ostringstream os;
359  os << intValue;
360  G4String vl = os.str();
361  return vl;
362 }
363 
365 {
366  std::ostringstream os;
367  os << doubleValue;
368  G4String vl = os.str();
369  return vl;
370 }
371 
372 G4String 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 
384 {
385  std::ostringstream os;
386  os << vec.x() << " " << vec.y() << " " << vec.z();
387  G4String vl = os.str();
388  return vl;
389 }
390 
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 
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 
414 {
415  G4int vl;
416  std::istringstream is(st);
417  is >> vl;
418  return vl;
419 }
420 
422 {
423  G4double vl;
424  std::istringstream is(st);
425  is >> vl;
426  return vl;
427 }
428 
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 
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 
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 
474 CheckNewValue(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 
485 G4int G4UIcommand::
486 TypeCheck(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 
526 G4int G4UIcommand::
527 IsInt(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 
550 G4int G4UIcommand::
551 ExpectExponent(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 
559 G4int G4UIcommand::
560 IsDouble(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 -------------------
619 G4int G4UIcommand::
620 RangeCheck(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 ------------------
650 yystype G4UIcommand::
651 Expression(void)
652 {
653  yystype result;
654  #ifdef DEBUG
655  G4cerr << " Expression()" << G4endl;
656  #endif
657  result = LogicalORExpression();
658  return result;
659 }
660 
661 yystype G4UIcommand::
662 LogicalORExpression(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.I += 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 
696 yystype G4UIcommand::
697 LogicalANDExpression(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.I *= 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 
732 yystype G4UIcommand::
733 EqualityExpression(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 
763 yystype G4UIcommand::
764 RelationalExpression(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 
792 yystype G4UIcommand::
793 AdditiveExpression(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 
804 yystype G4UIcommand::
805 MultiplicativeExpression(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 
816 yystype G4UIcommand::
817 UnaryExpression(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 
853 yystype G4UIcommand::
854 PrimaryExpression(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 
890 G4int G4UIcommand::
891 Eval2(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 
948 G4int G4UIcommand::
949 CompareInt(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 
973 G4int G4UIcommand::
974 CompareDouble(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 
999 unsigned G4UIcommand::
1000 IndexOf(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 
1017 unsigned G4UIcommand::
1018 IsParameter(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 
1032 tokenNum G4UIcommand::
1033 Yylex() // 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 
1090 G4int G4UIcommand::
1091 Follow(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 -----------------------------
1101 G4int G4UIcommand::
1102 G4UIpGetc() { // emulation of getc()
1103  G4int length = rangeString.length();
1104  if( bp < length)
1105  return rangeString(bp++);
1106  else
1107  return EOF;
1108 }
1109 G4int G4UIcommand::
1110 G4UIpUngetc(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 }