cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_string.c (42943B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      4
      5  This software is provided 'as-is', without any express or implied
      6  warranty.  In no event will the authors be held liable for any damages
      7  arising from the use of this software.
      8
      9  Permission is granted to anyone to use this software for any purpose,
     10  including commercial applications, and to alter it and redistribute it
     11  freely, subject to the following restrictions:
     12
     13  1. The origin of this software must not be misrepresented; you must not
     14     claim that you wrote the original software. If you use this software
     15     in a product, an acknowledgment in the product documentation would be
     16     appreciated but is not required.
     17  2. Altered source versions must be plainly marked as such, and must not be
     18     misrepresented as being the original software.
     19  3. This notice may not be removed or altered from any source distribution.
     20*/
     21#include "../SDL_internal.h"
     22
     23/* This file contains portable string manipulation functions for SDL */
     24
     25#include "SDL_stdinc.h"
     26
     27
     28#define SDL_isupperhex(X)   (((X) >= 'A') && ((X) <= 'F'))
     29#define SDL_islowerhex(X)   (((X) >= 'a') && ((X) <= 'f'))
     30
     31#define UTF8_IsLeadByte(c) ((c) >= 0xC0 && (c) <= 0xF4)
     32#define UTF8_IsTrailingByte(c) ((c) >= 0x80 && (c) <= 0xBF)
     33
     34static int UTF8_TrailingBytes(unsigned char c)
     35{
     36    if (c >= 0xC0 && c <= 0xDF)
     37        return 1;
     38    else if (c >= 0xE0 && c <= 0xEF)
     39        return 2;
     40    else if (c >= 0xF0 && c <= 0xF4)
     41        return 3;
     42    else
     43        return 0;
     44}
     45
     46#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOL)
     47static size_t
     48SDL_ScanLong(const char *text, int radix, long *valuep)
     49{
     50    const char *textstart = text;
     51    long value = 0;
     52    SDL_bool negative = SDL_FALSE;
     53
     54    if (*text == '-') {
     55        negative = SDL_TRUE;
     56        ++text;
     57    }
     58    if (radix == 16 && SDL_strncmp(text, "0x", 2) == 0) {
     59        text += 2;
     60    }
     61    for (;;) {
     62        int v;
     63        if (SDL_isdigit((unsigned char) *text)) {
     64            v = *text - '0';
     65        } else if (radix == 16 && SDL_isupperhex(*text)) {
     66            v = 10 + (*text - 'A');
     67        } else if (radix == 16 && SDL_islowerhex(*text)) {
     68            v = 10 + (*text - 'a');
     69        } else {
     70            break;
     71        }
     72        value *= radix;
     73        value += v;
     74        ++text;
     75    }
     76    if (valuep) {
     77        if (negative && value) {
     78            *valuep = -value;
     79        } else {
     80            *valuep = value;
     81        }
     82    }
     83    return (text - textstart);
     84}
     85#endif
     86
     87#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOUL) || !defined(HAVE_STRTOD)
     88static size_t
     89SDL_ScanUnsignedLong(const char *text, int radix, unsigned long *valuep)
     90{
     91    const char *textstart = text;
     92    unsigned long value = 0;
     93
     94    if (radix == 16 && SDL_strncmp(text, "0x", 2) == 0) {
     95        text += 2;
     96    }
     97    for (;;) {
     98        int v;
     99        if (SDL_isdigit((unsigned char) *text)) {
    100            v = *text - '0';
    101        } else if (radix == 16 && SDL_isupperhex(*text)) {
    102            v = 10 + (*text - 'A');
    103        } else if (radix == 16 && SDL_islowerhex(*text)) {
    104            v = 10 + (*text - 'a');
    105        } else {
    106            break;
    107        }
    108        value *= radix;
    109        value += v;
    110        ++text;
    111    }
    112    if (valuep) {
    113        *valuep = value;
    114    }
    115    return (text - textstart);
    116}
    117#endif
    118
    119#ifndef HAVE_VSSCANF
    120static size_t
    121SDL_ScanUintPtrT(const char *text, int radix, uintptr_t * valuep)
    122{
    123    const char *textstart = text;
    124    uintptr_t value = 0;
    125
    126    if (radix == 16 && SDL_strncmp(text, "0x", 2) == 0) {
    127        text += 2;
    128    }
    129    for (;;) {
    130        int v;
    131        if (SDL_isdigit((unsigned char) *text)) {
    132            v = *text - '0';
    133        } else if (radix == 16 && SDL_isupperhex(*text)) {
    134            v = 10 + (*text - 'A');
    135        } else if (radix == 16 && SDL_islowerhex(*text)) {
    136            v = 10 + (*text - 'a');
    137        } else {
    138            break;
    139        }
    140        value *= radix;
    141        value += v;
    142        ++text;
    143    }
    144    if (valuep) {
    145        *valuep = value;
    146    }
    147    return (text - textstart);
    148}
    149#endif
    150
    151#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOLL)
    152static size_t
    153SDL_ScanLongLong(const char *text, int radix, Sint64 * valuep)
    154{
    155    const char *textstart = text;
    156    Sint64 value = 0;
    157    SDL_bool negative = SDL_FALSE;
    158
    159    if (*text == '-') {
    160        negative = SDL_TRUE;
    161        ++text;
    162    }
    163    if (radix == 16 && SDL_strncmp(text, "0x", 2) == 0) {
    164        text += 2;
    165    }
    166    for (;;) {
    167        int v;
    168        if (SDL_isdigit((unsigned char) *text)) {
    169            v = *text - '0';
    170        } else if (radix == 16 && SDL_isupperhex(*text)) {
    171            v = 10 + (*text - 'A');
    172        } else if (radix == 16 && SDL_islowerhex(*text)) {
    173            v = 10 + (*text - 'a');
    174        } else {
    175            break;
    176        }
    177        value *= radix;
    178        value += v;
    179        ++text;
    180    }
    181    if (valuep) {
    182        if (negative && value) {
    183            *valuep = -value;
    184        } else {
    185            *valuep = value;
    186        }
    187    }
    188    return (text - textstart);
    189}
    190#endif
    191
    192#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOULL)
    193static size_t
    194SDL_ScanUnsignedLongLong(const char *text, int radix, Uint64 * valuep)
    195{
    196    const char *textstart = text;
    197    Uint64 value = 0;
    198
    199    if (radix == 16 && SDL_strncmp(text, "0x", 2) == 0) {
    200        text += 2;
    201    }
    202    for (;;) {
    203        int v;
    204        if (SDL_isdigit((unsigned char) *text)) {
    205            v = *text - '0';
    206        } else if (radix == 16 && SDL_isupperhex(*text)) {
    207            v = 10 + (*text - 'A');
    208        } else if (radix == 16 && SDL_islowerhex(*text)) {
    209            v = 10 + (*text - 'a');
    210        } else {
    211            break;
    212        }
    213        value *= radix;
    214        value += v;
    215        ++text;
    216    }
    217    if (valuep) {
    218        *valuep = value;
    219    }
    220    return (text - textstart);
    221}
    222#endif
    223
    224#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOD)
    225static size_t
    226SDL_ScanFloat(const char *text, double *valuep)
    227{
    228    const char *textstart = text;
    229    unsigned long lvalue = 0;
    230    double value = 0.0;
    231    SDL_bool negative = SDL_FALSE;
    232
    233    if (*text == '-') {
    234        negative = SDL_TRUE;
    235        ++text;
    236    }
    237    text += SDL_ScanUnsignedLong(text, 10, &lvalue);
    238    value += lvalue;
    239    if (*text == '.') {
    240        int mult = 10;
    241        ++text;
    242        while (SDL_isdigit((unsigned char) *text)) {
    243            lvalue = *text - '0';
    244            value += (double) lvalue / mult;
    245            mult *= 10;
    246            ++text;
    247        }
    248    }
    249    if (valuep) {
    250        if (negative && value) {
    251            *valuep = -value;
    252        } else {
    253            *valuep = value;
    254        }
    255    }
    256    return (text - textstart);
    257}
    258#endif
    259
    260void *
    261SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len)
    262{
    263#if defined(HAVE_MEMSET)
    264    return memset(dst, c, len);
    265#else
    266    size_t left;
    267    Uint32 *dstp4;
    268    Uint8 *dstp1 = (Uint8 *) dst;
    269    Uint32 value4 = (c | (c << 8) | (c << 16) | (c << 24));
    270    Uint8 value1 = (Uint8) c;
    271
    272    /* The destination pointer needs to be aligned on a 4-byte boundary to
    273     * execute a 32-bit set. Set first bytes manually if needed until it is
    274     * aligned. */
    275    while ((intptr_t)dstp1 & 0x3) {
    276        if (len--) {
    277            *dstp1++ = value1;
    278        } else {
    279            return dst;
    280        }
    281    }
    282
    283    dstp4 = (Uint32 *) dstp1;
    284    left = (len % 4);
    285    len /= 4;
    286    while (len--) {
    287        *dstp4++ = value4;
    288    }
    289
    290    dstp1 = (Uint8 *) dstp4;
    291    switch (left) {
    292    case 3:
    293        *dstp1++ = value1;
    294    case 2:
    295        *dstp1++ = value1;
    296    case 1:
    297        *dstp1++ = value1;
    298    }
    299
    300    return dst;
    301#endif /* HAVE_MEMSET */
    302}
    303
    304void *
    305SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len)
    306{
    307#ifdef __GNUC__
    308    /* Presumably this is well tuned for speed.
    309       On my machine this is twice as fast as the C code below.
    310     */
    311    return __builtin_memcpy(dst, src, len);
    312#elif defined(HAVE_MEMCPY)
    313    return memcpy(dst, src, len);
    314#elif defined(HAVE_BCOPY)
    315    bcopy(src, dst, len);
    316    return dst;
    317#else
    318    /* GCC 4.9.0 with -O3 will generate movaps instructions with the loop
    319       using Uint32* pointers, so we need to make sure the pointers are
    320       aligned before we loop using them.
    321     */
    322    if (((intptr_t)src & 0x3) || ((intptr_t)dst & 0x3)) {
    323        /* Do an unaligned byte copy */
    324        Uint8 *srcp1 = (Uint8 *)src;
    325        Uint8 *dstp1 = (Uint8 *)dst;
    326
    327        while (len--) {
    328            *dstp1++ = *srcp1++;
    329        }
    330    } else {
    331        size_t left = (len % 4);
    332        Uint32 *srcp4, *dstp4;
    333        Uint8 *srcp1, *dstp1;
    334
    335        srcp4 = (Uint32 *) src;
    336        dstp4 = (Uint32 *) dst;
    337        len /= 4;
    338        while (len--) {
    339            *dstp4++ = *srcp4++;
    340        }
    341
    342        srcp1 = (Uint8 *) srcp4;
    343        dstp1 = (Uint8 *) dstp4;
    344        switch (left) {
    345        case 3:
    346            *dstp1++ = *srcp1++;
    347        case 2:
    348            *dstp1++ = *srcp1++;
    349        case 1:
    350            *dstp1++ = *srcp1++;
    351        }
    352    }
    353    return dst;
    354#endif /* __GNUC__ */
    355}
    356
    357void *
    358SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len)
    359{
    360#if defined(HAVE_MEMMOVE)
    361    return memmove(dst, src, len);
    362#else
    363    char *srcp = (char *) src;
    364    char *dstp = (char *) dst;
    365
    366    if (src < dst) {
    367        srcp += len - 1;
    368        dstp += len - 1;
    369        while (len--) {
    370            *dstp-- = *srcp--;
    371        }
    372    } else {
    373        while (len--) {
    374            *dstp++ = *srcp++;
    375        }
    376    }
    377    return dst;
    378#endif /* HAVE_MEMMOVE */
    379}
    380
    381int
    382SDL_memcmp(const void *s1, const void *s2, size_t len)
    383{
    384#if defined(HAVE_MEMCMP)
    385    return memcmp(s1, s2, len);
    386#else
    387    char *s1p = (char *) s1;
    388    char *s2p = (char *) s2;
    389    while (len--) {
    390        if (*s1p != *s2p) {
    391            return (*s1p - *s2p);
    392        }
    393        ++s1p;
    394        ++s2p;
    395    }
    396    return 0;
    397#endif /* HAVE_MEMCMP */
    398}
    399
    400size_t
    401SDL_strlen(const char *string)
    402{
    403#if defined(HAVE_STRLEN)
    404    return strlen(string);
    405#else
    406    size_t len = 0;
    407    while (*string++) {
    408        ++len;
    409    }
    410    return len;
    411#endif /* HAVE_STRLEN */
    412}
    413
    414size_t
    415SDL_wcslen(const wchar_t * string)
    416{
    417#if defined(HAVE_WCSLEN)
    418    return wcslen(string);
    419#else
    420    size_t len = 0;
    421    while (*string++) {
    422        ++len;
    423    }
    424    return len;
    425#endif /* HAVE_WCSLEN */
    426}
    427
    428size_t
    429SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen)
    430{
    431#if defined(HAVE_WCSLCPY)
    432    return wcslcpy(dst, src, maxlen);
    433#else
    434    size_t srclen = SDL_wcslen(src);
    435    if (maxlen > 0) {
    436        size_t len = SDL_min(srclen, maxlen - 1);
    437        SDL_memcpy(dst, src, len * sizeof(wchar_t));
    438        dst[len] = '\0';
    439    }
    440    return srclen;
    441#endif /* HAVE_WCSLCPY */
    442}
    443
    444size_t
    445SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen)
    446{
    447#if defined(HAVE_WCSLCAT)
    448    return wcslcat(dst, src, maxlen);
    449#else
    450    size_t dstlen = SDL_wcslen(dst);
    451    size_t srclen = SDL_wcslen(src);
    452    if (dstlen < maxlen) {
    453        SDL_wcslcpy(dst + dstlen, src, maxlen - dstlen);
    454    }
    455    return dstlen + srclen;
    456#endif /* HAVE_WCSLCAT */
    457}
    458
    459size_t
    460SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen)
    461{
    462#if defined(HAVE_STRLCPY)
    463    return strlcpy(dst, src, maxlen);
    464#else
    465    size_t srclen = SDL_strlen(src);
    466    if (maxlen > 0) {
    467        size_t len = SDL_min(srclen, maxlen - 1);
    468        SDL_memcpy(dst, src, len);
    469        dst[len] = '\0';
    470    }
    471    return srclen;
    472#endif /* HAVE_STRLCPY */
    473}
    474
    475size_t SDL_utf8strlcpy(SDL_OUT_Z_CAP(dst_bytes) char *dst, const char *src, size_t dst_bytes)
    476{
    477    size_t src_bytes = SDL_strlen(src);
    478    size_t bytes = SDL_min(src_bytes, dst_bytes - 1);
    479    size_t i = 0;
    480    char trailing_bytes = 0;
    481    if (bytes)
    482    {
    483        unsigned char c = (unsigned char)src[bytes - 1];
    484        if (UTF8_IsLeadByte(c))
    485            --bytes;
    486        else if (UTF8_IsTrailingByte(c))
    487        {
    488            for (i = bytes - 1; i != 0; --i)
    489            {
    490                c = (unsigned char)src[i];
    491                trailing_bytes = UTF8_TrailingBytes(c);
    492                if (trailing_bytes)
    493                {
    494                    if (bytes - i != trailing_bytes + 1)
    495                        bytes = i;
    496
    497                    break;
    498                }
    499            }
    500        }
    501        SDL_memcpy(dst, src, bytes);
    502    }
    503    dst[bytes] = '\0';
    504    return bytes;
    505}
    506
    507size_t
    508SDL_strlcat(SDL_INOUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen)
    509{
    510#if defined(HAVE_STRLCAT)
    511    return strlcat(dst, src, maxlen);
    512#else
    513    size_t dstlen = SDL_strlen(dst);
    514    size_t srclen = SDL_strlen(src);
    515    if (dstlen < maxlen) {
    516        SDL_strlcpy(dst + dstlen, src, maxlen - dstlen);
    517    }
    518    return dstlen + srclen;
    519#endif /* HAVE_STRLCAT */
    520}
    521
    522char *
    523SDL_strdup(const char *string)
    524{
    525#if defined(HAVE_STRDUP)
    526    return strdup(string);
    527#else
    528    size_t len = SDL_strlen(string) + 1;
    529    char *newstr = SDL_malloc(len);
    530    if (newstr) {
    531        SDL_strlcpy(newstr, string, len);
    532    }
    533    return newstr;
    534#endif /* HAVE_STRDUP */
    535}
    536
    537char *
    538SDL_strrev(char *string)
    539{
    540#if defined(HAVE__STRREV)
    541    return _strrev(string);
    542#else
    543    size_t len = SDL_strlen(string);
    544    char *a = &string[0];
    545    char *b = &string[len - 1];
    546    len /= 2;
    547    while (len--) {
    548        char c = *a;
    549        *a++ = *b;
    550        *b-- = c;
    551    }
    552    return string;
    553#endif /* HAVE__STRREV */
    554}
    555
    556char *
    557SDL_strupr(char *string)
    558{
    559#if defined(HAVE__STRUPR)
    560    return _strupr(string);
    561#else
    562    char *bufp = string;
    563    while (*bufp) {
    564        *bufp = SDL_toupper((unsigned char) *bufp);
    565        ++bufp;
    566    }
    567    return string;
    568#endif /* HAVE__STRUPR */
    569}
    570
    571char *
    572SDL_strlwr(char *string)
    573{
    574#if defined(HAVE__STRLWR)
    575    return _strlwr(string);
    576#else
    577    char *bufp = string;
    578    while (*bufp) {
    579        *bufp = SDL_tolower((unsigned char) *bufp);
    580        ++bufp;
    581    }
    582    return string;
    583#endif /* HAVE__STRLWR */
    584}
    585
    586char *
    587SDL_strchr(const char *string, int c)
    588{
    589#ifdef HAVE_STRCHR
    590    return SDL_const_cast(char*,strchr(string, c));
    591#elif defined(HAVE_INDEX)
    592    return SDL_const_cast(char*,index(string, c));
    593#else
    594    while (*string) {
    595        if (*string == c) {
    596            return (char *) string;
    597        }
    598        ++string;
    599    }
    600    return NULL;
    601#endif /* HAVE_STRCHR */
    602}
    603
    604char *
    605SDL_strrchr(const char *string, int c)
    606{
    607#ifdef HAVE_STRRCHR
    608    return SDL_const_cast(char*,strrchr(string, c));
    609#elif defined(HAVE_RINDEX)
    610    return SDL_const_cast(char*,rindex(string, c));
    611#else
    612    const char *bufp = string + SDL_strlen(string) - 1;
    613    while (bufp >= string) {
    614        if (*bufp == c) {
    615            return (char *) bufp;
    616        }
    617        --bufp;
    618    }
    619    return NULL;
    620#endif /* HAVE_STRRCHR */
    621}
    622
    623char *
    624SDL_strstr(const char *haystack, const char *needle)
    625{
    626#if defined(HAVE_STRSTR)
    627    return SDL_const_cast(char*,strstr(haystack, needle));
    628#else
    629    size_t length = SDL_strlen(needle);
    630    while (*haystack) {
    631        if (SDL_strncmp(haystack, needle, length) == 0) {
    632            return (char *) haystack;
    633        }
    634        ++haystack;
    635    }
    636    return NULL;
    637#endif /* HAVE_STRSTR */
    638}
    639
    640#if !defined(HAVE__LTOA) || !defined(HAVE__I64TOA) || \
    641    !defined(HAVE__ULTOA) || !defined(HAVE__UI64TOA)
    642static const char ntoa_table[] = {
    643    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    644    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
    645    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    646    'U', 'V', 'W', 'X', 'Y', 'Z'
    647};
    648#endif /* ntoa() conversion table */
    649
    650char *
    651SDL_itoa(int value, char *string, int radix)
    652{
    653#ifdef HAVE_ITOA
    654    return itoa(value, string, radix);
    655#else
    656    return SDL_ltoa((long)value, string, radix);
    657#endif /* HAVE_ITOA */
    658}
    659
    660char *
    661SDL_uitoa(unsigned int value, char *string, int radix)
    662{
    663#ifdef HAVE__UITOA
    664    return _uitoa(value, string, radix);
    665#else
    666    return SDL_ultoa((unsigned long)value, string, radix);
    667#endif /* HAVE__UITOA */
    668}
    669
    670char *
    671SDL_ltoa(long value, char *string, int radix)
    672{
    673#if defined(HAVE__LTOA)
    674    return _ltoa(value, string, radix);
    675#else
    676    char *bufp = string;
    677
    678    if (value < 0) {
    679        *bufp++ = '-';
    680        SDL_ultoa(-value, bufp, radix);
    681    } else {
    682        SDL_ultoa(value, bufp, radix);
    683    }
    684
    685    return string;
    686#endif /* HAVE__LTOA */
    687}
    688
    689char *
    690SDL_ultoa(unsigned long value, char *string, int radix)
    691{
    692#if defined(HAVE__ULTOA)
    693    return _ultoa(value, string, radix);
    694#else
    695    char *bufp = string;
    696
    697    if (value) {
    698        while (value > 0) {
    699            *bufp++ = ntoa_table[value % radix];
    700            value /= radix;
    701        }
    702    } else {
    703        *bufp++ = '0';
    704    }
    705    *bufp = '\0';
    706
    707    /* The numbers went into the string backwards. :) */
    708    SDL_strrev(string);
    709
    710    return string;
    711#endif /* HAVE__ULTOA */
    712}
    713
    714char *
    715SDL_lltoa(Sint64 value, char *string, int radix)
    716{
    717#if defined(HAVE__I64TOA)
    718    return _i64toa(value, string, radix);
    719#else
    720    char *bufp = string;
    721
    722    if (value < 0) {
    723        *bufp++ = '-';
    724        SDL_ulltoa(-value, bufp, radix);
    725    } else {
    726        SDL_ulltoa(value, bufp, radix);
    727    }
    728
    729    return string;
    730#endif /* HAVE__I64TOA */
    731}
    732
    733char *
    734SDL_ulltoa(Uint64 value, char *string, int radix)
    735{
    736#if defined(HAVE__UI64TOA)
    737    return _ui64toa(value, string, radix);
    738#else
    739    char *bufp = string;
    740
    741    if (value) {
    742        while (value > 0) {
    743            *bufp++ = ntoa_table[value % radix];
    744            value /= radix;
    745        }
    746    } else {
    747        *bufp++ = '0';
    748    }
    749    *bufp = '\0';
    750
    751    /* The numbers went into the string backwards. :) */
    752    SDL_strrev(string);
    753
    754    return string;
    755#endif /* HAVE__UI64TOA */
    756}
    757
    758int SDL_atoi(const char *string)
    759{
    760#ifdef HAVE_ATOI
    761    return atoi(string);
    762#else
    763    return SDL_strtol(string, NULL, 0);
    764#endif /* HAVE_ATOI */
    765}
    766
    767double SDL_atof(const char *string)
    768{
    769#ifdef HAVE_ATOF
    770    return (double) atof(string);
    771#else
    772    return SDL_strtod(string, NULL);
    773#endif /* HAVE_ATOF */
    774}
    775
    776long
    777SDL_strtol(const char *string, char **endp, int base)
    778{
    779#if defined(HAVE_STRTOL)
    780    return strtol(string, endp, base);
    781#else
    782    size_t len;
    783    long value;
    784
    785    if (!base) {
    786        if ((SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0)) {
    787            base = 16;
    788        } else {
    789            base = 10;
    790        }
    791    }
    792
    793    len = SDL_ScanLong(string, base, &value);
    794    if (endp) {
    795        *endp = (char *) string + len;
    796    }
    797    return value;
    798#endif /* HAVE_STRTOL */
    799}
    800
    801unsigned long
    802SDL_strtoul(const char *string, char **endp, int base)
    803{
    804#if defined(HAVE_STRTOUL)
    805    return strtoul(string, endp, base);
    806#else
    807    size_t len;
    808    unsigned long value;
    809
    810    if (!base) {
    811        if ((SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0)) {
    812            base = 16;
    813        } else {
    814            base = 10;
    815        }
    816    }
    817
    818    len = SDL_ScanUnsignedLong(string, base, &value);
    819    if (endp) {
    820        *endp = (char *) string + len;
    821    }
    822    return value;
    823#endif /* HAVE_STRTOUL */
    824}
    825
    826Sint64
    827SDL_strtoll(const char *string, char **endp, int base)
    828{
    829#if defined(HAVE_STRTOLL)
    830    return strtoll(string, endp, base);
    831#else
    832    size_t len;
    833    Sint64 value;
    834
    835    if (!base) {
    836        if ((SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0)) {
    837            base = 16;
    838        } else {
    839            base = 10;
    840        }
    841    }
    842
    843    len = SDL_ScanLongLong(string, base, &value);
    844    if (endp) {
    845        *endp = (char *) string + len;
    846    }
    847    return value;
    848#endif /* HAVE_STRTOLL */
    849}
    850
    851Uint64
    852SDL_strtoull(const char *string, char **endp, int base)
    853{
    854#if defined(HAVE_STRTOULL)
    855    return strtoull(string, endp, base);
    856#else
    857    size_t len;
    858    Uint64 value;
    859
    860    if (!base) {
    861        if ((SDL_strlen(string) > 2) && (SDL_strncmp(string, "0x", 2) == 0)) {
    862            base = 16;
    863        } else {
    864            base = 10;
    865        }
    866    }
    867
    868    len = SDL_ScanUnsignedLongLong(string, base, &value);
    869    if (endp) {
    870        *endp = (char *) string + len;
    871    }
    872    return value;
    873#endif /* HAVE_STRTOULL */
    874}
    875
    876double
    877SDL_strtod(const char *string, char **endp)
    878{
    879#if defined(HAVE_STRTOD)
    880    return strtod(string, endp);
    881#else
    882    size_t len;
    883    double value;
    884
    885    len = SDL_ScanFloat(string, &value);
    886    if (endp) {
    887        *endp = (char *) string + len;
    888    }
    889    return value;
    890#endif /* HAVE_STRTOD */
    891}
    892
    893int
    894SDL_strcmp(const char *str1, const char *str2)
    895{
    896#if defined(HAVE_STRCMP)
    897    return strcmp(str1, str2);
    898#else
    899    while (*str1 && *str2) {
    900        if (*str1 != *str2)
    901            break;
    902        ++str1;
    903        ++str2;
    904    }
    905    return (int) ((unsigned char) *str1 - (unsigned char) *str2);
    906#endif /* HAVE_STRCMP */
    907}
    908
    909int
    910SDL_strncmp(const char *str1, const char *str2, size_t maxlen)
    911{
    912#if defined(HAVE_STRNCMP)
    913    return strncmp(str1, str2, maxlen);
    914#else
    915    while (*str1 && *str2 && maxlen) {
    916        if (*str1 != *str2)
    917            break;
    918        ++str1;
    919        ++str2;
    920        --maxlen;
    921    }
    922    if (!maxlen) {
    923        return 0;
    924    }
    925    return (int) ((unsigned char) *str1 - (unsigned char) *str2);
    926#endif /* HAVE_STRNCMP */
    927}
    928
    929int
    930SDL_strcasecmp(const char *str1, const char *str2)
    931{
    932#ifdef HAVE_STRCASECMP
    933    return strcasecmp(str1, str2);
    934#elif defined(HAVE__STRICMP)
    935    return _stricmp(str1, str2);
    936#else
    937    char a = 0;
    938    char b = 0;
    939    while (*str1 && *str2) {
    940        a = SDL_toupper((unsigned char) *str1);
    941        b = SDL_toupper((unsigned char) *str2);
    942        if (a != b)
    943            break;
    944        ++str1;
    945        ++str2;
    946    }
    947    a = SDL_toupper(*str1);
    948    b = SDL_toupper(*str2);
    949    return (int) ((unsigned char) a - (unsigned char) b);
    950#endif /* HAVE_STRCASECMP */
    951}
    952
    953int
    954SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen)
    955{
    956#ifdef HAVE_STRNCASECMP
    957    return strncasecmp(str1, str2, maxlen);
    958#elif defined(HAVE__STRNICMP)
    959    return _strnicmp(str1, str2, maxlen);
    960#else
    961    char a = 0;
    962    char b = 0;
    963    while (*str1 && *str2 && maxlen) {
    964        a = SDL_tolower((unsigned char) *str1);
    965        b = SDL_tolower((unsigned char) *str2);
    966        if (a != b)
    967            break;
    968        ++str1;
    969        ++str2;
    970        --maxlen;
    971    }
    972    if (maxlen == 0) {
    973        return 0;
    974    } else {
    975        a = SDL_tolower((unsigned char) *str1);
    976        b = SDL_tolower((unsigned char) *str2);
    977        return (int) ((unsigned char) a - (unsigned char) b);
    978    }
    979#endif /* HAVE_STRNCASECMP */
    980}
    981
    982int
    983SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...)
    984{
    985    int rc;
    986    va_list ap;
    987    va_start(ap, fmt);
    988    rc = SDL_vsscanf(text, fmt, ap);
    989    va_end(ap);
    990    return rc;
    991}
    992
    993#ifdef HAVE_VSSCANF
    994int
    995SDL_vsscanf(const char *text, const char *fmt, va_list ap)
    996{
    997    return vsscanf(text, fmt, ap);
    998}
    999#else
   1000int
   1001SDL_vsscanf(const char *text, const char *fmt, va_list ap)
   1002{
   1003    int retval = 0;
   1004
   1005    while (*fmt) {
   1006        if (*fmt == ' ') {
   1007            while (SDL_isspace((unsigned char) *text)) {
   1008                ++text;
   1009            }
   1010            ++fmt;
   1011            continue;
   1012        }
   1013        if (*fmt == '%') {
   1014            SDL_bool done = SDL_FALSE;
   1015            long count = 0;
   1016            int radix = 10;
   1017            enum
   1018            {
   1019                DO_SHORT,
   1020                DO_INT,
   1021                DO_LONG,
   1022                DO_LONGLONG
   1023            } inttype = DO_INT;
   1024            SDL_bool suppress = SDL_FALSE;
   1025
   1026            ++fmt;
   1027            if (*fmt == '%') {
   1028                if (*text == '%') {
   1029                    ++text;
   1030                    ++fmt;
   1031                    continue;
   1032                }
   1033                break;
   1034            }
   1035            if (*fmt == '*') {
   1036                suppress = SDL_TRUE;
   1037                ++fmt;
   1038            }
   1039            fmt += SDL_ScanLong(fmt, 10, &count);
   1040
   1041            if (*fmt == 'c') {
   1042                if (!count) {
   1043                    count = 1;
   1044                }
   1045                if (suppress) {
   1046                    while (count--) {
   1047                        ++text;
   1048                    }
   1049                } else {
   1050                    char *valuep = va_arg(ap, char *);
   1051                    while (count--) {
   1052                        *valuep++ = *text++;
   1053                    }
   1054                    ++retval;
   1055                }
   1056                continue;
   1057            }
   1058
   1059            while (SDL_isspace((unsigned char) *text)) {
   1060                ++text;
   1061            }
   1062
   1063            /* FIXME: implement more of the format specifiers */
   1064            while (!done) {
   1065                switch (*fmt) {
   1066                case '*':
   1067                    suppress = SDL_TRUE;
   1068                    break;
   1069                case 'h':
   1070                    if (inttype > DO_SHORT) {
   1071                        ++inttype;
   1072                    }
   1073                    break;
   1074                case 'l':
   1075                    if (inttype < DO_LONGLONG) {
   1076                        ++inttype;
   1077                    }
   1078                    break;
   1079                case 'I':
   1080                    if (SDL_strncmp(fmt, "I64", 3) == 0) {
   1081                        fmt += 2;
   1082                        inttype = DO_LONGLONG;
   1083                    }
   1084                    break;
   1085                case 'i':
   1086                    {
   1087                        int index = 0;
   1088                        if (text[index] == '-') {
   1089                            ++index;
   1090                        }
   1091                        if (text[index] == '0') {
   1092                            if (SDL_tolower((unsigned char) text[index + 1]) == 'x') {
   1093                                radix = 16;
   1094                            } else {
   1095                                radix = 8;
   1096                            }
   1097                        }
   1098                    }
   1099                    /* Fall through to %d handling */
   1100                case 'd':
   1101                    if (inttype == DO_LONGLONG) {
   1102                        Sint64 value;
   1103                        text += SDL_ScanLongLong(text, radix, &value);
   1104                        if (!suppress) {
   1105                            Sint64 *valuep = va_arg(ap, Sint64 *);
   1106                            *valuep = value;
   1107                            ++retval;
   1108                        }
   1109                    } else {
   1110                        long value;
   1111                        text += SDL_ScanLong(text, radix, &value);
   1112                        if (!suppress) {
   1113                            switch (inttype) {
   1114                            case DO_SHORT:
   1115                                {
   1116                                    short *valuep = va_arg(ap, short *);
   1117                                    *valuep = (short) value;
   1118                                }
   1119                                break;
   1120                            case DO_INT:
   1121                                {
   1122                                    int *valuep = va_arg(ap, int *);
   1123                                    *valuep = (int) value;
   1124                                }
   1125                                break;
   1126                            case DO_LONG:
   1127                                {
   1128                                    long *valuep = va_arg(ap, long *);
   1129                                    *valuep = value;
   1130                                }
   1131                                break;
   1132                            case DO_LONGLONG:
   1133                                /* Handled above */
   1134                                break;
   1135                            }
   1136                            ++retval;
   1137                        }
   1138                    }
   1139                    done = SDL_TRUE;
   1140                    break;
   1141                case 'o':
   1142                    if (radix == 10) {
   1143                        radix = 8;
   1144                    }
   1145                    /* Fall through to unsigned handling */
   1146                case 'x':
   1147                case 'X':
   1148                    if (radix == 10) {
   1149                        radix = 16;
   1150                    }
   1151                    /* Fall through to unsigned handling */
   1152                case 'u':
   1153                    if (inttype == DO_LONGLONG) {
   1154                        Uint64 value;
   1155                        text += SDL_ScanUnsignedLongLong(text, radix, &value);
   1156                        if (!suppress) {
   1157                            Uint64 *valuep = va_arg(ap, Uint64 *);
   1158                            *valuep = value;
   1159                            ++retval;
   1160                        }
   1161                    } else {
   1162                        unsigned long value;
   1163                        text += SDL_ScanUnsignedLong(text, radix, &value);
   1164                        if (!suppress) {
   1165                            switch (inttype) {
   1166                            case DO_SHORT:
   1167                                {
   1168                                    short *valuep = va_arg(ap, short *);
   1169                                    *valuep = (short) value;
   1170                                }
   1171                                break;
   1172                            case DO_INT:
   1173                                {
   1174                                    int *valuep = va_arg(ap, int *);
   1175                                    *valuep = (int) value;
   1176                                }
   1177                                break;
   1178                            case DO_LONG:
   1179                                {
   1180                                    long *valuep = va_arg(ap, long *);
   1181                                    *valuep = value;
   1182                                }
   1183                                break;
   1184                            case DO_LONGLONG:
   1185                                /* Handled above */
   1186                                break;
   1187                            }
   1188                            ++retval;
   1189                        }
   1190                    }
   1191                    done = SDL_TRUE;
   1192                    break;
   1193                case 'p':
   1194                    {
   1195                        uintptr_t value;
   1196                        text += SDL_ScanUintPtrT(text, 16, &value);
   1197                        if (!suppress) {
   1198                            void **valuep = va_arg(ap, void **);
   1199                            *valuep = (void *) value;
   1200                            ++retval;
   1201                        }
   1202                    }
   1203                    done = SDL_TRUE;
   1204                    break;
   1205                case 'f':
   1206                    {
   1207                        double value;
   1208                        text += SDL_ScanFloat(text, &value);
   1209                        if (!suppress) {
   1210                            float *valuep = va_arg(ap, float *);
   1211                            *valuep = (float) value;
   1212                            ++retval;
   1213                        }
   1214                    }
   1215                    done = SDL_TRUE;
   1216                    break;
   1217                case 's':
   1218                    if (suppress) {
   1219                        while (!SDL_isspace((unsigned char) *text)) {
   1220                            ++text;
   1221                            if (count) {
   1222                                if (--count == 0) {
   1223                                    break;
   1224                                }
   1225                            }
   1226                        }
   1227                    } else {
   1228                        char *valuep = va_arg(ap, char *);
   1229                        while (!SDL_isspace((unsigned char) *text)) {
   1230                            *valuep++ = *text++;
   1231                            if (count) {
   1232                                if (--count == 0) {
   1233                                    break;
   1234                                }
   1235                            }
   1236                        }
   1237                        *valuep = '\0';
   1238                        ++retval;
   1239                    }
   1240                    done = SDL_TRUE;
   1241                    break;
   1242                default:
   1243                    done = SDL_TRUE;
   1244                    break;
   1245                }
   1246                ++fmt;
   1247            }
   1248            continue;
   1249        }
   1250        if (*text == *fmt) {
   1251            ++text;
   1252            ++fmt;
   1253            continue;
   1254        }
   1255        /* Text didn't match format specifier */
   1256        break;
   1257    }
   1258
   1259    return retval;
   1260}
   1261#endif /* HAVE_VSSCANF */
   1262
   1263int
   1264SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
   1265{
   1266    va_list ap;
   1267    int retval;
   1268
   1269    va_start(ap, fmt);
   1270    retval = SDL_vsnprintf(text, maxlen, fmt, ap);
   1271    va_end(ap);
   1272
   1273    return retval;
   1274}
   1275
   1276#ifdef HAVE_VSNPRINTF
   1277int SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap)
   1278{
   1279    if (!fmt) {
   1280        fmt = "";
   1281    }
   1282    return vsnprintf(text, maxlen, fmt, ap);
   1283}
   1284#else
   1285 /* FIXME: implement more of the format specifiers */
   1286typedef enum
   1287{
   1288    SDL_CASE_NOCHANGE,
   1289    SDL_CASE_LOWER,
   1290    SDL_CASE_UPPER
   1291} SDL_letter_case;
   1292
   1293typedef struct
   1294{
   1295    SDL_bool left_justify;
   1296    SDL_bool force_sign;
   1297    SDL_bool force_type;
   1298    SDL_bool pad_zeroes;
   1299    SDL_letter_case force_case;
   1300    int width;
   1301    int radix;
   1302    int precision;
   1303} SDL_FormatInfo;
   1304
   1305static size_t
   1306SDL_PrintString(char *text, size_t maxlen, SDL_FormatInfo *info, const char *string)
   1307{
   1308    size_t length = 0;
   1309
   1310    if (info && info->width && (size_t)info->width > SDL_strlen(string)) {
   1311        char fill = info->pad_zeroes ? '0' : ' ';
   1312        size_t width = info->width - SDL_strlen(string);
   1313        while (width-- > 0 && maxlen > 0) {
   1314            *text++ = fill;
   1315            ++length;
   1316            --maxlen;
   1317        }
   1318    }
   1319
   1320    length += SDL_strlcpy(text, string, maxlen);
   1321
   1322    if (info) {
   1323        if (info->force_case == SDL_CASE_LOWER) {
   1324            SDL_strlwr(text);
   1325        } else if (info->force_case == SDL_CASE_UPPER) {
   1326            SDL_strupr(text);
   1327        }
   1328    }
   1329    return length;
   1330}
   1331
   1332static size_t
   1333SDL_PrintLong(char *text, size_t maxlen, SDL_FormatInfo *info, long value)
   1334{
   1335    char num[130];
   1336
   1337    SDL_ltoa(value, num, info ? info->radix : 10);
   1338    return SDL_PrintString(text, maxlen, info, num);
   1339}
   1340
   1341static size_t
   1342SDL_PrintUnsignedLong(char *text, size_t maxlen, SDL_FormatInfo *info, unsigned long value)
   1343{
   1344    char num[130];
   1345
   1346    SDL_ultoa(value, num, info ? info->radix : 10);
   1347    return SDL_PrintString(text, maxlen, info, num);
   1348}
   1349
   1350static size_t
   1351SDL_PrintLongLong(char *text, size_t maxlen, SDL_FormatInfo *info, Sint64 value)
   1352{
   1353    char num[130];
   1354
   1355    SDL_lltoa(value, num, info ? info->radix : 10);
   1356    return SDL_PrintString(text, maxlen, info, num);
   1357}
   1358
   1359static size_t
   1360SDL_PrintUnsignedLongLong(char *text, size_t maxlen, SDL_FormatInfo *info, Uint64 value)
   1361{
   1362    char num[130];
   1363
   1364    SDL_ulltoa(value, num, info ? info->radix : 10);
   1365    return SDL_PrintString(text, maxlen, info, num);
   1366}
   1367
   1368static size_t
   1369SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
   1370{
   1371    int width;
   1372    size_t len;
   1373    size_t left = maxlen;
   1374    char *textstart = text;
   1375
   1376    if (arg) {
   1377        /* This isn't especially accurate, but hey, it's easy. :) */
   1378        unsigned long value;
   1379
   1380        if (arg < 0) {
   1381            if (left > 1) {
   1382                *text = '-';
   1383                --left;
   1384            }
   1385            ++text;
   1386            arg = -arg;
   1387        } else if (info->force_sign) {
   1388            if (left > 1) {
   1389                *text = '+';
   1390                --left;
   1391            }
   1392            ++text;
   1393        }
   1394        value = (unsigned long) arg;
   1395        len = SDL_PrintUnsignedLong(text, left, NULL, value);
   1396        text += len;
   1397        if (len >= left) {
   1398            left = SDL_min(left, 1);
   1399        } else {
   1400            left -= len;
   1401        }
   1402        arg -= value;
   1403        if (info->precision < 0) {
   1404            info->precision = 6;
   1405        }
   1406        if (info->force_type || info->precision > 0) {
   1407            int mult = 10;
   1408            if (left > 1) {
   1409                *text = '.';
   1410                --left;
   1411            }
   1412            ++text;
   1413            while (info->precision-- > 0) {
   1414                value = (unsigned long) (arg * mult);
   1415                len = SDL_PrintUnsignedLong(text, left, NULL, value);
   1416                text += len;
   1417                if (len >= left) {
   1418                    left = SDL_min(left, 1);
   1419                } else {
   1420                    left -= len;
   1421                }
   1422                arg -= (double) value / mult;
   1423                mult *= 10;
   1424            }
   1425        }
   1426    } else {
   1427        if (left > 1) {
   1428            *text = '0';
   1429            --left;
   1430        }
   1431        ++text;
   1432        if (info->force_type) {
   1433            if (left > 1) {
   1434                *text = '.';
   1435                --left;
   1436            }
   1437            ++text;
   1438        }
   1439    }
   1440
   1441    width = info->width - (int)(text - textstart);
   1442    if (width > 0) {
   1443        char fill = info->pad_zeroes ? '0' : ' ';
   1444        char *end = text+left-1;
   1445        len = (text - textstart);
   1446        for (len = (text - textstart); len--; ) {
   1447            if ((textstart+len+width) < end) {
   1448                *(textstart+len+width) = *(textstart+len);
   1449            }
   1450        }
   1451        len = (size_t)width;
   1452        text += len;
   1453        if (len >= left) {
   1454            left = SDL_min(left, 1);
   1455        } else {
   1456            left -= len;
   1457        }
   1458        while (len--) {
   1459            if (textstart+len < end) {
   1460                textstart[len] = fill;
   1461            }
   1462        }
   1463    }
   1464
   1465    return (text - textstart);
   1466}
   1467
   1468int
   1469SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap)
   1470{
   1471    size_t left = maxlen;
   1472    char *textstart = text;
   1473
   1474    if (!fmt) {
   1475        fmt = "";
   1476    }
   1477    while (*fmt) {
   1478        if (*fmt == '%') {
   1479            SDL_bool done = SDL_FALSE;
   1480            size_t len = 0;
   1481            SDL_bool check_flag;
   1482            SDL_FormatInfo info;
   1483            enum
   1484            {
   1485                DO_INT,
   1486                DO_LONG,
   1487                DO_LONGLONG
   1488            } inttype = DO_INT;
   1489
   1490            SDL_zero(info);
   1491            info.radix = 10;
   1492            info.precision = -1;
   1493
   1494            check_flag = SDL_TRUE;
   1495            while (check_flag) {
   1496                ++fmt;
   1497                switch (*fmt) {
   1498                case '-':
   1499                    info.left_justify = SDL_TRUE;
   1500                    break;
   1501                case '+':
   1502                    info.force_sign = SDL_TRUE;
   1503                    break;
   1504                case '#':
   1505                    info.force_type = SDL_TRUE;
   1506                    break;
   1507                case '0':
   1508                    info.pad_zeroes = SDL_TRUE;
   1509                    break;
   1510                default:
   1511                    check_flag = SDL_FALSE;
   1512                    break;
   1513                }
   1514            }
   1515
   1516            if (*fmt >= '0' && *fmt <= '9') {
   1517                info.width = SDL_strtol(fmt, (char **)&fmt, 0);
   1518            }
   1519
   1520            if (*fmt == '.') {
   1521                ++fmt;
   1522                if (*fmt >= '0' && *fmt <= '9') {
   1523                    info.precision = SDL_strtol(fmt, (char **)&fmt, 0);
   1524                } else {
   1525                    info.precision = 0;
   1526                }
   1527            }
   1528
   1529            while (!done) {
   1530                switch (*fmt) {
   1531                case '%':
   1532                    if (left > 1) {
   1533                        *text = '%';
   1534                    }
   1535                    len = 1;
   1536                    done = SDL_TRUE;
   1537                    break;
   1538                case 'c':
   1539                    /* char is promoted to int when passed through (...) */
   1540                    if (left > 1) {
   1541                        *text = (char) va_arg(ap, int);
   1542                    }
   1543                    len = 1;
   1544                    done = SDL_TRUE;
   1545                    break;
   1546                case 'h':
   1547                    /* short is promoted to int when passed through (...) */
   1548                    break;
   1549                case 'l':
   1550                    if (inttype < DO_LONGLONG) {
   1551                        ++inttype;
   1552                    }
   1553                    break;
   1554                case 'I':
   1555                    if (SDL_strncmp(fmt, "I64", 3) == 0) {
   1556                        fmt += 2;
   1557                        inttype = DO_LONGLONG;
   1558                    }
   1559                    break;
   1560                case 'i':
   1561                case 'd':
   1562                    switch (inttype) {
   1563                    case DO_INT:
   1564                        len = SDL_PrintLong(text, left, &info,
   1565                                            (long) va_arg(ap, int));
   1566                        break;
   1567                    case DO_LONG:
   1568                        len = SDL_PrintLong(text, left, &info,
   1569                                            va_arg(ap, long));
   1570                        break;
   1571                    case DO_LONGLONG:
   1572                        len = SDL_PrintLongLong(text, left, &info,
   1573                                                va_arg(ap, Sint64));
   1574                        break;
   1575                    }
   1576                    done = SDL_TRUE;
   1577                    break;
   1578                case 'p':
   1579                case 'x':
   1580                    info.force_case = SDL_CASE_LOWER;
   1581                    /* Fall through to 'X' handling */
   1582                case 'X':
   1583                    if (info.force_case == SDL_CASE_NOCHANGE) {
   1584                        info.force_case = SDL_CASE_UPPER;
   1585                    }
   1586                    if (info.radix == 10) {
   1587                        info.radix = 16;
   1588                    }
   1589                    if (*fmt == 'p') {
   1590                        inttype = DO_LONG;
   1591                    }
   1592                    /* Fall through to unsigned handling */
   1593                case 'o':
   1594                    if (info.radix == 10) {
   1595                        info.radix = 8;
   1596                    }
   1597                    /* Fall through to unsigned handling */
   1598                case 'u':
   1599                    info.pad_zeroes = SDL_TRUE;
   1600                    switch (inttype) {
   1601                    case DO_INT:
   1602                        len = SDL_PrintUnsignedLong(text, left, &info,
   1603                                                    (unsigned long)
   1604                                                    va_arg(ap, unsigned int));
   1605                        break;
   1606                    case DO_LONG:
   1607                        len = SDL_PrintUnsignedLong(text, left, &info,
   1608                                                    va_arg(ap, unsigned long));
   1609                        break;
   1610                    case DO_LONGLONG:
   1611                        len = SDL_PrintUnsignedLongLong(text, left, &info,
   1612                                                        va_arg(ap, Uint64));
   1613                        break;
   1614                    }
   1615                    done = SDL_TRUE;
   1616                    break;
   1617                case 'f':
   1618                    len = SDL_PrintFloat(text, left, &info, va_arg(ap, double));
   1619                    done = SDL_TRUE;
   1620                    break;
   1621                case 's':
   1622                    len = SDL_PrintString(text, left, &info, va_arg(ap, char *));
   1623                    done = SDL_TRUE;
   1624                    break;
   1625                default:
   1626                    done = SDL_TRUE;
   1627                    break;
   1628                }
   1629                ++fmt;
   1630            }
   1631            text += len;
   1632            if (len >= left) {
   1633                left = SDL_min(left, 1);
   1634            } else {
   1635                left -= len;
   1636            }
   1637        } else {
   1638            if (left > 1) {
   1639                *text = *fmt;
   1640                --left;
   1641            }
   1642            ++fmt;
   1643            ++text;
   1644        }
   1645    }
   1646    if (left > 0) {
   1647        *text = '\0';
   1648    }
   1649    return (int)(text - textstart);
   1650}
   1651#endif /* HAVE_VSNPRINTF */
   1652
   1653/* vi: set ts=4 sw=4 expandtab: */