Yet Another .cvsignore file.
[obnox/wireshark/wip.git] / snprintf.c
1 /*
2  * $Id: snprintf.c,v 1.11 2000/08/11 22:03:02 guy Exp $
3  */
4
5 /*
6    Unix snprintf implementation.
7    Version 1.2
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    It can be redistribute also under the terms of GNU Library General
14    Public License.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24    
25    Revision History:
26
27    1.2:
28       * put the program under LGPL.
29    1.1:
30       *  added changes from Miles Bader
31       *  corrected a bug with %f
32       *  added support for %#g
33       *  added more comments :-)
34    1.0:
35       *  supporting must ANSI syntaxic_sugars
36    0.0:
37       *  suppot %s %c %d
38
39  THANKS(for the patches and ideas):
40      Miles Bader
41      Cyrille Rustom
42      Jacek Slabocewiz
43      Mike Parker(mouse)
44
45 */
46 #ifdef HAVE_CONFIG_H
47 # include "config.h"
48 #endif
49
50 #include <stdlib.h>     /* for atoi and for size_t */
51 #include <ctype.h>
52
53 #include "snprintf.h"
54 #include "snprintf-imp.h"
55
56 /*
57  * Find the nth power of 10
58  */
59 PRIVATE double
60 #ifdef __STDC__
61 pow_10(int n)
62 #else
63 pow_10(n)
64 int n;
65 #endif
66
67   int i;
68   double P;
69
70   if (n < 0)
71     for (i = 1, P = 1., n = -n ; i <= n ; i++) {P *= .1;}
72   else
73     for (i = 1, P = 1. ; i <= n ; i++) {P *= 10.0;}
74   return P;
75 }
76
77 /*
78  * Find the integral part of the log in base 10 
79  * Note: this not a real log10()
80          I just need and approximation(integerpart) of x in:
81           10^x ~= r
82  * log_10(200) = 2;
83  * log_10(250) = 2;
84  */
85 PRIVATE int
86 #ifdef __STDC__
87 log_10(double r)
88 #else
89 log_10(r)
90 double r;
91 #endif
92
93   int i = 0;
94   double result = 1.;
95
96   if (r < 0.)
97     r = -r;
98
99   if (r == 0.0)
100      return(0);
101   if (r < 1.) {
102     while (result >= r) {result *= .1; i++;}
103     return (-i);
104   } else {
105     while (result <= r) {result *= 10.; i++;}
106     return (i - 1);
107   }
108 }
109
110 /*
111  * This function return the fraction part of a double
112  * and set in ip the integral part.
113  * In many ways it resemble the modf() found on most Un*x
114  */
115 PRIVATE double
116 #ifdef __STDC__
117 integral(double real, double * ip)
118 #else
119 integral(real, ip)
120 double real;
121 double * ip;
122 #endif
123
124   int j;
125   double i, s, p;
126   double real_integral = 0.;
127
128 /* take care of the obvious */
129 /* equal to zero ? */
130   if (real == 0.) {
131     *ip = 0.;
132     return (0.);
133   }
134
135 /* negative number ? */
136   if (real < 0.)
137     real = -real;
138
139 /* a fraction ? */
140   if ( real < 1.) {
141     *ip = 0.;
142     return real;
143   }
144 /* the real work :-) */
145   for (j = log_10(real); j >= 0; j--) {
146     p = pow_10(j);
147     s = (real - real_integral)/p;
148     i = 0.;
149     while (i + 1. <= s) {i++;}
150     real_integral += i*p;
151   }
152   *ip = real_integral;
153   return (real - real_integral);
154 }
155
156 #define PRECISION 1.e-6
157 /* 
158  * return an ascii representation of the integral part of the number
159  * and set fract to be an ascii representation of the fraction part
160  * the container for the fraction and the integral part or staticly
161  * declare with fix size 
162  */
163 PRIVATE char *
164 #ifdef __STDC__
165 numtoa(double number, int base, int precision, char ** fract)
166 #else
167 numtoa(number, base, precision, fract)
168 double number;
169 int base;
170 int precision;
171 char ** fract;
172 #endif
173 {
174   register int i, j;
175   double ip, fp; /* integer and fraction part */
176   double fraction;
177   int digits = MAX_INT - 1;
178   static char integral_part[MAX_INT];
179   static char fraction_part[MAX_FRACT];
180   double sign;
181   int ch;
182
183 /* taking care of the obvious case: 0.0 */
184   if (number == 0.) { 
185     integral_part[0] = '0';
186     integral_part[1] = '\0';
187     fraction_part[0] = '0';
188     fraction_part[1] = '\0';
189     return integral_part;
190   }
191
192 /* for negative numbers */
193   if ((sign = number) < 0.) {
194     number = -number;
195     digits--; /* sign consume one digit */
196   } 
197
198   fraction = integral(number, &ip);
199   number = ip;
200 /* do the integral part */
201   if ( ip == 0.) {
202     integral_part[0] = '0';
203     i = 1;
204   } else {
205     for ( i = 0; i < digits && number != 0.; ++i) {
206       number /= base;
207       fp = integral(number, &ip);
208       ch = (int)((fp + PRECISION)*base); /* force to round */
209       integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
210       if (! isxdigit((unsigned char)integral_part[i])) /* bail out overflow !! */
211         break; 
212       number = ip;
213      }
214   }
215      
216 /* Oh No !! out of bound, ho well fill it up ! */
217   if (number != 0.)
218     for (i = 0; i < digits; ++i)
219       integral_part[i] = '9';
220
221 /* put the sign ? */
222   if (sign < 0.)
223     integral_part[i++] = '-';
224
225   integral_part[i] = '\0';
226
227 /* reverse every thing */
228   for ( i--, j = 0; j < i; j++, i--)
229     SWAP_INT(integral_part[i], integral_part[j]);  
230
231 /* the fractionnal part */
232   for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--      ) {
233     fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
234     if (! isdigit((unsigned char)fraction_part[i])) /* underflow ? */
235       break;
236     fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
237   }
238   fraction_part[i] = '\0';
239
240   if (fract != (char **)0)
241     *fract = fraction_part;
242
243   return integral_part;
244
245 }
246
247 /* for %d and friends, it puts in holder
248  * the representation with the right padding
249  */
250 PRIVATE void
251 #ifdef __STDC__
252 decimal(struct DATA *p, double d)
253 #else
254 decimal(p, d)
255 struct DATA *p;
256 double d;
257 #endif
258 {
259   char *tmp;
260
261   tmp = itoa(d);
262   p->width -= strlen(tmp);
263   PAD_RIGHT(p);
264   PUT_PLUS(d, p);
265   PUT_SPACE(d, p);
266   while (*tmp) { /* the integral */
267     PUT_CHAR(*tmp, p);
268     tmp++;
269   }
270   PAD_LEFT(p);
271 }
272
273 /* for %o octal representation */
274 PRIVATE void
275 #ifdef __STDC__
276 octal(struct DATA *p, double d)
277 #else
278 octal(p, d)
279 struct DATA *p;
280 double d;
281 #endif
282 {
283   char *tmp;
284
285   tmp = otoa(d);
286   p->width -= strlen(tmp);
287   if (p->square == FOUND) /* had prefix '0' for octal */
288     PUT_CHAR('0', p);
289   PAD_RIGHT(p);
290   while (*tmp) { /* octal */
291     PUT_CHAR(*tmp, p);
292     tmp++;
293   }
294   PAD_LEFT(p);
295 }
296
297 /* for %x %X hexadecimal representation */
298 PRIVATE void
299 #ifdef __STDC__
300 hexa(struct DATA *p, double d)
301 #else
302 hexa(p, d)
303 struct DATA *p;
304 double d;
305 #endif
306 {
307   char *tmp;
308
309   tmp = htoa(d);
310   p->width -= strlen(tmp);
311   if (p->square == FOUND) { /* prefix '0x' for hexa */
312     PUT_CHAR('0', p); PUT_CHAR(*p->pf, p);
313   }
314   PAD_RIGHT(p);
315   while (*tmp) { /* hexa */
316     PUT_CHAR((*p->pf == 'X' ? toupper(*tmp) : *tmp), p);
317     tmp++;
318   }
319   PAD_LEFT(p);
320 }
321
322 /* %s strings */
323 PRIVATE void
324 #ifdef __STDC__
325 strings(struct DATA *p, char *tmp)
326 #else
327 strings(p, tmp)
328 struct DATA *p;
329 char *tmp;
330 #endif
331 {
332   int i;
333
334   i = strlen(tmp);
335   if (p->precision != NOT_FOUND) /* the smallest number */
336     i = (i < p->precision ? i : p->precision);
337   p->width -= i;
338   PAD_RIGHT(p);
339   while (i-- > 0) { /* put the sting */
340     PUT_CHAR(*tmp, p);
341     tmp++;
342   }
343   PAD_LEFT(p);
344 }
345
346 /* %f or %g  floating point representation */
347 PRIVATE void
348 #ifdef __STDC__
349 floating(struct DATA *p, double d)
350 #else
351 floating(p, d)
352 struct DATA *p;
353 double d;
354 #endif
355 {
356   char *tmp, *tmp2;
357   int i;
358
359   DEF_PREC(p);
360   d = ROUND(d, p);
361   tmp = dtoa(d, p->precision, &tmp2);
362   /* calculate the padding. 1 for the dot */
363   p->width = p->width -
364             ((d > 0. && p->justify == RIGHT) ? 1:0) -
365             ((p->space == FOUND) ? 1:0) -
366             strlen(tmp) - p->precision - 1;
367   PAD_RIGHT(p);  
368   PUT_PLUS(d, p);
369   PUT_SPACE(d, p);
370   while (*tmp) { /* the integral */
371     PUT_CHAR(*tmp, p);
372     tmp++;
373   }
374   if (p->precision != 0 || p->square == FOUND)
375     PUT_CHAR('.', p);  /* put the '.' */
376   if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */
377     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
378        tmp2[i] = '\0'; 
379   for (; *tmp2; tmp2++)
380     PUT_CHAR(*tmp2, p); /* the fraction */
381   
382   PAD_LEFT(p);
383
384
385 /* %e %E %g exponent representation */
386 PRIVATE void
387 #ifdef __STDC__
388 exponent(struct DATA *p, double d)
389 #else
390 exponent(p, d)
391 struct DATA *p;
392 double d;
393 #endif
394 {
395   char *tmp, *tmp2;
396   int j, i;
397
398   DEF_PREC(p);
399   j = log_10(d);
400   d = d / pow_10(j);  /* get the Mantissa */
401   d = ROUND(d, p);                  
402   tmp = dtoa(d, p->precision, &tmp2);
403   /* 1 for unit, 1 for the '.', 1 for 'e|E',
404    * 1 for '+|-', 3 for 'exp' */
405   /* calculate how much padding need */
406   p->width = p->width - 
407              ((d > 0. && p->justify == RIGHT) ? 1:0) -
408              ((p->space == FOUND) ? 1:0) - p->precision - 7;
409   PAD_RIGHT(p);
410   PUT_PLUS(d, p);
411   PUT_SPACE(d, p);
412   while (*tmp) {/* the integral */
413     PUT_CHAR(*tmp, p);
414     tmp++;
415   }
416   if (p->precision != 0 || p->square == FOUND)
417     PUT_CHAR('.', p);  /* the '.' */
418   if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */
419     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
420        tmp2[i] = '\0'; 
421   for (; *tmp2; tmp2++)
422     PUT_CHAR(*tmp2, p); /* the fraction */
423
424   if (*p->pf == 'g' || *p->pf == 'e') { /* the exponent put the 'e|E' */
425      PUT_CHAR('e', p);
426    } else
427      PUT_CHAR('E', p);
428    if (j > 0) {  /* the sign of the exp */
429      PUT_CHAR('+', p);
430    } else {
431      PUT_CHAR('-', p);
432      j = -j;
433    }
434    tmp = itoa((double)j);
435    if (j < 9) {  /* need to pad the exponent with 0 '000' */
436      PUT_CHAR('0', p); PUT_CHAR('0', p);
437    } else if (j < 99)
438      PUT_CHAR('0', p);
439    while (*tmp) { /* the exponent */
440      PUT_CHAR(*tmp, p);
441      tmp++;
442    }
443    PAD_LEFT(p);
444 }
445
446 /* initialize the conversion specifiers */
447 PRIVATE void
448 #ifdef __STDC__
449 conv_flag(char * s, struct DATA * p)
450 #else
451 conv_flag(s, p)
452 char * s;
453 struct DATA * p;
454 #endif
455 {
456   char number[MAX_FIELD/2];
457   int i;
458
459   p->precision = p->width = NOT_FOUND;
460   p->star_w = p->star_p = NOT_FOUND;
461   p->square = p->space = NOT_FOUND;
462   p->a_long = p->justify = NOT_FOUND;
463   p->pad = ' ';
464
465   for(;s && *s ;s++) {
466     switch(*s) {
467       case ' ': p->space = FOUND; break;
468       case '#': p->square = FOUND; break;
469       case '*': if (p->width == NOT_FOUND)
470                   p->width = p->star_w = FOUND;
471                 else
472                   p->precision = p->star_p = FOUND;
473                 break;
474       case '+': p->justify = RIGHT; break;
475       case '-': p->justify = LEFT; break;
476       case '.': if (p->width == NOT_FOUND)
477                   p->width = 0;
478                 break;
479       case '0': p->pad = '0'; break;
480       case '1': case '2': case '3':
481       case '4': case '5': case '6':
482       case '7': case '8': case '9':     /* gob all the digits */
483         for (i = 0; isdigit((unsigned char)*s); i++, s++) 
484           if (i < MAX_FIELD/2 - 1)
485             number[i] = *s;
486         number[i] = '\0';
487         if (p->width == NOT_FOUND)
488           p->width = atoi(number);
489         else
490           p->precision = atoi(number);
491         s--;   /* went to far go back */
492         break;
493     }
494   }
495 }
496
497 PUBLIC int
498 #ifdef __STDC__
499 vsnprintf(char *string, size_t length, const char * format, va_list args)
500 #else
501 vsnprintf(string, length, format, args)
502 char *string;
503 size_t length;
504 char * format;
505 va_list args;
506 #endif
507 {
508   struct DATA data;
509   char conv_field[MAX_FIELD];
510   double d; /* temporary holder */
511   int state;
512   int i;
513
514   data.length = length - 1; /* leave room for '\0' */
515   data.holder = string;
516   data.pf = format;
517   data.counter = 0;
518
519
520 /* sanity check, the string must be > 1 */
521   if (length < 1)
522     return -1;
523
524
525   for (; *data.pf && (data.counter < data.length); data.pf++) {
526     if ( *data.pf == '%' ) { /* we got a magic % cookie */
527       conv_flag((char *)0, &data); /* initialise format flags */
528       for (state = 1; *data.pf && state;) {
529         switch (*(++data.pf)) {
530           case '\0': /* a NULL here ? ? bail out */
531             *data.holder = '\0';
532             return data.counter;
533             break;
534           case 'f':  /* float, double */
535             STAR_ARGS(&data);
536             d = va_arg(args, double);
537             floating(&data, d);  
538             state = 0;
539             break;
540           case 'g': 
541           case 'G':
542             STAR_ARGS(&data);
543             DEF_PREC(&data);
544             d = va_arg(args, double);
545             i = log_10(d);
546             /*
547              * for '%g|%G' ANSI: use f if exponent
548              * is in the range or [-4,p] exclusively
549              * else use %e|%E
550              */
551             if (-4 < i && i < data.precision)
552               floating(&data, d);
553             else
554               exponent(&data, d);
555             state = 0;
556             break;
557           case 'e':
558           case 'E':  /* Exponent double */
559             STAR_ARGS(&data);
560             d = va_arg(args, double);
561             exponent(&data, d);
562             state = 0;
563             break;
564           case 'u':  /* unsigned decimal */
565             STAR_ARGS(&data);
566             if (data.a_long == FOUND)
567               d = va_arg(args, unsigned long);
568             else
569               d = va_arg(args, unsigned int);
570             decimal(&data, d);
571             state = 0;
572             break;
573           case 'd':  /* decimal */
574           case 'i':  /* "integer" (signed decimal) */
575             STAR_ARGS(&data);
576             if (data.a_long == FOUND)
577               d = va_arg(args, long);
578             else
579               d = va_arg(args, int);
580             decimal(&data, d);
581             state = 0;
582             break;
583           case 'o':  /* octal */
584             STAR_ARGS(&data);
585             if (data.a_long == FOUND)
586               d = va_arg(args, unsigned long);
587             else
588               d = va_arg(args, unsigned int);
589             octal(&data, d);
590             state = 0;
591             break;
592           case 'x': 
593           case 'X':  /* hexadecimal */
594             STAR_ARGS(&data);
595             if (data.a_long == FOUND)
596               d = va_arg(args, unsigned long);
597             else
598               d = va_arg(args, unsigned int);
599             hexa(&data, d);
600             state = 0;
601             break;
602           case 'c': /* character */
603             d = va_arg(args, int);
604             PUT_CHAR(d, &data);
605             state = 0;
606             break;
607           case 's':  /* string */
608             STAR_ARGS(&data);
609             strings(&data, va_arg(args, char *));
610             state = 0;
611             break;
612           case 'n':
613              *(va_arg(args, int *)) = data.counter; /* what's the count ? */
614              state = 0;
615              break;
616           case 'l':
617             data.a_long = FOUND;
618             break;
619           case 'h':
620             break;
621           case '%':  /* nothing just % */
622             PUT_CHAR('%', &data);
623             state = 0;
624             break;
625           case '#': case ' ': case '+': case '*':
626           case '-': case '.': case '0': case '1': 
627           case '2': case '3': case '4': case '5':
628           case '6': case '7': case '8': case '9':
629            /* initialize width and precision */
630             for (i = 0; isflag((unsigned char)*data.pf); i++, data.pf++) 
631               if (i < MAX_FIELD - 1)
632                 conv_field[i] = *data.pf;
633             conv_field[i] = '\0';
634             conv_flag(conv_field, &data);
635             data.pf--;   /* went to far go back */
636             break;
637           default:
638             /* is this an error ? maybe bail out */
639             state = 0;
640             break;
641         } /* end switch */
642       } /* end of for state */
643     } else { /* not % */
644       PUT_CHAR(*data.pf, &data);  /* add the char the string */
645     }
646   }
647
648   *data.holder = '\0'; /* the end ye ! */
649
650   return data.counter;
651 }
652
653 #ifndef HAVE_SNPRINTF
654
655 PUBLIC int
656 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
657 snprintf(char *string, size_t length, const char * format, ...)
658 #else
659 snprintf(string, length, format, va_alist)
660 char *string;
661 size_t length;
662 char * format;
663 va_dcl
664 #endif
665 {
666   int rval;
667   va_list args;
668
669 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
670   va_start(args, format);
671 #else
672   va_start(args);
673 #endif
674
675   rval = vsnprintf (string, length, format, args);
676
677   va_end(args);
678
679   return rval;
680 }
681
682 #endif /* HAVE_SNPRINTF */
683
684
685 #ifdef DRIVER
686
687 #include <stdio.h>
688
689 /* set of small tests for snprintf() */
690 void main()
691 {
692   char holder[100];
693   int i;
694
695 /*
696   printf("Suite of test for snprintf:\n");
697   printf("a_format\n");
698   printf("printf() format\n");
699   printf("snprintf() format\n\n");
700 */
701 /* Checking the field widths */
702
703   printf("/%%d/, 336\n");
704   snprintf(holder, sizeof holder, "/%d/\n", 336);
705   printf("/%d/\n", 336);
706   printf("%s\n", holder);
707
708   printf("/%%2d/, 336\n");
709   snprintf(holder, sizeof holder, "/%2d/\n", 336);
710   printf("/%2d/\n", 336);
711   printf("%s\n", holder);
712
713   printf("/%%10d/, 336\n");
714   snprintf(holder, sizeof holder, "/%10d/\n", 336);
715   printf("/%10d/\n", 336);
716   printf("%s\n", holder);
717
718   printf("/%%-10d/, 336\n");
719   snprintf(holder, sizeof holder, "/%-10d/\n", 336);
720   printf("/%-10d/\n", 336);
721   printf("%s\n", holder);
722
723
724 /* floating points */
725
726   printf("/%%f/, 1234.56\n");
727   snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
728   printf("/%f/\n", 1234.56);
729   printf("%s\n", holder);
730
731   printf("/%%e/, 1234.56\n");
732   snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
733   printf("/%e/\n", 1234.56);
734   printf("%s\n", holder);
735
736   printf("/%%4.2f/, 1234.56\n");
737   snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
738   printf("/%4.2f/\n", 1234.56);
739   printf("%s\n", holder);
740
741   printf("/%%3.1f/, 1234.56\n");
742   snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
743   printf("/%3.1f/\n", 1234.56);
744   printf("%s\n", holder);
745
746   printf("/%%10.3f/, 1234.56\n");
747   snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
748   printf("/%10.3f/\n", 1234.56);
749   printf("%s\n", holder);
750
751   printf("/%%10.3e/, 1234.56\n");
752   snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
753   printf("/%10.3e/\n", 1234.56);
754   printf("%s\n", holder);
755
756   printf("/%%+4.2f/, 1234.56\n");
757   snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
758   printf("/%+4.2f/\n", 1234.56);
759   printf("%s\n", holder);
760
761   printf("/%%010.2f/, 1234.56\n");
762   snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
763   printf("/%010.2f/\n", 1234.56);
764   printf("%s\n", holder);
765
766 #define BLURB "Outstanding acting !"
767 /* strings precisions */
768
769   printf("/%%2s/, \"%s\"\n", BLURB);
770   snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
771   printf("/%2s/\n", BLURB);
772   printf("%s\n", holder);
773
774   printf("/%%22s/ %s\n", BLURB);
775   snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
776   printf("/%22s/\n", BLURB);
777   printf("%s\n", holder);
778
779   printf("/%%22.5s/ %s\n", BLURB);
780   snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
781   printf("/%22.5s/\n", BLURB);
782   printf("%s\n", holder);
783
784   printf("/%%-22.5s/ %s\n", BLURB);
785   snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
786   printf("/%-22.5s/\n", BLURB);
787   printf("%s\n", holder);
788
789 /* see some flags */
790
791   printf("%%x %%X %%#x, 31, 31, 31\n");
792   snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
793   printf("%x %X %#x\n", 31, 31, 31);
794   printf("%s\n", holder);
795
796   printf("**%%d**%% d**%% d**, 42, 42, -42\n");
797   snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
798   printf("**%d**% d**% d**\n", 42, 42, -42);
799   printf("%s\n", holder);
800
801 /* other flags */
802
803   printf("/%%g/, 31.4\n");
804   snprintf(holder, sizeof holder, "/%g/\n", 31.4);
805   printf("/%g/\n", 31.4);
806   printf("%s\n", holder);
807
808   printf("/%%.6g/, 31.4\n");
809   snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
810   printf("/%.6g/\n", 31.4);
811   printf("%s\n", holder);
812
813   printf("/%%.1G/, 31.4\n");
814   snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
815   printf("/%.1G/\n", 31.4);
816   printf("%s\n", holder);
817
818   printf("abc%%n\n");
819   printf("abc%n", &i); printf("%d\n", i);
820   snprintf(holder, sizeof holder, "abc%n", &i);
821   printf("%s", holder); printf("%d\n\n", i);
822   
823   printf("%%*.*s --> 10.10\n");
824   snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
825   printf("%*.*s\n", 10, 10, BLURB);
826   printf("%s\n", holder);
827
828   printf("%%%%%%%%\n");
829   snprintf(holder, sizeof holder, "%%%%\n");
830   printf("%%%%\n");
831   printf("%s\n", holder);
832
833 #define BIG "Hello this is a too big string for the buffer"
834 /*  printf("A buffer to small of 10, trying to put this:\n");*/
835   printf("<%%>, %s\n", BIG); 
836   i = snprintf(holder, 10, "%s\n", BIG);
837   printf("<%s>\n", BIG);
838   printf("<%s>\n", holder);
839 }
840 #endif