2 Copyright (C) 1999-2006 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
27 #include <sys/types.h>
35 #if defined ( __linux__ ) || defined ( __APPLE__ )
43 #define BASEDIRNAME "h"
44 #define PATHSEPERATOR '/'
46 extern qboolean verbose;
48 qboolean g_dokeypress = false;
50 qboolean g_nomkdir = false;
54 void *safe_malloc( size_t size ){
59 Error( "safe_malloc failed on allocation of %i bytes", size );
65 void *safe_malloc_info( size_t size, char* info ){
70 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
77 void *SafeMalloc( size_t n, char *desc ){
80 if ( ( p = malloc( n ) ) == NULL ) {
81 Error( "Failed to allocate %d bytes for '%s'.\n", n, desc );
87 #if defined ( __linux__ ) || defined ( __APPLE__ )
88 void strlwr( char *conv_str ){
91 for ( i = 0; i < strlen( conv_str ); i++ )
92 conv_str[i] = tolower( conv_str[i] );
97 // set these before calling CheckParm
101 char com_token[1024];
105 char archivedir[1024];
112 Mimic unix command line expansion
115 #define MAX_EX_ARGC 1024
117 char *ex_argv[MAX_EX_ARGC];
120 void ExpandWildcards( int *argc, char ***argv ){
121 struct _finddata_t fileinfo;
129 for ( i = 0 ; i < *argc ; i++ )
133 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
134 ex_argv[ex_argc++] = path;
138 handle = _findfirst( path, &fileinfo );
139 if ( handle == -1 ) {
143 ExtractFilePath( path, filebase );
147 sprintf( filename, "%s%s", filebase, fileinfo.name );
148 ex_argv[ex_argc++] = copystring( filename );
149 } while ( _findnext( handle, &fileinfo ) != -1 );
151 _findclose( handle );
158 void ExpandWildcards( int *argc, char ***argv ){
164 qdir will hold the path up to the quake directory, including the slash
169 gamedir will hold qdir + the game directory (id1, id2, etc)
177 void SetQdirFromPath( const char *path ){
183 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
185 strcat( temp, path );
189 // search for "quake2" in path
191 len = strlen( BASEDIRNAME );
192 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
196 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
198 //strncpy (qdir, path, c+len+2-path);
199 // the +2 assumes a 2 or 3 following quake which is not the
200 // case with a retail install
201 // so we need to add up how much to the next separator
204 while ( *sep && *sep != '/' && *sep != '\\' )
209 strncpy( qdir, path, c + len + count - path );
210 Sys_Printf( "qdir: %s\n", qdir );
211 for ( i = 0; i < strlen( qdir ); i++ )
213 if ( qdir[i] == '\\' ) {
221 if ( *c == '/' || *c == '\\' ) {
222 strncpy( gamedir, path, c + 1 - path );
224 for ( i = 0; i < strlen( gamedir ); i++ )
226 if ( gamedir[i] == '\\' ) {
231 Sys_Printf( "gamedir: %s\n", gamedir );
233 if ( !writedir[0] ) {
234 strcpy( writedir, gamedir );
236 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
237 writedir[strlen( writedir )] = '/';
238 writedir[strlen( writedir ) + 1] = 0;
245 Error( "No gamedir in %s", path );
249 Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
252 char *ExpandArg( const char *path ){
253 static char full[1024];
255 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
257 strcat( full, path );
260 strcpy( full, path );
265 char *ExpandPath( const char *path ){
266 static char full[1024];
268 Error( "ExpandPath called without qdir set" );
270 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
271 strcpy( full, path );
274 sprintf( full, "%s%s", qdir, path );
278 char *ExpandGamePath( const char *path ){
279 static char full[1024];
281 Error( "ExpandGamePath called without qdir set" );
283 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
284 strcpy( full, path );
287 sprintf( full, "%s%s", gamedir, path );
291 char *ExpandPathAndArchive( const char *path ){
293 char archivename[1024];
295 expanded = ExpandPath( path );
298 sprintf( archivename, "%s/%s", archivedir, path );
299 QCopyFile( expanded, archivename );
305 char *copystring( const char *s ){
307 b = safe_malloc( strlen( s ) + 1 );
319 double I_FloatTime( void ){
326 // more precise, less portable
331 gettimeofday( &tp, &tzp );
335 return tp.tv_usec / 1000000.0;
338 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
342 void Q_getwd( char *out ){
349 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
353 while ( out[i] != 0 )
355 if ( out[i] == '\\' ) {
363 void Q_mkdir( const char *path ){
365 if ( _mkdir( path ) != -1 ) {
369 if ( mkdir( path, 0777 ) != -1 ) {
373 if ( errno != EEXIST ) {
374 Error( "mkdir %s: %s",path, strerror( errno ) );
382 returns -1 if not present
385 int FileTime( const char *path ){
388 if ( stat( path,&buf ) == -1 ) {
401 Parse a token out of a string
404 char *COM_Parse( char *data ){
417 while ( ( c = *data ) <= ' ' )
421 return NULL; // end of file;
427 if ( c == '/' && data[1] == '/' ) {
428 while ( *data && *data != '\n' )
434 // handle quoted strings specially
449 // parse single characters
450 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
457 // parse a regular word
464 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
473 int Q_strncasecmp( const char *s1, const char *s2, int n ){
482 return 0; // strings are equal until end point
486 if ( c1 >= 'a' && c1 <= 'z' ) {
489 if ( c2 >= 'a' && c2 <= 'z' ) {
493 return -1; // strings not equal
498 return 0; // strings are equal
501 int Q_stricmp( const char *s1, const char *s2 ){
502 return Q_strncasecmp( s1, s2, 99999 );
505 int Q_strcasecmp( const char *s1, const char *s2 ){
506 return Q_strncasecmp( s1, s2, 99999 );
509 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
510 // started getting warnings about that function, prolly a duplicate with the runtime function
511 // maybe we still need to have it in linux builds
513 char *strupr (char *start)
526 char *strlower( char *start ){
531 *in = tolower( *in );
539 =============================================================================
543 =============================================================================
551 Checks for the given parameter in the program's command line arguments
552 Returns the argument number (1 to argc-1) or 0 if not present
555 int CheckParm( const char *check ){
558 for ( i = 1; i < myargc; i++ )
560 if ( !Q_stricmp( check, myargv[i] ) ) {
575 int Q_filelength( FILE *f ){
580 fseek( f, 0, SEEK_END );
582 fseek( f, pos, SEEK_SET );
588 FILE *SafeOpenWrite( const char *filename ){
591 f = fopen( filename, "wb" );
594 Error( "Error opening %s: %s",filename,strerror( errno ) );
600 FILE *SafeOpenRead( const char *filename ){
603 f = fopen( filename, "rb" );
606 Error( "Error opening %s: %s",filename,strerror( errno ) );
613 void SafeRead( FILE *f, void *buffer, int count ){
614 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
615 Error( "File read failure" );
620 void SafeWrite( FILE *f, const void *buffer, int count ){
621 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
622 Error( "File write failure" );
632 qboolean FileExists( const char *filename ){
635 f = fopen( filename, "r" );
648 int LoadFile( const char *filename, void **bufferptr ){
653 f = SafeOpenRead( filename );
654 length = Q_filelength( f );
655 buffer = safe_malloc( length + 1 );
656 ( (char *)buffer )[length] = 0;
657 SafeRead( f, buffer, length );
669 rounds up memory allocation to 4K boundry
673 int LoadFileBlock( const char *filename, void **bufferptr ){
675 int length, nBlock, nAllocSize;
678 f = SafeOpenRead( filename );
679 length = Q_filelength( f );
681 nBlock = nAllocSize % MEM_BLOCKSIZE;
683 nAllocSize += MEM_BLOCKSIZE - nBlock;
685 buffer = safe_malloc( nAllocSize + 1 );
686 memset( buffer, 0, nAllocSize + 1 );
687 SafeRead( f, buffer, length );
702 int TryLoadFile( const char *filename, void **bufferptr ){
709 f = fopen( filename, "rb" );
713 length = Q_filelength( f );
714 buffer = safe_malloc( length + 1 );
715 ( (char *)buffer )[length] = 0;
716 SafeRead( f, buffer, length );
729 void SaveFile( const char *filename, const void *buffer, int count ){
732 f = SafeOpenWrite( filename );
733 SafeWrite( f, buffer, count );
739 void DefaultExtension( char *path, const char *extension ){
742 // if path doesnt have a .EXT, append extension
743 // (extension should include the .)
745 src = path + strlen( path ) - 1;
747 while ( *src != '/' && *src != '\\' && src != path )
750 return; // it has an extension
755 strcat( path, extension );
759 void DefaultPath( char *path, const char *basepath ){
762 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
763 return; // absolute path location
766 strcpy( path,basepath );
771 void StripFilename( char *path ){
774 length = strlen( path ) - 1;
775 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
780 void StripExtension( char *path ){
783 length = strlen( path ) - 1;
784 while ( length > 0 && path[length] != '.' )
787 if ( path[length] == '/' || path[ length ] == '\\' ) {
788 return; // no extension
802 // FIXME: should include the slash, otherwise
803 // backing to an empty path will be wrong when appending a slash
804 void ExtractFilePath( const char *path, char *dest ){
807 src = path + strlen( path ) - 1;
810 // back up until a \ or the start
812 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
815 memcpy( dest, path, src - path );
816 dest[src - path] = 0;
819 void ExtractFileBase( const char *path, char *dest ){
822 src = path + strlen( path ) - 1;
825 // back up until a \ or the start
827 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
830 while ( *src && *src != '.' )
837 void ExtractFileExtension( const char *path, char *dest ){
840 src = path + strlen( path ) - 1;
843 // back up until a . or the start
845 while ( src != path && *( src - 1 ) != '.' )
848 *dest = 0; // no extension
861 int ParseHex( const char *hex ){
871 if ( *str >= '0' && *str <= '9' ) {
874 else if ( *str >= 'a' && *str <= 'f' ) {
875 num += 10 + *str - 'a';
877 else if ( *str >= 'A' && *str <= 'F' ) {
878 num += 10 + *str - 'A';
881 Error( "Bad hex number: %s",hex );
890 int ParseNum( const char *str ){
891 if ( str[0] == '$' ) {
892 return ParseHex( str + 1 );
894 if ( str[0] == '0' && str[1] == 'x' ) {
895 return ParseHex( str + 2 );
900 // all output ends up through here
901 void FPrintf (int flag, char *buf)
907 void Sys_FPrintf (int flag, const char *format, ...)
909 char out_buffer[4096];
912 if ((flag == SYS_VRB) && (verbose == false))
915 va_start (argptr, format);
916 vsprintf (out_buffer, format, argptr);
919 FPrintf (flag, out_buffer);
922 void Sys_Printf (const char *format, ...)
924 char out_buffer[4096];
927 va_start (argptr, format);
928 vsprintf (out_buffer, format, argptr);
931 FPrintf (SYS_STD, out_buffer);
937 //For abnormal program terminations
940 void Error( const char *error, ...)
942 char out_buffer[4096];
946 va_start (argptr,error);
947 vsprintf (tmp, error, argptr);
950 sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
952 FPrintf( SYS_ERR, out_buffer );
960 ============================================================================
964 ============================================================================
968 #define __BIG_ENDIAN__
971 #ifdef __BIG_ENDIAN__
973 short LittleShort( short l ){
977 b2 = ( l >> 8 ) & 255;
979 return ( b1 << 8 ) + b2;
982 short BigShort( short l ){
987 int LittleLong( int l ){
991 b2 = ( l >> 8 ) & 255;
992 b3 = ( l >> 16 ) & 255;
993 b4 = ( l >> 24 ) & 255;
995 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
998 int BigLong( int l ){
1003 float LittleFloat( float l ){
1004 union {byte b[4]; float f; } in, out;
1015 float BigFloat( float l ){
1023 short BigShort( short l ){
1027 b2 = ( l >> 8 ) & 255;
1029 return ( b1 << 8 ) + b2;
1032 short LittleShort( short l ){
1037 int BigLong( int l ){
1041 b2 = ( l >> 8 ) & 255;
1042 b3 = ( l >> 16 ) & 255;
1043 b4 = ( l >> 24 ) & 255;
1045 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
1048 int LittleLong( int l ){
1052 float BigFloat( float l ){
1053 union {byte b[4]; float f; } in, out;
1064 float LittleFloat( float l ){
1072 //=======================================================
1075 // FIXME: byte swap?
1077 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1078 // and the initial and final xor values shown below... in other words, the
1079 // CCITT standard CRC used by XMODEM
1081 #define CRC_INIT_VALUE 0xffff
1082 #define CRC_XOR_VALUE 0x0000
1084 static unsigned short crctable[256] =
1086 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1087 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1088 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1089 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1090 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1091 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1092 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1093 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1094 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1095 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1096 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1097 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1098 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1099 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1100 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1101 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1102 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1103 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1104 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1105 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1106 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1107 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1108 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1109 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1110 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1111 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1112 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1113 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1114 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1115 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1116 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1117 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1120 void CRC_Init( unsigned short *crcvalue ){
1121 *crcvalue = CRC_INIT_VALUE;
1124 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1125 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1128 unsigned short CRC_Value( unsigned short crcvalue ){
1129 return crcvalue ^ CRC_XOR_VALUE;
1131 //=============================================================================
1138 void CreatePath( const char *path ){
1146 if ( path[1] == ':' ) {
1147 olddrive = _getdrive();
1148 _chdrive( toupper( path[0] ) - 'A' + 1 );
1152 if ( path[1] == ':' ) {
1156 for ( ofs = path + 1 ; *ofs ; ofs++ )
1159 if ( c == '/' || c == '\\' ) { // create the directory
1160 memcpy( dir, path, ofs - path );
1161 dir[ ofs - path ] = 0;
1167 if ( olddrive != -1 ) {
1168 _chdrive( olddrive );
1178 Used to archive source files
1181 void QCopyFile( const char *from, const char *to ){
1185 length = LoadFile( from, &buffer );
1187 SaveFile( to, buffer, length );
1191 void Sys_Sleep( int n ){
1195 #if defined ( __linux__ ) || defined ( __APPLE__ )