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];
247 if ( !*qdir || 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];
258 Error( "ExpandGamePath called without gamedir set" );
260 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
261 strcpy( full, path );
264 sprintf( full, "%s%s", gamedir, path );
268 char *ExpandPathAndArchive( const char *path ){
270 char archivename[1024];
272 expanded = ExpandPath( path );
275 sprintf( archivename, "%s/%s", archivedir, path );
276 QCopyFile( expanded, archivename );
282 char *copystring( const char *s ){
284 b = safe_malloc( strlen( s ) + 1 );
296 double I_FloatTime( void ){
303 // more precise, less portable
308 gettimeofday( &tp, &tzp );
312 return tp.tv_usec / 1000000.0;
315 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
319 void Q_getwd( char *out ){
326 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
327 if ( !getcwd( out, 256 ) ) {
332 while ( out[i] != 0 )
334 if ( out[i] == '\\' ) {
342 void Q_mkdir( const char *path ){
344 const char *p = NULL;
349 const char *q = NULL;
350 if ( _mkdir( path ) != -1 ) {
353 if ( errno == ENOENT ) {
354 p = strrchr( path, '/' );
355 q = strrchr( path, '\\' );
356 if ( q && ( !p || q < p ) ) {
361 if ( mkdir( path, 0777 ) != -1 ) {
364 if ( errno == ENOENT ) {
365 p = strrchr( path, '/' );
369 strncpy( parentbuf, path, sizeof( parentbuf ) );
370 if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
371 parentbuf[p - path] = 0;
372 Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
373 Q_mkdir( parentbuf );
379 if ( errno != EEXIST ) {
380 Error( "mkdir %s: %s",path, strerror( errno ) );
388 returns -1 if not present
391 int FileTime( const char *path ){
394 if ( stat( path,&buf ) == -1 ) {
407 Parse a token out of a string
410 char *COM_Parse( char *data ){
423 while ( ( c = *data ) <= ' ' )
427 return NULL; // end of file;
433 if ( c == '/' && data[1] == '/' ) {
434 while ( *data && *data != '\n' )
440 // handle quoted strings specially
455 // parse single characters
456 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
463 // parse a regular word
470 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
479 int Q_strncasecmp( const char *s1, const char *s2, int n ){
488 return 0; // strings are equal until end point
492 if ( c1 >= 'a' && c1 <= 'z' ) {
495 if ( c2 >= 'a' && c2 <= 'z' ) {
499 return -1; // strings not equal
504 return 0; // strings are equal
507 int Q_stricmp( const char *s1, const char *s2 ){
508 return Q_strncasecmp( s1, s2, 99999 );
511 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
512 // started getting warnings about that function, prolly a duplicate with the runtime function
513 // maybe we still need to have it in linux builds
515 char *strupr (char *start)
528 char *strlower( char *start ){
533 *in = tolower( *in );
541 =============================================================================
545 =============================================================================
553 Checks for the given parameter in the program's command line arguments
554 Returns the argument number (1 to argc-1) or 0 if not present
557 int CheckParm( const char *check ){
560 for ( i = 1; i < myargc; i++ )
562 if ( !Q_stricmp( check, myargv[i] ) ) {
577 int Q_filelength( FILE *f ){
582 fseek( f, 0, SEEK_END );
584 fseek( f, pos, SEEK_SET );
590 FILE *SafeOpenWrite( const char *filename ){
593 f = fopen( filename, "wb" );
596 Error( "Error opening %s: %s",filename,strerror( errno ) );
602 FILE *SafeOpenRead( const char *filename ){
605 f = fopen( filename, "rb" );
608 Error( "Error opening %s: %s",filename,strerror( errno ) );
615 void SafeRead( FILE *f, void *buffer, int count ){
616 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
617 Error( "File read failure" );
622 void SafeWrite( FILE *f, const void *buffer, int count ){
623 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
624 Error( "File write failure" );
634 qboolean FileExists( const char *filename ){
637 f = fopen( filename, "r" );
650 int LoadFile( const char *filename, void **bufferptr ){
655 f = SafeOpenRead( filename );
656 length = Q_filelength( f );
657 buffer = safe_malloc( length + 1 );
658 ( (char *)buffer )[length] = 0;
659 SafeRead( f, buffer, length );
671 rounds up memory allocation to 4K boundry
675 int LoadFileBlock( const char *filename, void **bufferptr ){
677 int length, nBlock, nAllocSize;
680 f = SafeOpenRead( filename );
681 length = Q_filelength( f );
683 nBlock = nAllocSize % MEM_BLOCKSIZE;
685 nAllocSize += MEM_BLOCKSIZE - nBlock;
687 buffer = safe_malloc( nAllocSize + 1 );
688 memset( buffer, 0, nAllocSize + 1 );
689 SafeRead( f, buffer, length );
704 int TryLoadFile( const char *filename, void **bufferptr ){
711 f = fopen( filename, "rb" );
715 length = Q_filelength( f );
716 buffer = safe_malloc( length + 1 );
717 ( (char *)buffer )[length] = 0;
718 SafeRead( f, buffer, length );
731 void SaveFile( const char *filename, const void *buffer, int count ){
734 f = SafeOpenWrite( filename );
735 SafeWrite( f, buffer, count );
741 void DefaultExtension( char *path, const char *extension ){
744 // if path doesnt have a .EXT, append extension
745 // (extension should include the .)
747 src = path + strlen( path ) - 1;
749 while ( *src != '/' && *src != '\\' && src != path )
752 return; // it has an extension
757 strcat( path, extension );
761 void DefaultPath( char *path, const char *basepath ){
764 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
765 return; // absolute path location
768 strcpy( path,basepath );
773 void StripFilename( char *path ){
776 length = strlen( path ) - 1;
777 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
782 void StripExtension( char *path ){
785 length = strlen( path ) - 1;
786 while ( length > 0 && path[length] != '.' )
789 if ( path[length] == '/' || path[ length ] == '\\' ) {
790 return; // no extension
804 // FIXME: should include the slash, otherwise
805 // backing to an empty path will be wrong when appending a slash
806 void ExtractFilePath( const char *path, char *dest ){
809 src = path + strlen( path ) - 1;
812 // back up until a \ or the start
814 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
817 memcpy( dest, path, src - path );
818 dest[src - path] = 0;
821 void ExtractFileBase( const char *path, char *dest ){
824 src = path + strlen( path ) - 1;
827 // back up until a \ or the start
829 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
832 while ( *src && *src != '.' )
839 void ExtractFileExtension( const char *path, char *dest ){
842 src = path + strlen( path ) - 1;
845 // back up until a . or the start
847 while ( src != path && *( src - 1 ) != '.' )
850 *dest = 0; // no extension
863 int ParseHex( const char *hex ){
873 if ( *str >= '0' && *str <= '9' ) {
876 else if ( *str >= 'a' && *str <= 'f' ) {
877 num += 10 + *str - 'a';
879 else if ( *str >= 'A' && *str <= 'F' ) {
880 num += 10 + *str - 'A';
883 Error( "Bad hex number: %s",hex );
892 int ParseNum( const char *str ){
893 if ( str[0] == '$' ) {
894 return ParseHex( str + 1 );
896 if ( str[0] == '0' && str[1] == 'x' ) {
897 return ParseHex( str + 2 );
905 ============================================================================
909 ============================================================================
913 #define __BIG_ENDIAN__
916 #ifdef __BIG_ENDIAN__
918 short LittleShort( short l ){
922 b2 = ( l >> 8 ) & 255;
924 return ( b1 << 8 ) + b2;
927 short BigShort( short l ){
932 int LittleLong( int l ){
936 b2 = ( l >> 8 ) & 255;
937 b3 = ( l >> 16 ) & 255;
938 b4 = ( l >> 24 ) & 255;
940 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
943 int BigLong( int l ){
948 float LittleFloat( float l ){
949 union {byte b[4]; float f; } in, out;
960 float BigFloat( float l ){
968 short BigShort( short l ){
972 b2 = ( l >> 8 ) & 255;
974 return ( b1 << 8 ) + b2;
977 short LittleShort( short l ){
982 int BigLong( int l ){
986 b2 = ( l >> 8 ) & 255;
987 b3 = ( l >> 16 ) & 255;
988 b4 = ( l >> 24 ) & 255;
990 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
993 int LittleLong( int l ){
997 float BigFloat( float l ){
998 union {byte b[4]; float f; } in, out;
1009 float LittleFloat( float l ){
1017 //=======================================================
1020 // FIXME: byte swap?
1022 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1023 // and the initial and final xor values shown below... in other words, the
1024 // CCITT standard CRC used by XMODEM
1026 #define CRC_INIT_VALUE 0xffff
1027 #define CRC_XOR_VALUE 0x0000
1029 static unsigned short crctable[256] =
1031 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1032 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1033 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1034 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1035 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1036 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1037 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1038 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1039 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1040 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1041 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1042 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1043 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1044 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1045 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1046 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1047 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1048 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1049 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1050 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1051 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1052 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1053 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1054 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1055 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1056 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1057 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1058 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1059 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1060 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1061 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1062 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1065 void CRC_Init( unsigned short *crcvalue ){
1066 *crcvalue = CRC_INIT_VALUE;
1069 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1070 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1073 unsigned short CRC_Value( unsigned short crcvalue ){
1074 return crcvalue ^ CRC_XOR_VALUE;
1076 //=============================================================================
1083 void CreatePath( const char *path ){
1091 if ( path[1] == ':' ) {
1092 olddrive = _getdrive();
1093 _chdrive( toupper( path[0] ) - 'A' + 1 );
1097 if ( path[1] == ':' ) {
1101 for ( ofs = path + 1 ; *ofs ; ofs++ )
1104 if ( c == '/' || c == '\\' ) { // create the directory
1105 memcpy( dir, path, ofs - path );
1106 dir[ ofs - path ] = 0;
1112 if ( olddrive != -1 ) {
1113 _chdrive( olddrive );
1123 Used to archive source files
1126 void QCopyFile( const char *from, const char *to ){
1130 length = LoadFile( from, &buffer );
1132 SaveFile( to, buffer, length );
1136 void Sys_Sleep( int n ){
1140 #if defined ( __linux__ ) || defined ( __APPLE__ )