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
34 #include <sys/types.h>
42 #if defined ( __linux__ ) || defined ( __APPLE__ )
50 #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
51 #define PATHSEPERATOR '/'
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 // set these before calling CheckParm
85 char archivedir[1024];
92 Mimic unix command line expansion
95 #define MAX_EX_ARGC 1024
97 char *ex_argv[MAX_EX_ARGC];
100 void ExpandWildcards( int *argc, char ***argv ){
101 struct _finddata_t fileinfo;
109 for ( i = 0 ; i < *argc ; i++ )
113 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
114 ex_argv[ex_argc++] = path;
118 handle = _findfirst( path, &fileinfo );
119 if ( handle == -1 ) {
123 ExtractFilePath( path, filebase );
127 sprintf( filename, "%s%s", filebase, fileinfo.name );
128 ex_argv[ex_argc++] = copystring( filename );
129 } while ( _findnext( handle, &fileinfo ) != -1 );
131 _findclose( handle );
138 void ExpandWildcards( int *argc, char ***argv ){
144 qdir will hold the path up to the quake directory, including the slash
149 gamedir will hold qdir + the game directory (id1, id2, etc)
157 void SetQdirFromPath( const char *path ){
163 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
165 strcat( temp, path );
169 // search for "quake2" in path
171 len = strlen( BASEDIRNAME );
172 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
176 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
178 //strncpy (qdir, path, c+len+2-path);
179 // the +2 assumes a 2 or 3 following quake which is not the
180 // case with a retail install
181 // so we need to add up how much to the next separator
184 while ( *sep && *sep != '/' && *sep != '\\' )
189 strncpy( qdir, path, c + len + count - path );
190 Sys_Printf( "qdir: %s\n", qdir );
191 for ( i = 0; i < strlen( qdir ); i++ )
193 if ( qdir[i] == '\\' ) {
201 if ( *c == '/' || *c == '\\' ) {
202 strncpy( gamedir, path, c + 1 - path );
204 for ( i = 0; i < strlen( gamedir ); i++ )
206 if ( gamedir[i] == '\\' ) {
211 Sys_Printf( "gamedir: %s\n", gamedir );
213 if ( !writedir[0] ) {
214 strcpy( writedir, gamedir );
216 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
217 writedir[strlen( writedir )] = '/';
218 writedir[strlen( writedir ) + 1] = 0;
225 Error( "No gamedir in %s", path );
229 Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
232 char *ExpandArg( const char *path ){
233 static char full[1024];
235 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
237 strcat( full, path );
240 strcpy( full, path );
245 char *ExpandPath( const char *path ){
246 static char full[1024];
247 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
248 strcpy( full, path );
251 sprintf( full, "%s%s", qdir, path );
255 char *copystring( const char *s ){
257 b = safe_malloc( strlen( s ) + 1 );
269 double I_FloatTime( void ){
276 // more precise, less portable
281 gettimeofday( &tp, &tzp );
285 return tp.tv_usec / 1000000.0;
288 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
292 void Q_getwd( char *out ){
299 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
303 while ( out[i] != 0 )
305 if ( out[i] == '\\' ) {
313 void Q_mkdir( const char *path ){
315 if ( _mkdir( path ) != -1 ) {
319 if ( mkdir( path, 0777 ) != -1 ) {
323 if ( errno != EEXIST ) {
324 Error( "mkdir %s: %s",path, strerror( errno ) );
332 returns -1 if not present
335 int FileTime( const char *path ){
338 if ( stat( path,&buf ) == -1 ) {
351 Parse a token out of a string
354 char *COM_Parse( char *data ){
367 while ( ( c = *data ) <= ' ' )
371 return NULL; // end of file;
377 if ( c == '/' && data[1] == '/' ) {
378 while ( *data && *data != '\n' )
384 // handle quoted strings specially
399 // parse single characters
400 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
407 // parse a regular word
414 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
423 int Q_strncasecmp( const char *s1, const char *s2, int n ){
432 return 0; // strings are equal until end point
436 if ( c1 >= 'a' && c1 <= 'z' ) {
439 if ( c2 >= 'a' && c2 <= 'z' ) {
443 return -1; // strings not equal
448 return 0; // strings are equal
451 int Q_stricmp( const char *s1, const char *s2 ){
452 return Q_strncasecmp( s1, s2, 99999 );
455 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
456 // started getting warnings about that function, prolly a duplicate with the runtime function
457 // maybe we still need to have it in linux builds
459 char *strupr (char *start)
472 char *strlower( char *start ){
477 *in = tolower( *in );
485 =============================================================================
489 =============================================================================
497 Checks for the given parameter in the program's command line arguments
498 Returns the argument number (1 to argc-1) or 0 if not present
501 int CheckParm( const char *check ){
504 for ( i = 1; i < myargc; i++ )
506 if ( !Q_stricmp( check, myargv[i] ) ) {
521 int Q_filelength( FILE *f ){
526 fseek( f, 0, SEEK_END );
528 fseek( f, pos, SEEK_SET );
534 FILE *SafeOpenWrite( const char *filename ){
537 f = fopen( filename, "wb" );
540 Error( "Error opening %s: %s",filename,strerror( errno ) );
546 FILE *SafeOpenRead( const char *filename ){
549 f = fopen( filename, "rb" );
552 Error( "Error opening %s: %s",filename,strerror( errno ) );
559 void SafeRead( FILE *f, void *buffer, int count ){
560 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
561 Error( "File read failure" );
566 void SafeWrite( FILE *f, const void *buffer, int count ){
567 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
568 Error( "File write failure" );
578 qboolean FileExists( const char *filename ){
581 f = fopen( filename, "r" );
594 int LoadFile( const char *filename, void **bufferptr ){
599 f = SafeOpenRead( filename );
600 length = Q_filelength( f );
601 buffer = safe_malloc( length + 1 );
602 ( (char *)buffer )[length] = 0;
603 SafeRead( f, buffer, length );
615 rounds up memory allocation to 4K boundry
619 int LoadFileBlock( const char *filename, void **bufferptr ){
621 int length, nBlock, nAllocSize;
624 f = SafeOpenRead( filename );
625 length = Q_filelength( f );
627 nBlock = nAllocSize % MEM_BLOCKSIZE;
629 nAllocSize += MEM_BLOCKSIZE - nBlock;
631 buffer = safe_malloc( nAllocSize + 1 );
632 memset( buffer, 0, nAllocSize + 1 );
633 SafeRead( f, buffer, length );
648 int TryLoadFile( const char *filename, void **bufferptr ){
655 f = fopen( filename, "rb" );
659 length = Q_filelength( f );
660 buffer = safe_malloc( length + 1 );
661 ( (char *)buffer )[length] = 0;
662 SafeRead( f, buffer, length );
675 void SaveFile( const char *filename, const void *buffer, int count ){
678 f = SafeOpenWrite( filename );
679 SafeWrite( f, buffer, count );
685 void DefaultExtension( char *path, const char *extension ){
688 // if path doesnt have a .EXT, append extension
689 // (extension should include the .)
691 src = path + strlen( path ) - 1;
693 while ( *src != '/' && *src != '\\' && src != path )
696 return; // it has an extension
701 strcat( path, extension );
705 void DefaultPath( char *path, const char *basepath ){
708 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
709 return; // absolute path location
712 strcpy( path,basepath );
717 void StripFilename( char *path ){
720 length = strlen( path ) - 1;
721 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
726 void StripExtension( char *path ){
729 length = strlen( path ) - 1;
730 while ( length > 0 && path[length] != '.' )
733 if ( path[length] == '/' || path[ length ] == '\\' ) {
734 return; // no extension
748 // FIXME: should include the slash, otherwise
749 // backing to an empty path will be wrong when appending a slash
750 void ExtractFilePath( const char *path, char *dest ){
753 src = path + strlen( path ) - 1;
756 // back up until a \ or the start
758 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
761 memcpy( dest, path, src - path );
762 dest[src - path] = 0;
765 void ExtractFileBase( const char *path, char *dest ){
768 src = path + strlen( path ) - 1;
771 // back up until a \ or the start
773 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
776 while ( *src && *src != '.' )
783 void ExtractFileExtension( const char *path, char *dest ){
786 src = path + strlen( path ) - 1;
789 // back up until a . or the start
791 while ( src != path && *( src - 1 ) != '.' )
794 *dest = 0; // no extension
807 int ParseHex( const char *hex ){
817 if ( *str >= '0' && *str <= '9' ) {
820 else if ( *str >= 'a' && *str <= 'f' ) {
821 num += 10 + *str - 'a';
823 else if ( *str >= 'A' && *str <= 'F' ) {
824 num += 10 + *str - 'A';
827 Error( "Bad hex number: %s",hex );
836 int ParseNum( const char *str ){
837 if ( str[0] == '$' ) {
838 return ParseHex( str + 1 );
840 if ( str[0] == '0' && str[1] == 'x' ) {
841 return ParseHex( str + 2 );
849 ============================================================================
853 ============================================================================
857 #define __BIG_ENDIAN__
860 #ifdef __BIG_ENDIAN__
862 short LittleShort( short l ){
866 b2 = ( l >> 8 ) & 255;
868 return ( b1 << 8 ) + b2;
871 short BigShort( short l ){
876 int LittleLong( int l ){
880 b2 = ( l >> 8 ) & 255;
881 b3 = ( l >> 16 ) & 255;
882 b4 = ( l >> 24 ) & 255;
884 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
887 int BigLong( int l ){
892 float LittleFloat( float l ){
893 union {byte b[4]; float f; } in, out;
904 float BigFloat( float l ){
912 short BigShort( short l ){
916 b2 = ( l >> 8 ) & 255;
918 return ( b1 << 8 ) + b2;
921 short LittleShort( short l ){
926 int BigLong( int l ){
930 b2 = ( l >> 8 ) & 255;
931 b3 = ( l >> 16 ) & 255;
932 b4 = ( l >> 24 ) & 255;
934 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
937 int LittleLong( int l ){
941 float BigFloat( float l ){
942 union {byte b[4]; float f; } in, out;
953 float LittleFloat( float l ){
961 //=======================================================
966 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
967 // and the initial and final xor values shown below... in other words, the
968 // CCITT standard CRC used by XMODEM
970 #define CRC_INIT_VALUE 0xffff
971 #define CRC_XOR_VALUE 0x0000
973 static unsigned short crctable[256] =
975 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
976 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
977 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
978 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
979 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
980 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
981 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
982 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
983 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
984 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
985 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
986 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
987 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
988 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
989 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
990 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
991 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
992 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
993 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
994 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
995 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
996 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
997 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
998 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
999 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1000 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1001 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1002 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1003 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1004 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1005 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1006 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1009 void CRC_Init( unsigned short *crcvalue ){
1010 *crcvalue = CRC_INIT_VALUE;
1013 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1014 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1017 unsigned short CRC_Value( unsigned short crcvalue ){
1018 return crcvalue ^ CRC_XOR_VALUE;
1020 //=============================================================================
1027 void CreatePath( const char *path ){
1035 if ( path[1] == ':' ) {
1036 olddrive = _getdrive();
1037 _chdrive( toupper( path[0] ) - 'A' + 1 );
1041 if ( path[1] == ':' ) {
1045 for ( ofs = path + 1 ; *ofs ; ofs++ )
1048 if ( c == '/' || c == '\\' ) { // create the directory
1049 memcpy( dir, path, ofs - path );
1050 dir[ ofs - path ] = 0;
1056 if ( olddrive != -1 ) {
1057 _chdrive( olddrive );
1067 Used to archive source files
1070 void QCopyFile( const char *from, const char *to ){
1074 length = LoadFile( from, &buffer );
1076 SaveFile( to, buffer, length );
1080 void Sys_Sleep( int n ){
1084 #if defined ( __linux__ ) || defined ( __APPLE__ )