00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "G4UIparameter.hh"
00031 #include "G4UIcommandStatus.hh"
00032 #include "G4Tokenizer.hh"
00033 #include "G4ios.hh"
00034 #include <sstream>
00035
00036
00037 G4UIparameter::G4UIparameter():paramERR(0)
00038 {
00039 G4String nullString;
00040 parameterName = nullString;
00041 parameterType = '\0';
00042 omittable = false;
00043 parameterGuidance = nullString;
00044 defaultValue = nullString;
00045 parameterRange = nullString;
00046 currentAsDefaultFlag = false;
00047 parameterCandidate = nullString;
00048 widget = 0;
00049 bp = 0;
00050 token = NONE;
00051 }
00052
00053 G4UIparameter::G4UIparameter(char theType):paramERR(0)
00054 {
00055 G4String nullString;
00056 parameterName = nullString;
00057 parameterType = theType;
00058 omittable = false;
00059 parameterGuidance = nullString;
00060 defaultValue = nullString;
00061 parameterRange = nullString;
00062 currentAsDefaultFlag = false;
00063 parameterCandidate = nullString;
00064 widget = 0;
00065 bp = 0;
00066 token = NONE;
00067 }
00068
00069 G4UIparameter::G4UIparameter(const char * theName, char theType, G4bool theOmittable):paramERR(0)
00070 {
00071 parameterName = theName;
00072 parameterType = theType;
00073 omittable = theOmittable;
00074 G4String nullString;
00075 parameterGuidance = nullString;
00076 defaultValue = nullString;
00077 parameterRange = nullString;
00078 currentAsDefaultFlag = false;
00079 parameterCandidate = nullString;
00080 widget = 0;
00081 bp = 0;
00082 token = NONE;
00083 }
00084
00085 G4UIparameter::~G4UIparameter()
00086 { }
00087
00088 G4int G4UIparameter::operator==(const G4UIparameter &right) const
00089 {
00090 return ( this == &right );
00091 }
00092
00093 G4int G4UIparameter::operator!=(const G4UIparameter &right) const
00094 {
00095 return ( this != &right );
00096 }
00097
00098 void G4UIparameter::List()
00099 {
00100 G4cout << G4endl << "Parameter : " << parameterName << G4endl;
00101 if( ! parameterGuidance.isNull() )
00102 G4cout << parameterGuidance << G4endl ;
00103 G4cout << " Parameter type : " << parameterType << G4endl;
00104 if(omittable)
00105 { G4cout << " Omittable : True" << G4endl; }
00106 else
00107 { G4cout << " Omittable : False" << G4endl; }
00108 if( currentAsDefaultFlag )
00109 { G4cout << " Default value : taken from the current value" << G4endl; }
00110 else if( ! defaultValue.isNull() )
00111 { G4cout << " Default value : " << defaultValue << G4endl; }
00112 if( ! parameterRange.isNull() )
00113 G4cout << " Parameter range : " << parameterRange << G4endl;
00114 if( ! parameterCandidate.isNull() )
00115 G4cout << " Candidates : " << parameterCandidate << G4endl;
00116 }
00117
00118 void G4UIparameter::SetDefaultValue(G4int theDefaultValue)
00119 {
00120 std::ostringstream os;
00121 os << theDefaultValue;
00122 defaultValue = os.str();
00123 }
00124
00125 void G4UIparameter::SetDefaultValue(G4double theDefaultValue)
00126 {
00127 std::ostringstream os;
00128 os << theDefaultValue;
00129 defaultValue = os.str();
00130 }
00131
00132
00133
00134 #include <ctype.h>
00135 #include "G4UItokenNum.hh"
00136
00137
00138
00139
00140 G4int G4UIparameter::
00141 CheckNewValue(const char* newValue ) {
00142 if( TypeCheck(newValue) == 0) return fParameterUnreadable;
00143 if( ! parameterRange.isNull() )
00144 { if( RangeCheck(newValue) == 0 ) return fParameterOutOfRange; }
00145 if( ! parameterCandidate.isNull() )
00146 { if( CandidateCheck(newValue) == 0 ) return fParameterOutOfCandidates; }
00147 return 0;
00148 }
00149
00150 G4int G4UIparameter::
00151 CandidateCheck(const char* newValue) {
00152 G4Tokenizer candidateTokenizer(parameterCandidate);
00153 G4String aToken;
00154 G4int iToken = 0;
00155 while( ! (aToken=candidateTokenizer()).isNull() )
00156 {
00157 iToken++;
00158 if(aToken==newValue) return iToken;
00159 }
00160 G4cerr << "parameter value is not listed in the candidate List." << G4endl;
00161 return 0;
00162 }
00163
00164 G4int G4UIparameter::
00165 RangeCheck(const char* newValue) {
00166 yystype result;
00167 bp = 0;
00168 std::istringstream is(newValue);
00169 char type = toupper( parameterType );
00170 switch (type) {
00171 case 'D': { is >> newVal.D; } break;
00172 case 'I': { is >> newVal.I; } break;
00173 default: ;
00174 }
00175
00176 token= Yylex();
00177 result = Expression();
00178 if( paramERR == 1 ) return 0;
00179 if( result.type != CONSTINT) {
00180 G4cerr << "Illegal Expression in parameter range." << G4endl;
00181 return 0;
00182 }
00183 if ( result.I ) return 1;
00184 G4cerr << "parameter out of range: "<< parameterRange << G4endl;
00185 return 0;
00186 }
00187
00188
00189 G4int G4UIparameter::
00190 TypeCheck(const char* newValue)
00191 {
00192 G4String newValueString(newValue);
00193 char type = toupper( parameterType );
00194 switch(type) {
00195 case 'D':
00196 if( IsDouble(newValueString.data())== 0) {
00197 G4cerr<<newValue<<": double value expected."
00198 << G4endl;
00199 return 0;
00200 } break;
00201 case 'I':
00202 if( IsInt(newValueString.data(),20)== 0) {
00203 G4cerr<<newValue<<": integer expected."
00204 << G4endl;
00205 return 0;
00206 } break;
00207 case 'S': break;
00208 case 'B':
00209 newValueString.toUpper();
00210 if ( newValueString == "Y" || newValueString == "N"
00211 ||newValueString == "YES" || newValueString == "NO"
00212 ||newValueString == "1" || newValueString == "0"
00213 ||newValueString == "T" || newValueString == "F"
00214 ||newValueString == "TRUE" || newValueString == "FALSE")
00215 return 1;
00216 else {
00217 G4cerr<<newValue<<": bool expected." << G4endl;
00218 return 0;
00219 }
00220 default: ;
00221 }
00222 return 1;
00223 }
00224
00225
00226 G4int G4UIparameter::
00227 IsInt(const char* buf, short maxDigits)
00228 {
00229 const char* p= buf;
00230 G4int length=0;
00231 if( *p == '+' || *p == '-') { ++p; }
00232 if( isdigit( (G4int)(*p) )) {
00233 while( isdigit( (G4int)(*p) )) { ++p; ++length; }
00234 if( *p == '\0' ) {
00235 if( length > maxDigits) {
00236 G4cerr <<"digit length exceeds"<<G4endl;
00237 return 0;
00238 }
00239 return 1;
00240 } else {
00241
00242 }
00243 } else {
00244
00245 }
00246 return 0;
00247 }
00248
00249
00250 G4int G4UIparameter::
00251 ExpectExponent(const char* str)
00252 {
00253 G4int maxExplength;
00254 if( IsInt( str, maxExplength=7 )) return 1;
00255 else return 0;
00256 }
00257
00258 G4int G4UIparameter::
00259 IsDouble(const char* buf)
00260 {
00261 const char* p= buf;
00262 switch( *p) {
00263 case '+': case '-': ++p;
00264 if( isdigit(*p) ) {
00265 while( isdigit( (G4int)(*p) )) { ++p; }
00266 switch ( *p ) {
00267 case '\0': return 1;
00268 case 'E': case 'e':
00269 return ExpectExponent(++p );
00270 case '.': ++p;
00271 if( *p == '\0' ) return 1;
00272 if( *p == 'e' || *p =='E' ) return ExpectExponent(++p );
00273 if( isdigit(*p) ) {
00274 while( isdigit( (G4int)(*p) )) { ++p; }
00275 if( *p == '\0' ) return 1;
00276 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
00277 } else return 0; break;
00278 default: return 0;
00279 }
00280 }
00281 if( *p == '.' ) { ++p;
00282 if( isdigit(*p) ) {
00283 while( isdigit( (G4int)(*p) )) { ++p; }
00284 if( *p == '\0' ) return 1;
00285 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
00286 }
00287 }
00288 break;
00289 case '.': ++p;
00290 if( isdigit(*p) ) {
00291 while( isdigit( (G4int)(*p) )) { ++p; }
00292 if( *p == '\0' ) return 1;
00293 if( *p == 'e' || *p =='E' ) return ExpectExponent(++p);
00294 } break;
00295 default:
00296 if( isdigit(*p) ) {
00297 while( isdigit( (G4int)(*p) )) { ++p; }
00298 if( *p == '\0' ) return 1;
00299 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
00300 if( *p == '.' ) { ++p;
00301 if( *p == '\0' ) return 1;
00302 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
00303 if( isdigit(*p) ) {
00304 while( isdigit( (G4int)(*p) )) { ++p; }
00305 if( *p == '\0' ) return 1;
00306 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
00307 }
00308 }
00309 }
00310 }
00311 return 0;
00312 }
00313
00314
00315
00316
00317 yystype G4UIparameter::
00318 Expression(void)
00319 {
00320 yystype result;
00321 #ifdef DEBUG
00322 G4cerr << " Expression()" << G4endl;
00323 #endif
00324 result = LogicalORExpression();
00325 return result;
00326 }
00327
00328 yystype G4UIparameter::
00329 LogicalORExpression(void)
00330 {
00331 yystype result;
00332 yystype p;
00333 p = LogicalANDExpression();
00334 if( token != LOGICALOR) return p;
00335 if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
00336 G4cerr << "Parameter range: illegal type at '||'" << G4endl;
00337 paramERR = 1;
00338 }
00339 result.I = p.I;
00340 while (token == LOGICALOR)
00341 {
00342 token = Yylex();
00343 p = LogicalANDExpression();
00344 if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
00345 G4cerr << "Parameter range: illegal type at '||'" <<G4endl;
00346 paramERR = 1;
00347 }
00348 switch (p.type) {
00349 case CONSTINT:
00350 result.I += p.I;
00351 result.type = CONSTINT; break;
00352 case CONSTDOUBLE:
00353 result.I += (p.D != 0.0);
00354 result.type = CONSTINT; break;
00355 default:
00356 G4cerr << "Parameter range: unknown type"<<G4endl;
00357 paramERR = 1;
00358 }
00359 }
00360 return result;
00361 }
00362
00363 yystype G4UIparameter::
00364 LogicalANDExpression(void)
00365 {
00366 yystype result;
00367 yystype p;
00368 p = EqualityExpression();
00369 if( token != LOGICALAND) return p;
00370 if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
00371 G4cerr << "Parameter range: illegal type at '&&'" << G4endl;
00372 paramERR = 1;
00373 }
00374 result.I = p.I;
00375 while (token == LOGICALAND)
00376 {
00377 token = Yylex();
00378 p = EqualityExpression();
00379 if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
00380 G4cerr << "Parameter range: illegal type at '&&'" << G4endl;
00381 paramERR = 1;
00382 }
00383 switch (p.type) {
00384 case CONSTINT:
00385 result.I *= p.I;
00386 result.type = CONSTINT; break;
00387 case CONSTDOUBLE:
00388 result.I *= (p.D != 0.0);
00389 result.type = CONSTINT; break;
00390 default:
00391 G4cerr << "Parameter range: unknown type."<< G4endl;
00392 paramERR = 1;
00393 }
00394 }
00395 return result;
00396 }
00397
00398
00399 yystype G4UIparameter::
00400 EqualityExpression(void)
00401 {
00402 yystype arg1, arg2;
00403 G4int operat;
00404 yystype result;
00405 #ifdef DEBUG
00406 G4cerr << " EqualityExpression()" <<G4endl;
00407 #endif
00408 result = RelationalExpression();
00409 if( token==EQ || token==NE ) {
00410 operat = token;
00411 token = Yylex();
00412 arg1 = result;
00413 arg2 = RelationalExpression();
00414 result.I = Eval2( arg1, operat, arg2 );
00415 result.type = CONSTINT;
00416 #ifdef DEBUG
00417 G4cerr << " return code of Eval2(): " << result.I <<G4endl;
00418 #endif
00419 } else {
00420 if (result.type != CONSTINT && result.type != CONSTDOUBLE) {
00421 G4cerr << "Parameter range: error at EqualityExpression"
00422 << G4endl;
00423 paramERR = 1;
00424 }
00425 }
00426 return result;
00427 }
00428
00429
00430 yystype G4UIparameter::
00431 RelationalExpression(void)
00432 {
00433 yystype arg1, arg2;
00434 G4int operat;
00435 yystype result;
00436 #ifdef DEBUG
00437 G4cerr << " RelationalExpression()" <<G4endl;
00438 #endif
00439
00440 arg1 = AdditiveExpression();
00441 if( token==GT || token==GE || token==LT || token==LE ) {
00442 operat = token;
00443 token = Yylex();
00444 arg2 = AdditiveExpression();
00445 result.I = Eval2( arg1, operat, arg2 );
00446 result.type = CONSTINT;
00447 #ifdef DEBUG
00448 G4cerr << " return Eval2(): " << G4endl;
00449 #endif
00450 } else {
00451 result = arg1;
00452 }
00453 #ifdef DEBUG
00454 G4cerr <<" return RelationalExpression()" <<G4endl;
00455 #endif
00456 return result;
00457 }
00458
00459 yystype G4UIparameter::
00460 AdditiveExpression(void)
00461 { yystype result;
00462 result = MultiplicativeExpression();
00463 if( token != '+' && token != '-' ) return result;
00464 G4cerr << "Parameter range: operator "
00465 << (char)token
00466 << " is not supported." << G4endl;
00467 paramERR = 1;
00468 return result;
00469 }
00470
00471 yystype G4UIparameter::
00472 MultiplicativeExpression(void)
00473 { yystype result;
00474 result = UnaryExpression();
00475 if( token != '*' && token != '/' && token != '%' ) return result;
00476 G4cerr << "Parameter range: operator "
00477 << (char)token
00478 << " is not supported." << G4endl;
00479 paramERR = 1;
00480 return result;
00481 }
00482
00483 yystype G4UIparameter::
00484 UnaryExpression(void)
00485 {
00486 yystype result;
00487 yystype p;
00488 #ifdef DEBUG
00489 G4cerr <<" UnaryExpression"<< G4endl;
00490 #endif
00491 switch(token) {
00492 case '-':
00493 token = Yylex();
00494 p = UnaryExpression();
00495 if (p.type == CONSTINT) {
00496 result.I = - p.I;
00497 result.type = CONSTINT;
00498 }
00499 if (p.type == CONSTDOUBLE) {
00500 result.D = - p.D;
00501 result.type = CONSTDOUBLE;
00502 } break;
00503 case '+':
00504 token = Yylex();
00505 result = UnaryExpression(); break;
00506 case '!':
00507 token = Yylex();
00508 G4cerr << "Parameter range error: "
00509 << "operator '!' is not supported (sorry)."
00510 << G4endl;
00511 paramERR = 1;
00512 result = UnaryExpression(); break;
00513 default:
00514 result = PrimaryExpression();
00515 }
00516 return result;
00517 }
00518
00519
00520 yystype G4UIparameter::
00521 PrimaryExpression(void)
00522 {
00523 yystype result;
00524 #ifdef DEBUG
00525 G4cerr <<" PrimaryExpression" << G4endl;
00526 #endif
00527 switch (token) {
00528 case IDENTIFIER:
00529 result.S = yylval.S;
00530 result.type = token;
00531 token = Yylex(); break;
00532 case CONSTINT:
00533 result.I = yylval.I;
00534 result.type = token;
00535 token= Yylex(); break;
00536 case CONSTDOUBLE:
00537 result.D = yylval.D;
00538 result.type = token;
00539 token = Yylex(); break;
00540 case '(' :
00541 token= Yylex();
00542 result = Expression();
00543 if( token != ')' ) {
00544 G4cerr << " ')' expected" << G4endl;
00545 paramERR = 1;
00546 }
00547 token = Yylex();
00548 break;
00549 default:
00550 return result;
00551 }
00552 return result;
00553 }
00554
00555
00556
00557 G4int G4UIparameter::
00558 Eval2(yystype arg1, G4int op, yystype arg2)
00559 {
00560 if( (arg1.type != IDENTIFIER) && (arg2.type != IDENTIFIER)) {
00561 G4cerr << parameterName
00562 << ": meaningless comparison "
00563 << G4int(arg1.type) << " " << G4int(arg2.type) << G4endl;
00564 paramERR = 1;
00565 }
00566 char type = toupper( parameterType );
00567 if( arg1.type == IDENTIFIER) {
00568 switch (type) {
00569 case 'I':
00570 if ( arg2.type == CONSTINT ) {
00571 return CompareInt( newVal.I, op, arg2.I );
00572 } else {
00573 G4cerr << "integer operand expected for "
00574 << parameterRange << '.'
00575 << G4endl;
00576 }
00577 break;
00578 case 'D':
00579 if ( arg2.type == CONSTDOUBLE ) {
00580 return CompareDouble( newVal.D, op, arg2.D );
00581 } else
00582 if ( arg2.type == CONSTINT ) {
00583 return CompareDouble( newVal.D, op, arg2.I );
00584 } break;
00585 default: ;
00586 }
00587 }
00588 if( arg2.type == IDENTIFIER) {
00589 switch (type) {
00590 case 'I':
00591 if ( arg1.type == CONSTINT ) {
00592 return CompareInt( arg1.I, op, newVal.I );
00593 } else {
00594 G4cerr << "integer operand expected for "
00595 << parameterRange << '.'
00596 << G4endl;
00597 }
00598 break;
00599 case 'D':
00600 if ( arg1.type == CONSTDOUBLE ) {
00601 return CompareDouble( arg1.D, op, newVal.D );
00602 } else
00603 if ( arg1.type == CONSTINT ) {
00604 return CompareDouble( arg1.I, op, newVal.D );
00605 } break;
00606 default: ;
00607 }
00608 }
00609 G4cerr << "no param name is specified at the param range."<<G4endl;
00610 return 0;
00611 }
00612
00613 G4int G4UIparameter::
00614 CompareInt(G4int arg1, G4int op, G4int arg2)
00615 {
00616 G4int result=-1;
00617 G4String opr;
00618 switch (op) {
00619 case GT: result = ( arg1 > arg2); opr= ">" ; break;
00620 case GE: result = ( arg1 >= arg2); opr= ">="; break;
00621 case LT: result = ( arg1 < arg2); opr= "<" ; break;
00622 case LE: result = ( arg1 <= arg2); opr= "<="; break;
00623 case EQ: result = ( arg1 == arg2); opr= "=="; break;
00624 case NE: result = ( arg1 != arg2); opr= "!="; break;
00625 default:
00626 G4cerr << "Parameter range: error at CompareInt" << G4endl;
00627 paramERR = 1;
00628 }
00629 #ifdef DEBUG
00630 G4cerr << "CompareInt "
00631 << arg1 << " " << opr << arg2
00632 << " result: " << result
00633 << G4endl;
00634 #endif
00635 return result;
00636 }
00637
00638 G4int G4UIparameter::
00639 CompareDouble(G4double arg1, G4int op, G4double arg2)
00640 {
00641 G4int result=-1;
00642 G4String opr;
00643 switch (op) {
00644 case GT: result = ( arg1 > arg2); opr= ">"; break;
00645 case GE: result = ( arg1 >= arg2); opr= ">="; break;
00646 case LT: result = ( arg1 < arg2); opr= "<"; break;
00647 case LE: result = ( arg1 <= arg2); opr= "<="; break;
00648 case EQ: result = ( arg1 == arg2); opr= "=="; break;
00649 case NE: result = ( arg1 != arg2); opr= "!="; break;
00650 default:
00651 G4cerr << "Parameter range: error at CompareDouble" << G4endl;
00652 paramERR = 1;
00653 }
00654 #ifdef DEBUG
00655 G4cerr << "CompareDouble "
00656 << arg1 <<" " << opr << " "<< arg2
00657 << " result: " << result
00658 << G4endl;
00659 #endif
00660 return result;
00661 }
00662
00663
00664
00665 tokenNum G4UIparameter::
00666 Yylex()
00667 {
00668 G4int c;
00669 G4String buf;
00670
00671 while(( c= G4UIpGetc())==' '|| c=='\t' || c== '\n' )
00672 ;
00673 if (c== EOF)
00674 return (tokenNum)EOF;
00675 buf= "";
00676 if (isdigit(c) || c== '.') {
00677 do {
00678 buf += G4String((unsigned char)c);
00679 c=G4UIpGetc();
00680 } while (c=='.' || isdigit(c) ||
00681 c=='e' || c=='E' || c=='+' || c=='-');
00682 G4UIpUngetc(c);
00683 const char* t = buf;
00684 std::istringstream is(t);
00685 if ( IsInt(buf.data(),20) ) {
00686 is >> yylval.I;
00687 return CONSTINT;
00688 } else
00689 if ( IsDouble(buf.data()) ) {
00690 is >> yylval.D;
00691 return CONSTDOUBLE;
00692 } else {
00693 G4cerr << buf<<": numeric format error."<<G4endl;
00694 }
00695 }
00696 buf="";
00697 if (isalpha(c)|| c=='_') {
00698 do {
00699 buf += G4String((unsigned char)c);
00700 } while ((c=G4UIpGetc()) != EOF && (isalnum(c) || c=='_'));
00701 G4UIpUngetc(c);
00702 if( buf == parameterName ) {
00703 yylval.S =buf;
00704 return IDENTIFIER;
00705 } else {
00706 G4cerr << buf << " is not a parameter name."<< G4endl;
00707 paramERR = 1;
00708 }
00709 }
00710 switch (c) {
00711 case '>': return (tokenNum) Follow('=', GE, GT);
00712 case '<': return (tokenNum) Follow('=', LE, LT);
00713 case '=': return (tokenNum) Follow('=', EQ, '=');
00714 case '!': return (tokenNum) Follow('=', NE, '!');
00715 case '|': return (tokenNum) Follow('|', LOGICALOR, '|');
00716 case '&': return (tokenNum) Follow('&', LOGICALAND, '&');
00717 default:
00718 return (tokenNum) c;
00719 }
00720 }
00721
00722
00723 G4int G4UIparameter::
00724 Follow(G4int expect, G4int ifyes, G4int ifno)
00725 {
00726 G4int c = G4UIpGetc();
00727 if ( c== expect)
00728 return ifyes;
00729 G4UIpUngetc(c);
00730 return ifno;
00731 }
00732
00733
00734 G4int G4UIparameter::
00735 G4UIpGetc() {
00736 G4int length = parameterRange.length();
00737 if( bp < length)
00738 return parameterRange(bp++);
00739 else
00740 return EOF;
00741 }
00742 G4int G4UIparameter::
00743 G4UIpUngetc(G4int c) {
00744 if (c<0) return -1;
00745 if (bp >0 && c == parameterRange(bp-1)) {
00746 --bp;
00747 } else {
00748 G4cerr << "G4UIpUngetc() failed." << G4endl;
00749 G4cerr << "bp="<<bp <<" c="<<c
00750 << " pR(bp-1)=" << parameterRange(bp-1)
00751 << G4endl;
00752 paramERR = 1;
00753 return -1;
00754 }
00755 return 0;
00756 }
00757
00758