src/stdlib/SDL_string.c
author Sam Lantinga
Tue, 07 Feb 2006 12:11:33 +0000
changeset 1341 d02b552e5304
parent 1338 604d73db6802
child 1343 d5c4f8f6855e
permissions -rw-r--r--
Configure dynamically generates SDL_config.h
I'm still wrestling with autoheader, but this should work for now...
Fixed lots of build problems with C library support disabled
slouken@1330
     1
/*
slouken@1330
     2
    SDL - Simple DirectMedia Layer
slouken@1330
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@1330
     4
slouken@1330
     5
    This library is free software; you can redistribute it and/or
slouken@1330
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1330
     7
    License as published by the Free Software Foundation; either
slouken@1330
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1330
     9
slouken@1330
    10
    This library is distributed in the hope that it will be useful,
slouken@1330
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1330
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1330
    13
    Lesser General Public License for more details.
slouken@1330
    14
slouken@1330
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1330
    16
    License along with this library; if not, write to the Free Software
slouken@1330
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1330
    18
slouken@1330
    19
    Sam Lantinga
slouken@1330
    20
    slouken@libsdl.org
slouken@1330
    21
*/
slouken@1330
    22
slouken@1330
    23
slouken@1330
    24
/* This file contains portable string manipulation functions for SDL */
slouken@1330
    25
slouken@1330
    26
#include "SDL_types.h"
slouken@1330
    27
#include "SDL_ctype.h"
slouken@1341
    28
#include "SDL_stdlib.h"
slouken@1330
    29
#include "SDL_string.h"
slouken@1330
    30
slouken@1330
    31
slouken@1330
    32
#define isupperhex(X)   (((X) >= 'A') && ((X) <= 'F'))
slouken@1330
    33
#define islowerhex(X)   (((X) >= 'a') && ((X) <= 'f'))
slouken@1330
    34
slouken@1330
    35
#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOL)
slouken@1330
    36
static size_t SDL_ScanLong(const char *text, int radix, long *valuep)
slouken@1330
    37
{
slouken@1330
    38
    const char *textstart = text;
slouken@1330
    39
    long value = 0;
slouken@1330
    40
    SDL_bool negative = SDL_FALSE;
slouken@1330
    41
slouken@1330
    42
    if ( *text == '-' ) {
slouken@1330
    43
        negative = SDL_TRUE;
slouken@1330
    44
        ++text;
slouken@1330
    45
    }
slouken@1330
    46
    if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) {
slouken@1330
    47
        text += 2;
slouken@1330
    48
    }
slouken@1330
    49
    for ( ; ; ) {
slouken@1330
    50
        int v;
slouken@1330
    51
        if ( isdigit(*text) ) {
slouken@1330
    52
            v = *text - '0';
slouken@1330
    53
        } else if ( radix == 16 && isupperhex(*text) ) {
slouken@1330
    54
            v = 10 + (*text - 'A');
slouken@1330
    55
        } else if ( radix == 16 && islowerhex(*text) ) {
slouken@1330
    56
            v = 10 + (*text - 'a');
slouken@1330
    57
        } else {
slouken@1330
    58
            break;
slouken@1330
    59
        }
slouken@1330
    60
        value *= radix;
slouken@1330
    61
        value += v;
slouken@1330
    62
        ++text;
slouken@1330
    63
    }
slouken@1330
    64
    if ( valuep ) {
slouken@1330
    65
        if ( negative && value ) {
slouken@1330
    66
            *valuep = -value;
slouken@1330
    67
        } else {
slouken@1330
    68
            *valuep = value;
slouken@1330
    69
        }
slouken@1330
    70
    }
slouken@1330
    71
    return (text - textstart);
slouken@1330
    72
}
slouken@1330
    73
#endif
slouken@1330
    74
slouken@1330
    75
#ifndef HAVE_SSCANF
slouken@1330
    76
static size_t SDL_ScanUnsignedLong(const char *text, int radix, unsigned long *valuep)
slouken@1330
    77
{
slouken@1330
    78
    const char *textstart = text;
slouken@1330
    79
    unsigned long value = 0;
slouken@1330
    80
slouken@1330
    81
    if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) {
slouken@1330
    82
        text += 2;
slouken@1330
    83
    }
slouken@1330
    84
    for ( ; ; ) {
slouken@1330
    85
        int v;
slouken@1330
    86
        if ( isdigit(*text) ) {
slouken@1330
    87
            v = *text - '0';
slouken@1330
    88
        } else if ( radix == 16 && isupperhex(*text) ) {
slouken@1330
    89
            v = 10 + (*text - 'A');
slouken@1330
    90
        } else if ( radix == 16 && islowerhex(*text) ) {
slouken@1330
    91
            v = 10 + (*text - 'a');
slouken@1330
    92
        } else {
slouken@1330
    93
            break;
slouken@1330
    94
        }
slouken@1330
    95
        value *= radix;
slouken@1330
    96
        value += v;
slouken@1330
    97
        ++text;
slouken@1330
    98
    }
slouken@1330
    99
    if ( valuep ) {
slouken@1330
   100
        *valuep = value;
slouken@1330
   101
    }
slouken@1330
   102
    return (text - textstart);
slouken@1330
   103
}
slouken@1330
   104
#endif
slouken@1330
   105
slouken@1330
   106
#ifdef SDL_HAS_64BIT_TYPE
slouken@1330
   107
#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOLL)
slouken@1330
   108
static size_t SDL_ScanLongLong(const char *text, int radix, Sint64 *valuep)
slouken@1330
   109
{
slouken@1330
   110
    const char *textstart = text;
slouken@1330
   111
    Sint64 value = 0;
slouken@1330
   112
    SDL_bool negative = SDL_FALSE;
slouken@1330
   113
slouken@1330
   114
    if ( *text == '-' ) {
slouken@1330
   115
        negative = SDL_TRUE;
slouken@1330
   116
        ++text;
slouken@1330
   117
    }
slouken@1330
   118
    if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) {
slouken@1330
   119
        text += 2;
slouken@1330
   120
    }
slouken@1330
   121
    for ( ; ; ) {
slouken@1330
   122
        int v;
slouken@1330
   123
        if ( isdigit(*text) ) {
slouken@1330
   124
            v = *text - '0';
slouken@1330
   125
        } else if ( radix == 16 && isupperhex(*text) ) {
slouken@1330
   126
            v = 10 + (*text - 'A');
slouken@1330
   127
        } else if ( radix == 16 && islowerhex(*text) ) {
slouken@1330
   128
            v = 10 + (*text - 'a');
slouken@1330
   129
        } else {
slouken@1330
   130
            break;
slouken@1330
   131
        }
slouken@1330
   132
        value *= radix;
slouken@1330
   133
        value += v;
slouken@1330
   134
        ++text;
slouken@1330
   135
    }
slouken@1330
   136
    if ( valuep ) {
slouken@1330
   137
        if ( negative && value ) {
slouken@1330
   138
            *valuep = -value;
slouken@1330
   139
        } else {
slouken@1330
   140
            *valuep = value;
slouken@1330
   141
        }
slouken@1330
   142
    }
