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