2 Copyright (C) 1999-2006 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 < (int) strlen( qdir ); i++ )
193 if ( qdir[i] == '\\' ) {
201 if ( *c == '/' || *c == '\\' ) {
202 strncpy( gamedir, path, c + 1 - path );
204 for ( i = 0; i < (int) 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];
248 Error( "ExpandPath called without qdir set" );
250 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
251 strcpy( full, path );
254 sprintf( full, "%s%s", qdir, path );
258 char *ExpandGamePath( const char *path ){
259 static char full[1024];
261 Error( "ExpandGamePath called without gamedir set" );
263 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
264 strcpy( full, path );
267 sprintf( full, "%s%s", gamedir, path );
271 char *ExpandPathAndArchive( const char *path ){
273 char archivename[1024];
275 expanded = ExpandPath( path );
278 sprintf( archivename, "%s/%s", archivedir, path );
279 QCopyFile( expanded, archivename );
285 char *copystring( const char *s ){
287 b = safe_malloc( strlen( s ) + 1 );
299 double I_FloatTime( void ){
306 // more precise, less portable
311 gettimeofday( &tp, &tzp );
315 return tp.tv_usec / 1000000.0;
318 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
322 void Q_getwd( char *out ){
329 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
330 if ( !getcwd( out, 256 ) ) {
335 while ( out[i] != 0 )
337 if ( out[i] == '\\' ) {
345 void Q_mkdir( const char *path ){
347 const char *p = NULL;
352 const char *q = NULL;
353 if ( _mkdir( path ) != -1 ) {
356 if ( errno == ENOENT ) {
357 p = strrchr( path, '/' );
358 q = strrchr( path, '\\' );
359 if ( q && ( !p || q < p ) ) {
364 if ( mkdir( path, 0777 ) != -1 ) {
367 if ( errno == ENOENT ) {
368 p = strrchr( path, '/' );
372 strncpy( parentbuf, path, sizeof( parentbuf ) );
373 if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
374 parentbuf[p - path] = 0;
375 Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
376 Q_mkdir( parentbuf );
382 if ( errno != EEXIST ) {
383 Error( "mkdir %s: %s",path, strerror( errno ) );
391 returns -1 if not present
394 int FileTime( const char *path ){
397 if ( stat( path,&buf ) == -1 ) {
410 Parse a token out of a string
413 char *COM_Parse( char *data ){
426 while ( ( c = *data ) <= ' ' )
430 return NULL; // end of file;
436 if ( c == '/' && data[1] == '/' ) {
437 while ( *data && *data != '\n' )
443 // handle quoted strings specially
458 // parse single characters
459 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
466 // parse a regular word
473 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
482 int Q_strncasecmp( const char *s1, const char *s2, int n ){
491 return 0; // strings are equal until end point
495 if ( c1 >= 'a' && c1 <= 'z' ) {
498 if ( c2 >= 'a' && c2 <= 'z' ) {
502 return -1; // strings not equal
507 return 0; // strings are equal
510 int Q_stricmp( const char *s1, const char *s2 ){
511 return Q_strncasecmp( s1, s2, 99999 );
514 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
515 // started getting warnings about that function, prolly a duplicate with the runtime function
516 // maybe we still need to have it in linux builds
518 char *strupr (char *start)
531 char *strlower( char *start ){
536 *in = tolower( *in );
544 =============================================================================
548 =============================================================================
556 Checks for the given parameter in the program's command line arguments
557 Returns the argument number (1 to argc-1) or 0 if not present
560 int CheckParm( const char *check ){
563 for ( i = 1; i < myargc; i++ )
565 if ( !Q_stricmp( check, myargv[i] ) ) {
580 int Q_filelength( FILE *f ){
585 fseek( f, 0, SEEK_END );
587 fseek( f, pos, SEEK_SET );
593 FILE *SafeOpenWrite( const char *filename ){
596 f = fopen( filename, "wb" );
599 Error( "Error opening %s: %s",filename,strerror( errno ) );
605 FILE *SafeOpenRead( const char *filename ){
608 f = fopen( filename, "rb" );
611 Error( "Error opening %s: %s",filename,strerror( errno ) );
618 void SafeRead( FILE *f, void *buffer, int count ){
619 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
620 Error( "File read failure" );
625 void SafeWrite( FILE *f, const void *buffer, int count ){
626 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
627 Error( "File write failure" );
637 qboolean FileExists( const char *filename ){
640 f = fopen( filename, "r" );
653 int LoadFile( const char *filename, void **bufferptr ){
658 f = SafeOpenRead( filename );
659 length = Q_filelength( f );
660 buffer = safe_malloc( length + 1 );
661 ( (char *)buffer )[length] = 0;
662 SafeRead( f, buffer, length );
674 rounds up memory allocation to 4K boundry
678 int LoadFileBlock( const char *filename, void **bufferptr ){
680 int length, nBlock, nAllocSize;
683 f = SafeOpenRead( filename );
684 length = Q_filelength( f );
686 nBlock = nAllocSize % MEM_BLOCKSIZE;
688 nAllocSize += MEM_BLOCKSIZE - nBlock;
690 buffer = safe_malloc( nAllocSize + 1 );
691 memset( buffer, 0, nAllocSize + 1 );
692 SafeRead( f, buffer, length );
707 int TryLoadFile( const char *filename, void **bufferptr ){
714 f = fopen( filename, "rb" );
718 length = Q_filelength( f );
719 buffer = safe_malloc( length + 1 );
720 ( (char *)buffer )[length] = 0;
721 SafeRead( f, buffer, length );
734 void SaveFile( const char *filename, const void *buffer, int count ){
737 f = SafeOpenWrite( filename );
738 SafeWrite( f, buffer, count );
744 void DefaultExtension( char *path, const char *extension ){
747 // if path doesnt have a .EXT, append extension
748 // (extension should include the .)
750 src = path + strlen( path ) - 1;
752 while ( *src != '/' && *src != '\\' && src != path )
755 return; // it has an extension
760 strcat( path, extension );
764 void DefaultPath( char *path, const char *basepath ){
767 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
768 return; // absolute path location
771 strcpy( path,basepath );
776 void StripFilename( char *path ){
779 length = strlen( path ) - 1;
780 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
785 void StripExtension( char *path ){
788 length = strlen( path ) - 1;
789 while ( length > 0 && path[length] != '.' )
792 if ( path[length] == '/' || path[ length ] == '\\' ) {
793 return; // no extension
807 // FIXME: should include the slash, otherwise
808 // backing to an empty path will be wrong when appending a slash
809 void ExtractFilePath( const char *path, char *dest ){
812 src = path + strlen( path ) - 1;
815 // back up until a \ or the start
817 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
820 memcpy( dest, path, src - path );
821 dest[src - path] = 0;
824 void ExtractFileBase( const char *path, char *dest ){
827 src = path + strlen( path ) - 1;
830 // back up until a \ or the start
832 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
835 while ( *src && *src != '.' )
842 void ExtractFileExtension( const char *path, char *dest ){
845 src = path + strlen( path ) - 1;
848 // back up until a . or the start
850 while ( src != path && *( src - 1 ) != '.' )
853 *dest = 0; // no extension
866 int ParseHex( const char *hex ){
876 if ( *str >= '0' && *str <= '9' ) {
879 else if ( *str >= 'a' && *str <= 'f' ) {
880 num += 10 + *str - 'a';
882 else if ( *str >= 'A' && *str <= 'F' ) {
883 num += 10 + *str - 'A';
886 Error( "Bad hex number: %s",hex );
895 int ParseNum( const char *str ){
896 if ( str[0] == '$' ) {
897 return ParseHex( str + 1 );
899 if ( str[0] == '0' && str[1] == 'x' ) {
900 return ParseHex( str + 2 );
908 ============================================================================
912 ============================================================================
916 #define __BIG_ENDIAN__
919 #ifdef __BIG_ENDIAN__
921 short LittleShort( short l ){
925 b2 = ( l >> 8 ) & 255;
927 return ( b1 << 8 ) + b2;
930 short BigShort( short l ){
935 int LittleLong( int l ){
939 b2 = ( l >> 8 ) & 255;
940 b3 = ( l >> 16 ) & 255;
941 b4 = ( l >> 24 ) & 255;
943 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
946 int BigLong( int l ){
951 float LittleFloat( float l ){
952 union {byte b[4]; float f; } in, out;
963 float BigFloat( float l ){
971 short BigShort( short l ){
975 b2 = ( l >> 8 ) & 255;
977 return ( b1 << 8 ) + b2;
980 short LittleShort( short l ){
985 int BigLong( int l ){
989 b2 = ( l >> 8 ) & 255;
990 b3 = ( l >> 16 ) & 255;
991 b4 = ( l >> 24 ) & 255;
993 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
996 int LittleLong( int l ){
1000 float BigFloat( float l ){
1001 union {byte b[4]; float f; } in, out;
1012 float LittleFloat( float l ){
1020 //=======================================================
1023 // FIXME: byte swap?
1025 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1026 // and the initial and final xor values shown below... in other words, the
1027 // CCITT standard CRC used by XMODEM
1029 #define CRC_INIT_VALUE 0xffff
1030 #define CRC_XOR_VALUE 0x0000
1032 static unsigned short crctable[256] =
1034 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1035 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1036 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1037 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1038 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1039 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1040 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1041 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1042 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1043 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1044 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1045 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1046 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1047 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1048 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1049 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1050 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1051 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1052 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1053 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1054 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1055 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1056 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1057 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1058 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1059 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1060 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1061 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1062 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1063 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1064 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1065 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1068 void CRC_Init( unsigned short *crcvalue ){
1069 *crcvalue = CRC_INIT_VALUE;
1072 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1073 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1076 unsigned short CRC_Value( unsigned short crcvalue ){
1077 return crcvalue ^ CRC_XOR_VALUE;
1079 //=============================================================================
1086 void CreatePath( const char *path ){
1094 if ( path[1] == ':' ) {
1095 olddrive = _getdrive();
1096 _chdrive( toupper( path[0] ) - 'A' + 1 );
1100 if ( path[1] == ':' ) {
1104 for ( ofs = path + 1 ; *ofs ; ofs++ )
1107 if ( c == '/' || c == '\\' ) { // create the directory
1108 memcpy( dir, path, ofs - path );
1109 dir[ ofs - path ] = 0;
1115 if ( olddrive != -1 ) {
1116 _chdrive( olddrive );
1126 Used to archive source files
1129 void QCopyFile( const char *from, const char *to ){
1133 length = LoadFile( from, &buffer );
1135 SaveFile( to, buffer, length );
1139 void Sys_Sleep( int n ){
1143 #if defined ( __linux__ ) || defined ( __APPLE__ )