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
32 #include "globaldefs.h"
35 #include <sys/types.h>
47 #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
48 #define PATHSEPERATOR '/'
50 void *safe_malloc( size_t size ){
55 Error( "safe_malloc failed on allocation of %i bytes", size );
61 void *safe_malloc_info( size_t size, char* info ){
66 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
72 // set these before calling CheckParm
80 char archivedir[1024];
87 Mimic unix command line expansion
90 #define MAX_EX_ARGC 1024
92 char *ex_argv[MAX_EX_ARGC];
96 void ExpandWildcards( int *argc, char ***argv ){
97 struct _finddata_t fileinfo;
105 for ( i = 0 ; i < *argc ; i++ )
109 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
110 ex_argv[ex_argc++] = path;
114 handle = _findfirst( path, &fileinfo );
115 if ( handle == -1 ) {
119 ExtractFilePath( path, filebase );
123 sprintf( filename, "%s%s", filebase, fileinfo.name );
124 ex_argv[ex_argc++] = copystring( filename );
125 } while ( _findnext( handle, &fileinfo ) != -1 );
127 _findclose( handle );
133 #else // !GDEF_OS_WINDOWS
134 void ExpandWildcards( int *argc, char ***argv ){
136 #endif // !GDEF_OS_WINDOWS
140 qdir will hold the path up to the quake directory, including the slash
145 gamedir will hold qdir + the game directory (id1, id2, etc)
153 void SetQdirFromPath( const char *path ){
159 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
161 strcat( temp, path );
165 // search for "quake2" in path
167 len = strlen( BASEDIRNAME );
168 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
172 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
174 //strncpy (qdir, path, c+len+2-path);
175 // the +2 assumes a 2 or 3 following quake which is not the
176 // case with a retail install
177 // so we need to add up how much to the next separator
180 while ( *sep && *sep != '/' && *sep != '\\' )
185 strncpy( qdir, path, c + len + count - path );
186 Sys_Printf( "qdir: %s\n", qdir );
187 for ( i = 0; i < (int) strlen( qdir ); i++ )
189 if ( qdir[i] == '\\' ) {
197 if ( *c == '/' || *c == '\\' ) {
198 strncpy( gamedir, path, c + 1 - path );
200 for ( i = 0; i < (int) strlen( gamedir ); i++ )
202 if ( gamedir[i] == '\\' ) {
207 Sys_Printf( "gamedir: %s\n", gamedir );
209 if ( !writedir[0] ) {
210 strcpy( writedir, gamedir );
212 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
213 writedir[strlen( writedir )] = '/';
214 writedir[strlen( writedir ) + 1] = 0;
221 Error( "No gamedir in %s", path );
225 Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
228 char *ExpandArg( const char *path ){
229 static char full[1024];
231 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
233 strcat( full, path );
236 strcpy( full, path );
241 char *ExpandPath( const char *path ){
242 static char full[1024];
243 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
244 strcpy( full, path );
247 sprintf( full, "%s%s", qdir, path );
251 char *copystring( const char *s ){
253 b = safe_malloc( strlen( s ) + 1 );
265 double I_FloatTime( void ){
272 // more precise, less portable
277 gettimeofday( &tp, &tzp );
281 return tp.tv_usec / 1000000.0;
284 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
288 void Q_getwd( char *out ){
294 #else // !GDEF_OS_WINDOWS
295 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
296 if ( !getcwd( out, 256 ) ) {
300 #endif // !GDEF_OS_WINDOWS
301 while ( out[i] != 0 )
303 if ( out[i] == '\\' ) {
311 void Q_mkdir( const char *path ){
313 const char *p = NULL;
318 const char *q = NULL;
319 if ( _mkdir( path ) != -1 ) {
322 if ( errno == ENOENT ) {
323 p = strrchr( path, '/' );
324 q = strrchr( path, '\\' );
325 if ( q && ( !p || q < p ) ) {
329 #else // !GDEF_OS_WINDOWS
330 if ( mkdir( path, 0777 ) != -1 ) {
333 if ( errno == ENOENT ) {
334 p = strrchr( path, '/' );
336 #endif // !GDEF_OS_WINDOWS
338 strncpy( parentbuf, path, sizeof( parentbuf ) );
339 if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
340 parentbuf[p - path] = 0;
341 Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
342 Q_mkdir( parentbuf );
348 if ( errno != EEXIST ) {
349 Error( "mkdir %s: %s",path, strerror( errno ) );
357 returns -1 if not present
360 int FileTime( const char *path ){
363 if ( stat( path,&buf ) == -1 ) {
376 Parse a token out of a string
379 char *COM_Parse( char *data ){
392 while ( ( c = *data ) <= ' ' )
396 return NULL; // end of file;
402 if ( c == '/' && data[1] == '/' ) {
403 while ( *data && *data != '\n' )
409 // handle quoted strings specially
424 // parse single characters
425 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
432 // parse a regular word
439 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
448 int Q_strncasecmp( const char *s1, const char *s2, int n ){
457 return 0; // strings are equal until end point
461 if ( c1 >= 'a' && c1 <= 'z' ) {
464 if ( c2 >= 'a' && c2 <= 'z' ) {
468 return -1; // strings not equal
473 return 0; // strings are equal
476 int Q_stricmp( const char *s1, const char *s2 ){
477 return Q_strncasecmp( s1, s2, 99999 );
480 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
481 // started getting warnings about that function, prolly a duplicate with the runtime function
482 // maybe we still need to have it in linux builds
484 char *strupr (char *start)
497 char *strlower( char *start ){
502 *in = tolower( *in );
510 =============================================================================
514 =============================================================================
522 Checks for the given parameter in the program's command line arguments
523 Returns the argument number (1 to argc-1) or 0 if not present
526 int CheckParm( const char *check ){
529 for ( i = 1; i < myargc; i++ )
531 if ( !Q_stricmp( check, myargv[i] ) ) {
546 int Q_filelength( FILE *f ){
551 fseek( f, 0, SEEK_END );
553 fseek( f, pos, SEEK_SET );
559 FILE *SafeOpenWrite( const char *filename ){
562 f = fopen( filename, "wb" );
565 Error( "Error opening %s: %s",filename,strerror( errno ) );
571 FILE *SafeOpenRead( const char *filename ){
574 f = fopen( filename, "rb" );
577 Error( "Error opening %s: %s",filename,strerror( errno ) );
584 void SafeRead( FILE *f, void *buffer, int count ){
585 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
586 Error( "File read failure" );
591 void SafeWrite( FILE *f, const void *buffer, int count ){
592 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
593 Error( "File write failure" );
603 qboolean FileExists( const char *filename ){
606 f = fopen( filename, "r" );
619 int LoadFile( const char *filename, void **bufferptr ){
624 f = SafeOpenRead( filename );
625 length = Q_filelength( f );
626 buffer = safe_malloc( length + 1 );
627 ( (char *)buffer )[length] = 0;
628 SafeRead( f, buffer, length );
640 rounds up memory allocation to 4K boundry
644 int LoadFileBlock( const char *filename, void **bufferptr ){
646 int length, nBlock, nAllocSize;
649 f = SafeOpenRead( filename );
650 length = Q_filelength( f );
652 nBlock = nAllocSize % MEM_BLOCKSIZE;
654 nAllocSize += MEM_BLOCKSIZE - nBlock;
656 buffer = safe_malloc( nAllocSize + 1 );
657 memset( buffer, 0, nAllocSize + 1 );
658 SafeRead( f, buffer, length );
673 int TryLoadFile( const char *filename, void **bufferptr ){
680 f = fopen( filename, "rb" );
684 length = Q_filelength( f );
685 buffer = safe_malloc( length + 1 );
686 ( (char *)buffer )[length] = 0;
687 SafeRead( f, buffer, length );
700 void SaveFile( const char *filename, const void *buffer, int count ){
703 f = SafeOpenWrite( filename );
704 SafeWrite( f, buffer, count );
710 void DefaultExtension( char *path, const char *extension ){
713 // if path doesnt have a .EXT, append extension
714 // (extension should include the .)
716 src = path + strlen( path ) - 1;
718 while ( *src != '/' && *src != '\\' && src != path )
721 return; // it has an extension
726 strcat( path, extension );
730 void DefaultPath( char *path, const char *basepath ){
733 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
734 return; // absolute path location
737 strcpy( path,basepath );
742 void StripFilename( char *path ){
745 length = strlen( path ) - 1;
746 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
751 void StripExtension( char *path ){
754 length = strlen( path ) - 1;
755 while ( length > 0 && path[length] != '.' )
758 if ( path[length] == '/' || path[ length ] == '\\' ) {
759 return; // no extension
773 // FIXME: should include the slash, otherwise
774 // backing to an empty path will be wrong when appending a slash
775 void ExtractFilePath( const char *path, char *dest ){
778 src = path + strlen( path ) - 1;
781 // back up until a \ or the start
783 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
786 memcpy( dest, path, src - path );
787 dest[src - path] = 0;
790 void ExtractFileBase( const char *path, char *dest ){
793 src = path + strlen( path ) - 1;
796 // back up until a \ or the start
798 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
801 while ( *src && *src != '.' )
808 void ExtractFileExtension( const char *path, char *dest ){
811 src = path + strlen( path ) - 1;
814 // back up until a . or the start
816 while ( src != path && *( src - 1 ) != '.' )
819 *dest = 0; // no extension
832 int ParseHex( const char *hex ){
842 if ( *str >= '0' && *str <= '9' ) {
845 else if ( *str >= 'a' && *str <= 'f' ) {
846 num += 10 + *str - 'a';
848 else if ( *str >= 'A' && *str <= 'F' ) {
849 num += 10 + *str - 'A';
852 Error( "Bad hex number: %s",hex );
861 int ParseNum( const char *str ){
862 if ( str[0] == '$' ) {
863 return ParseHex( str + 1 );
865 if ( str[0] == '0' && str[1] == 'x' ) {
866 return ParseHex( str + 2 );
874 ============================================================================
878 ============================================================================
881 #if GDEF_ARCH_ENDIAN_BIG
883 short LittleShort( short l ){
887 b2 = ( l >> 8 ) & 255;
889 return ( b1 << 8 ) + b2;
892 short BigShort( short l ){
897 int LittleLong( int l ){
901 b2 = ( l >> 8 ) & 255;
902 b3 = ( l >> 16 ) & 255;
903 b4 = ( l >> 24 ) & 255;
905 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
908 int BigLong( int l ){
913 float LittleFloat( float l ){
914 union {byte b[4]; float f; } in, out;
925 float BigFloat( float l ){
929 #else // !GDEF_ARCH_ENDIAN_BIG
931 short BigShort( short l ){
935 b2 = ( l >> 8 ) & 255;
937 return ( b1 << 8 ) + b2;
940 short LittleShort( short l ){
945 int BigLong( int l ){
949 b2 = ( l >> 8 ) & 255;
950 b3 = ( l >> 16 ) & 255;
951 b4 = ( l >> 24 ) & 255;
953 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
956 int LittleLong( int l ){
960 float BigFloat( float l ){
961 union {byte b[4]; float f; } in, out;
972 float LittleFloat( float l ){
976 #endif // !GDEF_ARCH_ENDIAN_BIG
979 //=======================================================
984 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
985 // and the initial and final xor values shown below... in other words, the
986 // CCITT standard CRC used by XMODEM
988 #define CRC_INIT_VALUE 0xffff
989 #define CRC_XOR_VALUE 0x0000
991 static unsigned short crctable[256] =
993 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
994 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
995 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
996 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
997 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
998 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
999 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1000 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1001 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1002 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1003 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1004 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1005 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1006 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1007 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1008 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1009 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1010 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1011 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1012 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1013 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1014 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1015 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1016 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1017 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1018 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1019 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1020 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1021 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1022 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1023 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1024 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1027 void CRC_Init( unsigned short *crcvalue ){
1028 *crcvalue = CRC_INIT_VALUE;
1031 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1032 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1035 unsigned short CRC_Value( unsigned short crcvalue ){
1036 return crcvalue ^ CRC_XOR_VALUE;
1038 //=============================================================================
1045 void CreatePath( const char *path ){
1053 if ( path[1] == ':' ) {
1054 olddrive = _getdrive();
1055 _chdrive( toupper( path[0] ) - 'A' + 1 );
1057 #endif // !GDEF_OS_WINDOWS
1059 if ( path[1] == ':' ) {
1063 for ( ofs = path + 1 ; *ofs ; ofs++ )
1066 if ( c == '/' || c == '\\' ) { // create the directory
1067 memcpy( dir, path, ofs - path );
1068 dir[ ofs - path ] = 0;
1074 if ( olddrive != -1 ) {
1075 _chdrive( olddrive );
1077 #endif // !>GDEF_OS_WINDOWS
1085 Used to archive source files
1088 void QCopyFile( const char *from, const char *to ){
1092 length = LoadFile( from, &buffer );
1094 SaveFile( to, buffer, length );
1098 void Sys_Sleep( int n ){
1101 #else // !GDEF_OS_WINDOWS
1103 #endif // !GDEF_OS_WINDOWS