slouken@1330
   143
    return (text - textstart);
slouken@1330
   144
}
slouken@1330
   145
#endif
slouken@1330
   146
slouken@1330
   147
#ifndef HAVE_SSCANF
slouken@1330
   148
static size_t SDL_ScanUnsignedLongLong(const char *text, int radix, Uint64 *valuep)
slouken@1330
   149
{
slouken@1330
   150
    const char *textstart = text;
slouken@1330
   151
    Uint64 value = 0;
slouken@1330
   152
slouken@1330
   153
    if ( radix == 16 && SDL_strncmp(text, "0x", 2) == 0 ) {
slouken@1330
   154
        text += 2;
slouken@1330
   155
    }
slouken@1330
   156
    for ( ; ; ) {
slouken@1330
   157
        int v;
slouken@1330
   158
        if ( isdigit(*text) ) {
slouken@1330
   159
            v = *text - '0';
slouken@1330
   160
        } else if ( radix == 16 && isupperhex(*text) ) {
slouken@1330
   161
            v = 10 + (*text - 'A');
slouken@1330
   162
        } else if ( radix == 16 && islowerhex(*text) ) {
slouken@1330
   163
            v = 10 + (*text - 'a');
slouken@1330
   164
        } else {
slouken@1330
   165
            break;
slouken@1330
   166
        }
slouken@1330
   167
        value *= radix;
slouken@1330
   168
        value += v;
slouken@1330
   169
        ++text;
slouken@1330
   170
    }
slouken@1330
   171
    if ( valuep ) {
slouken@1330
   172
        *valuep = value;
slouken@1330
   173
    }
slouken@1330
   174
    return (text - textstart);
slouken@1330
   175
}
slouken@1330
   176
#endif
slouken@1330
   177
#endif /* SDL_HAS_64BIT_TYPE */
slouken@1330
   178
slouken@1341
   179
#if !defined(HAVE_SSCANF) || !defined(HAVE_STRTOD)
slouken@1330
   180
static size_t SDL_ScanFloat(const char *text, double *valuep)
slouken@1330
   181
{
slouken@1330
   182
    const char *textstart = text;
slouken@1330
   183
    unsigned long lvalue = 0;
slouken@1330
   184
    double value = 0.0;
slouken@1330
   185
    SDL_bool negative = SDL_FALSE;
slouken@1330
   186
slouken@1330
   187
    if ( *text == '-' ) {
slouken@1330
   188
        negative = SDL_TRUE;
slouken@1330
   189
        ++text;
slouken@1330
   190
    }
slouken@1330
   191
    text += SDL_ScanUnsignedLong(text, 10, &lvalue);
slouken@1330
   192
    value += lvalue;
slouken@1330
   193
    if ( *text == '.' ) {
slouken@1330
   194
        int mult = 10;
slouken@1330
   195
        ++text;
slouken@1330
   196
        while ( isdigit(*text) ) {
slouken@1330
   197
            lvalue = *text - '0';
slouken@1330
   198
            value += (double)lvalue / mult;
slouken@1330
   199
            mult *= 10;
slouken@1330
   200
            ++text;
slouken@1330
   201
        }
slouken@1330
   202
    }
slouken@1330
   203
    if ( valuep ) {
slouken@1330
   204
        if ( negative && value ) {
slouken@1330
   205
            *valuep = -value;
slouken@1330
   206
        } else {
slouken@1330
   207
            *valuep = value;
slouken@1330
   208
        }
slouken@1330
   209
    }
slouken@1330
   210
    return (text - textstart);
slouken@1330
   211
}
slouken@1330
   212
#endif
slouken@1330
   213
slouken@1330
   214
#ifndef SDL_memset
slouken@1330
   215
void *SDL_memset(void *dst, int c, size_t len)
slouken@1330
   216
{
slouken@1330
   217
    size_t left = (len % 4);
slouken@1330
   218
    if ( len >= 4 ) {
slouken@1330
   219
        Uint32 value = 0;
slouken@1330
   220
        Uint32 *dstp = (Uint32 *)dst;
slouken@1330
   221
        int i;
slouken@1330
   222
        for (i = 0; i < 4; ++i) {
slouken@1330
   223
            value <<= 8;
slouken@1330
   224
            value |= c;
slouken@1330
   225
        }
slouken@1330
   226
        len /= 4;
slouken@1330
   227
        while ( len-- ) {
slouken@1330
   228
            *dstp++ = value;
slouken@1330
   229
        }
slouken@1330
   230
    }
slouken@1330
   231
    if ( left > 0 ) {
slouken@1330
   232
        Uint8 value = (Uint8)c;
slouken@1330
   233
        Uint8 *dstp = (Uint8 *)dst;
slouken@1330
   234
	switch(left) {
slouken@1330
   235
	case 3:
slouken@1330
   236
            *dstp++ = value;
slouken@1330
   237
	case 2:
slouken@1330
   238
            *dstp++ = value;
slouken@1330
   239
	case 1:
slouken@1330
   240
            *dstp++ = value;
slouken@1330
   241
        }
slouken@1330
   242
    }
slouken@1330
   243
    return dst;
slouken@1330
   244
}
slouken@1330
   245
#endif
slouken@1330
   246
slouken@1330
   247
#ifndef SDL_memcpy
slouken@1330
   248
void *SDL_memcpy(void *dst, const void *src, size_t len)
slouken@1330
   249
{
slouken@1330
   250
    char *srcp = (char *)src;
slouken@1330
   251
    char *dstp = (char *)dst;
slouken@1330
   252
    while ( len-- ) {
slouken@1330
   253
        *dstp++ = *srcp++;
slouken@1330
   254
    }
slouken@1330
   255
    return dst;
slouken@1330
   256
}
slouken@1330
   257
#endif
slouken@1330
   258
slouken@1330
   259
#ifndef SDL_revcpy
slouken@1330
   260
void *SDL_revcpy(void *dst, const void *src, size_t len)
slouken@1330
   261
{
slouken@1330
   262
    char *srcp = (char *)src;
slouken@1330
   263
    char *dstp = (char *)dst;
slouken@1330
   264
    srcp += len;
slouken@1330
   265
    dstp += len;
slouken@1330
   266
    while ( len-- ) {
slouken@1330
   267
        *dstp-- = *srcp--;
slouken@1330
   268
    }
slouken@1330
   269
    return dst;
slouken@1330
   270
}
slouken@1330
   271
#endif
slouken@1330
   272
slouken@1330
   273
#ifndef SDL_memcmp
slouken@1330
   274
int SDL_memcmp(const void *s1, const void *s2, size_t len)
slouken@1330
   275
{
slouken@1330
   276
    char *s1p = (char *)s1;
slouken@1330
   277
    char *s2p = (char *)s2;
slouken@1330
   278
    while ( len-- ) {
slouken@1330
   279
        if ( *s1p != *s2p ) {
slouken@1330
   280
            return (*s1p - *s2p);
slouken@1330
   281
    }
slouken@1330
   282
    ++s1p;
slouken@1330
   283
    ++s2p;
slouken@1330
   284
    }
slouken@1330
   285
    return 0;
slouken@1330
   286
}
slouken@1330
   287
