stropheruby 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/snprintf.c ADDED
@@ -0,0 +1,839 @@
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
+ * Russ Allbery <rra@stanford.edu> 2000-08-26
53
+ * fixed return value to comply with C99
54
+ * fixed handling of snprintf(NULL, ...)
55
+ *
56
+ **************************************************************/
57
+
58
+ /** @file
59
+ * A snprintf implementation.
60
+ */
61
+
62
+ /* JAM: we don't need this - #include "config.h" */
63
+
64
+ /* JAM: changed declarations to xmpp_snprintf and xmpp_vsnprintf to
65
+ avoid namespace collision. */
66
+
67
+ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
68
+
69
+ #include <string.h>
70
+ #include <ctype.h>
71
+ #include <sys/types.h>
72
+
73
+ /* Define this as a fall through, HAVE_STDARG_H is probably already set */
74
+
75
+ #define HAVE_VARARGS_H
76
+ #define HAVE_STDARG_H /* JAM: set always */
77
+
78
+
79
+ /* varargs declarations: */
80
+
81
+ #if defined(HAVE_STDARG_H)
82
+ # include <stdarg.h>
83
+ # define HAVE_STDARGS /* let's hope that works everywhere (mj) */
84
+ # define VA_LOCAL_DECL va_list ap
85
+ # define VA_START(f) va_start(ap, f)
86
+ # define VA_SHIFT(v,t) ; /* no-op for ANSI */
87
+ # define VA_END va_end(ap)
88
+ #else
89
+ # if defined(HAVE_VARARGS_H)
90
+ # include <varargs.h>
91
+ # undef HAVE_STDARGS
92
+ # define VA_LOCAL_DECL va_list ap
93
+ # define VA_START(f) va_start(ap) /* f is ignored! */
94
+ # define VA_SHIFT(v,t) v = va_arg(ap,t)
95
+ # define VA_END va_end(ap)
96
+ # else
97
+ /*XX ** NO VARARGS ** XX*/
98
+ # endif
99
+ #endif
100
+
101
+ #ifdef HAVE_LONG_DOUBLE
102
+ #define LDOUBLE long double
103
+ #else
104
+ #define LDOUBLE double
105
+ #endif
106
+
107
+ int xmpp_snprintf (char *str, size_t count, const char *fmt, ...);
108
+ int xmpp_vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
109
+
110
+ static int dopr (char *buffer, size_t maxlen, const char *format,
111
+ va_list args);
112
+ static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
113
+ char *value, int flags, int min, int max);
114
+ static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
115
+ long value, int base, int min, int max, int flags);
116
+ static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
117
+ LDOUBLE fvalue, int min, int max, int flags);
118
+ static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
119
+
120
+ /*
121
+ * dopr(): poor man's version of doprintf
122
+ */
123
+
124
+ /* format read states */
125
+ #define DP_S_DEFAULT 0
126
+ #define DP_S_FLAGS 1
127
+ #define DP_S_MIN 2
128
+ #define DP_S_DOT 3
129
+ #define DP_S_MAX 4
130
+ #define DP_S_MOD 5
131
+ #define DP_S_CONV 6
132
+ #define DP_S_DONE 7
133
+
134
+ /* format flags - Bits */
135
+ #define DP_F_MINUS (1 << 0)
136
+ #define DP_F_PLUS (1 << 1)
137
+ #define DP_F_SPACE (1 << 2)
138
+ #define DP_F_NUM (1 << 3)
139
+ #define DP_F_ZERO (1 << 4)
140
+ #define DP_F_UP (1 << 5)
141
+ #define DP_F_UNSIGNED (1 << 6)
142
+
143
+ /* Conversion Flags */
144
+ #define DP_C_SHORT 1
145
+ #define DP_C_LONG 2
146
+ #define DP_C_LDOUBLE 3
147
+
148
+ #define char_to_int(p) (p - '0')
149
+ #define MAX(p,q) ((p >= q) ? p : q)
150
+ #define MIN(p,q) ((p <= q) ? p : q)
151
+
152
+ static int dopr (char *buffer, size_t maxlen, const char *format, va_list args)
153
+ {
154
+ char ch;
155
+ long value;
156
+ LDOUBLE fvalue;
157
+ char *strvalue;
158
+ int min;
159
+ int max;
160
+ int state;
161
+ int flags;
162
+ int cflags;
163
+ int total;
164
+ size_t currlen;
165
+
166
+ state = DP_S_DEFAULT;
167
+ currlen = flags = cflags = min = 0;
168
+ max = -1;
169
+ ch = *format++;
170
+ total = 0;
171
+
172
+ while (state != DP_S_DONE)
173
+ {
174
+ if (ch == '\0')
175
+ state = DP_S_DONE;
176
+
177
+ switch(state)
178
+ {
179
+ case DP_S_DEFAULT:
180
+ if (ch == '%')
181
+ state = DP_S_FLAGS;
182
+ else
183
+ total += dopr_outch (buffer, &currlen, maxlen, ch);
184
+ ch = *format++;
185
+ break;
186
+ case DP_S_FLAGS:
187
+ switch (ch)
188
+ {
189
+ case '-':
190
+ flags |= DP_F_MINUS;
191
+ ch = *format++;
192
+ break;
193
+ case '+':
194
+ flags |= DP_F_PLUS;
195
+ ch = *format++;
196
+ break;
197
+ case ' ':
198
+ flags |= DP_F_SPACE;
199
+ ch = *format++;
200
+ break;
201
+ case '#':
202
+ flags |= DP_F_NUM;
203
+ ch = *format++;
204
+ break;
205
+ case '0':
206
+ flags |= DP_F_ZERO;
207
+ ch = *format++;
208
+ break;
209
+ default:
210
+ state = DP_S_MIN;
211
+ break;
212
+ }
213
+ break;
214
+ case DP_S_MIN:
215
+ if (isdigit(ch))
216
+ {
217
+ min = 10*min + char_to_int (ch);
218
+ ch = *format++;
219
+ }
220
+ else if (ch == '*')
221
+ {
222
+ min = va_arg (args, int);
223
+ ch = *format++;
224
+ state = DP_S_DOT;
225
+ }
226
+ else
227
+ state = DP_S_DOT;
228
+ break;
229
+ case DP_S_DOT:
230
+ if (ch == '.')
231
+ {
232
+ state = DP_S_MAX;
233
+ ch = *format++;
234
+ }
235
+ else
236
+ state = DP_S_MOD;
237
+ break;
238
+ case DP_S_MAX:
239
+ if (isdigit(ch))
240
+ {
241
+ if (max < 0)
242
+ max = 0;
243
+ max = 10*max + char_to_int (ch);
244
+ ch = *format++;
245
+ }
246
+ else if (ch == '*')
247
+ {
248
+ max = va_arg (args, int);
249
+ ch = *format++;
250
+ state = DP_S_MOD;
251
+ }
252
+ else
253
+ state = DP_S_MOD;
254
+ break;
255
+ case DP_S_MOD:
256
+ /* Currently, we don't support Long Long, bummer */
257
+ switch (ch)
258
+ {
259
+ case 'h':
260
+ cflags = DP_C_SHORT;
261
+ ch = *format++;
262
+ break;
263
+ case 'l':
264
+ cflags = DP_C_LONG;
265
+ ch = *format++;
266
+ break;
267
+ case 'L':
268
+ cflags = DP_C_LDOUBLE;
269
+ ch = *format++;
270
+ break;
271
+ default:
272
+ break;
273
+ }
274
+ state = DP_S_CONV;
275
+ break;
276
+ case DP_S_CONV:
277
+ switch (ch)
278
+ {
279
+ case 'd':
280
+ case 'i':
281
+ if (cflags == DP_C_SHORT)
282
+ value = va_arg (args, int);
283
+ else if (cflags == DP_C_LONG)
284
+ value = va_arg (args, long int);
285
+ else
286
+ value = va_arg (args, int);
287
+ total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
288
+ break;
289
+ case 'o':
290
+ flags |= DP_F_UNSIGNED;
291
+ if (cflags == DP_C_SHORT)
292
+ value = va_arg (args, int);
293
+ else if (cflags == DP_C_LONG)
294
+ value = va_arg (args, unsigned long int);
295
+ else
296
+ value = va_arg (args, unsigned int);
297
+ total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
298
+ break;
299
+ case 'u':
300
+ flags |= DP_F_UNSIGNED;
301
+ if (cflags == DP_C_SHORT)
302
+ value = va_arg (args, int);
303
+ else if (cflags == DP_C_LONG)
304
+ value = va_arg (args, unsigned long int);
305
+ else
306
+ value = va_arg (args, unsigned int);
307
+ total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
308
+ break;
309
+ case 'X':
310
+ flags |= DP_F_UP;
311
+ case 'x':
312
+ flags |= DP_F_UNSIGNED;
313
+ if (cflags == DP_C_SHORT)
314
+ value = va_arg (args, int);
315
+ else if (cflags == DP_C_LONG)
316
+ value = va_arg (args, unsigned long int);
317
+ else
318
+ value = va_arg (args, unsigned int);
319
+ total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
320
+ break;
321
+ case 'f':
322
+ if (cflags == DP_C_LDOUBLE)
323
+ fvalue = va_arg (args, LDOUBLE);
324
+ else
325
+ fvalue = va_arg (args, double);
326
+ /* um, floating point? */
327
+ total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
328
+ break;
329
+ case 'E':
330
+ flags |= DP_F_UP;
331
+ case 'e':
332
+ if (cflags == DP_C_LDOUBLE)
333
+ fvalue = va_arg (args, LDOUBLE);
334
+ else
335
+ fvalue = va_arg (args, double);
336
+ break;
337
+ case 'G':
338
+ flags |= DP_F_UP;
339
+ case 'g':
340
+ if (cflags == DP_C_LDOUBLE)
341
+ fvalue = va_arg (args, LDOUBLE);
342
+ else
343
+ fvalue = va_arg (args, double);
344
+ break;
345
+ case 'c':
346
+ total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
347
+ break;
348
+ case 's':
349
+ strvalue = va_arg (args, char *);
350
+ total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
351
+ break;
352
+ case 'p':
353
+ strvalue = va_arg (args, void *);
354
+ total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min,
355
+ max, flags);
356
+ break;
357
+ case 'n':
358
+ if (cflags == DP_C_SHORT)
359
+ {
360
+ short int *num;
361
+ num = va_arg (args, short int *);
362
+ *num = currlen;
363
+ }
364
+ else if (cflags == DP_C_LONG)
365
+ {
366
+ long int *num;
367
+ num = va_arg (args, long int *);
368
+ *num = currlen;
369
+ }
370
+ else
371
+ {
372
+ int *num;
373
+ num = va_arg (args, int *);
374
+ *num = currlen;
375
+ }
376
+ break;
377
+ case '%':
378
+ total += dopr_outch (buffer, &currlen, maxlen, ch);
379
+ break;
380
+ case 'w':
381
+ /* not supported yet, treat as next char */
382
+ ch = *format++;
383
+ break;
384
+ default:
385
+ /* Unknown, skip */
386
+ break;
387
+ }
388
+ ch = *format++;
389
+ state = DP_S_DEFAULT;
390
+ flags = cflags = min = 0;
391
+ max = -1;
392
+ break;
393
+ case DP_S_DONE:
394
+ break;
395
+ default:
396
+ /* hmm? */
397
+ break; /* some picky compilers need this */
398
+ }
399
+ }
400
+ if (buffer != NULL)
401
+ {
402
+ if (currlen < maxlen - 1)
403
+ buffer[currlen] = '\0';
404
+ else
405
+ buffer[maxlen - 1] = '\0';
406
+ }
407
+ return total;
408
+ }
409
+
410
+ static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
411
+ char *value, int flags, int min, int max)
412
+ {
413
+ int padlen, strln; /* amount to pad */
414
+ int cnt = 0;
415
+ int total = 0;
416
+
417
+ if (value == 0)
418
+ {
419
+ value = "<NULL>";
420
+ }
421
+
422
+ for (strln = 0; value[strln]; ++strln); /* strlen */
423
+ if (max >= 0 && max < strln)
424
+ strln = max;
425
+ padlen = min - strln;
426
+ if (padlen < 0)
427
+ padlen = 0;
428
+ if (flags & DP_F_MINUS)
429
+ padlen = -padlen; /* Left Justify */
430
+
431
+ while (padlen > 0)
432
+ {
433
+ total += dopr_outch (buffer, currlen, maxlen, ' ');
434
+ --padlen;
435
+ }
436
+ while (*value && ((max < 0) || (cnt < max)))
437
+ {
438
+ total += dopr_outch (buffer, currlen, maxlen, *value++);
439
+ ++cnt;
440
+ }
441
+ while (padlen < 0)
442
+ {
443
+ total += dopr_outch (buffer, currlen, maxlen, ' ');
444
+ ++padlen;
445
+ }
446
+ return total;
447
+ }
448
+
449
+ /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
450
+
451
+ static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
452
+ long value, int base, int min, int max, int flags)
453
+ {
454
+ int signvalue = 0;
455
+ unsigned long uvalue;
456
+ char convert[20];
457
+ int place = 0;
458
+ int spadlen = 0; /* amount to space pad */
459
+ int zpadlen = 0; /* amount to zero pad */
460
+ int caps = 0;
461
+ int total = 0;
462
+
463
+ if (max < 0)
464
+ max = 0;
465
+
466
+ uvalue = value;
467
+
468
+ if(!(flags & DP_F_UNSIGNED))
469
+ {
470
+ if( value < 0 ) {
471
+ signvalue = '-';
472
+ uvalue = -value;
473
+ }
474
+ else
475
+ if (flags & DP_F_PLUS) /* Do a sign (+/i) */
476
+ signvalue = '+';
477
+ else
478
+ if (flags & DP_F_SPACE)
479
+ signvalue = ' ';
480
+ }
481
+
482
+ if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
483
+
484
+ do {
485
+ convert[place++] =
486
+ (caps? "0123456789ABCDEF":"0123456789abcdef")
487
+ [uvalue % (unsigned)base ];
488
+ uvalue = (uvalue / (unsigned)base );
489
+ } while(uvalue && (place < 20));
490
+ if (place == 20) place--;
491
+ convert[place] = 0;
492
+
493
+ zpadlen = max - place;
494
+ spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
495
+ if (zpadlen < 0) zpadlen = 0;
496
+ if (spadlen < 0) spadlen = 0;
497
+ if (flags & DP_F_ZERO)
498
+ {
499
+ zpadlen = MAX(zpadlen, spadlen);
500
+ spadlen = 0;
501
+ }
502
+ if (flags & DP_F_MINUS)
503
+ spadlen = -spadlen; /* Left Justifty */
504
+
505
+ #ifdef DEBUG_SNPRINTF
506
+ dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
507
+ zpadlen, spadlen, min, max, place));
508
+ #endif
509
+
510
+ /* Spaces */
511
+ while (spadlen > 0)
512
+ {
513
+ total += dopr_outch (buffer, currlen, maxlen, ' ');
514
+ --spadlen;
515
+ }
516
+
517
+ /* Sign */
518
+ if (signvalue)
519
+ total += dopr_outch (buffer, currlen, maxlen, signvalue);
520
+
521
+ /* Zeros */
522
+ if (zpadlen > 0)
523
+ {
524
+ while (zpadlen > 0)
525
+ {
526
+ total += dopr_outch (buffer, currlen, maxlen, '0');
527
+ --zpadlen;
528
+ }
529
+ }
530
+
531
+ /* Digits */
532
+ while (place > 0)
533
+ total += dopr_outch (buffer, currlen, maxlen, convert[--place]);
534
+
535
+ /* Left Justified spaces */
536
+ while (spadlen < 0) {
537
+ total += dopr_outch (buffer, currlen, maxlen, ' ');
538
+ ++spadlen;
539
+ }
540
+
541
+ return total;
542
+ }
543
+
544
+ static LDOUBLE abs_val (LDOUBLE value)
545
+ {
546
+ LDOUBLE result = value;
547
+
548
+ if (value < 0)
549
+ result = -value;
550
+
551
+ return result;
552
+ }
553
+
554
+ static LDOUBLE _snp_pow10 (int exp)
555
+ {
556
+ LDOUBLE result = 1;
557
+
558
+ while (exp)
559
+ {
560
+ result *= 10;
561
+ exp--;
562
+ }
563
+
564
+ return result;
565
+ }
566
+
567
+ static long _snp_round (LDOUBLE value)
568
+ {
569
+ long intpart;
570
+
571
+ intpart = value;
572
+ value = value - intpart;
573
+ if (value >= 0.5)
574
+ intpart++;
575
+
576
+ return intpart;
577
+ }
578
+
579
+ static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
580
+ LDOUBLE fvalue, int min, int max, int flags)
581
+ {
582
+ int signvalue = 0;
583
+ LDOUBLE ufvalue;
584
+ char iconvert[20];
585
+ char fconvert[20];
586
+ int iplace = 0;
587
+ int fplace = 0;
588
+ int padlen = 0; /* amount to pad */
589
+ int zpadlen = 0;
590
+ int caps = 0;
591
+ int total = 0;
592
+ long intpart;
593
+ long fracpart;
594
+
595
+ /*
596
+ * AIX manpage says the default is 0, but Solaris says the default
597
+ * is 6, and sprintf on AIX defaults to 6
598
+ */
599
+ if (max < 0)
600
+ max = 6;
601
+
602
+ ufvalue = abs_val (fvalue);
603
+
604
+ if (fvalue < 0)
605
+ signvalue = '-';
606
+ else
607
+ if (flags & DP_F_PLUS) /* Do a sign (+/i) */
608
+ signvalue = '+';
609
+ else
610
+ if (flags & DP_F_SPACE)
611
+ signvalue = ' ';
612
+
613
+ #if 0
614
+ if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
615
+ #endif
616
+
617
+ intpart = ufvalue;
618
+
619
+ /*
620
+ * Sorry, we only support 9 digits past the decimal because of our
621
+ * conversion method
622
+ */
623
+ if (max > 9)
624
+ max = 9;
625
+
626
+ /* We "cheat" by converting the fractional part to integer by
627
+ * multiplying by a factor of 10
628
+ */
629
+ fracpart = _snp_round ((_snp_pow10 (max)) * (ufvalue - intpart));
630
+
631
+ if (fracpart >= _snp_pow10 (max))
632
+ {
633
+ intpart++;
634
+ fracpart -= _snp_pow10 (max);
635
+ }
636
+
637
+ #ifdef DEBUG_SNPRINTF
638
+ dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
639
+ #endif
640
+
641
+ /* Convert integer part */
642
+ do {
643
+ iconvert[iplace++] =
644
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
645
+ intpart = (intpart / 10);
646
+ } while(intpart && (iplace < 20));
647
+ if (iplace == 20) iplace--;
648
+ iconvert[iplace] = 0;
649
+
650
+ /* Convert fractional part */
651
+ do {
652
+ fconvert[fplace++] =
653
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
654
+ fracpart = (fracpart / 10);
655
+ } while(fracpart && (fplace < 20));
656
+ if (fplace == 20) fplace--;
657
+ fconvert[fplace] = 0;
658
+
659
+ /* -1 for decimal point, another -1 if we are printing a sign */
660
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
661
+ zpadlen = max - fplace;
662
+ if (zpadlen < 0)
663
+ zpadlen = 0;
664
+ if (padlen < 0)
665
+ padlen = 0;
666
+ if (flags & DP_F_MINUS)
667
+ padlen = -padlen; /* Left Justifty */
668
+
669
+ if ((flags & DP_F_ZERO) && (padlen > 0))
670
+ {
671
+ if (signvalue)
672
+ {
673
+ total += dopr_outch (buffer, currlen, maxlen, signvalue);
674
+ --padlen;
675
+ signvalue = 0;
676
+ }
677
+ while (padlen > 0)
678
+ {
679
+ total += dopr_outch (buffer, currlen, maxlen, '0');
680
+ --padlen;
681
+ }
682
+ }
683
+ while (padlen > 0)
684
+ {
685
+ total += dopr_outch (buffer, currlen, maxlen, ' ');
686
+ --padlen;
687
+ }
688
+ if (signvalue)
689
+ total += dopr_outch (buffer, currlen, maxlen, signvalue);
690
+
691
+ while (iplace > 0)
692
+ total += dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
693
+
694
+ /*
695
+ * Decimal point. This should probably use locale to find the correct
696
+ * char to print out.
697
+ */
698
+ if (max > 0)
699
+ {
700
+ total += dopr_outch (buffer, currlen, maxlen, '.');
701
+
702
+ while (fplace > 0)
703
+ total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
704
+ }
705
+
706
+ while (zpadlen > 0)
707
+ {
708
+ total += dopr_outch (buffer, currlen, maxlen, '0');
709
+ --zpadlen;
710
+ }
711
+
712
+ while (padlen < 0)
713
+ {
714
+ total += dopr_outch (buffer, currlen, maxlen, ' ');
715
+ ++padlen;
716
+ }
717
+
718
+ return total;
719
+ }
720
+
721
+ static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
722
+ {
723
+ if (*currlen + 1 < maxlen)
724
+ buffer[(*currlen)++] = c;
725
+ return 1;
726
+ }
727
+
728
+ #ifndef HAVE_VSNPRINTF
729
+ int xmpp_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
730
+ {
731
+ if (str != NULL)
732
+ str[0] = 0;
733
+ return dopr(str, count, fmt, args);
734
+ }
735
+ #endif /* !HAVE_VSNPRINTF */
736
+
737
+ #ifndef HAVE_SNPRINTF
738
+ /* VARARGS3 */
739
+ #ifdef HAVE_STDARGS
740
+ int xmpp_snprintf (char *str,size_t count,const char *fmt,...)
741
+ #else
742
+ int xmpp_snprintf (va_alist) va_dcl
743
+ #endif
744
+ {
745
+ #ifndef HAVE_STDARGS
746
+ char *str;
747
+ size_t count;
748
+ char *fmt;
749
+ #endif
750
+ VA_LOCAL_DECL;
751
+ int total;
752
+
753
+ VA_START (fmt);
754
+ VA_SHIFT (str, char *);
755
+ VA_SHIFT (count, size_t );
756
+ VA_SHIFT (fmt, char *);
757
+ total = xmpp_vsnprintf(str, count, fmt, ap);
758
+ VA_END;
759
+ return total;
760
+ }
761
+ #endif /* !HAVE_SNPRINTF */
762
+
763
+ #ifdef TEST_SNPRINTF
764
+ #ifndef LONG_STRING
765
+ #define LONG_STRING 1024
766
+ #endif
767
+ int main (void)
768
+ {
769
+ char buf1[LONG_STRING];
770
+ char buf2[LONG_STRING];
771
+ char *fp_fmt[] = {
772
+ "%-1.5f",
773
+ "%1.5f",
774
+ "%123.9f",
775
+ "%10.5f",
776
+ "% 10.5f",
777
+ "%+22.9f",
778
+ "%+4.9f",
779
+ "%01.3f",
780
+ "%4f",
781
+ "%3.1f",
782
+ "%3.2f",
783
+ "%.0f",
784
+ "%.1f",
785
+ NULL
786
+ };
787
+ double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
788
+ 0.9996, 1.996, 4.136, 0};
789
+ char *int_fmt[] = {
790
+ "%-1.5d",
791
+ "%1.5d",
792
+ "%123.9d",
793
+ "%5.5d",
794
+ "%10.5d",
795
+ "% 10.5d",
796
+ "%+22.33d",
797
+ "%01.3d",
798
+ "%4d",
799
+ NULL
800
+ };
801
+ long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
802
+ int x, y;
803
+ int fail = 0;
804
+ int num = 0;
805
+
806
+ printf ("Testing xmpp_snprintf format codes against system sprintf...\n");
807
+
808
+ for (x = 0; fp_fmt[x] != NULL ; x++)
809
+ for (y = 0; fp_nums[y] != 0 ; y++)
810
+ {
811
+ xmpp_snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
812
+ sprintf (buf2, fp_fmt[x], fp_nums[y]);
813
+ if (strcmp (buf1, buf2))
814
+ {
815
+ printf("xmpp_snprintf doesn't match Format: %s\n\txmpp_snprintf = %s\n\tsprintf = %s\n",
816
+ fp_fmt[x], buf1, buf2);
817
+ fail++;
818
+ }
819
+ num++;
820
+ }
821
+
822
+ for (x = 0; int_fmt[x] != NULL ; x++)
823
+ for (y = 0; int_nums[y] != 0 ; y++)
824
+ {
825
+ xmpp_snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
826
+ sprintf (buf2, int_fmt[x], int_nums[y]);
827
+ if (strcmp (buf1, buf2))
828
+ {
829
+ printf("xmpp_snprintf doesn't match Format: %s\n\txmpp_snprintf = %s\n\tsprintf = %s\n",
830
+ int_fmt[x], buf1, buf2);
831
+ fail++;
832
+ }
833
+ num++;
834
+ }
835
+ printf ("%d tests failed out of %d.\n", fail, num);
836
+ }
837
+ #endif /* SNPRINTF_TEST */
838
+
839
+ #endif /* !HAVE_SNPRINTF */