00001 #include "lugre_prefix.h"
00002 #include "lugre_shell.h"
00003 #include "lugre_game.h"
00004 #include "lugre_robstring.h"
00005 #include "lugre_findpath.h"
00006 #include <Ogre.h>
00007
00008
00009 #if LUGRE_PLATFORM == LUGRE_PLATFORM_WIN32
00010 #define WIN32_LEAN_AND_MEAN
00011 #include "windows.h"
00012 #include <io.h>
00013 #endif
00014
00015 #include <time.h>
00016 #include <signal.h>
00017 #include <stdio.h>
00018 #include <fcntl.h>
00019 #include <iostream>
00020 #include <string>
00021 #include <vector>
00022 #include <stdexcept>
00023
00024
00025
00026
00027
00028
00029 #include <string>
00030
00031 #ifdef ENABLE_THREADS
00032 #include <boost/thread/thread.hpp>
00033 #endif
00034
00035 namespace Lugre {
00036
00037 std::string sLuaMainPath;
00038 std::string sLugreLuaPath;
00039 std::string sMainWorkingDir;
00040 std::string sCrashText;
00041
00042 #ifdef ENABLE_THREADS
00043 boost::thread::id gLugre_MainThreadID;
00044 bool Lugre_IsMainThread () { return gLugre_MainThreadID == boost::this_thread::get_id(); }
00045 #else
00046 bool Lugre_IsMainThread () { return true; }
00047 #endif
00048
00049 void PrintExceptionTipps (std::string sDescr);
00050
00051
00052 bool gbCustomWin32ConsoleOpen = false;
00053 bool gbLugreStarted = false;
00054
00055 void DisplayNotice (const char* szMsg);
00056 void DisplayErrorMessage (const char* szMsg);
00057 void MySignalHandler (int a);
00058 void MySignalHandlerAbort (int a);
00059 void MyCrash (const char* szMessage);
00060
00062 void PrintLuaStackTrace ();
00063 void PrintLuaStackTrace (const char *filename);
00064
00065
00066
00067 void DisplayNotice (const char* szMsg) {
00068 printf("NOTICE : %s\n",szMsg);
00069 #ifdef WIN32
00070
00071 MessageBox( NULL,szMsg, "Notice", MB_OK | MB_ICONERROR | MB_TASKMODAL);
00072 #endif
00073 }
00074
00075 void DisplayErrorMessage (const char* szMsg) {
00076 printf("ERROR : %s\n",szMsg);
00077 #ifdef WIN32
00078
00079 MessageBox( NULL,szMsg, "Error!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
00080 #endif
00081 }
00082
00083 bool gbCrashHandlerRunning = false;
00085 void MySignalHandler (int a) {
00086 if (gbCrashHandlerRunning) return;
00087 gbCrashHandlerRunning = true;
00088
00089 MyCrash("SegFault Detected");
00090 }
00092 void MySignalHandlerAbort (int a) {
00093 if (gbCrashHandlerRunning) return;
00094 gbCrashHandlerRunning = true;
00095
00096 MyCrash("Abort Signal Detected");
00097 }
00098
00099 void MyCrash (const char* szMessage,const char* szFile,unsigned int iLine,const char* szFunction) {
00100 MyCrash(strprintf("%s:%d: (in function %s): %s",szFile,iLine,szFunction,szMessage).c_str());
00101 }
00102
00103 void MyCrash (const char* szMessage) {
00104 if (!Lugre_IsMainThread()) printf("MyCrash called from non-main-thread!\n");
00105 MyShowError(szMessage);
00106 abort();
00107 }
00108
00109 void MyShowError (const char* szMessage,const char* szFile,unsigned int iLine,const char* szFunction) {
00110 MyShowError(strprintf("%s:%d: (in function %s): %s",szFile,iLine,szFunction,szMessage).c_str());
00111 }
00112
00113 void MyShowError (const char* szMessage) {
00114 if (!Lugre_IsMainThread()) { printf("MyShowError called from non-mainthread! (stacktrace not possible)\n"); }
00115 PROFILE_PRINT_STACKTRACE
00116 PrintLuaStackTrace();
00117
00118 const char *filename = "stacktrace.log";
00119
00120 {
00121
00122 struct tm *ptr;
00123 time_t tm;
00124 tm = time(NULL);
00125 ptr = localtime(&tm);
00126 FILE *f = fopen(filename,"a");
00127 if(f){
00128 fprintf(f,"\n\n:: %s\n%s\n",asctime(ptr),szMessage);
00129 fclose(f);
00130 }
00131 }
00132 PROFILE_PRINT_STACKTRACE_TOFILE(filename)
00133 PrintLuaStackTrace(filename);
00134
00135 std::string s(szMessage);
00136 s += "\n";
00137 s += sCrashText;
00138 DisplayErrorMessage(s.c_str());
00139 }
00140
00141 void Lugre_SetCrashText (const char* szCrashText) { sCrashText = szCrashText; }
00142
00143 void Lugre_ShowWin32Console () {
00144 #ifdef WIN32
00145 #ifdef SET_TERM_HANDLER
00146 SET_TERM_HANDLER;
00147 #endif
00148 gbCustomWin32ConsoleOpen = true;
00149 static const WORD MAX_CONSOLE_LINES = 500;
00150 int hConHandle;
00151 long lStdHandle;
00152 CONSOLE_SCREEN_BUFFER_INFO coninfo;
00153 FILE *fp;
00154
00155 AllocConsole();
00156
00157 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
00158 coninfo.dwSize.Y = MAX_CONSOLE_LINES;
00159 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
00160 coninfo.dwSize);
00161
00162 lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
00163 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
00164 fp = _fdopen( hConHandle, "w" );
00165 *stdout = *fp;
00166 setvbuf( stdout, NULL, _IONBF, 0 );
00167
00168 lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
00169 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
00170 fp = _fdopen( hConHandle, "r" );
00171 *stdin = *fp;
00172 setvbuf( stdin, NULL, _IONBF, 0 );
00173
00174 lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
00175 hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
00176 fp = _fdopen( hConHandle, "w" );
00177 *stderr = *fp;
00178 setvbuf( stderr, NULL, _IONBF, 0 );
00179
00180
00181 std::ios::sync_with_stdio();
00182 #endif
00183 }
00184
00185
00186 #ifdef WIN32
00187 #define strdup _strdup
00188 #endif
00189
00190 char** Lugre_ParseWinCommandLine (int& argc) {
00191 #ifdef WIN32
00192
00193 const char* szCommandLineWithProgrammName = GetCommandLine();
00194
00195 std::vector<std::string> myCmdLineParams;
00196 const char* szCmdLineSep = " \t";
00197 for (const char* r=szCommandLineWithProgrammName;*r;) {
00198 int len = strcspn(r,szCmdLineSep);
00199 myCmdLineParams.push_back(std::string(r,len));
00200 r += len;
00201 r += strspn(r,szCmdLineSep);
00202 }
00203
00204 argc = myCmdLineParams.size();
00205 char** argv = (char**)malloc(argc * sizeof(char*));
00206 for (int i=0;i<argc;++i) argv[i] = strdup(myCmdLineParams[i].c_str());
00207
00208 return argv;
00209 #else
00210 argc = 0;
00211 return 0;
00212 #endif
00213 }
00214
00215 void PrintOgreExceptionAndTipps(Ogre::Exception& e) {
00216 printf("OgreException:\n");
00217 printf(" errorcode=%d\n",e.getNumber());
00218 printf(" source=%s\n",e.getSource().c_str());
00219 printf(" file=%s\n",e.getFile().c_str());
00220 printf(" line=%ld\n",e.getLine());
00221 printf(" descr=%s\n",e.getDescription().c_str());
00222 printf(" fulldescription=%s\n",e.getFullDescription().c_str());
00223 PrintExceptionTipps(e.getFullDescription().c_str());
00224 }
00225
00226
00227 std::string GetLugreLuaPath (){
00228 return sLugreLuaPath;
00229 }
00230 std::string GetMainWorkingDir (){
00231 return sMainWorkingDir;
00232 }
00233
00234 void Lugre_Run (int argc, char* argv[]) { PROFILE
00235 #ifdef ENABLE_THREADS
00236 gLugre_MainThreadID = boost::this_thread::get_id();
00237 #endif
00238 gbLugreStarted = true;
00239
00240 try {
00241 FindBasePaths paths;
00242
00243 sLuaMainPath = paths.getMainLuaPath();
00244 sLugreLuaPath = paths.getLugreLuaPath();
00245 sMainWorkingDir = paths.getMainWorkingDir();
00246
00247 }catch(...){
00248 printf("no paths found, fallback to default settings\n");
00249 sLuaMainPath = "lua/main.lua";
00250 sLugreLuaPath = "lugre/lua/";
00251 sMainWorkingDir = "./";
00252 }
00253
00254 printf("lua main file: %s\n",sLuaMainPath.c_str());
00255 printf("lua lugre dir: %s\n",sLugreLuaPath.c_str());
00256 printf("main working dir: %s\n",sMainWorkingDir.c_str());
00257
00258
00259 signal(SIGSEGV,MySignalHandler);
00260 signal(SIGABRT,MySignalHandlerAbort);
00261
00262 try {
00263 cShell& shell = cShell::GetSingleton();
00264
00265 shell.Init(argc,argv);
00266
00267 cGame::GetSingleton().Run(argc,argv);
00268
00269 shell.DeInit();
00270
00271 } catch( Ogre::Exception& e ) {
00272 printf("ogre::exception\n");
00273 PrintOgreExceptionAndTipps(e);
00274 MyCrash((std::string("Ogre::exception occurred, see console\n") + e.getFullDescription()).c_str());
00275 } catch( std::exception& e ) {
00276 printf("std::exception\n");
00277 printf(" %s\n",e.what());
00278 PrintExceptionTipps(e.what());
00279 MyCrash((std::string("std::exception occurred, see console\n") + e.what()).c_str());
00280 } catch(...) {
00281 printf("unknown exception\n");
00282 MyCrash("unknown exception occurred\n");
00283 }
00284
00285 #ifdef WIN32
00286 if (gbCustomWin32ConsoleOpen) FreeConsole();
00287 #endif
00288 }
00289
00290 };