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