#endif
slouken@1330
   288
slouken@1330
   289
#ifndef HAVE_STRLEN
slouken@1330
   290
size_t SDL_strlen(const char *string)
slouken@1330
   291
{
slouken@1330
   292
    size_t len = 0;
slouken@1330
   293
    while ( *string++ ) {
slouken@1330
   294
        ++len;
slouken@1330
   295
    }
slouken@1330
   296
    return len;
slouken@1330
   297
}
slouken@1330
   298
#endif
slouken@1330
   299
slouken@1330
   300
#ifndef HAVE_STRCPY
slouken@1330
   301
char *SDL_strcpy(char *dst, const char *src)
slouken@1330
   302
{
slouken@1330
   303
    char *dstp = dst;
slouken@1330
   304
    while ( *src ) {
slouken@1330
   305
        *dstp++ = *src++;
slouken@1330
   306
    }
slouken@1330
   307
    *dstp = '\0';
slouken@1330
   308
slouken@1330
   309
    return dst;
slouken@1330
   310
}
slouken@1330
   311
#endif
slouken@1330
   312
slouken@1330
   313
#ifndef HAVE_STRNCPY
slouken@1330
   314
char *SDL_strncpy(char *dst, const char *src, size_t maxlen)
slouken@1330
   315
{
slouken@1330
   316
    char *dstp = dst;
slouken@1330
   317
    while ( maxlen-- && *src ) {
slouken@1330
   318
        *dstp++ = *src++;
slouken@1330
   319
    }
slouken@1330
   320
    *dstp = '\0';
slouken@1330
   321
slouken@1330
   322
    return dst;
slouken@1330
   323
}
slouken@1330
   324
#endif
slouken@1330
   325
slouken@1341
   326
#ifndef HAVE_STRDUP
slouken@1341
   327
char *SDL_strdup(const char *string)
slouken@1341
   328
{
slouken@1341
   329
    size_t len = SDL_strlen(string);
slouken@1341
   330
    char *newstr = SDL_malloc(len+1);
slouken@1341
   331
    if ( newstr ) {
slouken@1341
   332
        SDL_strcpy(newstr, string);
slouken@1341
   333
    }
slouken@1341
   334
    return newstr;
slouken@1341
   335
}
slouken@1341
   336
#endif
slouken@1341
   337
slouken@1330
   338
#ifndef HAVE__STRREV
slouken@1330
   339
char *SDL_strrev(char *string)
slouken@1330
   340
{
slouken@1330
   341
    size_t len = SDL_strlen(string);
slouken@1330
   342
    char *a = &string[0];
slouken@1330
   343
    char *b = &string[len-1];
slouken@1330
   344
    len /= 2;
slouken@1330
   345
    while ( len-- ) {
slouken@1330
   346
        char c = *a;
slouken@1330
   347
        *a++ = *b;
slouken@1330
   348
        *b-- = c;
slouken@1330
   349
    }
slouken@1330
   350
    return string;
slouken@1330
   351
}
slouken@1330
   352
#endif
slouken@1330
   353
slouken@1330
   354
#ifndef HAVE__STRUPR
slouken@1330
   355
char *SDL_strupr(char *string)
slouken@1330
   356
{
slouken@1330
   357
    char *bufp = string;
slouken@1330
   358
    while ( *bufp ) {
slouken@1338
   359
        *bufp = toupper(*bufp);
slouken@1338
   360
	++bufp;
slouken@1330
   361
    }
slouken@1330
   362
    return string;
slouken@1330
   363
}
slouken@1330
   364
#endif
slouken@1330
   365
slouken@1330
   366
#ifndef HAVE__STRLWR
slouken@1330
   367
char *SDL_strlwr(char *string)
slouken@1330
   368
{
slouken@1330
   369
    char *bufp = string;
slouken@1330
   370
    while ( *bufp ) {
slouken@1338
   371
        *bufp = tolower(*bufp);
slouken@1338
   372
	++bufp;
slouken@1330
   373
    }
slouken@1330
   374
    return string;
slouken@1330
   375
}
slouken@1330
   376
#endif
slouken@1330
   377
slouken@1330
   378
#ifndef HAVE_STRCHR
slouken@1330
   379
char *SDL_strchr(const char *string, int c)
slouken@1330
   380
{
slouken@1330
   381
    while ( *string ) {
slouken@1330
   382
        if ( *string == c ) {
slouken@1330
   383
            return (char *)string;
slouken@1330
   384
        }
slouken@1338
   385
	++string;
slouken@1330
   386
    }
slouken@1330
   387
    return NULL;
slouken@1330
   388
}
slouken@1330
   389
#endif
slouken@1330
   390
slouken@1330
   391
#ifndef HAVE_STRRCHR
slouken@1330
   392
char *SDL_strrchr(const char *string, int c)
slouken@1330
   393
{
slouken@1336
   394
    const char *bufp = string + SDL_strlen(string) - 1;
slouken@1330
   395
    while ( bufp >= string ) {
slouken@1330
   396
        if ( *bufp == c ) {
slouken@1330
   397
            return (char *)bufp;
slouken@1330
   398
        }
slouken@1338
   399
	--bufp;
slouken@1330
   400
    }
slouken@1330
   401
    return NULL;
slouken@1330
   402
}
slouken@1330
   403
#endif
slouken@1330
   404
slouken@1330
   405
#ifndef HAVE_STRSTR
slouken@1330
   406
char *SDL_strstr(const char *haystack, const char *needle)
slouken@1330
   407
{
slouken@1336
   408
    size_t length = SDL_strlen(needle);
slouken@1330
   409
    while ( *haystack ) {
slouken@1336
   410
        if ( SDL_strncmp(haystack, needle, length) == 0 ) {
slouken@1330
   411
            return (char *)haystack;
slouken@1330
   412
        }
slouken@1338
   413
	++haystack;
slouken@1330
   414
    }
slouken@1330
   415
    return NULL;
slouken@1330
   416
}
slouken@1330
   417
#endif
slouken@1330
   418
slouken@1330
   419
#if !defined(HAVE__LTOA)  || !defined(HAVE__I64TOA) || \
slouken@1330
   420
    !defined(HAVE__ULTOA) || !defined(HAVE__UI64TOA)
slouken@1330
   421
static const char ntoa_table[] = {
slouken@1330
   422
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
slouken@1330
   423
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
slouken@1330
   424
    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
slouken@1330
   425
    'U', 'V', 'W', 'X', 'Y', 'Z'
slouken@1330
   426
};
slouken@1330
   427
#endif /* ntoa() conversion table */
slouken@1330
   428
slouken@1330
   429
#ifndef HAVE__LTOA
slouken@1330
   430
