1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4 
5 This file is part of GtkRadiant.
6 
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.
11 
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.
16 
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
20 */
21 
22 // Nurail: Swiped from quake3/common
23 
24 #include "cmdlib.h"
25 #include "mathlib.h"
26 #include "inout.h"
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 
30 #ifdef WIN32
31 #include <direct.h>
32 #include <windows.h>
33 #endif
34 
35 #if defined (__linux__) || defined (__APPLE__) || defined (__FreeBSD__)
36 #include <unistd.h>
37 #endif
38 
39 #ifdef NeXT
40 #include <libc.h>
41 #endif
42 
43 #define	BASEDIRNAME	"quake"		// assumed to have a 2 or 3 following
44 #define HERETIC2_BASEDIRNAME	"h"
45 #define PATHSEPERATOR   '/'
46 
47 // qboolean verbose = false;
48 
49 #ifdef SAFE_MALLOC
safe_malloc(size_t size)50 void *safe_malloc( size_t size )
51 {
52   void *p;
53 
54   p = malloc(size);
55   if(!p)
56     Error ("safe_malloc failed on allocation of %i bytes", size);
57 
58   memset(p, 0, size);
59   return p;
60 }
61 
safe_malloc_info(size_t size,char * info)62 void *safe_malloc_info( size_t size, char* info )
63 {
64   void *p;
65 
66   p = malloc(size);
67   if(!p)
68     Error ("%s: safe_malloc failed on allocation of %i bytes", info, size);
69 
70   memset(p, 0, size);
71   return p;
72 }
73 #endif
74 
75 // set these before calling CheckParm
76 int myargc;
77 char **myargv;
78 
79 char		com_token[1024];
80 qboolean	com_eof;
81 
82 qboolean		archive;
83 char			archivedir[1024];
84 
85 
86 /*
87 ===================
88 ExpandWildcards
89 
90 Mimic unix command line expansion
91 ===================
92 */
93 #define	MAX_EX_ARGC	1024
94 int		ex_argc;
95 char	*ex_argv[MAX_EX_ARGC];
96 #ifdef WIN32
97 #include "io.h"
ExpandWildcards(int * argc,char *** argv)98 void ExpandWildcards( int *argc, char ***argv )
99 {
100 	struct _finddata_t fileinfo;
101 	int		handle;
102 	int		i;
103 	char	filename[1024];
104 	char	filebase[1024];
105 	char	*path;
106 
107 	ex_argc = 0;
108 	for (i=0 ; i<*argc ; i++)
109 	{
110 		path = (*argv)[i];
111 		if ( path[0] == '-'
112 			|| ( !strstr(path, "*") && !strstr(path, "?") ) )
113 		{
114 			ex_argv[ex_argc++] = path;
115 			continue;
116 		}
117 
118 		handle = _findfirst (path, &fileinfo);
119 		if (handle == -1)
120 			return;
121 
122 		ExtractFilePath (path, filebase);
123 
124 		do
125 		{
126 			sprintf (filename, "%s%s", filebase, fileinfo.name);
127 			ex_argv[ex_argc++] = copystring (filename);
128 		} while (_findnext( handle, &fileinfo ) != -1);
129 
130 		_findclose (handle);
131 	}
132 
133 	*argc = ex_argc;
134 	*argv = ex_argv;
135 }
136 #else
ExpandWildcards(int * argc,char *** argv)137 void ExpandWildcards (int *argc, char ***argv)
138 {
139 }
140 #endif
141 
142 /*
143 
144 qdir will hold the path up to the quake directory, including the slash
145 
146   f:\quake\
147   /raid/quake/
148 
149 gamedir will hold qdir + the game directory (id1, id2, etc)
150 
151 */
152 
153 char		qdir[1024];
154 char		gamedir[1024];
155 char		writedir[1024];
156 
SetQdirFromPath(const char * path)157 void SetQdirFromPath( const char *path )
158 {
159 	char	temp[1024];
160 	const char	*c;
161   const char *sep;
162 	int		len, count;
163 	char	basedirname[256];
164 
165 	if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
166 	{	// path is partial
167 		Q_getwd (temp);
168 		strcat (temp, path);
169 		path = temp;
170 	}
171 
172 	// search for "quake2" in path
173 
174 	if ( !strcmp( game, "heretic2" ) )
175 		strncpy(basedirname, HERETIC2_BASEDIRNAME, 256);
176 	else
177 		strncpy(basedirname, BASEDIRNAME, 256);
178 
179 	len = strlen(basedirname);
180 	for (c=path+strlen(path)-1 ; c != path ; c--)
181 	{
182 		int i;
183 
184 		if (!Q_strncasecmp (c, basedirname, len))
185 		{
186       //
187 			//strncpy (qdir, path, c+len+2-path);
188       // the +2 assumes a 2 or 3 following quake which is not the
189       // case with a retail install
190       // so we need to add up how much to the next separator
191       sep = c + len;
192       count = 1;
193       while (*sep && *sep != '/' && *sep != '\\')
194       {
195         sep++;
196         count++;
197       }
198 			strncpy (qdir, path, c+len+count-path);
199 			Sys_FPrintf( SYS_VRB, "qdir: %s\n", qdir);
200 			for ( i = 0; i < strlen( qdir ); i++ )
201 			{
202 				if ( qdir[i] == '\\' )
203 					qdir[i] = '/';
204 			}
205 
206 			c += len+count;
207 			while (*c)
208 			{
209 				if (*c == '/' || *c == '\\')
210 				{
211 					strncpy (gamedir, path, c+1-path);
212 
213 					for ( i = 0; i < strlen( gamedir ); i++ )
214 					{
215 						if ( gamedir[i] == '\\' )
216 							gamedir[i] = '/';
217 					}
218 
219 					Sys_FPrintf( SYS_VRB, "gamedir: %s\n", gamedir);
220 
221 					if ( !writedir[0] )
222 						strcpy( writedir, gamedir );
223 					else if ( writedir[strlen( writedir )-1] != '/' )
224 					{
225 						writedir[strlen( writedir )] = '/';
226 						writedir[strlen( writedir )+1] = 0;
227 					}
228 
229 					return;
230 				}
231 				c++;
232 			}
233 			Error ("No gamedir in %s", path);
234 			return;
235 		}
236 	}
237 	Error ("SetQdirFromPath: no '%s' in %s", basedirname, path);
238 }
239 
ExpandArg(const char * path)240 char *ExpandArg (const char *path)
241 {
242 	static char full[1024];
243 
244 	if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
245 	{
246 		Q_getwd (full);
247 		strcat (full, path);
248 	}
249 	else
250 		strcpy (full, path);
251 	return full;
252 }
253 
ExpandPath(const char * path)254 char *ExpandPath (const char *path)
255 {
256 	static char full[1024];
257 	if (!qdir)
258 		Error ("ExpandPath called without qdir set");
259 	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
260 		strcpy( full, path );
261 		return full;
262 	}
263 	sprintf (full, "%s%s", qdir, path);
264 	return full;
265 }
266 
ExpandGamePath(const char * path)267 char *ExpandGamePath (const char *path)
268 {
269 	static char full[1024];
270 	if (!qdir)
271 		Error ("ExpandGamePath called without qdir set");
272 	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
273 		strcpy( full, path );
274 		return full;
275 	}
276 	sprintf (full, "%s%s", gamedir, path);
277 	return full;
278 }
279 
ExpandPathAndArchive(const char * path)280 char *ExpandPathAndArchive (const char *path)
281 {
282 	char	*expanded;
283 	char	archivename[1024];
284 
285 	expanded = ExpandPath (path);
286 
287 	if (archive)
288 	{
289 		sprintf (archivename, "%s/%s", archivedir, path);
290 		QCopyFile (expanded, archivename);
291 	}
292 	return expanded;
293 }
294 
295 
copystring(const char * s)296 char *copystring(const char *s)
297 {
298 	char	*b;
299 	b = safe_malloc(strlen(s)+1);
300 	strcpy (b, s);
301 	return b;
302 }
303 
304 
305 
306 /*
307 ================
308 I_FloatTime
309 ================
310 */
I_FloatTime(void)311 double I_FloatTime (void)
312 {
313 	time_t	t;
314 
315 	time (&t);
316 
317 	return t;
318 #if 0
319 // more precise, less portable
320 	struct timeval tp;
321 	struct timezone tzp;
322 	static int		secbase;
323 
324 	gettimeofday(&tp, &tzp);
325 
326 	if (!secbase)
327 	{
328 		secbase = tp.tv_sec;
329 		return tp.tv_usec/1000000.0;
330 	}
331 
332 	return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
333 #endif
334 }
335 
Q_getwd(char * out)336 void Q_getwd (char *out)
337 {
338 	int i = 0;
339 
340 #ifdef WIN32
341    _getcwd (out, 256);
342    strcat (out, "\\");
343 #else
344    // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
345    getcwd (out, 256);
346    strcat (out, "/");
347 #endif
348    while ( out[i] != 0 )
349    {
350 	   if ( out[i] == '\\' )
351 		   out[i] = '/';
352 	   i++;
353    }
354 }
355 
356 
Q_mkdir(const char * path)357 void Q_mkdir (const char *path)
358 {
359 #ifdef WIN32
360 	if (_mkdir (path) != -1)
361 		return;
362 #else
363 	if (mkdir (path, 0777) != -1)
364 		return;
365 #endif
366 	if (errno != EEXIST)
367 		Error ("mkdir %s: %s",path, strerror(errno));
368 }
369 
370 /*
371 ============
372 FileTime
373 
374 returns -1 if not present
375 ============
376 */
FileTime(const char * path)377 int	FileTime (const char *path)
378 {
379 	struct	stat	buf;
380 
381 	if (stat (path,&buf) == -1)
382 		return -1;
383 
384 	return buf.st_mtime;
385 }
386 
387 
388 
389 /*
390 ==============
391 COM_Parse
392 
393 Parse a token out of a string
394 ==============
395 */
COM_Parse(char * data)396 char *COM_Parse (char *data)
397 {
398 	int		c;
399 	int		len;
400 
401 	len = 0;
402 	com_token[0] = 0;
403 
404 	if (!data)
405 		return NULL;
406 
407 // skip whitespace
408 skipwhite:
409 	while ( (c = *data) <= ' ')
410 	{
411 		if (c == 0)
412 		{
413 			com_eof = true;
414 			return NULL;			// end of file;
415 		}
416 		data++;
417 	}
418 
419 // skip // comments
420 	if (c=='/' && data[1] == '/')
421 	{
422 		while (*data && *data != '\n')
423 			data++;
424 		goto skipwhite;
425 	}
426 
427 
428 // handle quoted strings specially
429 	if (c == '\"')
430 	{
431 		data++;
432 		do
433 		{
434 			c = *data++;
435 			if (c=='\"')
436 			{
437 				com_token[len] = 0;
438 				return data;
439 			}
440 			com_token[len] = c;
441 			len++;
442 		} while (1);
443 	}
444 
445 // parse single characters
446 	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
447 	{
448 		com_token[len] = c;
449 		len++;
450 		com_token[len] = 0;
451 		return data+1;
452 	}
453 
454 // parse a regular word
455 	do
456 	{
457 		com_token[len] = c;
458 		data++;
459 		len++;
460 		c = *data;
461 	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
462 			break;
463 	} while (c>32);
464 
465 	com_token[len] = 0;
466 	return data;
467 }
468 
Q_strncasecmp(const char * s1,const char * s2,int n)469 int Q_strncasecmp (const char *s1, const char *s2, int n)
470 {
471 	int		c1, c2;
472 
473 	do
474 	{
475 		c1 = *s1++;
476 		c2 = *s2++;
477 
478 		if (!n--)
479 			return 0;		// strings are equal until end point
480 
481 		if (c1 != c2)
482 		{
483 			if (c1 >= 'a' && c1 <= 'z')
484 				c1 -= ('a' - 'A');
485 			if (c2 >= 'a' && c2 <= 'z')
486 				c2 -= ('a' - 'A');
487 			if (c1 != c2)
488 				return -1;		// strings not equal
489 		}
490 	} while (c1);
491 
492 	return 0;		// strings are equal
493 }
494 
Q_stricmp(const char * s1,const char * s2)495 int Q_stricmp (const char *s1, const char *s2)
496 {
497 	return Q_strncasecmp (s1, s2, 99999);
498 }
499 
Q_strcasecmp(const char * s1,const char * s2)500 int Q_strcasecmp (const char *s1, const char *s2)
501 {
502 	return Q_strncasecmp (s1, s2, 99999);
503 }
504 
505 
506 // NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
507 //   started getting warnings about that function, prolly a duplicate with the runtime function
508 //   maybe we still need to have it in linux builds
509 /*
510 char *strupr (char *start)
511 {
512 	char	*in;
513 	in = start;
514 	while (*in)
515 	{
516 		*in = toupper(*in);
517 		in++;
518 	}
519 	return start;
520 }
521 */
522 
strlower(char * start)523 char *strlower (char *start)
524 {
525 	char	*in;
526 	in = start;
527 	while (*in)
528 	{
529 		*in = tolower(*in);
530 		in++;
531 	}
532 	return start;
533 }
534 
535 
536 /*
537 =============================================================================
538 
539 						MISC FUNCTIONS
540 
541 =============================================================================
542 */
543 
544 
545 /*
546 =================
547 CheckParm
548 
549 Checks for the given parameter in the program's command line arguments
550 Returns the argument number (1 to argc-1) or 0 if not present
551 =================
552 */
CheckParm(const char * check)553 int CheckParm (const char *check)
554 {
555 	int             i;
556 
557 	for (i = 1;i<myargc;i++)
558 	{
559 		if ( !Q_stricmp(check, myargv[i]) )
560 			return i;
561 	}
562 
563 	return 0;
564 }
565 
566 
567 
568 /*
569 ================
570 Q_filelength
571 ================
572 */
Q_filelength(FILE * f)573 int Q_filelength (FILE *f)
574 {
575 	int		pos;
576 	int		end;
577 
578 	pos = ftell (f);
579 	fseek (f, 0, SEEK_END);
580 	end = ftell (f);
581 	fseek (f, pos, SEEK_SET);
582 
583 	return end;
584 }
585 
586 
SafeOpenWrite(const char * filename)587 FILE *SafeOpenWrite (const char *filename)
588 {
589 	FILE	*f;
590 
591 	f = fopen(filename, "wb");
592 
593 	if (!f)
594 		Error ("Error opening %s: %s",filename,strerror(errno));
595 
596 	return f;
597 }
598 
SafeOpenRead(const char * filename)599 FILE *SafeOpenRead (const char *filename)
600 {
601 	FILE	*f;
602 
603 	f = fopen(filename, "rb");
604 
605 	if (!f)
606 		Error ("Error opening %s: %s",filename,strerror(errno));
607 
608 	return f;
609 }
610 
611 
SafeRead(FILE * f,void * buffer,int count)612 void SafeRead (FILE *f, void *buffer, int count)
613 {
614 	if ( fread (buffer, 1, count, f) != (size_t)count)
615 		Error ("File read failure");
616 }
617 
618 
SafeWrite(FILE * f,const void * buffer,int count)619 void SafeWrite (FILE *f, const void *buffer, int count)
620 {
621 	if (fwrite (buffer, 1, count, f) != (size_t)count)
622 		Error ("File write failure");
623 }
624 
625 
626 /*
627 ==============
628 FileExists
629 ==============
630 */
FileExists(const char * filename)631 qboolean	FileExists (const char *filename)
632 {
633 	FILE	*f;
634 
635 	f = fopen (filename, "r");
636 	if (!f)
637 		return false;
638 	fclose (f);
639 	return true;
640 }
641 
642 /*
643 ==============
644 LoadFile
645 ==============
646 */
LoadFile(const char * filename,void ** bufferptr)647 int    LoadFile( const char *filename, void **bufferptr )
648 {
649 	FILE	*f;
650 	int    length;
651 	void    *buffer;
652 
653 	f = SafeOpenRead (filename);
654 	length = Q_filelength (f);
655 	buffer = safe_malloc (length+1);
656 	((char *)buffer)[length] = 0;
657 	SafeRead (f, buffer, length);
658 	fclose (f);
659 
660 	*bufferptr = buffer;
661 	return length;
662 }
663 
664 
665 /*
666 ==============
667 LoadFileBlock
668 -
669 rounds up memory allocation to 4K boundry
670 -
671 ==============
672 */
LoadFileBlock(const char * filename,void ** bufferptr)673 int    LoadFileBlock( const char *filename, void **bufferptr )
674 {
675 	FILE	*f;
676 	int    length, nBlock, nAllocSize;
677 	void    *buffer;
678 
679 	f = SafeOpenRead (filename);
680 	length = Q_filelength (f);
681   nAllocSize = length;
682   nBlock = nAllocSize % MEM_BLOCKSIZE;
683   if ( nBlock > 0) {
684     nAllocSize += MEM_BLOCKSIZE - nBlock;
685   }
686 	buffer = safe_malloc (nAllocSize+1);
687   memset(buffer, 0, nAllocSize+1);
688 	SafeRead (f, buffer, length);
689 	fclose (f);
690 
691 	*bufferptr = buffer;
692 	return length;
693 }
694 
695 
696 /*
697 ==============
698 TryLoadFile
699 
700 Allows failure
701 ==============
702 */
TryLoadFile(const char * filename,void ** bufferptr)703 int    TryLoadFile (const char *filename, void **bufferptr)
704 {
705 	FILE	*f;
706 	int    length;
707 	void    *buffer;
708 
709 	*bufferptr = NULL;
710 
711 	f = fopen (filename, "rb");
712 	if (!f)
713 		return -1;
714 	length = Q_filelength (f);
715 	buffer = safe_malloc (length+1);
716 	((char *)buffer)[length] = 0;
717 	SafeRead (f, buffer, length);
718 	fclose (f);
719 
720 	*bufferptr = buffer;
721 	return length;
722 }
723 
724 
725 /*
726 ==============
727 SaveFile
728 ==============
729 */
SaveFile(const char * filename,const void * buffer,int count)730 void    SaveFile (const char *filename, const void *buffer, int count)
731 {
732 	FILE	*f;
733 
734 	f = SafeOpenWrite (filename);
735 	SafeWrite (f, buffer, count);
736 	fclose (f);
737 }
738 
739 
740 
DefaultExtension(char * path,const char * extension)741 void DefaultExtension (char *path, const char *extension)
742 {
743 	char    *src;
744 //
745 // if path doesnt have a .EXT, append extension
746 // (extension should include the .)
747 //
748 	src = path + strlen(path) - 1;
749 
750 	while (*src != '/' && *src != '\\' && src != path)
751 	{
752 		if (*src == '.')
753 			return;                 // it has an extension
754 		src--;
755 	}
756 
757 	strcat (path, extension);
758 }
759 
760 
DefaultPath(char * path,const char * basepath)761 void DefaultPath (char *path, const char *basepath)
762 {
763 	char    temp[128];
764 
765 	if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
766 		return;                   // absolute path location
767 	strcpy (temp,path);
768 	strcpy (path,basepath);
769 	strcat (path,temp);
770 }
771 
772 
StripFilename(char * path)773 void    StripFilename (char *path)
774 {
775 	int             length;
776 
777 	length = strlen(path)-1;
778 	while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
779 		length--;
780 	path[length] = 0;
781 }
782 
StripExtension(char * path)783 void    StripExtension (char *path)
784 {
785 	int             length;
786 
787 	length = strlen(path)-1;
788 	while (length > 0 && path[length] != '.')
789 	{
790 		length--;
791 		if (path[length] == '/' || path[ length ] == '\\' )
792 			return;		// no extension
793 	}
794 	if (length)
795 		path[length] = 0;
796 }
797 
798 
799 /*
800 ====================
801 Extract file parts
802 ====================
803 */
804 // FIXME: should include the slash, otherwise
805 // backing to an empty path will be wrong when appending a slash
ExtractFilePath(const char * path,char * dest)806 void ExtractFilePath (const char *path, char *dest)
807 {
808 	const char    *src;
809 
810 	src = path + strlen(path) - 1;
811 
812 //
813 // back up until a \ or the start
814 //
815 	while (src != path && *(src-1) != '\\' && *(src-1) != '/')
816 		src--;
817 
818 	memcpy (dest, path, src-path);
819 	dest[src-path] = 0;
820 }
821 
ExtractFileBase(const char * path,char * dest)822 void ExtractFileBase (const char *path, char *dest)
823 {
824 	const char    *src;
825 
826 	src = path + strlen(path) - 1;
827 
828 //
829 // back up until a \ or the start
830 //
831 	while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
832 		src--;
833 
834 	while (*src && *src != '.')
835 	{
836 		*dest++ = *src++;
837 	}
838 	*dest = 0;
839 }
840 
ExtractFileExtension(const char * path,char * dest)841 void ExtractFileExtension (const char *path, char *dest)
842 {
843 	const char    *src;
844 
845 	src = path + strlen(path) - 1;
846 
847 //
848 // back up until a . or the start
849 //
850 	while (src != path && *(src-1) != '.')
851 		src--;
852 	if (src == path)
853 	{
854 		*dest = 0;	// no extension
855 		return;
856 	}
857 
858 	strcpy (dest,src);
859 }
860 
861 
862 /*
863 ==============
864 ParseNum / ParseHex
865 ==============
866 */
ParseHex(const char * hex)867 int ParseHex (const char *hex)
868 {
869 	const char    *str;
870 	int    num;
871 
872 	num = 0;
873 	str = hex;
874 
875 	while (*str)
876 	{
877 		num <<= 4;
878 		if (*str >= '0' && *str <= '9')
879 			num += *str-'0';
880 		else if (*str >= 'a' && *str <= 'f')
881 			num += 10 + *str-'a';
882 		else if (*str >= 'A' && *str <= 'F')
883 			num += 10 + *str-'A';
884 		else
885 			Error ("Bad hex number: %s",hex);
886 		str++;
887 	}
888 
889 	return num;
890 }
891 
892 
ParseNum(const char * str)893 int ParseNum (const char *str)
894 {
895 	if (str[0] == '$')
896 		return ParseHex (str+1);
897 	if (str[0] == '0' && str[1] == 'x')
898 		return ParseHex (str+2);
899 	return atol (str);
900 }
901 /*
902 // all output ends up through here
903 void FPrintf (int flag, char *buf)
904 {
905   printf(buf);
906 
907 }
908 
909 void Sys_FPrintf (int flag, const char *format, ...)
910 {
911   char out_buffer[4096];
912 	va_list argptr;
913 
914   if ((flag == SYS_VRB) && (verbose == false))
915     return;
916 
917   va_start (argptr, format);
918 	vsprintf (out_buffer, format, argptr);
919 	va_end (argptr);
920 
921   FPrintf (flag, out_buffer);
922 }
923 
924 void Sys_Printf (const char *format, ...)
925 {
926   char out_buffer[4096];
927 	va_list argptr;
928 
929   va_start (argptr, format);
930 	vsprintf (out_buffer, format, argptr);
931 	va_end (argptr);
932 
933   FPrintf (SYS_STD, out_buffer);
934 }
935 
936 
937 //=================
938 //Error
939 //
940 //For abnormal program terminations
941 //=================
942 
943 void Error( const char *error, ...)
944 {
945   char out_buffer[4096];
946   char tmp[4096];
947 	va_list argptr;
948 
949 	va_start (argptr,error);
950 	vsprintf (tmp, error, argptr);
951 	va_end (argptr);
952 
953   sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
954 
955   FPrintf( SYS_ERR, out_buffer );
956 
957 	exit (1);
958 }
959 */
960 
961 
962 /*
963 ============================================================================
964 
965 					BYTE ORDER FUNCTIONS
966 
967 ============================================================================
968 */
969 
970 #ifdef _SGI_SOURCE
971 #define	__BIG_ENDIAN__
972 #endif
973 
974 #ifdef __BIG_ENDIAN__
975 
LittleShort(short l)976 short   LittleShort (short l)
977 {
978 	byte    b1,b2;
979 
980 	b1 = l&255;
981 	b2 = (l>>8)&255;
982 
983 	return (b1<<8) + b2;
984 }
985 
BigShort(short l)986 short   BigShort (short l)
987 {
988 	return l;
989 }
990 
991 
LittleLong(int l)992 int    LittleLong (int l)
993 {
994 	byte    b1,b2,b3,b4;
995 
996 	b1 = l&255;
997 	b2 = (l>>8)&255;
998 	b3 = (l>>16)&255;
999 	b4 = (l>>24)&255;
1000 
1001 	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
1002 }
1003 
BigLong(int l)1004 int    BigLong (int l)
1005 {
1006 	return l;
1007 }
1008 
1009 
LittleFloat(float l)1010 float	LittleFloat (float l)
1011 {
1012 	union {byte b[4]; float f;} in, out;
1013 
1014 	in.f = l;
1015 	out.b[0] = in.b[3];
1016 	out.b[1] = in.b[2];
1017 	out.b[2] = in.b[1];
1018 	out.b[3] = in.b[0];
1019 
1020 	return out.f;
1021 }
1022 
BigFloat(float l)1023 float	BigFloat (float l)
1024 {
1025 	return l;
1026 }
1027 
1028 
1029 #else
1030 
1031 
BigShort(short l)1032 short   BigShort (short l)
1033 {
1034 	byte    b1,b2;
1035 
1036 	b1 = l&255;
1037 	b2 = (l>>8)&255;
1038 
1039 	return (b1<<8) + b2;
1040 }
1041 
LittleShort(short l)1042 short   LittleShort (short l)
1043 {
1044 	return l;
1045 }
1046 
1047 
BigLong(int l)1048 int    BigLong (int l)
1049 {
1050 	byte    b1,b2,b3,b4;
1051 
1052 	b1 = l&255;
1053 	b2 = (l>>8)&255;
1054 	b3 = (l>>16)&255;
1055 	b4 = (l>>24)&255;
1056 
1057 	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
1058 }
1059 
LittleLong(int l)1060 int    LittleLong (int l)
1061 {
1062 	return l;
1063 }
1064 
BigFloat(float l)1065 float	BigFloat (float l)
1066 {
1067 	union {byte b[4]; float f;} in, out;
1068 
1069 	in.f = l;
1070 	out.b[0] = in.b[3];
1071 	out.b[1] = in.b[2];
1072 	out.b[2] = in.b[1];
1073 	out.b[3] = in.b[0];
1074 
1075 	return out.f;
1076 }
1077 
LittleFloat(float l)1078 float	LittleFloat (float l)
1079 {
1080 	return l;
1081 }
1082 
1083 
1084 #endif
1085 
1086 
1087 //=======================================================
1088 
1089 
1090 // FIXME: byte swap?
1091 
1092 // this is a 16 bit, non-reflected CRC using the polynomial 0x1021
1093 // and the initial and final xor values shown below...  in other words, the
1094 // CCITT standard CRC used by XMODEM
1095 
1096 #define CRC_INIT_VALUE	0xffff
1097 #define CRC_XOR_VALUE	0x0000
1098 
1099 static unsigned short crctable[256] =
1100 {
1101 	0x0000,	0x1021,	0x2042,	0x3063,	0x4084,	0x50a5,	0x60c6,	0x70e7,
1102 	0x8108,	0x9129,	0xa14a,	0xb16b,	0xc18c,	0xd1ad,	0xe1ce,	0xf1ef,
1103 	0x1231,	0x0210,	0x3273,	0x2252,	0x52b5,	0x4294,	0x72f7,	0x62d6,
1104 	0x9339,	0x8318,	0xb37b,	0xa35a,	0xd3bd,	0xc39c,	0xf3ff,	0xe3de,
1105 	0x2462,	0x3443,	0x0420,	0x1401,	0x64e6,	0x74c7,	0x44a4,	0x5485,
1106 	0xa56a,	0xb54b,	0x8528,	0x9509,	0xe5ee,	0xf5cf,	0xc5ac,	0xd58d,
1107 	0x3653,	0x2672,	0x1611,	0x0630,	0x76d7,	0x66f6,	0x5695,	0x46b4,
1108 	0xb75b,	0xa77a,	0x9719,	0x8738,	0xf7df,	0xe7fe,	0xd79d,	0xc7bc,
1109 	0x48c4,	0x58e5,	0x6886,	0x78a7,	0x0840,	0x1861,	0x2802,	0x3823,
1110 	0xc9cc,	0xd9ed,	0xe98e,	0xf9af,	0x8948,	0x9969,	0xa90a,	0xb92b,
1111 	0x5af5,	0x4ad4,	0x7ab7,	0x6a96,	0x1a71,	0x0a50,	0x3a33,	0x2a12,
1112 	0xdbfd,	0xcbdc,	0xfbbf,	0xeb9e,	0x9b79,	0x8b58,	0xbb3b,	0xab1a,
1113 	0x6ca6,	0x7c87,	0x4ce4,	0x5cc5,	0x2c22,	0x3c03,	0x0c60,	0x1c41,
1114 	0xedae,	0xfd8f,	0xcdec,	0xddcd,	0xad2a,	0xbd0b,	0x8d68,	0x9d49,
1115 	0x7e97,	0x6eb6,	0x5ed5,	0x4ef4,	0x3e13,	0x2e32,	0x1e51,	0x0e70,
1116 	0xff9f,	0xefbe,	0xdfdd,	0xcffc,	0xbf1b,	0xaf3a,	0x9f59,	0x8f78,
1117 	0x9188,	0x81a9,	0xb1ca,	0xa1eb,	0xd10c,	0xc12d,	0xf14e,	0xe16f,
1118 	0x1080,	0x00a1,	0x30c2,	0x20e3,	0x5004,	0x4025,	0x7046,	0x6067,
1119 	0x83b9,	0x9398,	0xa3fb,	0xb3da,	0xc33d,	0xd31c,	0xe37f,	0xf35e,
1120 	0x02b1,	0x1290,	0x22f3,	0x32d2,	0x4235,	0x5214,	0x6277,	0x7256,
1121 	0xb5ea,	0xa5cb,	0x95a8,	0x8589,	0xf56e,	0xe54f,	0xd52c,	0xc50d,
1122 	0x34e2,	0x24c3,	0x14a0,	0x0481,	0x7466,	0x6447,	0x5424,	0x4405,
1123 	0xa7db,	0xb7fa,	0x8799,	0x97b8,	0xe75f,	0xf77e,	0xc71d,	0xd73c,
1124 	0x26d3,	0x36f2,	0x0691,	0x16b0,	0x6657,	0x7676,	0x4615,	0x5634,
1125 	0xd94c,	0xc96d,	0xf90e,	0xe92f,	0x99c8,	0x89e9,	0xb98a,	0xa9ab,
1126 	0x5844,	0x4865,	0x7806,	0x6827,	0x18c0,	0x08e1,	0x3882,	0x28a3,
1127 	0xcb7d,	0xdb5c,	0xeb3f,	0xfb1e,	0x8bf9,	0x9bd8,	0xabbb,	0xbb9a,
1128 	0x4a75,	0x5a54,	0x6a37,	0x7a16,	0x0af1,	0x1ad0,	0x2ab3,	0x3a92,
1129 	0xfd2e,	0xed0f,	0xdd6c,	0xcd4d,	0xbdaa,	0xad8b,	0x9de8,	0x8dc9,
1130 	0x7c26,	0x6c07,	0x5c64,	0x4c45,	0x3ca2,	0x2c83,	0x1ce0,	0x0cc1,
1131 	0xef1f,	0xff3e,	0xcf5d,	0xdf7c,	0xaf9b,	0xbfba,	0x8fd9,	0x9ff8,
1132 	0x6e17,	0x7e36,	0x4e55,	0x5e74,	0x2e93,	0x3eb2,	0x0ed1,	0x1ef0
1133 };
1134 
CRC_Init(unsigned short * crcvalue)1135 void CRC_Init(unsigned short *crcvalue)
1136 {
1137 	*crcvalue = CRC_INIT_VALUE;
1138 }
1139 
CRC_ProcessByte(unsigned short * crcvalue,byte data)1140 void CRC_ProcessByte(unsigned short *crcvalue, byte data)
1141 {
1142 	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
1143 }
1144 
CRC_Value(unsigned short crcvalue)1145 unsigned short CRC_Value(unsigned short crcvalue)
1146 {
1147 	return crcvalue ^ CRC_XOR_VALUE;
1148 }
1149 //=============================================================================
1150 
1151 /*
1152 ============
1153 CreatePath
1154 ============
1155 */
CreatePath(const char * path)1156 void	CreatePath (const char *path)
1157 {
1158 	const char	*ofs;
1159 	char		c;
1160 	char		dir[1024];
1161 
1162 #ifdef WIN32
1163 	int		olddrive = -1;
1164 
1165 	if ( path[1] == ':' )
1166 	{
1167 		olddrive = _getdrive();
1168 		_chdrive( toupper( path[0] ) - 'A' + 1 );
1169 	}
1170 #endif
1171 
1172 	if (path[1] == ':')
1173 		path += 2;
1174 
1175 	for (ofs = path+1 ; *ofs ; ofs++)
1176 	{
1177 		c = *ofs;
1178 		if (c == '/' || c == '\\')
1179 		{	// create the directory
1180 			memcpy( dir, path, ofs - path );
1181 			dir[ ofs - path ] = 0;
1182 			Q_mkdir( dir );
1183 		}
1184 	}
1185 
1186 #ifdef WIN32
1187 	if ( olddrive != -1 )
1188 	{
1189 		_chdrive( olddrive );
1190 	}
1191 #endif
1192 }
1193 
1194 
1195 /*
1196 ============
1197 QCopyFile
1198 
1199   Used to archive source files
1200 ============
1201 */
QCopyFile(const char * from,const char * to)1202 void QCopyFile (const char *from, const char *to)
1203 {
1204 	void	*buffer;
1205 	int		length;
1206 
1207 	length = LoadFile (from, &buffer);
1208 	CreatePath (to);
1209 	SaveFile (to, buffer, length);
1210 	free (buffer);
1211 }
1212 
Sys_Sleep(int n)1213 void Sys_Sleep(int n)
1214 {
1215 #ifdef WIN32
1216   Sleep (n);
1217 #endif
1218 #if defined (__linux__) || defined (__APPLE__) || defined (__FreeBSD__)
1219   usleep (n * 1000);
1220 #endif
1221 }
1222