1 /*
2  * This file was written by Bill Cox, originally in 1991, and maintained since.  It is hereby
3  * placed into the public domain.
4  */
5 
6 /*==================================================================================================
7    Module : Virtual Operating System
8    Purpose: Hide system specific operations from other modules.  This should help in portability.
9 ==================================================================================================*/
10 
11 #ifndef DD_UTIL_H
12 #define DD_UTIL_H
13 
14 #if __cplusplus
15 extern "C" {
16 #endif
17 
18 #include <stdarg.h> /* For utVsprintf declaration */
19 #include <setjmp.h> /* For utSetjmp */
20 #include <stdio.h> /* Everyone uses it */
21 #include <string.h> /* Has memset, used in generated macros */
22 
23 /*--------------------------------------------------------------------------------------------------
24   Datadraw defined Data types
25 --------------------------------------------------------------------------------------------------*/
26 
27 #ifndef UTTYPES_H
28 #include "uttypes.h"
29 #endif
30 
31 /*--------------------------------------------------------------------------------------------------
32   Basic symbol table support.  Note that user applications don't need to worry about which
33   header gets included here, since they should only be reading from symbols.
34 --------------------------------------------------------------------------------------------------*/
35 #if defined(UT_USE_UTDATABASEUP_H)
36 #include "utdatabaseup.h"
37 #elif defined(UT_USE_UTDATABASEP_H)
38 #include "utdatabasep.h"
39 #elif defined(UT_USE_UTDATABASEU_H)
40 #include "utdatabasep.h"
41 #else
42 #include "utdatabase.h"
43 #endif
44 
45 utSym utSymCreate(char *name);
46 utSym utSymCreateFormatted(char *format, ...);
47 utSym utUniqueSymCreate(char *name, char *suffix);
48 utSym utSymGetLowerSym(utSym sym);
49 
50 /*--------------------------------------------------------------------------------------------------
51   Basic memory management support.
52 --------------------------------------------------------------------------------------------------*/
53 #ifndef UTMEM_H
54 #include "utmem.h"
55 #endif
56 
57 #ifdef DMALLOC
58 #include "dmalloc.h"
59 #endif
60 
61 /*--------------------------------------------------------------------------------------------------
62   The max size of a string which the utFprintf, utExit, etc functions can print.
63 --------------------------------------------------------------------------------------------------*/
64 #define UTSTRLEN 4096
65 
66 extern uint32 utDebugVal;
67 extern uint32 utVerboseVal;
68 
69 /*--------------------------------------------------------------------------------------------------
70   Initialization, cleaning up.
71 --------------------------------------------------------------------------------------------------*/
72 void utStop(bool reportTimeAndMemory);
73 void utStart(void);
74 extern bool _utInitialized;
75 #define utInitialized() _utInitialized
76 
77 
78 /*--------------------------------------------------------------------------------------------------
79   Functions you may want to call after initialization.
80 --------------------------------------------------------------------------------------------------*/
81 void utSetConfigDirectory(char *dirName);
82 void utSetExeFullPath(char *fullName);
83 void utSetVersion(char *version);
84 char *utGetVersion(void);
85 char *utGetExeDirectory(void);
86 char *utGetConfigDirectory(void);
87 char *utGetExeFullPath(void);
88 
89 /*--------------------------------------------------------------------------------------------------
90   Error Callback function to be provided by the user.
91 --------------------------------------------------------------------------------------------------*/
92 typedef void(*utErrorProc)(char *message);
93 typedef bool(*utMessageYesNoProc)(char *message);
94 typedef void(*utExitProc)(void);
95 
96 /*--------------------------------------------------------------------------------------------------
97   Basic interface to file system.
98 --------------------------------------------------------------------------------------------------*/
99 char *utGetcwd(void);
100 bool utChdir(char *dirName);
101 bool utFileExists(char *fileName);
102 bool utDirectoryExists(char *dirName);
103 bool utAccess(char *name, char *mode);
104 uint64 utFindFileSize(char *fileName);
105 char *utExecPath(char *name);
106 char *utFullPath(char *relativePath);
107 char *utFindInPath(char *name, char *path);
108 void utTruncateFile(char *fileName, uint64 length);
109 bool utDeleteFile(char *fileName);
110 
111 /*--------------------------------------------------------------------------------------------------
112   Portable interface to launch an application.
113 --------------------------------------------------------------------------------------------------*/
114 bool utLaunchApp(char* cmdLine, char *wkgDir);
115 
116 /*--------------------------------------------------------------------------------------------------
117   Memory allocation.
118   There are things called malloc, calloc and free, but they deal in the
119   local heap, thus are to be avoided.
120 --------------------------------------------------------------------------------------------------*/
121 extern uint64 utUsedMem;
122 #define utMalloc(sStruct, size) utMallocTrace(sStruct, size, __FILE__, __LINE__)
123 #define utCalloc(sStruct, size) utCallocTrace(sStruct, size, \
124       __FILE__, __LINE__)
125 #define utRealloc(mem, numBlocks, size) \
126       utReallocTrace((void *)mem, numBlocks, size, __FILE__, __LINE__)
127 #define utResizeArray(array, num) \
128         ((array) = utRealloc((void *)(array), (num), sizeof(*(array))))
129 #define utNew(type) (type *)utCalloc(1, sizeof(type))
130 #define utNewA(type, num) (type *)utCalloc((num), sizeof(type))
131 #define utFree(p) utFreeTrace(p, __FILE__, __LINE__)
132 #define utAllocString(string) strcpy(utNewA(char, strlen(string) + 1), string)
133 
134 void * utReallocTrace(void *memPtr, size_t numBlocks, size_t size, char *fileName,
135     uint32 line);
136 void *utMallocTrace(size_t sStruct, size_t size, char *fileName, uint32 line);
137 void *utCallocTrace(size_t sStruct, size_t size, char *fileName, uint32 line);
138 void utFreeTrace(void *memPtr, char *fileName, uint32 line);
139 
140 /* maxmimum memory usage */
141 extern uint32 utmByte;
142 
143 /*--------------------------------------------------------------------------------------------------
144   Random number support.
145 --------------------------------------------------------------------------------------------------*/
146 void utInitSeed(uint32 seed);
147 uint32 utRand(void);
148 #define utRandN(n) (utRand() % (n))
149 #define utRandBool() ((bool) (utRand() & 1))
150 uint8 *utRealRandom(uint32 length);
151 
152 /*--------------------------------------------------------------------------------------------------
153   String and temporary buffer manipulation.
154 --------------------------------------------------------------------------------------------------*/
155 /* These use a queue of buffers */
156 void *utMakeBuffer_(uint32 length);
157 #define utNewBufA(type, num) (type *)utMakeBuffer_((num)*sizeof(type))
158 #define utNewBuf(type) (type *)utMakeBuffer_(sizeof(type))
159 #define utMakeString(length) (char *)utMakeBuffer_(length)
160 char *utCopyString(char *string);
161 char *utCatStrings(char *string1, char *string2);
162 char *utStringToUpperCase(char *string);
163 char *utStringToLowerCase(char *string);
164 char *utSprintf(char *format, ...);
165 char *utReplaceSuffix(char *originalName, char *newSuffix);
166 char *utSuffix(char *name);
167 char *utBaseName(char *name);
168 char *utDirName(char *name);
169 char *utExpandEnvVariables(char *string);
170 char *utVsprintf(char *format, va_list ap);
171 void utSetEnvironmentVariable(char *name, char *value);
172 char *utGetEnvironmentVariable(char *name);
173 char *utFindHexString(uint8 *values, uint32 size);
174 bool utReadHex(uint8 *dest, char *value, uint32 size);
175 char *utMemoryUnits(uint64 memory);
176 bool utParseInteger(int64 *dest, char *string);
177 char *utConvertDirSepChars(char *path);
178 
179 /*--------------------------------------------------------------------------------------------------
180   Message loging, error reporting.
181 --------------------------------------------------------------------------------------------------*/
182 typedef enum {
183     UT_MESSAGE_INFO,
184     UT_MESSAGE_WARNING,
185     UT_MESSAGE_ERROR,
186     UT_MESSAGE_EXIT,
187     UT_MESSAGE_DETAILS,
188     UT_MESSAGE_INTERNAL,
189     UT_MESSAGE_REPORT,
190 } utMessageType;
191 void utEnableMessageHeaders(bool value);
192 void utLogMessageType(utMessageType msgType, char *format, ...);
193 void utLogMessage(char *format, ...);
194 void utLogString(char *format, ...);
195 void utLogDebug(char *format, ...);
196 char *utGetCompileTime(void);
197 char *utCompileTime(void);
198 char *utGetDateAndTime(void);
199 bool utDebug(char *format,... );
200 void utLogError(char *format, ...);
201 void utLogTimeStamp(char *message, ...);
202 uint32 utStartTimer(char *message, ...);
203 void utStopTimer(uint32 timerID, char *message, ...);
204 void utStatus(char *format, ...);
205 void utExit_ (char *format, ...);
206 typedef void(*utExitProcType)(char *format, ...);
207 utExitProcType utSetFileAndLineAndReturnExitFunc(char *fileName, uint32 lineNum);
208 #define utExit utSetFileAndLineAndReturnExitFunc(__FILE__, __LINE__)
209 void utWarning(char *format, ...);
210 void utNote(char *format, ...);
211 void utError(char *format, ...);
212 void utCriticalError(char *format, ...);
213 void utReport(char *format, ...);
214 /* Log a message to the log file and exit if false is passed. */
215 void utAssert_(char *fileName, uint32 line, char *text);
216 #define utAssert(assertion) ((void)(utLikely(assertion) || (utAssert_(__FILE__, __LINE__, #assertion), 0)))
217 void utSetErrorCallback(utErrorProc errorProc);
218 void utSetWarningCallback(utErrorProc warningProc);
219 void utSetStatusCallback(utErrorProc statusProc);
220 void utSetLogMessageCallback(utErrorProc logMessageProc);
221 utErrorProc utGetErrorCallback(void);
222 utErrorProc utGetWarningCallback(void);
223 utErrorProc utGetStatusCallback(void);
224 utErrorProc utGetLogMessageCallback(void);
225 void utInitLogFile(char *fileName);
226 void utSetLogFile(char *fileName);
227 FILE *utGetLogFile(void);
228 char *utGetLogFileName(void);
229 void utInitReportFile(char *fileName);
230 void utSetReportFile(char *fileName);
231 FILE *utGetReportFile(void);
232 char *utGetReportFileName(void);
233 void utInitDebugFile(char *fileName);
234 void utSetDebugFile(char *fileName);
235 FILE *utGetDebugFile(void);
236 char *utGetDebugFileName(void);
237 #define utIfDebug(minVal) if(utUnlikely(utDebugVal >= minVal))
238 #define utIfVerbose(minVal) if(utUnlikely(utVerboseVal >= minVal))
239 
240 #define UT_MAX_SETJMP_DEPTH 5
241 #if defined(_WINDOWS) && !defined(_WIN32)
242 #if !defined(CATCHBUF)
243 typedef int CATCHBUF[9];
244 #endif
245 extern CATCHBUF utCatchBuf[UT_MAX_SETJMP_DEPTH];
246 #else
247 extern jmp_buf utJmpBuf[UT_MAX_SETJMP_DEPTH];
248 #endif
249 
250 /*--------------------------------------------------------------------------------------------------
251   Macros for computing simple hashed signatures.  Hash signatures are uint32s.
252 --------------------------------------------------------------------------------------------------*/
253 #define utHashValues(hash1, hash2) (((uint32)(hash1) ^ (uint32)(hash2))*1103515245 + 12345)
254 uint32 utHashData(void *data, uint32 length);
255 uint32 utHashString(char *string);
256 uint32 utHashFloat(float value);
257 uint32 utHashDouble(double value);
258 
259 /*--------------------------------------------------------------------------------------------------
260   Setjmp/longjmp stack.
261 --------------------------------------------------------------------------------------------------*/
262 extern int16 utSetjmpDepth;
263 extern uint32 utSetjmpLine[UT_MAX_SETJMP_DEPTH];
264 extern char *utSetjmpFile[UT_MAX_SETJMP_DEPTH];
265 #define utUnsetjmp() (utSetjmpDepth--,\
266       !strcmp(utSetjmpFile[utSetjmpDepth],__FILE__) ||\
267       (utExit("Mismatched utUnsetjmp in file %s, line %u", __FILE__, __LINE__), 1))
268 #define utSetjmp() (++utSetjmpDepth,\
269       utSetjmpFile[utSetjmpDepth - 1] = __FILE__,\
270       utSetjmpLine[utSetjmpDepth - 1] = __LINE__,\
271       setjmp(utJmpBuf[utSetjmpDepth - 1]))
272 void utLongjmp(void);
273 
274 /*--------------------------------------------------------------------------------------------------
275   Functions supporting database persistence.
276 --------------------------------------------------------------------------------------------------*/
277 
278 #ifndef UTPERSIST_H
279 #include "utpersist.h"
280 #endif
281 
282 /* These are used by DataDraw to manage the database, and can generally be ignored */
283 uint8 utRegisterModule(char *prefix, bool persistent, uint32 hashValue, uint16 numClasses, uint16 numFields,
284     uint16 numEnums, uint16 globalSize, void *globalData, void (*start)(void), void (*stop)(void));
285 void utUnregisterModule(uint8 moduleID);
286 void utRegisterClass(char *name, uint16 numFields, void *numUsedPtr, void *numAllocatedPtr,
287     void *firstFreePtr, uint16 nextFreeFieldIndex, uint8 referenceSize,
288     uint64 (*constructor)(void), void (*destructor)(uint64 objectIndex));
289 void utRegisterBaseClass(char *baseModulePrefix, uint16 baseClassIndex);
290 void utRegisterField(char *name, void *arrayPtr, uint32 size, utFieldType type,
291     char *destName);
292 void utSetFieldHidden(void);
293 void utRegisterArray(uint32 *numUsedPtr, uint32 *numAllocatedPtr,
294     void *(*getValues)(uint64 objectNumber, uint32 *numValues),
295     void *(*allocValues)(uint64 objectNumber, uint32 numValues),
296     void (*compactArray)(void));
297 void utRegisterFixedArray(uint32 length, void *(*getValues)(uint64 objectNumber, uint32 *numValues));
298 void utRegisterEnum(char *name, uint16 numEntries);
299 void utRegisterEntry(char *name, uint32 value);
300 void utRegisterUnion(char *switchFieldName, uint16 numCases);
301 void utRegisterUnionCase(uint32 value, utFieldType type, uint32 size);
302 void utRecordField(uint8 moduleID, uint16 fieldIndex, uint64 objectNumber, bool undo);
303 void utRecordArray(uint8 moduleID, uint16 fieldIndex, uint32 dataIndex, uint32 length, bool undo);
304 void utRecordGlobal(uint8 moduleID, uint8 numBytes, void *location, bool undo);
305 void utRecordResize(uint8 moduleID, uint16 fieldIndex, uint64 length, bool undo);
306 void utAllocPersistenceObjects(void);
307 void utFreePersistenceObjects(void);
308 void utInitSymTable(void);
309 void utDatabaseManagerStart(void);
310 void utDatabaseManagerStop(void);
311 void utDumpRecentChanges(void);
312 void utDumpCommand(uint8 *command);
313 
314 /* These are the useful functions */
315 bool utStartPersistence(char *directory, bool useTextDatabaseFormat, bool keepBackup);
316 void utStopPersistence(void);
317 uint32 utUndo(uint32 numChanges);
318 uint32 utRedo(uint32 numChanges);
319 void utStartUndoRedo(void);
320 void utStopUndoRedo(void);
321 void utTransactionComplete(bool flushToDisk);
322 void utLoadBinaryDatabase(FILE *file);
323 void utSaveBinaryDatabase(FILE *file);
324 void utLoadTextDatabase(FILE *file);
325 void utSaveTextDatabase(FILE *file);
326 void utManager(void);
327 void utDatabaseShowObject(char *modulePrefix, char *className, uint64 objectNumber);
328 void utResetDatabase(void);
329 void utCompactDatabase(void);
330 
331 /* Some dynamic array stuff */
332 #ifdef DD_DEBUG
333 /* this double-evaluates and might cause side-effects */
334 #define utDynarrayGetiValueType(Dynarray, type, x) (utAssert((uint32)(x) < utDynarrayGetSize( \
335     Dynarray)), ((type *)(utDynarrayGetValues(Dynarray)))[x])
336 #define utDynarraySetiValueType(Dynarray, type, x, Value) (utAssert((uint32)(x) < \
337     utDynarrayGetSize(Dynarray)), ((type *)(utDynarrayGetValues(Dynarray)))[x] = (Value))
338 #else
339 #define utDynarrayGetiValueType(Dynarray, type, x) (((type *)(utDynarrayGetValues(Dynarray)))[x])
340 #define utDynarraySetiValueType(Dynarray, type, x, Value) \
341     (((type *)utDynarrayGetValues(Dynarray))[x] = (Value))
342 #endif
343 utDynarray utDynarrayCreate_(uint16 valueSize);
344 #define utDynarrayCreate(type) utDynarrayCreate_(sizeof(type))
345 void utDynarrayResize(utDynarray dynarray, uint32 newSize);
346 #define utDynarrayAppendValue(dynarray, type, value) \
347     (utDynarrayGetUsedValue(dynarray) == utDynarrayGetSize(dynarray) && \
348     (utDynarrayResize((dynarray), 1 + utDynarrayGetSize(dynarray) + \
349     (utDynarrayGetSize(dynarray) >> 1)), true),\
350     utDynarraySetiValueType(dynarray, type, utDynarrayGetUsedValue(dynarray), (value)),\
351     utDynarraySetUsedValue(dynarray, utDynarrayGetUsedValue(dynarray) + 1))
352 #define utForeachDynarrayValue(dynarray, type, value) \
353 {\
354     uint32 _xValue;\
355     for(_xValue = 0; _xValue < utDynarrayGetUsedValue(dynarray); _xValue++) {\
356         (value) = utDynarrayGetiValueType((dynarray), type, _xValue);
357 #define utEndDynarrayValue }}
358 #define utDynarrayCopy(destDynarray, sourceDynarray, type) { \
359     uint32 _xValue; \
360     if (utDynarrayGetSize(destDynarray) < utDynarrayGetSize(sourceDynarray)) { \
361         utDynarrayResize(destDynarray, utDynarrayGetSize(sourceDynarray)); \
362     } \
363     utDynarraySetUsedValue(destDynarray, utDynarrayGetUsedValue(sourceDynarray)); \
364     for(_xValue = 0; _xValue < utDynarrayGetUsedValue(sourceDynarray); _xValue++) { \
365         utDynarraySetiValueType((destDynarray), type, _xValue, \
366             utDynarrayGetiValueType((sourceDynarray), type, _xValue)); \
367     } \
368 }
369 
370 #if __cplusplus
371 }
372 #endif
373 
374 #endif
375 
376