char *SDL_ltoa(long value, char *string, int radix)
slouken@1330
   431
{
slouken@1330
   432
    char *bufp = string;
slouken@1330
   433
slouken@1330
   434
    if ( value < 0 ) {
slouken@1330
   435
        *bufp++ = '-';
slouken@1330
   436
        value = -value;
slouken@1330
   437
    }
slouken@1330
   438
    if ( value ) {
slouken@1330
   439
        while ( value > 0 ) {
slouken@1330
   440
            *bufp++ = ntoa_table[value % radix];
slouken@1330
   441
            value /= radix;
slouken@1330
   442
        }
slouken@1330
   443
    } else {
slouken@1330
   444
        *bufp++ = '0';
slouken@1330
   445
    }
slouken@1330
   446
    *bufp = '\0';
slouken@1330
   447
slouken@1330
   448
    /* The numbers went into the string backwards. :) */
slouken@1330
   449
    if ( *string == '-' ) {
slouken@1336
   450
        SDL_strrev(string+1);
slouken@1330
   451
    } else {
slouken@1336
   452
        SDL_strrev(string);
slouken@1330
   453
    }
slouken@1330
   454
slouken@1330
   455
    return string;
slouken@1330
   456
}
slouken@1330
   457
#endif
slouken@1330
   458
slouken@1330
   459
#ifndef HAVE__ULTOA
slouken@1330
   460
char *SDL_ultoa(unsigned long value, char *string, int radix)
slouken@1330
   461
{
slouken@1330
   462
    char *bufp = string;
slouken@1330
   463
slouken@1330
   464
    if ( value ) {
slouken@1330
   465
        while ( value > 0 ) {
slouken@1330
   466
            *bufp++ = ntoa_table[value % radix];
slouken@1330
   467
            value /= radix;
slouken@1330
   468
        }
slouken@1330
   469
    } else {
slouken@1330
   470
        *bufp++ = '0';
slouken@1330
   471
    }
slouken@1330
   472
    *bufp = '\0';
slouken@1330
   473
slouken@1330
   474
    /* The numbers went into the string backwards. :) */
slouken@1336
   475
    SDL_strrev(string);
slouken@1330
   476
slouken@1330
   477
    return string;
slouken@1330
   478
}
slouken@1330
   479
#endif
slouken@1330
   480
slouken@1330
   481
#ifndef HAVE_STRTOL
slouken@1330
   482
long SDL_strtol(const char *string, char **endp, int base)
slouken@1330
   483
{
slouken@1330
   484
    size_t len;
slouken@1330
   485
    long value;
slouken@1330
   486
slouken@1330
   487
    len = SDL_ScanLong(string, base ? base : 10, &value);
slouken@1330
   488
    if ( endp ) {
slouken@1330
   489
        *endp = (char *)string + len;
slouken@1330
   490
    }
slouken@1330
   491
    return value;
slouken@1330
   492
}
slouken@1330
   493
#endif
slouken@1330
   494
slouken@1330
   495
#ifdef SDL_HAS_64BIT_TYPE
slouken@1330
   496
slouken@1330
   497
#ifndef HAVE__I64TOA
slouken@1330
   498
char *SDL_lltoa(Sint64 value, char *string, int radix)
slouken@1330
   499
{
slouken@1330
   500
    char *bufp = string;
slouken@1330
   501
slouken@1330
   502
    if ( value < 0 ) {
slouken@1330
   503
        *bufp++ = '-';
slouken@1330
   504
        value = -value;
slouken@1330
   505
    }
slouken@1330
   506
    if ( value ) {
slouken@1330
   507
        while ( value > 0 ) {
slouken@1330
   508
            *bufp++ = ntoa_table[value % radix];
slouken@1330
   509
            value /= radix;
slouken@1330
   510
        }
slouken@1330
   511
    } else {
slouken@1330
   512
        *bufp++ = '0';
slouken@1330
   513
    }
slouken@1330
   514
    *bufp = '\0';
slouken@1330
   515
slouken@1330
   516
    /* The numbers went into the string backwards. :) */
slouken@1330
   517
    if ( *string == '-' ) {
slouken@1336
   518
        SDL_strrev(string+1);
slouken@1330
   519
    } else {
slouken@1336
   520
        SDL_strrev(string);
slouken@1330
   521
    }
slouken@1330
   522
slouken@1330
   523
    return string;
slouken@1330
   524
}
slouken@1330
   525
#endif
slouken@1330
   526
slouken@1330
   527
#ifndef HAVE__UI64TOA
slouken@1330
   528
char *SDL_ulltoa(Uint64 value, char *string, int radix)
slouken@1330
   529
{
slouken@1330
   530
    char *bufp = string;
slouken@1330
   531
slouken@1330
   532
    if ( value ) {
slouken@1330
   533
        while ( value > 0 ) {
slouken@1330
   534
            *bufp++ = ntoa_table[value % radix];
slouken@1330
   535
            value /= radix;
slouken@1330
   536
        }
slouken@1330
   537
    } else {
slouken@1330
   538
        *bufp++ = '0';
slouken@1330
   539
    }
slouken@1330
   540
    *bufp = '\0';
slouken@1330
   541
slouken@1330
   542
    /* The numbers went into the string backwards. :) */
slouken@1336
   543
    SDL_strrev(string);
slouken@1330
   544
slouken@1330
   545
    return string;
slouken@1330
   546
}
slouken@1330
   547
#endif
slouken@1330
   548
slouken@1330
   549
#ifndef HAVE_STRTOLL
slouken@1330
   550
Sint64 SDL_strtoll(const char *string, char **endp, int base)
slouken@1330
   551
{
slouken@1330
   552
    size_t len;
slouken@1330
   553
    Sint64 value;
slouken@1330
   554
slouken@1330
   555
    len = SDL_ScanLongLong(string, base ? base : 10, &value);
slouken@1330
   556
    if ( endp ) {
slouken@1330
   557
        *endp = (char *)string + len;
slouken@1330
   558
    }
slouken@1330
   559
    return value;
slouken@1330
   560
}
slouken@1330
   561
#endif
slouken@1330
   562
slouken@1330
   563
#endif /* SDL_HAS_64BIT_TYPE */
slouken@1330
   564
slouken@1341
   565
#ifndef HAVE_STRTOD
slouken@1341
   566
double SDL_strtod(const char *string, char **endp)
slouken@1341
   567
{
slouken@1341
   568
    size_t len;
slouken@1341
   569
    double value;
slouken@1341
   570
slouken@1341
   571
    len = SDL_ScanFloat(string, &value);
slouken@1341
   572
    if ( endp ) {
slouken@1341
   573
        *endp = (char *)string + len;
slouken@1341
   574
    }
slouken@1341
   575
    return value;
slouken@1341
   576
}
slouken@1341
   577
#endif
slouken@1341
   578
slouken@1330
   579
#ifndef HAVE_STRCMP
slouken@1330
   580
int SDL_strcmp(const char *str1, const char *str2)
slouken@1330
   581
{
slouken@1330
   582
    while (*str1 && *str2) {
slouken@1330
   583
        if ( *str1 != *str2 )
slouken@1330
   584
            break;
slouken@1330
   585
        ++str1;
slouken@1330
   586
        ++str2;
slouken@1330
   587
    }
slouken@1330
   588
    return (int)((unsigned char)*str1 - (unsigned char)*str2);
slouken@1330
   589
}
slouken@1330
   590
#endif
slouken@1330
   591
slouken@1330
   592
#ifndef HAVE_STRNCMP
slouken@1330
   593
