Mercurial > mm7
comparison lib/swig/swigwin-2.0.11/CCache/snprintf.c @ 1899:b3009adc0e2f
Adding swig, gitignore, hgignore
author | Nomad |
---|---|
date | Mon, 21 Oct 2013 10:42:27 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1867:eb580660bbbb | 1899:b3009adc0e2f |
---|---|
1 /* | |
2 * Copyright Patrick Powell 1995 | |
3 * This code is based on code written by Patrick Powell (papowell@astart.com) | |
4 * It may be used for any purpose as long as this notice remains intact | |
5 * on all source code distributions | |
6 */ | |
7 | |
8 /************************************************************** | |
9 * Original: | |
10 * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 | |
11 * A bombproof version of doprnt (dopr) included. | |
12 * Sigh. This sort of thing is always nasty do deal with. Note that | |
13 * the version here does not include floating point... | |
14 * | |
15 * snprintf() is used instead of sprintf() as it does limit checks | |
16 * for string length. This covers a nasty loophole. | |
17 * | |
18 * The other functions are there to prevent NULL pointers from | |
19 * causing nast effects. | |
20 * | |
21 * More Recently: | |
22 * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 | |
23 * This was ugly. It is still ugly. I opted out of floating point | |
24 * numbers, but the formatter understands just about everything | |
25 * from the normal C string format, at least as far as I can tell from | |
26 * the Solaris 2.5 printf(3S) man page. | |
27 * | |
28 * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 | |
29 * Ok, added some minimal floating point support, which means this | |
30 * probably requires libm on most operating systems. Don't yet | |
31 * support the exponent (e,E) and sigfig (g,G). Also, fmtint() | |
32 * was pretty badly broken, it just wasn't being exercised in ways | |
33 * which showed it, so that's been fixed. Also, formated the code | |
34 * to mutt conventions, and removed dead code left over from the | |
35 * original. Also, there is now a builtin-test, just compile with: | |
36 * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm | |
37 * and run snprintf for results. | |
38 * | |
39 * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i | |
40 * The PGP code was using unsigned hexadecimal formats. | |
41 * Unfortunately, unsigned formats simply didn't work. | |
42 * | |
43 * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 | |
44 * The original code assumed that both snprintf() and vsnprintf() were | |
45 * missing. Some systems only have snprintf() but not vsnprintf(), so | |
46 * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. | |
47 * | |
48 * Andrew Tridgell (tridge@samba.org) Oct 1998 | |
49 * fixed handling of %.0f | |
50 * added test for HAVE_LONG_DOUBLE | |
51 * | |
52 * tridge@samba.org, idra@samba.org, April 2001 | |
53 * got rid of fcvt code (twas buggy and made testing harder) | |
54 * added C99 semantics | |
55 * | |
56 **************************************************************/ | |
57 | |
58 #ifndef NO_CONFIG_H /* for some tests */ | |
59 #include "config.h" | |
60 #endif | |
61 | |
62 #ifdef HAVE_STRING_H | |
63 #include <string.h> | |
64 #endif | |
65 | |
66 #ifdef HAVE_STRINGS_H | |
67 #include <strings.h> | |
68 #endif | |
69 #ifdef HAVE_CTYPE_H | |
70 #include <ctype.h> | |
71 #endif | |
72 #include <sys/types.h> | |
73 #include <stdarg.h> | |
74 #ifdef HAVE_STDLIB_H | |
75 #include <stdlib.h> | |
76 #endif | |
77 | |
78 #if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) | |
79 /* only include stdio.h if we are not re-defining snprintf or vsnprintf */ | |
80 #include <stdio.h> | |
81 /* make the compiler happy with an empty file */ | |
82 void dummy_snprintf(void) {} | |
83 #else | |
84 | |
85 #ifdef HAVE_LONG_DOUBLE | |
86 #define LDOUBLE long double | |
87 #else | |
88 #define LDOUBLE double | |
89 #endif | |
90 | |
91 #ifdef HAVE_LONG_LONG | |
92 #define LLONG long long | |
93 #else | |
94 #define LLONG long | |
95 #endif | |
96 | |
97 static size_t dopr(char *buffer, size_t maxlen, const char *format, | |
98 va_list args); | |
99 static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, | |
100 char *value, int flags, int min, int max); | |
101 static void fmtint(char *buffer, size_t *currlen, size_t maxlen, | |
102 long value, int base, int min, int max, int flags); | |
103 static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, | |
104 LDOUBLE fvalue, int min, int max, int flags); | |
105 static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); | |
106 | |
107 /* | |
108 * dopr(): poor man's version of doprintf | |
109 */ | |
110 | |
111 /* format read states */ | |
112 #define DP_S_DEFAULT 0 | |
113 #define DP_S_FLAGS 1 | |
114 #define DP_S_MIN 2 | |
115 #define DP_S_DOT 3 | |
116 #define DP_S_MAX 4 | |
117 #define DP_S_MOD 5 | |
118 #define DP_S_CONV 6 | |
119 #define DP_S_DONE 7 | |
120 | |
121 /* format flags - Bits */ | |
122 #define DP_F_MINUS (1 << 0) | |
123 #define DP_F_PLUS (1 << 1) | |
124 #define DP_F_SPACE (1 << 2) | |
125 #define DP_F_NUM (1 << 3) | |
126 #define DP_F_ZERO (1 << 4) | |
127 #define DP_F_UP (1 << 5) | |
128 #define DP_F_UNSIGNED (1 << 6) | |
129 | |
130 /* Conversion Flags */ | |
131 #define DP_C_SHORT 1 | |
132 #define DP_C_LONG 2 | |
133 #define DP_C_LDOUBLE 3 | |
134 #define DP_C_LLONG 4 | |
135 | |
136 #define char_to_int(p) ((p)- '0') | |
137 #ifndef MAX | |
138 #define MAX(p,q) (((p) >= (q)) ? (p) : (q)) | |
139 #endif | |
140 | |
141 static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args) | |
142 { | |
143 char ch; | |
144 LLONG value; | |
145 LDOUBLE fvalue; | |
146 char *strvalue; | |
147 int min; | |
148 int max; | |
149 int state; | |
150 int flags; | |
151 int cflags; | |
152 size_t currlen; | |
153 | |
154 state = DP_S_DEFAULT; | |
155 currlen = flags = cflags = min = 0; | |
156 max = -1; | |
157 ch = *format++; | |
158 | |
159 while (state != DP_S_DONE) { | |
160 if (ch == '\0') | |
161 state = DP_S_DONE; | |
162 | |
163 switch(state) { | |
164 case DP_S_DEFAULT: | |
165 if (ch == '%') | |
166 state = DP_S_FLAGS; | |
167 else | |
168 dopr_outch (buffer, &currlen, maxlen, ch); | |
169 ch = *format++; | |
170 break; | |
171 case DP_S_FLAGS: | |
172 switch (ch) { | |
173 case '-': | |
174 flags |= DP_F_MINUS; | |
175 ch = *format++; | |
176 break; | |
177 case '+': | |
178 flags |= DP_F_PLUS; | |
179 ch = *format++; | |
180 break; | |
181 case ' ': | |
182 flags |= DP_F_SPACE; | |
183 ch = *format++; | |
184 break; | |
185 case '#': | |
186 flags |= DP_F_NUM; | |
187 ch = *format++; | |
188 break; | |
189 case '0': | |
190 flags |= DP_F_ZERO; | |
191 ch = *format++; | |
192 break; | |
193 default: | |
194 state = DP_S_MIN; | |
195 break; | |
196 } | |
197 break; | |
198 case DP_S_MIN: | |
199 if (isdigit((unsigned char)ch)) { | |
200 min = 10*min + char_to_int (ch); | |
201 ch = *format++; | |
202 } else if (ch == '*') { | |
203 min = va_arg (args, int); | |
204 ch = *format++; | |
205 state = DP_S_DOT; | |
206 } else { | |
207 state = DP_S_DOT; | |
208 } | |
209 break; | |
210 case DP_S_DOT: | |
211 if (ch == '.') { | |
212 state = DP_S_MAX; | |
213 ch = *format++; | |
214 } else { | |
215 state = DP_S_MOD; | |
216 } | |
217 break; | |
218 case DP_S_MAX: | |
219 if (isdigit((unsigned char)ch)) { | |
220 if (max < 0) | |
221 max = 0; | |
222 max = 10*max + char_to_int (ch); | |
223 ch = *format++; | |
224 } else if (ch == '*') { | |
225 max = va_arg (args, int); | |
226 ch = *format++; | |
227 state = DP_S_MOD; | |
228 } else { | |
229 state = DP_S_MOD; | |
230 } | |
231 break; | |
232 case DP_S_MOD: | |
233 switch (ch) { | |
234 case 'h': | |
235 cflags = DP_C_SHORT; | |
236 ch = *format++; | |
237 break; | |
238 case 'l': | |
239 cflags = DP_C_LONG; | |
240 ch = *format++; | |
241 if (ch == 'l') { /* It's a long long */ | |
242 cflags = DP_C_LLONG; | |
243 ch = *format++; | |
244 } | |
245 break; | |
246 case 'L': | |
247 cflags = DP_C_LDOUBLE; | |
248 ch = *format++; | |
249 break; | |
250 default: | |
251 break; | |
252 } | |
253 state = DP_S_CONV; | |
254 break; | |
255 case DP_S_CONV: | |
256 switch (ch) { | |
257 case 'd': | |
258 case 'i': | |
259 if (cflags == DP_C_SHORT) | |
260 value = va_arg (args, int); | |
261 else if (cflags == DP_C_LONG) | |
262 value = va_arg (args, long int); | |
263 else if (cflags == DP_C_LLONG) | |
264 value = va_arg (args, LLONG); | |
265 else | |
266 value = va_arg (args, int); | |
267 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); | |
268 break; | |
269 case 'o': | |
270 flags |= DP_F_UNSIGNED; | |
271 if (cflags == DP_C_SHORT) | |
272 value = va_arg (args, unsigned int); | |
273 else if (cflags == DP_C_LONG) | |
274 value = (long)va_arg (args, unsigned long int); | |
275 else if (cflags == DP_C_LLONG) | |
276 value = (long)va_arg (args, unsigned LLONG); | |
277 else | |
278 value = (long)va_arg (args, unsigned int); | |
279 fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); | |
280 break; | |
281 case 'u': | |
282 flags |= DP_F_UNSIGNED; | |
283 if (cflags == DP_C_SHORT) | |
284 value = va_arg (args, unsigned int); | |
285 else if (cflags == DP_C_LONG) | |
286 value = (long)va_arg (args, unsigned long int); | |
287 else if (cflags == DP_C_LLONG) | |
288 value = (LLONG)va_arg (args, unsigned LLONG); | |
289 else | |
290 value = (long)va_arg (args, unsigned int); | |
291 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); | |
292 break; | |
293 case 'X': | |
294 flags |= DP_F_UP; | |
295 case 'x': | |
296 flags |= DP_F_UNSIGNED; | |
297 if (cflags == DP_C_SHORT) | |
298 value = va_arg (args, unsigned int); | |
299 else if (cflags == DP_C_LONG) | |
300 value = (long)va_arg (args, unsigned long int); | |
301 else if (cflags == DP_C_LLONG) | |
302 value = (LLONG)va_arg (args, unsigned LLONG); | |
303 else | |
304 value = (long)va_arg (args, unsigned int); | |
305 fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); | |
306 break; | |
307 case 'f': | |
308 if (cflags == DP_C_LDOUBLE) | |
309 fvalue = va_arg (args, LDOUBLE); | |
310 else | |
311 fvalue = va_arg (args, double); | |
312 /* um, floating point? */ | |
313 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); | |
314 break; | |
315 case 'E': | |
316 flags |= DP_F_UP; | |
317 case 'e': | |
318 if (cflags == DP_C_LDOUBLE) | |
319 fvalue = va_arg (args, LDOUBLE); | |
320 else | |
321 fvalue = va_arg (args, double); | |
322 break; | |
323 case 'G': | |
324 flags |= DP_F_UP; | |
325 case 'g': | |
326 if (cflags == DP_C_LDOUBLE) | |
327 fvalue = va_arg (args, LDOUBLE); | |
328 else | |
329 fvalue = va_arg (args, double); | |
330 break; | |
331 case 'c': | |
332 dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); | |
333 break; | |
334 case 's': | |
335 strvalue = va_arg (args, char *); | |
336 if (!strvalue) strvalue = "(NULL)"; | |
337 if (max == -1) { | |
338 max = strlen(strvalue); | |
339 } | |
340 if (min > 0 && max >= 0 && min > max) max = min; | |
341 fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); | |
342 break; | |
343 case 'p': | |
344 strvalue = (char *)va_arg(args, void *); | |
345 fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); | |
346 break; | |
347 case 'n': | |
348 if (cflags == DP_C_SHORT) { | |
349 short int *num; | |
350 num = va_arg (args, short int *); | |
351 *num = currlen; | |
352 } else if (cflags == DP_C_LONG) { | |
353 long int *num; | |
354 num = va_arg (args, long int *); | |
355 *num = (long int)currlen; | |
356 } else if (cflags == DP_C_LLONG) { | |
357 LLONG *num; | |
358 num = va_arg (args, LLONG *); | |
359 *num = (LLONG)currlen; | |
360 } else { | |
361 int *num; | |
362 num = va_arg (args, int *); | |
363 *num = currlen; | |
364 } | |
365 break; | |
366 case '%': | |
367 dopr_outch (buffer, &currlen, maxlen, ch); | |
368 break; | |
369 case 'w': | |
370 /* not supported yet, treat as next char */ | |
371 ch = *format++; | |
372 break; | |
373 default: | |
374 /* Unknown, skip */ | |
375 break; | |
376 } | |
377 ch = *format++; | |
378 state = DP_S_DEFAULT; | |
379 flags = cflags = min = 0; | |
380 max = -1; | |
381 break; | |
382 case DP_S_DONE: | |
383 break; | |
384 default: | |
385 /* hmm? */ | |
386 break; /* some picky compilers need this */ | |
387 } | |
388 } | |
389 if (maxlen != 0) { | |
390 if (currlen < maxlen - 1) | |
391 buffer[currlen] = '\0'; | |
392 else if (maxlen > 0) | |
393 buffer[maxlen - 1] = '\0'; | |
394 } | |
395 | |
396 return currlen; | |
397 } | |
398 | |
399 static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, | |
400 char *value, int flags, int min, int max) | |
401 { | |
402 int padlen, strln; /* amount to pad */ | |
403 int cnt = 0; | |
404 | |
405 #ifdef DEBUG_SNPRINTF | |
406 printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); | |
407 #endif | |
408 if (value == 0) { | |
409 value = "<NULL>"; | |
410 } | |
411 | |
412 for (strln = 0; value[strln]; ++strln); /* strlen */ | |
413 padlen = min - strln; | |
414 if (padlen < 0) | |
415 padlen = 0; | |
416 if (flags & DP_F_MINUS) | |
417 padlen = -padlen; /* Left Justify */ | |
418 | |
419 while ((padlen > 0) && (cnt < max)) { | |
420 dopr_outch (buffer, currlen, maxlen, ' '); | |
421 --padlen; | |
422 ++cnt; | |
423 } | |
424 while (*value && (cnt < max)) { | |
425 dopr_outch (buffer, currlen, maxlen, *value++); | |
426 ++cnt; | |
427 } | |
428 while ((padlen < 0) && (cnt < max)) { | |
429 dopr_outch (buffer, currlen, maxlen, ' '); | |
430 ++padlen; | |
431 ++cnt; | |
432 } | |
433 } | |
434 | |
435 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ | |
436 | |
437 static void fmtint(char *buffer, size_t *currlen, size_t maxlen, | |
438 long value, int base, int min, int max, int flags) | |
439 { | |
440 int signvalue = 0; | |
441 unsigned long uvalue; | |
442 char convert[20]; | |
443 int place = 0; | |
444 int spadlen = 0; /* amount to space pad */ | |
445 int zpadlen = 0; /* amount to zero pad */ | |
446 int caps = 0; | |
447 | |
448 if (max < 0) | |
449 max = 0; | |
450 | |
451 uvalue = value; | |
452 | |
453 if(!(flags & DP_F_UNSIGNED)) { | |
454 if( value < 0 ) { | |
455 signvalue = '-'; | |
456 uvalue = -value; | |
457 } else { | |
458 if (flags & DP_F_PLUS) /* Do a sign (+/i) */ | |
459 signvalue = '+'; | |
460 else if (flags & DP_F_SPACE) | |
461 signvalue = ' '; | |
462 } | |
463 } | |
464 | |
465 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ | |
466 | |
467 do { | |
468 convert[place++] = | |
469 (caps? "0123456789ABCDEF":"0123456789abcdef") | |
470 [uvalue % (unsigned)base ]; | |
471 uvalue = (uvalue / (unsigned)base ); | |
472 } while(uvalue && (place < 20)); | |
473 if (place == 20) place--; | |
474 convert[place] = 0; | |
475 | |
476 zpadlen = max - place; | |
477 spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); | |
478 if (zpadlen < 0) zpadlen = 0; | |
479 if (spadlen < 0) spadlen = 0; | |
480 if (flags & DP_F_ZERO) { | |
481 zpadlen = MAX(zpadlen, spadlen); | |
482 spadlen = 0; | |
483 } | |
484 if (flags & DP_F_MINUS) | |
485 spadlen = -spadlen; /* Left Justifty */ | |
486 | |
487 #ifdef DEBUG_SNPRINTF | |
488 printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", | |
489 zpadlen, spadlen, min, max, place); | |
490 #endif | |
491 | |
492 /* Spaces */ | |
493 while (spadlen > 0) { | |
494 dopr_outch (buffer, currlen, maxlen, ' '); | |
495 --spadlen; | |
496 } | |
497 | |
498 /* Sign */ | |
499 if (signvalue) | |
500 dopr_outch (buffer, currlen, maxlen, signvalue); | |
501 | |
502 /* Zeros */ | |
503 if (zpadlen > 0) { | |
504 while (zpadlen > 0) { | |
505 dopr_outch (buffer, currlen, maxlen, '0'); | |
506 --zpadlen; | |
507 } | |
508 } | |
509 | |
510 /* Digits */ | |
511 while (place > 0) | |
512 dopr_outch (buffer, currlen, maxlen, convert[--place]); | |
513 | |
514 /* Left Justified spaces */ | |
515 while (spadlen < 0) { | |
516 dopr_outch (buffer, currlen, maxlen, ' '); | |
517 ++spadlen; | |
518 } | |
519 } | |
520 | |
521 static LDOUBLE abs_val(LDOUBLE value) | |
522 { | |
523 LDOUBLE result = value; | |
524 | |
525 if (value < 0) | |
526 result = -value; | |
527 | |
528 return result; | |
529 } | |
530 | |
531 static LDOUBLE POW10(int exp) | |
532 { | |
533 LDOUBLE result = 1; | |
534 | |
535 while (exp) { | |
536 result *= 10; | |
537 exp--; | |
538 } | |
539 | |
540 return result; | |
541 } | |
542 | |
543 static LLONG ROUND(LDOUBLE value) | |
544 { | |
545 LLONG intpart; | |
546 | |
547 intpart = (LLONG)value; | |
548 value = value - intpart; | |
549 if (value >= 0.5) intpart++; | |
550 | |
551 return intpart; | |
552 } | |
553 | |
554 /* a replacement for modf that doesn't need the math library. Should | |
555 be portable, but slow */ | |
556 static double my_modf(double x0, double *iptr) | |
557 { | |
558 int i; | |
559 long l; | |
560 double x = x0; | |
561 double f = 1.0; | |
562 | |
563 for (i=0;i<100;i++) { | |
564 l = (long)x; | |
565 if (l <= (x+1) && l >= (x-1)) break; | |
566 x *= 0.1; | |
567 f *= 10.0; | |
568 } | |
569 | |
570 if (i == 100) { | |
571 /* yikes! the number is beyond what we can handle. What do we do? */ | |
572 (*iptr) = 0; | |
573 return 0; | |
574 } | |
575 | |
576 if (i != 0) { | |
577 double i2; | |
578 double ret; | |
579 | |
580 ret = my_modf(x0-l*f, &i2); | |
581 (*iptr) = l*f + i2; | |
582 return ret; | |
583 } | |
584 | |
585 (*iptr) = l; | |
586 return x - (*iptr); | |
587 } | |
588 | |
589 | |
590 static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, | |
591 LDOUBLE fvalue, int min, int max, int flags) | |
592 { | |
593 int signvalue = 0; | |
594 double ufvalue; | |
595 char iconvert[311]; | |
596 char fconvert[311]; | |
597 int iplace = 0; | |
598 int fplace = 0; | |
599 int padlen = 0; /* amount to pad */ | |
600 int zpadlen = 0; | |
601 int caps = 0; | |
602 int index; | |
603 double intpart; | |
604 double fracpart; | |
605 double temp; | |
606 | |
607 /* | |
608 * AIX manpage says the default is 0, but Solaris says the default | |
609 * is 6, and sprintf on AIX defaults to 6 | |
610 */ | |
611 if (max < 0) | |
612 max = 6; | |
613 | |
614 ufvalue = abs_val (fvalue); | |
615 | |
616 if (fvalue < 0) { | |
617 signvalue = '-'; | |
618 } else { | |
619 if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ | |
620 signvalue = '+'; | |
621 } else { | |
622 if (flags & DP_F_SPACE) | |
623 signvalue = ' '; | |
624 } | |
625 } | |
626 | |
627 #if 0 | |
628 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ | |
629 #endif | |
630 | |
631 #if 0 | |
632 if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ | |
633 #endif | |
634 | |
635 /* | |
636 * Sorry, we only support 16 digits past the decimal because of our | |
637 * conversion method | |
638 */ | |
639 if (max > 16) | |
640 max = 16; | |
641 | |
642 /* We "cheat" by converting the fractional part to integer by | |
643 * multiplying by a factor of 10 | |
644 */ | |
645 | |
646 temp = ufvalue; | |
647 my_modf(temp, &intpart); | |
648 | |
649 fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); | |
650 | |
651 if (fracpart >= POW10(max)) { | |
652 intpart++; | |
653 fracpart -= POW10(max); | |
654 } | |
655 | |
656 | |
657 /* Convert integer part */ | |
658 do { | |
659 temp = intpart; | |
660 my_modf(intpart*0.1, &intpart); | |
661 temp = temp*0.1; | |
662 index = (int) ((temp -intpart +0.05)* 10.0); | |
663 /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ | |
664 /* printf ("%llf, %f, %x\n", temp, intpart, index); */ | |
665 iconvert[iplace++] = | |
666 (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; | |
667 } while (intpart && (iplace < 311)); | |
668 if (iplace == 311) iplace--; | |
669 iconvert[iplace] = 0; | |
670 | |
671 /* Convert fractional part */ | |
672 if (fracpart) | |
673 { | |
674 do { | |
675 temp = fracpart; | |
676 my_modf(fracpart*0.1, &fracpart); | |
677 temp = temp*0.1; | |
678 index = (int) ((temp -fracpart +0.05)* 10.0); | |
679 /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */ | |
680 /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */ | |
681 fconvert[fplace++] = | |
682 (caps? "0123456789ABCDEF":"0123456789abcdef")[index]; | |
683 } while(fracpart && (fplace < 311)); | |
684 if (fplace == 311) fplace--; | |
685 } | |
686 fconvert[fplace] = 0; | |
687 | |
688 /* -1 for decimal point, another -1 if we are printing a sign */ | |
689 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); | |
690 zpadlen = max - fplace; | |
691 if (zpadlen < 0) zpadlen = 0; | |
692 if (padlen < 0) | |
693 padlen = 0; | |
694 if (flags & DP_F_MINUS) | |
695 padlen = -padlen; /* Left Justifty */ | |
696 | |
697 if ((flags & DP_F_ZERO) && (padlen > 0)) { | |
698 if (signvalue) { | |
699 dopr_outch (buffer, currlen, maxlen, signvalue); | |
700 --padlen; | |
701 signvalue = 0; | |
702 } | |
703 while (padlen > 0) { | |
704 dopr_outch (buffer, currlen, maxlen, '0'); | |
705 --padlen; | |
706 } | |
707 } | |
708 while (padlen > 0) { | |
709 dopr_outch (buffer, currlen, maxlen, ' '); | |
710 --padlen; | |
711 } | |
712 if (signvalue) | |
713 dopr_outch (buffer, currlen, maxlen, signvalue); | |
714 | |
715 while (iplace > 0) | |
716 dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); | |
717 | |
718 #ifdef DEBUG_SNPRINTF | |
719 printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); | |
720 #endif | |
721 | |
722 /* | |
723 * Decimal point. This should probably use locale to find the correct | |
724 * char to print out. | |
725 */ | |
726 if (max > 0) { | |
727 dopr_outch (buffer, currlen, maxlen, '.'); | |
728 | |
729 while (fplace > 0) | |
730 dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); | |
731 } | |
732 | |
733 while (zpadlen > 0) { | |
734 dopr_outch (buffer, currlen, maxlen, '0'); | |
735 --zpadlen; | |
736 } | |
737 | |
738 while (padlen < 0) { | |
739 dopr_outch (buffer, currlen, maxlen, ' '); | |
740 ++padlen; | |
741 } | |
742 } | |
743 | |
744 static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) | |
745 { | |
746 if (*currlen < maxlen) { | |
747 buffer[(*currlen)] = c; | |
748 } | |
749 (*currlen)++; | |
750 } | |
751 | |
752 /* yes this really must be a ||. Don't muck with this (tridge) */ | |
753 #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) | |
754 int vsnprintf (char *str, size_t count, const char *fmt, va_list args) | |
755 { | |
756 return dopr(str, count, fmt, args); | |
757 } | |
758 #endif | |
759 | |
760 /* yes this really must be a ||. Don't muck wiith this (tridge) | |
761 * | |
762 * The logic for these two is that we need our own definition if the | |
763 * OS *either* has no definition of *sprintf, or if it does have one | |
764 * that doesn't work properly according to the autoconf test. Perhaps | |
765 * these should really be smb_snprintf to avoid conflicts with buggy | |
766 * linkers? -- mbp | |
767 */ | |
768 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_SNPRINTF) | |
769 int snprintf(char *str,size_t count,const char *fmt,...) | |
770 { | |
771 size_t ret; | |
772 va_list ap; | |
773 | |
774 va_start(ap, fmt); | |
775 ret = vsnprintf(str, count, fmt, ap); | |
776 va_end(ap); | |
777 return ret; | |
778 } | |
779 #endif | |
780 | |
781 #endif | |
782 | |
783 #ifndef HAVE_VASPRINTF | |
784 int vasprintf(char **ptr, const char *format, va_list ap) | |
785 { | |
786 int ret; | |
787 | |
788 ret = vsnprintf(0, 0, format, ap); | |
789 if (ret <= 0) return ret; | |
790 | |
791 (*ptr) = (char *)malloc(ret+1); | |
792 if (!*ptr) return -1; | |
793 ret = vsnprintf(*ptr, ret+1, format, ap); | |
794 | |
795 return ret; | |
796 } | |
797 #endif | |
798 | |
799 | |
800 #ifndef HAVE_ASPRINTF | |
801 int asprintf(char **ptr, const char *format, ...) | |
802 { | |
803 va_list ap; | |
804 int ret; | |
805 | |
806 *ptr = 0; | |
807 va_start(ap, format); | |
808 ret = vasprintf(ptr, format, ap); | |
809 va_end(ap); | |
810 | |
811 return ret; | |
812 } | |
813 #endif | |
814 | |
815 #ifndef HAVE_VSYSLOG | |
816 #ifdef HAVE_SYSLOG | |
817 void vsyslog (int facility_priority, char *format, va_list arglist) | |
818 { | |
819 char *msg = 0; | |
820 vasprintf(&msg, format, arglist); | |
821 if (!msg) | |
822 return; | |
823 syslog(facility_priority, "%s", msg); | |
824 free(msg); | |
825 } | |
826 #endif /* HAVE_SYSLOG */ | |
827 #endif /* HAVE_VSYSLOG */ | |
828 | |
829 #ifdef TEST_SNPRINTF | |
830 | |
831 int sprintf(char *str,const char *fmt,...); | |
832 | |
833 int main (void) | |
834 { | |
835 char buf1[1024]; | |
836 char buf2[1024]; | |
837 char *fp_fmt[] = { | |
838 "%1.1f", | |
839 "%-1.5f", | |
840 "%1.5f", | |
841 "%123.9f", | |
842 "%10.5f", | |
843 "% 10.5f", | |
844 "%+22.9f", | |
845 "%+4.9f", | |
846 "%01.3f", | |
847 "%4f", | |
848 "%3.1f", | |
849 "%3.2f", | |
850 "%.0f", | |
851 "%f", | |
852 "-16.16f", | |
853 0 | |
854 }; | |
855 double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, | |
856 0.9996, 1.996, 4.136, 0}; | |
857 char *int_fmt[] = { | |
858 "%-1.5d", | |
859 "%1.5d", | |
860 "%123.9d", | |
861 "%5.5d", | |
862 "%10.5d", | |
863 "% 10.5d", | |
864 "%+22.33d", | |
865 "%01.3d", | |
866 "%4d", | |
867 "%d", | |
868 0 | |
869 }; | |
870 long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; | |
871 char *str_fmt[] = { | |
872 "10.5s", | |
873 "5.10s", | |
874 "10.1s", | |
875 "0.10s", | |
876 "10.0s", | |
877 "1.10s", | |
878 "%s", | |
879 "%.1s", | |
880 "%.10s", | |
881 "%10s", | |
882 0 | |
883 }; | |
884 char *str_vals[] = {"hello", "a", "", "a longer string", 0}; | |
885 int x, y; | |
886 int fail = 0; | |
887 int num = 0; | |
888 | |
889 printf ("Testing snprintf format codes against system sprintf...\n"); | |
890 | |
891 for (x = 0; fp_fmt[x] ; x++) { | |
892 for (y = 0; fp_nums[y] != 0 ; y++) { | |
893 int l1 = snprintf(0, 0, fp_fmt[x], fp_nums[y]); | |
894 int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); | |
895 sprintf (buf2, fp_fmt[x], fp_nums[y]); | |
896 if (strcmp (buf1, buf2)) { | |
897 printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", | |
898 fp_fmt[x], buf1, buf2); | |
899 fail++; | |
900 } | |
901 if (l1 != l2) { | |
902 printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]); | |
903 fail++; | |
904 } | |
905 num++; | |
906 } | |
907 } | |
908 | |
909 for (x = 0; int_fmt[x] ; x++) { | |
910 for (y = 0; int_nums[y] != 0 ; y++) { | |
911 int l1 = snprintf(0, 0, int_fmt[x], int_nums[y]); | |
912 int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); | |
913 sprintf (buf2, int_fmt[x], int_nums[y]); | |
914 if (strcmp (buf1, buf2)) { | |
915 printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", | |
916 int_fmt[x], buf1, buf2); | |
917 fail++; | |
918 } | |
919 if (l1 != l2) { | |
920 printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]); | |
921 fail++; | |
922 } | |
923 num++; | |
924 } | |
925 } | |
926 | |
927 for (x = 0; str_fmt[x] ; x++) { | |
928 for (y = 0; str_vals[y] != 0 ; y++) { | |
929 int l1 = snprintf(0, 0, str_fmt[x], str_vals[y]); | |
930 int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); | |
931 sprintf (buf2, str_fmt[x], str_vals[y]); | |
932 if (strcmp (buf1, buf2)) { | |
933 printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", | |
934 str_fmt[x], buf1, buf2); | |
935 fail++; | |
936 } | |
937 if (l1 != l2) { | |
938 printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]); | |
939 fail++; | |
940 } | |
941 num++; | |
942 } | |
943 } | |
944 | |
945 printf ("%d tests failed out of %d.\n", fail, num); | |
946 | |
947 printf("seeing how many digits we support\n"); | |
948 { | |
949 double v0 = 0.12345678901234567890123456789012345678901; | |
950 for (x=0; x<100; x++) { | |
951 snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x)); | |
952 sprintf(buf2, "%1.1f", v0*pow(10, x)); | |
953 if (strcmp(buf1, buf2)) { | |
954 printf("we seem to support %d digits\n", x-1); | |
955 break; | |
956 } | |
957 } | |
958 } | |
959 | |
960 return 0; | |
961 } | |
962 #endif /* SNPRINTF_TEST */ |