COPASI API  4.16.103
COptionParser.cpp
Go to the documentation of this file.
1 // Begin CVS Header
2 // $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/commandline/COptionParser.cpp,v $
3 // $Revision: 1.32 $
4 // $Name: $
5 // $Author: shoops $
6 // $Date: 2012/06/01 17:25:01 $
7 // End CVS Header
8 
9 // Copyright (C) 2012 by Pedro Mendes, Virginia Tech Intellectual
10 // Properties, Inc., University of Heidelberg, and The University
11 // of Manchester.
12 // All rights reserved.
13 
14 /*
15  * This file was automaticly generated by clo++ version 0.6.4 (REL-0_6_4)
16  * http://pmade.org/pjones/software/clo++/
17  *
18  * Template enhancements by Stefan Hoops mailto:shoops@vt.edu
19  */
20 
21 /**
22  * This file contains the implementation of the COptionParser class.
23  * You can control the name of this source file using the
24  * cxx_source_file variable.
25  */
26 
27 #ifdef WIN32
28 #pragma warning (disable: 4786)
29 #define strcasecmp _stricmp
30 #endif
31 
32 #include "COptionParser.h"
33 #include <cstring>
34 #include <cstdlib>
35 #include <cctype>
36 #include <fstream>
37 #include <sstream>
38 #include <errno.h>
39 
40 namespace
41 {
42 const char const_usage[] =
43  " --SBMLSchema schema The Schema of the SBML file to export.\n"
44  " --configdir dir The configuration directory for copasi. The\n"
45  " default is .copasi in the home directory.\n"
46  " --configfile file The configuration file for copasi. The\n"
47  " default is copasi in the ConfigDir.\n"
48  " --exportBerkeleyMadonna file The Berkeley Madonna file to export.\n"
49  " --exportC file The C code file to export.\n"
50  " --exportXPPAUT file The XPPAUT file to export.\n"
51  " --home dir Your home directory.\n"
52  " --license Display the license.\n"
53  " --maxTime seconds The maximal time CopasiSE may run in\n"
54  " seconds.\n"
55  " --nologo Surpresses the startup message.\n"
56  " --validate Only validate the given input file (COPASI,\n"
57  " Gepasi, or SBML) without performing any\n"
58  " calculations.\n"
59  " --verbose Enable output of messages during runtime to\n"
60  " std::error.\n"
61  " -c, --copasidir dir The COPASI installation directory.\n"
62  " -e, --exportSBML file The SBML file to export.\n"
63  " -i, --importSBML file A SBML file to import.\n"
64  " -s, --save file The file the model is saved to after work.\n"
65  " -t, --tmp dir The temp directory used for autosave.\n";
66 
67 const char const_help_comment[] =
68  "use the -h option for help";
69 
70 const char* expand_long_name(const std::string &name);
71 }
72 
73 //#########################################################################
75  : state_(state_option)
76 {
77  memset(&locations_, 0, sizeof(locations_));
78 }
79 //#########################################################################
80 void copasi::COptionParser::parse(int argc, char *argv[], bool call_finalize)
81 {
82  int i = 1;
83 
84 #ifdef Darwin
85 
86  if (argc > 1)
87  {
88  std::string tmp(argv[1]);
89 
90  if (!tmp.compare(0, 4, "-psn")) i = 2;
91  }
92 
93 #endif // Darwin
94 
95  for (; i < argc; ++i) parse_element(argv[i], i, source_cl);
96 
97  if (call_finalize) finalize();
98 }
99 //#########################################################################
100 void copasi::COptionParser::parse(const char * fileName)
101 {
102  int LineCounter = 0;
103  std::string Line;
104  std::string Option;
105  std::string Value;
106  std::string::size_type pos;
107  std::ifstream File(fileName);
108 
109  if (File.fail())
110  {
111  std::ostringstream error;
112  error << "error opening file: '" << fileName << "'";
113  errno = ENOENT;
114 
115  throw option_error(error.str());
116  }
117 
118  while (true)
119  {
120  try
121  {
122  std::getline(File, Line);
123  LineCounter++;
124 
125  if (File.eof()) break;
126 
127  if (File.fail())
128  {
129  std::ostringstream error;
130  error << "unknown problem";
131 
132  throw option_error(error.str());
133  }
134 
135 #ifndef WIN32
136  /* Take care of dos style line ending under UNIX */
137  /* A case where MS has the better implementation */
138  pos = Line.length();
139  (pos < 1) ? 0 : pos--;
140 
141  if (Line[pos] == 0xd) Line.erase(pos);
142 
143 #endif // not WIN32
144 
145  // eat leading spaces
146  Line.erase(0, Line.find_first_not_of(' '));
147 
148  // skip comments and empty lines
149  if (Line.length() == 0 || Line[0] == '#') continue;
150 
151  // find first position of '=' or ':'
152  pos = Line.find_first_of(":=");
153 
154  Option = "--" + Line.substr(0, pos);
155  Option.erase(Option.find_last_not_of(' ') + 1);
156 
157  parse_element(Option.c_str(), 0, source_cf);
158 
159  if (pos != std::string::npos) // We have a '='
160  {
161  Value = Line.substr(pos + 1);
162  Value.erase(0, Value.find_first_not_of(' '));
163  Value.erase(Value.find_last_not_of(' ') + 1);
164 
165  if (Value.length()) parse_element(Value.c_str(), 0, source_cf);
166  }
167 
168  finalize();
169  }
170 
171  catch (copasi::option_error &e)
172  {
173  std::ostringstream error;
174  error << "error reading file: '" << fileName << "(" << LineCounter
175  << ")': " << e.what();
176 
177  throw option_error(error.str());
178  }
179  }
180 
181  File.clear();
182  File.close();
183 }
184 //#########################################################################
186 {
187  if (state_ == state_value)
188  {
189  switch (openum_)
190  {
191  case option_ConfigDir:
192  throw option_error("missing value for 'configdir' option");
193  case option_ConfigFile:
194  throw option_error("missing value for 'configfile' option");
195  case option_CopasiDir:
196  throw option_error("missing value for 'copasidir' option");
197  case option_ExportBerkeleyMadonna:
198  throw option_error("missing value for 'exportBerkeleyMadonna' option");
199  case option_ExportC:
200  throw option_error("missing value for 'exportC' option");
201  case option_ExportSBML:
202  throw option_error("missing value for 'exportSBML' option");
203  case option_ExportXPPAUT:
204  throw option_error("missing value for 'exportXPPAUT' option");
205  case option_Home:
206  throw option_error("missing value for 'home' option");
207  case option_ImportSBML:
208  throw option_error("missing value for 'importSBML' option");
209  case option_License:
210  throw option_error("missing value for 'license' option");
211  case option_MaxTime:
212  throw option_error("missing value for 'maxTime' option");
213  case option_NoLogo:
214  throw option_error("missing value for 'nologo' option");
215  case option_SBMLSchema:
216  throw option_error("missing value for 'SBMLSchema' option");
217  case option_Save:
218  throw option_error("missing value for 'save' option");
219  case option_Tmp:
220  throw option_error("missing value for 'tmp' option");
221  case option_Validate:
222  throw option_error("missing value for 'validate' option");
223  case option_Verbose:
224  throw option_error("missing value for 'verbose' option");
225  }
226  }
227 }
228 //#########################################################################
229 void copasi::COptionParser::parse_element(const char *element, int position, opsource source)
230 {
231  size_t length = strlen(element);
232 
233  switch (state_)
234  {
235  case state_consume:
236  non_options_.push_back(element);
237  break;
238  case state_option:
239 
240  if (length >= 2 && element[0] == '-' && element[1] == '-')
241  {
242  if (length == 2) {state_ = state_consume; return;}
243 
244  element += 2;
245  const char *value = element;
246 
247  while (*value != 0 && *value != '=') ++value;
248 
249  if (*value == '=')
250  {
251  std::string selement(element, value - element), svalue(++value);
252 
253  parse_long_option(selement.c_str(), position, source);
254 
255  if (state_ != state_value)
256  {
257  std::string error("the '"); error += element; error += "' option does not take a value";
258  throw option_error(error);
259  }
260 
261  parse_value(svalue.c_str());
262  state_ = state_option;
263  }
264  else
265  {
266  parse_long_option(element, position, source);
267  }
268  }
269  else if (length >= 2 && element[0] == '-')
270  {
271  ++element;
272 
273  if (length > 2)
274  {
275  while (*element != 0)
276  {
277  parse_short_option(*element, position, source);
278  ++element;
279 
280  if (state_ == state_value && *element == '=')
281  {
282  parse_value(++element);
283  state_ = state_option;
284  break;
285  }
286  else if (state_ == state_value) finalize();
287  }
288  }
289  else
290  {
291  parse_short_option(*element, position, source);
292  }
293  }
294  else
295  {
296  non_options_.push_back(element);
297  }
298 
299  break;
300  case state_value:
301  parse_value(element);
302  state_ = state_option;
303  break;
304  }
305 }
306 //#########################################################################
307 void copasi::COptionParser::parse_short_option(char option, int position, opsource source)
308 {
309  switch (option)
310  {
311  case 'c':
312 
313  if (source != source_cl) throw option_error("the 'copasidir' option can only be used on the command line");
314 
315  if (locations_.CopasiDir)
316  {
317  throw option_error("the 'copasidir' option is only allowed once");
318  }
319 
320  openum_ = option_CopasiDir;
321  state_ = state_value;
322  locations_.CopasiDir = position;
323  return;
324  case 'e':
325 
326  if (source != source_cl) throw option_error("the 'exportSBML' option can only be used on the command line");
327 
328  if (locations_.ExportSBML)
329  {
330  throw option_error("the 'exportSBML' option is only allowed once");
331  }
332 
333  openum_ = option_ExportSBML;
334  state_ = state_value;
335  locations_.ExportSBML = position;
336  return;
337  case 'i':
338 
339  if (source != source_cl) throw option_error("the 'importSBML' option can only be used on the command line");
340 
341  if (locations_.ImportSBML)
342  {
343  throw option_error("the 'importSBML' option is only allowed once");
344  }
345 
346  openum_ = option_ImportSBML;
347  state_ = state_value;
348  locations_.ImportSBML = position;
349  return;
350  case 's':
351  source = source; // kill compiler unused variable warning
352 
353  if (locations_.Save)
354  {
355  throw option_error("the 'save' option is only allowed once");
356  }
357 
358  openum_ = option_Save;
359  state_ = state_value;
360  locations_.Save = position;
361  return;
362  case 't':
363  source = source; // kill compiler unused variable warning
364 
365  if (locations_.Tmp)
366  {
367  throw option_error("the 'tmp' option is only allowed once");
368  }
369 
370  openum_ = option_Tmp;
371  state_ = state_value;
372  locations_.Tmp = position;
373  return;
374  case 'h':
375 
376  if (source != source_cl) break;
377 
378  throw autoexcept(autothrow_help, const_usage);
379  case '?':
380 
381  if (source != source_cl) break;
382 
383  throw autoexcept(autothrow_help, const_usage);
384  }
385 
386  std::string error("unknown option: '"); error += option; error += "'";
387  throw option_error(error);
388 }
389 //#########################################################################
390 void copasi::COptionParser::parse_long_option(const char *option, int position, opsource source)
391 {
392  option = expand_long_name(option);
393 
394  if (strcmp(option, "SBMLSchema") == 0)
395  {
396  if (source != source_cl) throw option_error("the 'SBMLSchema' option is only allowed on the command line");
397 
398  if (locations_.SBMLSchema)
399  {
400  throw option_error("the 'SBMLSchema' option is only allowed once");
401  }
402 
403  openum_ = option_SBMLSchema;
404  locations_.SBMLSchema = position;
405  state_ = state_value;
406  return;
407  }
408  else if (strcmp(option, "configdir") == 0)
409  {
410  if (source != source_cl) throw option_error("the 'configdir' option is only allowed on the command line");
411 
412  if (locations_.ConfigDir)
413  {
414  throw option_error("the 'configdir' option is only allowed once");
415  }
416 
417  openum_ = option_ConfigDir;
418  locations_.ConfigDir = position;
419  state_ = state_value;
420  return;
421  }
422  else if (strcmp(option, "configfile") == 0)
423  {
424  if (source != source_cl) throw option_error("the 'configfile' option is only allowed on the command line");
425 
426  if (locations_.ConfigFile)
427  {
428  throw option_error("the 'configfile' option is only allowed once");
429  }
430 
431  openum_ = option_ConfigFile;
432  locations_.ConfigFile = position;
433  state_ = state_value;
434  return;
435  }
436  else if (strcmp(option, "copasidir") == 0)
437  {
438  if (source != source_cl) throw option_error("the 'copasidir' option is only allowed on the command line");
439 
440  if (locations_.CopasiDir)
441  {
442  throw option_error("the 'copasidir' option is only allowed once");
443  }
444 
445  openum_ = option_CopasiDir;
446  locations_.CopasiDir = position;
447  state_ = state_value;
448  return;
449  }
450  else if (strcmp(option, "exportBerkeleyMadonna") == 0)
451  {
452  if (source != source_cl) throw option_error("the 'exportBerkeleyMadonna' option is only allowed on the command line");
453 
454  if (locations_.ExportBerkeleyMadonna)
455  {
456  throw option_error("the 'exportBerkeleyMadonna' option is only allowed once");
457  }
458 
459  openum_ = option_ExportBerkeleyMadonna;
460  locations_.ExportBerkeleyMadonna = position;
461  state_ = state_value;
462  return;
463  }
464  else if (strcmp(option, "exportC") == 0)
465  {
466  if (source != source_cl) throw option_error("the 'exportC' option is only allowed on the command line");
467 
468  if (locations_.ExportC)
469  {
470  throw option_error("the 'exportC' option is only allowed once");
471  }
472 
473  openum_ = option_ExportC;
474  locations_.ExportC = position;
475  state_ = state_value;
476  return;
477  }
478  else if (strcmp(option, "exportSBML") == 0)
479  {
480  if (source != source_cl) throw option_error("the 'exportSBML' option is only allowed on the command line");
481 
482  if (locations_.ExportSBML)
483  {
484  throw option_error("the 'exportSBML' option is only allowed once");
485  }
486 
487  openum_ = option_ExportSBML;
488  locations_.ExportSBML = position;
489  state_ = state_value;
490  return;
491  }
492  else if (strcmp(option, "exportXPPAUT") == 0)
493  {
494  if (source != source_cl) throw option_error("the 'exportXPPAUT' option is only allowed on the command line");
495 
496  if (locations_.ExportXPPAUT)
497  {
498  throw option_error("the 'exportXPPAUT' option is only allowed once");
499  }
500 
501  openum_ = option_ExportXPPAUT;
502  locations_.ExportXPPAUT = position;
503  state_ = state_value;
504  return;
505  }
506  else if (strcmp(option, "home") == 0)
507  {
508  if (source != source_cl) throw option_error("the 'home' option is only allowed on the command line");
509 
510  if (locations_.Home)
511  {
512  throw option_error("the 'home' option is only allowed once");
513  }
514 
515  openum_ = option_Home;
516  locations_.Home = position;
517  state_ = state_value;
518  return;
519  }
520  else if (strcmp(option, "importSBML") == 0)
521  {
522  if (source != source_cl) throw option_error("the 'importSBML' option is only allowed on the command line");
523 
524  if (locations_.ImportSBML)
525  {
526  throw option_error("the 'importSBML' option is only allowed once");
527  }
528 
529  openum_ = option_ImportSBML;
530  locations_.ImportSBML = position;
531  state_ = state_value;
532  return;
533  }
534  else if (strcmp(option, "license") == 0)
535  {
536  if (source != source_cl) throw option_error("the 'license' option is only allowed on the command line");
537 
538  if (locations_.License)
539  {
540  throw option_error("the 'license' option is only allowed once");
541  }
542 
543  openum_ = option_License;
544  locations_.License = position;
545  options_.License = !options_.License;
546  return;
547  }
548  else if (strcmp(option, "maxTime") == 0)
549  {
550  if (source != source_cl) throw option_error("the 'maxTime' option is only allowed on the command line");
551 
552  if (locations_.MaxTime)
553  {
554  throw option_error("the 'maxTime' option is only allowed once");
555  }
556 
557  openum_ = option_MaxTime;
558  locations_.MaxTime = position;
559  state_ = state_value;
560  return;
561  }
562  else if (strcmp(option, "nologo") == 0)
563  {
564  source = source; // kill compiler unused variable warning
565 
566  if (locations_.NoLogo)
567  {
568  throw option_error("the 'nologo' option is only allowed once");
569  }
570 
571  openum_ = option_NoLogo;
572  locations_.NoLogo = position;
573  options_.NoLogo = !options_.NoLogo;
574  return;
575  }
576  else if (strcmp(option, "save") == 0)
577  {
578  source = source; // kill compiler unused variable warning
579 
580  if (locations_.Save)
581  {
582  throw option_error("the 'save' option is only allowed once");
583  }
584 
585  openum_ = option_Save;
586  locations_.Save = position;
587  state_ = state_value;
588  return;
589  }
590  else if (strcmp(option, "tmp") == 0)
591  {
592  source = source; // kill compiler unused variable warning
593 
594  if (locations_.Tmp)
595  {
596  throw option_error("the 'tmp' option is only allowed once");
597  }
598 
599  openum_ = option_Tmp;
600  locations_.Tmp = position;
601  state_ = state_value;
602  return;
603  }
604  else if (strcmp(option, "validate") == 0)
605  {
606  source = source; // kill compiler unused variable warning
607 
608  if (locations_.Validate)
609  {
610  throw option_error("the 'validate' option is only allowed once");
611  }
612 
613  openum_ = option_Validate;
614  locations_.Validate = position;
615  options_.Validate = !options_.Validate;
616  return;
617  }
618  else if (strcmp(option, "verbose") == 0)
619  {
620  source = source; // kill compiler unused variable warning
621 
622  if (locations_.Verbose)
623  {
624  throw option_error("the 'verbose' option is only allowed once");
625  }
626 
627  openum_ = option_Verbose;
628  locations_.Verbose = position;
629  options_.Verbose = !options_.Verbose;
630  return;
631  }
632  else if (source == source_cl && strcmp(option, "help") == 0)
633  {
634  throw autoexcept(autothrow_help, const_usage);
635  }
636 
637  std::string error("unknown option '"); error += option; error += "'";
638  throw option_error(error);
639 }
640 //#########################################################################
641 void copasi::COptionParser::parse_value(const char *value)
642 {
643  switch (openum_)
644  {
645  case option_ConfigDir:
646  {
647  options_.ConfigDir = value;
648  }
649  break;
650  case option_ConfigFile:
651  {
652  options_.ConfigFile = value;
653  }
654  break;
655  case option_CopasiDir:
656  {
657  options_.CopasiDir = value;
658  }
659  break;
660  case option_ExportBerkeleyMadonna:
661  {
662  options_.ExportBerkeleyMadonna = value;
663  }
664  break;
665  case option_ExportC:
666  {
667  options_.ExportC = value;
668  }
669  break;
670  case option_ExportSBML:
671  {
672  options_.ExportSBML = value;
673  }
674  break;
675  case option_ExportXPPAUT:
676  {
677  options_.ExportXPPAUT = value;
678  }
679  break;
680  case option_Home:
681  {
682  options_.Home = value;
683  }
684  break;
685  case option_ImportSBML:
686  {
687  options_.ImportSBML = value;
688  }
689  break;
690  case option_License:
691  break;
692  case option_MaxTime:
693  {
694  char *endptr; int tmp = std::strtol(value, &endptr, 0);
695 
696  while (*endptr != 0 && std::isspace(*endptr)) ++endptr;
697 
698  if (*endptr != 0)
699  {
700  std::string error("invalid integer value '"); error += value; error += "'";
701  throw option_error(error);
702  }
703 
704  if (tmp < 0)
705  {
706  throw option_error("integer value out of range, 'maxTime' min is 0");
707  }
708 
709  options_.MaxTime = tmp;
710  }
711  break;
712  case option_NoLogo:
713  break;
714  case option_SBMLSchema:
715  {
716  SBMLSchema_enum evalue;
717 
718  if (strcmp(value, "L1V1") == 0)
719  {
720  evalue = SBMLSchema_L1V1;
721  }
722  else if (strcmp(value, "L1V2") == 0)
723  {
724  evalue = SBMLSchema_L1V2;
725  }
726  else if (strcmp(value, "L2V1") == 0)
727  {
728  evalue = SBMLSchema_L2V1;
729  }
730  else if (strcmp(value, "L2V2") == 0)
731  {
732  evalue = SBMLSchema_L2V2;
733  }
734  else if (strcmp(value, "L2V3") == 0)
735  {
736  evalue = SBMLSchema_L2V3;
737  }
738  else if (strcmp(value, "L2V4") == 0)
739  {
740  evalue = SBMLSchema_L2V4;
741  }
742  else if (strcmp(value, "L3V1") == 0)
743  {
744  evalue = SBMLSchema_L3V1;
745  }
746  else
747  {
748  std::string error("'"); error += value; error += "' is an invalid value for the 'SBMLSchema' option";
749  throw option_error(error);
750  }
751 
752  options_.SBMLSchema = evalue;
753  }
754  break;
755  case option_Save:
756  {
757  options_.Save = value;
758  }
759  break;
760  case option_Tmp:
761  {
762  options_.Tmp = value;
763  }
764  break;
765  case option_Validate:
766  break;
767  case option_Verbose:
768  break;
769  }
770 }
771 //#########################################################################
773 {
774  return const_help_comment;
775 }
776 //#########################################################################
777 namespace
778 {
779 const char* expand_long_name(const std::string &name)
780 {
781  std::string::size_type name_size = name.size();
782  std::vector<const char*> matches;
783 
784  if (name_size <= 10 && name.compare("SBMLSchema") == 0)
785  matches.push_back("SBMLSchema");
786 
787  if (name_size <= 9 && name.compare("configdir") == 0)
788  matches.push_back("configdir");
789 
790  if (name_size <= 10 && name.compare("configfile") == 0)
791  matches.push_back("configfile");
792 
793  if (name_size <= 9 && name.compare("copasidir") == 0)
794  matches.push_back("copasidir");
795 
796  if (name_size <= 21 && name.compare("exportBerkeleyMadonna") == 0)
797  matches.push_back("exportBerkeleyMadonna");
798 
799  if (name_size <= 7 && name.compare("exportC") == 0)
800  matches.push_back("exportC");
801 
802  if (name_size <= 10 && name.compare("exportSBML") == 0)
803  matches.push_back("exportSBML");
804 
805  if (name_size <= 12 && name.compare("exportXPPAUT") == 0)
806  matches.push_back("exportXPPAUT");
807 
808  if (name_size <= 4 && name.compare("home") == 0)
809  matches.push_back("home");
810 
811  if (name_size <= 10 && name.compare("importSBML") == 0)
812  matches.push_back("importSBML");
813 
814  if (name_size <= 7 && name.compare("license") == 0)
815  matches.push_back("license");
816 
817  if (name_size <= 7 && name.compare("maxTime") == 0)
818  matches.push_back("maxTime");
819 
820  if (name_size <= 6 && name.compare("nologo") == 0)
821  matches.push_back("nologo");
822 
823  if (name_size <= 4 && name.compare("save") == 0)
824  matches.push_back("save");
825 
826  if (name_size <= 3 && name.compare("tmp") == 0)
827  matches.push_back("tmp");
828 
829  if (name_size <= 8 && name.compare("validate") == 0)
830  matches.push_back("validate");
831 
832  if (name_size <= 7 && name.compare("verbose") == 0)
833  matches.push_back("verbose");
834 
835  if (name_size <= 4 && name.compare("help") == 0)
836  matches.push_back("help");
837 
838  if (matches.empty())
839  {
840  std::string error("unknown option '"); error += name; error += "'";
841  throw copasi::option_error(error);
842  }
843 
844  if (matches.size() == 1)
845  {
846  return matches[0];
847  }
848 
849  std::string error("the option name '"); error += name; error += "' is ambiguous";
850  throw copasi::option_error(error);
851 }
852 } // end anonymous namespace
void parse_short_option(char option, int position, opsource source)
void parse_element(const char *element, int position, opsource source)
const char * get_help_comment(void) const
option_locations locations_
void parse_long_option(const char *option, int position, opsource source)
void parse_value(const char *value)
void parse(int argc, char *argv[], bool call_finalize=true)
parse the command line
COptionParser(void)
default constructor
void finalize(void)
finalize all parsing (eg. check for mandatory options)