ecere: Fixed warnings on Android
[sdk] / ecere / src / sys / System.ec
1 namespace sys;
2
3 #if defined(ECERE_BOOTSTRAP)
4 #undef __WIN32__
5 #undef __unix__
6 #undef __APPLE__
7 #endif
8
9 default:
10 #define uint _uint
11 #define set _set
12
13 #if defined(__WIN32__)
14
15 #define WIN32_LEAN_AND_MEAN
16 #define UNICODE
17 #define GetFreeSpace _GetFreeSpace
18 #define String String_
19 #include <windows.h>
20 #undef String
21 #undef GetFreeSpace
22
23 #elif defined(__unix__) || defined(__APPLE__)
24
25 #include <sys/time.h>
26 #include <unistd.h>
27
28 #endif
29
30 #undef __BLOCKS__
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #undef uint
35 #undef set
36
37 import "Array"
38 import "i18n"
39 import "File"
40 import "TempFile"
41 import "memory"
42
43 default:
44 FILE *eC_stdout(void);
45 FILE *eC_stderr(void);
46
47 // IMPLEMENTED IN _System.c
48 bool System_MoveFile(const char * source, const char * dest);
49 bool System_RenameFile(const char * oldName, const char * newName);
50 bool System_DeleteFile(const char * fileName);
51 bool System_MakeDir(const char * path);
52 bool System_RemoveDir(const char * path);
53 char * System_GetWorkingDir(char * buf, int size);
54 bool System_ChangeWorkingDir(const char * buf);
55 char * System_GetEnvironment(const char * envName, char * envValue, int max);
56 void System_SetEnvironment(const char * envName, const char * envValue);
57 void System_UnsetEnvironment(const char * envName);
58 bool System_Execute(const char * env, const char * command, va_list args, bool wait);
59 bool System_ShellOpen(const char * fileName, va_list args);
60 void System_GetFreeSpace(const char * path, FileSize64 * size);
61
62 private:
63
64 #if !defined(ECERE_BOOTSTRAP)
65 import "units"
66 import "Time"
67 import "Mutex"
68 import "Semaphore"
69 import "FileMonitor"
70 import "Thread"
71 import "Archive"
72 import "EARArchive"
73 import "Date"
74 import "unicode"
75 import "GuiApplication"
76 #endif
77
78 public enum LoggingMode { noLogging, stdOut, stdErr, debug, logFile, msgBox, buffer };
79
80 // GENERAL ERROR CODES
81 public enum ErrorLevel
82 {
83    veryFatal = 0,
84    fatal = 1,
85    major = 2,
86    minor = 3
87 };
88
89 public define AllErrors = ErrorLevel::minor;
90
91 public class ErrorCode
92 {
93 public:
94    ErrorLevel level:2:12;
95    uint code:12:0;
96 };
97
98 // TODO: Support enums resolved in compiling pass to allow moving this to GuiApplication.ec
99 public enum SysErrorCode : ErrorCode
100 {
101    allocationFailed = ErrorCode { fatal, 0x001 },
102    nameInexistant   = ErrorCode { fatal, 0x002 },
103    nameExists       = ErrorCode { fatal, 0x003 },
104    missingLibrary   = ErrorCode { fatal, 0x004 },
105    fileNotFound     = ErrorCode { minor, 0x005 },
106    writeFailed      = ErrorCode { major, 0x006 }
107 };
108
109 public enum GuiErrorCode : ErrorCode
110 {
111    driverNotSupported      = ErrorCode { veryFatal, 0x101 },
112    windowCreationFailed    = ErrorCode { veryFatal, 0x102 },
113    graphicsLoadingFailed   = ErrorCode { veryFatal, 0x103 },
114    modeSwitchFailed        = ErrorCode { veryFatal, 0x104 }
115 };
116
117 static define DEFAULT_BUFFER_SIZE = 100 * MAX_F_STRING;
118
119 static Array<const String> sysErrorMessages
120 { [
121    $"No error",
122    $"Memory allocation failed",
123    $"Inexistant string identifier specified",
124    $"Identic string identifier already exists",
125    $"Shared library loading failed",
126    $"File not found",
127    $"Couldn't write to file"
128 ] };
129
130 static Array<const String> guiErrorMessages
131 { [
132    $"No error",
133    $"Graphics driver not supported by any user interface system",
134    $"Window creation failed",
135    $"Window graphics loading failed",
136    $"Driver/Mode switch failed"
137 ] };
138
139 static Array<Array<const String>> errorMessages { [ sysErrorMessages, guiErrorMessages ] };
140
141 // --- File, directory & environment manipulation ---
142 #undef MoveFile
143
144 public bool MoveFile(const char * source, const char * dest)
145 {
146    return System_MoveFile(source, dest);
147 }
148
149 public bool RenameFile(const char * oldName, const char * newName)
150 {
151    return System_RenameFile(oldName, newName);
152 }
153
154 #undef DeleteFile
155
156 public bool DeleteFile(const char * fileName)
157 {
158    return System_DeleteFile(fileName);
159 }
160
161 public bool MakeDir(const char * path)
162 {
163    return System_MakeDir(path);
164 }
165
166 public bool RemoveDir(const char * path)
167 {
168    return System_RemoveDir(path);
169 }
170
171 public char * GetWorkingDir(char * buf, int size)
172 {
173    return System_GetWorkingDir(buf, size);
174 }
175
176 public bool ChangeWorkingDir(const char * buf)
177 {
178    return System_ChangeWorkingDir(buf);
179 }
180
181 public char * GetEnvironment(const char * envName, char * envValue, int max)
182 {
183    return System_GetEnvironment(envName, envValue, max);
184 }
185
186 public void SetEnvironment(const char * envName, const char * envValue)
187 {
188    System_SetEnvironment(envName, envValue);
189 }
190
191 public void UnsetEnvironment(const char * envName)
192 {
193    System_UnsetEnvironment(envName);
194 }
195
196 public bool Execute(const char * command, ...)
197 {
198    bool result;
199    va_list args;
200    va_start(args, command);
201    result = System_Execute(null, command, args, false);
202    va_end(args);
203    return result;
204 }
205
206 public bool ExecuteWait(const char * command, ...)
207 {
208    bool result;
209    va_list args;
210    va_start(args, command);
211    result = System_Execute(null, command, args, true);
212    va_end(args);
213    return result;
214 }
215
216 public bool ExecuteEnv(const char * env, const char * command, ...)
217 {
218    bool result;
219    va_list args;
220    va_start(args, command);
221    result = System_Execute(env, command, args, false);
222    va_end(args);
223    return result;
224 }
225
226 public bool ShellOpen(const char * fileName, ...)
227 {
228    bool result;
229    va_list args;
230    va_start(args, fileName);
231    result = System_ShellOpen(fileName, args);
232    va_end(args);
233    return result;
234 }
235
236 public void GetFreeSpace(const char * path, FileSize64 * size)
237 {
238    System_GetFreeSpace(path, size);
239 }
240
241 // --- Uncagotegorized Functions ---
242 public void Logf(const char * format, ...)
243 {
244    va_list args;
245    char string[MAX_F_STRING];
246    va_start(args, format);
247    vsnprintf(string, sizeof(string), format, args);
248    string[sizeof(string)-1] = 0;
249    Log(string);
250    va_end(args);
251 }
252
253 public void Log(const char * text)
254 {
255    switch(globalSystem.errorLoggingMode)
256    {
257       case debug:
258 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
259       {
260          uint16 * _wtext = UTF8toUTF16(text, null);
261          OutputDebugString(_wtext);
262          delete _wtext;
263          break;
264       }
265 #endif
266       case stdOut:
267          fputs(text, eC_stdout());
268          fflush(eC_stdout());
269          break;
270       case stdErr:
271          fputs(text, eC_stderr());
272          fflush(eC_stderr());
273          break;
274       case logFile:
275       {
276          File f;
277          if((f = FileOpen(globalSystem.logFile, append)))
278          {
279             f.Puts(text);
280             delete f;
281          }
282          break;
283       }
284       case buffer:
285       case msgBox:
286          strcat(globalSystem.errorBuffer, text);
287          break;
288    }
289 }
290
291 public void DumpErrors(bool display)
292 {
293    if(globalSystem.errorBuffer && globalSystem.errorBuffer[0])
294    {
295       if(display)
296       {
297 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
298          if(globalSystem.errorLoggingMode == buffer)
299             printf(globalSystem.errorBuffer);
300          else
301          {
302             char title[1024];
303             sprintf(title, "%s - Error Log", guiApp.appName);
304             MessageBoxA(HWND_DESKTOP, globalSystem.errorBuffer, title, MB_OK|MB_ICONWARNING);
305          }
306 #else
307          printf("%s", globalSystem.errorBuffer);
308 #endif
309       }
310       globalSystem.errorBuffer[0] = '\0';
311    }
312 }
313
314 public void LogErrorCode(ErrorCode errorCode, const char * details)
315 {
316    if(errorCode.level <= globalSystem.errorLevel)
317    {
318       int cat = (errorCode.code & 0xF00) >> 8;
319       int code = errorCode.code & 0xFF;
320       if(details)
321          Logf("System Error [%d]: %s (%s).\n",
322             errorCode.level,
323             errorMessages[cat][code],
324             details);
325       else
326          Logf("System Error [%d]: %s.\n",
327             errorCode.level,
328             errorMessages[cat][code]);
329    }
330    globalSystem.lastErrorCode = errorCode;
331 }
332
333 public uint GetLastErrorCode()
334 {
335    return globalSystem.lastErrorCode;
336 }
337
338 public void ResetError()
339 {
340    globalSystem.lastErrorCode = 0;
341 }
342
343 public void SetErrorLevel(ErrorLevel level)
344 {
345    globalSystem.errorLevel = level;
346 }
347
348 public void SetLoggingMode(LoggingMode mode, void * where)
349 {
350    globalSystem.errorLoggingMode = mode;
351
352    if(mode == logFile)
353    {
354       File file;
355       strcpy(globalSystem.logFile, where);
356       file = FileOpen(globalSystem.logFile, write);
357       delete file;
358    }
359    else if(mode == buffer || mode == msgBox)
360    {
361       if(!globalSystem.errorBuffer)
362       {
363          globalSystem.errorBufferSize = DEFAULT_BUFFER_SIZE;
364          globalSystem.errorBuffer = new char[DEFAULT_BUFFER_SIZE];
365       }
366       globalSystem.errorBuffer[0] = 0;
367    }
368    else if(mode == debug)
369    {
370 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
371       uint16 * _wappName = UTF8toUTF16(guiApp.appName, null);
372       OutputDebugString(L"\n");
373       OutputDebugString(_wappName);
374       OutputDebugString(L" - Logging Errors...\n");
375       delete _wappName;
376 #endif
377    }
378    if(mode == 0)
379    {
380       DumpErrors(true);
381       if(globalSystem.errorBuffer)
382       {
383          delete globalSystem.errorBuffer;
384          globalSystem.errorBufferSize = 0;
385       }
386    }
387 }
388
389 static define errorLogMsg = $"\n\nWould you like to view the error log?";
390 /*
391 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
392 static DWORD REAL_ExceptionHandler(EXCEPTION_POINTERS *exception)
393 {
394    EXCEPTION_RECORD * record = exception->ExceptionRecord;
395    char exceptionString[1024] = "", title[1024];
396
397    switch(record->ExceptionCode)
398    {
399       case EXCEPTION_ACCESS_VIOLATION:
400          if(record->ExceptionInformation[0])
401             sprintf(exceptionString, "Access Violation Writing to 0x%p", (void *)record->ExceptionInformation[1]);
402          else
403             sprintf(exceptionString, "Access Violation Reading from 0x%p", (void *)record->ExceptionInformation[1]);
404          break;
405       case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
406          sprintf(exceptionString, "Array Bounds Exceeded");
407          break;
408       case EXCEPTION_BREAKPOINT:
409          sprintf(exceptionString, "Breakpoint Encountered");
410          break;
411       case EXCEPTION_DATATYPE_MISALIGNMENT:
412          sprintf(exceptionString, "Data Type Misalignment");
413          break;
414       case EXCEPTION_FLT_DENORMAL_OPERAND:
415          sprintf(exceptionString, "Floating-Point Denormal Operand");
416          break;
417       case EXCEPTION_FLT_DIVIDE_BY_ZERO:
418          sprintf(exceptionString, "Floating-Point Divide by Zero");
419          break;
420       case EXCEPTION_FLT_INEXACT_RESULT:
421          sprintf(exceptionString, "Floating-Point Inexact Result");
422          break;
423       case EXCEPTION_FLT_INVALID_OPERATION:
424          sprintf(exceptionString, "Floating-Point Invalid Operation");
425          break;
426       case EXCEPTION_FLT_OVERFLOW:
427          sprintf(exceptionString, "Floating-Point Overflow");
428          break;
429       case EXCEPTION_FLT_STACK_CHECK:
430          sprintf(exceptionString, "Floating-Point Stack Check");
431          break;
432       case EXCEPTION_FLT_UNDERFLOW:
433          sprintf(exceptionString, "Floating-Point Underflow");
434          break;
435       case EXCEPTION_ILLEGAL_INSTRUCTION:
436          sprintf(exceptionString, "Illegal Instruction");
437          break;
438       case EXCEPTION_IN_PAGE_ERROR:
439          sprintf(exceptionString, "In Page Error");
440          break;
441       case EXCEPTION_INT_DIVIDE_BY_ZERO:
442          sprintf(exceptionString, "Integer Divide by Zero");
443          break;
444       case EXCEPTION_INT_OVERFLOW:
445          sprintf(exceptionString, "Integer Overflow");
446          break;
447       case EXCEPTION_INVALID_DISPOSITION:
448          sprintf(exceptionString, "Invalid Disposition");
449          break;
450       case EXCEPTION_NONCONTINUABLE_EXCEPTION:
451          sprintf(exceptionString, "Non Continuable Exception");
452          break;
453       case EXCEPTION_PRIV_INSTRUCTION:
454          sprintf(exceptionString, "Unallowed Instruction");
455          break;
456       case EXCEPTION_SINGLE_STEP:
457          sprintf(exceptionString, "Single Step Exception");
458          break;
459       case EXCEPTION_STACK_OVERFLOW:
460          return EXCEPTION_CONTINUE_SEARCH;
461          //sprintf(exceptionString, "Stack Overflow");
462          //break;
463    }
464
465    sprintf(title, "%s - Fatal Error", guiApp.appName);
466
467    if(globalSystem.errorBuffer && globalSystem.errorBuffer[0])
468    {
469       strcat(exceptionString, errorLogMsg);
470       if(MessageBoxA(HWND_DESKTOP, exceptionString, title, MB_YESNO|MB_ICONERROR) == IDYES)
471          DumpErrors(true);
472    }
473    else
474       MessageBoxA(HWND_DESKTOP, exceptionString, title, MB_OK|MB_ICONERROR);
475
476    return EXCEPTION_EXECUTE_HANDLER;
477 }
478 #endif
479 */
480
481 private struct System
482 {
483    LoggingMode errorLoggingMode;
484    char * errorBuffer;
485    int errorBufferSize;
486    char logFile[MAX_LOCATION];
487    ErrorCode lastErrorCode;
488    ErrorLevel errorLevel;
489
490 #ifndef ECERE_BOOTSTRAP
491    Semaphore eventSemaphore;
492
493    //FileSystem fileSystems;
494
495    // File Monitor
496    OldList fileMonitors;
497    Mutex fileMonitorMutex;
498    Thread fileMonitorThread;
499    bool systemTerminate;
500 #endif
501 };
502
503 System globalSystem;