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_malloc0( nAllocSize + 1 );
679 SafeRead( f, buffer, length );
694 int TryLoadFile( const char *filename, void **bufferptr ){
701 f = fopen( filename, "rb" );
705 length = Q_filelength( f );
706 buffer = safe_malloc( length + 1 );
707 ( (char *)buffer )[length] = 0;
708 SafeRead( f, buffer, length );
721 void SaveFile( const char *filename, const void *buffer, int count ){
724 f = SafeOpenWrite( filename );
725 SafeWrite( f, buffer, count );
731 void DefaultExtension( char *path, const char *extension ){
734 // if path doesnt have a .EXT, append extension
735 // (extension should include the .)
737 src = path + strlen( path ) - 1;
739 while ( *src != '/' && *src != '\\' && src != path )
742 return; // it has an extension
747 strcat( path, extension );
751 void DefaultPath( char *path, const char *basepath ){
754 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
755 return; // absolute path location
758 strcpy( path,basepath );
763 void StripFilename( char *path ){
766 length = strlen( path ) - 1;
767 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
772 void StripExtension( char *path ){
775 length = strlen( path ) - 1;
776 while ( length > 0 && path[length] != '.' )
779 if ( path[length] == '/' || path[ length ] == '\\' ) {
780 return; // no extension
794 // FIXME: should include the slash, otherwise
795 // backing to an empty path will be wrong when appending a slash
796 void ExtractFilePath( const char *path, char *dest ){
799 src = path + strlen( path ) - 1;
802 // back up until a \ or the start
804 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
807 memcpy( dest, path, src - path );
808 dest[src - path] = 0;
811 void ExtractFileBase( const char *path, char *dest ){
814 src = path + strlen( path ) - 1;
817 // back up until a \ or the start
819 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
822 while ( *src && *src != '.' )
829 void ExtractFileExtension( const char *path, char *dest ){
832 src = path + strlen( path ) - 1;
835 // back up until a . or the start
837 while ( src != path && *( src - 1 ) != '.' )
840 *dest = 0; // no extension
853 int ParseHex( const char *hex ){
863 if ( *str >= '0' && *str <= '9' ) {
866 else if ( *str >= 'a' && *str <= 'f' ) {
867 num += 10 + *str - 'a';
869 else if ( *str >= 'A' && *str <= 'F' ) {
870 num += 10 + *str - 'A';
873 Error( "Bad hex number: %s",hex );
882 int ParseNum( const char *str ){
883 if ( str[0] == '$' ) {
884 return ParseHex( str + 1 );
886 if ( str[0] == '0' && str[1] == 'x' ) {
887 return ParseHex( str + 2 );
895 ============================================================================
899 ============================================================================
902 #if GDEF_ARCH_ENDIAN_BIG
904 short LittleShort( short l ){
908 b2 = ( l >> 8 ) & 255;
910 return ( b1 << 8 ) + b2;
913 short BigShort( short l ){
918 int LittleLong( int l ){
922 b2 = ( l >> 8 ) & 255;
923 b3 = ( l >> 16 ) & 255;
924 b4 = ( l >> 24 ) & 255;
926 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
929 int BigLong( int l ){
934 float LittleFloat( float l ){
935 union {byte b[4]; float f; } in, out;
946 float BigFloat( float l ){
950 #else // !GDEF_ARCH_ENDIAN_BIG
952 short BigShort( short l ){
956 b2 = ( l >> 8 ) & 255;
958 return ( b1 << 8 ) + b2;
961 short LittleShort( short l ){
966 int BigLong( int l ){
970 b2 = ( l >> 8 ) & 255;
971 b3 = ( l >> 16 ) & 255;
972 b4 = ( l >> 24 ) & 255;
974 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
977 int LittleLong( int l ){
981 float BigFloat( float l ){
982 union {byte b[4]; float f; } in, out;
993 float LittleFloat( float l ){
997 #endif // !GDEF_ARCH_ENDIAN_BIG
1000 //=======================================================
1003 // FIXME: byte swap?
1005 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1006 // and the initial and final xor values shown below... in other words, the
1007 // CCITT standard CRC used by XMODEM
1009 #define CRC_INIT_VALUE 0xffff
1010 #define CRC_XOR_VALUE 0x0000
1012 static unsigned short crctable[256] =
1014 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1015 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1016 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1017 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1018 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1019 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1020 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1021 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1022 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1023 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1024 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1025 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1026 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1027 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1028 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1029 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1030 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1031 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1032 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1033 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1034 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1035 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1036 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1037 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1038 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1039 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1040 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1041 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1042 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1043 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1044 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1045 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1048 void CRC_Init( unsigned short *crcvalue ){
1049 *crcvalue = CRC_INIT_VALUE;
1052 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1053 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1056 unsigned short CRC_Value( unsigned short crcvalue ){
1057 return crcvalue ^ CRC_XOR_VALUE;
1059 //=============================================================================
1066 void CreatePath( const char *path ){
1074 if ( path[1] == ':' ) {
1075 olddrive = _getdrive();
1076 _chdrive( toupper( path[0] ) - 'A' + 1 );
1078 #endif // !GDEF_OS_WINDOWS
1080 if ( path[1] == ':' ) {
1084 for ( ofs = path + 1 ; *ofs ; ofs++ )
1087 if ( c == '/' || c == '\\' ) { // create the directory
1088 memcpy( dir, path, ofs - path );
1089 dir[ ofs - path ] = 0;
1095 if ( olddrive != -1 ) {
1096 _chdrive( olddrive );
1098 #endif // !>GDEF_OS_WINDOWS
1106 Used to archive source files
1109 void QCopyFile( const char *from, const char *to ){
1113 length = LoadFile( from, &buffer );
1115 SaveFile( to, buffer, length );
1119 void Sys_Sleep( int n ){
1122 #else // !GDEF_OS_WINDOWS
1124 #endif // !GDEF_OS_WINDOWS