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