1 //
2 //
3 // bg_lib,c -- standard C library replacement routines used by code
4 // compiled for the virtual machine
5 
6 #ifdef Q3_VM
7 
8 #include "../qcommon/q_shared.h"
9 
10 /*-
11  * Copyright (c) 1992, 1993
12  *	The Regents of the University of California.  All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #include "bg_lib.h"
40 
41 #if defined(LIBC_SCCS) && !defined(lint)
42 #if 0
43 static char sccsid[] = "@(#)qsort.c	8.1 (Berkeley) 6/4/93";
44 #endif
45 static const char rcsid[] =
46 #endif /* LIBC_SCCS and not lint */
47 
48 static char* med3(char *, char *, char *, cmp_t *);
49 static void	 swapfunc(char *, char *, int, int);
50 
51 /*
52  * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
53  */
54 #define swapcode(TYPE, parmi, parmj, n) {		\
55 	long i = (n) / sizeof (TYPE);			\
56 	TYPE *pi = (TYPE *) (parmi);			\
57 	TYPE *pj = (TYPE *) (parmj);			\
58 	do {						\
59 		TYPE	t = *pi;			\
60 		*pi++ = *pj;				\
61 		*pj++ = t;				\
62         } while (--i > 0);				\
63 }
64 
65 #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
66 	es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
67 
68 static void
swapfunc(a,b,n,swaptype)69 swapfunc(a, b, n, swaptype)
70 	char *a, *b;
71 	int n, swaptype;
72 {
73 	if(swaptype <= 1)
74 		swapcode(long, a, b, n)
75 	else
76 		swapcode(char, a, b, n)
77 }
78 
79 #define swap(a, b)					\
80 	if (swaptype == 0) {				\
81 		long t = *(long *)(a);			\
82 		*(long *)(a) = *(long *)(b);		\
83 		*(long *)(b) = t;			\
84 	} else						\
85 		swapfunc(a, b, es, swaptype)
86 
87 #define vecswap(a, b, n) 	if ((n) > 0) swapfunc(a, b, n, swaptype)
88 
89 static char *
med3(a,b,c,cmp)90 med3(a, b, c, cmp)
91 	char *a, *b, *c;
92 	cmp_t *cmp;
93 {
94 	return cmp(a, b) < 0 ?
95 	       (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
96               :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
97 }
98 
99 void
qsort(a,n,es,cmp)100 qsort(a, n, es, cmp)
101 	void *a;
102 	size_t n, es;
103 	cmp_t *cmp;
104 {
105 	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
106 	int d, r, swaptype, swap_cnt;
107 
108 loop:	SWAPINIT(a, es);
109 	swap_cnt = 0;
110 	if (n < 7) {
111 		for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
112 			for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0;
113 			     pl -= es)
114 				swap(pl, pl - es);
115 		return;
116 	}
117 	pm = (char *)a + (n / 2) * es;
118 	if (n > 7) {
119 		pl = a;
120 		pn = (char *)a + (n - 1) * es;
121 		if (n > 40) {
122 			d = (n / 8) * es;
123 			pl = med3(pl, pl + d, pl + 2 * d, cmp);
124 			pm = med3(pm - d, pm, pm + d, cmp);
125 			pn = med3(pn - 2 * d, pn - d, pn, cmp);
126 		}
127 		pm = med3(pl, pm, pn, cmp);
128 	}
129 	swap(a, pm);
130 	pa = pb = (char *)a + es;
131 
132 	pc = pd = (char *)a + (n - 1) * es;
133 	for (;;) {
134 		while (pb <= pc && (r = cmp(pb, a)) <= 0) {
135 			if (r == 0) {
136 				swap_cnt = 1;
137 				swap(pa, pb);
138 				pa += es;
139 			}
140 			pb += es;
141 		}
142 		while (pb <= pc && (r = cmp(pc, a)) >= 0) {
143 			if (r == 0) {
144 				swap_cnt = 1;
145 				swap(pc, pd);
146 				pd -= es;
147 			}
148 			pc -= es;
149 		}
150 		if (pb > pc)
151 			break;
152 		swap(pb, pc);
153 		swap_cnt = 1;
154 		pb += es;
155 		pc -= es;
156 	}
157 	if (swap_cnt == 0) {  /* Switch to insertion sort */
158 		for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
159 			for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0;
160 			     pl -= es)
161 				swap(pl, pl - es);
162 		return;
163 	}
164 
165 	pn = (char *)a + n * es;
166 	r = MIN(pa - (char *)a, pb - pa);
167 	vecswap(a, pb - r, r);
168 	r = MIN(pd - pc, pn - pd - es);
169 	vecswap(pb, pn - r, r);
170 	if ((r = pb - pa) > es)
171 		qsort(a, r / es, es, cmp);
172 	if ((r = pd - pc) > es) {
173 		/* Iterate rather than recurse to save stack space */
174 		a = pn - r;
175 		n = r / es;
176 		goto loop;
177 	}
178 /*		qsort(pn - r, r / es, es, cmp);*/
179 }
180 
181 //==================================================================================
182 
strlen(const char * string)183 size_t strlen( const char *string ) {
184 	const char	*s;
185 
186 	s = string;
187 	while ( *s ) {
188 		s++;
189 	}
190 	return s - string;
191 }
192 
193 
strcat(char * strDestination,const char * strSource)194 char *strcat( char *strDestination, const char *strSource ) {
195 	char	*s;
196 
197 	s = strDestination;
198 	while ( *s ) {
199 		s++;
200 	}
201 	while ( *strSource ) {
202 		*s++ = *strSource++;
203 	}
204 	*s = 0;
205 	return strDestination;
206 }
207 
strncat(char * strDestination,const char * strSource,size_t num)208 char *strncat( char *strDestination, const char *strSource, size_t num ) {
209 	char	*s;
210 	int		i;
211 
212 	s = strDestination;
213 	while ( *s ) {
214 		s++;
215 	}
216 	for ( i = 0; *strSource && i < num; i++ ) {
217 		*s++ = *strSource++;
218 	}
219 	*s = 0;
220 	return strDestination;
221 }
222 
strcpy(char * strDestination,const char * strSource)223 char *strcpy( char *strDestination, const char *strSource ) {
224 	char *s;
225 
226 	s = strDestination;
227 	while ( *strSource ) {
228 		*s++ = *strSource++;
229 	}
230 	*s = 0;
231 	return strDestination;
232 }
233 
234 
strcmp(const char * string1,const char * string2)235 int strcmp( const char *string1, const char *string2 ) {
236 	while ( *string1 == *string2 && *string1 && *string2 ) {
237 		string1++;
238 		string2++;
239 	}
240 	return *string1 - *string2;
241 }
242 
243 
strchr(const char * string,int c)244 char *strchr( const char *string, int c ) {
245 	while ( *string ) {
246 		if ( *string == c ) {
247 			return ( char * )string;
248 		}
249 		string++;
250 	}
251 
252 	if(c)
253 		return NULL;
254 	else
255 		return (char *) string;
256 }
257 
strrchr(const char * string,int c)258 char *strrchr(const char *string, int c)
259 {
260 	const char *found = NULL;
261 
262 	while(*string)
263 	{
264 		if(*string == c)
265 			found = string;
266 
267 		string++;
268 	}
269 
270 	if(c)
271 		return (char *) found;
272 	else
273 		return (char *) string;
274 }
275 
strstr(const char * string,const char * strCharSet)276 char *strstr( const char *string, const char *strCharSet ) {
277 	while ( *string ) {
278 		int		i;
279 
280 		for ( i = 0 ; strCharSet[i] ; i++ ) {
281 			if ( string[i] != strCharSet[i] ) {
282 				break;
283 			}
284 		}
285 		if ( !strCharSet[i] ) {
286 			return (char *)string;
287 		}
288 		string++;
289 	}
290 	return (char *)0;
291 }
292 
tolower(int c)293 int tolower( int c ) {
294 	if ( c >= 'A' && c <= 'Z' ) {
295 		c += 'a' - 'A';
296 	}
297 	return c;
298 }
299 
300 
toupper(int c)301 int toupper( int c ) {
302 	if ( c >= 'a' && c <= 'z' ) {
303 		c += 'A' - 'a';
304 	}
305 	return c;
306 }
307 
memmove(void * dest,const void * src,size_t count)308 void *memmove(void *dest, const void *src, size_t count)
309 {
310 	size_t		i;
311 
312 	if(count)
313 	{
314 		if(dest > src)
315 		{
316 			i = count;
317 
318 			do
319 			{
320 				i--;
321 				((char *) dest)[i] = ((char *) src)[i];
322 			} while(i > 0);
323 		}
324 		else
325 		{
326 			for(i = 0; i < count; i++)
327 				((char *) dest)[i] = ((char *) src)[i];
328 		}
329 	}
330 
331 	return dest;
332 }
333 
334 
335 #if 0
336 
337 double floor( double x ) {
338 	return (int)(x + 0x40000000) - 0x40000000;
339 }
340 
341 void *memset( void *dest, int c, size_t count ) {
342 	while ( count-- ) {
343 		((char *)dest)[count] = c;
344 	}
345 	return dest;
346 }
347 
348 void *memcpy( void *dest, const void *src, size_t count ) {
349 	while ( count-- ) {
350 		((char *)dest)[count] = ((char *)src)[count];
351 	}
352 	return dest;
353 }
354 
355 char *strncpy( char *strDest, const char *strSource, size_t count ) {
356 	char	*s;
357 
358 	s = strDest;
359 	while ( *strSource && count ) {
360 		*s++ = *strSource++;
361 		count--;
362 	}
363 	while ( count-- ) {
364 		*s++ = 0;
365 	}
366 	return strDest;
367 }
368 
369 double sqrt( double x ) {
370 	float	y;
371 	float	delta;
372 	float	maxError;
373 
374 	if ( x <= 0 ) {
375 		return 0;
376 	}
377 
378 	// initial guess
379 	y = x / 2;
380 
381 	// refine
382 	maxError = x * 0.001;
383 
384 	do {
385 		delta = ( y * y ) - x;
386 		y -= delta / ( 2 * y );
387 	} while ( delta > maxError || delta < -maxError );
388 
389 	return y;
390 }
391 
392 
393 float sintable[1024] = {
394 0.000000,0.001534,0.003068,0.004602,0.006136,0.007670,0.009204,0.010738,
395 0.012272,0.013805,0.015339,0.016873,0.018407,0.019940,0.021474,0.023008,
396 0.024541,0.026075,0.027608,0.029142,0.030675,0.032208,0.033741,0.035274,
397 0.036807,0.038340,0.039873,0.041406,0.042938,0.044471,0.046003,0.047535,
398 0.049068,0.050600,0.052132,0.053664,0.055195,0.056727,0.058258,0.059790,
399 0.061321,0.062852,0.064383,0.065913,0.067444,0.068974,0.070505,0.072035,
400 0.073565,0.075094,0.076624,0.078153,0.079682,0.081211,0.082740,0.084269,
401 0.085797,0.087326,0.088854,0.090381,0.091909,0.093436,0.094963,0.096490,
402 0.098017,0.099544,0.101070,0.102596,0.104122,0.105647,0.107172,0.108697,
403 0.110222,0.111747,0.113271,0.114795,0.116319,0.117842,0.119365,0.120888,
404 0.122411,0.123933,0.125455,0.126977,0.128498,0.130019,0.131540,0.133061,
405 0.134581,0.136101,0.137620,0.139139,0.140658,0.142177,0.143695,0.145213,
406 0.146730,0.148248,0.149765,0.151281,0.152797,0.154313,0.155828,0.157343,
407 0.158858,0.160372,0.161886,0.163400,0.164913,0.166426,0.167938,0.169450,
408 0.170962,0.172473,0.173984,0.175494,0.177004,0.178514,0.180023,0.181532,
409 0.183040,0.184548,0.186055,0.187562,0.189069,0.190575,0.192080,0.193586,
410 0.195090,0.196595,0.198098,0.199602,0.201105,0.202607,0.204109,0.205610,
411 0.207111,0.208612,0.210112,0.211611,0.213110,0.214609,0.216107,0.217604,
412 0.219101,0.220598,0.222094,0.223589,0.225084,0.226578,0.228072,0.229565,
413 0.231058,0.232550,0.234042,0.235533,0.237024,0.238514,0.240003,0.241492,
414 0.242980,0.244468,0.245955,0.247442,0.248928,0.250413,0.251898,0.253382,
415 0.254866,0.256349,0.257831,0.259313,0.260794,0.262275,0.263755,0.265234,
416 0.266713,0.268191,0.269668,0.271145,0.272621,0.274097,0.275572,0.277046,
417 0.278520,0.279993,0.281465,0.282937,0.284408,0.285878,0.287347,0.288816,
418 0.290285,0.291752,0.293219,0.294685,0.296151,0.297616,0.299080,0.300543,
419 0.302006,0.303468,0.304929,0.306390,0.307850,0.309309,0.310767,0.312225,
420 0.313682,0.315138,0.316593,0.318048,0.319502,0.320955,0.322408,0.323859,
421 0.325310,0.326760,0.328210,0.329658,0.331106,0.332553,0.334000,0.335445,
422 0.336890,0.338334,0.339777,0.341219,0.342661,0.344101,0.345541,0.346980,
423 0.348419,0.349856,0.351293,0.352729,0.354164,0.355598,0.357031,0.358463,
424 0.359895,0.361326,0.362756,0.364185,0.365613,0.367040,0.368467,0.369892,
425 0.371317,0.372741,0.374164,0.375586,0.377007,0.378428,0.379847,0.381266,
426 0.382683,0.384100,0.385516,0.386931,0.388345,0.389758,0.391170,0.392582,
427 0.393992,0.395401,0.396810,0.398218,0.399624,0.401030,0.402435,0.403838,
428 0.405241,0.406643,0.408044,0.409444,0.410843,0.412241,0.413638,0.415034,
429 0.416430,0.417824,0.419217,0.420609,0.422000,0.423390,0.424780,0.426168,
430 0.427555,0.428941,0.430326,0.431711,0.433094,0.434476,0.435857,0.437237,
431 0.438616,0.439994,0.441371,0.442747,0.444122,0.445496,0.446869,0.448241,
432 0.449611,0.450981,0.452350,0.453717,0.455084,0.456449,0.457813,0.459177,
433 0.460539,0.461900,0.463260,0.464619,0.465976,0.467333,0.468689,0.470043,
434 0.471397,0.472749,0.474100,0.475450,0.476799,0.478147,0.479494,0.480839,
435 0.482184,0.483527,0.484869,0.486210,0.487550,0.488889,0.490226,0.491563,
436 0.492898,0.494232,0.495565,0.496897,0.498228,0.499557,0.500885,0.502212,
437 0.503538,0.504863,0.506187,0.507509,0.508830,0.510150,0.511469,0.512786,
438 0.514103,0.515418,0.516732,0.518045,0.519356,0.520666,0.521975,0.523283,
439 0.524590,0.525895,0.527199,0.528502,0.529804,0.531104,0.532403,0.533701,
440 0.534998,0.536293,0.537587,0.538880,0.540171,0.541462,0.542751,0.544039,
441 0.545325,0.546610,0.547894,0.549177,0.550458,0.551738,0.553017,0.554294,
442 0.555570,0.556845,0.558119,0.559391,0.560662,0.561931,0.563199,0.564466,
443 0.565732,0.566996,0.568259,0.569521,0.570781,0.572040,0.573297,0.574553,
444 0.575808,0.577062,0.578314,0.579565,0.580814,0.582062,0.583309,0.584554,
445 0.585798,0.587040,0.588282,0.589521,0.590760,0.591997,0.593232,0.594466,
446 0.595699,0.596931,0.598161,0.599389,0.600616,0.601842,0.603067,0.604290,
447 0.605511,0.606731,0.607950,0.609167,0.610383,0.611597,0.612810,0.614022,
448 0.615232,0.616440,0.617647,0.618853,0.620057,0.621260,0.622461,0.623661,
449 0.624859,0.626056,0.627252,0.628446,0.629638,0.630829,0.632019,0.633207,
450 0.634393,0.635578,0.636762,0.637944,0.639124,0.640303,0.641481,0.642657,
451 0.643832,0.645005,0.646176,0.647346,0.648514,0.649681,0.650847,0.652011,
452 0.653173,0.654334,0.655493,0.656651,0.657807,0.658961,0.660114,0.661266,
453 0.662416,0.663564,0.664711,0.665856,0.667000,0.668142,0.669283,0.670422,
454 0.671559,0.672695,0.673829,0.674962,0.676093,0.677222,0.678350,0.679476,
455 0.680601,0.681724,0.682846,0.683965,0.685084,0.686200,0.687315,0.688429,
456 0.689541,0.690651,0.691759,0.692866,0.693971,0.695075,0.696177,0.697278,
457 0.698376,0.699473,0.700569,0.701663,0.702755,0.703845,0.704934,0.706021,
458 0.707107,0.708191,0.709273,0.710353,0.711432,0.712509,0.713585,0.714659,
459 0.715731,0.716801,0.717870,0.718937,0.720003,0.721066,0.722128,0.723188,
460 0.724247,0.725304,0.726359,0.727413,0.728464,0.729514,0.730563,0.731609,
461 0.732654,0.733697,0.734739,0.735779,0.736817,0.737853,0.738887,0.739920,
462 0.740951,0.741980,0.743008,0.744034,0.745058,0.746080,0.747101,0.748119,
463 0.749136,0.750152,0.751165,0.752177,0.753187,0.754195,0.755201,0.756206,
464 0.757209,0.758210,0.759209,0.760207,0.761202,0.762196,0.763188,0.764179,
465 0.765167,0.766154,0.767139,0.768122,0.769103,0.770083,0.771061,0.772036,
466 0.773010,0.773983,0.774953,0.775922,0.776888,0.777853,0.778817,0.779778,
467 0.780737,0.781695,0.782651,0.783605,0.784557,0.785507,0.786455,0.787402,
468 0.788346,0.789289,0.790230,0.791169,0.792107,0.793042,0.793975,0.794907,
469 0.795837,0.796765,0.797691,0.798615,0.799537,0.800458,0.801376,0.802293,
470 0.803208,0.804120,0.805031,0.805940,0.806848,0.807753,0.808656,0.809558,
471 0.810457,0.811355,0.812251,0.813144,0.814036,0.814926,0.815814,0.816701,
472 0.817585,0.818467,0.819348,0.820226,0.821103,0.821977,0.822850,0.823721,
473 0.824589,0.825456,0.826321,0.827184,0.828045,0.828904,0.829761,0.830616,
474 0.831470,0.832321,0.833170,0.834018,0.834863,0.835706,0.836548,0.837387,
475 0.838225,0.839060,0.839894,0.840725,0.841555,0.842383,0.843208,0.844032,
476 0.844854,0.845673,0.846491,0.847307,0.848120,0.848932,0.849742,0.850549,
477 0.851355,0.852159,0.852961,0.853760,0.854558,0.855354,0.856147,0.856939,
478 0.857729,0.858516,0.859302,0.860085,0.860867,0.861646,0.862424,0.863199,
479 0.863973,0.864744,0.865514,0.866281,0.867046,0.867809,0.868571,0.869330,
480 0.870087,0.870842,0.871595,0.872346,0.873095,0.873842,0.874587,0.875329,
481 0.876070,0.876809,0.877545,0.878280,0.879012,0.879743,0.880471,0.881197,
482 0.881921,0.882643,0.883363,0.884081,0.884797,0.885511,0.886223,0.886932,
483 0.887640,0.888345,0.889048,0.889750,0.890449,0.891146,0.891841,0.892534,
484 0.893224,0.893913,0.894599,0.895284,0.895966,0.896646,0.897325,0.898001,
485 0.898674,0.899346,0.900016,0.900683,0.901349,0.902012,0.902673,0.903332,
486 0.903989,0.904644,0.905297,0.905947,0.906596,0.907242,0.907886,0.908528,
487 0.909168,0.909806,0.910441,0.911075,0.911706,0.912335,0.912962,0.913587,
488 0.914210,0.914830,0.915449,0.916065,0.916679,0.917291,0.917901,0.918508,
489 0.919114,0.919717,0.920318,0.920917,0.921514,0.922109,0.922701,0.923291,
490 0.923880,0.924465,0.925049,0.925631,0.926210,0.926787,0.927363,0.927935,
491 0.928506,0.929075,0.929641,0.930205,0.930767,0.931327,0.931884,0.932440,
492 0.932993,0.933544,0.934093,0.934639,0.935184,0.935726,0.936266,0.936803,
493 0.937339,0.937872,0.938404,0.938932,0.939459,0.939984,0.940506,0.941026,
494 0.941544,0.942060,0.942573,0.943084,0.943593,0.944100,0.944605,0.945107,
495 0.945607,0.946105,0.946601,0.947094,0.947586,0.948075,0.948561,0.949046,
496 0.949528,0.950008,0.950486,0.950962,0.951435,0.951906,0.952375,0.952842,
497 0.953306,0.953768,0.954228,0.954686,0.955141,0.955594,0.956045,0.956494,
498 0.956940,0.957385,0.957826,0.958266,0.958703,0.959139,0.959572,0.960002,
499 0.960431,0.960857,0.961280,0.961702,0.962121,0.962538,0.962953,0.963366,
500 0.963776,0.964184,0.964590,0.964993,0.965394,0.965793,0.966190,0.966584,
501 0.966976,0.967366,0.967754,0.968139,0.968522,0.968903,0.969281,0.969657,
502 0.970031,0.970403,0.970772,0.971139,0.971504,0.971866,0.972226,0.972584,
503 0.972940,0.973293,0.973644,0.973993,0.974339,0.974684,0.975025,0.975365,
504 0.975702,0.976037,0.976370,0.976700,0.977028,0.977354,0.977677,0.977999,
505 0.978317,0.978634,0.978948,0.979260,0.979570,0.979877,0.980182,0.980485,
506 0.980785,0.981083,0.981379,0.981673,0.981964,0.982253,0.982539,0.982824,
507 0.983105,0.983385,0.983662,0.983937,0.984210,0.984480,0.984749,0.985014,
508 0.985278,0.985539,0.985798,0.986054,0.986308,0.986560,0.986809,0.987057,
509 0.987301,0.987544,0.987784,0.988022,0.988258,0.988491,0.988722,0.988950,
510 0.989177,0.989400,0.989622,0.989841,0.990058,0.990273,0.990485,0.990695,
511 0.990903,0.991108,0.991311,0.991511,0.991710,0.991906,0.992099,0.992291,
512 0.992480,0.992666,0.992850,0.993032,0.993212,0.993389,0.993564,0.993737,
513 0.993907,0.994075,0.994240,0.994404,0.994565,0.994723,0.994879,0.995033,
514 0.995185,0.995334,0.995481,0.995625,0.995767,0.995907,0.996045,0.996180,
515 0.996313,0.996443,0.996571,0.996697,0.996820,0.996941,0.997060,0.997176,
516 0.997290,0.997402,0.997511,0.997618,0.997723,0.997825,0.997925,0.998023,
517 0.998118,0.998211,0.998302,0.998390,0.998476,0.998559,0.998640,0.998719,
518 0.998795,0.998870,0.998941,0.999011,0.999078,0.999142,0.999205,0.999265,
519 0.999322,0.999378,0.999431,0.999481,0.999529,0.999575,0.999619,0.999660,
520 0.999699,0.999735,0.999769,0.999801,0.999831,0.999858,0.999882,0.999905,
521 0.999925,0.999942,0.999958,0.999971,0.999981,0.999989,0.999995,0.999999
522 };
523 
524 double sin( double x ) {
525 	int	index;
526 	int	quad;
527 
528 	index = 1024 * x / (M_PI * 0.5);
529 	quad = ( index >> 10 ) & 3;
530 	index &= 1023;
531 	switch ( quad ) {
532 	case 0:
533 		return sintable[index];
534 	case 1:
535 		return sintable[1023-index];
536 	case 2:
537 		return -sintable[index];
538 	case 3:
539 		return -sintable[1023-index];
540 	}
541 	return 0;
542 }
543 
544 
545 double cos( double x ) {
546 	int	index;
547 	int	quad;
548 
549 	index = 1024 * x / (M_PI * 0.5);
550 	quad = ( index >> 10 ) & 3;
551 	index &= 1023;
552 	switch ( quad ) {
553 	case 3:
554 		return sintable[index];
555 	case 0:
556 		return sintable[1023-index];
557 	case 1:
558 		return -sintable[index];
559 	case 2:
560 		return -sintable[1023-index];
561 	}
562 	return 0;
563 }
564 
565 
566 /*
567 void create_acostable( void ) {
568 	int i;
569 	FILE *fp;
570 	float a;
571 
572 	fp = fopen("c:\\acostable.txt", "w");
573 	fprintf(fp, "float acostable[] = {");
574 	for (i = 0; i < 1024; i++) {
575 		if (!(i & 7))
576 			fprintf(fp, "\n");
577 		a = acos( (float) -1 + i / 512 );
578 		fprintf(fp, "%1.8f,", a);
579 	}
580 	fprintf(fp, "\n}\n");
581 	fclose(fp);
582 }
583 */
584 
585 float acostable[] = {
586 3.14159265,3.07908248,3.05317551,3.03328655,3.01651113,3.00172442,2.98834964,2.97604422,
587 2.96458497,2.95381690,2.94362719,2.93393068,2.92466119,2.91576615,2.90720289,2.89893629,
588 2.89093699,2.88318015,2.87564455,2.86831188,2.86116621,2.85419358,2.84738169,2.84071962,
589 2.83419760,2.82780691,2.82153967,2.81538876,2.80934770,2.80341062,2.79757211,2.79182724,
590 2.78617145,2.78060056,2.77511069,2.76969824,2.76435988,2.75909250,2.75389319,2.74875926,
591 2.74368816,2.73867752,2.73372510,2.72882880,2.72398665,2.71919677,2.71445741,2.70976688,
592 2.70512362,2.70052613,2.69597298,2.69146283,2.68699438,2.68256642,2.67817778,2.67382735,
593 2.66951407,2.66523692,2.66099493,2.65678719,2.65261279,2.64847088,2.64436066,2.64028133,
594 2.63623214,2.63221238,2.62822133,2.62425835,2.62032277,2.61641398,2.61253138,2.60867440,
595 2.60484248,2.60103507,2.59725167,2.59349176,2.58975488,2.58604053,2.58234828,2.57867769,
596 2.57502832,2.57139977,2.56779164,2.56420354,2.56063509,2.55708594,2.55355572,2.55004409,
597 2.54655073,2.54307530,2.53961750,2.53617701,2.53275354,2.52934680,2.52595650,2.52258238,
598 2.51922417,2.51588159,2.51255441,2.50924238,2.50594525,2.50266278,2.49939476,2.49614096,
599 2.49290115,2.48967513,2.48646269,2.48326362,2.48007773,2.47690482,2.47374472,2.47059722,
600 2.46746215,2.46433933,2.46122860,2.45812977,2.45504269,2.45196720,2.44890314,2.44585034,
601 2.44280867,2.43977797,2.43675809,2.43374890,2.43075025,2.42776201,2.42478404,2.42181622,
602 2.41885841,2.41591048,2.41297232,2.41004380,2.40712480,2.40421521,2.40131491,2.39842379,
603 2.39554173,2.39266863,2.38980439,2.38694889,2.38410204,2.38126374,2.37843388,2.37561237,
604 2.37279910,2.36999400,2.36719697,2.36440790,2.36162673,2.35885335,2.35608768,2.35332964,
605 2.35057914,2.34783610,2.34510044,2.34237208,2.33965094,2.33693695,2.33423003,2.33153010,
606 2.32883709,2.32615093,2.32347155,2.32079888,2.31813284,2.31547337,2.31282041,2.31017388,
607 2.30753373,2.30489988,2.30227228,2.29965086,2.29703556,2.29442632,2.29182309,2.28922580,
608 2.28663439,2.28404881,2.28146900,2.27889490,2.27632647,2.27376364,2.27120637,2.26865460,
609 2.26610827,2.26356735,2.26103177,2.25850149,2.25597646,2.25345663,2.25094195,2.24843238,
610 2.24592786,2.24342836,2.24093382,2.23844420,2.23595946,2.23347956,2.23100444,2.22853408,
611 2.22606842,2.22360742,2.22115104,2.21869925,2.21625199,2.21380924,2.21137096,2.20893709,
612 2.20650761,2.20408248,2.20166166,2.19924511,2.19683280,2.19442469,2.19202074,2.18962092,
613 2.18722520,2.18483354,2.18244590,2.18006225,2.17768257,2.17530680,2.17293493,2.17056692,
614 2.16820274,2.16584236,2.16348574,2.16113285,2.15878367,2.15643816,2.15409630,2.15175805,
615 2.14942338,2.14709226,2.14476468,2.14244059,2.14011997,2.13780279,2.13548903,2.13317865,
616 2.13087163,2.12856795,2.12626757,2.12397047,2.12167662,2.11938600,2.11709859,2.11481435,
617 2.11253326,2.11025530,2.10798044,2.10570867,2.10343994,2.10117424,2.09891156,2.09665185,
618 2.09439510,2.09214129,2.08989040,2.08764239,2.08539725,2.08315496,2.08091550,2.07867884,
619 2.07644495,2.07421383,2.07198545,2.06975978,2.06753681,2.06531651,2.06309887,2.06088387,
620 2.05867147,2.05646168,2.05425445,2.05204979,2.04984765,2.04764804,2.04545092,2.04325628,
621 2.04106409,2.03887435,2.03668703,2.03450211,2.03231957,2.03013941,2.02796159,2.02578610,
622 2.02361292,2.02144204,2.01927344,2.01710710,2.01494300,2.01278113,2.01062146,2.00846399,
623 2.00630870,2.00415556,2.00200457,1.99985570,1.99770895,1.99556429,1.99342171,1.99128119,
624 1.98914271,1.98700627,1.98487185,1.98273942,1.98060898,1.97848051,1.97635399,1.97422942,
625 1.97210676,1.96998602,1.96786718,1.96575021,1.96363511,1.96152187,1.95941046,1.95730088,
626 1.95519310,1.95308712,1.95098292,1.94888050,1.94677982,1.94468089,1.94258368,1.94048818,
627 1.93839439,1.93630228,1.93421185,1.93212308,1.93003595,1.92795046,1.92586659,1.92378433,
628 1.92170367,1.91962459,1.91754708,1.91547113,1.91339673,1.91132385,1.90925250,1.90718266,
629 1.90511432,1.90304746,1.90098208,1.89891815,1.89685568,1.89479464,1.89273503,1.89067683,
630 1.88862003,1.88656463,1.88451060,1.88245794,1.88040664,1.87835668,1.87630806,1.87426076,
631 1.87221477,1.87017008,1.86812668,1.86608457,1.86404371,1.86200412,1.85996577,1.85792866,
632 1.85589277,1.85385809,1.85182462,1.84979234,1.84776125,1.84573132,1.84370256,1.84167495,
633 1.83964848,1.83762314,1.83559892,1.83357582,1.83155381,1.82953289,1.82751305,1.82549429,
634 1.82347658,1.82145993,1.81944431,1.81742973,1.81541617,1.81340362,1.81139207,1.80938151,
635 1.80737194,1.80536334,1.80335570,1.80134902,1.79934328,1.79733848,1.79533460,1.79333164,
636 1.79132959,1.78932843,1.78732817,1.78532878,1.78333027,1.78133261,1.77933581,1.77733985,
637 1.77534473,1.77335043,1.77135695,1.76936428,1.76737240,1.76538132,1.76339101,1.76140148,
638 1.75941271,1.75742470,1.75543743,1.75345090,1.75146510,1.74948002,1.74749565,1.74551198,
639 1.74352900,1.74154672,1.73956511,1.73758417,1.73560389,1.73362426,1.73164527,1.72966692,
640 1.72768920,1.72571209,1.72373560,1.72175971,1.71978441,1.71780969,1.71583556,1.71386199,
641 1.71188899,1.70991653,1.70794462,1.70597325,1.70400241,1.70203209,1.70006228,1.69809297,
642 1.69612416,1.69415584,1.69218799,1.69022062,1.68825372,1.68628727,1.68432127,1.68235571,
643 1.68039058,1.67842588,1.67646160,1.67449772,1.67253424,1.67057116,1.66860847,1.66664615,
644 1.66468420,1.66272262,1.66076139,1.65880050,1.65683996,1.65487975,1.65291986,1.65096028,
645 1.64900102,1.64704205,1.64508338,1.64312500,1.64116689,1.63920905,1.63725148,1.63529416,
646 1.63333709,1.63138026,1.62942366,1.62746728,1.62551112,1.62355517,1.62159943,1.61964388,
647 1.61768851,1.61573332,1.61377831,1.61182346,1.60986877,1.60791422,1.60595982,1.60400556,
648 1.60205142,1.60009739,1.59814349,1.59618968,1.59423597,1.59228235,1.59032882,1.58837536,
649 1.58642196,1.58446863,1.58251535,1.58056211,1.57860891,1.57665574,1.57470259,1.57274945,
650 1.57079633,1.56884320,1.56689007,1.56493692,1.56298375,1.56103055,1.55907731,1.55712403,
651 1.55517069,1.55321730,1.55126383,1.54931030,1.54735668,1.54540297,1.54344917,1.54149526,
652 1.53954124,1.53758710,1.53563283,1.53367843,1.53172389,1.52976919,1.52781434,1.52585933,
653 1.52390414,1.52194878,1.51999323,1.51803748,1.51608153,1.51412537,1.51216900,1.51021240,
654 1.50825556,1.50629849,1.50434117,1.50238360,1.50042576,1.49846765,1.49650927,1.49455060,
655 1.49259163,1.49063237,1.48867280,1.48671291,1.48475270,1.48279215,1.48083127,1.47887004,
656 1.47690845,1.47494650,1.47298419,1.47102149,1.46905841,1.46709493,1.46513106,1.46316677,
657 1.46120207,1.45923694,1.45727138,1.45530538,1.45333893,1.45137203,1.44940466,1.44743682,
658 1.44546850,1.44349969,1.44153038,1.43956057,1.43759024,1.43561940,1.43364803,1.43167612,
659 1.42970367,1.42773066,1.42575709,1.42378296,1.42180825,1.41983295,1.41785705,1.41588056,
660 1.41390346,1.41192573,1.40994738,1.40796840,1.40598877,1.40400849,1.40202755,1.40004594,
661 1.39806365,1.39608068,1.39409701,1.39211264,1.39012756,1.38814175,1.38615522,1.38416795,
662 1.38217994,1.38019117,1.37820164,1.37621134,1.37422025,1.37222837,1.37023570,1.36824222,
663 1.36624792,1.36425280,1.36225684,1.36026004,1.35826239,1.35626387,1.35426449,1.35226422,
664 1.35026307,1.34826101,1.34625805,1.34425418,1.34224937,1.34024364,1.33823695,1.33622932,
665 1.33422072,1.33221114,1.33020059,1.32818904,1.32617649,1.32416292,1.32214834,1.32013273,
666 1.31811607,1.31609837,1.31407960,1.31205976,1.31003885,1.30801684,1.30599373,1.30396951,
667 1.30194417,1.29991770,1.29789009,1.29586133,1.29383141,1.29180031,1.28976803,1.28773456,
668 1.28569989,1.28366400,1.28162688,1.27958854,1.27754894,1.27550809,1.27346597,1.27142257,
669 1.26937788,1.26733189,1.26528459,1.26323597,1.26118602,1.25913471,1.25708205,1.25502803,
670 1.25297262,1.25091583,1.24885763,1.24679802,1.24473698,1.24267450,1.24061058,1.23854519,
671 1.23647833,1.23440999,1.23234015,1.23026880,1.22819593,1.22612152,1.22404557,1.22196806,
672 1.21988898,1.21780832,1.21572606,1.21364219,1.21155670,1.20946958,1.20738080,1.20529037,
673 1.20319826,1.20110447,1.19900898,1.19691177,1.19481283,1.19271216,1.19060973,1.18850553,
674 1.18639955,1.18429178,1.18218219,1.18007079,1.17795754,1.17584244,1.17372548,1.17160663,
675 1.16948589,1.16736324,1.16523866,1.16311215,1.16098368,1.15885323,1.15672081,1.15458638,
676 1.15244994,1.15031147,1.14817095,1.14602836,1.14388370,1.14173695,1.13958808,1.13743709,
677 1.13528396,1.13312866,1.13097119,1.12881153,1.12664966,1.12448556,1.12231921,1.12015061,
678 1.11797973,1.11580656,1.11363107,1.11145325,1.10927308,1.10709055,1.10490563,1.10271831,
679 1.10052856,1.09833638,1.09614174,1.09394462,1.09174500,1.08954287,1.08733820,1.08513098,
680 1.08292118,1.08070879,1.07849378,1.07627614,1.07405585,1.07183287,1.06960721,1.06737882,
681 1.06514770,1.06291382,1.06067715,1.05843769,1.05619540,1.05395026,1.05170226,1.04945136,
682 1.04719755,1.04494080,1.04268110,1.04041841,1.03815271,1.03588399,1.03361221,1.03133735,
683 1.02905939,1.02677830,1.02449407,1.02220665,1.01991603,1.01762219,1.01532509,1.01302471,
684 1.01072102,1.00841400,1.00610363,1.00378986,1.00147268,0.99915206,0.99682798,0.99450039,
685 0.99216928,0.98983461,0.98749636,0.98515449,0.98280898,0.98045980,0.97810691,0.97575030,
686 0.97338991,0.97102573,0.96865772,0.96628585,0.96391009,0.96153040,0.95914675,0.95675912,
687 0.95436745,0.95197173,0.94957191,0.94716796,0.94475985,0.94234754,0.93993099,0.93751017,
688 0.93508504,0.93265556,0.93022170,0.92778341,0.92534066,0.92289341,0.92044161,0.91798524,
689 0.91552424,0.91305858,0.91058821,0.90811309,0.90563319,0.90314845,0.90065884,0.89816430,
690 0.89566479,0.89316028,0.89065070,0.88813602,0.88561619,0.88309116,0.88056088,0.87802531,
691 0.87548438,0.87293806,0.87038629,0.86782901,0.86526619,0.86269775,0.86012366,0.85754385,
692 0.85495827,0.85236686,0.84976956,0.84716633,0.84455709,0.84194179,0.83932037,0.83669277,
693 0.83405893,0.83141877,0.82877225,0.82611928,0.82345981,0.82079378,0.81812110,0.81544172,
694 0.81275556,0.81006255,0.80736262,0.80465570,0.80194171,0.79922057,0.79649221,0.79375655,
695 0.79101352,0.78826302,0.78550497,0.78273931,0.77996593,0.77718475,0.77439569,0.77159865,
696 0.76879355,0.76598029,0.76315878,0.76032891,0.75749061,0.75464376,0.75178826,0.74892402,
697 0.74605092,0.74316887,0.74027775,0.73737744,0.73446785,0.73154885,0.72862033,0.72568217,
698 0.72273425,0.71977644,0.71680861,0.71383064,0.71084240,0.70784376,0.70483456,0.70181469,
699 0.69878398,0.69574231,0.69268952,0.68962545,0.68654996,0.68346288,0.68036406,0.67725332,
700 0.67413051,0.67099544,0.66784794,0.66468783,0.66151492,0.65832903,0.65512997,0.65191753,
701 0.64869151,0.64545170,0.64219789,0.63892987,0.63564741,0.63235028,0.62903824,0.62571106,
702 0.62236849,0.61901027,0.61563615,0.61224585,0.60883911,0.60541564,0.60197515,0.59851735,
703 0.59504192,0.59154856,0.58803694,0.58450672,0.58095756,0.57738911,0.57380101,0.57019288,
704 0.56656433,0.56291496,0.55924437,0.55555212,0.55183778,0.54810089,0.54434099,0.54055758,
705 0.53675018,0.53291825,0.52906127,0.52517867,0.52126988,0.51733431,0.51337132,0.50938028,
706 0.50536051,0.50131132,0.49723200,0.49312177,0.48897987,0.48480547,0.48059772,0.47635573,
707 0.47207859,0.46776530,0.46341487,0.45902623,0.45459827,0.45012983,0.44561967,0.44106652,
708 0.43646903,0.43182577,0.42713525,0.42239588,0.41760600,0.41276385,0.40786755,0.40291513,
709 0.39790449,0.39283339,0.38769946,0.38250016,0.37723277,0.37189441,0.36648196,0.36099209,
710 0.35542120,0.34976542,0.34402054,0.33818204,0.33224495,0.32620390,0.32005298,0.31378574,
711 0.30739505,0.30087304,0.29421096,0.28739907,0.28042645,0.27328078,0.26594810,0.25841250,
712 0.25065566,0.24265636,0.23438976,0.22582651,0.21693146,0.20766198,0.19796546,0.18777575,
713 0.17700769,0.16554844,0.15324301,0.13986823,0.12508152,0.10830610,0.08841715,0.06251018,
714 }
715 
716 double acos( double x ) {
717 	int index;
718 
719 	if (x < -1)
720 		x = -1;
721 	if (x > 1)
722 		x = 1;
723 	index = (float) (1.0 + x) * 511.9;
724 	return acostable[index];
725 }
726 
727 double atan2( double y, double x ) {
728 	float	base;
729 	float	temp;
730 	float	dir;
731 	float	test;
732 	int		i;
733 
734 	if ( x < 0 ) {
735 		if ( y >= 0 ) {
736 			// quad 1
737 			base = M_PI / 2;
738 			temp = x;
739 			x = y;
740 			y = -temp;
741 		} else {
742 			// quad 2
743 			base = M_PI;
744 			x = -x;
745 			y = -y;
746 		}
747 	} else {
748 		if ( y < 0 ) {
749 			// quad 3
750 			base = 3 * M_PI / 2;
751 			temp = x;
752 			x = -y;
753 			y = temp;
754 		}
755 	}
756 
757 	if ( y > x ) {
758 		base += M_PI/2;
759 		temp = x;
760 		x = y;
761 		y = temp;
762 		dir = -1;
763 	} else {
764 		dir = 1;
765 	}
766 
767 	// calcualte angle in octant 0
768 	if ( x == 0 ) {
769 		return base;
770 	}
771 	y /= x;
772 
773 	for ( i = 0 ; i < 512 ; i++ ) {
774 		test = sintable[i] / sintable[1023-i];
775 		if ( test > y ) {
776 			break;
777 		}
778 	}
779 
780 	return base + dir * i * ( M_PI/2048);
781 }
782 
783 
784 #endif
785 
786 /*
787 ===============
788 powN
789 
790 Raise a double to a integer power
791 ===============
792 */
powN(double base,int exp)793 double powN( double base, int exp )
794 {
795 	if( exp >= 0 )
796 	{
797 		double result = 1.0;
798 
799 		// calculate x, x^2, x^4, ... by repeated squaring
800 		// and multiply together the ones corresponding to the
801 		// binary digits of the exponent
802 		// e.g. x^73 = x^(1 + 8 + 64) = x * x^8 * x^64
803 		while( exp > 0 )
804 		{
805 			if( exp % 2 == 1 )
806 				result *= base;
807 
808 			base *= base;
809 			exp /= 2;
810 		}
811 
812 		return result;
813 	}
814 	// if exp is INT_MIN, the next clause will be upset,
815 	// because -exp isn't representable
816 	else if( exp == INT_MIN )
817 		return powN( base, exp + 1 ) / base;
818 	// x < 0
819 	else
820 		return 1.0 / powN( base, -exp );
821 }
822 
tan(double x)823 double tan( double x ) {
824 	return sin(x) / cos(x);
825 }
826 
827 
828 static int randSeed = 0;
829 
srand(unsigned seed)830 void	srand( unsigned seed ) {
831 	randSeed = seed;
832 }
833 
rand(void)834 int		rand( void ) {
835 	randSeed = (69069 * randSeed + 1);
836 	return randSeed & 0x7fff;
837 }
838 
atof(const char * string)839 double atof( const char *string ) {
840 	float sign;
841 	float value;
842 	int		c;
843 
844 
845 	// skip whitespace
846 	while ( *string <= ' ' ) {
847 		if ( !*string ) {
848 			return 0;
849 		}
850 		string++;
851 	}
852 
853 	// check sign
854 	switch ( *string ) {
855 	case '+':
856 		string++;
857 		sign = 1;
858 		break;
859 	case '-':
860 		string++;
861 		sign = -1;
862 		break;
863 	default:
864 		sign = 1;
865 		break;
866 	}
867 
868 	// read digits
869 	value = 0;
870 	c = string[0];
871 	if ( c != '.' ) {
872 		do {
873 			c = *string++;
874 			if ( c < '0' || c > '9' ) {
875 				break;
876 			}
877 			c -= '0';
878 			value = value * 10 + c;
879 		} while ( 1 );
880 	} else {
881 		string++;
882 	}
883 
884 	// check for decimal point
885 	if ( c == '.' ) {
886 		double fraction;
887 
888 		fraction = 0.1;
889 		do {
890 			c = *string++;
891 			if ( c < '0' || c > '9' ) {
892 				break;
893 			}
894 			c -= '0';
895 			value += c * fraction;
896 			fraction *= 0.1;
897 		} while ( 1 );
898 
899 	}
900 
901 	// not handling 10e10 notation...
902 
903 	return value * sign;
904 }
905 
_atof(const char ** stringPtr)906 double _atof( const char **stringPtr ) {
907 	const char	*string;
908 	float sign;
909 	float value;
910 	int		c = '0';
911 
912 	string = *stringPtr;
913 
914 	// skip whitespace
915 	while ( *string <= ' ' ) {
916 		if ( !*string ) {
917 			*stringPtr = string;
918 			return 0;
919 		}
920 		string++;
921 	}
922 
923 	// check sign
924 	switch ( *string ) {
925 	case '+':
926 		string++;
927 		sign = 1;
928 		break;
929 	case '-':
930 		string++;
931 		sign = -1;
932 		break;
933 	default:
934 		sign = 1;
935 		break;
936 	}
937 
938 	// read digits
939 	value = 0;
940 	if ( string[0] == '.' ) {
941 		// read decimal point if followed by a digit
942 		if ( string[1] >= '0' && string[1] <= '9' ) {
943 			c = *string++;
944 		}
945 	} else {
946 		do {
947 			c = *string++;
948 			if ( c < '0' || c > '9' ) {
949 				break;
950 			}
951 			c -= '0';
952 			value = value * 10 + c;
953 		} while ( 1 );
954 	}
955 
956 	// check for decimal point
957 	if ( c == '.' ) {
958 		double fraction;
959 
960 		fraction = 0.1;
961 		do {
962 			c = *string++;
963 			if ( c < '0' || c > '9' ) {
964 				break;
965 			}
966 			c -= '0';
967 			value += c * fraction;
968 			fraction *= 0.1;
969 		} while ( 1 );
970 
971 	}
972 
973 	// not handling 10e10 notation...
974 	*stringPtr = string;
975 
976 	return value * sign;
977 }
978 
979 /*
980 ==============
981 strtod
982 
983 Without an errno variable, this is a fair bit less useful than it is in libc
984 but it's still a fair bit more capable than atof or _atof
985 Handles inf[inity], nan (ignoring case), hexadecimals, and decimals
986 Handles decimal exponents like 10e10 and hex exponents like 0x7f8p20
987 10e10 == 10000000000 (power of ten)
988 0x7f8p20 == 0x7f800000 (decimal power of two)
989 The variable pointed to by endptr will hold the location of the first character
990 in the nptr string that was not used in the conversion
991 ==============
992 */
strtod(const char * nptr,char ** endptr)993 double strtod( const char *nptr, char **endptr )
994 {
995 	double res;
996 	qboolean neg = qfalse;
997 
998 	// skip whitespace
999 	while( isspace( *nptr ) )
1000 		nptr++;
1001 
1002 	// special string parsing
1003 	if( Q_stricmpn( nptr, "nan", 3 ) == 0 )
1004 	{
1005 		floatint_t nan;
1006 
1007 		if( endptr )
1008 			*endptr = (char *)&nptr[3];
1009 
1010 		// nan can be followed by a bracketed number (in hex, octal,
1011 		// or decimal) which is then put in the mantissa
1012 		// this can be used to generate signalling or quiet NaNs, for
1013 		// example (though I doubt it'll ever be used)
1014 		// note that nan(0) is infinity!
1015 		if( nptr[3] == '(' )
1016 		{
1017 			char *end;
1018 			int mantissa = strtol( &nptr[4], &end, 0 );
1019 			if( *end == ')' )
1020 			{
1021 				nan.ui = 0x7f800000 | ( mantissa & 0x7fffff );
1022 				if( endptr )
1023 					*endptr = &end[1];
1024 				return nan.f;
1025 			}
1026 		}
1027 		nan.ui = 0x7fffffff;
1028 		return nan.f;
1029 	}
1030 	if( Q_stricmpn( nptr, "inf", 3 ) == 0 )
1031 	{
1032 		floatint_t inf;
1033 		inf.ui = 0x7f800000;
1034 		if( endptr == NULL )
1035 			return inf.f;
1036 		if( Q_stricmpn( &nptr[3], "inity", 5 ) == 0 )
1037 			*endptr = (char *)&nptr[8];
1038 		else
1039 			*endptr = (char *)&nptr[3];
1040 		return inf.f;
1041 	}
1042 
1043 	// normal numeric parsing
1044 	// sign
1045 	if( *nptr == '-' )
1046 	{
1047 		nptr++;
1048 		neg = qtrue;
1049 	}
1050 	else if( *nptr == '+' )
1051 		nptr++;
1052 	// hex
1053 	if( Q_stricmpn( nptr, "0x", 2 ) == 0 )
1054 	{
1055 		// track if we use any digits
1056 		const char *s = &nptr[1], *end = s;
1057 		nptr += 2;
1058 		res = 0;
1059 		while( qtrue )
1060 		{
1061 			if( isdigit( *nptr ) )
1062 				res = 16 * res + ( *nptr++ - '0' );
1063 			else if( *nptr >= 'A' && *nptr <= 'F' )
1064 				res = 16 * res + 10 + *nptr++ - 'A';
1065 			else if( *nptr >= 'a' && *nptr <= 'f' )
1066 				res = 16 * res + 10 + *nptr++ - 'a';
1067 			else
1068 				break;
1069 		}
1070 		// if nptr moved, save it
1071 		if( end + 1 < nptr )
1072 			end = nptr;
1073 		if( *nptr == '.' )
1074 		{
1075 			float place;
1076 			nptr++;
1077 			// 1.0 / 16.0 == 0.0625
1078 			// I don't expect the float accuracy to hold out for
1079 			// very long but since we need to know the length of
1080 			// the string anyway we keep on going regardless
1081 			for( place = 0.0625;; place /= 16.0 )
1082 			{
1083 				if( isdigit( *nptr ) )
1084 					res += place * ( *nptr++ - '0' );
1085 				else if( *nptr >= 'A' && *nptr <= 'F' )
1086 					res += place * ( 10 + *nptr++ - 'A' );
1087 				else if( *nptr >= 'a' && *nptr <= 'f' )
1088 					res += place * ( 10 + *nptr++ - 'a' );
1089 				else
1090 					break;
1091 			}
1092 			if( end < nptr )
1093 				end = nptr;
1094 		}
1095 		// parse an optional exponent, representing multiplication
1096 		// by a power of two
1097 		// exponents are only valid if we encountered at least one
1098 		// digit already (and have therefore set end to something)
1099 		if( end != s && tolower( *nptr ) == 'p' )
1100 		{
1101 			int exp;
1102 			// apparently (confusingly) the exponent should be
1103 			// decimal
1104 			exp = strtol( &nptr[1], (char **)&end, 10 );
1105 			if( &nptr[1] == end )
1106 			{
1107 				// no exponent
1108 				if( endptr )
1109 					*endptr = (char *)nptr;
1110 				return res;
1111 			}
1112 
1113 			res *= powN( 2, exp );
1114 		}
1115 		if( endptr )
1116 			*endptr = (char *)end;
1117 		return res;
1118 	}
1119 	// decimal
1120 	else
1121 	{
1122 		// track if we find any digits
1123 		const char *end = nptr, *p = nptr;
1124 		// this is most of the work
1125 		for( res = 0; isdigit( *nptr );
1126 			res = 10 * res + *nptr++ - '0' );
1127 		// if nptr moved, we read something
1128 		if( end < nptr )
1129 			end = nptr;
1130 		if( *nptr == '.' )
1131 		{
1132 			// fractional part
1133 			float place;
1134 			nptr++;
1135 			for( place = 0.1; isdigit( *nptr ); place /= 10.0 )
1136 				res += ( *nptr++ - '0' ) * place;
1137 			// if nptr moved, we read something
1138 			if( end + 1 < nptr )
1139 				end = nptr;
1140 		}
1141 		// exponent
1142 		// meaningless without having already read digits, so check
1143 		// we've set end to something
1144 		if( p != end && tolower( *nptr ) == 'e' )
1145 		{
1146 			int exp;
1147 			exp = strtol( &nptr[1], (char **)&end, 10 );
1148 			if( &nptr[1] == end )
1149 			{
1150 				// no exponent
1151 				if( endptr )
1152 					*endptr = (char *)nptr;
1153 				return res;
1154 			}
1155 
1156 			res *= powN( 10, exp );
1157 		}
1158 		if( endptr )
1159 			*endptr = (char *)end;
1160 		return res;
1161 	}
1162 }
1163 
atoi(const char * string)1164 int atoi( const char *string ) {
1165 	int		sign;
1166 	int		value;
1167 	int		c;
1168 
1169 
1170 	// skip whitespace
1171 	while ( *string <= ' ' ) {
1172 		if ( !*string ) {
1173 			return 0;
1174 		}
1175 		string++;
1176 	}
1177 
1178 	// check sign
1179 	switch ( *string ) {
1180 	case '+':
1181 		string++;
1182 		sign = 1;
1183 		break;
1184 	case '-':
1185 		string++;
1186 		sign = -1;
1187 		break;
1188 	default:
1189 		sign = 1;
1190 		break;
1191 	}
1192 
1193 	// read digits
1194 	value = 0;
1195 	do {
1196 		c = *string++;
1197 		if ( c < '0' || c > '9' ) {
1198 			break;
1199 		}
1200 		c -= '0';
1201 		value = value * 10 + c;
1202 	} while ( 1 );
1203 
1204 	// not handling 10e10 notation...
1205 
1206 	return value * sign;
1207 }
1208 
1209 
_atoi(const char ** stringPtr)1210 int _atoi( const char **stringPtr ) {
1211 	int		sign;
1212 	int		value;
1213 	int		c;
1214 	const char	*string;
1215 
1216 	string = *stringPtr;
1217 
1218 	// skip whitespace
1219 	while ( *string <= ' ' ) {
1220 		if ( !*string ) {
1221 			return 0;
1222 		}
1223 		string++;
1224 	}
1225 
1226 	// check sign
1227 	switch ( *string ) {
1228 	case '+':
1229 		string++;
1230 		sign = 1;
1231 		break;
1232 	case '-':
1233 		string++;
1234 		sign = -1;
1235 		break;
1236 	default:
1237 		sign = 1;
1238 		break;
1239 	}
1240 
1241 	// read digits
1242 	value = 0;
1243 	do {
1244 		c = *string++;
1245 		if ( c < '0' || c > '9' ) {
1246 			break;
1247 		}
1248 		c -= '0';
1249 		value = value * 10 + c;
1250 	} while ( 1 );
1251 
1252 	// not handling 10e10 notation...
1253 
1254 	*stringPtr = string;
1255 
1256 	return value * sign;
1257 }
1258 
1259 /*
1260 ==============
1261 strtol
1262 
1263 Handles any base from 2 to 36. If base is 0 then it guesses
1264 decimal, hex, or octal based on the format of the number (leading 0 or 0x)
1265 Will not overflow - returns LONG_MIN or LONG_MAX as appropriate
1266 *endptr is set to the location of the first character not used
1267 ==============
1268 */
strtol(const char * nptr,char ** endptr,int base)1269 long strtol( const char *nptr, char **endptr, int base )
1270 {
1271 	long res;
1272 	qboolean pos = qtrue;
1273 
1274 	if( endptr )
1275 		*endptr = (char *)nptr;
1276 	// bases other than 0, 2, 8, 16 are very rarely used, but they're
1277 	// not much extra effort to support
1278 	if( base < 0 || base == 1 || base > 36 )
1279 		return 0;
1280 	// skip leading whitespace
1281 	while( isspace( *nptr ) )
1282 		nptr++;
1283 	// sign
1284 	if( *nptr == '-' )
1285 	{
1286 		nptr++;
1287 		pos = qfalse;
1288 	}
1289 	else if( *nptr == '+' )
1290 		nptr++;
1291 	// look for base-identifying sequences e.g. 0x for hex, 0 for octal
1292 	if( nptr[0] == '0' )
1293 	{
1294 		nptr++;
1295 		// 0 is always a valid digit
1296 		if( endptr )
1297 			*endptr = (char *)nptr;
1298 		if( *nptr == 'x' || *nptr == 'X' )
1299 		{
1300 			if( base != 0 && base != 16 )
1301 			{
1302 				// can't be hex, reject x (accept 0)
1303 				if( endptr )
1304 					*endptr = (char *)nptr;
1305 				return 0;
1306 			}
1307 			nptr++;
1308 			base = 16;
1309 		}
1310 		else if( base == 0 )
1311 			base = 8;
1312 	}
1313 	else if( base == 0 )
1314 		base = 10;
1315 	res = 0;
1316 	while( qtrue )
1317 	{
1318 		int val;
1319 		if( isdigit( *nptr ) )
1320 			val = *nptr - '0';
1321 		else if( islower( *nptr ) )
1322 			val = 10 + *nptr - 'a';
1323 		else if( isupper( *nptr ) )
1324 			val = 10 + *nptr - 'A';
1325 		else
1326 			break;
1327 		if( val >= base )
1328 			break;
1329 		// we go negative because LONG_MIN is further from 0 than
1330 		// LONG_MAX
1331 		if( res < ( LONG_MIN + val ) / base )
1332 			res = LONG_MIN; // overflow
1333 		else
1334 			res = res * base - val;
1335 		nptr++;
1336 		if( endptr )
1337 			*endptr = (char *)nptr;
1338 	}
1339 	if( pos )
1340 	{
1341 		// can't represent LONG_MIN positive
1342 		if( res == LONG_MIN )
1343 			res = LONG_MAX;
1344 		else
1345 			res = -res;
1346 	}
1347 	return res;
1348 }
1349 
abs(int n)1350 int abs( int n ) {
1351 	return n < 0 ? -n : n;
1352 }
1353 
fabs(double x)1354 double fabs( double x ) {
1355 	return x < 0 ? -x : x;
1356 }
1357 
1358 
1359 
1360 //=========================================================
1361 
1362 /*
1363  * New implementation by Patrick Powell and others for vsnprintf.
1364  * Supports length checking in strings.
1365 */
1366 
1367 /*
1368  * Copyright Patrick Powell 1995
1369  * This code is based on code written by Patrick Powell (papowell@astart.com)
1370  * It may be used for any purpose as long as this notice remains intact
1371  * on all source code distributions
1372  */
1373 
1374 /**************************************************************
1375  * Original:
1376  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
1377  * A bombproof version of doprnt (dopr) included.
1378  * Sigh.  This sort of thing is always nasty do deal with.  Note that
1379  * the version here does not include floating point...
1380  *
1381  * snprintf() is used instead of sprintf() as it does limit checks
1382  * for string length.  This covers a nasty loophole.
1383  *
1384  * The other functions are there to prevent NULL pointers from
1385  * causing nast effects.
1386  *
1387  * More Recently:
1388  *  Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
1389  *  This was ugly.  It is still ugly.  I opted out of floating point
1390  *  numbers, but the formatter understands just about everything
1391  *  from the normal C string format, at least as far as I can tell from
1392  *  the Solaris 2.5 printf(3S) man page.
1393  *
1394  *  Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
1395  *    Ok, added some minimal floating point support, which means this
1396  *    probably requires libm on most operating systems.  Don't yet
1397  *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint()
1398  *    was pretty badly broken, it just wasn't being exercised in ways
1399  *    which showed it, so that's been fixed.  Also, formated the code
1400  *    to mutt conventions, and removed dead code left over from the
1401  *    original.  Also, there is now a builtin-test, just compile with:
1402  *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
1403  *    and run snprintf for results.
1404  *
1405  *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
1406  *    The PGP code was using unsigned hexadecimal formats.
1407  *    Unfortunately, unsigned formats simply didn't work.
1408  *
1409  *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
1410  *    The original code assumed that both snprintf() and vsnprintf() were
1411  *    missing.  Some systems only have snprintf() but not vsnprintf(), so
1412  *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
1413  *
1414  *  Andrew Tridgell (tridge@samba.org) Oct 1998
1415  *    fixed handling of %.0f
1416  *    added test for HAVE_LONG_DOUBLE
1417  *
1418  *  Russ Allbery <rra@stanford.edu> 2000-08-26
1419  *    fixed return value to comply with C99
1420  *    fixed handling of snprintf(NULL, ...)
1421  *
1422  *  Hrvoje Niksic <hniksic@arsdigita.com> 2000-11-04
1423  *    include <config.h> instead of "config.h".
1424  *    moved TEST_SNPRINTF stuff out of HAVE_SNPRINTF ifdef.
1425  *    include <stdio.h> for NULL.
1426  *    added support and test cases for long long.
1427  *    don't declare argument types to (v)snprintf if stdarg is not used.
1428  *    use int instead of short int as 2nd arg to va_arg.
1429  *
1430  **************************************************************/
1431 
1432 /* BDR 2002-01-13  %e and %g were being ignored.  Now do something,
1433    if not necessarily correctly */
1434 
1435 #if (SIZEOF_LONG_DOUBLE > 0)
1436 /* #ifdef HAVE_LONG_DOUBLE */
1437 #define LDOUBLE long double
1438 #else
1439 #define LDOUBLE double
1440 #endif
1441 
1442 #if (SIZEOF_LONG_LONG > 0)
1443 /* #ifdef HAVE_LONG_LONG */
1444 # define LLONG long long
1445 #else
1446 # define LLONG long
1447 #endif
1448 
1449 static int dopr (char *buffer, size_t maxlen, const char *format,
1450                  va_list args);
1451 static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
1452 		   char *value, int flags, int min, int max);
1453 static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
1454 		   LLONG value, int base, int min, int max, int flags);
1455 static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
1456 		  LDOUBLE fvalue, int min, int max, int flags);
1457 static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
1458 
1459 /*
1460  * dopr(): poor man's version of doprintf
1461  */
1462 
1463 /* format read states */
1464 #define DP_S_DEFAULT 0
1465 #define DP_S_FLAGS   1
1466 #define DP_S_MIN     2
1467 #define DP_S_DOT     3
1468 #define DP_S_MAX     4
1469 #define DP_S_MOD     5
1470 #define DP_S_MOD_L   6
1471 #define DP_S_CONV    7
1472 #define DP_S_DONE    8
1473 
1474 /* format flags - Bits */
1475 #define DP_F_MINUS 	(1 << 0)
1476 #define DP_F_PLUS  	(1 << 1)
1477 #define DP_F_SPACE 	(1 << 2)
1478 #define DP_F_NUM   	(1 << 3)
1479 #define DP_F_ZERO  	(1 << 4)
1480 #define DP_F_UP    	(1 << 5)
1481 #define DP_F_UNSIGNED 	(1 << 6)
1482 
1483 /* Conversion Flags */
1484 #define DP_C_SHORT   1
1485 #define DP_C_LONG    2
1486 #define DP_C_LLONG   3
1487 #define DP_C_LDOUBLE 4
1488 
1489 #define char_to_int(p) (p - '0')
1490 
dopr(char * buffer,size_t maxlen,const char * format,va_list args)1491 static int dopr (char *buffer, size_t maxlen, const char *format, va_list args)
1492 {
1493   char ch;
1494   LLONG value;
1495   LDOUBLE fvalue;
1496   char *strvalue;
1497   int min;
1498   int max;
1499   int state;
1500   int flags;
1501   int cflags;
1502   int total;
1503   size_t currlen;
1504 
1505   state = DP_S_DEFAULT;
1506   currlen = flags = cflags = min = 0;
1507   max = -1;
1508   ch = *format++;
1509   total = 0;
1510 
1511   while (state != DP_S_DONE)
1512   {
1513     if (ch == '\0')
1514       state = DP_S_DONE;
1515 
1516     switch(state)
1517     {
1518     case DP_S_DEFAULT:
1519       if (ch == '%')
1520 	state = DP_S_FLAGS;
1521       else
1522 	total += dopr_outch (buffer, &currlen, maxlen, ch);
1523       ch = *format++;
1524       break;
1525     case DP_S_FLAGS:
1526       switch (ch)
1527       {
1528       case '-':
1529 	flags |= DP_F_MINUS;
1530         ch = *format++;
1531 	break;
1532       case '+':
1533 	flags |= DP_F_PLUS;
1534         ch = *format++;
1535 	break;
1536       case ' ':
1537 	flags |= DP_F_SPACE;
1538         ch = *format++;
1539 	break;
1540       case '#':
1541 	flags |= DP_F_NUM;
1542         ch = *format++;
1543 	break;
1544       case '0':
1545 	flags |= DP_F_ZERO;
1546         ch = *format++;
1547 	break;
1548       default:
1549 	state = DP_S_MIN;
1550 	break;
1551       }
1552       break;
1553     case DP_S_MIN:
1554       if ('0' <= ch && ch <= '9')
1555       {
1556 	min = 10*min + char_to_int (ch);
1557 	ch = *format++;
1558       }
1559       else if (ch == '*')
1560       {
1561 	min = va_arg (args, int);
1562 	ch = *format++;
1563 	state = DP_S_DOT;
1564       }
1565       else
1566 	state = DP_S_DOT;
1567       break;
1568     case DP_S_DOT:
1569       if (ch == '.')
1570       {
1571 	state = DP_S_MAX;
1572 	ch = *format++;
1573       }
1574       else
1575 	state = DP_S_MOD;
1576       break;
1577     case DP_S_MAX:
1578       if ('0' <= ch && ch <= '9')
1579       {
1580 	if (max < 0)
1581 	  max = 0;
1582 	max = 10*max + char_to_int (ch);
1583 	ch = *format++;
1584       }
1585       else if (ch == '*')
1586       {
1587 	max = va_arg (args, int);
1588 	ch = *format++;
1589 	state = DP_S_MOD;
1590       }
1591       else
1592 	state = DP_S_MOD;
1593       break;
1594     case DP_S_MOD:
1595       switch (ch)
1596       {
1597       case 'h':
1598 	cflags = DP_C_SHORT;
1599 	ch = *format++;
1600 	break;
1601       case 'l':
1602 	cflags = DP_C_LONG;
1603 	ch = *format++;
1604 	break;
1605       case 'L':
1606 	cflags = DP_C_LDOUBLE;
1607 	ch = *format++;
1608 	break;
1609       default:
1610 	break;
1611       }
1612       if (cflags != DP_C_LONG)
1613 	state = DP_S_CONV;
1614       else
1615 	state = DP_S_MOD_L;
1616       break;
1617     case DP_S_MOD_L:
1618       switch (ch)
1619 	{
1620 	case 'l':
1621 	  cflags = DP_C_LLONG;
1622 	  ch = *format++;
1623 	  break;
1624 	default:
1625 	  break;
1626 	}
1627       state = DP_S_CONV;
1628       break;
1629     case DP_S_CONV:
1630       switch (ch)
1631       {
1632       case 'd':
1633       case 'i':
1634 	if (cflags == DP_C_SHORT)
1635 	  value = (short int)va_arg (args, int);
1636 	else if (cflags == DP_C_LONG)
1637 	  value = va_arg (args, long int);
1638 	else if (cflags == DP_C_LLONG)
1639 	  value = va_arg (args, LLONG);
1640 	else
1641 	  value = va_arg (args, int);
1642 	total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
1643 	break;
1644       case 'o':
1645 	flags |= DP_F_UNSIGNED;
1646 	if (cflags == DP_C_SHORT)
1647 //	  value = (unsigned short int) va_arg (args, unsigned short int); // Thilo: This does not work because the rcc compiler cannot do that cast correctly.
1648 	  value = va_arg (args, unsigned int) & ( (1 << sizeof(unsigned short int) * 8) - 1); // Using this workaround instead.
1649 	else if (cflags == DP_C_LONG)
1650 	  value = va_arg (args, unsigned long int);
1651 	else if (cflags == DP_C_LLONG)
1652 	  value = va_arg (args, unsigned LLONG);
1653 	else
1654 	  value = va_arg (args, unsigned int);
1655 	total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
1656 	break;
1657       case 'u':
1658 	flags |= DP_F_UNSIGNED;
1659 	if (cflags == DP_C_SHORT)
1660 	  value = va_arg (args, unsigned int) & ( (1 << sizeof(unsigned short int) * 8) - 1);
1661 	else if (cflags == DP_C_LONG)
1662 	  value = va_arg (args, unsigned long int);
1663 	else if (cflags == DP_C_LLONG)
1664 	  value = va_arg (args, unsigned LLONG);
1665 	else
1666 	  value = va_arg (args, unsigned int);
1667 	total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
1668 	break;
1669       case 'X':
1670 	flags |= DP_F_UP;
1671       case 'x':
1672 	flags |= DP_F_UNSIGNED;
1673 	if (cflags == DP_C_SHORT)
1674 	  value = va_arg (args, unsigned int) & ( (1 << sizeof(unsigned short int) * 8) - 1);
1675 	else if (cflags == DP_C_LONG)
1676 	  value = va_arg (args, unsigned long int);
1677 	else if (cflags == DP_C_LLONG)
1678 	  value = va_arg (args, unsigned LLONG);
1679 	else
1680 	  value = va_arg (args, unsigned int);
1681 	total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
1682 	break;
1683       case 'f':
1684 	if (cflags == DP_C_LDOUBLE)
1685 	  fvalue = va_arg (args, LDOUBLE);
1686 	else
1687 	  fvalue = va_arg (args, double);
1688 	/* um, floating point? */
1689 	total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
1690 	break;
1691       case 'E':
1692 	flags |= DP_F_UP;
1693       case 'e':
1694 	if (cflags == DP_C_LDOUBLE)
1695 	  fvalue = va_arg (args, LDOUBLE);
1696 	else
1697 	  fvalue = va_arg (args, double);
1698 	/* um, floating point? */
1699 	total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
1700 	break;
1701       case 'G':
1702 	flags |= DP_F_UP;
1703       case 'g':
1704 	if (cflags == DP_C_LDOUBLE)
1705 	  fvalue = va_arg (args, LDOUBLE);
1706 	else
1707 	  fvalue = va_arg (args, double);
1708 	/* um, floating point? */
1709 	total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
1710 	break;
1711       case 'c':
1712 	total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
1713 	break;
1714       case 's':
1715 	strvalue = va_arg (args, char *);
1716 	total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
1717 	break;
1718       case 'p':
1719 	strvalue = va_arg (args, void *);
1720 	total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min,
1721                          max, flags);
1722 	break;
1723       case 'n':
1724 	if (cflags == DP_C_SHORT)
1725 	{
1726 	  short int *num;
1727 	  num = va_arg (args, short int *);
1728 	  *num = currlen;
1729         }
1730 	else if (cflags == DP_C_LONG)
1731 	{
1732 	  long int *num;
1733 	  num = va_arg (args, long int *);
1734 	  *num = currlen;
1735         }
1736 	else if (cflags == DP_C_LLONG)
1737 	{
1738 	  LLONG *num;
1739 	  num = va_arg (args, LLONG *);
1740 	  *num = currlen;
1741         }
1742 	else
1743 	{
1744 	  int *num;
1745 	  num = va_arg (args, int *);
1746 	  *num = currlen;
1747         }
1748 	break;
1749       case '%':
1750 	total += dopr_outch (buffer, &currlen, maxlen, ch);
1751 	break;
1752       case 'w':
1753 	/* not supported yet, treat as next char */
1754 	ch = *format++;
1755 	break;
1756       default:
1757 	/* Unknown, skip */
1758 	break;
1759       }
1760       ch = *format++;
1761       state = DP_S_DEFAULT;
1762       flags = cflags = min = 0;
1763       max = -1;
1764       break;
1765     case DP_S_DONE:
1766       break;
1767     default:
1768       /* hmm? */
1769       break; /* some picky compilers need this */
1770     }
1771   }
1772   if (maxlen > 0)
1773     buffer[currlen] = '\0';
1774   return total;
1775 }
1776 
fmtstr(char * buffer,size_t * currlen,size_t maxlen,char * value,int flags,int min,int max)1777 static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
1778                    char *value, int flags, int min, int max)
1779 {
1780   int padlen, strln;     /* amount to pad */
1781   int cnt = 0;
1782   int total = 0;
1783 
1784   if (value == 0)
1785   {
1786     value = "<NULL>";
1787   }
1788 
1789   for (strln = 0; value[strln]; ++strln); /* strlen */
1790   if (max >= 0 && max < strln)
1791     strln = max;
1792   padlen = min - strln;
1793   if (padlen < 0)
1794     padlen = 0;
1795   if (flags & DP_F_MINUS)
1796     padlen = -padlen; /* Left Justify */
1797 
1798   while (padlen > 0)
1799   {
1800     total += dopr_outch (buffer, currlen, maxlen, ' ');
1801     --padlen;
1802   }
1803   while (*value && ((max < 0) || (cnt < max)))
1804   {
1805     total += dopr_outch (buffer, currlen, maxlen, *value++);
1806     ++cnt;
1807   }
1808   while (padlen < 0)
1809   {
1810     total += dopr_outch (buffer, currlen, maxlen, ' ');
1811     ++padlen;
1812   }
1813   return total;
1814 }
1815 
1816 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
1817 
fmtint(char * buffer,size_t * currlen,size_t maxlen,LLONG value,int base,int min,int max,int flags)1818 static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
1819 		   LLONG value, int base, int min, int max, int flags)
1820 {
1821   int signvalue = 0;
1822   unsigned LLONG uvalue;
1823   char convert[24];
1824   int place = 0;
1825   int spadlen = 0; /* amount to space pad */
1826   int zpadlen = 0; /* amount to zero pad */
1827   const char *digits;
1828   int total = 0;
1829 
1830   if (max < 0)
1831     max = 0;
1832 
1833   uvalue = value;
1834 
1835   if(!(flags & DP_F_UNSIGNED))
1836   {
1837     if( value < 0 ) {
1838       signvalue = '-';
1839       uvalue = -value;
1840     }
1841     else
1842       if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
1843 	signvalue = '+';
1844     else
1845       if (flags & DP_F_SPACE)
1846 	signvalue = ' ';
1847   }
1848 
1849   if (flags & DP_F_UP)
1850     /* Should characters be upper case? */
1851     digits = "0123456789ABCDEF";
1852   else
1853     digits = "0123456789abcdef";
1854 
1855   do {
1856     convert[place++] = digits[uvalue % (unsigned)base];
1857     uvalue = (uvalue / (unsigned)base );
1858   } while(uvalue && (place < sizeof (convert)));
1859   if (place == sizeof (convert)) place--;
1860   convert[place] = 0;
1861 
1862   zpadlen = max - place;
1863   spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
1864   if (zpadlen < 0) zpadlen = 0;
1865   if (spadlen < 0) spadlen = 0;
1866   if (flags & DP_F_ZERO)
1867   {
1868     zpadlen = MAX(zpadlen, spadlen);
1869     spadlen = 0;
1870   }
1871   if (flags & DP_F_MINUS)
1872     spadlen = -spadlen; /* Left Justifty */
1873 
1874 #ifdef DEBUG_SNPRINTF
1875   dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
1876       zpadlen, spadlen, min, max, place));
1877 #endif
1878 
1879   /* Spaces */
1880   while (spadlen > 0)
1881   {
1882     total += dopr_outch (buffer, currlen, maxlen, ' ');
1883     --spadlen;
1884   }
1885 
1886   /* Sign */
1887   if (signvalue)
1888     total += dopr_outch (buffer, currlen, maxlen, signvalue);
1889 
1890   /* Zeros */
1891   if (zpadlen > 0)
1892   {
1893     while (zpadlen > 0)
1894     {
1895       total += dopr_outch (buffer, currlen, maxlen, '0');
1896       --zpadlen;
1897     }
1898   }
1899 
1900   /* Digits */
1901   while (place > 0)
1902     total += dopr_outch (buffer, currlen, maxlen, convert[--place]);
1903 
1904   /* Left Justified spaces */
1905   while (spadlen < 0) {
1906     total += dopr_outch (buffer, currlen, maxlen, ' ');
1907     ++spadlen;
1908   }
1909 
1910   return total;
1911 }
1912 
abs_val(LDOUBLE value)1913 static LDOUBLE abs_val (LDOUBLE value)
1914 {
1915   LDOUBLE result = value;
1916 
1917   if (value < 0)
1918     result = -value;
1919 
1920   return result;
1921 }
1922 
round(LDOUBLE value)1923 static long round (LDOUBLE value)
1924 {
1925   long intpart;
1926 
1927   intpart = value;
1928   value = value - intpart;
1929   if (value >= 0.5)
1930     intpart++;
1931 
1932   return intpart;
1933 }
1934 
fmtfp(char * buffer,size_t * currlen,size_t maxlen,LDOUBLE fvalue,int min,int max,int flags)1935 static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
1936 		  LDOUBLE fvalue, int min, int max, int flags)
1937 {
1938   int signvalue = 0;
1939   LDOUBLE ufvalue;
1940   char iconvert[20];
1941   char fconvert[20];
1942   int iplace = 0;
1943   int fplace = 0;
1944   int padlen = 0; /* amount to pad */
1945   int zpadlen = 0;
1946   int caps = 0;
1947   int total = 0;
1948   long intpart;
1949   long fracpart;
1950 
1951   /*
1952    * AIX manpage says the default is 0, but Solaris says the default
1953    * is 6, and sprintf on AIX defaults to 6
1954    */
1955   if (max < 0)
1956     max = 6;
1957 
1958   ufvalue = abs_val (fvalue);
1959 
1960   if (fvalue < 0)
1961     signvalue = '-';
1962   else
1963     if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
1964       signvalue = '+';
1965     else
1966       if (flags & DP_F_SPACE)
1967 	signvalue = ' ';
1968 
1969 #if 0
1970   if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
1971 #endif
1972 
1973   intpart = ufvalue;
1974 
1975   /*
1976    * Sorry, we only support 9 digits past the decimal because of our
1977    * conversion method
1978    */
1979   if (max > 9)
1980     max = 9;
1981 
1982   /* We "cheat" by converting the fractional part to integer by
1983    * multiplying by a factor of 10
1984    */
1985   fracpart = round ((powN (10, max)) * (ufvalue - intpart));
1986 
1987   if (fracpart >= powN (10, max))
1988   {
1989     intpart++;
1990     fracpart -= powN (10, max);
1991   }
1992 
1993 #ifdef DEBUG_SNPRINTF
1994   dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
1995 #endif
1996 
1997   /* Convert integer part */
1998   do {
1999     iconvert[iplace++] =
2000       (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
2001     intpart = (intpart / 10);
2002   } while(intpart && (iplace < 20));
2003   if (iplace == 20) iplace--;
2004   iconvert[iplace] = 0;
2005 
2006   /* Convert fractional part */
2007   do {
2008     fconvert[fplace++] =
2009       (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
2010     fracpart = (fracpart / 10);
2011   } while(fracpart && (fplace < 20));
2012   if (fplace == 20) fplace--;
2013   fconvert[fplace] = 0;
2014 
2015   /* -1 for decimal point, another -1 if we are printing a sign */
2016   padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
2017   zpadlen = max - fplace;
2018   if (zpadlen < 0)
2019     zpadlen = 0;
2020   if (padlen < 0)
2021     padlen = 0;
2022   if (flags & DP_F_MINUS)
2023     padlen = -padlen; /* Left Justifty */
2024 
2025   if ((flags & DP_F_ZERO) && (padlen > 0))
2026   {
2027     if (signvalue)
2028     {
2029       total += dopr_outch (buffer, currlen, maxlen, signvalue);
2030       --padlen;
2031       signvalue = 0;
2032     }
2033     while (padlen > 0)
2034     {
2035       total += dopr_outch (buffer, currlen, maxlen, '0');
2036       --padlen;
2037     }
2038   }
2039   while (padlen > 0)
2040   {
2041     total += dopr_outch (buffer, currlen, maxlen, ' ');
2042     --padlen;
2043   }
2044   if (signvalue)
2045     total += dopr_outch (buffer, currlen, maxlen, signvalue);
2046 
2047   while (iplace > 0)
2048     total += dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
2049 
2050   /*
2051    * Decimal point.  This should probably use locale to find the correct
2052    * char to print out.
2053    */
2054   if (max > 0)
2055   {
2056     total += dopr_outch (buffer, currlen, maxlen, '.');
2057 
2058     while (zpadlen-- > 0)
2059       total += dopr_outch (buffer, currlen, maxlen, '0');
2060 
2061     while (fplace > 0)
2062       total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
2063   }
2064 
2065   while (padlen < 0)
2066   {
2067     total += dopr_outch (buffer, currlen, maxlen, ' ');
2068     ++padlen;
2069   }
2070 
2071   return total;
2072 }
2073 
dopr_outch(char * buffer,size_t * currlen,size_t maxlen,char c)2074 static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
2075 {
2076   if (*currlen + 1 < maxlen)
2077     buffer[(*currlen)++] = c;
2078   return 1;
2079 }
2080 
Q_vsnprintf(char * str,size_t length,const char * fmt,va_list args)2081 int Q_vsnprintf(char *str, size_t length, const char *fmt, va_list args)
2082 {
2083 	return dopr(str, length, fmt, args);
2084 }
2085 
2086 /* this is really crappy */
sscanf(const char * buffer,const char * fmt,...)2087 int sscanf( const char *buffer, const char *fmt, ... ) {
2088 	int		cmd;
2089 	va_list		ap;
2090 	int		count;
2091 	size_t		len;
2092 
2093 	va_start (ap, fmt);
2094 	count = 0;
2095 
2096 	while ( *fmt ) {
2097 		if ( fmt[0] != '%' ) {
2098 			fmt++;
2099 			continue;
2100 		}
2101 
2102 		fmt++;
2103 		cmd = *fmt;
2104 
2105 		if (isdigit (cmd)) {
2106 			len = (size_t)_atoi (&fmt);
2107 			cmd = *(fmt - 1);
2108 		} else {
2109 			len = MAX_STRING_CHARS - 1;
2110 			fmt++;
2111 		}
2112 
2113 		switch ( cmd ) {
2114 		case 'i':
2115 		case 'd':
2116 		case 'u':
2117 			*(va_arg (ap, int *)) = _atoi( &buffer );
2118 			break;
2119 		case 'f':
2120 			*(va_arg (ap, float *)) = _atof( &buffer );
2121 			break;
2122 		case 's':
2123 			{
2124 			char *s = va_arg (ap, char *);
2125 			while (isspace (*buffer))
2126 				buffer++;
2127 			while (*buffer && !isspace (*buffer) && len-- > 0 )
2128 				*s++ = *buffer++;
2129 			*s++ = '\0';
2130 			break;
2131 			}
2132 		}
2133 	}
2134 
2135 	va_end (ap);
2136 	return count;
2137 }
2138 
2139 #endif
2140