diff options
author | Andrey Nazarov <skuller@skuller.net> | 2010-09-15 22:41:27 +0400 |
---|---|---|
committer | Andrey Nazarov <skuller@skuller.net> | 2010-09-15 22:41:27 +0400 |
commit | cd8d25aa0b96b48e1a6d0edf9893afe9cbf796c1 (patch) | |
tree | 322d2ed47d1ab4c7afdd5e70f34829f252877872 /source/q_shared.c | |
parent | de41ad148d857184ead919fa488fd58cec5b1864 (diff) |
Renamed source tree subdirectory into ‘src’, moved ‘asm’ subdirectory there and renamed it into ‘i386’.
Diffstat (limited to 'source/q_shared.c')
-rw-r--r-- | source/q_shared.c | 1229 |
1 files changed, 0 insertions, 1229 deletions
diff --git a/source/q_shared.c b/source/q_shared.c deleted file mode 100644 index a032749..0000000 --- a/source/q_shared.c +++ /dev/null @@ -1,1229 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include <config.h> -#include "q_shared.h" - -vec3_t vec3_origin = { 0, 0, 0 }; - -void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[YAW] * (M_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[PITCH] * (M_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - if (forward) - { - forward[0] = cp*cy; - forward[1] = cp*sy; - forward[2] = -sp; - } - if (right) - { - right[0] = (-1*sr*sp*cy+-1*cr*-sy); - right[1] = (-1*sr*sp*sy+-1*cr*cy); - right[2] = -1*sr*cp; - } - if (up) - { - up[0] = (cr*sp*cy+-sr*-sy); - up[1] = (cr*sp*sy+-sr*cy); - up[2] = cr*cp; - } -} - -vec_t VectorNormalize (vec3_t v) -{ - float length, ilength; - - length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; - length = sqrt (length); // FIXME - - if (length) - { - ilength = 1/length; - v[0] *= ilength; - v[1] *= ilength; - v[2] *= ilength; - } - - return length; - -} - -vec_t VectorNormalize2 (vec3_t v, vec3_t out) -{ - float length, ilength; - - length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; - length = sqrt (length); // FIXME - - if (length) - { - ilength = 1/length; - out[0] = v[0]*ilength; - out[1] = v[1]*ilength; - out[2] = v[2]*ilength; - } - - return length; - -} - -void ClearBounds (vec3_t mins, vec3_t maxs) { - mins[0] = mins[1] = mins[2] = 99999; - maxs[0] = maxs[1] = maxs[2] = -99999; -} - -void AddPointToBounds (const vec3_t v, vec3_t mins, vec3_t maxs) { - int i; - vec_t val; - - for (i=0 ; i<3 ; i++) - { - val = v[i]; - if (val < mins[i]) - mins[i] = val; - if (val > maxs[i]) - maxs[i] = val; - } -} - -void UnionBounds( vec3_t a[2], vec3_t b[2], vec3_t c[2] ) { - c[0][0] = b[0][0] < a[0][0] ? b[0][0] : a[0][0]; - c[0][1] = b[0][1] < a[0][1] ? b[0][1] : a[0][1]; - c[0][2] = b[0][2] < a[0][2] ? b[0][2] : a[0][2]; - - c[1][0] = b[1][0] > a[1][0] ? b[1][0] : a[1][0]; - c[1][1] = b[1][1] > a[1][1] ? b[1][1] : a[1][1]; - c[1][2] = b[1][2] > a[1][2] ? b[1][2] : a[1][2]; -} - -/* -================= -RadiusFromBounds -================= -*/ -vec_t RadiusFromBounds (const vec3_t mins, const vec3_t maxs) { - int i; - vec3_t corner; - vec_t a, b; - - for (i=0 ; i<3 ; i++) - { - a = Q_fabs(mins[i]); - b = Q_fabs(maxs[i]); - corner[i] = a > b ? a : b; - } - - return VectorLength (corner); -} - -//==================================================================================== - -static const char hexchars[] = "0123456789ABCDEF"; - -/* -============ -COM_SkipPath -============ -*/ -char *COM_SkipPath( const char *pathname ) { - char *last; - - if( !pathname ) { - Com_Error( ERR_FATAL, "%s: NULL", __func__ ); - } - - last = (char *)pathname; - while( *pathname ) { - if( *pathname == '/' ) - last = (char *)pathname + 1; - pathname++; - } - return last; -} - -/* -============ -COM_StripExtension -============ -*/ -void COM_StripExtension( const char *in, char *out, size_t size ) { - char *s; - - Q_strlcpy( out, in, size ); - - s = out + strlen( out ); - - while( s != out ) { - if( *s == '/' ) { - break; - } - if( *s == '.' ) { - *s = 0; - break; - } - s--; - } -} - -/* -============ -COM_FileExtension -============ -*/ -char *COM_FileExtension( const char *in ) { - const char *s; - const char *last; - - if( !in ) { - Com_Error( ERR_FATAL, "%s: NULL", __func__ ); - } - - s = in + strlen( in ); - last = s; - - while( s != in ) { - if( *s == '/' ) { - break; - } - if( *s == '.' ) { - return (char *)s; - } - s--; - } - - return (char *)last; -} - -/* -============ -COM_FileBase -============ -*/ -void COM_FileBase (char *in, char *out) -{ - char *s, *s2; - - s = in + strlen(in) - 1; - - while (s != in && *s != '.') - s--; - - for (s2 = s ; s2 != in && *s2 != '/' ; s2--) - ; - - if (s-s2 < 2) - out[0] = 0; - else - { - s--; - strncpy (out,s2+1, s-s2); - out[s-s2] = 0; - } -} - -/* -============ -COM_FilePath - -Returns the path up to, but not including the last / -============ -*/ -void COM_FilePath( const char *in, char *out, size_t size ) { - char *s; - - Q_strlcpy( out, in, size ); - s = strrchr( out, '/' ); - if( s ) { - *s = 0; - } else { - *out = 0; - } -} - - -/* -================== -COM_DefaultExtension - -if path doesn't have .EXT, append extension -(extension should include the .) -================== -*/ -size_t COM_DefaultExtension( char *path, const char *ext, size_t size ) { - char *src; - size_t len; - - if( *path ) { - len = strlen( path ); - src = path + len - 1; - - while( *src != '/' && src != path ) { - if( *src == '.' ) - return len; // it has an extension - src--; - } - } - - len = Q_strlcat( path, ext, size ); - return len; -} - -/* -================== -COM_IsFloat - -Returns true if the given string is valid representation -of floating point number. -================== -*/ -qboolean COM_IsFloat( const char *s ) { - int c, dot = '.'; - - if( *s == '-' ) { - s++; - } - if( !*s ) { - return qfalse; - } - - do { - c = *s++; - if( c == dot ) { - dot = 0; - } else if( !Q_isdigit( c ) ) { - return qfalse; - } - } while( *s ); - - return qtrue; -} - -qboolean COM_IsUint( const char *s ) { - int c; - - if( !*s ) { - return qfalse; - } - - do { - c = *s++; - if( !Q_isdigit( c ) ) { - return qfalse; - } - } while( *s ); - - return qtrue; -} - -qboolean COM_HasSpaces( const char *s ) { - while( *s ) { - if( *s <= 32 ) { - return qtrue; - } - s++; - } - return qfalse; -} - -unsigned COM_ParseHex( const char *s ) { - int c; - unsigned result; - - for( result = 0; *s; s++ ) { - if( ( c = Q_charhex( *s ) ) == -1 ) { - break; - } - if( result & ~( UINT_MAX >> 4 ) ) { - return UINT_MAX; - } - result = c | ( result << 4 ); - } - - return result; -} - -int QDECL SortStrcmp( const void *p1, const void *p2 ) { - return strcmp( *( const char ** )p1, *( const char ** )p2 ); -} - -int QDECL SortStricmp( const void *p1, const void *p2 ) { - return Q_stricmp( *( const char ** )p1, *( const char ** )p2 ); -} - -/* -================ -COM_strclr - -Operates inplace, normalizing high-bit and removing unprintable characters. -Returns final number of characters, not including the NUL character. -================ -*/ -size_t COM_strclr( char *s ) { - char *p; - int c; - size_t len; - - p = s; - len = 0; - while( *s ) { - c = *s++; - c &= 127; - if( Q_isprint( c ) ) { - *p++ = c; - len++; - } - } - - *p = 0; - - return len; -} - -qboolean COM_iswhite( const char *s ) { - int c; - - while( *s ) { - c = *s++; - c &= 127; - if( Q_isgraph( c ) ) { - return qfalse; - } - } - - return qtrue; -} - -size_t COM_FormatFileSize( char *dest, size_t bytes, size_t size ) { - if( bytes >= 1000000 ) { - return Q_snprintf( dest, size, "%2.1fM", ( float )bytes / 1000000 ); - } - if( bytes >= 1000 ) { - return Q_snprintf( dest, size, "%3"PRIz"K", bytes / 1000 ); - } - return Q_snprintf( dest, size, "%3"PRIz, bytes ); -} - -/* -============ -va - -does a varargs printf into a temp buffer, so I don't need to have -varargs versions of all text functions. -FIXME: make this buffer size safe someday -============ -*/ -char *va( const char *format, ... ) { - va_list argptr; - static char buffers[2][0x2800]; - static int index; - - index ^= 1; - - va_start( argptr, format ); - Q_vsnprintf( buffers[index], sizeof( buffers[0] ), format, argptr ); - va_end( argptr ); - - return buffers[index]; -} - -static char com_token[4][MAX_TOKEN_CHARS]; -static int com_tokidx; - -/* -============== -COM_Parse - -Parse a token out of a string. -Handles C and C++ comments. -============== -*/ -char *COM_Parse( const char **data_p ) { - int c; - int len; - const char *data; - char *s = com_token[com_tokidx++ & 3]; - - data = *data_p; - len = 0; - s[0] = 0; - - if( !data ) { - *data_p = NULL; - return s; - } - -// skip whitespace -skipwhite: - while( ( c = *data ) <= ' ' ) { - if( c == 0 ) { - *data_p = NULL; - return s; - } - data++; - } - -// skip // comments - if( c == '/' && data[1] == '/' ) { - data += 2; - while( *data && *data != '\n' ) - data++; - goto skipwhite; - } - -// skip /* */ comments - if( c == '/' && data[1] == '*' ) { - data += 2; - while( *data ) { - if( data[0] == '*' && data[1] == '/' ) { - data += 2; - break; - } - data++; - } - goto skipwhite; - } - -// handle quoted strings specially - if( c == '\"' ) { - data++; - while( 1 ) { - c = *data++; - if( c == '\"' || !c ) { - goto finish; - } - - if( len < MAX_TOKEN_CHARS - 1 ) { - s[len++] = c; - } - } - } - -// parse a regular word - do { - if( len < MAX_TOKEN_CHARS - 1 ) { - s[len++] = c; - } - data++; - c = *data; - } while( c > 32 ); - -finish: - s[len] = 0; - - *data_p = data; - return s; -} - -/* -============== -COM_Compress - -Operates in place, removing excess whitespace and comments. -Non-contiguous line feeds are preserved. - -Returns resulting data length. -============== -*/ -int COM_Compress( char *data ) { - int c, n = 0; - char *s = data, *d = data; - - while( *s ) { - // skip whitespace - if( *s <= ' ' ) { - n = ' '; - do { - c = *s++; - if( c == '\n' ) { - n = '\n'; - } - if( !c ) { - goto finish; - } - } while( *s <= ' ' ); - } - - // skip // comments - if( s[0] == '/' && s[1] == '/' ) { - n = ' '; - s += 2; - while( *s && *s != '\n' ) { - s++; - } - continue; - } - - // skip /* */ comments - if( s[0] == '/' && s[1] == '*' ) { - n = ' '; - s += 2; - while( *s ) { - if( s[0] == '*' && s[1] == '/' ) { - s += 2; - break; - } - s++; - } - continue; - } - - // add whitespace character - if( n ) { - *d++ = n; - n = 0; - } - - // handle quoted strings specially - if( *s == '\"' ) { - s++; - *d++ = '\"'; - do { - c = *s++; - if( !c ) { - goto finish; - } - *d++ = c; - } while( c != '\"' ); - continue; - } - - // handle line feed escape - if( *s == '\\' && s[1] == '\n' ) { - s += 2; - continue; - } - - // parse a regular word - do { - *d++ = *s++; - } while( *s > ' ' ); - } - -finish: - *d = 0; - - return d - data; -} - -/* -============================================================================ - - LIBRARY REPLACEMENT FUNCTIONS - -============================================================================ -*/ - -int Q_strncasecmp( const char *s1, const char *s2, size_t n ) { - int c1, c2; - - do { - c1 = *s1++; - c2 = *s2++; - - if( !n-- ) - return 0; /* strings are equal until end point */ - - if( c1 != c2 ) { - c1 = Q_tolower( c1 ); - c2 = Q_tolower( c2 ); - if( c1 < c2 ) - return -1; - if( c1 > c2 ) - return 1; /* strings not equal */ - } - } while( c1 ); - - return 0; /* strings are equal */ -} - -int Q_strcasecmp( const char *s1, const char *s2 ) { - int c1, c2; - - do { - c1 = *s1++; - c2 = *s2++; - - if( c1 != c2 ) { - c1 = Q_tolower( c1 ); - c2 = Q_tolower( c2 ); - if( c1 < c2 ) - return -1; - if( c1 > c2 ) - return 1; /* strings not equal */ - } - } while( c1 ); - - return 0; /* strings are equal */ -} - -char *Q_strcasestr( const char *s1, const char *s2 ) { - size_t l1, l2; - - l2 = strlen( s2 ); - if( !l2 ) { - return ( char * )s1; - } - - l1 = strlen( s1 ); - while( l1 >= l2 ) { - l1--; - if( !Q_strncasecmp( s1, s2, l2 ) ) { - return ( char * )s1; - } - s1++; - } - - return NULL; -} - -/* -=============== -Q_strlcpy - -Returns length of the source string. -=============== -*/ -size_t Q_strlcpy( char *dst, const char *src, size_t size ) { - size_t ret = strlen( src ); - - if( size ) { - size_t len = ret >= size ? size - 1 : ret; - memcpy( dst, src, len ); - dst[len] = 0; - } - - return ret; -} - -/* -=============== -Q_strlcat - -Returns length of the source and destinations strings combined. -=============== -*/ -size_t Q_strlcat( char *dst, const char *src, size_t size ) { - size_t ret, len = strlen( dst ); - - if( len >= size ) { - Com_Error( ERR_FATAL, "%s: already overflowed", __func__ ); - } - - ret = Q_strlcpy( dst + len, src, size - len ); - ret += len; - - return ret; -} - -/* -=============== -Q_concat - -Returns number of characters that would be written into the buffer, -excluding trailing '\0'. If the returned value is equal to or greater than -buffer size, resulting string is truncated. -=============== -*/ -size_t Q_concat( char *dest, size_t size, ... ) { - va_list argptr; - const char *s; - size_t len, total = 0; - - va_start( argptr, size ); - while( ( s = va_arg( argptr, const char * ) ) != NULL ) { - len = strlen( s ); - if( total + len < size ) { - memcpy( dest, s, len ); - dest += len; - } - total += len; - } - va_end( argptr ); - - if( size ) { - *dest = 0; - } - - return total; -} - -/* -=============== -Q_vsnprintf - -Returns number of characters that would be written into the buffer, -excluding trailing '\0'. If the returned value is equal to or greater than -buffer size, resulting string is truncated. -=============== -*/ -size_t Q_vsnprintf( char *dest, size_t size, const char *fmt, va_list argptr ) { - int ret; - - if( size > INT_MAX ) { - Com_Error( ERR_FATAL, "%s: bad buffer size", __func__ ); - } - -#ifdef _WIN32 - // work around broken M$ C runtime semantics. - if( !size ) { - return 0; - } - ret = _vsnprintf( dest, size - 1, fmt, argptr ); - if( ret >= size - 1 ) { - dest[size - 1] = 0; - } -#else - ret = vsnprintf( dest, size, fmt, argptr ); -#endif - - // this shouldn't happen - if( ret < 0 ) { - if( size ) { - *dest = 0; - } - ret = 0; - } - - return ( size_t )ret; -} - -/* -=============== -Q_vscnprintf - -Returns number of characters actually written into the buffer, -excluding trailing '\0'. If buffer size is 0, this function does nothing -and returns 0. -=============== -*/ -size_t Q_vscnprintf( char *dest, size_t size, const char *fmt, va_list argptr ) { - size_t ret; - - if( !size ) { - return 0; - } - - ret = Q_vsnprintf( dest, size, fmt, argptr ); - return ret >= size ? size - 1 : ret; -} - - -/* -=============== -Q_snprintf - -Returns number of characters that would be written into the buffer, -excluding trailing '\0'. If the returned value is equal to or greater than -buffer size, resulting string is truncated. -=============== -*/ -size_t Q_snprintf( char *dest, size_t size, const char *fmt, ... ) { - va_list argptr; - size_t ret; - - va_start( argptr, fmt ); - ret = Q_vsnprintf( dest, size, fmt, argptr ); - va_end( argptr ); - - return ret; -} - -/* -=============== -Q_scnprintf - -Returns number of characters actually written into the buffer, -excluding trailing '\0'. If buffer size is 0, this function does nothing -and returns 0. -=============== -*/ -size_t Q_scnprintf( char *dest, size_t size, const char *fmt, ... ) { - va_list argptr; - size_t ret; - - va_start( argptr, fmt ); - ret = Q_vscnprintf( dest, size, fmt, argptr ); - va_end( argptr ); - - return ret; -} - -char *Q_strchrnul( const char *s, int c ) { - while( *s && *s != c ) { - s++; - } - return ( char * )s; -} - -void Q_setenv( const char *name, const char *value ) { -#ifdef _WIN32 -#ifndef __COREDLL__ - if( !value ) { - value = ""; - } -#if( _MSC_VER >= 1400 ) - _putenv_s( name, value ); -#else - _putenv( va( "%s=%s", name, value ) ); -#endif -#endif -#else // _WIN32 - if( value ) { - setenv( name, value, 1 ); - } else { - unsetenv( name ); - } -#endif // !_WIN32 -} - -/* -===================================================================== - - INFO STRINGS - -===================================================================== -*/ - -/* -=============== -Info_ValueForKey - -Searches the string for the given -key and returns the associated value, or an empty string. -=============== -*/ -char *Info_ValueForKey( const char *s, const char *key ) { - static char value[4][MAX_INFO_STRING]; // use 4 buffers so compares - // work without stomping on each other - static int valueindex; - char pkey[MAX_INFO_STRING]; - char *o; - - valueindex++; - if( *s == '\\' ) - s++; - while( 1 ) { - o = pkey; - while( *s != '\\' ) { - if( !*s ) - return ""; - *o++ = *s++; - } - *o = 0; - s++; - - o = value[valueindex & 3]; - while( *s != '\\' && *s ) { - *o++ = *s++; - } - *o = 0; - - if( !strcmp( key, pkey ) ) - return value[valueindex & 3]; - - if( !*s ) - return ""; - s++; - } - - return ""; -} - -/* -================== -Info_RemoveKey -================== -*/ -void Info_RemoveKey( char *s, const char *key ) { - char *start; - char pkey[MAX_INFO_STRING]; - char *o; - - while( 1 ) { - start = s; - if( *s == '\\' ) - s++; - o = pkey; - while( *s != '\\' ) { - if( !*s ) - return; - *o++ = *s++; - } - *o = 0; - s++; - - while( *s != '\\' && *s ) { - s++; - } - - if( !strcmp( key, pkey ) ) { - o = start; // remove this part - while( *s ) { - *o++ = *s++; - } - *o = 0; - s = start; - continue; // search for duplicates - } - - if( !*s ) - return; - } - -} - - -/* -================== -Info_Validate - -Some characters are illegal in info strings because they -can mess up the server's parsing. -Also checks the length of keys/values and the whole string. -================== -*/ -qboolean Info_Validate( const char *s ) { - size_t len, total; - int c; - - total = 0; - while( 1 ) { - // - // validate key - // - if( *s == '\\' ) { - s++; - if( ++total == MAX_INFO_STRING ) { - return qfalse; // oversize infostring - } - } - if( !*s ) { - return qfalse; // missing key - } - len = 0; - while( *s != '\\' ) { - c = *s++; - if( !Q_isprint( c ) || c == '\"' || c == ';' ) { - return qfalse; // illegal characters - } - if( ++len == MAX_INFO_KEY ) { - return qfalse; // oversize key - } - if( ++total == MAX_INFO_STRING ) { - return qfalse; // oversize infostring - } - if( !*s ) { - return qfalse; // missing value - } - } - - // - // validate value - // - s++; - if( ++total == MAX_INFO_STRING ) { - return qfalse; // oversize infostring - } - if( !*s ) { - return qfalse; // missing value - } - len = 0; - while( *s != '\\' ) { - c = *s++; - if( !Q_isprint( c ) || c == '\"' || c == ';' ) { - return qfalse; // illegal characters - } - if( ++len == MAX_INFO_VALUE ) { - return qfalse; // oversize value - } - if( ++total == MAX_INFO_STRING ) { - return qfalse; // oversize infostring - } - if( !*s ) { - return qtrue; // end of string - } - } - } - - return qfalse; // quiet compiler warning -} - -/* -============ -Info_SubValidate -============ -*/ -size_t Info_SubValidate( const char *s ) { - size_t len; - int c; - - len = 0; - while( *s ) { - c = *s++; - c &= 127; // strip high bits - if( c == '\\' || c == '\"' || c == ';' ) { - return SIZE_MAX; // illegal characters - } - if( ++len == MAX_QPATH ) { - return MAX_QPATH; // oversize value - } - } - - return len; -} - -/* -================== -Info_SetValueForKey -================== -*/ -qboolean Info_SetValueForKey( char *s, const char *key, const char *value ) { - char newi[MAX_INFO_STRING], *v; - size_t l, kl, vl; - int c; - - // validate key - kl = Info_SubValidate( key ); - if( kl >= MAX_QPATH ) { - return qfalse; - } - - // validate value - vl = Info_SubValidate( value ); - if( vl >= MAX_QPATH ) { - return qfalse; - } - - Info_RemoveKey( s, key ); - if( !vl ) { - return qtrue; - } - - l = strlen( s ); - if( l + kl + vl + 2 >= MAX_INFO_STRING ) { - return qfalse; - } - - newi[0] = '\\'; - memcpy( newi + 1, key, kl ); - newi[kl + 1] = '\\'; - memcpy( newi + kl + 2, value, vl + 1 ); - - // only copy ascii values - s += l; - v = newi; - while( *v ) { - c = *v++; - c &= 127; // strip high bits - if( Q_isprint( c ) ) - *s++ = c; - } - *s = 0; - - return qtrue; -} - -/* -================== -Info_NextPair -================== -*/ -void Info_NextPair( const char **string, char *key, char *value ) { - char *o; - const char *s; - - *value = *key = 0; - - s = *string; - if( !s ) { - return; - } - - if( *s == '\\' ) - s++; - - if( !*s ) { - *string = NULL; - return; - } - - o = key; - while( *s && *s != '\\' ) { - *o++ = *s++; - } - - *o = 0; - - if( !*s ) { - *string = NULL; - return; - } - - o = value; - s++; - while( *s && *s != '\\' ) { - *o++ = *s++; - } - *o = 0; - - if( *s ) { - s++; - } - - *string = s; - -} - -/* -================== -Info_Print -================== -*/ -void Info_Print( const char *infostring ) { - char key[MAX_INFO_STRING]; - char value[MAX_INFO_STRING]; - - while( infostring ) { - Info_NextPair( &infostring, key, value ); - - if( !key[0] ) { - break; - } - - if( value[0] ) { - Com_Printf( "%-20s %s\n", key, value ); - } else { - Com_Printf( "%-20s <MISSING VALUE>\n", key ); - } - } -} - |