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