Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/intercoms/src/G4UIparsing.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

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