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