source: trunk/source/intercoms/src/G4UIparameter.cc@ 1093

Last change on this file since 1093 was 1016, checked in by garnier, 17 years ago

update

File size: 22.8 KB
RevLine 
[821]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: G4UIparameter.cc,v 1.14 2006/06/29 19:09:09 gunter Exp $
[1016]28// GEANT4 tag $Name: geant4-09-02 $
[821]29//
30
31#include "G4UIparameter.hh"
32#include "G4UIcommandStatus.hh"
33#include "G4Tokenizer.hh"
34#include "G4ios.hh"
35#include <sstream>
36
37
38G4UIparameter::G4UIparameter():paramERR(0)
39{
40 G4String nullString;
41 parameterName = nullString;
42 parameterType = '\0';
43 omittable = false;
44 parameterGuidance = nullString;
45 defaultValue = nullString;
46 parameterRange = nullString;
47 currentAsDefaultFlag = false;
48 parameterCandidate = nullString;
49 widget = 0;
50}
51
52G4UIparameter::G4UIparameter(char theType):paramERR(0)
53{
54 G4String nullString;
55 parameterName = nullString;
56 parameterType = theType;
57 omittable = false;
58 parameterGuidance = nullString;
59 defaultValue = nullString;
60 parameterRange = nullString;
61 currentAsDefaultFlag = false;
62 parameterCandidate = nullString;
63 widget = 0;
64}
65
66G4UIparameter::G4UIparameter(const char * theName, char theType, G4bool theOmittable):paramERR(0)
67{
68 parameterName = theName;
69 parameterType = theType;
70 omittable = theOmittable;
71 G4String nullString;
72 parameterGuidance = nullString;
73 defaultValue = nullString;
74 parameterRange = nullString;
75 currentAsDefaultFlag = false;
76 parameterCandidate = nullString;
77 widget = 0;
78}
79
80G4UIparameter::~G4UIparameter()
81{ }
82
83G4int G4UIparameter::operator==(const G4UIparameter &right) const
84{
85 return ( this == &right );
86}
87
88G4int G4UIparameter::operator!=(const G4UIparameter &right) const
89{
90 return ( this != &right );
91}
92
93void G4UIparameter::List()
94{
95 G4cout << G4endl << "Parameter : " << parameterName << G4endl;
96 if( ! parameterGuidance.isNull() )
97 G4cout << parameterGuidance << G4endl ;
98 G4cout << " Parameter type : " << parameterType << G4endl;
99 if(omittable)
100 { G4cout << " Omittable : True" << G4endl; }
101 else
102 { G4cout << " Omittable : False" << G4endl; }
103 if( currentAsDefaultFlag )
104 { G4cout << " Default value : taken from the current value" << G4endl; }
105 else if( ! defaultValue.isNull() )
106 { G4cout << " Default value : " << defaultValue << G4endl; }
107 if( ! parameterRange.isNull() )
108 G4cout << " Parameter range : " << parameterRange << G4endl;
109 if( ! parameterCandidate.isNull() )
110 G4cout << " Candidates : " << parameterCandidate << G4endl;
111}
112
113void G4UIparameter::SetDefaultValue(G4int theDefaultValue)
114{
115 std::ostringstream os;
116 os << theDefaultValue;
117 defaultValue = os.str();
118}
119
120void G4UIparameter::SetDefaultValue(G4double theDefaultValue)
121{
122 std::ostringstream os;
123 os << theDefaultValue;
124 defaultValue = os.str();
125}
126
127
128// ---------- CheckNewValue() related routines -----------
129#include <ctype.h>
130#include "G4UItokenNum.hh"
131
132//#include "checkNewValue_debug.icc"
133//#define DEBUG 1
134
135G4int G4UIparameter::
136CheckNewValue(const char* newValue ) {
137 if( TypeCheck(newValue) == 0) return fParameterUnreadable;
138 if( ! parameterRange.isNull() )
139 { if( RangeCheck(newValue) == 0 ) return fParameterOutOfRange; }
140 if( ! parameterCandidate.isNull() )
141 { if( CandidateCheck(newValue) == 0 ) return fParameterOutOfCandidates; }
142 return 0; // succeeded
143}
144
145G4int G4UIparameter::
146CandidateCheck(const char* newValue) {
147 G4Tokenizer candidateTokenizer(parameterCandidate);
148 G4String aToken;
149 G4int iToken = 0;
150 while( ! (aToken=candidateTokenizer()).isNull() )
151 {
152 iToken++;
153 if(aToken==newValue) return iToken;
154 }
155 G4cerr << "parameter value is not listed in the candidate List." << G4endl;
156 return 0;
157}
158
159G4int G4UIparameter::
160RangeCheck(const char* newValue) {
161 yystype result;
162 bp = 0; // reset buffer pointer for G4UIpGetc()
163 std::istringstream is(newValue);
164 char type = toupper( parameterType );
165 switch (type) {
166 case 'D': { is >> newVal.D; } break;
167 case 'I': { is >> newVal.I; } break;
168 default: ;
169 }
170 // PrintToken(); // Print tokens (consumes all tokens)
171 token= Yylex();
172 result = Expression();
173 if( paramERR == 1 ) return 0;
174 if( result.type != CONSTINT) {
175 G4cerr << "Illegal Expression in parameter range." << G4endl;
176 return 0;
177 }
178 if ( result.I ) return 1;
179 G4cerr << "parameter out of range: "<< parameterRange << G4endl;
180 return 0;
181}
182
183
184G4int G4UIparameter::
185TypeCheck(const char* newValue)
186{
187 G4String newValueString(newValue);
188 char type = toupper( parameterType );
189 switch(type) {
190 case 'D':
191 if( IsDouble(newValueString.data())== 0) {
192 G4cerr<<newValue<<": double value expected."
193 << G4endl;
194 return 0;
195 } break;
196 case 'I':
197 if( IsInt(newValueString.data(),20)== 0) {
198 G4cerr<<newValue<<": integer expected."
199 << G4endl;
200 return 0;
201 } break;
202 case 'S': break;
203 case 'B':
204 newValueString.toUpper();
205 if ( newValueString == "Y" || newValueString == "N"
206 ||newValueString == "YES" || newValueString == "NO"
207 ||newValueString == "1" || newValueString == "0"
208 ||newValueString == "T" || newValueString == "F"
209 ||newValueString == "TRUE" || newValueString == "FALSE")
210 return 1;
211 else {
212 G4cerr<<newValue<<": bool expected." << G4endl;
213 return 0;
214 }
215 default: ;
216 }
217 return 1;
218}
219
220
221G4int G4UIparameter::
222IsInt(const char* buf, short maxDigits) // do not allow any std::ws
223{
224 const char* p= buf;
225 G4int length=0;
226 if( *p == '+' || *p == '-') { ++p; }
227 if( isdigit( (G4int)(*p) )) {
228 while( isdigit( (G4int)(*p) )) { ++p; ++length; }
229 if( *p == '\0' ) {
230 if( length > maxDigits) {
231 G4cerr <<"digit length exceeds"<<G4endl;
232 return 0;
233 }
234 return 1;
235 } else {
236 // G4cerr <<"illegal character after int:"<<buf<<G4endl;
237 }
238 } else {
239 // G4cerr <<"illegal int:"<<buf<<G4endl;
240 }
241 return 0;
242}
243
244
245G4int G4UIparameter::
246ExpectExponent(const char* str) // used only by IsDouble()
247{
248 G4int maxExplength;
249 if( IsInt( str, maxExplength=7 )) return 1;
250 else return 0;
251}
252
253G4int G4UIparameter::
254IsDouble(const char* buf) // see state diagram for this spec.
255{
256 const char* p= buf;
257 switch( *p) {
258 case '+': case '-': ++p;
259 if( isdigit(*p) ) {
260 while( isdigit( (G4int)(*p) )) { ++p; }
261 switch ( *p ) {
262 case '\0': return 1; //break;
263 case 'E': case 'e':
264 return ExpectExponent(++p ); //break;
265 case '.': ++p;
266 if( *p == '\0' ) return 1;
267 if( *p == 'e' || *p =='E' ) return ExpectExponent(++p );
268 if( isdigit(*p) ) {
269 while( isdigit( (G4int)(*p) )) { ++p; }
270 if( *p == '\0' ) return 1;
271 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
272 } else return 0; break;
273 default: return 0;
274 }
275 }
276 if( *p == '.' ) { ++p;
277 if( isdigit(*p) ) {
278 while( isdigit( (G4int)(*p) )) { ++p; }
279 if( *p == '\0' ) return 1;
280 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
281 }
282 }
283 break;
284 case '.': ++p;
285 if( isdigit(*p) ) {
286 while( isdigit( (G4int)(*p) )) { ++p; }
287 if( *p == '\0' ) return 1;
288 if( *p == 'e' || *p =='E' ) return ExpectExponent(++p);
289 } break;
290 default: // digit is expected
291 if( isdigit(*p) ) {
292 while( isdigit( (G4int)(*p) )) { ++p; }
293 if( *p == '\0' ) return 1;
294 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
295 if( *p == '.' ) { ++p;
296 if( *p == '\0' ) return 1;
297 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
298 if( isdigit(*p) ) {
299 while( isdigit( (G4int)(*p) )) { ++p; }
300 if( *p == '\0' ) return 1;
301 if( *p == 'e' || *p =='E') return ExpectExponent(++p);
302 }
303 }
304 }
305 }
306 return 0;
307}
308
309
310// ------------------ syntax node functions ------------------
311
312yystype G4UIparameter::
313Expression(void)
314{
315 yystype result;
316 #ifdef DEBUG
317 G4cerr << " Expression()" << G4endl;
318 #endif
319 result = LogicalORExpression();
320 return result;
321}
322
323yystype G4UIparameter::
324LogicalORExpression(void)
325{
326 yystype result;
327 yystype p;
328 p = LogicalANDExpression();
329 if( token != LOGICALOR) return p;
330 if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
331 G4cerr << "Parameter range: illegal type at '||'" << G4endl;
332 paramERR = 1;
333 }
334 result.I = p.I;
335 while (token == LOGICALOR)
336 {
337 token = Yylex();
338 p = LogicalANDExpression();
339 if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
340 G4cerr << "Parameter range: illegal type at '||'" <<G4endl;
341 paramERR = 1;
342 }
343 switch (p.type) {
344 case CONSTINT:
345 result.I += p.I;
346 result.type = CONSTINT; break;
347 case CONSTDOUBLE:
348 result.I += (p.D != 0.0);
349 result.type = CONSTINT; break;
350 default:
351 G4cerr << "Parameter range: unknown type"<<G4endl;
352 paramERR = 1;
353 }
354 }
355 return result;
356}
357
358yystype G4UIparameter::
359LogicalANDExpression(void)
360{
361 yystype result;
362 yystype p;
363 p = EqualityExpression();
364 if( token != LOGICALAND) return p;
365 if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
366 G4cerr << "Parameter range: illegal type at '&&'" << G4endl;
367 paramERR = 1;
368 }
369 result.I = p.I;
370 while (token == LOGICALAND)
371 {
372 token = Yylex();
373 p = EqualityExpression();
374 if( p.type == CONSTSTRING || p.type == IDENTIFIER ) {
375 G4cerr << "Parameter range: illegal type at '&&'" << G4endl;
376 paramERR = 1;
377 }
378 switch (p.type) {
379 case CONSTINT:
380 result.I *= p.I;
381 result.type = CONSTINT; break;
382 case CONSTDOUBLE:
383 result.I *= (p.D != 0.0);
384 result.type = CONSTINT; break;
385 default:
386 G4cerr << "Parameter range: unknown type."<< G4endl;
387 paramERR = 1;
388 }
389 }
390 return result;
391}
392
393
394yystype G4UIparameter::
395EqualityExpression(void)
396{
397 yystype arg1, arg2;
398 G4int operat;
399 yystype result;
400 #ifdef DEBUG
401 G4cerr << " EqualityExpression()" <<G4endl;
402 #endif
403 result = RelationalExpression();
404 if( token==EQ || token==NE ) {
405 operat = token;
406 token = Yylex();
407 arg1 = result;
408 arg2 = RelationalExpression();
409 result.I = Eval2( arg1, operat, arg2 ); // semantic action
410 result.type = CONSTINT;
411 #ifdef DEBUG
412 G4cerr << " return code of Eval2(): " << result.I <<G4endl;
413 #endif
414 } else {
415 if (result.type != CONSTINT && result.type != CONSTDOUBLE) {
416 G4cerr << "Parameter range: error at EqualityExpression"
417 << G4endl;
418 paramERR = 1;
419 }
420 }
421 return result;
422}
423
424
425yystype G4UIparameter::
426RelationalExpression(void)
427{
428 yystype arg1, arg2;
429 G4int operat;
430 yystype result;
431 #ifdef DEBUG
432 G4cerr << " RelationalExpression()" <<G4endl;
433 #endif
434
435 arg1 = AdditiveExpression();
436 if( token==GT || token==GE || token==LT || token==LE ) {
437 operat = token;
438 token = Yylex();
439 arg2 = AdditiveExpression();
440 result.I = Eval2( arg1, operat, arg2 ); // semantic action
441 result.type = CONSTINT;
442 #ifdef DEBUG
443 G4cerr << " return Eval2(): " << G4endl;
444 #endif
445 } else {
446 result = arg1;
447 }
448 #ifdef DEBUG
449 G4cerr <<" return RelationalExpression()" <<G4endl;
450 #endif
451 return result;
452}
453
454yystype G4UIparameter::
455AdditiveExpression(void)
456{ yystype result;
457 result = MultiplicativeExpression();
458 if( token != '+' && token != '-' ) return result;
459 G4cerr << "Parameter range: operator "
460 << (char)token
461 << " is not supported." << G4endl;
462 paramERR = 1;
463 return result;
464}
465
466yystype G4UIparameter::
467MultiplicativeExpression(void)
468{ yystype result;
469 result = UnaryExpression();
470 if( token != '*' && token != '/' && token != '%' ) return result;
471 G4cerr << "Parameter range: operator "
472 << (char)token
473 << " is not supported." << G4endl;
474 paramERR = 1;
475 return result;
476}
477
478yystype G4UIparameter::
479UnaryExpression(void)
480{
481 yystype result;
482 yystype p;
483 #ifdef DEBUG
484 G4cerr <<" UnaryExpression"<< G4endl;
485 #endif
486 switch(token) {
487 case '-':
488 token = Yylex();
489 p = UnaryExpression();
490 if (p.type == CONSTINT) {
491 result.I = - p.I;
492 result.type = CONSTINT;
493 }
494 if (p.type == CONSTDOUBLE) {
495 result.D = - p.D;
496 result.type = CONSTDOUBLE;
497 } break;
498 case '+':
499 token = Yylex();
500 result = UnaryExpression(); break;
501 case '!':
502 token = Yylex();
503 G4cerr << "Parameter range error: "
504 << "operator '!' is not supported (sorry)."
505 << G4endl;
506 paramERR = 1;
507 result = UnaryExpression(); break;
508 default:
509 result = PrimaryExpression();
510 }
511 return result;
512}
513
514
515yystype G4UIparameter::
516PrimaryExpression(void)
517{
518 yystype result;
519 #ifdef DEBUG
520 G4cerr <<" PrimaryExpression" << G4endl;
521 #endif
522 switch (token) {
523 case IDENTIFIER:
524 result.S = yylval.S;
525 result.type = token;
526 token = Yylex(); break;
527 case CONSTINT:
528 result.I = yylval.I;
529 result.type = token;
530 token= Yylex(); break;
531 case CONSTDOUBLE:
532 result.D = yylval.D;
533 result.type = token;
534 token = Yylex(); break;
535 case '(' :
536 token= Yylex();
537 result = Expression();
538 if( token != ')' ) {
539 G4cerr << " ')' expected" << G4endl;
540 paramERR = 1;
541 }
542 token = Yylex();
543 break;
544 default:
545 return result;
546 }
547 return result; // never executed
548}
549
550//---------------- semantic routines ---------------------------------
551
552G4int G4UIparameter::
553Eval2(yystype arg1, G4int op, yystype arg2)
554{
555 if( (arg1.type != IDENTIFIER) && (arg2.type != IDENTIFIER)) {
556 G4cerr << parameterName
557 << ": meaningless comparison "
558 << G4int(arg1.type) << " " << G4int(arg2.type) << G4endl;
559 paramERR = 1;
560 }
561 char type = toupper( parameterType );
562 if( arg1.type == IDENTIFIER) {
563 switch (type) {
564 case 'I':
565 if ( arg2.type == CONSTINT ) {
566 return CompareInt( newVal.I, op, arg2.I );
567 } else {
568 G4cerr << "integer operand expected for "
569 << parameterRange << '.'
570 << G4endl;
571 }
572 break;
573 case 'D':
574 if ( arg2.type == CONSTDOUBLE ) {
575 return CompareDouble( newVal.D, op, arg2.D );
576 } else
577 if ( arg2.type == CONSTINT ) { // integral promotion
578 return CompareDouble( newVal.D, op, arg2.I );
579 } break;
580 default: ;
581 }
582 }
583 if( arg2.type == IDENTIFIER) {
584 switch (type) {
585 case 'I':
586 if ( arg1.type == CONSTINT ) {
587 return CompareInt( arg1.I, op, newVal.I );
588 } else {
589 G4cerr << "integer operand expected for "
590 << parameterRange << '.'
591 << G4endl;
592 }
593 break;
594 case 'D':
595 if ( arg1.type == CONSTDOUBLE ) {
596 return CompareDouble( arg1.D, op, newVal.D );
597 } else
598 if ( arg1.type == CONSTINT ) { // integral promotion
599 return CompareDouble( arg1.I, op, newVal.D );
600 } break;
601 default: ;
602 }
603 }
604 G4cerr << "no param name is specified at the param range."<<G4endl;
605 return 0;
606}
607
608G4int G4UIparameter::
609CompareInt(G4int arg1, G4int op, G4int arg2)
610{
611 G4int result=-1;
612 G4String opr;
613 switch (op) {
614 case GT: result = ( arg1 > arg2); opr= ">" ; break;
615 case GE: result = ( arg1 >= arg2); opr= ">="; break;
616 case LT: result = ( arg1 < arg2); opr= "<" ; break;
617 case LE: result = ( arg1 <= arg2); opr= "<="; break;
618 case EQ: result = ( arg1 == arg2); opr= "=="; break;
619 case NE: result = ( arg1 != arg2); opr= "!="; break;
620 default:
621 G4cerr << "Parameter range: error at CompareInt" << G4endl;
622 paramERR = 1;
623 }
624 #ifdef DEBUG
625 G4cerr << "CompareInt "
626 << arg1 << " " << opr << arg2
627 << " result: " << result
628 << G4endl;
629 #endif
630 return result;
631}
632
633G4int G4UIparameter::
634CompareDouble(G4double arg1, G4int op, G4double arg2)
635{
636 G4int result=-1;
637 G4String opr;
638 switch (op) {
639 case GT: result = ( arg1 > arg2); opr= ">"; break;
640 case GE: result = ( arg1 >= arg2); opr= ">="; break;
641 case LT: result = ( arg1 < arg2); opr= "<"; break;
642 case LE: result = ( arg1 <= arg2); opr= "<="; break;
643 case EQ: result = ( arg1 == arg2); opr= "=="; break;
644 case NE: result = ( arg1 != arg2); opr= "!="; break;
645 default:
646 G4cerr << "Parameter range: error at CompareDouble" << G4endl;
647 paramERR = 1;
648 }
649 #ifdef DEBUG
650 G4cerr << "CompareDouble "
651 << arg1 <<" " << opr << " "<< arg2
652 << " result: " << result
653 << G4endl;
654 #endif
655 return result;
656}
657
658// --------------------- utility functions --------------------------
659
660tokenNum G4UIparameter::
661Yylex() // reads input and returns token number KR486
662{ // (returns EOF)
663 G4int c;
664 G4String buf;
665
666 while(( c= G4UIpGetc())==' '|| c=='\t' || c== '\n' )
667 ;
668 if (c== EOF)
669 return (tokenNum)EOF; // KR488
670 buf= "";
671 if (isdigit(c) || c== '.') { // I or D
672 do {
673 buf += G4String((unsigned char)c);
674 c=G4UIpGetc();
675 } while (c=='.' || isdigit(c) ||
676 c=='e' || c=='E' || c=='+' || c=='-');
677 G4UIpUngetc(c);
678 const char* t = buf;
679 std::istringstream is(t);
680 if ( IsInt(buf.data(),20) ) {
681 is >> yylval.I;
682 return CONSTINT;
683 } else
684 if ( IsDouble(buf.data()) ) {
685 is >> yylval.D;
686 return CONSTDOUBLE;
687 } else {
688 G4cerr << buf<<": numeric format error."<<G4endl;
689 }
690 }
691 buf="";
692 if (isalpha(c)|| c=='_') { // IDENTIFIER
693 do {
694 buf += G4String((unsigned char)c);
695 } while ((c=G4UIpGetc()) != EOF && (isalnum(c) || c=='_'));
696 G4UIpUngetc(c);
697 if( buf == parameterName ) {
698 yylval.S =buf;
699 return IDENTIFIER;
700 } else {
701 G4cerr << buf << " is not a parameter name."<< G4endl;
702 paramERR = 1;
703 }
704 }
705 switch (c) {
706 case '>': return (tokenNum) Follow('=', GE, GT);
707 case '<': return (tokenNum) Follow('=', LE, LT);
708 case '=': return (tokenNum) Follow('=', EQ, '=');
709 case '!': return (tokenNum) Follow('=', NE, '!');
710 case '|': return (tokenNum) Follow('|', LOGICALOR, '|');
711 case '&': return (tokenNum) Follow('&', LOGICALAND, '&');
712 default:
713 return (tokenNum) c;
714 }
715}
716
717
718G4int G4UIparameter::
719Follow(G4int expect, G4int ifyes, G4int ifno)
720{
721 G4int c = G4UIpGetc();
722 if ( c== expect)
723 return ifyes;
724 G4UIpUngetc(c);
725 return ifno;
726}
727
728//------------------ low level routines -----------------------------
729G4int G4UIparameter::
730G4UIpGetc() { // emulation of getc()
731 G4int length = parameterRange.length();
732 if( bp < length)
733 return parameterRange(bp++);
734 else
735 return EOF;
736}
737G4int G4UIparameter::
738G4UIpUngetc(G4int c) { // emulation of ungetc()
739 if (c<0) return -1;
740 if (bp >0 && c == parameterRange(bp-1)) {
741 --bp;
742 } else {
743 G4cerr << "G4UIpUngetc() failed." << G4endl;
744 G4cerr << "bp="<<bp <<" c="<<c
745 << " pR(bp-1)=" << parameterRange(bp-1)
746 << G4endl;
747 paramERR = 1;
748 return -1;
749 }
750 return 0;
751}
752// ***** end of CheckNewValue() related code ******
753
Note: See TracBrowser for help on using the repository browser.