X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=util.c;h=f6b9808657f272125381bc06cb6e9ab39ad619db;hp=9b32e48394806022e2ab2f0e9c7446aeb211cae1;hb=ef51b303873db5e97b9ddcf12cadc0c5df6bb855;hpb=fa14ca93d2b60f722d55c24214fde7ac84581ad0 diff --git a/util.c b/util.c index 9b32e48..f6b9808 100644 --- a/util.c +++ b/util.c @@ -21,10 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include -#include - +#define GMQCC_PLATFORM_HEADER #include "gmqcc.h" +#include "platform.h" /* * Initially this was handled with a table in the gmqcc.h header, but @@ -224,167 +223,103 @@ size_t util_optimizationtostr(const char *in, char *out, size_t outsz) { return util_strtransform(in, out, outsz, "_ ", 'a'-'A'); } -/* - * Portable implementation of vasprintf/asprintf. Assumes vsnprintf - * exists, otherwise compiler error. - * - * TODO: fix for MSVC .... - */ -int util_vasprintf(char **dat, const char *fmt, va_list args) { - int ret; - int len; - char *tmp = NULL; - - /* - * For visual studio _vsnprintf doesn't tell you the length of a - * formatted string if it overflows. However there is a MSVC - * intrinsic (which is documented wrong) called _vcsprintf which - * will return the required amount to allocate. - */ - #ifdef _MSC_VER - if ((len = _vscprintf(fmt, args)) < 0) { - *dat = NULL; - return -1; - } - - tmp = (char*)mem_a(len + 1); - if ((ret = _vsnprintf_s(tmp, len+1, len+1, fmt, args)) != len) { - mem_d(tmp); - *dat = NULL; - return -1; - } - *dat = tmp; - return len; - #else - /* - * For everything else we have a decent conforming vsnprintf that - * returns the number of bytes needed. We give it a try though on - * a short buffer, since efficiently speaking, it could be nice to - * above a second vsnprintf call. - */ - char buf[128]; - va_list cpy; - va_copy(cpy, args); - len = vsnprintf(buf, sizeof(buf), fmt, cpy); - va_end (cpy); - - if (len < (int)sizeof(buf)) { - *dat = util_strdup(buf); - return len; - } +int util_snprintf(char *str, size_t size, const char *fmt, ...) { + va_list arg; + int ret; - /* not large enough ... */ - tmp = (char*)mem_a(len + 1); - if ((ret = vsnprintf(tmp, len + 1, fmt, args)) != len) { - mem_d(tmp); - *dat = NULL; - return -1; - } + va_start(arg, fmt); + ret = platform_vsnprintf(str, size, fmt, arg); + va_end(arg); - *dat = tmp; - return len; - #endif + return ret; } + int util_asprintf(char **ret, const char *fmt, ...) { va_list args; int read; + va_start(args, fmt); - read = util_vasprintf(ret, fmt, args); + read = platform_vasprintf(ret, fmt, args); va_end (args); return read; } -/* - * These are various re-implementations (wrapping the real ones) of - * string functions that MSVC considers unsafe. We wrap these up and - * use the safe variations on MSVC. - */ -#ifdef _MSC_VER - static char **util_strerror_allocated() { - static char **data = NULL; - return data; - } - - static void util_strerror_cleanup(void) { - size_t i; - char **data = util_strerror_allocated(); - for (i = 0; i < vec_size(data); i++) - mem_d(data[i]); - vec_free(data); - } - - const char *util_strerror(int num) { - char *allocated = NULL; - static bool install = false; - static size_t tries = 0; - char **vector = util_strerror_allocated(); - - /* try installing cleanup handler */ - while (!install) { - if (tries == 32) - return "(unknown)"; +int util_sscanf(const char *str, const char *format, ...) { + va_list args; + int read; - install = !atexit(&util_strerror_cleanup); - tries ++; - } + va_start(args, format); + read = platform_vsscanf(str, format, args); + va_end(args); - allocated = (char*)mem_a(4096); /* A page must be enough */ - strerror_s(allocated, 4096, num); + return read; +} - vec_push(vector, allocated); - return (const char *)allocated; - } +char *util_strncpy(char *dest, const char *src, size_t n) { + return platform_strncpy(dest, src, n); +} +char *util_strncat(char *dest, const char *src, size_t n) { + return platform_strncat(dest, src, n); +} +char *util_strcat(char *dest, const char *src) { + return platform_strcat(dest, src); +} +const char *util_strerror(int err) { + return platform_strerror(err); +} - int util_snprintf(char *src, size_t bytes, const char *format, ...) { - int rt; - va_list va; - va_start(va, format); +const struct tm *util_localtime(const time_t *timer) { + return platform_localtime(timer); +} +const char *util_ctime(const time_t *timer) { + return platform_ctime(timer); +} - rt = vsprintf_s(src, bytes, format, va); - va_end (va); +bool util_isatty(fs_file_t *file) { + if (file == (fs_file_t*)stdout) return !!platform_isatty(STDOUT_FILENO); + if (file == (fs_file_t*)stderr) return !!platform_isatty(STDERR_FILENO); + return false; +} - return rt; - } +const char *util_tmpnam(char *str) { + return platform_tmpnam(str); +} - char *util_strcat(char *dest, const char *src) { - strcat_s(dest, strlen(src), src); - return dest; - } +/* + * A small noncryptographic PRNG based on: + * http://burtleburtle.net/bob/rand/smallprng.html + */ +static uint32_t util_rand_state[4] = { + 0xF1EA5EED, 0x00000000, + 0x00000000, 0x00000000 +}; - char *util_strncpy(char *dest, const char *src, size_t num) { - strncpy_s(dest, num, src, num); - return dest; - } -#else - const char *util_strerror(int num) { - return strerror(num); - } +#define util_rand_rot(X, Y) (((X)<<(Y))|((X)>>(32-(Y)))) - int util_snprintf(char *src, size_t bytes, const char *format, ...) { - int rt; - va_list va; - va_start(va, format); - rt = vsnprintf(src, bytes, format, va); - va_end (va); +uint32_t util_rand() { + uint32_t last; - return rt; - } + last = util_rand_state[0] - util_rand_rot(util_rand_state[1], 27); + util_rand_state[0] = util_rand_state[1] ^ util_rand_rot(util_rand_state[2], 17); + util_rand_state[1] = util_rand_state[2] + util_rand_state[3]; + util_rand_state[2] = util_rand_state[3] + last; + util_rand_state[3] = util_rand_state[0] + last; - char *util_strcat(char *dest, const char *src) { - return strcat(dest, src); - } + return util_rand_state[3]; +} - char *util_strncpy(char *dest, const char *src, size_t num) { - return strncpy(dest, src, num); - } +#undef util_rand_rot -#endif /*! _MSC_VER */ +void util_seed(uint32_t value) { + size_t i; + util_rand_state[0] = 0xF1EA5EED; + util_rand_state[1] = value; + util_rand_state[2] = value; + util_rand_state[3] = value; -void util_seed(uint32_t value) { - srand((int)value); -} -uint32_t util_rand() { - return rand(); + for (i = 0; i < 20; ++i) + (void)util_rand(); } +