int SDL_strncmp(const char *str1, const char *str2, size_t maxlen)
slouken@1330
   594
{
slouken@1330
   595
    while ( *str1 && *str2 && maxlen ) {
slouken@1330
   596
        if ( *str1 != *str2 )
slouken@1330
   597
            break;
slouken@1330
   598
        ++str1;
slouken@1330
   599
        ++str2;
slouken@1330
   600
        --maxlen;
slouken@1330
   601
    }
slouken@1330
   602
    if ( ! maxlen ) {
slouken@1330
   603
        return 0;
slouken@1330
   604
    }
slouken@1330
   605
    return (int)((unsigned char)*str1 - (unsigned char)*str2);
slouken@1330
   606
}
slouken@1330
   607
#endif
slouken@1330
   608
slouken@1330
   609
#ifndef HAVE_STRCASECMP
slouken@1330
   610
int SDL_strcasecmp(const char *str1, const char *str2)
slouken@1330
   611
{
slouken@1330
   612
    char a = 0;
slouken@1330
   613
    char b = 0;
slouken@1330
   614
    while (*str1 && *str2) {
slouken@1330
   615
        a = tolower(*str1);
slouken@1330
   616
        b = tolower(*str2);
slouken@1330
   617
        if ( a != b )
slouken@1330
   618
            break;
slouken@1330
   619
        ++str1;
slouken@1330
   620
        ++str2;
slouken@1330
   621
    }
slouken@1330
   622
    return (int)((unsigned char)a - (unsigned char)b);
slouken@1330
   623
}
slouken@1330
   624
#endif
slouken@1330
   625
slouken@1330
   626
#ifndef HAVE_SSCANF
slouken@1330
   627
