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
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
339 if(!getcwd (out, 256)) *out = 0;
342 while ( out[i] != 0 )
344 if ( out[i] == '\\' )
351 void Q_mkdir (const char *path)
354 if (_mkdir (path) != -1)
357 if (mkdir (path, 0777) != -1)
361 Error ("mkdir %s: %s",path, strerror(errno));
368 returns -1 if not present
371 int FileTime (const char *path)
375 if (stat (path,&buf) == -1)
387 Parse a token out of a string
390 char *COM_Parse (char *data)
403 while ( (c = *data) <= ' ')
408 return NULL; // end of file;
414 if (c=='/' && data[1] == '/')
416 while (*data && *data != '\n')
422 // handle quoted strings specially
439 // parse single characters
440 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
448 // parse a regular word
455 if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
463 int Q_strncasecmp (const char *s1, const char *s2, int n)
473 return 0; // strings are equal until end point
477 if (c1 >= 'a' && c1 <= 'z')
479 if (c2 >= 'a' && c2 <= 'z')
482 return -1; // strings not equal
486 return 0; // strings are equal
489 int Q_stricmp (const char *s1, const char *s2)
491 return Q_strncasecmp (s1, s2, 99999);
494 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
495 // started getting warnings about that function, prolly a duplicate with the runtime function
496 // maybe we still need to have it in linux builds
498 char *strupr (char *start)
511 char *strlower (char *start)
525 =============================================================================
529 =============================================================================
537 Checks for the given parameter in the program's command line arguments
538 Returns the argument number (1 to argc-1) or 0 if not present
541 int CheckParm (const char *check)
545 for (i = 1;i<myargc;i++)
547 if ( !Q_stricmp(check, myargv[i]) )
561 int Q_filelength (FILE *f)
567 fseek (f, 0, SEEK_END);
569 fseek (f, pos, SEEK_SET);
575 FILE *SafeOpenWrite (const char *filename)
579 f = fopen(filename, "wb");
582 Error ("Error opening %s: %s",filename,strerror(errno));
587 FILE *SafeOpenRead (const char *filename)
591 f = fopen(filename, "rb");
594 Error ("Error opening %s: %s",filename,strerror(errno));
600 void SafeRead (FILE *f, void *buffer, int count)
602 if ( fread (buffer, 1, count, f) != (size_t)count)
603 Error ("File read failure");
607 void SafeWrite (FILE *f, const void *buffer, int count)
609 if (fwrite (buffer, 1, count, f) != (size_t)count)
610 Error ("File write failure");
619 qboolean FileExists (const char *filename)
623 f = fopen (filename, "r");
635 int LoadFile( const char *filename, void **bufferptr )
641 f = SafeOpenRead (filename);
642 length = Q_filelength (f);
643 buffer = safe_malloc (length+1);
644 ((char *)buffer)[length] = 0;
645 SafeRead (f, buffer, length);
657 rounds up memory allocation to 4K boundry
661 int LoadFileBlock( const char *filename, void **bufferptr )
664 int length, nBlock, nAllocSize;
667 f = SafeOpenRead (filename);
668 length = Q_filelength (f);
670 nBlock = nAllocSize % MEM_BLOCKSIZE;
672 nAllocSize += MEM_BLOCKSIZE - nBlock;
674 buffer = safe_malloc (nAllocSize+1);
675 memset(buffer, 0, nAllocSize+1);
676 SafeRead (f, buffer, length);
691 int TryLoadFile (const char *filename, void **bufferptr)
699 f = fopen (filename, "rb");
702 length = Q_filelength (f);
703 buffer = safe_malloc (length+1);
704 ((char *)buffer)[length] = 0;
705 SafeRead (f, buffer, length);
718 void SaveFile (const char *filename, const void *buffer, int count)
722 f = SafeOpenWrite (filename);
723 SafeWrite (f, buffer, count);
729 void DefaultExtension (char *path, const char *extension)
733 // if path doesnt have a .EXT, append extension
734 // (extension should include the .)
736 src = path + strlen(path) - 1;
738 while (*src != '/' && *src != '\\' && src != path)
741 return; // it has an extension
745 strcat (path, extension);
749 void DefaultPath (char *path, const char *basepath)
753 if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
754 return; // absolute path location
756 strcpy (path,basepath);
761 void StripFilename (char *path)
765 length = strlen(path)-1;
766 while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
771 void StripExtension (char *path)
775 length = strlen(path)-1;
776 while (length > 0 && path[length] != '.')
779 if (path[length] == '/' || path[ length ] == '\\' )
780 return; // no extension
792 // FIXME: should include the slash, otherwise
793 // backing to an empty path will be wrong when appending a slash
794 void ExtractFilePath (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 memcpy (dest, path, src-path);
810 void ExtractFileBase (const char *path, char *dest)
814 src = path + strlen(path) - 1;
817 // back up until a \ or the start
819 while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
822 while (*src && *src != '.')
829 void ExtractFileExtension (const char *path, char *dest)
833 src = path + strlen(path) - 1;
836 // back up until a . or the start
838 while (src != path && *(src-1) != '.')
842 *dest = 0; // no extension
855 int ParseHex (const char *hex)
866 if (*str >= '0' && *str <= '9')
868 else if (*str >= 'a' && *str <= 'f')
869 num += 10 + *str-'a';
870 else if (*str >= 'A' && *str <= 'F')
871 num += 10 + *str-'A';
873 Error ("Bad hex number: %s",hex);
881 int ParseNum (const char *str)
884 return ParseHex (str+1);
885 if (str[0] == '0' && str[1] == 'x')
886 return ParseHex (str+2);
893 ============================================================================
897 ============================================================================
901 #define __BIG_ENDIAN__
904 #ifdef __BIG_ENDIAN__
906 short LittleShort (short l)
916 short BigShort (short l)
922 int LittleLong (int l)
931 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
940 float LittleFloat (float l)
942 union {byte b[4]; float f;} in, out;
953 float BigFloat (float l)
962 short BigShort (short l)
972 short LittleShort (short l)
987 return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
990 int LittleLong (int l)
995 float BigFloat (float l)
997 union {byte b[4]; float f;} in, out;
1008 float LittleFloat (float l)
1017 //=======================================================
1020 // FIXME: byte swap?
1022 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1023 // and the initial and final xor values shown below... in other words, the
1024 // CCITT standard CRC used by XMODEM
1026 #define CRC_INIT_VALUE 0xffff
1027 #define CRC_XOR_VALUE 0x0000
1029 static unsigned short crctable[256] =
1031 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1032 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1033 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1034 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1035 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1036 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1037 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1038 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1039 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1040 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1041 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1042 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1043 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1044 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1045 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1046 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1047 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1048 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1049 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1050 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1051 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1052 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1053 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1054 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1055 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1056 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1057 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1058 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1059 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1060 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1061 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1062 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1065 void CRC_Init(unsigned short *crcvalue)
1067 *crcvalue = CRC_INIT_VALUE;
1070 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1072 *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1075 unsigned short CRC_Value(unsigned short crcvalue)
1077 return crcvalue ^ CRC_XOR_VALUE;
1079 //=============================================================================
1086 void CreatePath (const char *path)
1095 if ( path[1] == ':' )
1097 olddrive = _getdrive();
1098 _chdrive( toupper( path[0] ) - 'A' + 1 );
1105 for (ofs = path+1 ; *ofs ; ofs++)
1108 if (c == '/' || c == '\\')
1109 { // create the directory
1110 memcpy( dir, path, ofs - path );
1111 dir[ ofs - path ] = 0;
1117 if ( olddrive != -1 )
1119 _chdrive( olddrive );
1129 Used to archive source files
1132 void QCopyFile (const char *from, const char *to)
1137 length = LoadFile (from, &buffer);
1139 SaveFile (to, buffer, length);
1143 void Sys_Sleep(int n)
1148 #if defined (__linux__) || defined (__APPLE__)