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 ( 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
300 if ( !getcwd( out, 256 ) ) {
305 while ( out[i] != 0 )
307 if ( out[i] == '\\' ) {
315 void Q_mkdir( const char *path ){
317 const char *p = NULL;
322 const char *q = NULL;
323 if ( _mkdir( path ) != -1 ) {
326 if ( errno == ENOENT ) {
327 p = strrchr( path, '/' );
328 q = strrchr( path, '\\' );
329 if ( q && ( !p || q < p ) ) {
334 if ( mkdir( path, 0777 ) != -1 ) {
337 if ( errno == ENOENT ) {
338 p = strrchr( path, '/' );
342 strncpy( parentbuf, path, sizeof( parentbuf ) );
343 if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
344 parentbuf[p - path] = 0;
345 Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
346 Q_mkdir( parentbuf );
352 if ( errno != EEXIST ) {
353 Error( "mkdir %s: %s",path, strerror( errno ) );
361 returns -1 if not present
364 int FileTime( const char *path ){
367 if ( stat( path,&buf ) == -1 ) {
380 Parse a token out of a string
383 char *COM_Parse( char *data ){
396 while ( ( c = *data ) <= ' ' )
400 return NULL; // end of file;
406 if ( c == '/' && data[1] == '/' ) {
407 while ( *data && *data != '\n' )
413 // handle quoted strings specially
428 // parse single characters
429 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
436 // parse a regular word
443 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
452 int Q_strncasecmp( const char *s1, const char *s2, int n ){
461 return 0; // strings are equal until end point
465 if ( c1 >= 'a' && c1 <= 'z' ) {
468 if ( c2 >= 'a' && c2 <= 'z' ) {
472 return -1; // strings not equal
477 return 0; // strings are equal
480 int Q_stricmp( const char *s1, const char *s2 ){
481 return Q_strncasecmp( s1, s2, 99999 );
484 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
485 // started getting warnings about that function, prolly a duplicate with the runtime function
486 // maybe we still need to have it in linux builds
488 char *strupr (char *start)
501 char *strlower( char *start ){
506 *in = tolower( *in );
514 =============================================================================
518 =============================================================================
526 Checks for the given parameter in the program's command line arguments
527 Returns the argument number (1 to argc-1) or 0 if not present
530 int CheckParm( const char *check ){
533 for ( i = 1; i < myargc; i++ )
535 if ( !Q_stricmp( check, myargv[i] ) ) {
550 int Q_filelength( FILE *f ){
555 fseek( f, 0, SEEK_END );
557 fseek( f, pos, SEEK_SET );
563 FILE *SafeOpenWrite( const char *filename ){
566 f = fopen( filename, "wb" );
569 Error( "Error opening %s: %s",filename,strerror( errno ) );
575 FILE *SafeOpenRead( const char *filename ){
578 f = fopen( filename, "rb" );
581 Error( "Error opening %s: %s",filename,strerror( errno ) );
588 void SafeRead( FILE *f, void *buffer, int count ){
589 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
590 Error( "File read failure" );
595 void SafeWrite( FILE *f, const void *buffer, int count ){
596 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
597 Error( "File write failure" );
607 qboolean FileExists( const char *filename ){
610 f = fopen( filename, "r" );
623 int LoadFile( const char *filename, void **bufferptr ){
628 f = SafeOpenRead( filename );
629 length = Q_filelength( f );
630 buffer = safe_malloc( length + 1 );
631 ( (char *)buffer )[length] = 0;
632 SafeRead( f, buffer, length );
644 rounds up memory allocation to 4K boundry
648 int LoadFileBlock( const char *filename, void **bufferptr ){
650 int length, nBlock, nAllocSize;
653 f = SafeOpenRead( filename );
654 length = Q_filelength( f );
656 nBlock = nAllocSize % MEM_BLOCKSIZE;
658 nAllocSize += MEM_BLOCKSIZE - nBlock;
660 buffer = safe_malloc( nAllocSize + 1 );
661 memset( buffer, 0, nAllocSize + 1 );
662 SafeRead( f, buffer, length );
677 int TryLoadFile( const char *filename, void **bufferptr ){
684 f = fopen( filename, "rb" );
688 length = Q_filelength( f );
689 buffer = safe_malloc( length + 1 );
690 ( (char *)buffer )[length] = 0;
691 SafeRead( f, buffer, length );
704 void SaveFile( const char *filename, const void *buffer, int count ){
707 f = SafeOpenWrite( filename );
708 SafeWrite( f, buffer, count );
714 void DefaultExtension( char *path, const char *extension ){
717 // if path doesnt have a .EXT, append extension
718 // (extension should include the .)
720 src = path + strlen( path ) - 1;
722 while ( *src != '/' && *src != '\\' && src != path )
725 return; // it has an extension
730 strcat( path, extension );
734 void DefaultPath( char *path, const char *basepath ){
737 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
738 return; // absolute path location
741 strcpy( path,basepath );
746 void StripFilename( char *path ){
749 length = strlen( path ) - 1;
750 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
755 void StripExtension( char *path ){
758 length = strlen( path ) - 1;
759 while ( length > 0 && path[length] != '.' )
762 if ( path[length] == '/' || path[ length ] == '\\' ) {
763 return; // no extension
777 // FIXME: should include the slash, otherwise
778 // backing to an empty path will be wrong when appending a slash
779 void ExtractFilePath( const char *path, char *dest ){
782 src = path + strlen( path ) - 1;
785 // back up until a \ or the start
787 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
790 memcpy( dest, path, src - path );
791 dest[src - path] = 0;
794 void ExtractFileBase( const char *path, char *dest ){
797 src = path + strlen( path ) - 1;
800 // back up until a \ or the start
802 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
805 while ( *src && *src != '.' )
812 void ExtractFileExtension( const char *path, char *dest ){
815 src = path + strlen( path ) - 1;
818 // back up until a . or the start
820 while ( src != path && *( src - 1 ) != '.' )
823 *dest = 0; // no extension
836 int ParseHex( const char *hex ){
846 if ( *str >= '0' && *str <= '9' ) {
849 else if ( *str >= 'a' && *str <= 'f' ) {
850 num += 10 + *str - 'a';
852 else if ( *str >= 'A' && *str <= 'F' ) {
853 num += 10 + *str - 'A';
856 Error( "Bad hex number: %s",hex );
865 int ParseNum( const char *str ){
866 if ( str[0] == '$' ) {
867 return ParseHex( str + 1 );
869 if ( str[0] == '0' && str[1] == 'x' ) {
870 return ParseHex( str + 2 );
878 ============================================================================
882 ============================================================================
886 #define __BIG_ENDIAN__
889 #ifdef __BIG_ENDIAN__
891 short LittleShort( short l ){
895 b2 = ( l >> 8 ) & 255;
897 return ( b1 << 8 ) + b2;
900 short BigShort( short l ){
905 int LittleLong( int l ){
909 b2 = ( l >> 8 ) & 255;
910 b3 = ( l >> 16 ) & 255;
911 b4 = ( l >> 24 ) & 255;
913 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
916 int BigLong( int l ){
921 float LittleFloat( float l ){
922 union {byte b[4]; float f; } in, out;
933 float BigFloat( float l ){
941 short BigShort( short l ){
945 b2 = ( l >> 8 ) & 255;
947 return ( b1 << 8 ) + b2;
950 short LittleShort( short l ){
955 int BigLong( int l ){
959 b2 = ( l >> 8 ) & 255;
960 b3 = ( l >> 16 ) & 255;
961 b4 = ( l >> 24 ) & 255;
963 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
966 int LittleLong( int l ){
970 float BigFloat( float l ){
971 union {byte b[4]; float f; } in, out;
982 float LittleFloat( float l ){
990 //=======================================================
995 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
996 // and the initial and final xor values shown below... in other words, the
997 // CCITT standard CRC used by XMODEM
999 #define CRC_INIT_VALUE 0xffff
1000 #define CRC_XOR_VALUE 0x0000
1002 static unsigned short crctable[256] =
1004 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1005 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1006 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1007 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1008 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1009 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1010 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1011 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1012 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1013 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1014 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1015 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1016 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1017 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1018 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1019 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1020 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1021 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1022 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1023 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1024 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1025 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1026 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1027 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1028 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1029 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1030 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1031 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1032 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1033 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1034 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1035 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1038 void CRC_Init( unsigned short *crcvalue ){
1039 *crcvalue = CRC_INIT_VALUE;
1042 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1043 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1046 unsigned short CRC_Value( unsigned short crcvalue ){
1047 return crcvalue ^ CRC_XOR_VALUE;
1049 //=============================================================================
1056 void CreatePath( const char *path ){
1064 if ( path[1] == ':' ) {
1065 olddrive = _getdrive();
1066 _chdrive( toupper( path[0] ) - 'A' + 1 );
1070 if ( path[1] == ':' ) {
1074 for ( ofs = path + 1 ; *ofs ; ofs++ )
1077 if ( c == '/' || c == '\\' ) { // create the directory
1078 memcpy( dir, path, ofs - path );
1079 dir[ ofs - path ] = 0;
1085 if ( olddrive != -1 ) {
1086 _chdrive( olddrive );
1096 Used to archive source files
1099 void QCopyFile( const char *from, const char *to ){
1103 length = LoadFile( from, &buffer );
1105 SaveFile( to, buffer, length );
1109 void Sys_Sleep( int n ){
1113 #if defined ( __linux__ ) || defined ( __APPLE__ )