int SDL_sscanf(const char *text, const char *fmt, ...)
slouken@1330
   628
{
slouken@1330
   629
    va_list ap;
slouken@1330
   630
    int retval = 0;
slouken@1330
   631
slouken@1330
   632
    va_start(ap, fmt);
slouken@1330
   633
    while ( *fmt ) {
slouken@1330
   634
        if ( *fmt == ' ' ) {
slouken@1330
   635
            while ( isspace(*text) ) {
slouken@1330
   636
                ++text;
slouken@1330
   637
            }
slouken@1330
   638
            ++fmt;
slouken@1330
   639
            continue;
slouken@1330
   640
        }
slouken@1330
   641
        if ( *fmt == '%' ) {
slouken@1330
   642
            SDL_bool done = SDL_FALSE;
slouken@1330
   643
            long count = 0;
slouken@1330
   644
            int radix = 10;
slouken@1330
   645
            enum {
slouken@1330
   646
                DO_SHORT,
slouken@1330
   647
                DO_INT,
slouken@1330
   648
                DO_LONG,
slouken@1330
   649
                DO_LONGLONG
slouken@1330
   650
            } inttype = DO_INT;
slouken@1330
   651
            SDL_bool suppress = SDL_FALSE;
slouken@1330
   652
slouken@1330
   653
            ++fmt;
slouken@1330
   654
            if ( *fmt == '%' ) {
slouken@1330
   655
                if ( *text == '%' ) {
slouken@1330
   656
                    ++text;
slouken@1330
   657
                    ++fmt;
slouken@1330
   658
                    continue;
slouken@1330
   659
                }
slouken@1330
   660
                break;
slouken@1330
   661
            }
slouken@1330
   662
            if ( *fmt == '*' ) {
slouken@1330
   663
                suppress = SDL_TRUE;
slouken@1330
   664
                ++fmt;
slouken@1330
   665
            }
slouken@1330
   666
            fmt += SDL_ScanLong(fmt, 10, &count);
slouken@1330
   667
slouken@1330
   668
            if ( *fmt == 'c' ) {
slouken@1330
   669
                if ( ! count ) {
slouken@1330
   670
                    count = 1;
slouken@1330
   671
                }
slouken@1330
   672
                if ( suppress ) {
slouken@1330
   673
                    while ( count-- ) {
slouken@1330
   674
                        ++text;
slouken@1330
   675
                    }
slouken@1330
   676
                } else {
slouken@1330
   677
                    char *valuep = va_arg(ap, char*);
slouken@1330
   678
                    while ( count-- ) {
slouken@1330
   679
                        *valuep++ = *text++;
slouken@1330
   680
                    }
slouken@1330
   681
                    ++retval;
slouken@1330
   682
                }
slouken@1330
   683
                continue;
slouken@1330
   684
            }
slouken@1330
   685
slouken@1330
   686
            while ( isspace(*text) ) {
slouken@1330
   687
                ++text;
slouken@1330
   688
            }
slouken@1330
   689
slouken@1330
   690
            /* FIXME: implement more of the format specifiers */
slouken@1330
   691
            while (!done) {
slouken@1330
   692
                switch(*fmt) {
slouken@1330
   693
                    case '*':
slouken@1330
   694
                        suppress = SDL_TRUE;
slouken@1330
   695
                        break;
slouken@1330
   696
                    case 'h':
slouken@1330
   697
                        if ( inttype > DO_SHORT ) {
slouken@1330
   698
                            ++inttype;
slouken@1330
   699
                        }
slouken@1330
   700
                        break;
slouken@1330
   701
                    case 'l':
slouken@1330
   702
                        if ( inttype < DO_LONGLONG ) {
slouken@1330
   703
                            ++inttype;
slouken@1330
   704
                        }
slouken@1330
   705
                        break;
slouken@1330
   706
                    case 'I':
slouken@1330
   707
                        if ( SDL_strncmp(fmt, "I64", 3) == 0 ) {
slouken@1330
   708
                            fmt += 2;
slouken@1330
   709
                            inttype = DO_LONGLONG;
slouken@1330
   710
                        }
slouken@1330
   711
                        break;
slouken@1330
   712
                    case 'i':
slouken@1330
   713
                        {
slouken@1330
   714
                            int index = 0;
slouken@1330
   715
                            if ( text[index] == '-' ) {
slouken@1330
   716
                                ++index;
slouken@1330
   717
                            }
slouken@1330
   718
                            if ( text[index] == '0' ) {
slouken@1330
   719
                                if ( tolower(text[index+1]) == 'x' ) {
slouken@1330
   720
                                    radix = 16;
slouken@1330
   721
                                } else {
slouken@1330
   722
                                    radix = 8;
slouken@1330
   723
                                }
slouken@1330
   724
                            }
slouken@1330
   725
                        }
slouken@1330
   726
                        /* Fall through to %d handling */
slouken@1330
   727
                    case 'd':
slouken@1330
   728
#ifdef SDL_HAS_64BIT_TYPE
slouken@1330
   729
                        if ( inttype == DO_LONGLONG ) {
slouken@1330
   730
                            Sint64 value;
slouken@1330
   731
                            text += SDL_ScanLongLong(text, radix, &value);
slouken@1330
   732
                            if ( ! suppress ) {
slouken@1330
   733
                                Sint64 *valuep = va_arg(ap, Sint64*);
slouken@1330
   734
                                *valuep = value;
slouken@1330
   735
                                ++retval;
slouken@1330
   736
                            }
slouken@1330
   737
                        }
slouken@1330
   738
                        else
slouken@1330
   739
#endif /* SDL_HAS_64BIT_TYPE */
slouken@1330
   740
                        {
slouken@1330
   741
                            long value;
slouken@1330
   742
                            text += SDL_ScanLong(text, radix, &value);
slouken@1330
   743
                            if ( ! suppress ) {
slouken@1330
   744
                                switch (inttype) {
slouken@1330
   745
                                    case DO_SHORT:
slouken@1330
   746
                                        { short* valuep = va_arg(ap, short*);
slouken@1330
   747
                                            *valuep = (short)value;
slouken@1330
   748
                                        }
slouken@1330
   749
                                        break;
slouken@1330
   750
                                    case DO_INT:
slouken@1330
   751
                                        { int* valuep = va_arg(ap, int*);
slouken@1330
   752
                                            *valuep = (int)value;
slouken@1330
   753
                                        }
slouken@1330
   754
                                        break;
slouken@1330
   755
                                    case DO_LONG:
slouken@1330
   756
                                        { long* valuep = va_arg(ap, long*);
slouken@1330
   757
                                            *valuep = value;
slouken@1330
   758
                                        }
slouken@1330
   759
                                        break;
slouken@1330
   760
                                    case DO_LONGLONG:
slouken@1330
   761
                                        /* Handled above */
slouken@1330
   762
                                        break;
slouken@1330
   763
                                }
slouken@1330
   764
                                ++retval;
slouken@1330
   765
                            }
slouken@1330
   766
                        }
slouken@1330
   767
                        done = SDL_TRUE;
slouken@1330
   768
                        break;
slouken@1330
   769
                    case 'o':
slouken@1330
   770
                        if ( radix == 10 ) {
slouken@1330
   771
                            radix = 8;
slouken@1330
   772
                        }
slouken@1330
   773
                        /* Fall through to unsigned handling */
slouken@1330
   774
                    case 'x':
slouken@1330
   775
                    case 'X':
slouken@1330
   776
                        if ( radix == 10 ) {
slouken@1330
   777
                            radix = 16;
slouken@1330
   778
                        }
slouken@1330
   779
                        /* Fall through to unsigned handling */
slouken@1330
   780
                    case 'u':
slouken@1330
   781
#ifdef SDL_HAS_64BIT_TYPE
slouken@1330
   782
                        if ( inttype == DO_LONGLONG ) {
slouken@1330
   783
                            Uint64 value;
slouken@1330
   784
                            text += SDL_ScanUnsignedLongLong(text, radix, &value);
slouken@1330
   785
                            if ( ! suppress ) {
slouken@1330
   786
                                Uint64 *valuep = va_arg(ap, Uint64*);
slouken@1330
   787
                                *valuep = value;
slouken@1330
   788
                                ++retval;
slouken@1330
   789
                            }
slouken@1330
   790
                        }
slouken@1330
   791
                        else
slouken@1330
   792
#endif /* SDL_HAS_64BIT_TYPE */
slouken@1330
   793
                        {
slouken@1330
   794
                            unsigned long value;
slouken@1330
   795
                            text += SDL_ScanUnsignedLong(text, radix, &value);
slouken@1330
   796
                            if ( ! suppress ) {
slouken@1330
   797
                                switch (inttype) {
slouken@1330
   798
                                    case DO_SHORT:
slouken@1330
   799
                                        { short* valuep = va_arg(ap, short*);
slouken@1330
   800
                                            *valuep = (short)value;
slouken@1330
   801
                                        }
slouken@1330
   802
                                        break;
slouken@1330
   803
                                    case DO_INT:
slouken@1330
   804
                                        { int* valuep = va_arg(ap, int*);
slouken@1330
   805
                                            *valuep = (int)value;
slouken@1330
   806
                                        }
slouken@1330
   807
                                        break;
slouken@1330
   808
                                    case DO_LONG:
slouken@1330
   809
                                        { long* valuep = va_arg(ap, long*);
slouken@1330
   810
                                            *valuep = value;
slouken@1330
   811
                                        }
slouken@1330
   812
                                        break;
slouken@1330
   813
                                    case DO_LONGLONG:
slouken@1330
   814
                                        /* Handled above */
slouken@1330
   815
                                        break;
slouken@1330
   816
                                }
slouken@1330
   817
                                ++retval;
slouken@1330
   818
                            }
slouken@1330
   819
                        }
slouken@1330
   820
                        done = SDL_TRUE;
slouken@1330
   821
                        break;
slouken@1330
   822
                    case 'p':
slouken@1330
   823
                        {
slouken@1330
   824
                            unsigned long value;
slouken@1330
   825
                            text += SDL_ScanUnsignedLong(text, 16, &value);
slouken@1330
   826
                            if ( ! suppress ) {
slouken@1330
   827
                                void** valuep = va_arg(ap, void**);
slouken@1330
   828
                                *valuep = (void*)value;
slouken@1330
   829
                                ++retval;
slouken@1330
   830
                            }
slouken@1330
   831
                        }
slouken@1330
   832
                        done = SDL_TRUE;
slouken@1330
   833
                        break;
slouken@1330
   834
                    case 'f':
slouken@1330
   835
                        {
slouken@1330
   836
                            double value;
slouken@1330
   837
                            text += SDL_ScanFloat(text, &value);
slouken@1330
   838
                            if ( ! suppress ) {
slouken@1330
   839
                                float* valuep = va_arg(ap, float*);
slouken@1330
   840
                                *valuep = (float)value;
slouken@1330
   841
                                ++retval;
slouken@1330
   842
                            }
slouken@1330
   843
                        }
slouken@1330
   844
                        done = SDL_TRUE;
slouken@1330
   845
                        break;
slouken@1330
   846
                    case 's':
slouken@1330
   847
                        if ( suppress ) {
slouken@1330
   848
                            while ( !isspace(*text) ) {
slouken@1330
   849
                                ++text;
slouken@1330
   850
                                if ( count ) {
slouken@1330
   851
                                    if ( --count == 0 ) {
slouken@1330
   852
                                        break;
slouken@1330
   853
                                    }
slouken@1330
   854
                                }
slouken@1330
   855
                            }
slouken@1330
   856
                        } else {
slouken@1330
   857
                            char *valuep = va_arg(ap, char*);
slouken@1330
   858
                            while ( !isspace(*text) ) {
slouken@1330
   859
                                *valuep++ = *text++;
slouken@1330
   860
                                if ( count ) {
slouken@1330
   861
                                    if ( --count == 0 ) {
slouken@1330
   862
                                        break;
slouken@1330
   863
                                    }
slouken@1330
   864
                                }
slouken@1330
   865
                            }
slouken@1330
   866
                            *valuep = '\0';
slouken@1330
   867
                            ++retval;
slouken@1330
   868
                        }
slouken@1330
   869
                        done = SDL_TRUE;
slouken@1330
   870
                        break;
slouken@1330
   871
                    default:
slouken@1330
   872
                        done = SDL_TRUE;
slouken@1330
   873
                        break;
slouken@1330
   874
                }
slouken@1330
   875
                ++fmt;
slouken@1330
   876
            }
slouken@1330
   877
            continue;
slouken@1330
   878
        }
slouken@1330
   879
        if ( *text == *fmt ) {
slouken@1330
   880
            ++text;
slouken@1330
   881
            ++fmt;
slouken@1330
   882
            continue;
slouken@1330
   883
        }
slouken@1330
   884
        /* Text didn't match format specifier */
slouken@1330
   885
        break;
slouken@1330
   886
    }
slouken@1330
   887
    va_end(ap);
slouken@1330
   888
slouken@1330
   889
    return retval;
slouken@1330
   890
}
slouken@1330
   891
