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
24 // from an intial copy of common/cmdlib.c
25 // stripped out the Sys_Printf Sys_Printf stuff
28 // merging alpha branch into trunk
29 // replaced qprintf with Sys_Printf
32 #include "globaldefs.h"
35 #include <sys/types.h>
47 #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
48 #define PATHSEPERATOR '/'
50 void *safe_malloc( size_t size ){
55 Error( "safe_malloc failed on allocation of %i bytes", size );
61 void *safe_malloc_info( size_t size, char* info ){
66 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
72 void *safe_malloc0( size_t size ){
75 p = calloc( 1, size );
77 Error( "safe_malloc0 failed on allocation of %i bytes", size );
83 void *safe_malloc0_info( size_t size, char* info ){
86 p = calloc( 1, size );
88 Error( "%s: safe_malloc0 failed on allocation of %i bytes", info, size );
94 // set these before calling CheckParm
102 char archivedir[1024];
109 Mimic unix command line expansion
112 #define MAX_EX_ARGC 1024
114 char *ex_argv[MAX_EX_ARGC];
118 void ExpandWildcards( int *argc, char ***argv ){
119 struct _finddata_t fileinfo;
127 for ( i = 0 ; i < *argc ; i++ )
131 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
132 ex_argv[ex_argc++] = path;
136 handle = _findfirst( path, &fileinfo );
137 if ( handle == -1 ) {
141 ExtractFilePath( path, filebase );
145 sprintf( filename, "%s%s", filebase, fileinfo.name );
146 ex_argv[ex_argc++] = copystring( filename );
147 } while ( _findnext( handle, &fileinfo ) != -1 );
149 _findclose( handle );
155 #else // !GDEF_OS_WINDOWS
156 void ExpandWildcards( int *argc, char ***argv ){
158 #endif // !GDEF_OS_WINDOWS
162 qdir will hold the path up to the quake directory, including the slash
167 gamedir will hold qdir + the game directory (id1, id2, etc)
175 void SetQdirFromPath( const char *path ){
181 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
183 strcat( temp, path );
187 // search for "quake2" in path
189 len = strlen( BASEDIRNAME );
190 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
194 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
196 //strncpy (qdir, path, c+len+2-path);
197 // the +2 assumes a 2 or 3 following quake which is not the
198 // case with a retail install
199 // so we need to add up how much to the next separator
202 while ( *sep && *sep != '/' && *sep != '\\' )
207 strncpy( qdir, path, c + len + count - path );
208 Sys_Printf( "qdir: %s\n", qdir );
209 for ( i = 0; i < (int) strlen( qdir ); i++ )
211 if ( qdir[i] == '\\' ) {
219 if ( *c == '/' || *c == '\\' ) {
220 strncpy( gamedir, path, c + 1 - path );
222 for ( i = 0; i < (int) strlen( gamedir ); i++ )
224 if ( gamedir[i] == '\\' ) {
229 Sys_Printf( "gamedir: %s\n", gamedir );
231 if ( !writedir[0] ) {
232 strcpy( writedir, gamedir );
234 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
235 writedir[strlen( writedir )] = '/';
236 writedir[strlen( writedir ) + 1] = 0;
243 Error( "No gamedir in %s", path );
247 Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
250 char *ExpandArg( const char *path ){
251 static char full[1024];
253 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
255 strcat( full, path );
258 strcpy( full, path );
263 char *ExpandPath( const char *path ){
264 static char full[1024];
265 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
266 strcpy( full, path );
269 sprintf( full, "%s%s", qdir, path );
273 char *copystring( const char *s ){
275 b = safe_malloc( strlen( s ) + 1 );
287 double I_FloatTime( void ){
294 // more precise, less portable
299 gettimeofday( &tp, &tzp );
303 return tp.tv_usec / 1000000.0;
306 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
310 void Q_getwd( char *out ){
316 #else // !GDEF_OS_WINDOWS
317 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
318 if ( !getcwd( out, 256 ) ) {
322 #endif // !GDEF_OS_WINDOWS
323 while ( out[i] != 0 )
325 if ( out[i] == '\\' ) {
333 void Q_mkdir( const char *path ){
335 const char *p = NULL;
340 const char *q = NULL;
341 if ( _mkdir( path ) != -1 ) {
344 if ( errno == ENOENT ) {
345 p = strrchr( path, '/' );
346 q = strrchr( path, '\\' );
347 if ( q && ( !p || q < p ) ) {
351 #else // !GDEF_OS_WINDOWS
352 if ( mkdir( path, 0777 ) != -1 ) {
355 if ( errno == ENOENT ) {
356 p = strrchr( path, '/' );
358 #endif // !GDEF_OS_WINDOWS
360 strncpy( parentbuf, path, sizeof( parentbuf ) );
361 if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
362 parentbuf[p - path] = 0;
363 Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
364 Q_mkdir( parentbuf );
370 if ( errno != EEXIST ) {
371 Error( "mkdir %s: %s",path, strerror( errno ) );
379 returns -1 if not present
382 int FileTime( const char *path ){
385 if ( stat( path,&buf ) == -1 ) {
398 Parse a token out of a string
401 char *COM_Parse( char *data ){
414 while ( ( c = *data ) <= ' ' )
418 return NULL; // end of file;
424 if ( c == '/' && data[1] == '/' ) {
425 while ( *data && *data != '\n' )
431 // handle quoted strings specially
446 // parse single characters
447 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
454 // parse a regular word
461 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
470 int Q_strncasecmp( const char *s1, const char *s2, int n ){
479 return 0; // strings are equal until end point
483 if ( c1 >= 'a' && c1 <= 'z' ) {
486 if ( c2 >= 'a' && c2 <= 'z' ) {
490 return -1; // strings not equal
495 return 0; // strings are equal
498 int Q_stricmp( 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
795 // FIXME: should include the slash, otherwise
796 // backing to an empty path will be wrong when appending a slash
797 void ExtractFilePath( const char *path, char *dest ){
800 src = path + strlen( path ) - 1;
803 // back up until a \ or the start
805 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
808 memcpy( dest, path, src - path );
809 dest[src - path] = 0;
812 void ExtractFileBase( const char *path, char *dest ){
815 src = path + strlen( path ) - 1;
818 // back up until a \ or the start
820 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
823 while ( *src && *src != '.' )
830 void ExtractFileExtension( const char *path, char *dest ){
833 src = path + strlen( path ) - 1;
836 // back up until a . or the start
838 while ( src != path && *( src - 1 ) != '.' )
841 *dest = 0; // no extension
854 int ParseHex( const char *hex ){
864 if ( *str >= '0' && *str <= '9' ) {
867 else if ( *str >= 'a' && *str <= 'f' ) {
868 num += 10 + *str - 'a';
870 else if ( *str >= 'A' && *str <= 'F' ) {
871 num += 10 + *str - 'A';
874 Error( "Bad hex number: %s",hex );
883 int ParseNum( const char *str ){
884 if ( str[0] == '$' ) {
885 return ParseHex( str + 1 );
887 if ( str[0] == '0' && str[1] == 'x' ) {
888 return ParseHex( str + 2 );
896 ============================================================================
900 ============================================================================
903 #if GDEF_ARCH_ENDIAN_BIG
905 short LittleShort( short l ){
909 b2 = ( l >> 8 ) & 255;
911 return ( b1 << 8 ) + b2;
914 short BigShort( short l ){
919 int LittleLong( int l ){
923 b2 = ( l >> 8 ) & 255;
924 b3 = ( l >> 16 ) & 255;
925 b4 = ( l >> 24 ) & 255;
927 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
930 int BigLong( int l ){
935 float LittleFloat( float l ){
936 union {byte b[4]; float f; } in, out;
947 float BigFloat( float l ){
951 #else // !GDEF_ARCH_ENDIAN_BIG
953 short BigShort( short l ){
957 b2 = ( l >> 8 ) & 255;
959 return ( b1 << 8 ) + b2;
962 short LittleShort( short l ){
967 int BigLong( int l ){
971 b2 = ( l >> 8 ) & 255;
972 b3 = ( l >> 16 ) & 255;
973 b4 = ( l >> 24 ) & 255;
975 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
978 int LittleLong( int l ){
982 float BigFloat( float l ){
983 union {byte b[4]; float f; } in, out;
994 float LittleFloat( float l ){
998 #endif // !GDEF_ARCH_ENDIAN_BIG
1001 //=======================================================
1004 // FIXME: byte swap?
1006 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1007 // and the initial and final xor values shown below... in other words, the
1008 // CCITT standard CRC used by XMODEM
1010 #define CRC_INIT_VALUE 0xffff
1011 #define CRC_XOR_VALUE 0x0000
1013 static unsigned short crctable[256] =
1015 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1016 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1017 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1018 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1019 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1020 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1021 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1022 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1023 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1024 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1025 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1026 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1027 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1028 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1029 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1030 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1031 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1032 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1033 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1034 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1035 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1036 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1037 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1038 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1039 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1040 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1041 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1042 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1043 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1044 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1045 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1046 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1049 void CRC_Init( unsigned short *crcvalue ){
1050 *crcvalue = CRC_INIT_VALUE;
1053 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1054 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1057 unsigned short CRC_Value( unsigned short crcvalue ){
1058 return crcvalue ^ CRC_XOR_VALUE;
1060 //=============================================================================
1067 void CreatePath( const char *path ){
1075 if ( path[1] == ':' ) {
1076 olddrive = _getdrive();
1077 _chdrive( toupper( path[0] ) - 'A' + 1 );
1079 #endif // !GDEF_OS_WINDOWS
1081 if ( path[1] == ':' ) {
1085 for ( ofs = path + 1 ; *ofs ; ofs++ )
1088 if ( c == '/' || c == '\\' ) { // create the directory
1089 memcpy( dir, path, ofs - path );
1090 dir[ ofs - path ] = 0;
1096 if ( olddrive != -1 ) {
1097 _chdrive( olddrive );
1099 #endif // !>GDEF_OS_WINDOWS
1107 Used to archive source files
1110 void QCopyFile( const char *from, const char *to ){
1114 length = LoadFile( from, &buffer );
1116 SaveFile( to, buffer, length );
1120 void Sys_Sleep( int n ){
1123 #else // !GDEF_OS_WINDOWS
1125 #endif // !GDEF_OS_WINDOWS