--- quake3/game/bg_lib.c Tue Feb 13 03:05:00 2001 +++ fi/game/bg_lib.c Thu Jun 27 03:10:28 2002 @@ -45,7 +45,7 @@ static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; #endif static const char rcsid[] = - "$Id: bg_lib.c,v 1.2 2001/02/13 11:05:00 quake3 Exp $"; + "$Id: bg_lib.c,v 1.5 2001/10/13 06:34:46 quake3 Exp $"; #endif /* LIBC_SCCS and not lint */ //typedef int cmp_t(const void *, const void *); @@ -264,7 +264,7 @@ return (char *)0; } -#if !defined ( _MSC_VER ) && ! defined ( __linux__ ) || defined (Q3_VM) +#if !defined ( _MSC_VER ) && ! defined ( __linux__ ) int tolower( int c ) { if ( c >= 'A' && c <= 'Z' ) { @@ -903,7 +903,7 @@ } -#if !defined( _MSC_VER ) && !defined( __linux__ ) || defined (Q3_VM) +#if !defined( _MSC_VER ) && !defined( __linux__ ) int atoi( const char *string ) { int sign; @@ -1022,16 +1022,29 @@ #define SHORTINT 0x00000040 /* short integer */ #define ZEROPAD 0x00000080 /* zero (as opposed to blank) pad */ #define FPT 0x00000100 /* floating point number */ +#define UNSIGNED 0x00000200 /* unsigned integer. */ #define to_digit(c) ((c) - '0') #define is_digit(c) ((unsigned)to_digit(c) <= 9) #define to_char(n) ((n) + '0') -void AddInt( char **buf_p, int val, int width, int flags ) { +#undef TRY_APPEND +#define TRY_APPEND(ch) do { if (fill < maxlen) { *buf++ = (ch); } fill++; } while (0) + +int AddInt( char **buf_p, size_t maxlen, int val, int width, int flags, char *charset ) { char text[32]; int digits; int signedVal; char *buf; + int base; + int fill; + + fill = 0; + if (charset == NULL) + charset = "0123456789"; /* Decimal by default. */ + + for (base = 0; charset[base]; base++); /* Note NOP operation. */ + /* Offset of NULL is the number base. So "0123456789" -> base-10. */ digits = 0; signedVal = val; @@ -1039,11 +1052,11 @@ val = -val; } do { - text[digits++] = '0' + val % 10; - val /= 10; + text[digits++] = charset[val % base]; //'0' + val % 10; + val /= base; //10; } while ( val ); - if ( signedVal < 0 ) { + if (( signedVal < 0 ) && !(flags & UNSIGNED)) { text[digits++] = '-'; } @@ -1051,32 +1064,39 @@ if( !( flags & LADJUST ) ) { while ( digits < width ) { - *buf++ = ( flags & ZEROPAD ) ? '0' : ' '; +// *buf++ = ( flags & ZEROPAD ) ? '0' : ' '; + TRY_APPEND(( flags & ZEROPAD ) ? '0' : ' '); width--; } } while ( digits-- ) { - *buf++ = text[digits]; +// *buf++ = text[digits]; + TRY_APPEND(text[digits]); width--; } if( flags & LADJUST ) { while ( width-- ) { - *buf++ = ( flags & ZEROPAD ) ? '0' : ' '; +// *buf++ = ( flags & ZEROPAD ) ? '0' : ' '; + TRY_APPEND(( flags & ZEROPAD ) ? '0' : ' '); } } *buf_p = buf; + return fill; } -void AddFloat( char **buf_p, float fval, int width, int prec ) { +int AddFloat( char **buf_p, size_t maxlen, float fval, int width, int prec ) { char text[32]; int digits; float signedVal; char *buf; int val; + int zerofrac; /* Fractional part remains zero? */ + int fill; + fill = 0; // get the sign signedVal = fval; if ( fval < 0 ) { @@ -1098,12 +1118,14 @@ buf = *buf_p; while ( digits < width ) { - *buf++ = ' '; +// *buf++ = ' '; + TRY_APPEND(' '); width--; } while ( digits-- ) { - *buf++ = text[digits]; +// *buf++ = text[digits]; + TRY_APPEND(text[digits]); } *buf_p = buf; @@ -1111,29 +1133,42 @@ if (prec < 0) prec = 6; // write the fraction + zerofrac = 1; /* Assume fractional part is zero. */ digits = 0; while (digits < prec) { fval -= (int) fval; fval *= 10.0; val = (int) fval; text[digits++] = '0' + val % 10; + zerofrac &= (val == 0); /* Does fractional part remain zero? */ + } + + if (zerofrac) { + /* Fractional part is zero. Don't bother with fractional. */ + /* Um... how do we figure out if we need to do alternate form? */ + return fill; } if (digits > 0) { buf = *buf_p; - *buf++ = '.'; +// *buf++ = '.'; + TRY_APPEND('.'); for (prec = 0; prec < digits; prec++) { - *buf++ = text[prec]; +// *buf++ = text[prec]; + TRY_APPEND(text[prec]); } *buf_p = buf; } + return fill; } -void AddString( char **buf_p, char *string, int width, int prec ) { +int AddString( char **buf_p, size_t maxlen, char *string, int width, int prec ) { int size; char *buf; + int fill; + fill = 0; buf = *buf_p; if ( string == NULL ) { @@ -1155,16 +1190,21 @@ width -= size; while( size-- ) { - *buf++ = *string++; +// *buf++ = *string++; + TRY_APPEND((*string++)); } while( width-- > 0 ) { - *buf++ = ' '; +// *buf++ = ' '; + TRY_APPEND(' '); } *buf_p = buf; + return fill; } + +#if 0 /* vsprintf @@ -1241,12 +1281,17 @@ *buf_p++ = (char)*arg; arg++; break; + case 'l': + /* Just ignore. */ + goto rflag; + break; case 'd': case 'i': - AddInt( &buf_p, *arg, width, flags ); + AddInt( &buf_p, *arg, width, flags, "0123456789" ); arg++; break; case 'f': + case 'g': AddFloat( &buf_p, *(double *)arg, width, prec ); #ifdef __LCC__ arg += 1; // everything is 32 bit in my compiler @@ -1261,6 +1306,24 @@ case '%': *buf_p++ = ch; break; + + case 'u': /* Unsigned decimal. */ + AddInt (&buf_p, *arg, width, flags | UNSIGNED, "0123456789"); + arg++; + break; + case 'o': /* (Unsigned) Octal. */ + AddInt (&buf_p, *arg, width, flags | UNSIGNED, "01234567"); + arg++; + break; + case 'x': /* (unsigned) hexadecimal (lower-case letters). */ + AddInt (&buf_p, *arg, width, flags | UNSIGNED, "0123456789abcdef"); + arg++; + break; + case 'X': /* (unsigned) Hexadecimal (upper-case letters). */ + AddInt (&buf_p, *arg, width, flags | UNSIGNED, "0123456789ABCDEF"); + arg++; + break; + default: *buf_p++ = (char)*arg; arg++; @@ -1272,6 +1335,7 @@ *buf_p = 0; return buf_p - buffer; } +#endif /* 0 */ /* this is really crappy */ @@ -1309,3 +1373,167 @@ } #endif + + + +/* vsnprintf, extended version of Q3A 1.29h bg_libc.c:vsprintf() */ +/* Return value is how many characters filled, or how many would have been filled had there been enough space. */ +/* +vsnprintf + +I'm not going to support a bunch of the more arcane stuff in here +just to keep it simpler. For example, the '*' and '$' are not +currently supported. I've tried to make it so that it will just +parse and ignore formats we don't support. +*/ +int vsnprintf( char *buffer, size_t size, const char *fmt, va_list argptr ) { + int *arg; + char *buf_p; + char ch; + int flags; + int width; + int prec; + int n; + char sign; + int pneumonoultramicroscopicsilicovolcanoconiosis; /* Just for you, vogon_jeltz. */ + +#undef TRY_APPEND +#define TRY_APPEND(ch) do { if (pneumonoultramicroscopicsilicovolcanoconiosis < size) { *buf_p++ = (ch); } pneumonoultramicroscopicsilicovolcanoconiosis++; } while (0) + + if (size < 1) + return 0; + pneumonoultramicroscopicsilicovolcanoconiosis = 0; + size--; /* Make room for trailing \0. */ + buf_p = buffer; + arg = (int *)argptr; + + while( qtrue ) { + // run through the format string until we hit a '%' or '\0' + for ( ch = *fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++ ) { +// *buf_p++ = ch; + TRY_APPEND(ch); + } + if ( ch == '\0' ) { + goto done; + } + + // skip over the '%' + fmt++; + + // reset formatting state + flags = 0; + width = 0; + prec = -1; + sign = '\0'; + +rflag: + ch = *fmt++; +reswitch: + switch( ch ) { + case '-': + flags |= LADJUST; + goto rflag; + case '.': + n = 0; + while( is_digit( ( ch = *fmt++ ) ) ) { + n = 10 * n + ( ch - '0' ); + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + flags |= ZEROPAD; + goto rflag; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + n = 0; + do { + n = 10 * n + ( ch - '0' ); + ch = *fmt++; + } while( is_digit( ch ) ); + width = n; + goto reswitch; + case 'c': +// *buf_p++ = (char)*arg; + TRY_APPEND((char)*arg); + arg++; + break; + case 'l': + /* Just ignore. */ + goto rflag; + break; + case 'd': + case 'i': + pneumonoultramicroscopicsilicovolcanoconiosis += AddInt( &buf_p, size - pneumonoultramicroscopicsilicovolcanoconiosis, *arg, width, flags, "0123456789" ); + arg++; + break; + case 'f': + case 'g': + pneumonoultramicroscopicsilicovolcanoconiosis += AddFloat( &buf_p, size - pneumonoultramicroscopicsilicovolcanoconiosis, *(double *)arg, width, prec ); +#ifdef __LCC__ + arg += 1; // everything is 32 bit in my compiler +#else + arg += 2; +#endif + break; + case 's': + pneumonoultramicroscopicsilicovolcanoconiosis += AddString( &buf_p, size - pneumonoultramicroscopicsilicovolcanoconiosis, (char *)*arg, width, prec ); + arg++; + break; + case '%': +// *buf_p++ = ch; + TRY_APPEND(ch); + break; + + case 'u': /* Unsigned decimal. */ + pneumonoultramicroscopicsilicovolcanoconiosis += AddInt (&buf_p, size - pneumonoultramicroscopicsilicovolcanoconiosis, *arg, width, flags | UNSIGNED, "0123456789"); + arg++; + break; + case 'o': /* (Unsigned) Octal. */ + pneumonoultramicroscopicsilicovolcanoconiosis += AddInt (&buf_p, size - pneumonoultramicroscopicsilicovolcanoconiosis, *arg, width, flags | UNSIGNED, "01234567"); + arg++; + break; + case 'x': /* (unsigned) hexadecimal (lower-case letters). */ + pneumonoultramicroscopicsilicovolcanoconiosis += AddInt (&buf_p, size - pneumonoultramicroscopicsilicovolcanoconiosis, *arg, width, flags | UNSIGNED, "0123456789abcdef"); + arg++; + break; + case 'X': /* (unsigned) Hexadecimal (upper-case letters). */ + pneumonoultramicroscopicsilicovolcanoconiosis += AddInt (&buf_p, size - pneumonoultramicroscopicsilicovolcanoconiosis, *arg, width, flags | UNSIGNED, "0123456789ABCDEF"); + arg++; + break; + + default: +// *buf_p++ = (char)*arg; + TRY_APPEND((char)*arg); + arg++; + break; + } + } + +done: + *buf_p = 0; +// return buf_p - buffer; + return pneumonoultramicroscopicsilicovolcanoconiosis; +} + + +int snprintf(char *buffer, int size, const char *fmt, ...) +{ + va_list vp; + int retval; + + va_start(vp, fmt); + retval = vsnprintf(buffer, size, fmt, vp); + va_end(vp); + return retval; +} + +int vsprintf( char *buffer, const char *fmt, va_list argptr ) { + return vsnprintf(buffer, INT_MAX, fmt, argptr); +}