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 )
60 Error ("safe_malloc failed on allocation of %i bytes", size);
65 void *safe_malloc_info( size_t size, char* info )
71 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 )
102 struct _finddata_t fileinfo;
110 for (i=0 ; i<*argc ; i++)
114 || ( !strstr(path, "*") && !strstr(path, "?") ) )
116 ex_argv[ex_argc++] = path;
120 handle = _findfirst (path, &fileinfo);
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);
139 void ExpandWildcards (int *argc, char ***argv)
146 qdir will hold the path up to the quake directory, including the slash
151 gamedir will hold qdir + the game directory (id1, id2, etc)
159 void SetQdirFromPath( const char *path )
166 if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
173 // search for "quake2" in path
175 len = strlen(BASEDIRNAME);
176 for (c=path+strlen(path)-1 ; c != path ; c--)
180 if (!Q_strncasecmp (c, BASEDIRNAME, len))
183 //strncpy (qdir, path, c+len+2-path);
184 // the +2 assumes a 2 or 3 following quake which is not the
185 // case with a retail install
186 // so we need to add up how much to the next separator
189 while (*sep && *sep != '/' && *sep != '\\')
194 strncpy (qdir, path, c+len+count-path);
195 Sys_Printf ("qdir: %s\n", qdir);
196 for ( i = 0; i < (int) strlen( qdir ); i++ )
198 if ( qdir[i] == '\\' )
205 if (*c == '/' || *c == '\\')
207 strncpy (gamedir, path, c+1-path);
209 for ( i = 0; i < (int) strlen( gamedir ); i++ )
211 if ( gamedir[i] == '\\' )
215 Sys_Printf ("gamedir: %s\n", gamedir);
218 strcpy( writedir, gamedir );
219 else if ( writedir[strlen( writedir )-1] != '/' )
221 writedir[strlen( writedir )] = '/';
222 writedir[strlen( writedir )+1] = 0;
229 Error ("No gamedir in %s", path);
233 Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
236 char *ExpandArg (const char *path)
238 static char full[1024];
240 if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
250 char *ExpandPath (const char *path)
252 static char full[1024];
253 if (!*qdir || path[0] == '/' || path[0] == '\\' || path[1] == ':') {
254 strcpy( full, path );
257 sprintf (full, "%s%s", qdir, path);
261 char *ExpandGamePath (const char *path)
263 static char full[1024];
265 Error ("ExpandGamePath called without gamedir set");
266 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
267 strcpy( full, path );
270 sprintf (full, "%s%s", gamedir, path);
274 char *ExpandPathAndArchive (const char *path)
277 char archivename[1024];
279 expanded = ExpandPath (path);
283 sprintf (archivename, "%s/%s", archivedir, path);
284 QCopyFile (expanded, archivename);
290 char *copystring(const char *s)
293 b = safe_malloc(strlen(s)+1);
305 double I_FloatTime (void)
313 // more precise, less portable
318 gettimeofday(&tp, &tzp);
323 return tp.tv_usec/1000000.0;
326 return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
330 void Q_getwd (char *out)
338 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
342 while ( out[i] != 0 )
344 if ( out[i] == '\\' )
351 void Q_mkdir (const char *path)
354 const char *p = NULL;
359 const char *q = NULL;
360 if (_mkdir (path) != -1)
364 p = strrchr(path, '/');
365 q = strrchr(path, '\\');
366 if(q && (!p || q < p))
370 if (mkdir (path, 0777) != -1)
373 p = strrchr(path, '/');
377 strncpy(parentbuf, path, sizeof(parentbuf));
378 if((int) (p - path) < (int) sizeof(parentbuf))
380 parentbuf[p - path] = 0;
381 Sys_Printf ("mkdir: %s: creating parent %s first\n", path, parentbuf);
389 Error ("mkdir %s: %s",path, strerror(errno));
396 returns -1 if not present
399 int FileTime (const char *path)
403 if (stat (path,&buf) == -1)
415 Parse a token out of a string
418 char *COM_Parse (char *data)
431 while ( (c = *data) <= ' ')
436 return NULL; // end of file;
442 if (c=='/' && data[1] == '/')
444 while (*data && *data != '\n')
450 // handle quoted strings specially
467 // parse single characters
468 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
476 // parse a regular word
483 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
491 int Q_strncasecmp (const char *s1, const char *s2, int n)
501 return 0; // strings are equal until end point
505 if (c1 >= 'a' && c1 <= 'z')
507 if (c2 >= 'a' && c2 <= 'z')
510 return -1; // strings not equal
514 return 0; // strings are equal
517 int Q_stricmp (const char *s1, const char *s2)
519 return Q_strncasecmp (s1, s2, 99999);
522 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
523 // started getting warnings about that function, prolly a duplicate with the runtime function
524 // maybe we still need to have it in linux builds
526 char *strupr (char *start)
539 char *strlower (char *start)
553 =============================================================================
557 =============================================================================
565 Checks for the given parameter in the program's command line arguments
566 Returns the argument number (1 to argc-1) or 0 if not present
569 int CheckParm (const char *check)
573 for (i = 1;i<myargc;i++)
575 if ( !Q_stricmp(check, myargv[i]) )
589 int Q_filelength (FILE *f)
595 fseek (f, 0, SEEK_END);
597 fseek (f, pos, SEEK_SET);
603 FILE *SafeOpenWrite (const char *filename)
607 f = fopen(filename, "wb");
610 Error ("Error opening %s: %s",filename,strerror(errno));
615 FILE *SafeOpenRead (const char *filename)
619 f = fopen(filename, "rb");
622 Error ("Error opening %s: %s",filename,strerror(errno));
628 void SafeRead (FILE *f, void *buffer, int count)
630 if ( fread (buffer, 1, count, f) != (size_t)count)
631 Error ("File read failure");
635 void SafeWrite (FILE *f, const void *buffer, int count)
637 if (fwrite (buffer, 1, count, f) != (size_t)count)
638 Error ("File write failure");
647 qboolean FileExists (const char *filename)
651 f = fopen (filename, "r");
663 int LoadFile( const char *filename, void **bufferptr )
669 f = SafeOpenRead (filename);
670 length = Q_filelength (f);
671 buffer = safe_malloc (length+1);
672 ((char *)buffer)[length] = 0;
673 SafeRead (f, buffer, length);
685 rounds up memory allocation to 4K boundry
689 int LoadFileBlock( const char *filename, void **bufferptr )
692 int length, nBlock, nAllocSize;
695 f = SafeOpenRead (filename);
696 length = Q_filelength (f);
698 nBlock = nAllocSize % MEM_BLOCKSIZE;
700 nAllocSize += MEM_BLOCKSIZE - nBlock;
702 buffer = safe_malloc (nAllocSize+1);
703 memset(buffer, 0, nAllocSize+1);
704 SafeRead (f, buffer, length);
719 int TryLoadFile (const char *filename, void **bufferptr)
727 f = fopen (filename, "rb");
730 length = Q_filelength (f);
731 buffer = safe_malloc (length+1);
732 ((char *)buffer)[length] = 0;
733 SafeRead (f, buffer, length);
746 void SaveFile (const char *filename, const void *buffer, int count)
750 f = SafeOpenWrite (filename);
751 SafeWrite (f, buffer, count);
757 void DefaultExtension (char *path, const char *extension)
761 // if path doesnt have a .EXT, append extension
762 // (extension should include the .)
764 src = path + strlen(path) - 1;
766 while (*src != '/' && *src != '\\' && src != path)
769 return; // it has an extension
773 strcat (path, extension);
777 void DefaultPath (char *path, const char *basepath)
781 if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
782 return; // absolute path location
784 strcpy (path,basepath);
789 void StripFilename (char *path)
793 length = strlen(path)-1;
794 while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
799 void StripExtension (char *path)
803 length = strlen(path)-1;
804 while (length > 0 && path[length] != '.')
807 if (path[length] == '/' || path[ length ] == '\\' )
808 return; // no extension
820 // FIXME: should include the slash, otherwise
821 // backing to an empty path will be wrong when appending a slash
822 void ExtractFilePath (const char *path, char *dest)
826 src = path + strlen(path) - 1;
829 // back up until a \ or the start
831 while (src != path && *(src-1) != '\\' && *(src-1) != '/')
834 memcpy (dest, path, src-path);
838 void ExtractFileBase (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) != '/' && *(src-1) != '\\' )
850 while (*src && *src != '.')
857 void ExtractFileExtension (const char *path, char *dest)
861 src = path + strlen(path) - 1;
864 // back up until a . or the start
866 while (src != path && *(src-1) != '.')
870 *dest = 0; // no extension
883 int ParseHex (const char *hex)
894 if (*str >= '0' && *str <= '9')
896 else if (*str >= 'a' && *str <= 'f')
897 num += 10 + *str-'a';
898 else if (*str >= 'A' && *str <= 'F')
899 num += 10 + *str-'A';
901 Error ("Bad hex number: %s",hex);
909 int ParseNum (const char *str)
912 return ParseHex (str+1);
913 if (str[0] == '0' && str[1] == 'x')
914 return ParseHex (str+2);
921 ============================================================================
925 ============================================================================
929 #define __BIG_ENDIAN__
932 #ifdef __BIG_ENDIAN__
934 short LittleShort (short l)
944 short BigShort (short l)
950 int LittleLong (int l)
959 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
968 float LittleFloat (float l)
970 union {byte b[4]; float f;} in, out;
981 float BigFloat (float l)
990 short BigShort (short l)
1000 short LittleShort (short l)
1015 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
1018 int LittleLong (int l)
1023 float BigFloat (float l)
1025 union {byte b[4]; float f;} in, out;
1036 float LittleFloat (float l)
1045 //=======================================================
1048 // FIXME: byte swap?
1050 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1051 // and the initial and final xor values shown below... in other words, the
1052 // CCITT standard CRC used by XMODEM
1054 #define CRC_INIT_VALUE 0xffff
1055 #define CRC_XOR_VALUE 0x0000
1057 static unsigned short crctable[256] =
1059 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1060 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1061 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1062 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1063 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1064 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1065 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1066 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1067 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1068 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1069 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1070 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1071 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1072 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1073 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1074 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1075 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1076 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1077 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1078 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1079 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1080 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1081 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1082 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1083 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1084 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1085 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1086 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1087 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1088 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1089 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1090 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1093 void CRC_Init(unsigned short *crcvalue)
1095 *crcvalue = CRC_INIT_VALUE;
1098 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1100 *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1103 unsigned short CRC_Value(unsigned short crcvalue)
1105 return crcvalue ^ CRC_XOR_VALUE;
1107 //=============================================================================
1114 void CreatePath (const char *path)
1123 if ( path[1] == ':' )
1125 olddrive = _getdrive();
1126 _chdrive( toupper( path[0] ) - 'A' + 1 );
1133 for (ofs = path+1 ; *ofs ; ofs++)
1136 if (c == '/' || c == '\\')
1137 { // create the directory
1138 memcpy( dir, path, ofs - path );
1139 dir[ ofs - path ] = 0;
1145 if ( olddrive != -1 )
1147 _chdrive( olddrive );
1157 Used to archive source files
1160 void QCopyFile (const char *from, const char *to)
1165 length = LoadFile (from, &buffer);
1167 SaveFile (to, buffer, length);
1171 void Sys_Sleep(int n)
1176 #if defined (__linux__) || defined (__APPLE__)