OpenWalnut  1.5.0dev
OpenWalnutScript.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <fstream>
26 #include <iostream>
27 #include <memory>
28 #include <string>
29 #include <vector>
30 
31 #ifdef OW_BOOST_PROGRAM_OPTIONS_FIX
32 // This circumvents an issue with boost program_options. The linker complains about missing "arg".
33 namespace boost
34 {
35  namespace program_options
36  {
37  std::string arg;
38  }
39 }
40 #endif // OW_BOOST_PROGRAM_OPTIONS_FIX
41 #include <boost/program_options.hpp>
42 #include <boost/filesystem.hpp>
43 
44 #include "core/common/WLogger.h"
45 #include "core/common/WIOTools.h"
46 #include "core/common/WLogStream.h"
47 #include "core/common/WThreadedRunner.h"
48 #include "core/common/WSegmentationFault.h"
49 #include "core/common/WPathHelper.h"
50 
51 #include "core/kernel/WKernel.h"
52 #include "core/kernel/WModuleFactory.h"
53 
54 #include "WScriptUI.h"
55 
56 #include "core/WVersion.h" // NOTE: this file is auto-generated by CMAKE
57 
58 /**
59  * Print version info to std::cout.
60  */
61 void printVersion()
62 {
63  std::cout << "OpenWalnut -- Version: " << W_VERSION << " ( http://www.openwalnut.org )"
64  << std::endl
65  << std::endl;
66 
67  std::cout <<
68  "Copyright 2009-2022 The OpenWalnut Community\n"
69  " 2015-2022 Hochschule Worms\n"
70  " 2009-2022 BSV at Universitaet Leipzig\n"
71  " 2012-2017 Nemtics & Sebastian Eichelbaum\n"
72  " 2009-2013 MPI CBS, Leipzig, Germany\n"
73  "For more information see http://www.openwalnut.org/copying\n"
74  "This program comes with ABSOLUTELY NO WARRANTY.\n"
75  "This is free software, and you are welcome to redistribute it\n"
76  "under the terms of the GNU Lesser General Public License.\n"
77  "You should have received a copy of the GNU Lesser General Public License\n"
78  "along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>." << std::endl;
79  std::cout << std::endl; // Create new line after message for clarity.
80 
81  std::cout << "Written by the OpenWalnut Community, Hochschule Worms, Nemtics, BSV@Uni-Leipzig and CNCF@MPI-CBS." << std::endl;
82 }
83 
84 /**
85  * The main routine starting up the whole application.
86  *
87  * \param argc As always.
88  * \param argv Nothing to see here.
89  *
90  * \return 0 on success.
91  */
92 int main( int argc, char** argv )
93 {
95 
96  // where to write the by default?
97  std::string logFile = "openwalnut.log";
98 
99  // process user parameter
100  namespace po = boost::program_options; // since the namespace is far to big we use a shortcut here
101  po::options_description desc( "Options" );
102 
103  // NOTE: if you modify this, also modify the manual pages! (use help2man or do it manually) But be careful. There need
104  // to be several manual changes to be done in the manual after help2man has done its job.
105  desc.add_options()
106  ( "help,h", "Prints this help message" )
107  ( "version,v", "Prints the version information" )
108  ( "log,l", po::value< std::string >(), ( std::string( "The log-file to use. If not specified, \"" ) + logFile +
109  std::string( "\" is used in the current directory." ) ).c_str() )
110  ( "interp,i", po::value< std::string >(), "The interpreter to use." )
111  ( "file,f", po::value< std::vector< std::string > >()->multitoken(), "The script file to load and its parameters." );
112 
113  boost::program_options::variables_map optionsMap;
114  try
115  {
116  po::store( po::command_line_parser( argc, argv ).options( desc ).run(), optionsMap );
117  }
118  catch( const po::error &e )
119  {
120  std::cerr << e.what() << std::endl;
121  return -1;
122  }
123 
124  po::notify( optionsMap );
125 
126  // print usage information if command line asks for help.
127  if( optionsMap.count( "version" ) )
128  {
129  printVersion();
130  return 0;
131  }
132  else if( optionsMap.count( "help" ) || ( optionsMap.count( "interp" ) == 0 && optionsMap.count( "file" ) == 0 ) )
133  {
134  // NOTE: if you modify this, check that help2man still works properly! (http://www.gnu.org/software/help2man) But be careful. There need
135  // to be several manual changes to be done in the manual after help2man has done its job.
136  std::cout << "OpenWalnut is a highly expansible visualization system with focus on brain- and neurological data." << std::endl
137  << std::endl
138  << "Usage: openwalnut [OPTION]... [FILE]..." << std::endl
139  << std::endl
140  << desc << std::endl
141  << std::endl
142  << "Examples:" << std::endl
143  << " openwalnut-script -i lua \t\tStartup OpenWalnut in lua interpreter mode." << std::endl
144  << " openwalnut-script -i python \t\tStartup OpenWalnut in python interpreter mode." << std::endl
145  << std::endl
146  << " openwalnut-script -f doSth.py\t\tStart OpenWalnut and execute the doSth.py python script." << std::endl
147  << std::endl;
148  return 0;
149  }
150 
151  printVersion();
152 
153  // install signal handler as early as possible
155 
156  // initialize logger here. It will be started by the UI with one default console stream
158 
159  // add a crash-log.
160  if( optionsMap.count( "log" ) )
161  {
162  logFile = optionsMap["log"].as< std::string >();
163  }
164 
165  // determine log paths
166  boost::filesystem::path logPath( logFile );
167  logPath = boost::filesystem::system_complete( logPath );
168  bool fallbackLog = false; // if true, the original log file could not be opened. A fallback is provided.
169  boost::filesystem::path fallbackLogFile = tempFilename( "OpenWalnutLog-%%%%%%%%.log" );
170 
171  // is the log writeable?
172  std::ofstream crashLogFile( logPath.string().c_str() );
173  if( !crashLogFile.is_open() )
174  {
175  // try to create fallback
176  crashLogFile.open( fallbackLogFile.string().c_str() );
177  fallbackLog = true;
178  }
179 
180  // create log stream
181  if( crashLogFile.is_open() )
182  {
183  // create the WLogStream. Set special format and DISABLE colors.
184  WLogStream::SharedPtr crashLog = WLogStream::SharedPtr( new WLogStream( crashLogFile, LL_DEBUG, "%t %l %s: %m\n", false ) );
185  WLogger::getLogger()->addStream( crashLog );
186 
187  // NOTE: the stream flushes after each entry. This is needed if a crash occurs.
188  if( !fallbackLog )
189  {
190  wlog::info( "Walnut" ) << "Using the file \"" << logPath.string() << "\" for logging.";
191  }
192  else
193  {
194  wlog::info( "Walnut" ) << "Using the fallback file \"" << fallbackLogFile.string() << "\" for logging.";
195  }
196  }
197  else
198  {
199  wlog::warn( "Walnut" ) << "Could not open \"" << logPath.string() << "\" for writing. You will have no log-file.";
200  }
201 
202  // the kernel, and the UI should print their version info. This helps processing crashlogs from users.
203  wlog::info( "Walnut" ) << "Version: " << W_VERSION;
204 
205  // initialize UI
206  // NOTE: we need a shared_ptr here since WUI uses enable_shared_from_this.
207  std::shared_ptr< WScriptUI > ui( new WScriptUI( argc, argv, optionsMap ) );
208  int result = ui->run();
209 
210  std::cout << "Closed OpenWalnut smoothly. Goodbye!" << std::endl;
211 
212  return result;
213 }
214 
Class implementing a capsule for an output stream and the needed level and format information.
Definition: WLogStream.h:39
std::shared_ptr< WLogStream > SharedPtr
shared pointer type
Definition: WLogStream.h:41
static void startup(std::ostream &output=std::cout, LogLevel level=LL_DEBUG)
Create the first and only instance of the logger as it is a singleton.
Definition: WLogger.cpp:41
static WLogger * getLogger()
Returns pointer to the currently running logger instance.
Definition: WLogger.cpp:64
void addStream(WLogStream::SharedPtr s)
Adds a new stream to the logger.
Definition: WLogger.cpp:116
Implements a UI that executes scripts.
Definition: WScriptUI.h:43
static void installSignalHandler()
Installs this exception as signal handler for SIGSEGV.
static void setThisThreadName(std::string name)
Static function to set the name of the calling thread.
WStreamedLogger warn(const std::string &source)
Logging a warning message.
Definition: WLogger.h:309
WStreamedLogger info(const std::string &source)
Logging an information message.
Definition: WLogger.h:320