1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 
21 #include "qwsvdef.h"
22 
23 /*
24 ============
25 va
26 
27 does a varargs printf into a temp buffer, so I don't need to have
28 varargs versions of all text functions.
29 ============
30 */
31 #define STRING_SIZE 1024
va(const char * format,...)32 char *va (const char *format, ...)
33 {
34 	va_list argptr;
35 	static char string[MAX_STRINGS][STRING_SIZE];
36 	static int index1 = 0;
37 
38 	index1 &= (MAX_STRINGS - 1);
39 	va_start (argptr, format);
40 	vsnprintf (string[index1], STRING_SIZE, format, argptr);
41 	va_end (argptr);
42 
43 	return string[index1++];
44 }
45 
46 /*
47 ============================================================================
48 
49 			LIBRARY REPLACEMENT FUNCTIONS
50 
51 ============================================================================
52 */
53 
Q_atoi(const char * str)54 int Q_atoi (const char *str)
55 {
56 	int	val;
57 	int	sign;
58 	int	c;
59 
60 	if (!str)
61 		return 0;
62 
63 	for (; *str && *str <= ' '; str++);
64 
65 	if (*str == '-')
66 	{
67 		sign = -1;
68 		str++;
69 	}
70 	else
71 	{
72 		if (*str == '+')
73 			str++;
74 
75 		sign = 1;
76 	}
77 
78 	val = 0;
79 
80 	//
81 	// check for hex
82 	//
83 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
84 	{
85 		str += 2;
86 		while (1)
87 		{
88 			c = (int)(unsigned char)*str++;
89 			if ( isdigit(c) )
90 				val = (val<<4) + c - '0';
91 			else if ( isxdigit(c) )
92 				val = (val<<4) + tolower(c) - 'a' + 10;
93 			else
94 				return val*sign;
95 		}
96 	}
97 
98 	//
99 	// check for character
100 	//
101 	if (str[0] == '\'')
102 	{
103 		return sign * str[1];
104 	}
105 
106 	//
107 	// assume decimal
108 	//
109 	while (1)
110 	{
111 		c = (int)(unsigned char)*str++;
112 		if ( !isdigit(c) )
113 			return val*sign;
114 		val = val*10 + c - '0';
115 	}
116 
117 	return 0;
118 }
119 
120 
Q_atof(const char * str)121 float Q_atof (const char *str)
122 {
123 	double	val;
124 	int		sign;
125 	int		c;
126 	int		decimal, total;
127 
128 	if (!str)
129 		return 0;
130 
131 	for (; *str && *str <= ' '; str++);
132 
133 	if (*str == '-')
134 	{
135 		sign = -1;
136 		str++;
137 	}
138 	else
139 	{
140 		if (*str == '+')
141 			str++;
142 
143 		sign = 1;
144 	}
145 
146 	val = 0;
147 
148 	//
149 	// check for hex
150 	//
151 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
152 	{
153 		str += 2;
154 		while (1)
155 		{
156 			c = (int)(unsigned char)*str++;
157 			if ( isdigit(c) )
158 				val = (val*16) + c - '0';
159 			else if ( isxdigit(c) )
160 				val = (val*16) + tolower(c) - 'a' + 10;
161 			else
162 				return val*sign;
163 		}
164 	}
165 
166 	//
167 	// check for character
168 	//
169 	if (str[0] == '\'')
170 	{
171 		return sign * str[1];
172 	}
173 
174 	//
175 	// assume decimal
176 	//
177 	decimal = -1;
178 	total = 0;
179 	while (1)
180 	{
181 		c = *str++;
182 		if (c == '.')
183 		{
184 			decimal = total;
185 			continue;
186 		}
187 		if ( !isdigit(c) )
188 			break;
189 		val = val*10 + c - '0';
190 		total++;
191 	}
192 
193 	if (decimal == -1)
194 		return val*sign;
195 	while (total > decimal)
196 	{
197 		val /= 10;
198 		total--;
199 	}
200 
201 	return val*sign;
202 }
203 
204 // removes trailing zeros
205 /*char *Q_ftos (float value)
206 {
207 	static char str[128];
208 	int	i;
209 
210 	snprintf (str, sizeof(str), "%f", value);
211 
212 	for (i=strlen(str)-1 ; i>0 && str[i]=='0' ; i--)
213 		str[i] = 0;
214 	if (str[i] == '.')
215 		str[i] = 0;
216 
217 	return str;
218 }*/
219 
220 #if defined(_MSC_VER) && (_MSC_VER < 1900)
snprintf(char * buffer,size_t count,char const * format,...)221 int snprintf(char *buffer, size_t count, char const *format, ...)
222 {
223 	int ret;
224 	va_list argptr;
225 	if (!count) return 0;
226 	va_start(argptr, format);
227 	ret = _vsnprintf(buffer, count, format, argptr);
228 	buffer[count - 1] = 0;
229 	va_end(argptr);
230 	return ret;
231 }
232 #endif // !(Visual Studio 2015+)
233 
234 #if defined(_MSC_VER) && (_MSC_VER < 1400)
vsnprintf(char * buffer,size_t count,const char * format,va_list argptr)235 int vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
236 {
237 	int ret;
238 	if (!count) return 0;
239 	ret = _vsnprintf(buffer, count, format, argptr);
240 	buffer[count - 1] = 0;
241 	return ret;
242 }
243 #endif
244 
245 #if defined(__linux__) || defined(_WIN32)
246 /*
247  * Functions strlcpy, strlcat, strnstr and strcasestr
248  * was copied from FreeBSD 4.10 libc: src/lib/libc/string/
249  *
250  *  // VVD
251  */
strlcpy(char * dst,const char * src,size_t siz)252 size_t strlcpy(char *dst, const char *src, size_t siz)
253 {
254 	register char *d = dst;
255 	register const char *s = src;
256 	register size_t n = siz;
257 
258 	/* Copy as many bytes as will fit */
259 	if (n != 0 && --n != 0)
260 	{
261 		do
262 		{
263 			if ((*d++ = *s++) == 0)
264 				break;
265 		}
266 		while (--n != 0);
267 	}
268 
269 	/* Not enough room in dst, add NUL and traverse rest of src */
270 	if (n == 0)
271 	{
272 		if (siz != 0)
273 			*d = '\0';		/* NUL-terminate dst */
274 		while (*s++)
275 			;
276 	}
277 
278 	return(s - src - 1);	/* count does not include NUL */
279 }
280 
strlcat(char * dst,const char * src,size_t siz)281 size_t strlcat(char *dst, const char *src, size_t siz)
282 {
283 	register char *d = dst;
284 	register const char *s = src;
285 	register size_t n = siz;
286 	size_t dlen;
287 
288 	/* Find the end of dst and adjust bytes left but don't go past end */
289 	while (n-- != 0 && *d != '\0')
290 		d++;
291 	dlen = d - dst;
292 	n = siz - dlen;
293 
294 	if (n == 0)
295 		return(dlen + strlen(s));
296 	while (*s != '\0')
297 	{
298 		if (n != 1)
299 		{
300 			*d++ = *s;
301 			n--;
302 		}
303 		s++;
304 	}
305 	*d = '\0';
306 
307 	return(dlen + (s - src));       /* count does not include NUL */
308 }
309 #endif
310 
311 #if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__DragonFly__)
strnstr(const char * s,const char * find,size_t slen)312 char *strnstr (const char *s, const char *find, size_t slen)
313 {
314 	char c, sc;
315 	size_t len;
316 
317 	if ((c = *find++) != '\0')
318 	{
319 		len = strlen (find);
320 		do
321 		{
322 			do
323 			{
324 				if ((sc = *s++) == '\0' || slen-- < 1)
325 					return (NULL);
326 			}
327 			while (sc != c);
328 			if (len > slen)
329 				return (NULL);
330 		}
331 		while (strncmp (s, find, len) != 0);
332 		s--;
333 	}
334 	return ((char *)s);
335 }
336 
337 /*
338  * Find the first occurrence of find in s, ignore case.
339  */
strcasestr(register const char * s,register const char * find)340 char *strcasestr(register const char *s, register const char *find)
341 {
342 	register char c, sc;
343 	register size_t len;
344 
345 	if ((c = *find++) != 0)
346 	{
347 		c = tolower((unsigned char)c);
348 		len = strlen(find);
349 		do
350 		{
351 			do
352 			{
353 				if ((sc = *s++) == 0)
354 					return (NULL);
355 			}
356 			while ((char)tolower((unsigned char)sc) != c);
357 		}
358 		while (strncasecmp(s, find, len) != 0);
359 		s--;
360 	}
361 	return ((char *)s);
362 }
363 #endif
364 
365 #ifdef _WIN32
strchrn(const char * str,const char c)366 int strchrn (const char* str, const char c)
367 {
368 	int i = 0;
369 	while (*str)
370 		if (*str++ == c)
371 			++i;
372 	return i;
373 }
374 #endif
375 
376 /*
377 ============================================================================
378 
379 			BYTE ORDER FUNCTIONS
380 
381 ============================================================================
382 */
383 
384 /*short ShortSwap (short s)
385 {
386 	byte    b1,b2;
387 
388 	b1 = s&255;
389 	b2 = (s>>8)&255;
390 
391 	return (b1<<8) + b2;
392 }
393 
394 int LongSwap (int l)
395 {
396 	byte    b1,b2,b3,b4;
397 
398 	b1 = l&255;
399 	b2 = (l>>8)&255;
400 	b3 = (l>>16)&255;
401 	b4 = (l>>24)&255;
402 
403 	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
404 }
405 
406 float FloatSwap (float f)
407 {
408 	union
409 	{
410 		float	f;
411 		byte	b[4];
412 	} dat1, dat2;
413 
414 	dat1.f = f;
415 	dat2.b[0] = dat1.b[3];
416 	dat2.b[1] = dat1.b[2];
417 	dat2.b[2] = dat1.b[1];
418 	dat2.b[3] = dat1.b[0];
419 	return dat2.f;
420 }*/
421 
422 #ifndef id386
423 #ifdef __cplusplus
424 extern "C" {
425 #endif
ShortSwap(short s)426 short ShortSwap (short s)
427 {
428 	union
429 	{
430 		short	s;
431 		byte	b[2];
432 	} dat1, dat2;
433 	dat1.s = s;
434 	dat2.b[0] = dat1.b[1];
435 	dat2.b[1] = dat1.b[0];
436 	return dat2.s;
437 }
438 
LongSwap(int l)439 int LongSwap (int l)
440 {
441 	union
442 	{
443 		int		l;
444 		byte	b[4];
445 	} dat1, dat2;
446 	dat1.l = l;
447 	dat2.b[0] = dat1.b[3];
448 	dat2.b[1] = dat1.b[2];
449 	dat2.b[2] = dat1.b[1];
450 	dat2.b[3] = dat1.b[0];
451 	return dat2.l;
452 }
453 
FloatSwap(float f)454 float FloatSwap (float f)
455 {
456 	union
457 	{
458 		float	f;
459 		byte	b[4];
460 	} dat1, dat2;
461 	dat1.f = f;
462 	dat2.b[0] = dat1.b[3];
463 	dat2.b[1] = dat1.b[2];
464 	dat2.b[2] = dat1.b[1];
465 	dat2.b[3] = dat1.b[0];
466 	return dat2.f;
467 }
468 #ifdef __cplusplus
469 }  /* extern "C" */
470 #endif
471 #endif
472 
473 #ifdef __PDP_ENDIAN__Q__
LongSwapPDP2Big(int l)474 int LongSwapPDP2Big (int l)
475 {
476 	union
477 	{
478 		int		l;
479 		byte	b[4];
480 	} dat1, dat2;
481 	dat1.l = l;
482 	dat2.b[0] = dat1.b[1];
483 	dat2.b[1] = dat1.b[0];
484 	dat2.b[2] = dat1.b[3];
485 	dat2.b[3] = dat1.b[2];
486 	return dat2.l;
487 }
488 
LongSwapPDP2Lit(int l)489 int LongSwapPDP2Lit (int l)
490 {
491 	union
492 	{
493 		int		l;
494 		short	s[2];
495 	} dat1, dat2;
496 	dat1.l = l;
497 	dat2.s[0] = dat1.s[1];
498 	dat2.s[1] = dat1.s[0];
499 	return dat2.l;
500 }
501 
FloatSwapPDP2Big(float f)502 float FloatSwapPDP2Big (float f)
503 {
504 	union
505 	{
506 		float	f;
507 		byte	b[4];
508 	} dat1, dat2;
509 	dat1.f = f;
510 	dat2.b[0] = dat1.b[1];
511 	dat2.b[1] = dat1.b[0];
512 	dat2.b[2] = dat1.b[3];
513 	dat2.b[3] = dat1.b[2];
514 	return dat2.f;
515 }
516 
FloatSwapPDP2Lit(float f)517 float FloatSwapPDP2Lit (float f)
518 {
519 	union
520 	{
521 		float	f;
522 		short	s[2];
523 	} dat1, dat2;
524 	dat1.f = f;
525 	dat2.s[0] = dat1.s[1];
526 	dat2.s[1] = dat1.s[0];
527 	return dat2.f;
528 }
529 #endif
530 
531 /*
532 ===================
533 Q_malloc
534 
535 Use it instead of malloc so that if memory allocation fails,
536 the program exits with a message saying there's not enough memory
537 instead of crashing after trying to use a NULL pointer.
538 It also sets memory to zero.
539 ===================
540 */
Q_malloc(size_t size)541 void *Q_malloc (size_t size)
542 {
543 	void *p = malloc(size);
544 	//p = calloc(1, size); //malloc & memset or just calloc?
545 	if (!p)
546 		Sys_Error ("Q_malloc: Not enough memory free");
547 	memset(p, 0, size);
548 
549 	return p;
550 }
551 
Q_calloc(size_t n,size_t size)552 void *Q_calloc (size_t n, size_t size)
553 {
554 	void *p = calloc(n, size);
555 
556 	if (!p)
557 		Sys_Error ("Q_calloc: Not enough memory free");
558 
559 	return p;
560 }
561 
562 /*
563 ===================
564 Q_strdup
565 ===================
566 */
Q_strdup(const char * src)567 char *Q_strdup (const char *src)
568 {
569 	char *p = strdup(src);
570 
571 	if (!p)
572 		Sys_Error ("Q_strdup: Not enough memory free");
573 	return p;
574 }
575 
576 
577 /*
578 ============
579 COM_StripExtension
580 ============
581 */
COM_StripExtension(char * str)582 char *COM_StripExtension (char *str)
583 {
584 	char *p = strrchr(str, '.');
585 
586     /* truncate extension */
587     if (p)
588         *p = '\0';
589 
590     return str;
591 }
592 
593 /*
594 ============
595 COM_FileExtension
596 ============
597 */
COM_FileExtension(const char * in)598 char *COM_FileExtension (const char *in)
599 {
600 	static char exten[8];
601 	int i;
602 
603 	in = strrchr(in, '.');
604 	if (!in || strchr(in, '/'))
605 		return "";
606 	in++;
607 	for (i=0 ; i<7 && *in ; i++,in++)
608 		exten[i] = *in;
609 	exten[i] = 0;
610 	return exten;
611 }
612 
613 /*
614 ==================
615 COM_DefaultExtension
616 
617 If path doesn't have a .EXT, append extension
618 (extension should include the .)
619 ==================
620 */
COM_DefaultExtension(char * path,const char * extension)621 void COM_DefaultExtension (char *path, const char *extension)
622 {
623 	char *src;
624 
625 	src = path + strlen (path) - 1;
626 
627 	while (*src != '/' && src != path)
628 	{
629 		if (*src == '.')
630 			return; // it has an extension
631 		src--;
632 	}
633 
634 	strlcat (path, extension, MAX_OSPATH);
635 }
636 
637 //=====================================================
638 
AdjustAngle(float current,float ideal,float fraction)639 float AdjustAngle(float current, float ideal, float fraction)
640 {
641 	float move = ideal - current;
642 
643 	if (move >= 180)
644 		move -= 360;
645 	else if (move <= -180)
646 		move += 360;
647 
648 	return current + fraction * move;
649 }
650 
651 //=======================================================
652 
wildcmp(char * wild,char * string)653 int wildcmp(char *wild, char *string)
654 {
655 	char *cp=NULL, *mp=NULL;
656 
657 	while ((*string) && (*wild != '*'))
658 	{
659 		if ((*wild != *string) && (*wild != '?'))
660 		{
661 			return 0;
662 		}
663 		wild++;
664 		string++;
665 	}
666 
667 	while (*string)
668 	{
669 		if (*wild == '*')
670 		{
671 			if (!*++wild)   //a * at the end of the wild string matches anything the checked string has
672 			{
673 				return 1;
674 			}
675 			mp = wild;
676 			cp = string+1;
677 		}
678 		else if ((*wild == *string) || (*wild == '?'))
679 		{
680 			wild++;
681 			string++;
682 		}
683 		else
684 		{
685 			wild = mp;
686 			string = cp++;
687 		}
688 	}
689 
690 	while (*wild == '*')
691 	{
692 		wild++;
693 	}
694 	return !*wild;
695 }
696 
697