#endif
slouken@1330
   892
slouken@1330
   893
#ifndef HAVE_SNPRINTF
slouken@1330
   894
int SDL_snprintf(char *text, size_t maxlen, const char *fmt, ...)
slouken@1330
   895
{
slouken@1330
   896
    va_list ap;
slouken@1330
   897
    int retval;
slouken@1330
   898
slouken@1330
   899
    va_start(ap, fmt);
slouken@1330
   900
    retval = SDL_vsnprintf(text, maxlen, fmt, ap);
slouken@1330
   901
    va_end(ap);
slouken@1330
   902
slouken@1330
   903
    return retval;
slouken@1330
   904
}
slouken@1330
   905
#endif
slouken@1330
   906
slouken@1330
   907
#ifndef HAVE_VSNPRINTF
slouken@1330
   908
static size_t SDL_PrintLong(char *text, long value, int radix, size_t maxlen)
slouken@1330
   909
{
slouken@1330
   910
    char num[130];
slouken@1330
   911
    size_t size;
slouken@1330
   912
slouken@1336
   913
    SDL_ltoa(value, num, radix);
slouken@1330
   914
    size = SDL_strlen(num);
slouken@1330
   915
    if ( size > maxlen ) {
slouken@1330
   916
        size = maxlen;
slouken@1330
   917
    }
slouken@1336
   918
    SDL_strncpy(text, num, size);
slouken@1330
   919
slouken@1330
   920
    return size;
slouken@1330
   921
}
slouken@1330
   922
static size_t SDL_PrintUnsignedLong(char *text, unsigned long value, int radix, size_t maxlen)
slouken@1330
   923
{
slouken@1330
   924
    char num[130];
slouken@1330
   925
    size_t size;
slouken@1330
   926
slouken@1336
   927
    SDL_ultoa(value, num, radix);
slouken@1330
   928
    size = SDL_strlen(num);
slouken@1330
   929
    if ( size > maxlen ) {
slouken@1330
   930
        size = maxlen;
slouken@1330
   931
    }
slouken@1336
   932
    SDL_strncpy(text, num, size);
slouken@1330
   933
slouken@1330
   934
    return size;
slouken@1330
   935
}
slouken@1330
   936
#ifdef SDL_HAS_64BIT_TYPE
slouken@1330
   937
static size_t SDL_PrintLongLong(char *text, Sint64 value, int radix, size_t maxlen)
slouken@1330
   938
{
slouken@1330
   939
    char num[130];
slouken@1330
   940
    size_t size;
slouken@1330
   941
slouken@1336
   942
    SDL_lltoa(value, num, radix);
slouken@1330
   943
    size = SDL_strlen(num);
slouken@1330
   944
    if ( size > maxlen ) {
slouken@1330
   945
        size = maxlen;
slouken@1330
   946
    }
slouken@1336
   947
    SDL_strncpy(text, num, size);
slouken@1330
   948
slouken@1330
   949
    return size;
slouken@1330
   950
}
slouken@1330
   951
static size_t SDL_PrintUnsignedLongLong(char *text, Uint64 value, int radix, size_t maxlen)
slouken@1330
   952
{
slouken@1330
   953
    char num[130];
slouken@1330
   954
    size_t size;
slouken@1330
   955
slouken@1336
   956
    SDL_ulltoa(value, num, radix);
slouken@1330
   957
    size = SDL_strlen(num);
slouken@1330
   958
    if ( size > maxlen ) {
slouken@1330
   959
        size = maxlen;
slouken@1330
   960
    }
slouken@1336
   961
    SDL_strncpy(text, num, size);
slouken@1330
   962
slouken@1330
   963
    return size;
slouken@1330
   964
}
slouken@1330
   965
#endif /* SDL_HAS_64BIT_TYPE */
slouken@1330
   966
static size_t SDL_PrintFloat(char *text, double arg, size_t maxlen)
slouken@1330
   967
{
slouken@1330
   968
    char *textstart = text;
slouken@1330
   969
    if ( arg ) {
slouken@1330
   970
        /* This isn't especially accurate, but hey, it's easy. :) */
slouken@1330
   971
        const double precision = 0.00000001;
slouken@1330
   972
        size_t len;
slouken@1330
   973
        unsigned long value;
slouken@1330
   974
slouken@1330
   975
        if ( arg < 0 ) {
slouken@1330
   976
            *text++ = '-';
slouken@1330
   977
            --maxlen;
slouken@1330
   978
            arg = -arg;
slouken@1330
   979
        }
slouken@1330
   980
        value = (unsigned long)arg;
slouken@1330
   981
        len = SDL_PrintUnsignedLong(text, value, 10, maxlen);
slouken@1330
   982
        text += len;
slouken@1330
   983
        maxlen -= len;
slouken@1330
   984
        arg -= value;
slouken@1330
   985
        if ( arg > precision && maxlen ) {
slouken@1330
   986
            int mult = 10;
slouken@1330
   987
            *text++ = '.';
slouken@1330
   988
            while ( (arg > precision) && maxlen ) {
slouken@1330
   989
                value = (unsigned long)(arg * mult);
slouken@1330
   990
                len = SDL_PrintUnsignedLong(text, value, 10, maxlen);
slouken@1330
   991
                text += len;
slouken@1330
   992
                maxlen -= len;
slouken@1330
   993
                arg -= (double)value / mult;
slouken@1330
   994
                mult *= 10;
slouken@1330
   995
            }
slouken@1330
   996
        }
slouken@1330
   997
    } else {
slouken@1330
   998
        *text++ = '0';
slouken@1330
   999
    }
slouken@1330
  1000
    return (text - textstart);
slouken@1330
  1001
}
slouken@1330
  1002
static size_t SDL_PrintString(char *text, const char *string, size_t maxlen)
slouken@1330
  1003
{
slouken@1330
  1004
    char *textstart = text;
slouken@1330
  1005
    while ( *string && maxlen-- ) {
slouken@1330
  1006
        *text++ = *string++;
slouken@1330
  1007
    }
slouken@1330
  1008
    return (text - textstart);
slouken@1330
  1009
}
slouken@1330
  1010
