2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 // Nurail: Swiped from quake3/common
25 #include "globaldefs.h"
28 #include <sys/types.h>
41 #define strlwr strlower
42 #endif // !GDEF_OS_WINDOWS
44 #define BASEDIRNAME "h"
45 #define PATHSEPERATOR '/'
47 extern qboolean verbose;
49 qboolean g_dokeypress = false;
51 qboolean g_nomkdir = false;
53 void *safe_malloc( size_t size ){
58 Error( "safe_malloc failed on allocation of %i bytes", size );
64 void *safe_malloc_info( size_t size, char* info ){
69 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
75 void *SafeMalloc( size_t n, char *desc ){
78 if ( ( p = malloc( n ) ) == NULL ) {
79 Error( "Failed to allocate %d bytes for '%s'.\n", n, desc );
85 // set these before calling CheckParm
93 char archivedir[1024];
100 Mimic unix command line expansion
103 #define MAX_EX_ARGC 1024
106 char *ex_argv[MAX_EX_ARGC];
110 void ExpandWildcards( int *argc, char ***argv ){
111 struct _finddata_t fileinfo;
119 for ( i = 0 ; i < *argc ; i++ )
123 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
124 ex_argv[ex_argc++] = path;
128 handle = _findfirst( path, &fileinfo );
129 if ( handle == -1 ) {
133 ExtractFilePath( path, filebase );
137 sprintf( filename, "%s%s", filebase, fileinfo.name );
138 ex_argv[ex_argc++] = copystring( filename );
139 } while ( _findnext( handle, &fileinfo ) != -1 );
141 _findclose( handle );
147 #else // !GDEF_OS_WINDOWS
148 void ExpandWildcards( int *argc, char ***argv ){
150 #endif // !GDEF_OS_WINDOWS
154 qdir will hold the path up to the quake directory, including the slash
159 gamedir will hold qdir + the game directory (id1, id2, etc)
167 void SetQdirFromPath( const char *path ){
173 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
175 strcat( temp, path );
179 // search for "quake2" in path
181 len = strlen( BASEDIRNAME );
182 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
186 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
188 //strncpy (qdir, path, c+len+2-path);
189 // the +2 assumes a 2 or 3 following quake which is not the
190 // case with a retail install
191 // so we need to add up how much to the next separator
194 while ( *sep && *sep != '/' && *sep != '\\' )
199 strncpy( qdir, path, c + len + count - path );
200 Sys_Printf( "qdir: %s\n", qdir );
201 for ( i = 0; i < strlen( qdir ); i++ )
203 if ( qdir[i] == '\\' ) {
211 if ( *c == '/' || *c == '\\' ) {
212 strncpy( gamedir, path, c + 1 - path );
214 for ( i = 0; i < strlen( gamedir ); i++ )
216 if ( gamedir[i] == '\\' ) {
221 Sys_Printf( "gamedir: %s\n", gamedir );
223 if ( !writedir[0] ) {
224 strcpy( writedir, gamedir );
226 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
227 writedir[strlen( writedir )] = '/';
228 writedir[strlen( writedir ) + 1] = 0;
235 Error( "No gamedir in %s", path );
239 Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
242 char *ExpandArg( const char *path ){
243 static char full[1024];
245 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
247 strcat( full, path );
250 strcpy( full, path );
255 char *ExpandPath( const char *path ){
256 static char full[1024];
258 Error( "ExpandPath called without qdir set" );
260 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
261 strcpy( full, path );
264 sprintf( full, "%s%s", qdir, path );
268 char *ExpandGamePath( const char *path ){
269 static char full[1024];
271 Error( "ExpandGamePath called without qdir set" );
273 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
274 strcpy( full, path );
277 sprintf( full, "%s%s", gamedir, path );
281 char *ExpandPathAndArchive( const char *path ){
283 char archivename[1024];
285 expanded = ExpandPath( path );
288 sprintf( archivename, "%s/%s", archivedir, path );
289 QCopyFile( expanded, archivename );
295 char *copystring( const char *s ){
297 b = safe_malloc( strlen( s ) + 1 );
309 double I_FloatTime( void ){
316 // more precise, less portable
321 gettimeofday( &tp, &tzp );
325 return tp.tv_usec / 1000000.0;
328 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
332 void Q_getwd( char *out ){
338 #else // !GDEF_OS_WINDOWS
339 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
342 #endif // !GDEF_OS_WINDOWS
343 while ( out[i] != 0 )
345 if ( out[i] == '\\' ) {
353 void Q_mkdir( const char *path ){
355 if ( _mkdir( path ) != -1 ) {
358 #else // !GDEF_OS_WINDOWS
359 if ( mkdir( path, 0777 ) != -1 ) {
362 #endif // !GDEF_OS_WINDOWS
363 if ( errno != EEXIST ) {
364 Error( "mkdir %s: %s",path, strerror( errno ) );
372 returns -1 if not present
375 int FileTime( const char *path ){
378 if ( stat( path,&buf ) == -1 ) {
391 Parse a token out of a string
394 char *COM_Parse( char *data ){
407 while ( ( c = *data ) <= ' ' )
411 return NULL; // end of file;
417 if ( c == '/' && data[1] == '/' ) {
418 while ( *data && *data != '\n' )
424 // handle quoted strings specially
439 // parse single characters
440 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
447 // parse a regular word
454 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
463 int Q_strncasecmp( const char *s1, const char *s2, int n ){
472 return 0; // strings are equal until end point
476 if ( c1 >= 'a' && c1 <= 'z' ) {
479 if ( c2 >= 'a' && c2 <= 'z' ) {
483 return -1; // strings not equal
488 return 0; // strings are equal
491 int Q_stricmp( const char *s1, const char *s2 ){
492 return Q_strncasecmp( s1, s2, 99999 );
495 int Q_strcasecmp( const char *s1, const char *s2 ){
496 return Q_strncasecmp( s1, s2, 99999 );
499 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
500 // started getting warnings about that function, prolly a duplicate with the runtime function
501 // maybe we still need to have it in linux builds
503 char *strupr (char *start)
516 char *strlower( char *start ){
521 *in = tolower( *in );
529 =============================================================================
533 =============================================================================
541 Checks for the given parameter in the program's command line arguments
542 Returns the argument number (1 to argc-1) or 0 if not present
545 int CheckParm( const char *check ){
548 for ( i = 1; i < myargc; i++ )
550 if ( !Q_stricmp( check, myargv[i] ) ) {
565 int Q_filelength( FILE *f ){
570 fseek( f, 0, SEEK_END );
572 fseek( f, pos, SEEK_SET );
578 FILE *SafeOpenWrite( const char *filename ){
581 f = fopen( filename, "wb" );
584 Error( "Error opening %s: %s",filename,strerror( errno ) );
590 FILE *SafeOpenRead( const char *filename ){
593 f = fopen( filename, "rb" );
596 Error( "Error opening %s: %s",filename,strerror( errno ) );
603 void SafeRead( FILE *f, void *buffer, int count ){
604 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
605 Error( "File read failure" );
610 void SafeWrite( FILE *f, const void *buffer, int count ){
611 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
612 Error( "File write failure" );
622 qboolean FileExists( const char *filename ){
625 f = fopen( filename, "r" );
638 int LoadFile( const char *filename, void **bufferptr ){
643 f = SafeOpenRead( filename );
644 length = Q_filelength( f );
645 buffer = safe_malloc( length + 1 );
646 ( (char *)buffer )[length] = 0;
647 SafeRead( f, buffer, length );
659 rounds up memory allocation to 4K boundry
663 int LoadFileBlock( const char *filename, void **bufferptr ){
665 int length, nBlock, nAllocSize;
668 f = SafeOpenRead( filename );
669 length = Q_filelength( f );
671 nBlock = nAllocSize % MEM_BLOCKSIZE;
673 nAllocSize += MEM_BLOCKSIZE - nBlock;
675 buffer = safe_malloc( nAllocSize + 1 );
676 memset( buffer, 0, nAllocSize + 1 );
677 SafeRead( f, buffer, length );
692 int TryLoadFile( const char *filename, void **bufferptr ){
699 f = fopen( filename, "rb" );
703 length = Q_filelength( f );
704 buffer = safe_malloc( length + 1 );
705 ( (char *)buffer )[length] = 0;
706 SafeRead( f, buffer, length );
719 void SaveFile( const char *filename, const void *buffer, int count ){
722 f = SafeOpenWrite( filename );
723 SafeWrite( f, buffer, count );
729 void DefaultExtension( char *path, const char *extension ){
732 // if path doesnt have a .EXT, append extension
733 // (extension should include the .)
735 src = path + strlen( path ) - 1;
737 while ( *src != '/' && *src != '\\' && src != path )
740 return; // it has an extension
745 strcat( path, extension );
749 void DefaultPath( char *path, const char *basepath ){
752 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
753 return; // absolute path location
756 strcpy( path,basepath );
761 void StripFilename( char *path ){
764 length = strlen( path ) - 1;
765 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
770 void StripExtension( char *path ){
773 length = strlen( path ) - 1;
774 while ( length > 0 && path[length] != '.' )
777 if ( path[length] == '/' || path[ length ] == '\\' ) {
778 return; // no extension
793 // FIXME: should include the slash, otherwise
794 // backing to an empty path will be wrong when appending a slash
795 void ExtractFilePath( const char *path, char *dest ){
798 src = path + strlen( path ) - 1;
801 // back up until a \ or the start
803 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
806 memcpy( dest, path, src - path );
807 dest[src - path] = 0;
810 void ExtractFileBase( const char *path, char *dest ){
813 src = path + strlen( path ) - 1;
816 // back up until a \ or the start
818 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
821 while ( *src && *src != '.' )
828 void ExtractFileExtension( const char *path, char *dest ){
831 src = path + strlen( path ) - 1;
834 // back up until a . or the start
836 while ( src != path && *( src - 1 ) != '.' )
839 *dest = 0; // no extension
852 int ParseHex( const char *hex ){
862 if ( *str >= '0' && *str <= '9' ) {
865 else if ( *str >= 'a' && *str <= 'f' ) {
866 num += 10 + *str - 'a';
868 else if ( *str >= 'A' && *str <= 'F' ) {
869 num += 10 + *str - 'A';
872 Error( "Bad hex number: %s",hex );
881 int ParseNum( const char *str ){
882 if ( str[0] == '$' ) {
883 return ParseHex( str + 1 );
885 if ( str[0] == '0' && str[1] == 'x' ) {
886 return ParseHex( str + 2 );
891 // all output ends up through here
892 void FPrintf (int flag, char *buf)
898 void Sys_FPrintf (int flag, const char *format, ...)
900 char out_buffer[4096];
903 if ((flag == SYS_VRB) && (verbose == false))
906 va_start (argptr, format);
907 vsprintf (out_buffer, format, argptr);
910 FPrintf (flag, out_buffer);
913 void Sys_Printf (const char *format, ...)
915 char out_buffer[4096];
918 va_start (argptr, format);
919 vsprintf (out_buffer, format, argptr);
922 FPrintf (SYS_STD, out_buffer);
928 //For abnormal program terminations
931 void Error( const char *error, ...)
933 char out_buffer[4096];
937 va_start (argptr,error);
938 vsprintf (tmp, error, argptr);
941 sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
943 FPrintf( SYS_ERR, out_buffer );
951 ============================================================================
955 ============================================================================
958 #if GDEF_ARCH_ENDIAN_BIG
960 short LittleShort( short l ){
964 b2 = ( l >> 8 ) & 255;
966 return ( b1 << 8 ) + b2;
969 short BigShort( short l ){
974 int LittleLong( int l ){
978 b2 = ( l >> 8 ) & 255;
979 b3 = ( l >> 16 ) & 255;
980 b4 = ( l >> 24 ) & 255;
982 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
985 int BigLong( int l ){
990 float LittleFloat( float l ){
991 union {byte b[4]; float f; } in, out;
1002 float BigFloat( float l ){
1007 #else // !GDEF_ARCH_ENDIAN_BIG
1010 short BigShort( short l ){
1014 b2 = ( l >> 8 ) & 255;
1016 return ( b1 << 8 ) + b2;
1019 short LittleShort( short l ){
1024 int BigLong( int l ){
1028 b2 = ( l >> 8 ) & 255;
1029 b3 = ( l >> 16 ) & 255;
1030 b4 = ( l >> 24 ) & 255;
1032 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
1035 int LittleLong( int l ){
1039 float BigFloat( float l ){
1040 union {byte b[4]; float f; } in, out;
1051 float LittleFloat( float l ){
1055 #endif // ! GDEF_ARCH_ENDIAN_BIG
1058 //=======================================================
1061 // FIXME: byte swap?
1063 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1064 // and the initial and final xor values shown below... in other words, the
1065 // CCITT standard CRC used by XMODEM
1067 #define CRC_INIT_VALUE 0xffff
1068 #define CRC_XOR_VALUE 0x0000
1070 static unsigned short crctable[256] =
1072 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1073 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1074 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1075 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1076 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1077 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1078 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1079 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1080 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1081 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1082 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1083 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1084 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1085 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1086 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1087 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1088 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1089 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1090 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1091 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1092 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1093 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1094 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1095 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1096 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1097 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1098 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1099 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1100 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1101 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1102 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1103 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1106 void CRC_Init( unsigned short *crcvalue ){
1107 *crcvalue = CRC_INIT_VALUE;
1110 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1111 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1114 unsigned short CRC_Value( unsigned short crcvalue ){
1115 return crcvalue ^ CRC_XOR_VALUE;
1117 //=============================================================================
1124 void CreatePath( const char *path ){
1132 if ( path[1] == ':' ) {
1133 olddrive = _getdrive();
1134 _chdrive( toupper( path[0] ) - 'A' + 1 );
1136 #endif // !GDEF_OS_WINDOWS
1138 if ( path[1] == ':' ) {
1142 for ( ofs = path + 1 ; *ofs ; ofs++ )
1145 if ( c == '/' || c == '\\' ) { // create the directory
1146 memcpy( dir, path, ofs - path );
1147 dir[ ofs - path ] = 0;
1153 if ( olddrive != -1 ) {
1154 _chdrive( olddrive );
1156 #endif // !GDEF_OS_WINDOWS
1164 Used to archive source files
1167 void QCopyFile( const char *from, const char *to ){
1171 length = LoadFile( from, &buffer );
1173 SaveFile( to, buffer, length );
1177 void Sys_Sleep( int n ){
1180 #else // !GDEF_OS_WINDOWS
1182 #endif // !GDEF_OS_WINDOWS