]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bsnprintf.c
kes If doing a mount, look for a slot, and if specified pass it to
[bacula/bacula] / bacula / src / lib / bsnprintf.c
1 /*
2  * Copyright Patrick Powell 1995
3  *
4  * This code is based on code written by Patrick Powell
5  * (papowell@astart.com) It may be used for any purpose as long
6  * as this notice remains intact on all source code distributions.
7  *
8  * Adapted for Bacula -- note there were lots of bugs in
9  *     the original code: %lld and %s were seriously broken, and
10  *     with FP turned off %f seg faulted.
11  *
12  *   Kern Sibbald, November MMV
13  *
14  *   Version $Id$
15  */
16
17
18 #include "bacula.h"
19 #define FP_OUTPUT 1 /* Bacula uses floating point */
20 /* Define the following if you want all the features of
21  *  normal printf, but with all the security problems.
22  *  For Bacula we turn this off, and it silently ignores
23  *  formats that could pose a security problem.
24  */
25 #undef SECURITY_PROBLEM 
26
27 #ifdef USE_BSNPRINTF
28
29 #ifdef HAVE_LONG_DOUBLE
30 #define LDOUBLE long double
31 #else
32 #define LDOUBLE double
33 #endif
34
35 int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args);
36 static int32_t fmtstr(char *buffer, int32_t currlen, int32_t maxlen,
37                    char *value, int flags, int min, int max);
38 static int32_t fmtint(char *buffer, int32_t currlen, int32_t maxlen,
39                    int64_t value, int base, int min, int max, int flags);
40
41 #ifdef FP_OUTPUT
42 # ifdef HAVE_FCVTL
43 #  define fcvt fcvtl
44 # endif
45 static int32_t fmtfp(char *buffer, int32_t currlen, int32_t maxlen,
46                   LDOUBLE fvalue, int min, int max, int flags);
47 #else
48 #define fmtfp(b, c, m, f, min, max, fl) currlen
49 #endif
50
51 #define outch(c) {int len=currlen; if (currlen++ < maxlen) { buffer[len] = (c);}}
52
53
54 /* format read states */
55 #define DP_S_DEFAULT 0
56 #define DP_S_FLAGS   1
57 #define DP_S_MIN     2
58 #define DP_S_DOT     3
59 #define DP_S_MAX     4
60 #define DP_S_MOD     5
61 #define DP_S_CONV    6
62 #define DP_S_DONE    7
63
64 /* format flags - Bits */
65 #define DP_F_MINUS      (1 << 0)
66 #define DP_F_PLUS       (1 << 1)
67 #define DP_F_SPACE      (1 << 2)
68 #define DP_F_NUM        (1 << 3)
69 #define DP_F_ZERO       (1 << 4)
70 #define DP_F_UP         (1 << 5)
71 #define DP_F_UNSIGNED   (1 << 6)
72 #define DP_F_DOT        (1 << 7)
73
74 /* Conversion Flags */
75 #define DP_C_INT16   1
76 #define DP_C_INT32    2
77 #define DP_C_LDOUBLE 3
78 #define DP_C_INT64   4
79
80 #define char_to_int(p) ((p)- '0')
81 #undef MAX
82 #define MAX(p,q) (((p) >= (q)) ? (p) : (q))
83
84 /*
85   You might ask why does Bacula have it's own printf routine? Well,
86   There are two reasons: 1. Here (as opposed to library routines), we
87   define %d and %ld to be 32 bit; %lld and %q to be 64 bit.  2. We 
88   disable %n for security reasons.                
89  */
90
91 int bsnprintf(char *str, int32_t size, const char *fmt,  ...)
92 {
93    va_list   arg_ptr;
94    int len;
95
96    va_start(arg_ptr, fmt);
97    len = bvsnprintf(str, size, fmt, arg_ptr);
98    va_end(arg_ptr);
99    return len;
100 }
101
102
103 int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args)
104 {
105    char ch;
106    int64_t value;
107    char *strvalue;
108    int min;
109    int max;
110    int state;
111    int flags;
112    int cflags;
113    int32_t currlen;
114    int base;
115 #ifdef FP_OUTPUT
116    LDOUBLE fvalue;
117 #endif
118
119    state = DP_S_DEFAULT;
120    currlen = flags = cflags = min = 0;
121    max = -1;
122    ch = *format++;
123    *buffer = 0;
124
125    while (state != DP_S_DONE) {
126       if ((ch == '\0') || (currlen >= maxlen))
127          state = DP_S_DONE;
128
129       switch (state) {
130       case DP_S_DEFAULT:
131          if (ch == '%') {
132             state = DP_S_FLAGS;
133          } else {
134             outch(ch);
135          }
136          ch = *format++;
137          break;
138       case DP_S_FLAGS:
139          switch (ch) {
140          case '-':
141             flags |= DP_F_MINUS;
142             ch = *format++;
143             break;
144          case '+':
145             flags |= DP_F_PLUS;
146             ch = *format++;
147             break;
148          case ' ':
149             flags |= DP_F_SPACE;
150             ch = *format++;
151             break;
152          case '#':
153             flags |= DP_F_NUM;
154             ch = *format++;
155             break;
156          case '0':
157             flags |= DP_F_ZERO;
158             ch = *format++;
159             break;
160          default:
161             state = DP_S_MIN;
162             break;
163          }
164          break;
165       case DP_S_MIN:
166          if (isdigit((unsigned char)ch)) {
167             min = 10 * min + char_to_int(ch);
168             ch = *format++;
169          } else if (ch == '*') {
170             min = va_arg(args, int);
171             ch = *format++;
172             state = DP_S_DOT;
173          } else
174             state = DP_S_DOT;
175          break;
176       case DP_S_DOT:
177          if (ch == '.') {
178             state = DP_S_MAX;
179             flags |= DP_F_DOT;
180             ch = *format++;
181          } else
182             state = DP_S_MOD;
183          break;
184       case DP_S_MAX:
185          if (isdigit((unsigned char)ch)) {
186             if (max < 0)
187                max = 0;
188             max = 10 * max + char_to_int(ch);
189             ch = *format++;
190          } else if (ch == '*') {
191             max = va_arg(args, int);
192             ch = *format++;
193             state = DP_S_MOD;
194          } else
195             state = DP_S_MOD;
196          break;
197       case DP_S_MOD:
198          switch (ch) {
199          case 'h':
200             cflags = DP_C_INT16;
201             ch = *format++;
202             break;
203          case 'l':
204             cflags = DP_C_INT32;
205             ch = *format++;
206             if (ch == 'l') {       /* It's a long long */
207                cflags = DP_C_INT64;
208                ch = *format++;
209             }
210             break;
211          case 'L':
212             cflags = DP_C_LDOUBLE;
213             ch = *format++;
214             break;
215          case 'q':                 /* same as long long */
216             cflags = DP_C_INT64;
217             ch = *format++;
218             break;
219          default:
220             break;
221          }
222          state = DP_S_CONV;
223          break;
224       case DP_S_CONV:
225          switch (ch) {
226          case 'd':
227          case 'i':
228             if (cflags == DP_C_INT16) {
229                value = va_arg(args, int32_t);
230             } else if (cflags == DP_C_INT32) {
231                value = va_arg(args, int32_t);
232             } else if (cflags == DP_C_INT64) {
233                value = va_arg(args, int64_t);
234             } else {
235                value = va_arg(args, int);
236             }
237             currlen = fmtint(buffer, currlen, maxlen, value, 10, min, max, flags);
238             break;
239          case 'X':
240          case 'x':
241          case 'o':
242          case 'u':
243             if (ch == 'o') {
244                base = 8;
245             } else if (ch == 'x') {
246                base = 16;
247             } else if (ch == 'X') {
248                base = 16;
249                flags |= DP_F_UP;
250             } else {
251                base = 10;
252             }
253             flags |= DP_F_UNSIGNED;
254             if (cflags == DP_C_INT16) {
255                value = va_arg(args, uint32_t);
256             } else if (cflags == DP_C_INT32) {
257                value = (long)va_arg(args, uint32_t);
258             } else if (cflags == DP_C_INT64) {
259                value = (int64_t) va_arg(args, uint64_t);
260             } else {
261                value = (long)va_arg(args, unsigned int);
262             }
263             currlen = fmtint(buffer, currlen, maxlen, value, base, min, max, flags);
264             break;
265          case 'f':
266             if (cflags == DP_C_LDOUBLE) {
267                fvalue = va_arg(args, LDOUBLE);
268             } else {
269                fvalue = va_arg(args, double);
270             }
271             currlen = fmtfp(buffer, currlen, maxlen, fvalue, min, max, flags);
272             break;
273          case 'E':
274             flags |= DP_F_UP;
275          case 'e':
276             if (cflags == DP_C_LDOUBLE) {
277                fvalue = va_arg(args, LDOUBLE);
278             } else {
279                fvalue = va_arg(args, double);
280             }
281             currlen = fmtfp(buffer, currlen, maxlen, fvalue, min, max, flags);
282             break;
283          case 'G':
284             flags |= DP_F_UP;
285          case 'g':
286             if (cflags == DP_C_LDOUBLE) {
287                fvalue = va_arg(args, LDOUBLE);
288             } else {
289                fvalue = va_arg(args, double);
290             }
291             currlen = fmtfp(buffer, currlen, maxlen, fvalue, min, max, flags);
292             break;
293          case 'c':
294             outch(va_arg(args, int));
295             break;
296          case 's':
297             strvalue = va_arg(args, char *);
298             currlen = fmtstr(buffer, currlen, maxlen, strvalue, flags, min, max);
299             break;
300          case 'p':
301             strvalue = va_arg(args, char *);
302             currlen = fmtint(buffer, currlen, maxlen, (long)strvalue, 16, min, max, flags);
303             break;
304          case 'n':
305             if (cflags == DP_C_INT16) {
306                int16_t *num;
307                num = va_arg(args, int16_t *);
308 #ifdef SECURITY_PROBLEM
309                *num = currlen;
310 #endif
311             } else if (cflags == DP_C_INT32) {
312                int32_t *num;
313                num = va_arg(args, int32_t *);
314 #ifdef SECURITY_PROBLEM
315                *num = (int32_t)currlen;
316 #endif
317             } else if (cflags == DP_C_INT64) {
318                int64_t *num;
319                num = va_arg(args, int64_t *);
320 #ifdef SECURITY_PROBLEM
321                *num = (int64_t)currlen;
322 #endif
323             } else {
324                int32_t *num;
325                num = va_arg(args, int32_t *);
326 #ifdef SECURITY_PROBLEM
327                *num = (int32_t)currlen;
328 #endif
329             }
330             break;
331          case '%':
332             outch(ch);
333             break;
334          case 'w':
335             /* not supported yet, treat as next char */
336             ch = *format++;
337             break;
338          default:
339             /* Unknown, skip */
340             break;
341          }
342          ch = *format++;
343          state = DP_S_DEFAULT;
344          flags = cflags = min = 0;
345          max = -1;
346          break;
347       case DP_S_DONE:
348          break;
349       default:
350          /* hmm? */
351          break;                    /* some picky compilers need this */
352       }
353    }
354    if (currlen < maxlen - 1) {
355       buffer[currlen] = '\0';
356    } else {
357       buffer[maxlen - 1] = '\0';
358    }
359    return currlen;
360 }
361
362 static int32_t fmtstr(char *buffer, int32_t currlen, int32_t maxlen,
363                    char *value, int flags, int min, int max)
364 {
365    int padlen, strln;              /* amount to pad */
366    int cnt = 0;
367
368    if (value == 0) {
369       value = "<NULL>";
370    }
371
372    if (flags & DP_F_DOT && max < 0) {   /* Max not specified */
373       max = 0;
374    } else if (max < 0) {
375       max = maxlen;
376    }
377    strln = strlen(value);
378    if (strln > max) {
379       strln = max;                /* truncate to max */
380    }
381    padlen = min - strln;
382    if (padlen < 0) {
383       padlen = 0;
384    }
385    if (flags & DP_F_MINUS) {
386       padlen = -padlen;            /* Left Justify */
387    }
388
389    while (padlen > 0) {
390       outch(' ');
391       --padlen;
392    }
393    while (*value && (cnt < max)) {
394       outch(*value++);
395       ++cnt;
396    }
397    while (padlen < 0) {
398       outch(' ');
399       ++padlen;
400    }
401    return currlen;
402 }
403
404 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
405
406 static int32_t fmtint(char *buffer, int32_t currlen, int32_t maxlen,
407                    int64_t value, int base, int min, int max, int flags)
408 {
409    int signvalue = 0;
410    uint64_t uvalue;
411    char convert[20];
412    int place = 0;
413    int spadlen = 0;                /* amount to space pad */
414    int zpadlen = 0;                /* amount to zero pad */
415    int caps = 0;
416
417    if (max < 0) {
418       max = 0;
419    }
420
421    uvalue = value;
422
423    if (!(flags & DP_F_UNSIGNED)) {
424       if (value < 0) {
425          signvalue = '-';
426          uvalue = -value;
427       } else if (flags & DP_F_PLUS) {  /* Do a sign (+/i) */
428          signvalue = '+';
429       } else if (flags & DP_F_SPACE) {
430          signvalue = ' ';
431       }
432    }
433
434    if (flags & DP_F_UP) {
435       caps = 1;                    /* Should characters be upper case? */
436    }
437
438    do {
439       convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
440          [uvalue % (unsigned)base];
441       uvalue = (uvalue / (unsigned)base);
442    } while (uvalue && (place < 20));
443    if (place == 20) {
444       place--;
445    }
446    convert[place] = 0;
447
448    zpadlen = max - place;
449    spadlen = min - MAX(max, place) - (signvalue ? 1 : 0);
450    if (zpadlen < 0)
451       zpadlen = 0;
452    if (spadlen < 0)
453       spadlen = 0;
454    if (flags & DP_F_ZERO) {
455       zpadlen = MAX(zpadlen, spadlen);
456       spadlen = 0;
457    }
458    if (flags & DP_F_MINUS)
459       spadlen = -spadlen;          /* Left Justifty */
460
461 #ifdef DEBUG_SNPRINTF
462    printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
463           zpadlen, spadlen, min, max, place);
464 #endif
465
466    /* Spaces */
467    while (spadlen > 0) {
468       outch(' ');
469       --spadlen;
470    }
471
472    /* Sign */
473    if (signvalue) {
474       outch(signvalue);
475    }
476
477    /* Zeros */
478    if (zpadlen > 0) {
479       while (zpadlen > 0) {
480          outch('0');
481          --zpadlen;
482       }
483    }
484
485    /* Digits */
486    while (place > 0) {
487       outch(convert[--place]);
488    }
489
490    /* Left Justified spaces */
491    while (spadlen < 0) {
492       outch(' ');
493       ++spadlen;
494    }
495    return currlen;
496 }
497
498 #ifdef FP_OUTPUT
499
500 static LDOUBLE abs_val(LDOUBLE value)
501 {
502    LDOUBLE result = value;
503
504    if (value < 0)
505       result = -value;
506
507    return result;
508 }
509
510 static LDOUBLE pow10(int exp)
511 {
512    LDOUBLE result = 1;
513
514    while (exp) {
515       result *= 10;
516       exp--;
517    }
518
519    return result;
520 }
521
522 static long round(LDOUBLE value)
523 {
524    long intpart;
525
526    intpart = (long)value;
527    value = value - intpart;
528    if (value >= 0.5)
529       intpart++;
530
531    return intpart;
532 }
533
534 static int32_t fmtfp(char *buffer, int32_t currlen, int32_t maxlen,
535                   LDOUBLE fvalue, int min, int max, int flags)
536 {
537    int signvalue = 0;
538    LDOUBLE ufvalue;
539 #ifndef HAVE_FCVT
540    char iconvert[20];
541    char fconvert[20];
542 #else
543    char iconvert[311];
544    char fconvert[311];
545    char *result;
546    int dec_pt, sig;
547    int r_length;
548    extern char *fcvt(double value, int ndigit, int *decpt, int *sign);
549 #endif
550    int iplace = 0;
551    int fplace = 0;
552    int padlen = 0;                 /* amount to pad */
553    int zpadlen = 0;
554    int caps = 0;
555    int64_t intpart;
556    int64_t fracpart;
557
558    /* 
559     * AIX manpage says the default is 0, but Solaris says the default
560     * is 6, and sprintf on AIX defaults to 6
561     */
562    if (max < 0)
563       max = 6;
564
565    ufvalue = abs_val(fvalue);
566
567    if (fvalue < 0)
568       signvalue = '-';
569    else if (flags & DP_F_PLUS)     /* Do a sign (+/i) */
570       signvalue = '+';
571    else if (flags & DP_F_SPACE)
572       signvalue = ' ';
573
574 #if 0
575    if (flags & DP_F_UP)
576       caps = 1;                    /* Should characters be upper case? */
577 #endif
578
579 #ifndef HAVE_FCVT
580    intpart = (long)ufvalue;
581
582    /* 
583     * Sorry, we only support 9 digits past the decimal because of our 
584     * conversion method
585     */
586    if (max > 9)
587       max = 9;
588
589    /* We "cheat" by converting the fractional part to integer by
590     * multiplying by a factor of 10
591     */
592    fracpart = round((pow10(max)) * (ufvalue - intpart));
593
594    if (fracpart >= pow10(max)) {
595       intpart++;
596       fracpart -= (int64_t)pow10(max);
597    }
598 #ifdef DEBUG_SNPRINTF
599    printf("fmtfp: %g %d.%d min=%d max=%d\n",
600           (double)fvalue, intpart, fracpart, min, max);
601 #endif
602
603    /* Convert integer part */
604    do {
605       iconvert[iplace++] =
606          (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10];
607       intpart = (intpart / 10);
608    } while (intpart && (iplace < 20));
609    if (iplace == 20)
610       iplace--;
611    iconvert[iplace] = 0;
612
613    /* Convert fractional part */
614    do {
615       fconvert[fplace++] =
616          (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10];
617       fracpart = (fracpart / 10);
618    } while (fracpart && (fplace < 20));
619    if (fplace == 20)
620       fplace--;
621    fconvert[fplace] = 0;
622 #else                              /* use fcvt() */
623    if (max > 310)
624       max = 310;
625 # ifdef HAVE_FCVTL
626    result = fcvtl(ufvalue, max, &dec_pt, &sig);
627 # else
628    result = fcvt(ufvalue, max, &dec_pt, &sig);
629 # endif
630
631    r_length = strlen(result);
632
633    /*
634     * Fix broken fcvt implementation returns..
635     */
636
637    if (r_length == 0) {
638       result[0] = '0';
639       result[1] = '\0';
640       r_length = 1;
641    }
642
643    if (r_length < dec_pt)
644       dec_pt = r_length;
645
646    if (dec_pt <= 0) {
647       iplace = 1;
648       iconvert[0] = '0';
649       iconvert[1] = '\0';
650
651       fplace = 0;
652
653       while (r_length)
654          fconvert[fplace++] = result[--r_length];
655
656       while ((dec_pt < 0) && (fplace < max)) {
657          fconvert[fplace++] = '0';
658          dec_pt++;
659       }
660    } else {
661       int c;
662
663       iplace = 0;
664       for (c = dec_pt; c; iconvert[iplace++] = result[--c]);
665       iconvert[iplace] = '\0';
666
667       result += dec_pt;
668       fplace = 0;
669
670       for (c = (r_length - dec_pt); c; fconvert[fplace++] = result[--c]);
671    }
672 #endif  /* HAVE_FCVT */
673
674    /* -1 for decimal point, another -1 if we are printing a sign */
675    padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
676    zpadlen = max - fplace;
677    if (zpadlen < 0) {
678       zpadlen = 0;
679    }
680    if (padlen < 0) {
681       padlen = 0;
682    }
683    if (flags & DP_F_MINUS) {
684       padlen = -padlen;            /* Left Justifty */
685    }
686
687    if ((flags & DP_F_ZERO) && (padlen > 0)) {
688       if (signvalue) {
689          outch(signvalue);
690          --padlen;
691          signvalue = 0;
692       }
693       while (padlen > 0) {
694          outch('0');
695          --padlen;
696       }
697    }
698    while (padlen > 0) {
699       outch(' ');
700       --padlen;
701    }
702    if (signvalue) {
703       outch(signvalue);
704    }
705
706    while (iplace > 0) {
707       outch(iconvert[--iplace]);
708    }
709
710
711 #ifdef DEBUG_SNPRINTF
712    printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
713 #endif
714
715    /*
716     * Decimal point.  This should probably use locale to find the correct
717     * char to print out.
718     */
719    if (max > 0) {
720       outch('.');
721       while (fplace > 0) {
722          outch(fconvert[--fplace]);
723       }
724    }
725
726    while (zpadlen > 0) {
727       outch('0');
728       --zpadlen;
729    }
730
731    while (padlen < 0) {
732       outch(' ');
733       ++padlen;
734    }
735    return currlen;
736 }
737 #endif  /* FP_OUTPUT */
738
739
740 #ifdef TEST_PROGRAM
741
742 #ifndef LONG_STRING
743 #define LONG_STRING 1024
744 #endif
745 int main(void)
746 {
747    char buf1[LONG_STRING];
748    char buf2[LONG_STRING];
749
750 #ifdef FP_OUTPUT
751    char *fp_fmt[] = {
752       "%-1.5f",
753       "%1.5f",
754       "%123.9f",
755       "%10.5f",
756       "% 10.5f",
757       "%+22.9f",
758       "%+4.9f",
759       "%01.3f",
760       "%4f",
761       "%3.1f",
762       "%3.2f",
763       "%.0f",
764       "%.1f",
765       NULL
766    };
767    double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
768       0.9996, 1.996, 4.136, 6442452944.1234, 0
769    };
770 #endif
771    char *int_fmt[] = {
772       "%-1.5d",
773       "%1.5d",
774       "%123.9d",
775       "%5.5d",
776       "%10.5d",
777       "% 10.5d",
778       "%+22.33d",
779       "%01.3d",
780       "%4d",
781       "%-1.5ld",
782       "%1.5ld",
783       "%123.9ld",
784       "%5.5ld",
785       "%10.5ld",
786       "% 10.5ld",
787       "%+22.33ld",
788       "%01.3ld",
789       "%4ld",
790       NULL
791    };
792    long int_nums[] = { -1, 134, 91340, 341, 0203, 0 };
793
794    char *ll_fmt[] = {
795       "%-1.8lld",
796       "%1.8lld",
797       "%123.9lld",
798       "%5.8lld",
799       "%10.5lld",
800       "% 10.8lld",
801       "%+22.33lld",
802       "%01.3lld",
803       "%4lld",
804       NULL
805    };
806    int64_t ll_nums[] = { -1976, 789134567890LL, 91340, 34123, 0203, 0 };
807
808    char *s_fmt[] = {
809       "%-1.8s",
810       "%1.8s",
811       "%123.9s",
812       "%5.8s",
813       "%10.5s",
814       "% 10.3s",
815       "%+22.1s",
816       "%01.3s",
817       "%s",
818       "%10s",
819       "%3s",
820       "%3.0s",
821       "%3.s",
822       NULL
823    };
824    char *s_nums[] = { "abc", "def", "ghi", "123", "4567", "a", "bb", "ccccccc", NULL};
825
826
827    int x, y;
828    int fail = 0;
829    int num = 0;
830
831    printf("Testing snprintf format codes against system sprintf...\n");
832
833 #ifdef FP_OUTPUT
834    for (x = 0; fp_fmt[x] != NULL; x++)
835       for (y = 0; fp_nums[y] != 0; y++) {
836          bsnprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
837          sprintf(buf2, fp_fmt[x], fp_nums[y]);
838          if (strcmp(buf1, buf2)) {
839             printf
840                ("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
841                 fp_fmt[x], buf1, buf2);
842             fail++;
843          }
844          num++;
845       }
846 #endif
847
848    for (x = 0; int_fmt[x] != NULL; x++)
849       for (y = 0; int_nums[y] != 0; y++) {
850          int pcount, bcount;
851          bcount = bsnprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
852          printf("%s\n", buf1);
853          pcount = sprintf(buf2, int_fmt[x], int_nums[y]);
854          if (bcount != pcount) {
855             printf("bsnprintf count %d doesn't match sprintf count %d\n",
856                bcount, pcount);
857          }
858          if (strcmp(buf1, buf2)) {
859             printf
860                ("bsnprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
861                 int_fmt[x], buf1, buf2);
862             fail++;
863          }
864          num++;
865       }
866
867    for (x = 0; ll_fmt[x] != NULL; x++) {
868       for (y = 0; ll_nums[y] != 0; y++) {
869          int pcount, bcount;
870          bcount = bsnprintf(buf1, sizeof(buf1), ll_fmt[x], ll_nums[y]);
871          printf("%s\n", buf1);
872          pcount = sprintf(buf2, ll_fmt[x], ll_nums[y]);
873          if (bcount != pcount) {
874             printf("bsnprintf count %d doesn't match sprintf count %d\n",
875                bcount, pcount);
876          }
877          if (strcmp(buf1, buf2)) {
878             printf
879                ("bsnprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
880                 ll_fmt[x], buf1, buf2);
881             fail++;
882          }
883          num++;
884       }
885    }
886
887    for (x = 0; s_fmt[x] != NULL; x++) {
888       for (y = 0; s_nums[y] != 0; y++) {
889          int pcount, bcount;
890          bcount = bsnprintf(buf1, sizeof(buf1), s_fmt[x], s_nums[y]);
891          printf("%s\n", buf1);
892          pcount = sprintf(buf2, s_fmt[x], s_nums[y]);
893          if (bcount != pcount) {
894             printf("bsnprintf count %d doesn't match sprintf count %d\n",
895                bcount, pcount);
896          }
897          if (strcmp(buf1, buf2)) {
898             printf
899                ("bsnprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
900                 s_fmt[x], buf1, buf2);
901             fail++;
902          }
903          num++;
904       }
905    }
906
907
908    printf("%d tests failed out of %d.\n", fail, num);
909 }
910 #endif /* TEST_PROGRAM */
911
912 #endif /* USE_BSNPRINTF */