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