Jpp
 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 
27  /**
28  * Auxiliary class for environment variable.
29  */
30  template<class T>
31  struct JParameter {
32  /**
33  * Constructor.
34  *
35  * \param variable environment variable
36  */
37  JParameter(const std::string& variable = "") :
38  name (variable),
39  value()
40  {}
41 
42 
43  /**
44  * Equals operator.
45  *
46  * \param first first parameter
47  * \param second second parameter
48  * \return true if first parameter equals second parameter; else false
49  */
50  friend bool operator==(const JParameter& first, const JParameter& second)
51  {
52  return (first.name == second.name &&
53  first.value == second.value);
54  }
55 
56 
57  /**
58  * Stream input.
59  *
60  * Note that only the value of the parameter is read.
61  *
62  * \param in input stream
63  * \return input stream
64  */
65  inline std::istream& read(std::istream& in)
66  {
67  return in >> this->value;
68  }
69 
70 
71  /**
72  * Stream output.
73  *
74  * Note that only the value of the parameter is written.
75  *
76  * \param out output stream
77  * \return output stream
78  */
79  inline std::ostream& write(std::ostream& out) const
80  {
81  return out << this->value;
82  }
83 
84  std::string name; //!< environment variable name
85  T value; //!< environment variable value
86  };
87 
88 
89  /**
90  * Template specialisation of JParameter<std::string>::read.
91  *
92  * \param in input stream
93  * \return input stream
94  */
95  template<>
96  inline std::istream& JParameter<std::string>::read(std::istream& in)
97  {
98  return std::getline(in, this->value);
99  }
100 
101 
102  /**
103  * Template specialisation of JParameter<bool>::read.
104  *
105  * \param in input stream
106  * \return input stream
107  */
108  template<>
109  inline std::istream& JParameter<bool>::read(std::istream& in)
110  {
111  this->value = true;
112 
113  return in;
114  }
115 
116 
117  /**
118  * Template specialisation of JParameter<bool>::write.
119  *
120  * \param out output stream
121  * \return output stream
122  */
123  template<>
124  inline std::ostream& JParameter<bool>::write(std::ostream& out) const
125  {
126  return out << (this->value ? "1" : "0");
127  }
128 
129 
130  /**
131  * Stream input of parameter.
132  *
133  * \param in input stream
134  * \param parameter parameter
135  * \return input stream
136  */
137  template<class T>
138  inline std::istream& operator>>(std::istream& in, JParameter<T>& parameter)
139  {
140  return parameter.read(in);
141  }
142 
143 
144  /**
145  * Stream output of parameter.
146  *
147  * \param out output stream
148  * \param parameter parameter
149  * \return output stream
150  */
151  template<class T>
152  inline std::ostream& operator<<(std::ostream& out, const JParameter<T>& parameter)
153  {
154  return parameter.write(out);
155  }
156 
157 
158  /**
159  * Parser for environment variables.
160  */
161  template<class T = JNullType>
162  struct JEnvironment;
163 
164 
165  /**
166  * Base class for environment variables.
167  */
168  template<>
169  struct JEnvironment<JNullType> :
170  public JParser<>
171  {
172  typedef JParser<>::key_type key_type;
173 
174 
175  /**
176  * Default constructor.
177  */
178  JEnvironment()
179  {}
180 
181 
182  /**
183  * Join environment.
184  *
185  * \param environment environment
186  * \return this environment
187  */
188  JEnvironment join(const JEnvironment& environment)
189  {
190  this->insert(environment.begin(), environment.end());
191 
192  return *this;
193  }
194 
195 
196  /**
197  * Process command line arguments.
198  *
199  * \param argc number of command line arguments
200  * \param argv array of command line arguments
201  * \return status (0 = OK)
202  */
203  int operator()(int argc, char** argv)
204  {
205  using namespace std;
206  using namespace JPP;
207 
208  // look for pending command line arguments
209 
210  for ( ; argc != 0 && strcmp(*argv, "--") != 0; --argc, ++argv) {}
211 
212  int status = -1;
213  ostringstream os;
214 
215  {
216  JRedirectStream redirect[] = { JRedirectStream(cout, os),
217  JRedirectStream(cerr, os) };
218 
219  if (redirect[0] &&
220  redirect[1]) {
221  status = this->read(argc, argv);
222  }
223  }
224 
225  gprint(os.str());
226 
227  return status;
228  }
229  };
230 
231 
232  /**
233  * Template specialisation of JEnvironment for regular environment variables.
234  */
235  template<>
236  struct JEnvironment<std::string> :
237  public JEnvironment<>
238  {
239  typedef JParser<>::key_type key_type;
240  typedef JParameter<std::string> parameter_type;
241  typedef std::list<parameter_type>::const_iterator const_iterator;
242 
243 
244  /**
245  * Default constructor.
246  */
247  JEnvironment()
248  {}
249 
250 
251  /**
252  * Stream input.
253  *
254  * \param in input stream
255  * \param environment environment
256  * \return input stream
257  */
258  friend inline std::istream& operator>>(std::istream& in, JEnvironment& environment)
259  {
260  using namespace std;
261  using namespace JPP;
262 
263  static const JEquationFacet facet(JEquationParameters("=", ";\n", "./", "#"));
264 
265  char c;
266  key_type key;
267  JEquation equation;
268 
269  if (!has_facet<JEquationFacet>(in.getloc())) {
270  in.imbue(locale(in.getloc(), facet.clone()));
271  }
272 
273  if (in >> c >> key >> equation) {
274 
275  if (c == '-' && !equation.getKey().empty()) {
276 
277  environment.data.push_back(parameter_type(equation.getKey()));
278 
279  parameter_type& parameter = environment.data.back();
280 
281  if (facet.isSeparator(equation.getSeparator())) {
282 
283  // read possible values
284 
285  istringstream is(equation.getValue());
286 
287  vector<parameter_type> possible_values;
288 
289  for (parameter_type buffer(parameter.name); getline(is, buffer.value, ','); ) {
290 
291  buffer.value = trim(buffer.value);
292 
293  possible_values.push_back(buffer);
294  }
295 
296  environment[key] = JPARSER::getOption(parameter, equation.getKey(), possible_values.begin(), possible_values.end());
297 
298  } else {
299 
300  environment[key] = JPARSER::getOption(parameter, equation.getKey());
301  }
302 
303  } else {
304 
305  THROW(JParseError, "JEnvironment: error parsing " << c << " <" << equation.getKey() << ">");
306  }
307  }
308 
309  return in;
310  }
311 
312 
313  std::list<parameter_type> data; //!< internal memory
314  };
315 
316 
317  /**
318  * Template specialisation of JEnvironment for boolean environment variables.
319  */
320  template<>
321  struct JEnvironment<bool> :
322  public JEnvironment<>
323  {
324  typedef JParser<>::key_type key_type;
325  typedef JParameter<bool> parameter_type;
326  typedef std::list<parameter_type>::const_iterator const_iterator;
327 
328 
329  /**
330  * Default constructor.
331  */
332  JEnvironment()
333  {}
334 
335 
336  /**
337  * Stream input.
338  *
339  * \param in input stream
340  * \param environment environment
341  * \return input stream
342  */
343  friend inline std::istream& operator>>(std::istream& in, JEnvironment& environment)
344  {
345  using namespace std;
346  using namespace JPP;
347 
348  static const JEquationFacet facet(JEquationParameters("=", ";\n", "./", "#"));
349 
350  char c;
351  key_type key;
352  JEquation equation;
353 
354  if (!has_facet<JEquationFacet>(in.getloc())) {
355  in.imbue(locale(in.getloc(), facet.clone()));
356  }
357 
358  if (in >> c >> key >> equation) {
359 
360  if (c == '-' && !equation.getKey().empty()) {
361 
362  environment.data.push_back(parameter_type(equation.getKey()));
363 
364  parameter_type& parameter = environment.data.back();
365 
366  if (facet.isSeparator(equation.getSeparator()) || equation.getValue() != "") {
367 
368  THROW(JParseError, "JEnvironment: invalid operation " << c << " <" << equation.getKey() << ">");
369 
370  } else {
371 
372  environment[key] = JPARSER::getOption(parameter.value, equation.getKey());
373  }
374 
375  } else {
376 
377  THROW(JParseError, "JEnvironment: error parsing " << c << " <" << equation.getKey() << ">");
378  }
379  }
380 
381  return in;
382  }
383 
384 
385  std::list<parameter_type> data; //!< internal memory
386  };
387 
388 
389  /**
390  * Evaluate environment to shell commands.
391  *
392  * \param environment environment
393  */
394  template<class T>
395  void evaluate(const JEnvironment<T>& environment)
396  {
397  using namespace std;
398 
399  for (typename JEnvironment<T>::const_iterator i = environment.data.begin(); i != environment.data.end(); ++i) {
400 
401  stringbuf buffer;
402 
403  ostream os(&buffer);
404 
405  os << *i;
406 
407  set_variable(i->name, buffer.str());
408  }
409  }
410 }
411 
412 
413 /**
414  * Auxiliary program to interface JPARSER::JParser to command line of shell scripts.
415  * Syntax:
416  * <pre>
417  * eval `JShellParser -o "-a <environment variable> [= <default value>[, <possible value>]]" -- $*`
418  * </pre>
419  */
420 int main(int argc, char **argv)
421 {
422  using namespace std;
423 
424  int debug;
425 
426  try {
427 
428  JEnvironment<bool> boolean;
429  JEnvironment<string> regular;
430 
431  JParser<> zap("Auxiliary program to interface C++ parser to command line of shell scripts.");
432 
433  zap['b'] = make_field(boolean) = JPARSER::initialised();
434  zap['o'] = make_field(regular) = JPARSER::initialised();
435  zap['d'] = make_field(debug) = 1;
436 
437  if (zap.read(argc, argv) != 0) {
438  return gexit(1);
439  }
440 
441  JEnvironment<> buffer;
442 
444 
445  buffer.join(boolean);
446  buffer.join(regular);
447 
448  if (buffer(argc, argv) == 0) {
449  evaluate(boolean);
450  evaluate(regular);
451  } else {
452  gexit(1);
453  }
454  }
455  catch(const exception& error) {
456  return gexit(2, error.what());
457  }
458 }
Utility class to parse command line options.
Definition: JParser.hh:1410
Exceptions.
std::istream & operator>>(std::istream &in, JHead &header)
Read header from input.
JParameter()
Default constructor.
Definition: JParameter.hh:42
Facet class to specify parsing of equations in currect locale (see class JLANG::JEquation).
JRange< T, JComparator_t > join(const JRange< T, JComparator_t > &first, const JRange< T, JComparator_t > &second)
Join ranges.
Definition: JRange.hh:573
void set_variable(const std::string &name, const std::string &value)
Set environment variable.
Parameter class.
Definition: JParameter.hh:32
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:1757
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:633
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.
Definition: JParser.hh:64
std::string trim(const std::string &buffer)
Trim string.
Definition: JLangToolkit.hh:79
General purpose equation class.
Definition: JEquation.hh:47
std::istream & read(std::istream &in, JContainer_t< TString, JAllocator_t > &object, const JBool< false > &option)
Auxiliary method for reading if TString does not exist.
Definition: JParser.hh:720
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:1836
Auxiliary class for no type definition.
Definition: JNullType.hh:19
std::istream & getline(std::istream &in, JString &object)
Read string from input stream until end of line.
Definition: JString.hh:468
int debug
debug level
Definition: JSirene.cc:59
friend bool operator==(const JParameter< T > &first, typename JClass< JNullType >::argument_type second)
Equal operator.
Definition: JComparable.hh:262
int gexit(int status, const std::string &message="")
Exit method.
int read(const int argc, const char *const argv[])
Parse the program&#39;s command line options.
Definition: JParser.hh:1673
Utility class to parse command line options.
System calls via shell interactions.
Exception for parsing value.
Definition: JException.hh:162
int main(int argc, char *argv[])
Definition: Main.cpp:15