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