1 /**************************************************************
2  * Original:
3  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
4  * A bombproof version of doprnt (dopr) included.
5  * Sigh.  This sort of thing is always nasty do deal with.  Note that
6  * the version here does not include floating point...
7  *
8  * snprintf() is used instead of sprintf() as it does limit checks
9  * for string length.  This covers a nasty loophole.
10  *
11  * The other functions are there to prevent NULL pointers from
12  * causing nast effects.
13  *
14  * More Recently:
15  *  Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
16  *  This was ugly.  It is still ugly.  I opted out of floating point
17  *  numbers, but the formatter understands just about everything
18  *  from the normal C string format, at least as far as I can tell from
19  *  the Solaris 2.5 printf(3S) man page.
20  *
21  *  Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
22  *    Ok, added some minimal floating point support, which means this
23  *    probably requires libm on most operating systems.  Don't yet
24  *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint()
25  *    was pretty badly broken, it just wasn't being exercised in ways
26  *    which showed it, so that's been fixed.  Also, formated the code
27  *    to mutt conventions, and removed dead code left over from the
28  *    original.  Also, there is now a builtin-test, just compile with:
29  *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
30  *    and run snprintf for results.
31  *
32  *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
33  *    The PGP code was using unsigned hexadecimal formats.
34  *    Unfortunately, unsigned formats simply didn't work.
35  *
36  *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
37  *    The original code assumed that both snprintf() and vsnprintf() were
38  *    missing.  Some systems only have snprintf() but not vsnprintf(), so
39  *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
40  *
41  **************************************************************/
42 
43 #include <config.h>
44 
45 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
46 
47 #include <string.h>
48 # include <ctype.h>
49 #include <sys/types.h>
50 
51 /* varargs declarations: */
52 
53 #if defined(HAVE_STDARG_H)
54 # include <stdarg.h>
55 # define HAVE_STDARGS    /* let's hope that works everywhere (mj) */
56 # define VA_LOCAL_DECL   va_list ap
57 # define VA_START(f)     va_start(ap, f)
58 # define VA_SHIFT(v,t)  ;   /* no-op for ANSI */
59 # define VA_END          va_end(ap)
60 #else
61 # if defined(HAVE_VARARGS_H)
62 #  include <varargs.h>
63 #  undef HAVE_STDARGS
64 #  define VA_LOCAL_DECL   va_list ap
65 #  define VA_START(f)     va_start(ap)      /* f is ignored! */
66 #  define VA_SHIFT(v,t) v = va_arg(ap,t)
67 #  define VA_END        va_end(ap)
68 # else
69 /*XX ** NO VARARGS ** XX*/
70 # endif
71 #endif
72 
73 /*int snprintf (char *str, size_t count, const char *fmt, ...);*/
74 /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/
75 
76 static void dopr (char *buffer, size_t maxlen, const char *format,
77                   va_list args);
78 static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
79 		    char *value, int flags, int min, int max);
80 static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
81 		    long value, int base, int min, int max, int flags);
82 static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
83 		   long double fvalue, int min, int max, int flags);
84 static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
85 
86 /*
87  * dopr(): poor man's version of doprintf
88  */
89 
90 /* format read states */
91 #define DP_S_DEFAULT 0
92 #define DP_S_FLAGS   1
93 #define DP_S_MIN     2
94 #define DP_S_DOT     3
95 #define DP_S_MAX     4
96 #define DP_S_MOD     5
97 #define DP_S_CONV    6
98 #define DP_S_DONE    7
99 
100 /* format flags - Bits */
101 #define DP_F_MINUS 	(1 << 0)
102 #define DP_F_PLUS  	(1 << 1)
103 #define DP_F_SPACE 	(1 << 2)
104 #define DP_F_NUM   	(1 << 3)
105 #define DP_F_ZERO  	(1 << 4)
106 #define DP_F_UP    	(1 << 5)
107 #define DP_F_UNSIGNED 	(1 << 6)
108 
109 /* Conversion Flags */
110 #define DP_C_SHORT   1
111 #define DP_C_LONG    2
112 #define DP_C_LDOUBLE 3
113 
114 #define char_to_int(p) (p - '0')
115 
116 #ifndef MAX
117 #define MAX(p,q) ((p >= q) ? p : q)
118 #endif  /* MAX */
119 
dopr(char * buffer,size_t maxlen,const char * format,va_list args)120 static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
121 {
122   char ch;
123   long value;
124   long double fvalue;
125   char *strvalue;
126   int min;
127   int max;
128   int state;
129   int flags;
130   int cflags;
131   size_t currlen;
132 
133   state = DP_S_DEFAULT;
134   currlen = flags = cflags = min = 0;
135   max = -1;
136   ch = *format++;
137 
138   while (state != DP_S_DONE)
139   {
140     if ((ch == '\0') || (currlen >= maxlen))
141       state = DP_S_DONE;
142 
143     switch(state)
144     {
145     case DP_S_DEFAULT:
146       if (ch == '%')
147 	state = DP_S_FLAGS;
148       else
149 	dopr_outch (buffer, &currlen, maxlen, ch);
150       ch = *format++;
151       break;
152     case DP_S_FLAGS:
153       switch (ch)
154       {
155       case '-':
156 	flags |= DP_F_MINUS;
157         ch = *format++;
158 	break;
159       case '+':
160 	flags |= DP_F_PLUS;
161         ch = *format++;
162 	break;
163       case ' ':
164 	flags |= DP_F_SPACE;
165         ch = *format++;
166 	break;
167       case '#':
168 	flags |= DP_F_NUM;
169         ch = *format++;
170 	break;
171       case '0':
172 	flags |= DP_F_ZERO;
173         ch = *format++;
174 	break;
175       default:
176 	state = DP_S_MIN;
177 	break;
178       }
179       break;
180     case DP_S_MIN:
181       if (isdigit((unsigned char)ch))
182       {
183 	min = 10*min + char_to_int (ch);
184 	ch = *format++;
185       }
186       else if (ch == '*')
187       {
188 	min = va_arg (args, int);
189 	ch = *format++;
190 	state = DP_S_DOT;
191       }
192       else
193 	state = DP_S_DOT;
194       break;
195     case DP_S_DOT:
196       if (ch == '.')
197       {
198 	state = DP_S_MAX;
199 	ch = *format++;
200       }
201       else
202 	state = DP_S_MOD;
203       break;
204     case DP_S_MAX:
205       if (isdigit((unsigned char)ch))
206       {
207 	if (max < 0)
208 	  max = 0;
209 	max = 10*max + char_to_int (ch);
210 	ch = *format++;
211       }
212       else if (ch == '*')
213       {
214 	max = va_arg (args, int);
215 	ch = *format++;
216 	state = DP_S_MOD;
217       }
218       else
219 	state = DP_S_MOD;
220       break;
221     case DP_S_MOD:
222       /* Currently, we don't support Long Long, bummer */
223       switch (ch)
224       {
225       case 'h':
226 	cflags = DP_C_SHORT;
227 	ch = *format++;
228 	break;
229       case 'l':
230 	cflags = DP_C_LONG;
231 	ch = *format++;
232 	break;
233       case 'L':
234 	cflags = DP_C_LDOUBLE;
235 	ch = *format++;
236 	break;
237       default:
238 	break;
239       }
240       state = DP_S_CONV;
241       break;
242     case DP_S_CONV:
243       switch (ch)
244       {
245       case 'd':
246       case 'i':
247 	if (cflags == DP_C_SHORT)
248 	  value = (short int) va_arg (args, int);
249 	else if (cflags == DP_C_LONG)
250 	  value = va_arg (args, long int);
251 	else
252 	  value = va_arg (args, int);
253 	fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
254 	break;
255       case 'o':
256 	flags |= DP_F_UNSIGNED;
257 	if (cflags == DP_C_SHORT)
258 	  value = (unsigned short int) va_arg (args, int);
259 	else if (cflags == DP_C_LONG)
260 	  value = va_arg (args, unsigned long int);
261 	else
262 	  value = va_arg (args, unsigned int);
263 	fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
264 	break;
265       case 'u':
266 	flags |= DP_F_UNSIGNED;
267 	if (cflags == DP_C_SHORT)
268 	  value = (unsigned short int) va_arg (args, int);
269 	else if (cflags == DP_C_LONG)
270 	  value = va_arg (args, unsigned long int);
271 	else
272 	  value = va_arg (args, unsigned int);
273 	fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
274 	break;
275       case 'X':
276 	flags |= DP_F_UP;
277 
278 	GCC_FALLTHROUGH
279 
280       case 'x':
281 	flags |= DP_F_UNSIGNED;
282 	if (cflags == DP_C_SHORT)
283 	  value = (unsigned short int) va_arg (args, int);
284 	else if (cflags == DP_C_LONG)
285 	  value = va_arg (args, unsigned long int);
286 	else
287 	  value = va_arg (args, unsigned int);
288 	fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
289 	break;
290       case 'f':
291 	if (cflags == DP_C_LDOUBLE)
292 	  fvalue = va_arg (args, long double);
293 	else
294 	  fvalue = va_arg (args, double);
295 	/* um, floating point? */
296 	fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
297 	break;
298       case 'E':
299 	flags |= DP_F_UP;
300 
301 	GCC_FALLTHROUGH
302 
303       case 'e':
304 	if (cflags == DP_C_LDOUBLE)
305 	  fvalue = va_arg (args, long double);
306 	else
307 	  fvalue = va_arg (args, double);
308 	break;
309       case 'G':
310 	flags |= DP_F_UP;
311 
312 	GCC_FALLTHROUGH
313 
314       case 'g':
315 	if (cflags == DP_C_LDOUBLE)
316 	  fvalue = va_arg (args, long double);
317 	else
318 	  fvalue = va_arg (args, double);
319 	break;
320       case 'c':
321 	dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
322 	break;
323       case 's':
324 	strvalue = va_arg (args, char *);
325 	if (max < 0)
326 	  max = maxlen; /* ie, no max */
327 	fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
328 	break;
329       case 'p':
330 	strvalue = va_arg (args, void *);
331 	fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
332 	break;
333       case 'n':
334 	if (cflags == DP_C_SHORT)
335 	{
336 	  short int *num;
337 	  num = va_arg (args, short int *);
338 	  *num = currlen;
339         }
340 	else if (cflags == DP_C_LONG)
341 	{
342 	  long int *num;
343 	  num = va_arg (args, long int *);
344 	  *num = currlen;
345         }
346 	else
347 	{
348 	  int *num;
349 	  num = va_arg (args, int *);
350 	  *num = currlen;
351         }
352 	break;
353       case '%':
354 	dopr_outch (buffer, &currlen, maxlen, ch);
355 	break;
356       case 'w':
357 	/* not supported yet, treat as next char */
358 	ch = *format++;
359 	break;
360       default:
361 	/* Unknown, skip */
362 	break;
363       }
364       ch = *format++;
365       state = DP_S_DEFAULT;
366       flags = cflags = min = 0;
367       max = -1;
368       break;
369     case DP_S_DONE:
370       break;
371     default:
372       /* hmm? */
373       break; /* some picky compilers need this */
374     }
375   }
376   if (currlen < maxlen - 1)
377     buffer[currlen] = '\0';
378   else
379     buffer[maxlen - 1] = '\0';
380 }
381 
fmtstr(char * buffer,size_t * currlen,size_t maxlen,char * value,int flags,int min,int max)382 static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
383 		    char *value, int flags, int min, int max)
384 {
385   int padlen, strln;     /* amount to pad */
386   int cnt = 0;
387 
388   if (value == 0)
389   {
390     value = "<NULL>";
391   }
392 
393   for (strln = 0; value[strln]; ++strln); /* strlen */
394   padlen = min - strln;
395   if (padlen < 0)
396     padlen = 0;
397   if (flags & DP_F_MINUS)
398     padlen = -padlen; /* Left Justify */
399 
400   while ((padlen > 0) && (cnt < max))
401   {
402     dopr_outch (buffer, currlen, maxlen, ' ');
403     --padlen;
404     ++cnt;
405   }
406   while (*value && (cnt < max))
407   {
408     dopr_outch (buffer, currlen, maxlen, *value++);
409     ++cnt;
410   }
411   while ((padlen < 0) && (cnt < max))
412   {
413     dopr_outch (buffer, currlen, maxlen, ' ');
414     ++padlen;
415     ++cnt;
416   }
417 }
418 
419 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
420 
fmtint(char * buffer,size_t * currlen,size_t maxlen,long value,int base,int min,int max,int flags)421 static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
422 		    long value, int base, int min, int max, int flags)
423 {
424   int signvalue = 0;
425   unsigned long uvalue;
426   char convert[20];
427   int place = 0;
428   int spadlen = 0; /* amount to space pad */
429   int zpadlen = 0; /* amount to zero pad */
430   int caps = 0;
431 
432   if (max < 0)
433     max = 0;
434 
435   uvalue = value;
436 
437   if(!(flags & DP_F_UNSIGNED))
438   {
439     if( value < 0 ) {
440       signvalue = '-';
441       uvalue = -value;
442     }
443     else
444       if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
445 	signvalue = '+';
446     else
447       if (flags & DP_F_SPACE)
448 	signvalue = ' ';
449   }
450 
451   if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
452 
453   do {
454     convert[place++] =
455       (caps? "0123456789ABCDEF":"0123456789abcdef")
456       [uvalue % (unsigned)base  ];
457     uvalue = (uvalue / (unsigned)base );
458   } while(uvalue && (place < 20));
459   if (place == 20) place--;
460   convert[place] = 0;
461 
462   zpadlen = max - place;
463   spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
464   if (zpadlen < 0) zpadlen = 0;
465   if (spadlen < 0) spadlen = 0;
466   if (flags & DP_F_ZERO)
467   {
468     zpadlen = MAX(zpadlen, spadlen);
469     spadlen = 0;
470   }
471   if (flags & DP_F_MINUS)
472     spadlen = -spadlen; /* Left Justifty */
473 
474 #ifdef DEBUG_SNPRINTF
475   dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
476       zpadlen, spadlen, min, max, place));
477 #endif
478 
479   /* Spaces */
480   while (spadlen > 0)
481   {
482     dopr_outch (buffer, currlen, maxlen, ' ');
483     --spadlen;
484   }
485 
486   /* Sign */
487   if (signvalue)
488     dopr_outch (buffer, currlen, maxlen, signvalue);
489 
490   /* Zeros */
491   if (zpadlen > 0)
492   {
493     while (zpadlen > 0)
494     {
495       dopr_outch (buffer, currlen, maxlen, '0');
496       --zpadlen;
497     }
498   }
499 
500   /* Digits */
501   while (place > 0)
502     dopr_outch (buffer, currlen, maxlen, convert[--place]);
503 
504   /* Left Justified spaces */
505   while (spadlen < 0) {
506     dopr_outch (buffer, currlen, maxlen, ' ');
507     ++spadlen;
508   }
509 }
510 
abs_val(long double value)511 static long double abs_val (long double value)
512 {
513   long double result = value;
514 
515   if (value < 0)
516     result = -value;
517 
518   return result;
519 }
520 
my_pow10(int exp)521 static long double my_pow10 (int exp)
522 {
523   long double result = 1;
524 
525   while (exp)
526   {
527     result *= 10;
528     exp--;
529   }
530 
531   return result;
532 }
533 
my_round(long double value)534 static long my_round (long double value)
535 {
536   long intpart;
537 
538   intpart = value;
539   value = value - intpart;
540   if (value >= 0.5)
541     intpart++;
542 
543   return intpart;
544 }
545 
fmtfp(char * buffer,size_t * currlen,size_t maxlen,long double fvalue,int min,int max,int flags)546 static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
547 		   long double fvalue, int min, int max, int flags)
548 {
549   int signvalue = 0;
550   long double ufvalue;
551   char iconvert[20];
552   char fconvert[20];
553   int iplace = 0;
554   int fplace = 0;
555   int padlen = 0; /* amount to pad */
556   int zpadlen = 0;
557   int caps = 0;
558   long intpart;
559   long fracpart;
560 
561   /*
562    * AIX manpage says the default is 0, but Solaris says the default
563    * is 6, and sprintf on AIX defaults to 6
564    */
565   if (max < 0)
566     max = 6;
567 
568   ufvalue = abs_val (fvalue);
569 
570   if (fvalue < 0)
571     signvalue = '-';
572   else
573     if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
574       signvalue = '+';
575     else
576       if (flags & DP_F_SPACE)
577 	signvalue = ' ';
578 
579 #if 0
580   if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
581 #endif
582 
583   intpart = ufvalue;
584 
585   /*
586    * Sorry, we only support 9 digits past the decimal because of our
587    * conversion method
588    */
589   if (max > 9)
590     max = 9;
591 
592   /* We "cheat" by converting the fractional part to integer by
593    * multiplying by a factor of 10
594    */
595   fracpart = my_round ((my_pow10 (max)) * (ufvalue - intpart));
596 
597   if (fracpart >= my_pow10 (max))
598   {
599     intpart++;
600     fracpart -= my_pow10 (max);
601   }
602 
603 #ifdef DEBUG_SNPRINTF
604   dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
605 #endif
606 
607   /* Convert integer part */
608   do {
609     iconvert[iplace++] =
610       (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
611     intpart = (intpart / 10);
612   } while(intpart && (iplace < 20));
613   if (iplace == 20) iplace--;
614   iconvert[iplace] = 0;
615 
616   /* Convert fractional part */
617   do {
618     fconvert[fplace++] =
619       (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
620     fracpart = (fracpart / 10);
621   } while(fracpart && (fplace < 20));
622   if (fplace == 20) fplace--;
623   fconvert[fplace] = 0;
624 
625   /* -1 for decimal point, another -1 if we are printing a sign */
626   padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
627   zpadlen = max - fplace;
628   if (zpadlen < 0)
629     zpadlen = 0;
630   if (padlen < 0)
631     padlen = 0;
632   if (flags & DP_F_MINUS)
633     padlen = -padlen; /* Left Justifty */
634 
635   if ((flags & DP_F_ZERO) && (padlen > 0))
636   {
637     if (signvalue)
638     {
639       dopr_outch (buffer, currlen, maxlen, signvalue);
640       --padlen;
641       signvalue = 0;
642     }
643     while (padlen > 0)
644     {
645       dopr_outch (buffer, currlen, maxlen, '0');
646       --padlen;
647     }
648   }
649   while (padlen > 0)
650   {
651     dopr_outch (buffer, currlen, maxlen, ' ');
652     --padlen;
653   }
654   if (signvalue)
655     dopr_outch (buffer, currlen, maxlen, signvalue);
656 
657   while (iplace > 0)
658     dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
659 
660   /*
661    * Decimal point.  This should probably use locale to find the correct
662    * char to print out.
663    */
664   dopr_outch (buffer, currlen, maxlen, '.');
665 
666   while (fplace > 0)
667     dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
668 
669   while (zpadlen > 0)
670   {
671     dopr_outch (buffer, currlen, maxlen, '0');
672     --zpadlen;
673   }
674 
675   while (padlen < 0)
676   {
677     dopr_outch (buffer, currlen, maxlen, ' ');
678     ++padlen;
679   }
680 }
681 
dopr_outch(char * buffer,size_t * currlen,size_t maxlen,char c)682 static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
683 {
684   if (*currlen < maxlen)
685     buffer[(*currlen)++] = c;
686 }
687 #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
688 
689 #ifndef HAVE_VSNPRINTF
vsnprintf(char * str,size_t count,const char * fmt,va_list args)690 int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
691 {
692   str[0] = 0;
693   dopr(str, count, fmt, args);
694   return(strlen(str));
695 }
696 #endif /* !HAVE_VSNPRINTF */
697 
698 #ifndef HAVE_SNPRINTF
699 /* VARARGS3 */
700 #ifdef HAVE_STDARGS
snprintf(char * str,size_t count,const char * fmt,...)701 int snprintf (char *str,size_t count,const char *fmt,...)
702 #else
703 int snprintf (va_alist) va_dcl
704 #endif
705 {
706 #ifndef HAVE_STDARGS
707   char *str;
708   size_t count;
709   char *fmt;
710 #endif
711   VA_LOCAL_DECL;
712 
713   VA_START (fmt);
714   VA_SHIFT (str, char *);
715   VA_SHIFT (count, size_t );
716   VA_SHIFT (fmt, char *);
717   (void) vsnprintf(str, count, fmt, ap);
718   VA_END;
719   return(strlen(str));
720 }
721 
722 #ifdef TEST_SNPRINTF
723 #ifndef LONG_STRING
724 #define LONG_STRING 1024
725 #endif
main(void)726 int main (void)
727 {
728   char buf1[LONG_STRING];
729   char buf2[LONG_STRING];
730   char *fp_fmt[] = {
731     "%-1.5f",
732     "%1.5f",
733     "%123.9f",
734     "%10.5f",
735     "% 10.5f",
736     "%+22.9f",
737     "%+4.9f",
738     "%01.3f",
739     "%4f",
740     "%3.1f",
741     "%3.2f",
742     NULL
743   };
744   double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
745     0.9996, 1.996, 4.136, 0};
746   char *int_fmt[] = {
747     "%-1.5d",
748     "%1.5d",
749     "%123.9d",
750     "%5.5d",
751     "%10.5d",
752     "% 10.5d",
753     "%+22.33d",
754     "%01.3d",
755     "%4d",
756     NULL
757   };
758   long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
759   int x, y;
760   int fail = 0;
761   int num = 0;
762 
763   printf ("Testing snprintf format codes against system sprintf...\n");
764 
765   for (x = 0; fp_fmt[x] != NULL ; x++)
766     for (y = 0; fp_nums[y] != 0 ; y++)
767     {
768       snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
769       sprintf (buf2, fp_fmt[x], fp_nums[y]);
770       if (strcmp (buf1, buf2))
771       {
772 	printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
773 	    fp_fmt[x], buf1, buf2);
774 	fail++;
775       }
776       num++;
777     }
778 
779   for (x = 0; int_fmt[x] != NULL ; x++)
780     for (y = 0; int_nums[y] != 0 ; y++)
781     {
782       snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
783       sprintf (buf2, int_fmt[x], int_nums[y]);
784       if (strcmp (buf1, buf2))
785       {
786 	printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
787 	    int_fmt[x], buf1, buf2);
788 	fail++;
789       }
790       num++;
791     }
792   printf ("%d tests failed out of %d.\n", fail, num);
793 }
794 #endif /* SNPRINTF_TEST */
795 
796 #endif /* !HAVE_SNPRINTF */
797