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 *ExpandGamePath( const char *path ){
256 static char full[1024];
257 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
258 strcpy( full, path );
261 sprintf( full, "%s%s", gamedir, path );
265 char *ExpandPathAndArchive( const char *path ){
267 char archivename[1024];
269 expanded = ExpandPath( path );
272 sprintf( archivename, "%s/%s", archivedir, path );
273 QCopyFile( expanded, archivename );
279 char *copystring( const char *s ){
281 b = safe_malloc( strlen( s ) + 1 );
293 double I_FloatTime( void ){
300 // more precise, less portable
305 gettimeofday( &tp, &tzp );
309 return tp.tv_usec / 1000000.0;
312 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
316 void Q_getwd( char *out ){
323 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
327 while ( out[i] != 0 )
329 if ( out[i] == '\\' ) {
337 void Q_mkdir( const char *path ){
339 if ( _mkdir( path ) != -1 ) {
343 if ( mkdir( path, 0777 ) != -1 ) {
347 if ( errno != EEXIST ) {
348 Error( "mkdir %s: %s",path, strerror( errno ) );
356 returns -1 if not present
359 int FileTime( const char *path ){
362 if ( stat( path,&buf ) == -1 ) {
375 Parse a token out of a string
378 char *COM_Parse( char *data ){
391 while ( ( c = *data ) <= ' ' )
395 return NULL; // end of file;
401 if ( c == '/' && data[1] == '/' ) {
402 while ( *data && *data != '\n' )
408 // handle quoted strings specially
423 // parse single characters
424 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
431 // parse a regular word
438 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
447 int Q_strncasecmp( const char *s1, const char *s2, int n ){
456 return 0; // strings are equal until end point
460 if ( c1 >= 'a' && c1 <= 'z' ) {
463 if ( c2 >= 'a' && c2 <= 'z' ) {
467 return -1; // strings not equal
472 return 0; // strings are equal
475 int Q_stricmp( const char *s1, const char *s2 ){
476 return Q_strncasecmp( s1, s2, 99999 );
479 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
480 // started getting warnings about that function, prolly a duplicate with the runtime function
481 // maybe we still need to have it in linux builds
483 char *strupr (char *start)
496 char *strlower( char *start ){
501 *in = tolower( *in );
509 =============================================================================
513 =============================================================================
521 Checks for the given parameter in the program's command line arguments
522 Returns the argument number (1 to argc-1) or 0 if not present
525 int CheckParm( const char *check ){
528 for ( i = 1; i < myargc; i++ )
530 if ( !Q_stricmp( check, myargv[i] ) ) {
545 int Q_filelength( FILE *f ){
550 fseek( f, 0, SEEK_END );
552 fseek( f, pos, SEEK_SET );
558 FILE *SafeOpenWrite( const char *filename ){
561 f = fopen( filename, "wb" );
564 Error( "Error opening %s: %s",filename,strerror( errno ) );
570 FILE *SafeOpenRead( const char *filename ){
573 f = fopen( filename, "rb" );
576 Error( "Error opening %s: %s",filename,strerror( errno ) );
583 void SafeRead( FILE *f, void *buffer, int count ){
584 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
585 Error( "File read failure" );
590 void SafeWrite( FILE *f, const void *buffer, int count ){
591 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
592 Error( "File write failure" );
602 qboolean FileExists( const char *filename ){
605 f = fopen( filename, "r" );
618 int LoadFile( const char *filename, void **bufferptr ){
623 f = SafeOpenRead( filename );
624 length = Q_filelength( f );
625 buffer = safe_malloc( length + 1 );
626 ( (char *)buffer )[length] = 0;
627 SafeRead( f, buffer, length );
639 rounds up memory allocation to 4K boundry
643 int LoadFileBlock( const char *filename, void **bufferptr ){
645 int length, nBlock, nAllocSize;
648 f = SafeOpenRead( filename );
649 length = Q_filelength( f );
651 nBlock = nAllocSize % MEM_BLOCKSIZE;
653 nAllocSize += MEM_BLOCKSIZE - nBlock;
655 buffer = safe_malloc( nAllocSize + 1 );
656 memset( buffer, 0, nAllocSize + 1 );
657 SafeRead( f, buffer, length );
672 int TryLoadFile( const char *filename, void **bufferptr ){
679 f = fopen( filename, "rb" );
683 length = Q_filelength( f );
684 buffer = safe_malloc( length + 1 );
685 ( (char *)buffer )[length] = 0;
686 SafeRead( f, buffer, length );
699 void SaveFile( const char *filename, const void *buffer, int count ){
702 f = SafeOpenWrite( filename );
703 SafeWrite( f, buffer, count );
709 void DefaultExtension( char *path, const char *extension ){
712 // if path doesnt have a .EXT, append extension
713 // (extension should include the .)
715 src = path + strlen( path ) - 1;
717 while ( *src != '/' && *src != '\\' && src != path )
720 return; // it has an extension
725 strcat( path, extension );
729 void DefaultPath( char *path, const char *basepath ){
732 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
733 return; // absolute path location
736 strcpy( path,basepath );
741 void StripFilename( char *path ){
744 length = strlen( path ) - 1;
745 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
750 void StripExtension( char *path ){
753 length = strlen( path ) - 1;
754 while ( length > 0 && path[length] != '.' )
757 if ( path[length] == '/' || path[ length ] == '\\' ) {
758 return; // no extension
772 // FIXME: should include the slash, otherwise
773 // backing to an empty path will be wrong when appending a slash
774 void ExtractFilePath( const char *path, char *dest ){
777 src = path + strlen( path ) - 1;
780 // back up until a \ or the start
782 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
785 memcpy( dest, path, src - path );
786 dest[src - path] = 0;
789 void ExtractFileBase( const char *path, char *dest ){
792 src = path + strlen( path ) - 1;
795 // back up until a \ or the start
797 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
800 while ( *src && *src != '.' )
807 void ExtractFileExtension( const char *path, char *dest ){
810 src = path + strlen( path ) - 1;
813 // back up until a . or the start
815 while ( src != path && *( src - 1 ) != '.' )
818 *dest = 0; // no extension
831 int ParseHex( const char *hex ){
841 if ( *str >= '0' && *str <= '9' ) {
844 else if ( *str >= 'a' && *str <= 'f' ) {
845 num += 10 + *str - 'a';
847 else if ( *str >= 'A' && *str <= 'F' ) {
848 num += 10 + *str - 'A';
851 Error( "Bad hex number: %s",hex );
860 int ParseNum( const char *str ){
861 if ( str[0] == '$' ) {
862 return ParseHex( str + 1 );
864 if ( str[0] == '0' && str[1] == 'x' ) {
865 return ParseHex( str + 2 );
873 ============================================================================
877 ============================================================================
881 #define __BIG_ENDIAN__
884 #ifdef __BIG_ENDIAN__
886 short LittleShort( short l ){
890 b2 = ( l >> 8 ) & 255;
892 return ( b1 << 8 ) + b2;
895 short BigShort( short l ){
900 int LittleLong( int l ){
904 b2 = ( l >> 8 ) & 255;
905 b3 = ( l >> 16 ) & 255;
906 b4 = ( l >> 24 ) & 255;
908 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
911 int BigLong( int l ){
916 float LittleFloat( float l ){
917 union {byte b[4]; float f; } in, out;
928 float BigFloat( float l ){
936 short BigShort( short l ){
940 b2 = ( l >> 8 ) & 255;
942 return ( b1 << 8 ) + b2;
945 short LittleShort( short l ){
950 int BigLong( int l ){
954 b2 = ( l >> 8 ) & 255;
955 b3 = ( l >> 16 ) & 255;
956 b4 = ( l >> 24 ) & 255;
958 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
961 int LittleLong( int l ){
965 float BigFloat( float l ){
966 union {byte b[4]; float f; } in, out;
977 float LittleFloat( float l ){
985 //=======================================================
990 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
991 // and the initial and final xor values shown below... in other words, the
992 // CCITT standard CRC used by XMODEM
994 #define CRC_INIT_VALUE 0xffff
995 #define CRC_XOR_VALUE 0x0000
997 static unsigned short crctable[256] =
999 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1000 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1001 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1002 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1003 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1004 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1005 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1006 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1007 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1008 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1009 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1010 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1011 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1012 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1013 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1014 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1015 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1016 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1017 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1018 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1019 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1020 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1021 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1022 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1023 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1024 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1025 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1026 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1027 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1028 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1029 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1030 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1033 void CRC_Init( unsigned short *crcvalue ){
1034 *crcvalue = CRC_INIT_VALUE;
1037 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1038 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1041 unsigned short CRC_Value( unsigned short crcvalue ){
1042 return crcvalue ^ CRC_XOR_VALUE;
1044 //=============================================================================
1051 void CreatePath( const char *path ){
1059 if ( path[1] == ':' ) {
1060 olddrive = _getdrive();
1061 _chdrive( toupper( path[0] ) - 'A' + 1 );
1065 if ( path[1] == ':' ) {
1069 for ( ofs = path + 1 ; *ofs ; ofs++ )
1072 if ( c == '/' || c == '\\' ) { // create the directory
1073 memcpy( dir, path, ofs - path );
1074 dir[ ofs - path ] = 0;
1080 if ( olddrive != -1 ) {
1081 _chdrive( olddrive );
1091 Used to archive source files
1094 void QCopyFile( const char *from, const char *to ){
1098 length = LoadFile( from, &buffer );
1100 SaveFile( to, buffer, length );
1104 void Sys_Sleep( int n ){
1108 #if defined ( __linux__ ) || defined ( __APPLE__ )