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 char *strlower( char *start ){
507 *in = tolower( *in );
515 =============================================================================
519 =============================================================================
527 Checks for the given parameter in the program's command line arguments
528 Returns the argument number (1 to argc-1) or 0 if not present
531 int CheckParm( const char *check ){
534 for ( i = 1; i < myargc; i++ )
536 if ( !Q_stricmp( check, myargv[i] ) ) {
551 int Q_filelength( FILE *f ){
556 fseek( f, 0, SEEK_END );
558 fseek( f, pos, SEEK_SET );
564 FILE *SafeOpenWrite( const char *filename ){
567 f = fopen( filename, "wb" );
570 Error( "Error opening %s: %s",filename,strerror( errno ) );
576 FILE *SafeOpenRead( const char *filename ){
579 f = fopen( filename, "rb" );
582 Error( "Error opening %s: %s",filename,strerror( errno ) );
589 void SafeRead( FILE *f, void *buffer, int count ){
590 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
591 Error( "File read failure" );
596 void SafeWrite( FILE *f, const void *buffer, int count ){
597 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
598 Error( "File write failure" );
608 qboolean FileExists( const char *filename ){
611 f = fopen( filename, "r" );
624 int LoadFile( const char *filename, void **bufferptr ){
629 f = SafeOpenRead( filename );
630 length = Q_filelength( f );
631 buffer = safe_malloc( length + 1 );
632 ( (char *)buffer )[length] = 0;
633 SafeRead( f, buffer, length );
645 rounds up memory allocation to 4K boundry
649 int LoadFileBlock( const char *filename, void **bufferptr ){
651 int length, nBlock, nAllocSize;
654 f = SafeOpenRead( filename );
655 length = Q_filelength( f );
657 nBlock = nAllocSize % MEM_BLOCKSIZE;
659 nAllocSize += MEM_BLOCKSIZE - nBlock;
661 buffer = safe_malloc0( nAllocSize + 1 );
662 SafeRead( f, buffer, length );
677 int TryLoadFile( const char *filename, void **bufferptr ){
684 f = fopen( filename, "rb" );
688 length = Q_filelength( f );
689 buffer = safe_malloc( length + 1 );
690 ( (char *)buffer )[length] = 0;
691 SafeRead( f, buffer, length );
704 void SaveFile( const char *filename, const void *buffer, int count ){
707 f = SafeOpenWrite( filename );
708 SafeWrite( f, buffer, count );
714 void DefaultExtension( char *path, const char *extension ){
717 // if path doesnt have a .EXT, append extension
718 // (extension should include the .)
720 src = path + strlen( path ) - 1;
722 while ( *src != '/' && *src != '\\' && src != path )
725 return; // it has an extension
730 strcat( path, extension );
734 void DefaultPath( char *path, const char *basepath ){
737 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
738 return; // absolute path location
741 strcpy( path,basepath );
746 void StripFilename( char *path ){
749 length = strlen( path ) - 1;
750 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
755 void StripExtension( char *path ){
758 length = strlen( path ) - 1;
759 while ( length > 0 && path[length] != '.' )
762 if ( path[length] == '/' || path[ length ] == '\\' ) {
763 return; // no extension
777 // FIXME: should include the slash, otherwise
778 // backing to an empty path will be wrong when appending a slash
779 void ExtractFilePath( const char *path, char *dest ){
782 src = path + strlen( path ) - 1;
785 // back up until a \ or the start
787 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
790 memcpy( dest, path, src - path );
791 dest[src - path] = 0;
794 void ExtractFileBase( const char *path, char *dest ){
797 src = path + strlen( path ) - 1;
800 // back up until a \ or the start
802 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
805 while ( *src && *src != '.' )
812 void ExtractFileExtension( 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 ) != '.' )
823 *dest = 0; // no extension
836 int ParseHex( const char *hex ){
846 if ( *str >= '0' && *str <= '9' ) {
849 else if ( *str >= 'a' && *str <= 'f' ) {
850 num += 10 + *str - 'a';
852 else if ( *str >= 'A' && *str <= 'F' ) {
853 num += 10 + *str - 'A';
856 Error( "Bad hex number: %s",hex );
865 int ParseNum( const char *str ){
866 if ( str[0] == '$' ) {
867 return ParseHex( str + 1 );
869 if ( str[0] == '0' && str[1] == 'x' ) {
870 return ParseHex( str + 2 );
878 ============================================================================
882 ============================================================================
885 #if GDEF_ARCH_ENDIAN_BIG
887 short LittleShort( short l ){
891 b2 = ( l >> 8 ) & 255;
893 return ( b1 << 8 ) + b2;
896 short BigShort( short l ){
901 int LittleLong( int l ){
905 b2 = ( l >> 8 ) & 255;
906 b3 = ( l >> 16 ) & 255;
907 b4 = ( l >> 24 ) & 255;
909 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
912 int BigLong( int l ){
917 float LittleFloat( float l ){
918 union {byte b[4]; float f; } in, out;
929 float BigFloat( float l ){
933 #else // !GDEF_ARCH_ENDIAN_BIG
935 short BigShort( short l ){
939 b2 = ( l >> 8 ) & 255;
941 return ( b1 << 8 ) + b2;
944 short LittleShort( short l ){
949 int BigLong( int l ){
953 b2 = ( l >> 8 ) & 255;
954 b3 = ( l >> 16 ) & 255;
955 b4 = ( l >> 24 ) & 255;
957 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
960 int LittleLong( int l ){
964 float BigFloat( float l ){
965 union {byte b[4]; float f; } in, out;
976 float LittleFloat( float l ){
980 #endif // !GDEF_ARCH_ENDIAN_BIG
983 //=======================================================
988 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
989 // and the initial and final xor values shown below... in other words, the
990 // CCITT standard CRC used by XMODEM
992 #define CRC_INIT_VALUE 0xffff
993 #define CRC_XOR_VALUE 0x0000
995 static unsigned short crctable[256] =
997 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
998 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
999 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1000 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1001 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1002 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1003 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1004 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1005 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1006 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1007 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1008 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1009 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1010 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1011 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1012 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1013 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1014 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1015 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1016 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1017 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1018 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1019 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1020 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1021 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1022 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1023 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1024 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1025 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1026 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1027 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1028 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1031 void CRC_Init( unsigned short *crcvalue ){
1032 *crcvalue = CRC_INIT_VALUE;
1035 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1036 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1039 unsigned short CRC_Value( unsigned short crcvalue ){
1040 return crcvalue ^ CRC_XOR_VALUE;
1042 //=============================================================================
1049 void CreatePath( const char *path ){
1057 if ( path[1] == ':' ) {
1058 olddrive = _getdrive();
1059 _chdrive( toupper( path[0] ) - 'A' + 1 );
1061 #endif // !GDEF_OS_WINDOWS
1063 if ( path[1] == ':' ) {
1067 for ( ofs = path + 1 ; *ofs ; ofs++ )
1070 if ( c == '/' || c == '\\' ) { // create the directory
1071 memcpy( dir, path, ofs - path );
1072 dir[ ofs - path ] = 0;
1078 if ( olddrive != -1 ) {
1079 _chdrive( olddrive );
1081 #endif // !>GDEF_OS_WINDOWS
1089 Used to archive source files
1092 void QCopyFile( const char *from, const char *to ){
1096 length = LoadFile( from, &buffer );
1098 SaveFile( to, buffer, length );
1102 void Sys_Sleep( int n ){
1105 #else // !GDEF_OS_WINDOWS
1107 #endif // !GDEF_OS_WINDOWS