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>
43 #if GDEF_OS_LINUX || GDEF_OS_MACOS
51 #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
52 #define PATHSEPERATOR '/'
55 void *safe_malloc( size_t size ){
60 Error( "safe_malloc failed on allocation of %i bytes", size );
66 void *safe_malloc_info( size_t size, char* info ){
71 Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
78 // set these before calling CheckParm
86 char archivedir[1024];
93 Mimic unix command line expansion
96 #define MAX_EX_ARGC 1024
98 char *ex_argv[MAX_EX_ARGC];
101 void ExpandWildcards( int *argc, char ***argv ){
102 struct _finddata_t fileinfo;
110 for ( i = 0 ; i < *argc ; i++ )
114 || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
115 ex_argv[ex_argc++] = path;
119 handle = _findfirst( path, &fileinfo );
120 if ( handle == -1 ) {
124 ExtractFilePath( path, filebase );
128 sprintf( filename, "%s%s", filebase, fileinfo.name );
129 ex_argv[ex_argc++] = copystring( filename );
130 } while ( _findnext( handle, &fileinfo ) != -1 );
132 _findclose( handle );
139 void ExpandWildcards( int *argc, char ***argv ){
145 qdir will hold the path up to the quake directory, including the slash
150 gamedir will hold qdir + the game directory (id1, id2, etc)
158 void SetQdirFromPath( const char *path ){
164 if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
166 strcat( temp, path );
170 // search for "quake2" in path
172 len = strlen( BASEDIRNAME );
173 for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
177 if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
179 //strncpy (qdir, path, c+len+2-path);
180 // the +2 assumes a 2 or 3 following quake which is not the
181 // case with a retail install
182 // so we need to add up how much to the next separator
185 while ( *sep && *sep != '/' && *sep != '\\' )
190 strncpy( qdir, path, c + len + count - path );
191 Sys_Printf( "qdir: %s\n", qdir );
192 for ( i = 0; i < (int) strlen( qdir ); i++ )
194 if ( qdir[i] == '\\' ) {
202 if ( *c == '/' || *c == '\\' ) {
203 strncpy( gamedir, path, c + 1 - path );
205 for ( i = 0; i < (int) strlen( gamedir ); i++ )
207 if ( gamedir[i] == '\\' ) {
212 Sys_Printf( "gamedir: %s\n", gamedir );
214 if ( !writedir[0] ) {
215 strcpy( writedir, gamedir );
217 else if ( writedir[strlen( writedir ) - 1] != '/' ) {
218 writedir[strlen( writedir )] = '/';
219 writedir[strlen( writedir ) + 1] = 0;
226 Error( "No gamedir in %s", path );
230 Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
233 char *ExpandArg( const char *path ){
234 static char full[1024];
236 if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
238 strcat( full, path );
241 strcpy( full, path );
246 char *ExpandPath( const char *path ){
247 static char full[1024];
248 if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
249 strcpy( full, path );
252 sprintf( full, "%s%s", qdir, path );
256 char *copystring( const char *s ){
258 b = safe_malloc( strlen( s ) + 1 );
270 double I_FloatTime( void ){
277 // more precise, less portable
282 gettimeofday( &tp, &tzp );
286 return tp.tv_usec / 1000000.0;
289 return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
293 void Q_getwd( char *out ){
300 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
301 if ( !getcwd( out, 256 ) ) {
306 while ( out[i] != 0 )
308 if ( out[i] == '\\' ) {
316 void Q_mkdir( const char *path ){
318 const char *p = NULL;
323 const char *q = NULL;
324 if ( _mkdir( path ) != -1 ) {
327 if ( errno == ENOENT ) {
328 p = strrchr( path, '/' );
329 q = strrchr( path, '\\' );
330 if ( q && ( !p || q < p ) ) {
335 if ( mkdir( path, 0777 ) != -1 ) {
338 if ( errno == ENOENT ) {
339 p = strrchr( path, '/' );
343 strncpy( parentbuf, path, sizeof( parentbuf ) );
344 if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
345 parentbuf[p - path] = 0;
346 Sys_Printf( "mkdir: %s: creating parent %s first\n", path, parentbuf );
347 Q_mkdir( parentbuf );
353 if ( errno != EEXIST ) {
354 Error( "mkdir %s: %s",path, strerror( errno ) );
362 returns -1 if not present
365 int FileTime( const char *path ){
368 if ( stat( path,&buf ) == -1 ) {
381 Parse a token out of a string
384 char *COM_Parse( char *data ){
397 while ( ( c = *data ) <= ' ' )
401 return NULL; // end of file;
407 if ( c == '/' && data[1] == '/' ) {
408 while ( *data && *data != '\n' )
414 // handle quoted strings specially
429 // parse single characters
430 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
437 // parse a regular word
444 if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
453 int Q_strncasecmp( const char *s1, const char *s2, int n ){
462 return 0; // strings are equal until end point
466 if ( c1 >= 'a' && c1 <= 'z' ) {
469 if ( c2 >= 'a' && c2 <= 'z' ) {
473 return -1; // strings not equal
478 return 0; // strings are equal
481 int Q_stricmp( const char *s1, const char *s2 ){
482 return Q_strncasecmp( s1, s2, 99999 );
485 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
486 // started getting warnings about that function, prolly a duplicate with the runtime function
487 // maybe we still need to have it in linux builds
489 char *strupr (char *start)
502 char *strlower( char *start ){
507 *in = tolower( *in );
515 =============================================================================
519 =============================================================================
527 Checks for the given parameter in the program's command line arguments
528 Returns the argument number (1 to argc-1) or 0 if not present
531 int CheckParm( const char *check ){
534 for ( i = 1; i < myargc; i++ )
536 if ( !Q_stricmp( check, myargv[i] ) ) {
551 int Q_filelength( FILE *f ){
556 fseek( f, 0, SEEK_END );
558 fseek( f, pos, SEEK_SET );
564 FILE *SafeOpenWrite( const char *filename ){
567 f = fopen( filename, "wb" );
570 Error( "Error opening %s: %s",filename,strerror( errno ) );
576 FILE *SafeOpenRead( const char *filename ){
579 f = fopen( filename, "rb" );
582 Error( "Error opening %s: %s",filename,strerror( errno ) );
589 void SafeRead( FILE *f, void *buffer, int count ){
590 if ( fread( buffer, 1, count, f ) != (size_t)count ) {
591 Error( "File read failure" );
596 void SafeWrite( FILE *f, const void *buffer, int count ){
597 if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
598 Error( "File write failure" );
608 qboolean FileExists( const char *filename ){
611 f = fopen( filename, "r" );
624 int LoadFile( const char *filename, void **bufferptr ){
629 f = SafeOpenRead( filename );
630 length = Q_filelength( f );
631 buffer = safe_malloc( length + 1 );
632 ( (char *)buffer )[length] = 0;
633 SafeRead( f, buffer, length );
645 rounds up memory allocation to 4K boundry
649 int LoadFileBlock( const char *filename, void **bufferptr ){
651 int length, nBlock, nAllocSize;
654 f = SafeOpenRead( filename );
655 length = Q_filelength( f );
657 nBlock = nAllocSize % MEM_BLOCKSIZE;
659 nAllocSize += MEM_BLOCKSIZE - nBlock;
661 buffer = safe_malloc( nAllocSize + 1 );
662 memset( buffer, 0, nAllocSize + 1 );
663 SafeRead( f, buffer, length );
678 int TryLoadFile( const char *filename, void **bufferptr ){
685 f = fopen( filename, "rb" );
689 length = Q_filelength( f );
690 buffer = safe_malloc( length + 1 );
691 ( (char *)buffer )[length] = 0;
692 SafeRead( f, buffer, length );
705 void SaveFile( const char *filename, const void *buffer, int count ){
708 f = SafeOpenWrite( filename );
709 SafeWrite( f, buffer, count );
715 void DefaultExtension( char *path, const char *extension ){
718 // if path doesnt have a .EXT, append extension
719 // (extension should include the .)
721 src = path + strlen( path ) - 1;
723 while ( *src != '/' && *src != '\\' && src != path )
726 return; // it has an extension
731 strcat( path, extension );
735 void DefaultPath( char *path, const char *basepath ){
738 if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
739 return; // absolute path location
742 strcpy( path,basepath );
747 void StripFilename( char *path ){
750 length = strlen( path ) - 1;
751 while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
756 void StripExtension( char *path ){
759 length = strlen( path ) - 1;
760 while ( length > 0 && path[length] != '.' )
763 if ( path[length] == '/' || path[ length ] == '\\' ) {
764 return; // no extension
778 // FIXME: should include the slash, otherwise
779 // backing to an empty path will be wrong when appending a slash
780 void ExtractFilePath( const char *path, char *dest ){
783 src = path + strlen( path ) - 1;
786 // back up until a \ or the start
788 while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
791 memcpy( dest, path, src - path );
792 dest[src - path] = 0;
795 void ExtractFileBase( const char *path, char *dest ){
798 src = path + strlen( path ) - 1;
801 // back up until a \ or the start
803 while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
806 while ( *src && *src != '.' )
813 void ExtractFileExtension( const char *path, char *dest ){
816 src = path + strlen( path ) - 1;
819 // back up until a . or the start
821 while ( src != path && *( src - 1 ) != '.' )
824 *dest = 0; // no extension
837 int ParseHex( const char *hex ){
847 if ( *str >= '0' && *str <= '9' ) {
850 else if ( *str >= 'a' && *str <= 'f' ) {
851 num += 10 + *str - 'a';
853 else if ( *str >= 'A' && *str <= 'F' ) {
854 num += 10 + *str - 'A';
857 Error( "Bad hex number: %s",hex );
866 int ParseNum( const char *str ){
867 if ( str[0] == '$' ) {
868 return ParseHex( str + 1 );
870 if ( str[0] == '0' && str[1] == 'x' ) {
871 return ParseHex( str + 2 );
879 ============================================================================
883 ============================================================================
886 #if GDEF_ARCH_ENDIAN_BIG
888 short LittleShort( short l ){
892 b2 = ( l >> 8 ) & 255;
894 return ( b1 << 8 ) + b2;
897 short BigShort( short l ){
902 int LittleLong( int l ){
906 b2 = ( l >> 8 ) & 255;
907 b3 = ( l >> 16 ) & 255;
908 b4 = ( l >> 24 ) & 255;
910 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
913 int BigLong( int l ){
918 float LittleFloat( float l ){
919 union {byte b[4]; float f; } in, out;
930 float BigFloat( float l ){
938 short BigShort( short l ){
942 b2 = ( l >> 8 ) & 255;
944 return ( b1 << 8 ) + b2;
947 short LittleShort( short l ){
952 int BigLong( int l ){
956 b2 = ( l >> 8 ) & 255;
957 b3 = ( l >> 16 ) & 255;
958 b4 = ( l >> 24 ) & 255;
960 return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
963 int LittleLong( int l ){
967 float BigFloat( float l ){
968 union {byte b[4]; float f; } in, out;
979 float LittleFloat( float l ){
987 //=======================================================
992 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
993 // and the initial and final xor values shown below... in other words, the
994 // CCITT standard CRC used by XMODEM
996 #define CRC_INIT_VALUE 0xffff
997 #define CRC_XOR_VALUE 0x0000
999 static unsigned short crctable[256] =
1001 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1002 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1003 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1004 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1005 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1006 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1007 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1008 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1009 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1010 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1011 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1012 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1013 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1014 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1015 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1016 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1017 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1018 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1019 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1020 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1021 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1022 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1023 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1024 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1025 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1026 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1027 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1028 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1029 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1030 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1031 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1032 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1035 void CRC_Init( unsigned short *crcvalue ){
1036 *crcvalue = CRC_INIT_VALUE;
1039 void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
1040 *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
1043 unsigned short CRC_Value( unsigned short crcvalue ){
1044 return crcvalue ^ CRC_XOR_VALUE;
1046 //=============================================================================
1053 void CreatePath( const char *path ){
1061 if ( path[1] == ':' ) {
1062 olddrive = _getdrive();
1063 _chdrive( toupper( path[0] ) - 'A' + 1 );
1067 if ( path[1] == ':' ) {
1071 for ( ofs = path + 1 ; *ofs ; ofs++ )
1074 if ( c == '/' || c == '\\' ) { // create the directory
1075 memcpy( dir, path, ofs - path );
1076 dir[ ofs - path ] = 0;
1082 if ( olddrive != -1 ) {
1083 _chdrive( olddrive );
1093 Used to archive source files
1096 void QCopyFile( const char *from, const char *to ){
1100 length = LoadFile( from, &buffer );
1102 SaveFile( to, buffer, length );
1106 void Sys_Sleep( int n ){
1110 #if GDEF_OS_LINUX || GDEF_OS_MACOS