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 // May be already defined with some compilers on Windows
501 char *strupr (char *start)
514 char *strlower( char *start ){
519 *in = tolower( *in );
527 =============================================================================
531 =============================================================================
539 Checks for the given parameter in the program's command line arguments
540 Returns the argument number (1 to argc-1) or 0 if not present
543 int CheckParm( const char *check ){
546 for ( i = 1; i < myargc; i++ )
548 if ( !Q_stricmp( check, myargv[i] ) ) {
563 int Q_filelength( FILE *f ){
568 fseek( f, 0, SEEK_END );
570 fseek( f, pos, SEEK_SET );
576 FILE *SafeOpenWrite( const char *filename ){
579 f = fopen( filename, "wb" );
582 Error( "Error opening %s: %s",filename,strerror( errno ) );
588 FILE *SafeOpenRead( const char *filename ){
591 f = fopen( filename, "rb" );
594 Error( "Error opening %s: %s",filename,strerror( errno ) );
601 void SafeRead( FILE *f, void *buffer, int count ){
602 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
603 Error( "File read failure" );
608 void SafeWrite( FILE *f, const void *buffer, int count ){
609 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
610 Error( "File write failure" );
620 qboolean FileExists( const char *filename ){
623 f = fopen( filename, "r" );
636 int LoadFile( const char *filename, void **bufferptr ){
641 f = SafeOpenRead( filename );
642 length = Q_filelength( f );
643 buffer = safe_malloc( length + 1 );
644 ( (char *)buffer )[length] = 0;
645 SafeRead( f, buffer, length );
657 rounds up memory allocation to 4K boundry
661 int LoadFileBlock( const char *filename, void **bufferptr ){
663 int length, nBlock, nAllocSize;
666 f = SafeOpenRead( filename );
667 length = Q_filelength( f );
669 nBlock = nAllocSize % MEM_BLOCKSIZE;
671 nAllocSize += MEM_BLOCKSIZE - nBlock;
673 buffer = safe_malloc( nAllocSize + 1 );
674 memset( buffer, 0, nAllocSize + 1 );
675 SafeRead( f, buffer, length );
690 int TryLoadFile( const char *filename, void **bufferptr ){
697 f = fopen( filename, "rb" );
701 length = Q_filelength( f );
702 buffer = safe_malloc( length + 1 );
703 ( (char *)buffer )[length] = 0;
704 SafeRead( f, buffer, length );
717 void SaveFile( const char *filename, const void *buffer, int count ){
720 f = SafeOpenWrite( filename );
721 SafeWrite( f, buffer, count );
727 void DefaultExtension( char *path, const char *extension ){
730 // if path doesnt have a .EXT, append extension
731 // (extension should include the .)
733 src = path + strlen( path ) - 1;
735 while ( *src != '/' && *src != '\\' && src != path )
738 return; // it has an extension
743 strcat( path, extension );
747 void DefaultPath( char *path, const char *basepath ){
750 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
751 return; // absolute path location
754 strcpy( path,basepath );
759 void StripFilename( char *path ){
762 length = strlen( path ) - 1;
763 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
768 void StripExtension( char *path ){
771 length = strlen( path ) - 1;
772 while ( length > 0 && path[length] != '.' )
775 if ( path[length] == '/' || path[ length ] == '\\' ) {
776 return; // no extension
791 // FIXME: should include the slash, otherwise
792 // backing to an empty path will be wrong when appending a slash
793 void ExtractFilePath( const char *path, char *dest ){
796 src = path + strlen( path ) - 1;
799 // back up until a \ or the start
801 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
804 memcpy( dest, path, src - path );
805 dest[src - path] = 0;
808 void ExtractFileBase( const char *path, char *dest ){
811 src = path + strlen( path ) - 1;
814 // back up until a \ or the start
816 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
819 while ( *src && *src != '.' )
826 void ExtractFileExtension( const char *path, char *dest ){
829 src = path + strlen( path ) - 1;
832 // back up until a . or the start
834 while ( src != path && *( src - 1 ) != '.' )
837 *dest = 0; // no extension
850 int ParseHex( const char *hex ){
860 if ( *str >= '0' && *str <= '9' ) {
863 else if ( *str >= 'a' && *str <= 'f' ) {
864 num += 10 + *str - 'a';
866 else if ( *str >= 'A' && *str <= 'F' ) {
867 num += 10 + *str - 'A';
870 Error( "Bad hex number: %s",hex );
879 int ParseNum( const char *str ){
880 if ( str[0] == '$' ) {
881 return ParseHex( str + 1 );
883 if ( str[0] == '0' && str[1] == 'x' ) {
884 return ParseHex( str + 2 );
889 // all output ends up through here
890 void FPrintf (int flag, char *buf)
896 void Sys_FPrintf (int flag, const char *format, ...)
898 char out_buffer[4096];
901 if ((flag == SYS_VRB) && (verbose == false))
904 va_start (argptr, format);
905 vsprintf (out_buffer, format, argptr);
908 FPrintf (flag, out_buffer);
911 void Sys_Printf (const char *format, ...)
913 char out_buffer[4096];
916 va_start (argptr, format);
917 vsprintf (out_buffer, format, argptr);
920 FPrintf (SYS_STD, out_buffer);
926 //For abnormal program terminations
929 void Error( const char *error, ...)
931 char out_buffer[4096];
935 va_start (argptr,error);
936 vsprintf (tmp, error, argptr);
939 sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
941 FPrintf( SYS_ERR, out_buffer );
949 ============================================================================
953 ============================================================================
956 #if GDEF_ARCH_ENDIAN_BIG
958 short LittleShort( short l ){
962 b2 = ( l >> 8 ) & 255;
964 return ( b1 << 8 ) + b2;
967 short BigShort( short l ){
972 int LittleLong( int l ){
976 b2 = ( l >> 8 ) & 255;
977 b3 = ( l >> 16 ) & 255;
978 b4 = ( l >> 24 ) & 255;
980 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
983 int BigLong( int l ){
988 float LittleFloat( float l ){
989 union {byte b[4]; float f; } in, out;
1000 float BigFloat( float l ){
1005 #else // !GDEF_ARCH_ENDIAN_BIG
1008 short BigShort( short l ){
1012 b2 = ( l >> 8 ) & 255;
1014 return ( b1 << 8 ) + b2;
1017 short LittleShort( short l ){
1022 int BigLong( int l ){
1026 b2 = ( l >> 8 ) & 255;
1027 b3 = ( l >> 16 ) & 255;
1028 b4 = ( l >> 24 ) & 255;
1030 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
1033 int LittleLong( int l ){
1037 float BigFloat( float l ){
1038 union {byte b[4]; float f; } in, out;
1049 float LittleFloat( float l ){
1053 #endif // ! GDEF_ARCH_ENDIAN_BIG
1056 //=======================================================
1059 // FIXME: byte swap?
1061 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1062 // and the initial and final xor values shown below... in other words, the
1063 // CCITT standard CRC used by XMODEM
1065 #define CRC_INIT_VALUE 0xffff
1066 #define CRC_XOR_VALUE 0x0000
1068 static unsigned short crctable[256] =
1070 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1071 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1072 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1073 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1074 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1075 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1076 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1077 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1078 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1079 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1080 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1081 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1082 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1083 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1084 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1085 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1086 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1087 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1088 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1089 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1090 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1091 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1092 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1093 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1094 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1095 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1096 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1097 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1098 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1099 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1100 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1101 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1104 void CRC_Init( unsigned short *crcvalue ){
1105 *crcvalue = CRC_INIT_VALUE;
1108 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1109 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1112 unsigned short CRC_Value( unsigned short crcvalue ){
1113 return crcvalue ^ CRC_XOR_VALUE;
1115 //=============================================================================
1122 void CreatePath( const char *path ){
1130 if ( path[1] == ':' ) {
1131 olddrive = _getdrive();
1132 _chdrive( toupper( path[0] ) - 'A' + 1 );
1134 #endif // !GDEF_OS_WINDOWS
1136 if ( path[1] == ':' ) {
1140 for ( ofs = path + 1 ; *ofs ; ofs++ )
1143 if ( c == '/' || c == '\\' ) { // create the directory
1144 memcpy( dir, path, ofs - path );
1145 dir[ ofs - path ] = 0;
1151 if ( olddrive != -1 ) {
1152 _chdrive( olddrive );
1154 #endif // !GDEF_OS_WINDOWS
1162 Used to archive source files
1165 void QCopyFile( const char *from, const char *to ){
1169 length = LoadFile( from, &buffer );
1171 SaveFile( to, buffer, length );
1175 void Sys_Sleep( int n ){
1178 #else // !GDEF_OS_WINDOWS
1180 #endif // !GDEF_OS_WINDOWS