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];
254 Error ("ExpandPath called without qdir set");
255 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
256 strcpy( full, path );
259 sprintf (full, "%s%s", qdir, path);
263 char *ExpandGamePath (const char *path)
265 static char full[1024];
267 Error ("ExpandGamePath called without qdir set");
268 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
269 strcpy( full, path );
272 sprintf (full, "%s%s", gamedir, path);
276 char *ExpandPathAndArchive (const char *path)
279 char archivename[1024];
281 expanded = ExpandPath (path);
285 sprintf (archivename, "%s/%s", archivedir, path);
286 QCopyFile (expanded, archivename);
292 char *copystring(const char *s)
295 b = safe_malloc(strlen(s)+1);
307 double I_FloatTime (void)
315 // more precise, less portable
320 gettimeofday(&tp, &tzp);
325 return tp.tv_usec/1000000.0;
328 return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
332 void Q_getwd (char *out)
340 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
344 while ( out[i] != 0 )
346 if ( out[i] == '\\' )
353 void Q_mkdir (const char *path)
356 const char *p = NULL;
361 const char *q = NULL;
362 if (_mkdir (path) != -1)
366 p = strrchr(path, '/');
367 q = strrchr(path, '\\');
368 if(q && (!p || q < p))
372 if (mkdir (path, 0777) != -1)
375 p = strrchr(path, '/');
379 strncpy(parentbuf, path, sizeof(parentbuf));
380 if((int) (p - path) < (int) sizeof(parentbuf))
382 parentbuf[p - path] = 0;
383 Sys_Printf ("mkdir: %s: creating parent %s first\n", path, parentbuf);
391 Error ("mkdir %s: %s",path, strerror(errno));
398 returns -1 if not present
401 int FileTime (const char *path)
405 if (stat (path,&buf) == -1)
417 Parse a token out of a string
420 char *COM_Parse (char *data)
433 while ( (c = *data) <= ' ')
438 return NULL; // end of file;
444 if (c=='/' && data[1] == '/')
446 while (*data && *data != '\n')
452 // handle quoted strings specially
469 // parse single characters
470 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
478 // parse a regular word
485 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
493 int Q_strncasecmp (const char *s1, const char *s2, int n)
503 return 0; // strings are equal until end point
507 if (c1 >= 'a' && c1 <= 'z')
509 if (c2 >= 'a' && c2 <= 'z')
512 return -1; // strings not equal
516 return 0; // strings are equal
519 int Q_stricmp (const char *s1, const char *s2)
521 return Q_strncasecmp (s1, s2, 99999);
524 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
525 // started getting warnings about that function, prolly a duplicate with the runtime function
526 // maybe we still need to have it in linux builds
528 char *strupr (char *start)
541 char *strlower (char *start)
555 =============================================================================
559 =============================================================================
567 Checks for the given parameter in the program's command line arguments
568 Returns the argument number (1 to argc-1) or 0 if not present
571 int CheckParm (const char *check)
575 for (i = 1;i<myargc;i++)
577 if ( !Q_stricmp(check, myargv[i]) )
591 int Q_filelength (FILE *f)
597 fseek (f, 0, SEEK_END);
599 fseek (f, pos, SEEK_SET);
605 FILE *SafeOpenWrite (const char *filename)
609 f = fopen(filename, "wb");
612 Error ("Error opening %s: %s",filename,strerror(errno));
617 FILE *SafeOpenRead (const char *filename)
621 f = fopen(filename, "rb");
624 Error ("Error opening %s: %s",filename,strerror(errno));
630 void SafeRead (FILE *f, void *buffer, int count)
632 if ( fread (buffer, 1, count, f) != (size_t)count)
633 Error ("File read failure");
637 void SafeWrite (FILE *f, const void *buffer, int count)
639 if (fwrite (buffer, 1, count, f) != (size_t)count)
640 Error ("File write failure");
649 qboolean FileExists (const char *filename)
653 f = fopen (filename, "r");
665 int LoadFile( const char *filename, void **bufferptr )
671 f = SafeOpenRead (filename);
672 length = Q_filelength (f);
673 buffer = safe_malloc (length+1);
674 ((char *)buffer)[length] = 0;
675 SafeRead (f, buffer, length);
687 rounds up memory allocation to 4K boundry
691 int LoadFileBlock( const char *filename, void **bufferptr )
694 int length, nBlock, nAllocSize;
697 f = SafeOpenRead (filename);
698 length = Q_filelength (f);
700 nBlock = nAllocSize % MEM_BLOCKSIZE;
702 nAllocSize += MEM_BLOCKSIZE - nBlock;
704 buffer = safe_malloc (nAllocSize+1);
705 memset(buffer, 0, nAllocSize+1);
706 SafeRead (f, buffer, length);
721 int TryLoadFile (const char *filename, void **bufferptr)
729 f = fopen (filename, "rb");
732 length = Q_filelength (f);
733 buffer = safe_malloc (length+1);
734 ((char *)buffer)[length] = 0;
735 SafeRead (f, buffer, length);
748 void SaveFile (const char *filename, const void *buffer, int count)
752 f = SafeOpenWrite (filename);
753 SafeWrite (f, buffer, count);
759 void DefaultExtension (char *path, const char *extension)
763 // if path doesnt have a .EXT, append extension
764 // (extension should include the .)
766 src = path + strlen(path) - 1;
768 while (*src != '/' && *src != '\\' && src != path)
771 return; // it has an extension
775 strcat (path, extension);
779 void DefaultPath (char *path, const char *basepath)
783 if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
784 return; // absolute path location
786 strcpy (path,basepath);
791 void StripFilename (char *path)
795 length = strlen(path)-1;
796 while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
801 void StripExtension (char *path)
805 length = strlen(path)-1;
806 while (length > 0 && path[length] != '.')
809 if (path[length] == '/' || path[ length ] == '\\' )
810 return; // no extension
822 // FIXME: should include the slash, otherwise
823 // backing to an empty path will be wrong when appending a slash
824 void ExtractFilePath (const char *path, char *dest)
828 src = path + strlen(path) - 1;
831 // back up until a \ or the start
833 while (src != path && *(src-1) != '\\' && *(src-1) != '/')
836 memcpy (dest, path, src-path);
840 void ExtractFileBase (const char *path, char *dest)
844 src = path + strlen(path) - 1;
847 // back up until a \ or the start
849 while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
852 while (*src && *src != '.')
859 void ExtractFileExtension (const char *path, char *dest)
863 src = path + strlen(path) - 1;
866 // back up until a . or the start
868 while (src != path && *(src-1) != '.')
872 *dest = 0; // no extension
885 int ParseHex (const char *hex)
896 if (*str >= '0' && *str <= '9')
898 else if (*str >= 'a' && *str <= 'f')
899 num += 10 + *str-'a';
900 else if (*str >= 'A' && *str <= 'F')
901 num += 10 + *str-'A';
903 Error ("Bad hex number: %s",hex);
911 int ParseNum (const char *str)
914 return ParseHex (str+1);
915 if (str[0] == '0' && str[1] == 'x')
916 return ParseHex (str+2);
923 ============================================================================
927 ============================================================================
931 #define __BIG_ENDIAN__
934 #ifdef __BIG_ENDIAN__
936 short LittleShort (short l)
946 short BigShort (short l)
952 int LittleLong (int l)
961 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
970 float LittleFloat (float l)
972 union {byte b[4]; float f;} in, out;
983 float BigFloat (float l)
992 short BigShort (short l)
1002 short LittleShort (short l)
1017 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
1020 int LittleLong (int l)
1025 float BigFloat (float l)
1027 union {byte b[4]; float f;} in, out;
1038 float LittleFloat (float l)
1047 //=======================================================
1050 // FIXME: byte swap?
1052 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1053 // and the initial and final xor values shown below... in other words, the
1054 // CCITT standard CRC used by XMODEM
1056 #define CRC_INIT_VALUE 0xffff
1057 #define CRC_XOR_VALUE 0x0000
1059 static unsigned short crctable[256] =
1061 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1062 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1063 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1064 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1065 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1066 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1067 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1068 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1069 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1070 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1071 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1072 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1073 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1074 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1075 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1076 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1077 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1078 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1079 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1080 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1081 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1082 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1083 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1084 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1085 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1086 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1087 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1088 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1089 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1090 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1091 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1092 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1095 void CRC_Init(unsigned short *crcvalue)
1097 *crcvalue = CRC_INIT_VALUE;
1100 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1102 *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1105 unsigned short CRC_Value(unsigned short crcvalue)
1107 return crcvalue ^ CRC_XOR_VALUE;
1109 //=============================================================================
1116 void CreatePath (const char *path)
1125 if ( path[1] == ':' )
1127 olddrive = _getdrive();
1128 _chdrive( toupper( path[0] ) - 'A' + 1 );
1135 for (ofs = path+1 ; *ofs ; ofs++)
1138 if (c == '/' || c == '\\')
1139 { // create the directory
1140 memcpy( dir, path, ofs - path );
1141 dir[ ofs - path ] = 0;
1147 if ( olddrive != -1 )
1149 _chdrive( olddrive );
1159 Used to archive source files
1162 void QCopyFile (const char *from, const char *to)
1167 length = LoadFile (from, &buffer);
1169 SaveFile (to, buffer, length);
1173 void Sys_Sleep(int n)
1178 #if defined (__linux__) || defined (__APPLE__)