openETCS
case study for the European Train Control System developed for the authors dissertation
GEN/Main.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010-2011
3  Johannes Feuser <feuser@uni-bremen.de>
4  This file is part of the openETCS library.
5 
6  The openETCS library is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  any later version.
10 
11  The openETCS library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with the openETCS library. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /*!
21  * \file
22  * \author Johannes Feuser <feuser@uni-bremen.de>
23  * \brief main file for generator binary
24  *
25  * File holding the main() function and CMain class for the openETCS
26  * generator binary execution.
27  */
28 
29 #include "Main.h"
30 #include <fstream>
31 
32 
33 
34 
35 namespace oETCS {
36 
37 namespace GEN {
38 
39 
40 CMain::CMain(char ** ppArguements, int iNumberArguments) throw()
41 :m_bHelp(false),
42  m_bSource(false),
43  m_bBuildConfig(false),
44  m_bVMConfig(false),
45  m_bContraintChecking(false),
46  m_OutputDirectory("./")
47 {
48  // Bouml preserved body begin 00020D82
49  const char* const pOptions(":absvc:o:h");
50  int iOption(0);
51 
52 
53  // check, if any argument was delivered
54  if (iNumberArguments > 0)
55  {
56 
57  // get binary name from argument vector
58  m_BinaryName = ppArguements[0];
59 
60 
61  // check, if no additional arguments at all were supplied
62  if (iNumberArguments == 1)
63  {
64  // activate help flag
65  m_bHelp = true;
66 
67  // store error message
68  m_ErrorMessage << "at least the XML model file is required as argument" << ::std::endl;
69 
70  } // if (iNumberArguments == 1)
71  else
72  {
73  // process all options in argument vector
74  do
75  {
76  // get current option
77  iOption = getopt(iNumberArguments, ppArguements, pOptions);
78 
79  // switch the current option
80  switch (iOption)
81  {
82  case 'b':
83  // activate build configuration flag
84  m_bBuildConfig = true;
85  break;
86 
87 
88  case 's':
89  // activate source flag
90  m_bSource = true;
91  break;
92 
93 
94  case 'v':
95  // activate VM configuration flag
96  m_bVMConfig = true;
97  break;
98 
99 
100  case 'a':
101  // activate all generation flags
102  m_bBuildConfig = true;
103  m_bSource = true;
104  m_bVMConfig = true;
105  break;
106 
107 
108  case 'c':
109  // activate constraint checking flag
110  m_bContraintChecking = true;
111 
112  // get constraint file name from argument
113  m_ContraintFile = optarg;
114  break;
115 
116 
117  case 'o':
118  // set output directory from argument
119  m_OutputDirectory = optarg;
120  break;
121 
122 
123  case 'h':
124  // activate help flag
125  m_bHelp = true;
126  break;
127 
128 
129  case ':':
130  // activate help flag
131  m_bHelp = true;
132 
133  // store error message
134  m_ErrorMessage << "option -" << char(optopt) << " needs an operand" << ::std::endl;
135  break;
136 
137 
138  case '?':
139  // activate help flag
140  m_bHelp = true;
141 
142  // store error message
143  m_ErrorMessage << "unknown option -" << char(optopt) << ::std::endl;
144  break;
145 
146  } // switch (iOption)
147 
148  }
149  while (iOption != -1);
150 
151  // check, if all options were parsed successfully and there is still one left
152  if (iOption == -1 && (optind == (iNumberArguments - 1) || iNumberArguments > 2))
153  {
154  // set XML file name as last argument
155  m_XMLFile = ppArguements[iNumberArguments - 1];
156 
157  } // if (iOption == -1 && (optind == (iNumberArguments - 1) || iNumberArguments == 2))
158  else
159  {
160  // set error message
161  m_ErrorMessage << "XML model file must always passed as argument" << ::std::endl;
162 
163  // activate help flag
164  m_bHelp = true;
165 
166  } // else
167 
168  } // else
169 
170  } // if (iNumberArguments > 0)
171  // Bouml preserved body end 00020D82
172 
173 } // CMain::CMain() throw()
174 
175 
176 
177 
178 CMain::~CMain() throw()
179 {
180  // Bouml preserved body begin 00020E02
181  // empty destructor
182  // Bouml preserved body end 00020E02
183 
184 } // CMain::~CMain() throw()
185 
186 
187 
188 
189 int CMain::Execute() throw()
190 {
191  // Bouml preserved body begin 00097382
192  int iReturnValue(0);
193  ::GOPPRR::CGraph* pRootGraph(0);
194  ::std::fstream SourceFile;
195  ::std::fstream CMakeFile;
196  ::std::fstream PIMFile;
197  ::std::fstream PSMFile;
198  ::std::fstream ReportFile;
199  ::std::string FileNamePrefix;
200  ::std::string SourceFileName;
201  ::std::string CMakeFileName;
202  ::std::string PIMFileName;
203  ::std::string PSMFileName;
204  ::std::string ReportFileName;
205 
206 
207 
208 
209  // check, if help was activate
210  if (m_bHelp)
211  {
212  // first print error message
213  ::std::cout << m_ErrorMessage.str();
214 
215  // than usage
216  this->PrintUsage();
217 
218  // set execution code
219  iReturnValue = 1;
220 
221  } // if (m_bHelp)
222  else
223  {
224  try
225  {
226  // print starting of parsing
227  ::std::cout << "Parsing XML model file...";
228  ::std::cout.flush();
229 
230  // first parse XML model file and create syntax tree
232 
233  // print finishing of parsing
234  ::std::cout << "done" << ::std::endl;
235 
236  // get filename prefix from root graph
237  if (pRootGraph != 0)
238  {
239  // set filename prefix from root graph ID
240  FileNamePrefix = pRootGraph->m_ID;
241 
242  // remove all white spaces from prefix
243  while (FileNamePrefix.find(" ") != std::string::npos)
244  {
245  // replace current white space with _
246  FileNamePrefix.replace(FileNamePrefix.find(" "), 1, "_");
247 
248  } // while (FileNamePrefix.find(" ") != std::string::npos)
249 
250  } // if (pRootGraph != 0)
251 
252  // check, if filename prefix is still empty
253  if (FileNamePrefix.empty())
254  {
255  // set default prefix
256  FileNamePrefix = "openETCS";
257 
258  } // if (FileNamePrefix.empty())
259 
260 
261 
262  // check for source generation flag
263  if (m_bSource)
264  {
265  // set source file name
266  SourceFileName = m_OutputDirectory + "/";
267  SourceFileName += FileNamePrefix;
268  SourceFileName += ".cpp";
269 
270  // open file stream for output
271  SourceFile.open(SourceFileName, ::std::ios_base::out);
272 
273  // check, if source file could be opened
274  if (not SourceFile.is_open())
275  {
276  // print error message
277  ::std::cout << "Could not open " << SourceFileName << " for source generation!" << ::std::endl;
278 
279  } // if (not SourceFile.is_open())
280  else
281  {
282  try
283  {
284  // print starting of parsing
285  ::std::cout << "generating C++ source file " << SourceFileName << "...";
286  ::std::cout.flush();
287 
288  // call C++ generator with syntax tree
290 
291  // print finishing of parsing
292  ::std::cout << "done" << ::std::endl;
293 
294  } // try
295  catch (const ::std::exception& Exception)
296  {
297  // print error
298  ::std::cout << "abort" << ::std::endl;
299  ::std::cerr << Exception.what() << ::std::endl;
300 
301  // set execution code
302  iReturnValue = 3;
303 
304  } // catch (const ::std::exception& Exception)
305 
306  // always close file here
307  SourceFile.close();
308 
309  } // else
310 
311  } // if (m_bSource)
312 
313 
314  // check for build generation
315  if (m_bBuildConfig)
316  {
317  // set cmake file name
318  CMakeFileName = m_OutputDirectory + "/";
319  CMakeFileName += "CMakeLists.txt";
320 
321  // open file stream for output
322  CMakeFile.open(CMakeFileName, ::std::ios_base::out);
323 
324  // check, if cmake file could be opened
325  if (not CMakeFile.is_open())
326  {
327  // print error message
328  ::std::cout << "Could not create " << CMakeFileName << " for build configuration generation!" << ::std::endl;
329 
330  } // if (not CMakeFile())
331  else
332  {
333  try
334  {
335  // print starting of parsing
336  ::std::cout << "generating CMake build configuration file " << CMakeFileName << "...";
337  ::std::cout.flush();
338 
339  // call build config generator with syntax tree
341 
342  // print finishing of parsing
343  ::std::cout << "done" << ::std::endl;
344 
345  } // try
346  catch (const ::std::exception& Exception)
347  {
348  // print error
349  ::std::cout << "abort" << ::std::endl;
350  ::std::cerr << Exception.what() << ::std::endl;
351 
352  // set execution code
353  iReturnValue = 4;
354 
355  } // catch (const ::std::exception& Exception)
356 
357  // always close file here
358  CMakeFile.close();
359 
360  } // else
361 
362  } // if (m_bBuildConfig)
363 
364 
365  // check for VM configuration
366  if (m_bVMConfig)
367  {
368  // set PIM file name
369  PIMFileName = m_OutputDirectory + "/";
370  PIMFileName += FileNamePrefix;
371  PIMFileName += "_PIM";
372  PIMFileName += ".cfg";
373 
374  // open file stream for output
375  PIMFile.open(PIMFileName, ::std::ios_base::out);
376 
377  // check, if config file could be opened
378  if (not PIMFile.is_open())
379  {
380  // print error message
381  ::std::cout << "Could not open " << PIMFileName << " for hypervisor configuration generation!" << ::std::endl;
382 
383  } // if (not PIMFile.is_open())
384  else
385  {
386  try
387  {
388  // print starting of parsing
389  ::std::cout << "generating Xen PIM config file " << PIMFileName << "...";
390  ::std::cout.flush();
391 
392  // call C++ generator with syntax tree
394 
395  // print finishing of parsing
396  ::std::cout << "done" << ::std::endl;
397 
398  } // try
399  catch (const ::std::exception& Exception)
400  {
401  // print error
402  ::std::cout << "abort" << ::std::endl;
403  ::std::cerr << Exception.what() << ::std::endl;
404 
405  // set execution code
406  iReturnValue = 5;
407 
408  } // catch (const ::std::exception& Exception)
409 
410  // always close file here
411  PIMFile.close();
412 
413  } // else
414 
415  // check, if model requires PSM configuration, too
417  {
418  // set PSM file name
419  PSMFileName = m_OutputDirectory + "/";
420  PSMFileName += FileNamePrefix;
421  PSMFileName += "_PSM";
422  PSMFileName += ".cfg";
423 
424  // open file stream for output
425  PSMFile.open(PSMFileName, ::std::ios_base::out);
426 
427  // check, if config file could be opened
428  if (not PSMFile.is_open())
429  {
430  // print error message
431  ::std::cout << "Could not open " << PSMFileName << " for hypervisor configuration generation!" << ::std::endl;
432 
433  } // if (not PSMFile.is_open())
434  else
435  {
436  try
437  {
438  // print starting of parsing
439  ::std::cout << "generating Xen PSM config file " << PSMFileName << "...";
440  ::std::cout.flush();
441 
442  // call C++ generator with syntax tree
444 
445  // print finishing of parsing
446  ::std::cout << "done" << ::std::endl;
447 
448  } // try
449  catch (const ::std::exception& Exception)
450  {
451  // print error
452  ::std::cout << "abort" << ::std::endl;
453  ::std::cerr << Exception.what() << ::std::endl;
454 
455  // set execution code
456  iReturnValue = 6;
457 
458  } // catch (const ::std::exception& Exception)
459 
460  // always close file here
461  PSMFile.close();
462 
463  } // else
464 
465  } // if (m_VMGenerator.HasPSM(m_Lexer.GetGOPRRTree()))
466 
467  } // if (m_bVMConfig)
468 
469 
470 
471  // check for constrain checking
473  {
474  // set report file name
475  ReportFileName = m_OutputDirectory + "/";
476  ReportFileName += FileNamePrefix;
477  ReportFileName += ".log";
478 
479  // open file stream for output
480  ReportFile.open(ReportFileName, ::std::ios_base::out);
481 
482  // check, if report file could be opened
483  if (not ReportFile.is_open())
484  {
485  // print error message
486  ::std::cout << "Could not create " << ReportFileName << " for static semantics report generation!" << ::std::endl;
487 
488  } // if (not ReportFile.is_open())
489  else
490  {
491  try
492  {
493  // print starting of parsing
494  ::std::cout << "WARNING: OCL usage currently not supported! Using static constraint implementation!" << ::std::endl;
495  ::std::cout << "generating report for static semantics / model constraints " << ReportFileName << "...";
496  ::std::cout.flush();
497 
498  // call build constraint report generator with project model
500 
501  // print finishing of parsing
502  ::std::cout << "done" << ::std::endl;
503 
504  } // try
505  catch (const ::std::exception& Exception)
506  {
507  // print error
508  ::std::cout << "abort" << ::std::endl;
509  ::std::cerr << Exception.what() << ::std::endl;
510 
511  // set execution code
512  iReturnValue = 7;
513 
514  } // catch (const ::std::exception& Exception)
515 
516  // always close file here
517  ReportFile.close();
518 
519  } // else
520 
521 
522 
523  } // if (m_bContraintChecking)
524 
525 
526  } // try
527  catch (const ::DSM::Error::CException& Exception)
528  {
529  // print error message
530  ::std::cout << "abort" << ::std::endl;
531  ::std::cerr << Exception.what() << ::std::endl;
532 
533  // set execution code
534  iReturnValue = 2;
535 
536  } // catch (const ::DSM::Error::CException& Exception)
537  catch (const ::std::exception& Exception)
538  {
539  // print error message
540  ::std::cerr << Exception.what() << ::std::endl;
541 
542  // set execution code
543  iReturnValue = 2;
544 
545  } // catch (const ::std::exception& Exception)
546  catch (...)
547  {
548  // print error message
549  ::std::cerr << "unhandled and unknown exception" << ::std::endl;
550 
551  // set execution code
552  iReturnValue = 2;
553 
554  } // catch (...)
555 
556  } // else
557 
558 
559 
560  // return execution code
561  return iReturnValue;
562  // Bouml preserved body end 00097382
563 
564 } // int CMain::Execute() throw()
565 
566 
567 
568 
569 void CMain::PrintUsage() throw()
570 {
571  // Bouml preserved body begin 00098F02
572  // print usage
573  ::std::cout << "Usage: " << m_BinaryName << " -a | [ -b ] [ -s ] [ -v ] [ -c <constraints file> ] [-o <output directory> ] [ -h ] <XML model file>" << ::std::endl;
574  ::std::cout << " -b generate build configuration" << ::std::endl;
575  ::std::cout << " -s generate C++ source file" << ::std::endl;
576  ::std::cout << " -v generate Xen configuration file(s)" << ::std::endl;
577  ::std::cout << " -a generates all output files" << ::std::endl;
578  ::std::cout << " -c check static semantics for <constraints file>" << ::std::endl;
579  ::std::cout << " -o sets the output directory to <output directory> instead of current one" << ::std::endl;
580  ::std::cout << " -h prints this short help" << ::std::endl;
581  ::std::cout << " The model file <XML model file> must always be set" << ::std::endl;
582  // Bouml preserved body end 00098F02
583 
584 } // void CMain::PrintUsage() throw()
585 
586 
587 
588 
589 
590 
591 } // namespace oETCS::GEN
592 
593 } // namespace oETCS
594 
595 
596 int main(int argc, char* argv[])
597 {
598  ::oETCS::GEN::CMain Main(argv, argc);
599 
600 
601  // execute Main object and return numerical result
602  return Main.Execute();
603 
604 } // int main(int argc, char* argv[])

Copyright (C) 2010-2012 Johannes Feuser (feuser@uni-bremen.de)
The openETCS library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.
The openETCS library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with the openETCS library. If not, see "http://www.gnu.org/licenses/.