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 '/'
51 void *safe_malloc( size_t size ){
56 Error( "safe_malloc failed on allocation of %i bytes", size );
62 void *safe_malloc_info( size_t size, char* info ){
67 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
72 #endif // !SAFE_MALLOC
74 // set these before calling CheckParm
82 char archivedir[1024];
89 Mimic unix command line expansion
92 #define MAX_EX_ARGC 1024
94 char *ex_argv[MAX_EX_ARGC];
98 void ExpandWildcards( int *argc, char ***argv ){
99 struct _finddata_t fileinfo;
107 for ( i = 0 ; i < *argc ; i++ )
111 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
112 ex_argv[ex_argc++] = path;
116 handle = _findfirst( path, &fileinfo );
117 if ( handle == -1 ) {
121 ExtractFilePath( path, filebase );
125 sprintf( filename, "%s%s", filebase, fileinfo.name );
126 ex_argv[ex_argc++] = copystring( filename );
127 } while ( _findnext( handle, &fileinfo ) != -1 );
129 _findclose( handle );
135 #else // !GDEF_OS_WINDOWS
136 void ExpandWildcards( int *argc, char ***argv ){
138 #endif // !GDEF_OS_WINDOWS
142 qdir will hold the path up to the quake directory, including the slash
147 gamedir will hold qdir + the game directory (id1, id2, etc)
155 void SetQdirFromPath( const char *path ){
161 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
163 strcat( temp, path );
167 // search for "quake2" in path
169 len = strlen( BASEDIRNAME );
170 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
174 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
176 //strncpy (qdir, path, c+len+2-path);
177 // the +2 assumes a 2 or 3 following quake which is not the
178 // case with a retail install
179 // so we need to add up how much to the next separator
182 while ( *sep && *sep != '/' && *sep != '\\' )
187 strncpy( qdir, path, c + len + count - path );
188 Sys_Printf( "qdir: %s\n", qdir );
189 for ( i = 0; i < (int) strlen( qdir ); i++ )
191 if ( qdir[i] == '\\' ) {
199 if ( *c == '/' || *c == '\\' ) {
200 strncpy( gamedir, path, c + 1 - path );
202 for ( i = 0; i < (int) strlen( gamedir ); i++ )
204 if ( gamedir[i] == '\\' ) {
209 Sys_Printf( "gamedir: %s\n", gamedir );
211 if ( !writedir[0] ) {
212 strcpy( writedir, gamedir );
214 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
215 writedir[strlen( writedir )] = '/';
216 writedir[strlen( writedir ) + 1] = 0;
223 Error( "No gamedir in %s", path );
227 Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
230 char *ExpandArg( const char *path ){
231 static char full[1024];
233 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
235 strcat( full, path );
238 strcpy( full, path );
243 char *ExpandPath( const char *path ){
244 static char full[1024];
245 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
246 strcpy( full, path );
249 sprintf( full, "%s%s", qdir, path );
253 char *copystring( const char *s ){
255 b = safe_malloc( strlen( s ) + 1 );
267 double I_FloatTime( void ){
274 // more precise, less portable
279 gettimeofday( &tp, &tzp );
283 return tp.tv_usec / 1000000.0;
286 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
290 void Q_getwd( char *out ){
296 #else // !GDEF_OS_WINDOWS
297 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
298 if ( !getcwd( out, 256 ) ) {
302 #endif // !GDEF_OS_WINDOWS
303 while ( out[i] != 0 )
305 if ( out[i] == '\\' ) {
313 void Q_mkdir( const char *path ){
315 const char *p = NULL;
320 const char *q = NULL;
321 if ( _mkdir( path ) != -1 ) {
324 if ( errno == ENOENT ) {
325 p = strrchr( path, '/' );
326 q = strrchr( path, '\\' );
327 if ( q && ( !p || q < p ) ) {
331 #else // !GDEF_OS_WINDOWS
332 if ( mkdir( path, 0777 ) != -1 ) {
335 if ( errno == ENOENT ) {
336 p = strrchr( path, '/' );
338 #endif // !GDEF_OS_WINDOWS
340 strncpy( parentbuf, path, sizeof( parentbuf ) );
341 if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
342 parentbuf[p - path] = 0;
343 Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
344 Q_mkdir( parentbuf );
350 if ( errno != EEXIST ) {
351 Error( "mkdir %s: %s",path, strerror( errno ) );
359 returns -1 if not present
362 int FileTime( const char *path ){
365 if ( stat( path,&buf ) == -1 ) {
378 Parse a token out of a string
381 char *COM_Parse( char *data ){
394 while ( ( c = *data ) <= ' ' )
398 return NULL; // end of file;
404 if ( c == '/' && data[1] == '/' ) {
405 while ( *data && *data != '\n' )
411 // handle quoted strings specially
426 // parse single characters
427 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
434 // parse a regular word
441 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
450 int Q_strncasecmp( const char *s1, const char *s2, int n ){
459 return 0; // strings are equal until end point
463 if ( c1 >= 'a' && c1 <= 'z' ) {
466 if ( c2 >= 'a' && c2 <= 'z' ) {
470 return -1; // strings not equal
475 return 0; // strings are equal
478 int Q_stricmp( const char *s1, const char *s2 ){
479 return Q_strncasecmp( s1, s2, 99999 );
482 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
483 // started getting warnings about that function, prolly a duplicate with the runtime function
484 // maybe we still need to have it in linux builds
486 char *strupr (char *start)
499 char *strlower( char *start ){
504 *in = tolower( *in );
512 =============================================================================
516 =============================================================================
524 Checks for the given parameter in the program's command line arguments
525 Returns the argument number (1 to argc-1) or 0 if not present
528 int CheckParm( const char *check ){
531 for ( i = 1; i < myargc; i++ )
533 if ( !Q_stricmp( check, myargv[i] ) ) {
548 int Q_filelength( FILE *f ){
553 fseek( f, 0, SEEK_END );
555 fseek( f, pos, SEEK_SET );
561 FILE *SafeOpenWrite( const char *filename ){
564 f = fopen( filename, "wb" );
567 Error( "Error opening %s: %s",filename,strerror( errno ) );
573 FILE *SafeOpenRead( const char *filename ){
576 f = fopen( filename, "rb" );
579 Error( "Error opening %s: %s",filename,strerror( errno ) );
586 void SafeRead( FILE *f, void *buffer, int count ){
587 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
588 Error( "File read failure" );
593 void SafeWrite( FILE *f, const void *buffer, int count ){
594 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
595 Error( "File write failure" );
605 qboolean FileExists( const char *filename ){
608 f = fopen( filename, "r" );
621 int LoadFile( const char *filename, void **bufferptr ){
626 f = SafeOpenRead( filename );
627 length = Q_filelength( f );
628 buffer = safe_malloc( length + 1 );
629 ( (char *)buffer )[length] = 0;
630 SafeRead( f, buffer, length );
642 rounds up memory allocation to 4K boundry
646 int LoadFileBlock( const char *filename, void **bufferptr ){
648 int length, nBlock, nAllocSize;
651 f = SafeOpenRead( filename );
652 length = Q_filelength( f );
654 nBlock = nAllocSize % MEM_BLOCKSIZE;
656 nAllocSize += MEM_BLOCKSIZE - nBlock;
658 buffer = safe_malloc( nAllocSize + 1 );
659 memset( buffer, 0, nAllocSize + 1 );
660 SafeRead( f, buffer, length );
675 int TryLoadFile( const char *filename, void **bufferptr ){
682 f = fopen( filename, "rb" );
686 length = Q_filelength( f );
687 buffer = safe_malloc( length + 1 );
688 ( (char *)buffer )[length] = 0;
689 SafeRead( f, buffer, length );
702 void SaveFile( const char *filename, const void *buffer, int count ){
705 f = SafeOpenWrite( filename );
706 SafeWrite( f, buffer, count );
712 void DefaultExtension( char *path, const char *extension ){
715 // if path doesnt have a .EXT, append extension
716 // (extension should include the .)
718 src = path + strlen( path ) - 1;
720 while ( *src != '/' && *src != '\\' && src != path )
723 return; // it has an extension
728 strcat( path, extension );
732 void DefaultPath( char *path, const char *basepath ){
735 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
736 return; // absolute path location
739 strcpy( path,basepath );
744 void StripFilename( char *path ){
747 length = strlen( path ) - 1;
748 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
753 void StripExtension( char *path ){
756 length = strlen( path ) - 1;
757 while ( length > 0 && path[length] != '.' )
760 if ( path[length] == '/' || path[ length ] == '\\' ) {
761 return; // no extension
775 // FIXME: should include the slash, otherwise
776 // backing to an empty path will be wrong when appending a slash
777 void ExtractFilePath( const char *path, char *dest ){
780 src = path + strlen( path ) - 1;
783 // back up until a \ or the start
785 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
788 memcpy( dest, path, src - path );
789 dest[src - path] = 0;
792 void ExtractFileBase( const char *path, char *dest ){
795 src = path + strlen( path ) - 1;
798 // back up until a \ or the start
800 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
803 while ( *src && *src != '.' )
810 void ExtractFileExtension( const char *path, char *dest ){
813 src = path + strlen( path ) - 1;
816 // back up until a . or the start
818 while ( src != path && *( src - 1 ) != '.' )
821 *dest = 0; // no extension
834 int ParseHex( const char *hex ){
844 if ( *str >= '0' && *str <= '9' ) {
847 else if ( *str >= 'a' && *str <= 'f' ) {
848 num += 10 + *str - 'a';
850 else if ( *str >= 'A' && *str <= 'F' ) {
851 num += 10 + *str - 'A';
854 Error( "Bad hex number: %s",hex );
863 int ParseNum( const char *str ){
864 if ( str[0] == '$' ) {
865 return ParseHex( str + 1 );
867 if ( str[0] == '0' && str[1] == 'x' ) {
868 return ParseHex( str + 2 );
876 ============================================================================
880 ============================================================================
883 #if GDEF_ARCH_ENDIAN_BIG
885 short LittleShort( short l ){
889 b2 = ( l >> 8 ) & 255;
891 return ( b1 << 8 ) + b2;
894 short BigShort( short l ){
899 int LittleLong( int l ){
903 b2 = ( l >> 8 ) & 255;
904 b3 = ( l >> 16 ) & 255;
905 b4 = ( l >> 24 ) & 255;
907 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
910 int BigLong( int l ){
915 float LittleFloat( float l ){
916 union {byte b[4]; float f; } in, out;
927 float BigFloat( float l ){
931 #else // !GDEF_ARCH_ENDIAN_BIG
933 short BigShort( short l ){
937 b2 = ( l >> 8 ) & 255;
939 return ( b1 << 8 ) + b2;
942 short LittleShort( short l ){
947 int BigLong( int l ){
951 b2 = ( l >> 8 ) & 255;
952 b3 = ( l >> 16 ) & 255;
953 b4 = ( l >> 24 ) & 255;
955 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
958 int LittleLong( int l ){
962 float BigFloat( float l ){
963 union {byte b[4]; float f; } in, out;
974 float LittleFloat( float l ){
978 #endif // !GDEF_ARCH_ENDIAN_BIG
981 //=======================================================
986 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
987 // and the initial and final xor values shown below... in other words, the
988 // CCITT standard CRC used by XMODEM
990 #define CRC_INIT_VALUE 0xffff
991 #define CRC_XOR_VALUE 0x0000
993 static unsigned short crctable[256] =
995 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
996 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
997 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
998 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
999 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1000 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1001 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1002 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1003 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1004 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1005 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1006 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1007 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1008 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1009 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1010 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1011 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1012 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1013 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1014 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1015 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1016 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1017 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1018 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1019 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1020 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1021 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1022 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1023 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1024 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1025 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1026 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1029 void CRC_Init( unsigned short *crcvalue ){
1030 *crcvalue = CRC_INIT_VALUE;
1033 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1034 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1037 unsigned short CRC_Value( unsigned short crcvalue ){
1038 return crcvalue ^ CRC_XOR_VALUE;
1040 //=============================================================================
1047 void CreatePath( const char *path ){
1055 if ( path[1] == ':' ) {
1056 olddrive = _getdrive();
1057 _chdrive( toupper( path[0] ) - 'A' + 1 );
1059 #endif // !GDEF_OS_WINDOWS
1061 if ( path[1] == ':' ) {
1065 for ( ofs = path + 1 ; *ofs ; ofs++ )
1068 if ( c == '/' || c == '\\' ) { // create the directory
1069 memcpy( dir, path, ofs - path );
1070 dir[ ofs - path ] = 0;
1076 if ( olddrive != -1 ) {
1077 _chdrive( olddrive );
1079 #endif // !>GDEF_OS_WINDOWS
1087 Used to archive source files
1090 void QCopyFile( const char *from, const char *to ){
1094 length = LoadFile( from, &buffer );
1096 SaveFile( to, buffer, length );
1100 void Sys_Sleep( int n ){
1103 #else // !GDEF_OS_WINDOWS
1105 #endif // !GDEF_OS_WINDOWS