2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
24 // from an intial copy of common/cmdlib.c
\r
25 // stripped out the Sys_Printf Sys_Printf stuff
\r
28 // merging alpha branch into trunk
\r
29 // replaced qprintf with Sys_Printf
\r
32 #include "mathlib.h"
\r
34 #include <sys/types.h>
\r
35 #include <sys/stat.h>
\r
39 #include <windows.h>
\r
42 #if defined (__linux__) || defined (__APPLE__)
\r
50 #define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
\r
51 #define PATHSEPERATOR '/'
\r
54 void *safe_malloc( size_t size )
\r
60 Error ("safe_malloc failed on allocation of %i bytes", size);
\r
65 void *safe_malloc_info( size_t size, char* info )
\r
71 Error ("%s: safe_malloc failed on allocation of %i bytes", info, size);
\r
77 // set these before calling CheckParm
\r
81 char com_token[1024];
\r
85 char archivedir[1024];
\r
92 Mimic unix command line expansion
\r
95 #define MAX_EX_ARGC 1024
\r
97 char *ex_argv[MAX_EX_ARGC];
\r
100 void ExpandWildcards( int *argc, char ***argv )
\r
102 struct _finddata_t fileinfo;
\r
105 char filename[1024];
\r
106 char filebase[1024];
\r
110 for (i=0 ; i<*argc ; i++)
\r
113 if ( path[0] == '-'
\r
114 || ( !strstr(path, "*") && !strstr(path, "?") ) )
\r
116 ex_argv[ex_argc++] = path;
\r
120 handle = _findfirst (path, &fileinfo);
\r
124 ExtractFilePath (path, filebase);
\r
128 sprintf (filename, "%s%s", filebase, fileinfo.name);
\r
129 ex_argv[ex_argc++] = copystring (filename);
\r
130 } while (_findnext( handle, &fileinfo ) != -1);
\r
132 _findclose (handle);
\r
139 void ExpandWildcards (int *argc, char ***argv)
\r
146 qdir will hold the path up to the quake directory, including the slash
\r
151 gamedir will hold qdir + the game directory (id1, id2, etc)
\r
156 char gamedir[1024];
\r
157 char writedir[1024];
\r
159 void SetQdirFromPath( const char *path )
\r
166 if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
\r
167 { // path is partial
\r
169 strcat (temp, path);
\r
173 // search for "quake2" in path
\r
175 len = strlen(BASEDIRNAME);
\r
176 for (c=path+strlen(path)-1 ; c != path ; c--)
\r
180 if (!Q_strncasecmp (c, BASEDIRNAME, len))
\r
183 //strncpy (qdir, path, c+len+2-path);
\r
184 // the +2 assumes a 2 or 3 following quake which is not the
\r
185 // case with a retail install
\r
186 // so we need to add up how much to the next separator
\r
189 while (*sep && *sep != '/' && *sep != '\\')
\r
194 strncpy (qdir, path, c+len+count-path);
\r
195 Sys_Printf ("qdir: %s\n", qdir);
\r
196 for ( i = 0; i < strlen( qdir ); i++ )
\r
198 if ( qdir[i] == '\\' )
\r
205 if (*c == '/' || *c == '\\')
\r
207 strncpy (gamedir, path, c+1-path);
\r
209 for ( i = 0; i < strlen( gamedir ); i++ )
\r
211 if ( gamedir[i] == '\\' )
\r
215 Sys_Printf ("gamedir: %s\n", gamedir);
\r
217 if ( !writedir[0] )
\r
218 strcpy( writedir, gamedir );
\r
219 else if ( writedir[strlen( writedir )-1] != '/' )
\r
221 writedir[strlen( writedir )] = '/';
\r
222 writedir[strlen( writedir )+1] = 0;
\r
229 Error ("No gamedir in %s", path);
\r
233 Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
\r
236 char *ExpandArg (const char *path)
\r
238 static char full[1024];
\r
240 if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
\r
243 strcat (full, path);
\r
246 strcpy (full, path);
\r
250 char *ExpandPath (const char *path)
\r
252 static char full[1024];
\r
254 Error ("ExpandPath called without qdir set");
\r
255 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
\r
256 strcpy( full, path );
\r
259 sprintf (full, "%s%s", qdir, path);
\r
263 char *ExpandGamePath (const char *path)
\r
265 static char full[1024];
\r
267 Error ("ExpandGamePath called without qdir set");
\r
268 if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
\r
269 strcpy( full, path );
\r
272 sprintf (full, "%s%s", gamedir, path);
\r
276 char *ExpandPathAndArchive (const char *path)
\r
279 char archivename[1024];
\r
281 expanded = ExpandPath (path);
\r
285 sprintf (archivename, "%s/%s", archivedir, path);
\r
286 QCopyFile (expanded, archivename);
\r
292 char *copystring(const char *s)
\r
295 b = safe_malloc(strlen(s)+1);
\r
307 double I_FloatTime (void)
\r
315 // more precise, less portable
\r
317 struct timezone tzp;
\r
318 static int secbase;
\r
320 gettimeofday(&tp, &tzp);
\r
324 secbase = tp.tv_sec;
\r
325 return tp.tv_usec/1000000.0;
\r
328 return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
\r
332 void Q_getwd (char *out)
\r
337 _getcwd (out, 256);
\r
338 strcat (out, "\\");
\r
340 // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
\r
344 while ( out[i] != 0 )
\r
346 if ( out[i] == '\\' )
\r
353 void Q_mkdir (const char *path)
\r
356 if (_mkdir (path) != -1)
\r
359 if (mkdir (path, 0777) != -1)
\r
362 if (errno != EEXIST)
\r
363 Error ("mkdir %s: %s",path, strerror(errno));
\r
370 returns -1 if not present
\r
373 int FileTime (const char *path)
\r
377 if (stat (path,&buf) == -1)
\r
380 return buf.st_mtime;
\r
389 Parse a token out of a string
\r
392 char *COM_Parse (char *data)
\r
405 while ( (c = *data) <= ' ')
\r
410 return NULL; // end of file;
\r
415 // skip // comments
\r
416 if (c=='/' && data[1] == '/')
\r
418 while (*data && *data != '\n')
\r
424 // handle quoted strings specially
\r
433 com_token[len] = 0;
\r
436 com_token[len] = c;
\r
441 // parse single characters
\r
442 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
\r
444 com_token[len] = c;
\r
446 com_token[len] = 0;
\r
450 // parse a regular word
\r
453 com_token[len] = c;
\r
457 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
\r
461 com_token[len] = 0;
\r
465 int Q_strncasecmp (const char *s1, const char *s2, int n)
\r
475 return 0; // strings are equal until end point
\r
479 if (c1 >= 'a' && c1 <= 'z')
\r
481 if (c2 >= 'a' && c2 <= 'z')
\r
484 return -1; // strings not equal
\r
488 return 0; // strings are equal
\r
491 int Q_stricmp (const char *s1, const char *s2)
\r
493 return Q_strncasecmp (s1, s2, 99999);
\r
496 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
\r
497 // started getting warnings about that function, prolly a duplicate with the runtime function
\r
498 // maybe we still need to have it in linux builds
\r
500 char *strupr (char *start)
\r
506 *in = toupper(*in);
\r
513 char *strlower (char *start)
\r
519 *in = tolower(*in);
\r
527 =============================================================================
\r
531 =============================================================================
\r
539 Checks for the given parameter in the program's command line arguments
\r
540 Returns the argument number (1 to argc-1) or 0 if not present
\r
543 int CheckParm (const char *check)
\r
547 for (i = 1;i<myargc;i++)
\r
549 if ( !Q_stricmp(check, myargv[i]) )
\r
563 int Q_filelength (FILE *f)
\r
569 fseek (f, 0, SEEK_END);
\r
571 fseek (f, pos, SEEK_SET);
\r
577 FILE *SafeOpenWrite (const char *filename)
\r
581 f = fopen(filename, "wb");
\r
584 Error ("Error opening %s: %s",filename,strerror(errno));
\r
589 FILE *SafeOpenRead (const char *filename)
\r
593 f = fopen(filename, "rb");
\r
596 Error ("Error opening %s: %s",filename,strerror(errno));
\r
602 void SafeRead (FILE *f, void *buffer, int count)
\r
604 if ( fread (buffer, 1, count, f) != (size_t)count)
\r
605 Error ("File read failure");
\r
609 void SafeWrite (FILE *f, const void *buffer, int count)
\r
611 if (fwrite (buffer, 1, count, f) != (size_t)count)
\r
612 Error ("File write failure");
\r
621 qboolean FileExists (const char *filename)
\r
625 f = fopen (filename, "r");
\r
637 int LoadFile( const char *filename, void **bufferptr )
\r
643 f = SafeOpenRead (filename);
\r
644 length = Q_filelength (f);
\r
645 buffer = safe_malloc (length+1);
\r
646 ((char *)buffer)[length] = 0;
\r
647 SafeRead (f, buffer, length);
\r
650 *bufferptr = buffer;
\r
659 rounds up memory allocation to 4K boundry
\r
663 int LoadFileBlock( const char *filename, void **bufferptr )
\r
666 int length, nBlock, nAllocSize;
\r
669 f = SafeOpenRead (filename);
\r
670 length = Q_filelength (f);
\r
671 nAllocSize = length;
\r
672 nBlock = nAllocSize % MEM_BLOCKSIZE;
\r
674 nAllocSize += MEM_BLOCKSIZE - nBlock;
\r
676 buffer = safe_malloc (nAllocSize+1);
\r
677 memset(buffer, 0, nAllocSize+1);
\r
678 SafeRead (f, buffer, length);
\r
681 *bufferptr = buffer;
\r
693 int TryLoadFile (const char *filename, void **bufferptr)
\r
701 f = fopen (filename, "rb");
\r
704 length = Q_filelength (f);
\r
705 buffer = safe_malloc (length+1);
\r
706 ((char *)buffer)[length] = 0;
\r
707 SafeRead (f, buffer, length);
\r
710 *bufferptr = buffer;
\r
720 void SaveFile (const char *filename, const void *buffer, int count)
\r
724 f = SafeOpenWrite (filename);
\r
725 SafeWrite (f, buffer, count);
\r
731 void DefaultExtension (char *path, const char *extension)
\r
735 // if path doesnt have a .EXT, append extension
\r
736 // (extension should include the .)
\r
738 src = path + strlen(path) - 1;
\r
740 while (*src != '/' && *src != '\\' && src != path)
\r
743 return; // it has an extension
\r
747 strcat (path, extension);
\r
751 void DefaultPath (char *path, const char *basepath)
\r
755 if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
\r
756 return; // absolute path location
\r
757 strcpy (temp,path);
\r
758 strcpy (path,basepath);
\r
759 strcat (path,temp);
\r
763 void StripFilename (char *path)
\r
767 length = strlen(path)-1;
\r
768 while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
\r
773 void StripExtension (char *path)
\r
777 length = strlen(path)-1;
\r
778 while (length > 0 && path[length] != '.')
\r
781 if (path[length] == '/' || path[ length ] == '\\' )
\r
782 return; // no extension
\r
790 ====================
\r
792 ====================
\r
794 // FIXME: should include the slash, otherwise
\r
795 // backing to an empty path will be wrong when appending a slash
\r
796 void ExtractFilePath (const char *path, char *dest)
\r
800 src = path + strlen(path) - 1;
\r
803 // back up until a \ or the start
\r
805 while (src != path && *(src-1) != '\\' && *(src-1) != '/')
\r
808 memcpy (dest, path, src-path);
\r
809 dest[src-path] = 0;
\r
812 void ExtractFileBase (const char *path, char *dest)
\r
816 src = path + strlen(path) - 1;
\r
819 // back up until a \ or the start
\r
821 while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
\r
824 while (*src && *src != '.')
\r
831 void ExtractFileExtension (const char *path, char *dest)
\r
835 src = path + strlen(path) - 1;
\r
838 // back up until a . or the start
\r
840 while (src != path && *(src-1) != '.')
\r
844 *dest = 0; // no extension
\r
854 ParseNum / ParseHex
\r
857 int ParseHex (const char *hex)
\r
868 if (*str >= '0' && *str <= '9')
\r
870 else if (*str >= 'a' && *str <= 'f')
\r
871 num += 10 + *str-'a';
\r
872 else if (*str >= 'A' && *str <= 'F')
\r
873 num += 10 + *str-'A';
\r
875 Error ("Bad hex number: %s",hex);
\r
883 int ParseNum (const char *str)
\r
886 return ParseHex (str+1);
\r
887 if (str[0] == '0' && str[1] == 'x')
\r
888 return ParseHex (str+2);
\r
895 ============================================================================
\r
897 BYTE ORDER FUNCTIONS
\r
899 ============================================================================
\r
903 #define __BIG_ENDIAN__
\r
906 #ifdef __BIG_ENDIAN__
\r
908 short LittleShort (short l)
\r
915 return (b1<<8) + b2;
\r
918 short BigShort (short l)
\r
924 int LittleLong (int l)
\r
933 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
\r
936 int BigLong (int l)
\r
942 float LittleFloat (float l)
\r
944 union {byte b[4]; float f;} in, out;
\r
947 out.b[0] = in.b[3];
\r
948 out.b[1] = in.b[2];
\r
949 out.b[2] = in.b[1];
\r
950 out.b[3] = in.b[0];
\r
955 float BigFloat (float l)
\r
964 short BigShort (short l)
\r
971 return (b1<<8) + b2;
\r
974 short LittleShort (short l)
\r
980 int BigLong (int l)
\r
989 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
\r
992 int LittleLong (int l)
\r
997 float BigFloat (float l)
\r
999 union {byte b[4]; float f;} in, out;
\r
1002 out.b[0] = in.b[3];
\r
1003 out.b[1] = in.b[2];
\r
1004 out.b[2] = in.b[1];
\r
1005 out.b[3] = in.b[0];
\r
1010 float LittleFloat (float l)
\r
1019 //=======================================================
\r
1022 // FIXME: byte swap?
\r
1024 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
\r
1025 // and the initial and final xor values shown below... in other words, the
\r
1026 // CCITT standard CRC used by XMODEM
\r
1028 #define CRC_INIT_VALUE 0xffff
\r
1029 #define CRC_XOR_VALUE 0x0000
\r
1031 static unsigned short crctable[256] =
\r
1033 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
\r
1034 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
\r
1035 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
\r
1036 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
\r
1037 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
\r
1038 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
\r
1039 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
\r
1040 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
\r
1041 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
\r
1042 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
\r
1043 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
\r
1044 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
\r
1045 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
\r
1046 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
\r
1047 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
\r
1048 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
\r
1049 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
\r
1050 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
\r
1051 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
\r
1052 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
\r
1053 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
\r
1054 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
\r
1055 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
\r
1056 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
\r
1057 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
\r
1058 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
\r
1059 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
\r
1060 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
\r
1061 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
\r
1062 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
\r
1063 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
\r
1064 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
\r
1067 void CRC_Init(unsigned short *crcvalue)
\r
1069 *crcvalue = CRC_INIT_VALUE;
\r
1072 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
\r
1074 *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
\r
1077 unsigned short CRC_Value(unsigned short crcvalue)
\r
1079 return crcvalue ^ CRC_XOR_VALUE;
\r
1081 //=============================================================================
\r
1088 void CreatePath (const char *path)
\r
1095 int olddrive = -1;
\r
1097 if ( path[1] == ':' )
\r
1099 olddrive = _getdrive();
\r
1100 _chdrive( toupper( path[0] ) - 'A' + 1 );
\r
1104 if (path[1] == ':')
\r
1107 for (ofs = path+1 ; *ofs ; ofs++)
\r
1110 if (c == '/' || c == '\\')
\r
1111 { // create the directory
\r
1112 memcpy( dir, path, ofs - path );
\r
1113 dir[ ofs - path ] = 0;
\r
1119 if ( olddrive != -1 )
\r
1121 _chdrive( olddrive );
\r
1131 Used to archive source files
\r
1134 void QCopyFile (const char *from, const char *to)
\r
1139 length = LoadFile (from, &buffer);
\r
1141 SaveFile (to, buffer, length);
\r
1145 void Sys_Sleep(int n)
\r
1150 #if defined (__linux__) || defined (__APPLE__)
\r
1151 usleep (n * 1000);
\r