/** * MojoSetup; a portable, flexible installation application. * * Please see the file LICENSE.txt in the source's root directory. * * This file written by Ryan C. Gordon. */ #ifndef _INCL_UNIVERSAL_H_ #define _INCL_UNIVERSAL_H_ // Include this file from everywhere...it provides basic type sanity, etc. // Include the Holy Trinity... #include #include #include // and some others... #include #include // !!! FIXME: maybe use this in platform layer? // Windows system headers conflict with MojoSetup typedefs, so chop out // all the massive and unnecessary dependencies that windows.h pulls in... #if PLATFORM_WINDOWS #define WIN32_LEAN_AND_MEAN 1 #endif #if _MSC_VER #include // need this to get alloca() in MSVC. // !!! FIXME: temporary solution. #define snprintf _snprintf #define strcasecmp(x,y) _stricmp(x,y) #endif #ifdef __cplusplus extern "C" { #endif // !!! FIXME: bad. typedef char int8; typedef unsigned char uint8; typedef short int16; typedef unsigned short uint16; typedef int int32; typedef unsigned int uint32; typedef long long int64; typedef unsigned long long uint64; // These are likely to get stolen by some overzealous library header... #ifdef boolean #error Something is defining boolean. Resolve this before including universal.h. #endif #ifdef true #error Something is defining true. Resolve this before including universal.h. #endif #ifdef false #error Something is defining false. Resolve this before including universal.h. #endif typedef int boolean; #define true 1 #define false 0 // MSVC doesn't support the "inline" keyword for normal C sources, just C++. #if defined(_MSC_VER) && !defined(__cplusplus) && !defined(inline) #define inline __inline #endif // Compiler-enforced printf() safety helper. // This is appended to function declarations that use printf-style semantics, // and will make sure your passed the right params to "..." for the // format you specified, so gcc can catch programmer bugs at compile time. #ifdef __GNUC__ #define ISPRINTF(x,y) __attribute__((format (printf, x, y))) #else #define ISPRINTF(x,y) #endif // Compiler-enforced sentinel safety helper. // This is appended to function declarations that use sentinel-style semantics, // and will make sure your passed the right params to "..." where a NULL // is needed at the end of the list. #ifdef __GNUC__ #define ISSENTINEL __attribute__((sentinel)) #else #define ISSENTINEL #endif // Command line access outside of main(). extern int GArgc; extern const char **GArgv; // Build-specific details. extern const char *GBuildVer; // Static, non-stack memory for scratch work...not thread safe! extern uint8 scratchbuf_128k[128 * 1024]; #define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF #define UNICODE_BOGUS_CHAR_CODEPOINT '?' // !!! FIXME: document me! uint32 utf8codepoint(const char **str); // !!! FIXME: document me! int utf8len(const char *str); // !!! FIXME: document me! char **splitText(const char *text, int scrw, int *_count, int *_w); // Format a string, sort of (but not exactly!) like sprintf(). // The only formatters accepted are %0 through %9 (and %%), which do not // have to appear in order in the string, but match the varargs passed to the // function. Only strings are accepted for varargs. This function allocates // memory as necessary, so you need to free() the result, but don't need to // preallocate a buffer and be concerned about overflowing it. // This does not use scratchbuf_128k. char *format(const char *fmt, ...); // Convert an int to a string. This uses incremental pieces of // scratchbuf_128k for a buffer to store the results, and // will overwrite itself after some number of calls when the memory // is all used, but note that other things use scratchbuf_128k too, // so this is only good for printf() things: // fmtfunc("mission took %0 seconds, %1 points", numstr(secs), numstr(pts)); const char *numstr(int val); // Call this for fatal errors that require immediate app termination. // Does not clean up, or translate the error string. Try to avoid this. // These are for crucial lowlevel issues that preclude any meaningful // recovery (GUI didn't initialize, etc) // Doesn't return, but if it did, you can assume it returns zero, so you can // do: 'return panic("out of memory");' or whatnot. int panic(const char *err); // Call this for a fatal problem that attempts an orderly shutdown (system // is fully working, but config file is hosed, etc). // This makes an attempt to clean up any files already created by the // current installer (successfully run Setup.Install blocks in the config // file are not cleaned up). // If there's no GUI or Lua isn't initialized, this calls panic(). That's bad. // Doesn't return, but if it did, you can assume it returns zero, so you can // do: 'return fatal("missing config file");' or whatnot. // THIS DOES NOT USE PRINTF-STYLE FORMAT CODES. Please see the comments for // format() for details. int fatal(const char *fmt, ...); // The platform layer should set up signal/exception handlers before calling // MojoSetup_main(), that will call these functions. "crashed" for bug // signals (SIGSEGV, GPF, etc), and "terminated" for external forces that // destroy the process (SIGKILL, SIGINT, etc). These functions do not return. void MojoSetup_crashed(void); void MojoSetup_terminated(void); // Malloc replacements that blow up on allocation failure. // Please note that xmalloc() will zero the newly-allocated memory buffer, // like calloc() would, but xrealloc() makes no such promise! void *xmalloc(size_t bytes); void *xrealloc(void *ptr, size_t bytes); char *xstrdup(const char *str); // strncpy() that promises to null-terminate the string, even on overflow. char *xstrncpy(char *dst, const char *src, size_t len); #ifdef malloc #undef malloc #endif #define malloc(x) DO_NOT_CALL_MALLOC__USE_XMALLOC_INSTEAD #ifdef calloc #undef calloc #endif #define calloc(x,y) DO_NOT_CALL_CALLOC__USE_XMALLOC_INSTEAD #ifdef realloc #undef realloc #endif #define realloc(x,y) DO_NOT_CALL_REALLOC__USE_XREALLOC_INSTEAD #ifdef strdup #undef strdup #endif #define strdup(x) DO_NOT_CALL_STRDUP__USE_XSTRDUP_INSTEAD #ifdef strncpy #undef strncpy #endif #define strncpy(x,y,z) DO_NOT_CALL_STRNCPY__USE_XSTRNCPY_INSTEAD #if 0 // !!! FIXME: write me. #ifdef strcasecmp #undef strcasecmp #endif #define strcasecmp(x,y) DO_NOT_CALL_STRCASECMP__USE_UTF8STRICMP_INSTEAD #endif #if 0 // !!! FIXME: write me. #ifdef stricmp #undef stricmp #endif #define stricmp(x,y) DO_NOT_CALL_STRICMP__USE_UTF8STRICMP_INSTEAD #endif #if 0 // !!! FIXME: write me. #ifdef strcmpi #undef strcmpi #endif #define strcmpi(x,y) DO_NOT_CALL_STRCMPI__USE_UTF8STRICMP_INSTEAD #endif // Localization support. const char *translate(const char *str); #ifdef _ #undef _ #endif #define _(x) translate(x) // Call this with what you are profiling and the start time to log it: // uint32 start = MojoPlatform_ticks(); // ...do something... // profile("Something I did", start); uint32 profile(const char *what, uint32 start_time); // This tries to decode a graphic file in memory into an RGBA framebuffer, // first with platform-specific facilities, if any, and then any built-in // decoders, if that fails. // (data) points to the compressed data, (size) is the number of bytes // of compressed data. (*w) and (*h) will contain the images dimensions on // return. // Returns NULL on failure (unsupported, etc) and a pointer to the // uncompressed data on success. Caller must free() the returned pointer! uint8 *decodeImage(const uint8 *data, uint32 size, uint32 *w, uint32 *h); // See if a given string is in a valid product key format. // (fmt) points to a string that would be a Setup.ProductKey.format. // (key) is the key as it currently stands. It might be partially entered. // Returns true if the key is valid for the format, false otherwise. boolean isValidProductKey(const char *fmt, const char *key); // See if a given flag was on the command line // // cmdline("nosound") will return true if "-nosound", "--nosound", // etc was on the command line. The option must start with a '-' on the // command line to be noticed by this function. // // \param arg the command line flag to find // \return true if arg was on the command line, false otherwise. boolean cmdline(const char *arg); // Get robust command line options, with optional default for missing ones. // // If the command line was ./myapp --a=b -c=d ----e f // - cmdlinestr("a") will return "b" // - cmdlinestr("c") will return "d" // - cmdlinestr("e") will return "f" // - cmdlinestr("g") will return the default string. // // Like cmdline(), the option must start with a '-'. // // \param arg The command line option to find. // \param envr optional environment var to check if command line wasn't found. // \param deflt The return value if (arg) isn't on the command line. // \return The command line option, or (deflt) if the command line wasn't // found. This return value is READ ONLY. Do not free it, either. const char *cmdlinestr(const char *arg, const char *envr, const char *deflt); // Returns true if (str) matches (pattern), false otherwise. // This is NOT a regexp! It only understands '?' and '*', similar to how // wildcards worked in MS-DOS command lines. '?' matches one char, and // '*' matches until the end of string or the next char in the pattern // is seen. Case matters! boolean wildcardMatch(const char *str, const char *pattern); // Logging functions. typedef enum { MOJOSETUP_LOG_NOTHING, MOJOSETUP_LOG_ERRORS, MOJOSETUP_LOG_WARNINGS, MOJOSETUP_LOG_INFO, MOJOSETUP_LOG_DEBUG, MOJOSETUP_LOG_EVERYTHING } MojoSetupLogLevel; extern MojoSetupLogLevel MojoLog_logLevel; void MojoLog_initLogging(void); void MojoLog_deinitLogging(void); // Logging facilities. // THESE DO NOT USE PRINTF-STYLE FORMAT CODES. Please see the comments for // format() for details. void logWarning(const char *fmt, ...); void logError(const char *fmt, ...); void logInfo(const char *fmt, ...); void logDebug(const char *fmt, ...); // Checksums. typedef uint32 MojoCrc32; void MojoCrc32_init(MojoCrc32 *context); void MojoCrc32_append(MojoCrc32 *context, const uint8 *buf, uint32 len); void MojoCrc32_finish(MojoCrc32 *context, uint32 *digest); typedef struct MojoMd5 { uint32 count[2]; uint32 abcd[4]; uint8 buf[64]; } MojoMd5; void MojoMd5_init(MojoMd5 *pms); void MojoMd5_append(MojoMd5 *pms, const uint8 *data, int nbytes); void MojoMd5_finish(MojoMd5 *pms, uint8 digest[16]); typedef struct { uint32 state[5]; uint32 count[2]; uint8 buffer[64]; } MojoSha1; void MojoSha1_init(MojoSha1 *context); void MojoSha1_append(MojoSha1 *context, const uint8 *data, uint32 len); void MojoSha1_finish(MojoSha1 *context, uint8 digest[20]); typedef struct MojoChecksumContext { MojoCrc32 crc32; MojoMd5 md5; MojoSha1 sha1; } MojoChecksumContext; typedef struct MojoChecksums { uint32 crc32; uint8 md5[16]; uint8 sha1[20]; } MojoChecksums; void MojoChecksum_init(MojoChecksumContext *ctx); void MojoChecksum_append(MojoChecksumContext *c, const uint8 *data, uint32 ln); void MojoChecksum_finish(MojoChecksumContext *c, MojoChecksums *sums); // A pointer to this struct is passed to plugins, so they can access // functionality in the base application. (Add to this as you need to.) typedef struct MojoSetupEntryPoints { void *(*xmalloc)(size_t bytes); void *(*xrealloc)(void *ptr, size_t bytes); char *(*xstrdup)(const char *str); char *(*xstrncpy)(char *dst, const char *src, size_t len); const char *(*translate)(const char *str); void (*logWarning)(const char *fmt, ...); void (*logError)(const char *fmt, ...); void (*logInfo)(const char *fmt, ...); void (*logDebug)(const char *fmt, ...); char *(*format)(const char *fmt, ...); const char *(*numstr)(int val); uint32 (*ticks)(void); uint32 (*utf8codepoint)(const char **_str); int (*utf8len)(const char *str); char **(*splitText)(const char *text, int scrw, int *_count, int *_w); boolean (*isValidProductKey)(const char *f, const char *k); } MojoSetupEntryPoints; extern MojoSetupEntryPoints GEntryPoints; #ifndef DOXYGEN_SHOULD_IGNORE_THIS #if ((defined _MSC_VER) || (PLATFORM_BEOS)) #define __EXPORT__ __declspec(dllexport) #elif (defined SUNPRO_C) #define __EXPORT__ __global #elif (__GNUC__ >= 3) #define __EXPORT__ __attribute__((visibility("default"))) #else #define __EXPORT__ #endif #endif // DOXYGEN_SHOULD_IGNORE_THIS #define DEFINE_TO_STR2(x) #x #define DEFINE_TO_STR(x) DEFINE_TO_STR2(x) #ifndef DOXYGEN_SHOULD_IGNORE_THIS #define STUBBED2(prelog, x) \ do { \ static boolean seen_this = false; \ if (!seen_this) \ { \ seen_this = true; \ prelog logDebug("STUBBED: %0 at %1 (%2:%3)\n", x, __FUNCTION__, \ __FILE__, DEFINE_TO_STR(__LINE__)); \ } \ } while (false) #define STUBBED(x) STUBBED2(,x) #endif #define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) ) #ifdef __cplusplus } #endif #endif // end of universal.h ...