Jpp  17.3.0
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JShellParser.cc
Go to the documentation of this file.
1 
2 #include <iostream>
3 #include <iomanip>
4 #include <string>
5 #include <cstring>
6 #include <list>
7 
8 #include "JLang/JNullType.hh"
9 #include "JLang/JEquation.hh"
10 #include "JLang/JEquationFacet.hh"
11 #include "JLang/JException.hh"
12 #include "JLang/JRedirectStream.hh"
13 #include "JLang/JLangToolkit.hh"
15 #include "Jeep/JParser.hh"
16 
17 
18 /**
19  * \author mdejong
20  */
21 
22 namespace {
23 
24  using namespace JPP;
25 
26  const char OPTIONS_SEPARATOR = ','; //!< options separator
27 
28 
29  /**
30  * Auxiliary class for environment variable.
31  */
32  template<class T>
33  struct JParameter {
34  /**
35  * Constructor.
36  *
37  * \param variable environment variable
38  */
39  JParameter(const std::string& variable) :
40  name (variable),
41  value()
42  {}
43 
44 
45  /**
46  * Equals operator.
47  *
48  * \param first first parameter
49  * \param second second parameter
50  * \return true if first parameter equals second parameter; else false
51  */
52  friend bool operator==(const JParameter& first, const JParameter& second)
53  {
54  return (first.name == second.name &&
55  first.value == second.value);
56  }
57 
58 
59  /**
60  * Stream input.
61  *
62  * Note that only the value of the parameter is read.
63  *
64  * \param in input stream
65  * \return input stream
66  */
67  inline std::istream& read(std::istream& in)
68  {
69  return in >> this->value;
70  }
71 
72 
73  /**
74  * Stream output.
75  *
76  * Note that only the value of the parameter is written.
77  *
78  * \param out output stream
79  * \return output stream
80  */
81  inline std::ostream& write(std::ostream& out) const
82  {
83  return out << this->value;
84  }
85 
86  std::string name; //!< environment variable name
87  T value; //!< environment variable value
88  };
89 
90 
91  /**
92  * Template specialisation of JParameter<std::string>::read.
93  *
94  * Note that the complete text until the end-of-line is read, including possible white spaces.
95  *
96  * \param in input stream
97  * \return input stream
98  */
99  template<>
100  inline std::istream& JParameter<std::string>::read(std::istream& in)
101  {
102  return std::getline(in, this->value);
103  }
104 
105 
106  /**
107  * Template specialisation of JParameter<bool>::read.
108  *
109  * Note that no data are read; only the value is set to <tt>true</tt>
110  *
111  * \param in input stream
112  * \return input stream
113  */
114  template<>
115  inline std::istream& JParameter<bool>::read(std::istream& in)
116  {
117  this->value = true;
118 
119  return in;
120  }
121 
122 
123  /**
124  * Template specialisation of JParameter<bool>::write.
125  *
126  * \param out output stream
127  * \return output stream
128  */
129  template<>
130  inline std::ostream& JParameter<bool>::write(std::ostream& out) const
131  {
132  return out << (this->value ? "1" : "0");
133  }
134 
135 
136  /**
137  * Stream input of parameter.
138  *
139  * \param in input stream
140  * \param parameter parameter
141  * \return input stream
142  */
143  template<class T>
144  inline std::istream& operator>>(std::istream& in, JParameter<T>& parameter)
145  {
146  return parameter.read(in);
147  }
148 
149 
150  /**
151  * Stream output of parameter.
152  *
153  * \param out output stream
154  * \param parameter parameter
155  * \return output stream
156  */
157  template<class T>
158  inline std::ostream& operator<<(std::ostream& out, const JParameter<T>& parameter)
159  {
160  return parameter.write(out);
161  }
162 
163 
164  /**
165  * Base class for environment variables.
166  */
167  template<class T = JNullType>
168  struct JShellParser;
169 
170 
171  /**
172  * Base class for environment variables.
173  *
174  * This class is used to redirect the standard output and error so that
175  * - output is parsed via JSYSTEM::gprint; and
176  * - termination is handled via JSYSTEM::gexit.
177  */
178  template<>
179  struct JShellParser<JNullType> :
180  public JParser<>
181  {
182  typedef JParser<>::key_type key_type;
183 
184 
185  /**
186  * Default constructor.
187  */
188  JShellParser() :
189  __terminate__(false),
190  __exit_code__(0)
191  {}
192 
193 
194  /**
195  * Terminate.
196  *
197  * \param status exit status
198  */
199  virtual void terminate(const int status)
200  {
201  __terminate__ = true;
202  __exit_code__ = status;
203  }
204 
205 
206  /**
207  * Parse the program's command line options.
208  *
209  * \param args argument list
210  * \return argument list
211  */
212  JArgs operator()(const JArgs& args)
213  {
214  using namespace std;
215  using namespace JPP;
216 
217  ostringstream os;
218 
219  {
220  JRedirectStream rs_out(cout, os);
221  JRedirectStream rs_err(cerr, os);
222 
223  if (rs_out &&
224  rs_err) {
225  static_cast<JParser<>&>(*this)(args);
226  }
227  }
228 
229  gprint(os.str());
230 
231  if (__terminate__) {
232  gexit(__exit_code__);
233  }
234 
235  return JArgs();
236  }
237 
238  private:
239  bool __terminate__;
240  int __exit_code__;
241  };
242 
243 
244  /**
245  * Base class for environment variables.
246  *
247  * This class includes the data to be evaluated to shell variables in the end.
248  */
249  template<class T>
250  struct JShellParser :
251  public JShellParser<>
252  {
253  typedef JShellParser<>::key_type key_type;
254  typedef JParameter<T> parameter_type;
255  typedef std::list<parameter_type> data_type;
256 
257 
258  /**
259  * Evaluate environment to shell commands.
260  */
261  void evaluate() const
262  {
263  for (typename data_type::const_iterator i = this->data.begin(); i != this->data.end(); ++i) {
264 
265  std::ostringstream os;
266 
267  os << *i;
268 
269  set_variable(i->name, os.str());
270  }
271  }
272 
273 
274  protected:
275  data_type data; //!< internal memory
276  };
277 
278 
279  /**
280  * Parser for environment variables.
281  */
282  template<class T>
283  struct JEnvironment;
284 
285 
286  /**
287  * Template specialisation of JEnvironment for regular environment variables.
288  */
289  template<>
290  struct JEnvironment<std::string> :
291  public JShellParser<std::string>
292  {
293  typedef JShellParser<std::string>::key_type key_type;
294  typedef JShellParser<std::string>::parameter_type parameter_type;
295 
296 
297  /**
298  * Default constructor.
299  */
300  JEnvironment()
301  {}
302 
303 
304  /**
305  * Stream input.
306  *
307  * \param in input stream
308  * \param environment environment
309  * \return input stream
310  */
311  friend inline std::istream& operator>>(std::istream& in, JEnvironment& environment)
312  {
313  using namespace std;
314  using namespace JPP;
315 
316  static const JEquationFacet facet(JEquationParameters("=", ";\n", "./", "#"));
317 
318  char c;
319  key_type key;
320  JEquation equation;
321 
322  if (!has_facet<JEquationFacet>(in.getloc())) {
323  in.imbue(locale(in.getloc(), facet.clone()));
324  }
325 
326  if (in >> c >> key >> equation) {
327 
328  if (c == '-' && !equation.getKey().empty()) {
329 
330  environment.data.push_back(parameter_type(equation.getKey()));
331 
332  parameter_type& parameter = environment.data.back();
333 
334  if (facet.isSeparator(equation.getSeparator())) {
335 
336  // read possible values
337 
338  istringstream is(equation.getValue());
339 
340  vector<parameter_type> possible_values;
341 
342  for (parameter_type buffer(parameter.name); getline(is, buffer.value, OPTIONS_SEPARATOR); ) {
343 
344  buffer.value = trim(buffer.value);
345 
346  possible_values.push_back(buffer);
347  }
348 
349  environment[key] = JPARSER::getOption(parameter, equation.getKey(), possible_values.begin(), possible_values.end());
350 
351  } else {
352 
353  environment[key] = JPARSER::getOption(parameter, equation.getKey());
354  }
355 
356  } else {
357 
358  THROW(JParseError, "JEnvironment: error parsing " << c << " <" << equation.getKey() << ">");
359  }
360  }
361 
362  return in;
363  }
364  };
365 
366 
367  /**
368  * Template specialisation of JEnvironment for boolean environment variables.
369  */
370  template<>
371  struct JEnvironment<bool> :
372  public JShellParser<bool>
373  {
374  typedef JShellParser<bool>::key_type key_type;
375  typedef JShellParser<bool>::parameter_type parameter_type;
376 
377 
378  /**
379  * Default constructor.
380  */
381  JEnvironment()
382  {}
383 
384 
385  /**
386  * Stream input.
387  *
388  * \param in input stream
389  * \param environment environment
390  * \return input stream
391  */
392  friend inline std::istream& operator>>(std::istream& in, JEnvironment& environment)
393  {
394  using namespace std;
395  using namespace JPP;
396 
397  static const JEquationFacet facet(JEquationParameters("=", ";\n", "./", "#"));
398 
399  char c;
400  key_type key;
401  JEquation equation;
402 
403  if (!has_facet<JEquationFacet>(in.getloc())) {
404  in.imbue(locale(in.getloc(), facet.clone()));
405  }
406 
407  if (in >> c >> key >> equation) {
408 
409  if (c == '-' && !equation.getKey().empty()) {
410 
411  environment.data.push_back(parameter_type(equation.getKey()));
412 
413  parameter_type& parameter = environment.data.back();
414 
415  if (facet.isSeparator(equation.getSeparator()) || equation.getValue() != "") {
416 
417  THROW(JParseError, "JEnvironment: invalid operation " << c << " <" << equation.getKey() << ">");
418 
419  } else {
420 
421  environment[key] = JPARSER::getOption(parameter.value, equation.getKey());
422  }
423 
424  } else {
425 
426  THROW(JParseError, "JEnvironment: error parsing " << c << " <" << equation.getKey() << ">");
427  }
428  }
429 
430  return in;
431  }
432  };
433 }
434 
435 
436 /**
437  * \file
438  *
439  * Auxiliary program to interface JPARSER::JParser to command line of shell scripts.
440  * Syntax:
441  * <pre>
442  * eval `JShellParser -o "-a <environment variable> [= <default value>[, <possible value>]]" -- $*`
443  * </pre>
444  */
445 int main(int argc, char **argv)
446 {
447  using namespace std;
448  using namespace JPP;
449 
450  try {
451 
452  JEnvironment<bool> boolean;
453  JEnvironment<string> regular;
454 
455  JParser<> zap;
456 
457  zap['b'] = make_field(boolean) = JPARSER::initialised();
458  zap['o'] = make_field(regular) = JPARSER::initialised();
459 
460  const JArgs options = zap(argc, argv);
461 
462  JShellParser<> buffer;
463 
464  buffer.join(boolean);
465  buffer.join(regular);
466 
467  buffer(options);
468 
469  boolean.evaluate();
470  regular.evaluate();
471  }
472  catch(const exception& error) {
473  return gexit(2, error.what());
474  }
475 }
Utility class to parse command line options.
Definition: JParser.hh:1517
Exceptions.
JParameter()
Default constructor.
Definition: JParameter.hh:44
int main(int argc, char *argv[])
Definition: Main.cc:15
Facet class to specify parsing of equations in currect locale (see class JLANG::JEquation).
std::istream & read(std::istream &in, JTestSummary &summary, const char delimiter= ' ')
Read test summary.
Parameter class.
Definition: JParameter.hh:34
void gprint(const std::string &message)
Print method.
JParserTemplateElement< bool > getOption(bool &object, const std::string &name, const std::string &help="")
Auxiliary method for creation of template parser element object.
Definition: JParser.hh:1899
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:696
then echo Enter input within $TIMEOUT_S seconds echo n User name
Definition: JCookie.sh:42
Simple data structure to support I/O of equations (see class JLANG::JEquation).
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition: JParser.hh:83
is
Definition: JDAQCHSM.chsm:167
then echo The file $DIR KM3NeT_00000001_00000000 root already please rename or remove it first
std::string trim(const std::string &buffer)
Trim string.
Definition: JLangToolkit.hh:79
General purpose equation class.
Definition: JEquation.hh:47
then usage $script[port]< option > nPossible options
This class can be used to temporarily redirect one output (input) stream to another output (input) st...
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1993
then echo Variable JPP_DIR undefined exit fi source $JPP_DIR setenv sh $JPP_DIR &dev null set_variable
Definition: JAcoustics.sh:21
do set_variable OUTPUT_DIRECTORY $WORKDIR T
Auxiliary class for no type definition.
Definition: JNullType.hh:19
then awk string
std::istream & getline(std::istream &in, JString &object)
Read string from input stream until end of line.
Definition: JString.hh:478
Data structure to store command line arguments.
Definition: JArgs.hh:24
friend bool operator==(const JParameter< T > &first, typename JClass< JNullType >::argument_type second)
Equal operator.
Definition: JComparable.hh:260
$WORKDIR ev_configure_dqsimulator txt echo process $DQ_SIMULATOR $i $SOURCE_HOST[$index] csh c(setenv ROOTSYS $ROOTSYS &&source $JPP_DIR/setenv.csh $JPP_DIR &&($DQ_SIMULATOR\-u\$NAME\$\-H\$SERVER\$\-M\$LOGGER\$\-d $DEBUG</dev/null > &/dev/null &))'
std::istream & operator>>(std::istream &in, JAANET::JHead &header)
Read header from input.
Definition: JHead.hh:1756
int gexit(int status, const std::string &message="")
Exit method.
bool write(const Vec &v, std::ostream &os)
Write a Vec(tor) to a stream.
Definition: io_ascii.hh:155
Utility class to parse command line options.
System auxiliaries.
Exception for parsing value.
Definition: JException.hh:180
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable INPUT_FILE $argv[2] eval JPrintDetector a $DETECTOR O IDENTIFIER eval JPrintDetector a $DETECTOR O SUMMARY JAcoustics sh $DETECTOR_ID source JAcousticsToolkit sh CHECK_EXIT_CODE typeset A EMITTERS get_tripods $WORKDIR tripod txt EMITTERS get_transmitters $WORKDIR transmitter txt EMITTERS for EMITTER in
Definition: JCanberra.sh:46