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;
55 void *safe_malloc( size_t size ){
60 Error( "safe_malloc failed on allocation of %i bytes", size );
66 void *safe_malloc_info( size_t size, char* info ){
71 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
76 #endif // !SAFE_MALLOC
78 void *SafeMalloc( size_t n, char *desc ){
81 if ( ( p = malloc( n ) ) == NULL ) {
82 Error( "Failed to allocate %d bytes for '%s'.\n", n, desc );
88 // set these before calling CheckParm
96 char archivedir[1024];
103 Mimic unix command line expansion
106 #define MAX_EX_ARGC 1024
109 char *ex_argv[MAX_EX_ARGC];
113 void ExpandWildcards( int *argc, char ***argv ){
114 struct _finddata_t fileinfo;
122 for ( i = 0 ; i < *argc ; i++ )
126 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
127 ex_argv[ex_argc++] = path;
131 handle = _findfirst( path, &fileinfo );
132 if ( handle == -1 ) {
136 ExtractFilePath( path, filebase );
140 sprintf( filename, "%s%s", filebase, fileinfo.name );
141 ex_argv[ex_argc++] = copystring( filename );
142 } while ( _findnext( handle, &fileinfo ) != -1 );
144 _findclose( handle );
150 #else // !GDEF_OS_WINDOWS
151 void ExpandWildcards( int *argc, char ***argv ){
153 #endif // !GDEF_OS_WINDOWS
157 qdir will hold the path up to the quake directory, including the slash
162 gamedir will hold qdir + the game directory (id1, id2, etc)
170 void SetQdirFromPath( const char *path ){
176 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
178 strcat( temp, path );
182 // search for "quake2" in path
184 len = strlen( BASEDIRNAME );
185 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
189 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
191 //strncpy (qdir, path, c+len+2-path);
192 // the +2 assumes a 2 or 3 following quake which is not the
193 // case with a retail install
194 // so we need to add up how much to the next separator
197 while ( *sep && *sep != '/' && *sep != '\\' )
202 strncpy( qdir, path, c + len + count - path );
203 Sys_Printf( "qdir: %s\n", qdir );
204 for ( i = 0; i < strlen( qdir ); i++ )
206 if ( qdir[i] == '\\' ) {
214 if ( *c == '/' || *c == '\\' ) {
215 strncpy( gamedir, path, c + 1 - path );
217 for ( i = 0; i < strlen( gamedir ); i++ )
219 if ( gamedir[i] == '\\' ) {
224 Sys_Printf( "gamedir: %s\n", gamedir );
226 if ( !writedir[0] ) {
227 strcpy( writedir, gamedir );
229 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
230 writedir[strlen( writedir )] = '/';
231 writedir[strlen( writedir ) + 1] = 0;
238 Error( "No gamedir in %s", path );
242 Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
245 char *ExpandArg( const char *path ){
246 static char full[1024];
248 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
250 strcat( full, path );
253 strcpy( full, path );
258 char *ExpandPath( const char *path ){
259 static char full[1024];
261 Error( "ExpandPath called without qdir set" );
263 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
264 strcpy( full, path );
267 sprintf( full, "%s%s", qdir, path );
271 char *ExpandGamePath( const char *path ){
272 static char full[1024];
274 Error( "ExpandGamePath called without qdir set" );
276 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
277 strcpy( full, path );
280 sprintf( full, "%s%s", gamedir, path );
284 char *ExpandPathAndArchive( const char *path ){
286 char archivename[1024];
288 expanded = ExpandPath( path );
291 sprintf( archivename, "%s/%s", archivedir, path );
292 QCopyFile( expanded, archivename );
298 char *copystring( const char *s ){
300 b = safe_malloc( strlen( s ) + 1 );
312 double I_FloatTime( void ){
319 // more precise, less portable
324 gettimeofday( &tp, &tzp );
328 return tp.tv_usec / 1000000.0;
331 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
335 void Q_getwd( char *out ){
341 #else // !GDEF_OS_WINDOWS
342 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
345 #endif // !GDEF_OS_WINDOWS
346 while ( out[i] != 0 )
348 if ( out[i] == '\\' ) {
356 void Q_mkdir( const char *path ){
358 if ( _mkdir( path ) != -1 ) {
361 #else // !GDEF_OS_WINDOWS
362 if ( mkdir( path, 0777 ) != -1 ) {
365 #endif // !GDEF_OS_WINDOWS
366 if ( errno != EEXIST ) {
367 Error( "mkdir %s: %s",path, strerror( errno ) );
375 returns -1 if not present
378 int FileTime( const char *path ){
381 if ( stat( path,&buf ) == -1 ) {
394 Parse a token out of a string
397 char *COM_Parse( char *data ){
410 while ( ( c = *data ) <= ' ' )
414 return NULL; // end of file;
420 if ( c == '/' && data[1] == '/' ) {
421 while ( *data && *data != '\n' )
427 // handle quoted strings specially
442 // parse single characters
443 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
450 // parse a regular word
457 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
466 int Q_strncasecmp( const char *s1, const char *s2, int n ){
475 return 0; // strings are equal until end point
479 if ( c1 >= 'a' && c1 <= 'z' ) {
482 if ( c2 >= 'a' && c2 <= 'z' ) {
486 return -1; // strings not equal
491 return 0; // strings are equal
494 int Q_stricmp( const char *s1, const char *s2 ){
495 return Q_strncasecmp( s1, s2, 99999 );
498 int Q_strcasecmp( const char *s1, const char *s2 ){
499 return Q_strncasecmp( s1, s2, 99999 );
502 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
503 // started getting warnings about that function, prolly a duplicate with the runtime function
504 // maybe we still need to have it in linux builds
506 char *strupr (char *start)
519 char *strlower( char *start ){
524 *in = tolower( *in );
532 =============================================================================
536 =============================================================================
544 Checks for the given parameter in the program's command line arguments
545 Returns the argument number (1 to argc-1) or 0 if not present
548 int CheckParm( const char *check ){
551 for ( i = 1; i < myargc; i++ )
553 if ( !Q_stricmp( check, myargv[i] ) ) {
568 int Q_filelength( FILE *f ){
573 fseek( f, 0, SEEK_END );
575 fseek( f, pos, SEEK_SET );
581 FILE *SafeOpenWrite( const char *filename ){
584 f = fopen( filename, "wb" );
587 Error( "Error opening %s: %s",filename,strerror( errno ) );
593 FILE *SafeOpenRead( const char *filename ){
596 f = fopen( filename, "rb" );
599 Error( "Error opening %s: %s",filename,strerror( errno ) );
606 void SafeRead( FILE *f, void *buffer, int count ){
607 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
608 Error( "File read failure" );
613 void SafeWrite( FILE *f, const void *buffer, int count ){
614 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
615 Error( "File write failure" );
625 qboolean FileExists( const char *filename ){
628 f = fopen( filename, "r" );
641 int LoadFile( const char *filename, void **bufferptr ){
646 f = SafeOpenRead( filename );
647 length = Q_filelength( f );
648 buffer = safe_malloc( length + 1 );
649 ( (char *)buffer )[length] = 0;
650 SafeRead( f, buffer, length );
662 rounds up memory allocation to 4K boundry
666 int LoadFileBlock( const char *filename, void **bufferptr ){
668 int length, nBlock, nAllocSize;
671 f = SafeOpenRead( filename );
672 length = Q_filelength( f );
674 nBlock = nAllocSize % MEM_BLOCKSIZE;
676 nAllocSize += MEM_BLOCKSIZE - nBlock;
678 buffer = safe_malloc( nAllocSize + 1 );
679 memset( buffer, 0, nAllocSize + 1 );
680 SafeRead( f, buffer, length );
695 int TryLoadFile( const char *filename, void **bufferptr ){
702 f = fopen( filename, "rb" );
706 length = Q_filelength( f );
707 buffer = safe_malloc( length + 1 );
708 ( (char *)buffer )[length] = 0;
709 SafeRead( f, buffer, length );
722 void SaveFile( const char *filename, const void *buffer, int count ){
725 f = SafeOpenWrite( filename );
726 SafeWrite( f, buffer, count );
732 void DefaultExtension( char *path, const char *extension ){
735 // if path doesnt have a .EXT, append extension
736 // (extension should include the .)
738 src = path + strlen( path ) - 1;
740 while ( *src != '/' && *src != '\\' && src != path )
743 return; // it has an extension
748 strcat( path, extension );
752 void DefaultPath( char *path, const char *basepath ){
755 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
756 return; // absolute path location
759 strcpy( path,basepath );
764 void StripFilename( char *path ){
767 length = strlen( path ) - 1;
768 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
773 void StripExtension( char *path ){
776 length = strlen( path ) - 1;
777 while ( length > 0 && path[length] != '.' )
780 if ( path[length] == '/' || path[ length ] == '\\' ) {
781 return; // no extension
796 // FIXME: should include the slash, otherwise
797 // backing to an empty path will be wrong when appending a slash
798 void ExtractFilePath( const char *path, char *dest ){
801 src = path + strlen( path ) - 1;
804 // back up until a \ or the start
806 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
809 memcpy( dest, path, src - path );
810 dest[src - path] = 0;
813 void ExtractFileBase( const char *path, char *dest ){
816 src = path + strlen( path ) - 1;
819 // back up until a \ or the start
821 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
824 while ( *src && *src != '.' )
831 void ExtractFileExtension( const char *path, char *dest ){
834 src = path + strlen( path ) - 1;
837 // back up until a . or the start
839 while ( src != path && *( src - 1 ) != '.' )
842 *dest = 0; // no extension
855 int ParseHex( const char *hex ){
865 if ( *str >= '0' && *str <= '9' ) {
868 else if ( *str >= 'a' && *str <= 'f' ) {
869 num += 10 + *str - 'a';
871 else if ( *str >= 'A' && *str <= 'F' ) {
872 num += 10 + *str - 'A';
875 Error( "Bad hex number: %s",hex );
884 int ParseNum( const char *str ){
885 if ( str[0] == '$' ) {
886 return ParseHex( str + 1 );
888 if ( str[0] == '0' && str[1] == 'x' ) {
889 return ParseHex( str + 2 );
894 // all output ends up through here
895 void FPrintf (int flag, char *buf)
901 void Sys_FPrintf (int flag, const char *format, ...)
903 char out_buffer[4096];
906 if ((flag == SYS_VRB) && (verbose == false))
909 va_start (argptr, format);
910 vsprintf (out_buffer, format, argptr);
913 FPrintf (flag, out_buffer);
916 void Sys_Printf (const char *format, ...)
918 char out_buffer[4096];
921 va_start (argptr, format);
922 vsprintf (out_buffer, format, argptr);
925 FPrintf (SYS_STD, out_buffer);
931 //For abnormal program terminations
934 void Error( const char *error, ...)
936 char out_buffer[4096];
940 va_start (argptr,error);
941 vsprintf (tmp, error, argptr);
944 sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
946 FPrintf( SYS_ERR, out_buffer );
954 ============================================================================
958 ============================================================================
961 #if GDEF_ARCH_ENDIAN_BIG
963 short LittleShort( short l ){
967 b2 = ( l >> 8 ) & 255;
969 return ( b1 << 8 ) + b2;
972 short BigShort( short l ){
977 int LittleLong( int l ){
981 b2 = ( l >> 8 ) & 255;
982 b3 = ( l >> 16 ) & 255;
983 b4 = ( l >> 24 ) & 255;
985 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
988 int BigLong( int l ){
993 float LittleFloat( float l ){
994 union {byte b[4]; float f; } in, out;
1005 float BigFloat( float l ){
1010 #else // !GDEF_ARCH_ENDIAN_BIG
1013 short BigShort( short l ){
1017 b2 = ( l >> 8 ) & 255;
1019 return ( b1 << 8 ) + b2;
1022 short LittleShort( short l ){
1027 int BigLong( int l ){
1031 b2 = ( l >> 8 ) & 255;
1032 b3 = ( l >> 16 ) & 255;
1033 b4 = ( l >> 24 ) & 255;
1035 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
1038 int LittleLong( int l ){
1042 float BigFloat( float l ){
1043 union {byte b[4]; float f; } in, out;
1054 float LittleFloat( float l ){
1058 #endif // ! GDEF_ARCH_ENDIAN_BIG
1061 //=======================================================
1064 // FIXME: byte swap?
1066 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1067 // and the initial and final xor values shown below... in other words, the
1068 // CCITT standard CRC used by XMODEM
1070 #define CRC_INIT_VALUE 0xffff
1071 #define CRC_XOR_VALUE 0x0000
1073 static unsigned short crctable[256] =
1075 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1076 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1077 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1078 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1079 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1080 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1081 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1082 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1083 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1084 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1085 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1086 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1087 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1088 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1089 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1090 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1091 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1092 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1093 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1094 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1095 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1096 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1097 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1098 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1099 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1100 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1101 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1102 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1103 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1104 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1105 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1106 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1109 void CRC_Init( unsigned short *crcvalue ){
1110 *crcvalue = CRC_INIT_VALUE;
1113 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1114 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1117 unsigned short CRC_Value( unsigned short crcvalue ){
1118 return crcvalue ^ CRC_XOR_VALUE;
1120 //=============================================================================
1127 void CreatePath( const char *path ){
1135 if ( path[1] == ':' ) {
1136 olddrive = _getdrive();
1137 _chdrive( toupper( path[0] ) - 'A' + 1 );
1139 #endif // !GDEF_OS_WINDOWS
1141 if ( path[1] == ':' ) {
1145 for ( ofs = path + 1 ; *ofs ; ofs++ )
1148 if ( c == '/' || c == '\\' ) { // create the directory
1149 memcpy( dir, path, ofs - path );
1150 dir[ ofs - path ] = 0;
1156 if ( olddrive != -1 ) {
1157 _chdrive( olddrive );
1159 #endif // !GDEF_OS_WINDOWS
1167 Used to archive source files
1170 void QCopyFile( const char *from, const char *to ){
1174 length = LoadFile( from, &buffer );
1176 SaveFile( to, buffer, length );
1180 void Sys_Sleep( int n ){
1183 #else // !GDEF_OS_WINDOWS
1185 #endif // !GDEF_OS_WINDOWS