Jpp  debug
the software that should make you happy
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  * Virtual destructor.
196  */
197  virtual ~JShellParser()
198  {}
199 
200 
201  /**
202  * Terminate.
203  *
204  * \param status exit status
205  */
206  virtual void terminate(const int status)
207  {
208  __terminate__ = true;
209  __exit_code__ = status;
210  }
211 
212 
213  /**
214  * Parse the program's command line options.
215  *
216  * \param args argument list
217  * \return argument list
218  */
219  JArgs operator()(const JArgs& args)
220  {
221  using namespace std;
222  using namespace JPP;
223 
224  ostringstream os;
225 
226  {
227  JRedirectStream rs_out(cout, os);
228  JRedirectStream rs_err(cerr, os);
229 
230  if (rs_out &&
231  rs_err) {
232  static_cast<JParser<>&>(*this)(args);
233  }
234  }
235 
236  gprint(os.str());
237 
238  if (__terminate__) {
239  gexit(__exit_code__);
240  }
241 
242  return JArgs();
243  }
244 
245  private:
246  bool __terminate__;
247  int __exit_code__;
248  };
249 
250 
251  /**
252  * Base class for environment variables.
253  *
254  * This class includes the data to be evaluated to shell variables in the end.
255  */
256  template<class T>
257  struct JShellParser :
258  public JShellParser<>
259  {
260  typedef JShellParser<>::key_type key_type;
261  typedef JParameter<T> parameter_type;
263 
264 
265  /**
266  * Evaluate environment to shell commands.
267  */
268  void evaluate() const
269  {
270  for (typename data_type::const_iterator i = this->data.begin(); i != this->data.end(); ++i) {
271 
272  std::ostringstream os;
273 
274  os << *i;
275 
276  set_variable(i->name, os.str());
277  }
278  }
279 
280 
281  protected:
282  data_type data; //!< internal memory
283  };
284 
285 
286  /**
287  * Parser for environment variables.
288  */
289  template<class T>
290  struct JEnvironment;
291 
292 
293  /**
294  * Template specialisation of JEnvironment for regular environment variables.
295  */
296  template<>
297  struct JEnvironment<std::string> :
298  public JShellParser<std::string>
299  {
300  typedef JShellParser<std::string>::key_type key_type;
301  typedef JShellParser<std::string>::parameter_type parameter_type;
302 
303 
304  /**
305  * Default constructor.
306  */
307  JEnvironment()
308  {}
309 
310 
311  /**
312  * Stream input.
313  *
314  * \param in input stream
315  * \param environment environment
316  * \return input stream
317  */
318  friend inline std::istream& operator>>(std::istream& in, JEnvironment& environment)
319  {
320  using namespace std;
321  using namespace JPP;
322 
323  static const JEquationFacet facet(JEquationParameters("=", ";\n", "./", "#"));
324 
325  char c;
326  key_type key;
327  JEquation equation;
328 
329  if (!has_facet<JEquationFacet>(in.getloc())) {
330  in.imbue(locale(in.getloc(), facet.clone()));
331  }
332 
333  if (in >> c >> key >> equation) {
334 
335  if (c == '-' && !equation.getKey().empty()) {
336 
337  environment.data.push_back(parameter_type(equation.getKey()));
338 
339  parameter_type& parameter = environment.data.back();
340 
341  if (facet.isSeparator(equation.getSeparator())) {
342 
343  // read possible values
344 
345  istringstream is(equation.getValue());
346 
347  vector<parameter_type> possible_values;
348 
349  for (parameter_type buffer(parameter.name); getline(is, buffer.value, OPTIONS_SEPARATOR); ) {
350 
351  buffer.value = trim(buffer.value);
352 
353  possible_values.push_back(buffer);
354  }
355 
356  environment[key] = JPARSER::getOption(parameter, equation.getKey(), possible_values.begin(), possible_values.end());
357 
358  } else {
359 
360  environment[key] = JPARSER::getOption(parameter, equation.getKey());
361  }
362 
363  } else {
364 
365  THROW(JParseError, "JEnvironment: error parsing " << c << " <" << equation.getKey() << ">");
366  }
367  }
368 
369  return in;
370  }
371  };
372 
373 
374  /**
375  * Template specialisation of JEnvironment for boolean environment variables.
376  */
377  template<>
378  struct JEnvironment<bool> :
379  public JShellParser<bool>
380  {
381  typedef JShellParser<bool>::key_type key_type;
382  typedef JShellParser<bool>::parameter_type parameter_type;
383 
384 
385  /**
386  * Default constructor.
387  */
388  JEnvironment()
389  {}
390 
391 
392  /**
393  * Stream input.
394  *
395  * \param in input stream
396  * \param environment environment
397  * \return input stream
398  */
399  friend inline std::istream& operator>>(std::istream& in, JEnvironment& environment)
400  {
401  using namespace std;
402  using namespace JPP;
403 
404  static const JEquationFacet facet(JEquationParameters("=", ";\n", "./", "#"));
405 
406  char c;
407  key_type key;
408  JEquation equation;
409 
410  if (!has_facet<JEquationFacet>(in.getloc())) {
411  in.imbue(locale(in.getloc(), facet.clone()));
412  }
413 
414  if (in >> c >> key >> equation) {
415 
416  if (c == '-' && !equation.getKey().empty()) {
417 
418  environment.data.push_back(parameter_type(equation.getKey()));
419 
420  parameter_type& parameter = environment.data.back();
421 
422  if (facet.isSeparator(equation.getSeparator()) || equation.getValue() != "") {
423 
424  THROW(JParseError, "JEnvironment: invalid operation " << c << " <" << equation.getKey() << ">");
425 
426  } else {
427 
428  environment[key] = JPARSER::getOption(parameter.value, equation.getKey());
429  }
430 
431  } else {
432 
433  THROW(JParseError, "JEnvironment: error parsing " << c << " <" << equation.getKey() << ">");
434  }
435  }
436 
437  return in;
438  }
439  };
440 }
441 
442 
443 /**
444  * \file
445  *
446  * Auxiliary program to interface JPARSER::JParser to command line of shell scripts.
447  * Syntax:
448  * <pre>
449  * eval `JShellParser -o "-a <environment variable> [= <default value>[, <possible value>]]" -- $*`
450  * </pre>
451  */
452 int main(int argc, char **argv)
453 {
454  using namespace std;
455  using namespace JPP;
456 
457  try {
458 
459  JEnvironment<bool> boolean;
460  JEnvironment<string> regular;
461 
462  JParser<> zap;
463 
464  zap['b'] = make_field(boolean) = JPARSER::initialised();
465  zap['o'] = make_field(regular) = JPARSER::initialised();
466 
467  const JArgs options = zap(argc, argv);
468 
469  JShellParser<> buffer;
470 
471  buffer.join(boolean);
472  buffer.join(regular);
473 
474  buffer(options);
475 
476  boolean.evaluate();
477  regular.evaluate();
478  }
479  catch(const exception& error) {
480  return gexit(2, error.what());
481  }
482 }
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
std::istream & operator>>(std::istream &in, JAANET::JHead &header)
Read header from input.
Definition: JHead.hh:1832
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:2158
int main(int argc, char **argv)
System auxiliaries.
Data structure to store command line arguments.
Definition: JArgs.hh:26
Facet class to specify parsing of equations in currect locale (see class JLANG::JEquation).
Simple data structure to support I/O of equations (see class JLANG::JEquation).
General purpose equation class.
Definition: JEquation.hh:47
const std::string & getKey() const
Get key.
Definition: JEquation.hh:163
const std::string & getValue() const
Get value.
Definition: JEquation.hh:185
const char getSeparator() const
Get separator.
Definition: JEquation.hh:174
Parameter class.
Definition: JParameter.hh:36
JParameter()
Default constructor.
Definition: JParameter.hh:46
Exception for parsing value.
Definition: JException.hh:198
This class can be used to temporarily redirect one output (input) stream to another output (input) st...
Utility class to parse command line options.
Definition: JParser.hh:1714
std::ostream & operator<<(std::ostream &stream, const CLBCommonHeader &header)
bool write(const Vec &v, std::ostream &os)
Write a Vec(tor) to a stream.
Definition: io_ascii.hh:155
std::istream & read(std::istream &in, JTestSummary &summary, const char delimiter=' ')
Read test summary.
std::istream & getline(std::istream &in, JString &object)
Read string from input stream until end of line.
Definition: JString.hh:478
std::string trim(const std::string &buffer)
Trim string.
Definition: JLangToolkit.hh:79
JParserTemplateElement< JType_t > getOption(JType_t &object, const std::string &name, const std::string &help="")
Auxiliary method for creation of template parser element object.
Definition: JParser.hh:2093
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
std::vector< event_type > data_type
Definition: JPerth.cc:81
int gexit(int status, const std::string &message="")
Exit method.
void gprint(const std::string &message)
Print method.
void set_variable(const std::string &name, const std::string &value)
Set environment variable.
Definition: JSTDTypes.hh:14
Data structure for measured coincidence rates of all pairs of PMTs in optical module.
Definition: JFitK40.hh:103
friend bool operator==(const JParameter< T > &first, typename JClass< JSecond_t >::argument_type second)
Equal operator.
Definition: JComparable.hh:260
Auxiliary class for no type definition.
Definition: JNullType.hh:19
Empty structure for specification of parser element that is initialised (i.e. does not require input)...
Definition: JParser.hh:84