5 #if defined(ECERE_BOOTSTRAP)
15 #if defined(__WIN32__)
17 #define WIN32_LEAN_AND_MEAN
19 #define GetFreeSpace _GetFreeSpace
20 #define String String_
25 #elif defined(__unix__) || defined(__APPLE__)
46 FILE *eC_stdout(void);
47 FILE *eC_stderr(void);
49 // IMPLEMENTED IN _System.c
50 bool System_MoveFile(const char * source, const char * dest);
51 bool System_RenameFile(const char * oldName, const char * newName);
52 bool System_DeleteFile(const char * fileName);
53 bool System_MakeDir(const char * path);
54 bool System_RemoveDir(const char * path);
55 char * System_GetWorkingDir(char * buf, int size);
56 bool System_ChangeWorkingDir(const char * buf);
57 char * System_GetEnvironment(const char * envName, char * envValue, int max);
58 void System_SetEnvironment(const char * envName, const char * envValue);
59 void System_UnsetEnvironment(const char * envName);
60 bool System_Execute(const char * env, const char * command, va_list args, bool wait);
61 bool System_ShellOpen(const char * fileName, va_list args);
62 void System_GetFreeSpace(const char * path, FileSize64 * size);
66 #if !defined(ECERE_BOOTSTRAP)
69 #if !defined(__EMSCRIPTEN__)
79 import "GuiApplication"
82 public enum LoggingMode { noLogging, stdOut, stdErr, debug, logFile, msgBox, buffer };
84 // GENERAL ERROR CODES
85 public enum ErrorLevel
93 public define AllErrors = ErrorLevel::minor;
95 public class ErrorCode
98 ErrorLevel level:2:12;
102 // TODO: Support enums resolved in compiling pass to allow moving this to GuiApplication.ec
103 public enum SysErrorCode : ErrorCode
105 allocationFailed = ErrorCode { fatal, 0x001 },
106 nameInexistant = ErrorCode { fatal, 0x002 },
107 nameExists = ErrorCode { fatal, 0x003 },
108 missingLibrary = ErrorCode { fatal, 0x004 },
109 fileNotFound = ErrorCode { minor, 0x005 },
110 writeFailed = ErrorCode { major, 0x006 }
113 public enum GuiErrorCode : ErrorCode
115 driverNotSupported = ErrorCode { veryFatal, 0x101 },
116 windowCreationFailed = ErrorCode { veryFatal, 0x102 },
117 graphicsLoadingFailed = ErrorCode { veryFatal, 0x103 },
118 modeSwitchFailed = ErrorCode { veryFatal, 0x104 }
121 static define DEFAULT_BUFFER_SIZE = 100 * MAX_F_STRING;
123 static Array<const String> sysErrorMessages
126 $"Memory allocation failed",
127 $"Inexistant string identifier specified",
128 $"Identic string identifier already exists",
129 $"Shared library loading failed",
131 $"Couldn't write to file"
134 static Array<const String> guiErrorMessages
137 $"Graphics driver not supported by any user interface system",
138 $"Window creation failed",
139 $"Window graphics loading failed",
140 $"Driver/Mode switch failed"
143 static Array<Array<const String>> errorMessages { [ sysErrorMessages, guiErrorMessages ] };
145 // --- File, directory & environment manipulation ---
148 public bool MoveFile(const char * source, const char * dest)
150 return System_MoveFile(source, dest);
153 public bool RenameFile(const char * oldName, const char * newName)
155 return System_RenameFile(oldName, newName);
160 public bool DeleteFile(const char * fileName)
162 return System_DeleteFile(fileName);
165 public bool MakeDir(const char * path)
167 return System_MakeDir(path);
170 public bool RemoveDir(const char * path)
172 return System_RemoveDir(path);
175 public char * GetWorkingDir(char * buf, int size)
177 return System_GetWorkingDir(buf, size);
180 public bool ChangeWorkingDir(const char * buf)
182 return System_ChangeWorkingDir(buf);
185 public char * GetEnvironment(const char * envName, char * envValue, int max)
187 return System_GetEnvironment(envName, envValue, max);
190 public void SetEnvironment(const char * envName, const char * envValue)
192 System_SetEnvironment(envName, envValue);
195 public void UnsetEnvironment(const char * envName)
197 System_UnsetEnvironment(envName);
200 public bool Execute(const char * command, ...)
204 va_start(args, command);
205 result = System_Execute(null, command, args, false);
210 public bool ExecuteWait(const char * command, ...)
214 va_start(args, command);
215 result = System_Execute(null, command, args, true);
220 public bool ExecuteEnv(const char * env, const char * command, ...)
224 va_start(args, command);
225 result = System_Execute(env, command, args, false);
230 public bool ShellOpen(const char * fileName, ...)
234 va_start(args, fileName);
235 result = System_ShellOpen(fileName, args);
240 public void GetFreeSpace(const char * path, FileSize64 * size)
242 System_GetFreeSpace(path, size);
245 // --- Uncagotegorized Functions ---
246 public void Logf(const char * format, ...)
249 char string[MAX_F_STRING];
250 va_start(args, format);
251 vsnprintf(string, sizeof(string), format, args);
252 string[sizeof(string)-1] = 0;
257 public void Log(const char * text)
259 switch(globalSystem.errorLoggingMode)
262 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
264 uint16 * _wtext = UTF8toUTF16(text, null);
265 OutputDebugString(_wtext);
271 fputs(text, eC_stdout());
275 fputs(text, eC_stderr());
281 if((f = FileOpen(globalSystem.logFile, append)))
290 strcat(globalSystem.errorBuffer, text);
295 public void DumpErrors(bool display)
297 if(globalSystem.errorBuffer && globalSystem.errorBuffer[0])
301 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
302 if(globalSystem.errorLoggingMode == buffer)
303 printf(globalSystem.errorBuffer);
307 sprintf(title, "%s - Error Log", guiApp.appName);
308 MessageBoxA(HWND_DESKTOP, globalSystem.errorBuffer, title, MB_OK|MB_ICONWARNING);
311 printf("%s", globalSystem.errorBuffer);
314 globalSystem.errorBuffer[0] = '\0';
318 public void LogErrorCode(ErrorCode errorCode, const char * details)
320 if(errorCode.level <= globalSystem.errorLevel)
322 int cat = (errorCode.code & 0xF00) >> 8;
323 int code = errorCode.code & 0xFF;
325 Logf("System Error [%d]: %s (%s).\n",
327 errorMessages[cat][code],
330 Logf("System Error [%d]: %s.\n",
332 errorMessages[cat][code]);
334 globalSystem.lastErrorCode = errorCode;
337 public uint GetLastErrorCode()
339 return globalSystem.lastErrorCode;
342 public void ResetError()
344 globalSystem.lastErrorCode = 0;
347 public void SetErrorLevel(ErrorLevel level)
349 globalSystem.errorLevel = level;
352 public void SetLoggingMode(LoggingMode mode, void * where)
354 globalSystem.errorLoggingMode = mode;
359 strcpy(globalSystem.logFile, where);
360 file = FileOpen(globalSystem.logFile, write);
363 else if(mode == buffer || mode == msgBox)
365 if(!globalSystem.errorBuffer)
367 globalSystem.errorBufferSize = DEFAULT_BUFFER_SIZE;
368 globalSystem.errorBuffer = new char[DEFAULT_BUFFER_SIZE];
370 globalSystem.errorBuffer[0] = 0;
372 else if(mode == debug)
374 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
375 uint16 * _wappName = UTF8toUTF16(guiApp.appName, null);
376 OutputDebugString(L"\n");
377 OutputDebugString(_wappName);
378 OutputDebugString(L" - Logging Errors...\n");
385 if(globalSystem.errorBuffer)
387 delete globalSystem.errorBuffer;
388 globalSystem.errorBufferSize = 0;
393 static define errorLogMsg = $"\n\nWould you like to view the error log?";
395 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
396 static DWORD REAL_ExceptionHandler(EXCEPTION_POINTERS *exception)
398 EXCEPTION_RECORD * record = exception->ExceptionRecord;
399 char exceptionString[1024] = "", title[1024];
401 switch(record->ExceptionCode)
403 case EXCEPTION_ACCESS_VIOLATION:
404 if(record->ExceptionInformation[0])
405 sprintf(exceptionString, "Access Violation Writing to 0x%p", (void *)record->ExceptionInformation[1]);
407 sprintf(exceptionString, "Access Violation Reading from 0x%p", (void *)record->ExceptionInformation[1]);
409 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
410 sprintf(exceptionString, "Array Bounds Exceeded");
412 case EXCEPTION_BREAKPOINT:
413 sprintf(exceptionString, "Breakpoint Encountered");
415 case EXCEPTION_DATATYPE_MISALIGNMENT:
416 sprintf(exceptionString, "Data Type Misalignment");
418 case EXCEPTION_FLT_DENORMAL_OPERAND:
419 sprintf(exceptionString, "Floating-Point Denormal Operand");
421 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
422 sprintf(exceptionString, "Floating-Point Divide by Zero");
424 case EXCEPTION_FLT_INEXACT_RESULT:
425 sprintf(exceptionString, "Floating-Point Inexact Result");
427 case EXCEPTION_FLT_INVALID_OPERATION:
428 sprintf(exceptionString, "Floating-Point Invalid Operation");
430 case EXCEPTION_FLT_OVERFLOW:
431 sprintf(exceptionString, "Floating-Point Overflow");
433 case EXCEPTION_FLT_STACK_CHECK:
434 sprintf(exceptionString, "Floating-Point Stack Check");
436 case EXCEPTION_FLT_UNDERFLOW:
437 sprintf(exceptionString, "Floating-Point Underflow");
439 case EXCEPTION_ILLEGAL_INSTRUCTION:
440 sprintf(exceptionString, "Illegal Instruction");
442 case EXCEPTION_IN_PAGE_ERROR:
443 sprintf(exceptionString, "In Page Error");
445 case EXCEPTION_INT_DIVIDE_BY_ZERO:
446 sprintf(exceptionString, "Integer Divide by Zero");
448 case EXCEPTION_INT_OVERFLOW:
449 sprintf(exceptionString, "Integer Overflow");
451 case EXCEPTION_INVALID_DISPOSITION:
452 sprintf(exceptionString, "Invalid Disposition");
454 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
455 sprintf(exceptionString, "Non Continuable Exception");
457 case EXCEPTION_PRIV_INSTRUCTION:
458 sprintf(exceptionString, "Unallowed Instruction");
460 case EXCEPTION_SINGLE_STEP:
461 sprintf(exceptionString, "Single Step Exception");
463 case EXCEPTION_STACK_OVERFLOW:
464 return EXCEPTION_CONTINUE_SEARCH;
465 //sprintf(exceptionString, "Stack Overflow");
469 sprintf(title, "%s - Fatal Error", guiApp.appName);
471 if(globalSystem.errorBuffer && globalSystem.errorBuffer[0])
473 strcat(exceptionString, errorLogMsg);
474 if(MessageBoxA(HWND_DESKTOP, exceptionString, title, MB_YESNO|MB_ICONERROR) == IDYES)
478 MessageBoxA(HWND_DESKTOP, exceptionString, title, MB_OK|MB_ICONERROR);
480 return EXCEPTION_EXECUTE_HANDLER;
485 private struct System
487 LoggingMode errorLoggingMode;
490 char logFile[MAX_LOCATION];
491 ErrorCode lastErrorCode;
492 ErrorLevel errorLevel;
494 #ifndef ECERE_BOOTSTRAP
495 #if !defined(__EMSCRIPTEN__)
496 Semaphore eventSemaphore;
499 //FileSystem fileSystems;
502 OldList fileMonitors;
503 #if !defined(__EMSCRIPTEN__)
504 Mutex fileMonitorMutex;
505 Thread fileMonitorThread;
507 bool systemTerminate;