int  SDL_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap)
slouken@1330
  1011
{
slouken@1330
  1012
    char *textstart = text;
slouken@1330
  1013
    if ( maxlen <= 0 ) {
slouken@1330
  1014
        return 0;
slouken@1330
  1015
    }
slouken@1330
  1016
    --maxlen; /* For the trailing '\0' */
slouken@1330
  1017
    while ( *fmt && maxlen ) {
slouken@1330
  1018
        if ( *fmt == '%' ) {
slouken@1330
  1019
            SDL_bool done = SDL_FALSE;
slouken@1330
  1020
            size_t len = 0;
slouken@1330
  1021
            SDL_bool do_lowercase = SDL_FALSE;
slouken@1330
  1022
            int radix = 10;
slouken@1330
  1023
            enum {
slouken@1330
  1024
                DO_INT,
slouken@1330
  1025
                DO_LONG,
slouken@1330
  1026
                DO_LONGLONG
slouken@1330
  1027
            } inttype = DO_INT;
slouken@1330
  1028
slouken@1330
  1029
            ++fmt;
slouken@1330
  1030
            /* FIXME: implement more of the format specifiers */
slouken@1330
  1031
            while (!done) {
slouken@1330
  1032
                switch(*fmt) {
slouken@1330
  1033
                    case '%':
slouken@1330
  1034
                        *text = '%';
slouken@1330
  1035
                        len = 1;
slouken@1330
  1036
                        done = SDL_TRUE;
slouken@1330
  1037
                        break;
slouken@1330
  1038
                    case 'c':
slouken@1330
  1039
                        /* char is promoted to int when passed through (...) */
slouken@1330
  1040
                        *text = (char)va_arg(ap, int);
slouken@1330
  1041
                        len = 1;
slouken@1330
  1042
                        done = SDL_TRUE;
slouken@1330
  1043
                        break;
slouken@1330
  1044
                    case 'h':
slouken@1330
  1045
                        /* short is promoted to int when passed through (...) */
slouken@1330
  1046
                        break;
slouken@1330
  1047
                    case 'l':
slouken@1330
  1048
                        if ( inttype < DO_LONGLONG ) {
slouken@1330
  1049
                            ++inttype;
slouken@1330
  1050
                        }
slouken@1330
  1051
                        break;
slouken@1330
  1052
                    case 'I':
slouken@1330
  1053
                        if ( SDL_strncmp(fmt, "I64", 3) == 0 ) {
slouken@1330
  1054
                            fmt += 2;
slouken@1330
  1055
                            inttype = DO_LONGLONG;
slouken@1330
  1056
                        }
slouken@1330
  1057
                        break;
slouken@1330
  1058
                    case 'i':
slouken@1330
  1059
                    case 'd':
slouken@1330
  1060
                        switch (inttype) {
slouken@1330
  1061
                            case DO_INT:
slouken@1330
  1062
                                len = SDL_PrintLong(text, (long)va_arg(ap, int), radix, maxlen);
slouken@1330
  1063
                                break;
slouken@1330
  1064
                            case DO_LONG:
slouken@1330
  1065
                                len = SDL_PrintLong(text, va_arg(ap, long), radix, maxlen);
slouken@1330
  1066
                                break;
slouken@1330
  1067
                            case DO_LONGLONG:
slouken@1330
  1068
#ifdef SDL_HAS_64BIT_TYPE
slouken@1330
  1069
                                len = SDL_PrintLongLong(text, va_arg(ap, Sint64), radix, maxlen);
slouken@1330
  1070
#else
slouken@1330
  1071
                                len = SDL_PrintLong(text, va_arg(ap, long), radix, maxlen);
slouken@1330
  1072
#endif
slouken@1330
  1073
                                break;
slouken@1330
  1074
                        }
slouken@1330
  1075
                        done = SDL_TRUE;
slouken@1330
  1076
                        break;
slouken@1330
  1077
                    case 'p':
slouken@1330
  1078
                    case 'x':
slouken@1330
  1079
                        do_lowercase = SDL_TRUE;
slouken@1330
  1080
                        /* Fall through to 'X' handling */
slouken@1330
  1081
                    case 'X':
slouken@1330
  1082
                        if ( radix == 10 ) {
slouken@1330
  1083
                            radix = 16;
slouken@1330
  1084
                        }
slouken@1330
  1085
                        if ( *fmt == 'p' ) {
slouken@1330
  1086
                            inttype = DO_LONG;
slouken@1330
  1087
                        }
slouken@1330
  1088
                        /* Fall through to unsigned handling */
slouken@1330
  1089
                    case 'o':
slouken@1330
  1090
                        if ( radix == 10 ) {
slouken@1330
  1091
                            radix = 8;
slouken@1330
  1092
                        }
slouken@1330
  1093
                        /* Fall through to unsigned handling */
slouken@1330
  1094
                    case 'u':
slouken@1330
  1095
                        switch (inttype) {
slouken@1330
  1096
                            case DO_INT:
slouken@1330
  1097
                                len = SDL_PrintUnsignedLong(text, (unsigned long)va_arg(ap, unsigned int), radix, maxlen);
slouken@1330
  1098
                                break;
slouken@1330
  1099
                            case DO_LONG:
slouken@1330
  1100
                                len = SDL_PrintUnsignedLong(text, va_arg(ap, unsigned long), radix, maxlen);
slouken@1330
  1101
                                break;
slouken@1330
  1102
                            case DO_LONGLONG:
slouken@1330
  1103
#ifdef SDL_HAS_64BIT_TYPE
slouken@1330
  1104
                                len = SDL_PrintUnsignedLongLong(text, va_arg(ap, Uint64), radix, maxlen);
slouken@1330
  1105
#else
slouken@1330
  1106
                                len = SDL_PrintUnsignedLong(text, va_arg(ap, unsigned long), radix, maxlen);
slouken@1330
  1107
#endif
slouken@1330
  1108
                                break;
slouken@1330
  1109
                        }
slouken@1330
  1110
                        if ( do_lowercase ) {
slouken@1336
  1111
                            SDL_strlwr(text);
slouken@1330
  1112
                        }
slouken@1330
  1113
                        done = SDL_TRUE;
slouken@1330
  1114
                        break;
slouken@1330
  1115
                    case 'f':
slouken@1330
  1116
                        len = SDL_PrintFloat(text, va_arg(ap, double), maxlen);
slouken@1330
  1117
                        done = SDL_TRUE;
slouken@1330
  1118
                        break;
slouken@1330
  1119
                    case 's':
slouken@1330
  1120
                        len = SDL_PrintString(text, va_arg(ap, char*), maxlen);
slouken@1330
  1121
                        done = SDL_TRUE;
slouken@1330
  1122
                        break;
slouken@1330
  1123
                    default:
slouken@1330
  1124
                        done = SDL_TRUE;
slouken@1330
  1125
                        break;
slouken@1330
  1126
                }
slouken@1330
  1127
                ++fmt;
slouken@1330
  1128
            }
slouken@1330
  1129
            text += len;
slouken@1330
  1130
            maxlen -= len;
slouken@1330
  1131
        } else {
slouken@1330
  1132
            *text++ = *fmt++;
slouken@1330
  1133
            --maxlen;
slouken@1330
  1134
        }
slouken@1330
  1135
    }
slouken@1330
  1136
    *text = '\0';
slouken@1330
  1137
slouken@1330
  1138
    return (text - textstart);
slouken@1330
  1139
}
slouken@1330
  1140
#endif