summaryrefslogtreecommitdiff
path: root/tvision/compat/snprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'tvision/compat/snprintf.c')
-rw-r--r--tvision/compat/snprintf.c892
1 files changed, 892 insertions, 0 deletions
diff --git a/tvision/compat/snprintf.c b/tvision/compat/snprintf.c
new file mode 100644
index 0000000..fc61538
--- /dev/null
+++ b/tvision/compat/snprintf.c
@@ -0,0 +1,892 @@
+/*
+ Unix snprintf implementation.
+ Version 1.1
+ Code by Caolán McNamara <caolan@skynet.ie>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 1.1:
+ * added changes from Miles Bader
+ * corrected a bug with %f
+ * added support for %#g
+ * added more comments :-)
+ 1.0:
+ * supporting must ANSI syntaxic_sugars
+ 0.0:
+ * suppot %s %c %d
+
+ THANKS(for the patches and ideas):
+ Miles Bader
+ Cyrille Rustom
+ Jacek Slabocewiz
+ Mike Parker(mouse)
+ ------------------------------------
+
+ Modified by Salvador E. Tropea (c) 2003.
+ Don't blame Caolán for the bugs introduced by me ;-)
+ I removed all the pre-ANSI previsions because they make the code unreadable
+and I don't plan to support such an old compilers.
+ I modified (or at least tried to ;-) the code to return not the used length
+but the length needed to put all. This is the standard behavior and not what
+Caolán implemented. In fact this code gets useless without it because I use
+a first call without a buffer to determine the length of the buffer in most
+cases.
+
+*/
+
+#include <cl/needs.h>
+
+#ifdef NEEDS_SNPRINTF
+
+#include <stdarg.h>
+#include <stdlib.h> /* for atoi() */
+#include <ctype.h>
+#include <string.h> /* strlen() and others */
+
+/*
+ * For the FLOATING POINT FORMAT :
+ * the challenge was finding a way to
+ * manipulate the Real numbers without having
+ * to resort to mathematical function(it
+ * would require to link with -lm) and not
+ * going down to the bit pattern(not portable)
+ *
+ * so a number, a real is:
+
+ real = integral + fraction
+
+ integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
+ fraction = b(1)*10^-1 + b(2)*10^-2 + ...
+
+ where:
+ 0 <= a(i) => 9
+ 0 <= b(i) => 9
+
+ from then it was simple math
+ */
+
+/*
+ * size of the buffer for the integral part
+ * and the fraction part
+ */
+#define MAX_INT 99 + 1 /* 1 for the null */
+#define MAX_FRACT 29 + 1
+
+/*
+ * numtoa() uses PRIVATE buffers to store the results,
+ * So this function is not reentrant
+ */
+#define itoa(n) numtoa(n, 10, 0, (char **)0)
+#define otoa(n) numtoa(n, 8, 0, (char **)0)
+#define htoa(n) numtoa(n, 16, 0, (char **)0)
+#define dtoa(n, p, f) numtoa(n, 10, p, f)
+
+#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
+
+/* this struct holds everything we need */
+struct DATA {
+ int length;
+ char *holder;
+ int counter;
+ const char *pf;
+/* FLAGS */
+ int width, precision;
+ int justify; char pad;
+ int square, space, star_w, star_p, a_long ;
+};
+
+#define PRIVATE static
+#define PUBLIC
+/* signature of the functions */
+/* the floating point stuff */
+ PRIVATE double pow_10(int);
+ PRIVATE int log_10(double);
+ PRIVATE double integral(double, double *);
+ PRIVATE char * numtoa(double, int, int, char **);
+
+/* for the format */
+ PRIVATE void conv_flag(char *, struct DATA *);
+ PRIVATE void floating(struct DATA *, double);
+ PRIVATE void exponent(struct DATA *, double);
+ PRIVATE void decimal(struct DATA *, double);
+ PRIVATE void octal(struct DATA *, double);
+ PRIVATE void hexa(struct DATA *, double);
+ PRIVATE void strings(struct DATA *, char *);
+
+/* those are defines specific to snprintf to hopefully
+ * make the code clearer :-)
+ */
+#define RIGHT 1
+#define LEFT 0
+#define NOT_FOUND -1
+#define FOUND 1
+#define MAX_FIELD 15
+
+/* the conversion flags */
+#define isflag(c) ((c) == '#' || (c) == ' ' || \
+ (c) == '*' || (c) == '+' || \
+ (c) == '-' || (c) == '.' || \
+ isdigit(c))
+
+/* round off to the precision */
+#define ROUND(d, p) \
+ (d < 0.) ? \
+ d - pow_10(-(p)->precision) * 0.5 : \
+ d + pow_10(-(p)->precision) * 0.5
+
+/* set default precision */
+#define DEF_PREC(p) \
+ if ((p)->precision == NOT_FOUND) \
+ (p)->precision = 6
+
+/* put a char */
+#define PUT_CHAR(c, p) \
+ { \
+ if ((p)->counter < (p)->length) \
+ *(p)->holder++ = (c); \
+ (p)->counter++; /* SET: Moved outside if */ \
+ }
+
+/* SET: put a char, no increment */
+#define PUT_EOS(p) \
+ { \
+ if ((p)->counter <= (p)->length) \
+ *(p)->holder = 0; \
+ }
+
+#define PUT_PLUS(d, p) \
+ if ((d) > 0. && (p)->justify == RIGHT) \
+ PUT_CHAR('+', p)
+
+#define PUT_SPACE(d, p) \
+ if ((p)->space == FOUND && (d) > 0.) \
+ PUT_CHAR(' ', p)
+
+/* pad right */
+#define PAD_RIGHT(p) \
+ if ((p)->width > 0 && (p)->justify != LEFT) \
+ for (; (p)->width > 0; (p)->width--) \
+ PUT_CHAR((p)->pad, p)
+
+/* pad left */
+#define PAD_LEFT(p) \
+ if ((p)->width > 0 && (p)->justify == LEFT) \
+ for (; (p)->width > 0; (p)->width--) \
+ PUT_CHAR((p)->pad, p)
+
+/* if width and prec. in the args */
+#define STAR_ARGS(p) \
+ if ((p)->star_w == FOUND) \
+ (p)->width = va_arg(args, int); \
+ if ((p)->star_p == FOUND) \
+ (p)->precision = va_arg(args, int)
+
+/*
+ * Find the nth power of 10
+ */
+PRIVATE double
+pow_10(int n)
+{
+ int i;
+ double P;
+
+ if (n < 0)
+ for (i = 1, P = 1., n = -n ; i <= n ; i++) {P *= .1;}
+ else
+ for (i = 1, P = 1. ; i <= n ; i++) {P *= 10.0;}
+ return P;
+}
+
+/*
+ * Find the integral part of the log in base 10
+ * Note: this not a real log10()
+ I just need and approximation(integerpart) of x in:
+ 10^x ~= r
+ * log_10(200) = 2;
+ * log_10(250) = 2;
+ */
+PRIVATE int
+log_10(double r)
+{
+ int i = 0;
+ double result = 1.;
+
+ if (r < 0.)
+ r = -r;
+
+ if (r < 1.) {
+ while (result >= r) {result *= .1; i++;}
+ return (-i);
+ } else {
+ while (result <= r) {result *= 10.; i++;}
+ return (i - 1);
+ }
+}
+
+/*
+ * This function return the fraction part of a double
+ * and set in ip the integral part.
+ * In many ways it resemble the modf() found on most Un*x
+ */
+PRIVATE double
+integral(double real, double * ip)
+{
+ int j;
+ double i, s, p;
+ double real_integral = 0.;
+
+/* take care of the obvious */
+/* equal to zero ? */
+ if (real == 0.) {
+ *ip = 0.;
+ return (0.);
+ }
+
+/* negative number ? */
+ if (real < 0.)
+ real = -real;
+
+/* a fraction ? */
+ if ( real < 1.) {
+ *ip = 0.;
+ return real;
+ }
+/* the real work :-) */
+ for (j = log_10(real); j >= 0; j--) {
+ p = pow_10(j);
+ s = (real - real_integral)/p;
+ i = 0.;
+ while (i + 1. <= s) {i++;}
+ real_integral += i*p;
+ }
+ *ip = real_integral;
+ return (real - real_integral);
+}
+
+#define PRECISION 1.e-6
+/*
+ * return an ascii representation of the integral part of the number
+ * and set fract to be an ascii representation of the fraction part
+ * the container for the fraction and the integral part or staticly
+ * declare with fix size
+ */
+PRIVATE char *
+numtoa(double number, int base, int precision, char ** fract)
+{
+ register int i, j;
+ double ip, fp; /* integer and fraction part */
+ double fraction;
+ int digits = MAX_INT - 1;
+ static char integral_part[MAX_INT];
+ static char fraction_part[MAX_FRACT];
+ double sign;
+ int ch;
+
+/* taking care of the obvious case: 0.0 */
+ if (number == 0.) {
+ integral_part[0] = '0';
+ integral_part[1] = '\0';
+ fraction_part[0] = '0';
+ fraction_part[1] = '\0';
+ return integral_part;
+ }
+
+/* for negative numbers */
+ if ((sign = number) < 0.) {
+ number = -number;
+ digits--; /* sign consume one digit */
+ }
+
+ fraction = integral(number, &ip);
+ number = ip;
+/* do the integral part */
+ if ( ip == 0.) {
+ integral_part[0] = '0';
+ i = 1;
+ } else {
+ for ( i = 0; i < digits && number != 0.; ++i) {
+ number /= base;
+ fp = integral(number, &ip);
+ ch = (int)((fp + PRECISION)*base); /* force to round */
+ integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
+ if (! isxdigit(integral_part[i])) /* bail out overflow !! */
+ break;
+ number = ip;
+ }
+ }
+
+/* Oh No !! out of bound, ho well fill it up ! */
+ if (number != 0.)
+ for (i = 0; i < digits; ++i)
+ integral_part[i] = '9';
+
+/* put the sign ? */
+ if (sign < 0.)
+ integral_part[i++] = '-';
+
+ integral_part[i] = '\0';
+
+/* reverse every thing */
+ for ( i--, j = 0; j < i; j++, i--)
+ SWAP_INT(integral_part[i], integral_part[j]);
+
+/* the fractionnal part */
+ for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision-- ) {
+ fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
+ if (! isdigit(fraction_part[i])) /* underflow ? */
+ break;
+ fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
+ }
+ fraction_part[i] = '\0';
+
+ if (fract != (char **)0)
+ *fract = fraction_part;
+
+ return integral_part;
+
+}
+
+/* for %d and friends, it puts in holder
+ * the representation with the right padding
+ */
+PRIVATE void
+decimal(struct DATA *p, double d)
+{
+ char *tmp;
+
+ tmp = itoa(d);
+ p->width -= strlen(tmp);
+ PAD_RIGHT(p);
+ PUT_PLUS(d, p);
+ PUT_SPACE(d, p);
+ while (*tmp) { /* the integral */
+ PUT_CHAR(*tmp, p);
+ tmp++;
+ }
+ PAD_LEFT(p);
+}
+
+/* for %o octal representation */
+PRIVATE void
+octal(struct DATA *p, double d)
+{
+ char *tmp;
+
+ tmp = otoa(d);
+ p->width -= strlen(tmp);
+ PAD_RIGHT(p);
+ if (p->square == FOUND) /* had prefix '0' for octal */
+ PUT_CHAR('0', p);
+ while (*tmp) { /* octal */
+ PUT_CHAR(*tmp, p);
+ tmp++;
+ }
+ PAD_LEFT(p);
+}
+
+/* for %x %X hexadecimal representation */
+PRIVATE void
+hexa(struct DATA *p, double d)
+{
+ char *tmp;
+
+ tmp = htoa(d);
+ p->width -= strlen(tmp);
+ PAD_RIGHT(p);
+ if (p->square == FOUND) { /* prefix '0x' for hexa */
+ PUT_CHAR('0', p); PUT_CHAR(*p->pf, p);
+ }
+ while (*tmp) { /* hexa */
+ PUT_CHAR((*p->pf == 'X' ? toupper(*tmp) : *tmp), p);
+ tmp++;
+ }
+ PAD_LEFT(p);
+}
+
+/* %s strings */
+PRIVATE void
+strings(struct DATA *p, char *tmp)
+{
+ int i;
+
+ i = strlen(tmp);
+ if (p->precision != NOT_FOUND) /* the smallest number */
+ i = (i < p->precision ? i : p->precision);
+ p->width -= i;
+ PAD_RIGHT(p);
+ while (i-- > 0) { /* put the sting */
+ PUT_CHAR(*tmp, p);
+ tmp++;
+ }
+ PAD_LEFT(p);
+}
+
+/* %f or %g floating point representation */
+PRIVATE void
+floating(struct DATA *p, double d)
+{
+ char *tmp, *tmp2;
+ int i;
+
+ DEF_PREC(p);
+ d = ROUND(d, p);
+ tmp = dtoa(d, p->precision, &tmp2);
+ /* calculate the padding. 1 for the dot */
+ p->width = p->width -
+ ((d > 0. && p->justify == RIGHT) ? 1:0) -
+ ((p->space == FOUND) ? 1:0) -
+ strlen(tmp) - p->precision - 1;
+ PAD_RIGHT(p);
+ PUT_PLUS(d, p);
+ PUT_SPACE(d, p);
+ while (*tmp) { /* the integral */
+ PUT_CHAR(*tmp, p);
+ tmp++;
+ }
+ if (p->precision != 0 || p->square == FOUND)
+ PUT_CHAR('.', p); /* put the '.' */
+ if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */
+ for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
+ tmp2[i] = '\0';
+ for (; *tmp2; tmp2++)
+ PUT_CHAR(*tmp2, p); /* the fraction */
+
+ PAD_LEFT(p);
+}
+
+/* %e %E %g exponent representation */
+PRIVATE void
+exponent(struct DATA *p, double d)
+{
+ char *tmp, *tmp2;
+ int j, i;
+
+ DEF_PREC(p);
+ j = log_10(d);
+ d = d / pow_10(j); /* get the Mantissa */
+ d = ROUND(d, p);
+ tmp = dtoa(d, p->precision, &tmp2);
+ /* 1 for unit, 1 for the '.', 1 for 'e|E',
+ * 1 for '+|-', 3 for 'exp' */
+ /* calculate how much padding need */
+ p->width = p->width -
+ ((d > 0. && p->justify == RIGHT) ? 1:0) -
+ ((p->space == FOUND) ? 1:0) - p->precision - 7;
+ PAD_RIGHT(p);
+ PUT_PLUS(d, p);
+ PUT_SPACE(d, p);
+ while (*tmp) {/* the integral */
+ PUT_CHAR(*tmp, p);
+ tmp++;
+ }
+ if (p->precision != 0 || p->square == FOUND)
+ PUT_CHAR('.', p); /* the '.' */
+ if (*p->pf == 'g' || *p->pf == 'G') /* smash the trailing zeros */
+ for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
+ tmp2[i] = '\0';
+ for (; *tmp2; tmp2++)
+ PUT_CHAR(*tmp2, p); /* the fraction */
+
+ if (*p->pf == 'g' || *p->pf == 'e') { /* the exponent put the 'e|E' */
+ PUT_CHAR('e', p);
+ } else
+ PUT_CHAR('E', p);
+ if (j > 0) { /* the sign of the exp */
+ PUT_CHAR('+', p);
+ } else {
+ PUT_CHAR('-', p);
+ j = -j;
+ }
+ tmp = itoa((double)j);
+ if (j < 9) { /* need to pad the exponent with 0 '000' */
+ PUT_CHAR('0', p); PUT_CHAR('0', p);
+ } else if (j < 99)
+ PUT_CHAR('0', p);
+ while (*tmp) { /* the exponent */
+ PUT_CHAR(*tmp, p);
+ tmp++;
+ }
+ PAD_LEFT(p);
+}
+
+/* initialize the conversion specifiers */
+PRIVATE void
+conv_flag(char * s, struct DATA * p)
+{
+ char number[MAX_FIELD/2];
+ int i;
+
+ p->precision = p->width = NOT_FOUND;
+ p->star_w = p->star_p = NOT_FOUND;
+ p->square = p->space = NOT_FOUND;
+ p->a_long = p->justify = NOT_FOUND;
+ p->pad = ' ';
+
+ for(;s && *s ;s++) {
+ switch(*s) {
+ case ' ': p->space = FOUND; break;
+ case '#': p->square = FOUND; break;
+ case '*': if (p->width == NOT_FOUND)
+ p->width = p->star_w = FOUND;
+ else
+ p->precision = p->star_p = FOUND;
+ break;
+ case '+': p->justify = RIGHT; break;
+ case '-': p->justify = LEFT; break;
+ case '.': if (p->width == NOT_FOUND)
+ p->width = 0;
+ break;
+ case '0': p->pad = '0'; break;
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9': /* gob all the digits */
+ for (i = 0; isdigit(*s); i++, s++)
+ if (i < MAX_FIELD/2 - 1)
+ number[i] = *s;
+ number[i] = '\0';
+ if (p->width == NOT_FOUND)
+ p->width = atoi(number);
+ else
+ p->precision = atoi(number);
+ s--; /* went to far go back */
+ break;
+ }
+ }
+}
+
+PUBLIC int
+CLY_vsnprintf(char *string, size_t length, const char * format, va_list args)
+{
+ struct DATA data;
+ char conv_field[MAX_FIELD];
+ double d; /* temporary holder */
+ int state;
+ int i;
+
+ data.length = length - 1; /* leave room for '\0' */
+ data.holder = string;
+ data.pf = format;
+ data.counter = 0;
+
+
+/* sanity check, the string must be > 1
+ SET: Wrong! we must compute the length!
+ if (length < 1)
+ return -1; */
+
+
+ for (; *data.pf /*SET: && (data.counter < data.length)*/; data.pf++) {
+ if ( *data.pf == '%' ) { /* we got a magic % cookie */
+ conv_flag((char *)0, &data); /* initialise format flags */
+ for (state = 1; *data.pf && state;) {
+ switch (*(++data.pf)) {
+ case '\0': /* a NULL here ? ? bail out */
+ PUT_EOS(&data);
+ return data.counter;
+ break;
+ case 'f': /* float, double */
+ STAR_ARGS(&data);
+ d = va_arg(args, double);
+ floating(&data, d);
+ state = 0;
+ break;
+ case 'g':
+ case 'G':
+ STAR_ARGS(&data);
+ DEF_PREC(&data);
+ d = va_arg(args, double);
+ i = log_10(d);
+ /*
+ * for '%g|%G' ANSI: use f if exponent
+ * is in the range or [-4,p] exclusively
+ * else use %e|%E
+ */
+ if (-4 < i && i < data.precision)
+ floating(&data, d);
+ else
+ exponent(&data, d);
+ state = 0;
+ break;
+ case 'e':
+ case 'E': /* Exponent double */
+ STAR_ARGS(&data);
+ d = va_arg(args, double);
+ exponent(&data, d);
+ state = 0;
+ break;
+ case 'u':
+ case 'd': /* decimal */
+ STAR_ARGS(&data);
+ if (data.a_long == FOUND)
+ d = va_arg(args, long);
+ else
+ d = va_arg(args, int);
+ decimal(&data, d);
+ state = 0;
+ break;
+ case 'o': /* octal */
+ STAR_ARGS(&data);
+ if (data.a_long == FOUND)
+ d = va_arg(args, long);
+ else
+ d = va_arg(args, int);
+ octal(&data, d);
+ state = 0;
+ break;
+ case 'x':
+ case 'X': /* hexadecimal */
+ STAR_ARGS(&data);
+ if (data.a_long == FOUND)
+ d = va_arg(args, long);
+ else
+ d = va_arg(args, int);
+ hexa(&data, d);
+ state = 0;
+ break;
+ case 'c': /* character */
+ d = va_arg(args, int);
+ PUT_CHAR((char)d, &data);
+ state = 0;
+ break;
+ case 's': /* string */
+ STAR_ARGS(&data);
+ strings(&data, va_arg(args, char *));
+ state = 0;
+ break;
+ case 'n':
+ *(va_arg(args, int *)) = data.counter; /* what's the count ? */
+ state = 0;
+ break;
+ case 'l':
+ data.a_long = FOUND;
+ break;
+ case 'h':
+ break;
+ case '%': /* nothing just % */
+ PUT_CHAR('%', &data);
+ state = 0;
+ break;
+ case '#': case ' ': case '+': case '*':
+ case '-': case '.': case '0': case '1':
+ case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ /* initialize width and precision */
+ for (i = 0; isflag(*data.pf); i++, data.pf++)
+ if (i < MAX_FIELD - 1)
+ conv_field[i] = *data.pf;
+ conv_field[i] = '\0';
+ conv_flag(conv_field, &data);
+ data.pf--; /* went to far go back */
+ break;
+ default:
+ /* is this an error ? maybe bail out */
+ state = 0;
+ break;
+ } /* end switch */
+ } /* end of for state */
+ } else { /* not % */
+ PUT_CHAR(*data.pf, &data); /* add the char the string */
+ }
+ }
+
+ PUT_EOS(&data); /* the end ye ! */
+
+ return data.counter;
+}
+
+#ifndef HAVE_SNPRINTF
+
+PUBLIC int
+CLY_snprintf(char *string, size_t length, const char * format, ...)
+{
+ int rval;
+ va_list args;
+
+ va_start(args, format);
+
+ rval = CLY_vsnprintf (string, length, format, args);
+
+ va_end(args);
+
+ return rval;
+}
+
+#endif /* HAVE_SNPRINTF */
+
+
+#ifdef DRIVER
+
+#include <stdio.h>
+
+/* set of small tests for snprintf() */
+int main()
+{
+ char holder[100];
+ int i;
+
+/*
+ printf("Suite of test for snprintf:\n");
+ printf("a_format\n");
+ printf("printf() format\n");
+ printf("snprintf() format\n\n");
+*/
+/* Checking the field widths */
+
+ printf("/%%d/, 336\n");
+ CLY_snprintf(holder, sizeof holder, "/%d/\n", 336);
+ printf("/%d/\n", 336);
+ printf("%s\n", holder);
+
+ printf("/%%2d/, 336\n");
+ CLY_snprintf(holder, sizeof holder, "/%2d/\n", 336);
+ printf("/%2d/\n", 336);
+ printf("%s\n", holder);
+
+ printf("/%%10d/, 336\n");
+ CLY_snprintf(holder, sizeof holder, "/%10d/\n", 336);
+ printf("/%10d/\n", 336);
+ printf("%s\n", holder);
+
+ printf("/%%-10d/, 336\n");
+ CLY_snprintf(holder, sizeof holder, "/%-10d/\n", 336);
+ printf("/%-10d/\n", 336);
+ printf("%s\n", holder);
+
+
+/* floating points */
+
+ printf("/%%f/, 1234.56\n");
+ CLY_snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
+ printf("/%f/\n", 1234.56);
+ printf("%s\n", holder);
+
+ printf("/%%e/, 1234.56\n");
+ CLY_snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
+ printf("/%e/\n", 1234.56);
+ printf("%s\n", holder);
+
+ printf("/%%4.2f/, 1234.56\n");
+ CLY_snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
+ printf("/%4.2f/\n", 1234.56);
+ printf("%s\n", holder);
+
+ printf("/%%3.1f/, 1234.56\n");
+ CLY_snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
+ printf("/%3.1f/\n", 1234.56);
+ printf("%s\n", holder);
+
+ printf("/%%10.3f/, 1234.56\n");
+ CLY_snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
+ printf("/%10.3f/\n", 1234.56);
+ printf("%s\n", holder);
+
+ printf("/%%10.3e/, 1234.56\n");
+ CLY_snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
+ printf("/%10.3e/\n", 1234.56);
+ printf("%s\n", holder);
+
+ printf("/%%+4.2f/, 1234.56\n");
+ CLY_snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
+ printf("/%+4.2f/\n", 1234.56);
+ printf("%s\n", holder);
+
+ printf("/%%010.2f/, 1234.56\n");
+ CLY_snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
+ printf("/%010.2f/\n", 1234.56);
+ printf("%s\n", holder);
+
+#define BLURB "Outstanding acting !"
+/* strings precisions */
+
+ printf("/%%2s/, \"%s\"\n", BLURB);
+ CLY_snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
+ printf("/%2s/\n", BLURB);
+ printf("%s\n", holder);
+
+ printf("/%%22s/ %s\n", BLURB);
+ CLY_snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
+ printf("/%22s/\n", BLURB);
+ printf("%s\n", holder);
+
+ printf("/%%22.5s/ %s\n", BLURB);
+ CLY_snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
+ printf("/%22.5s/\n", BLURB);
+ printf("%s\n", holder);
+
+ printf("/%%-22.5s/ %s\n", BLURB);
+ CLY_snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
+ printf("/%-22.5s/\n", BLURB);
+ printf("%s\n", holder);
+
+/* see some flags */
+
+ printf("%%x %%X %%#x, 31, 31, 31\n");
+ CLY_snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
+ printf("%x %X %#x\n", 31, 31, 31);
+ printf("%s\n", holder);
+
+ printf("**%%d**%% d**%% d**, 42, 42, -42\n");
+ CLY_snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
+ printf("**%d**% d**% d**\n", 42, 42, -42);
+ printf("%s\n", holder);
+
+/* other flags */
+
+ printf("/%%g/, 31.4\n");
+ CLY_snprintf(holder, sizeof holder, "/%g/\n", 31.4);
+ printf("/%g/\n", 31.4);
+ printf("%s\n", holder);
+
+ printf("/%%.6g/, 31.4\n");
+ CLY_snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
+ printf("/%.6g/\n", 31.4);
+ printf("%s\n", holder);
+
+ printf("/%%.1G/, 31.4\n");
+ CLY_snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
+ printf("/%.1G/\n", 31.4);
+ printf("%s\n", holder);
+
+ printf("abc%%n\n");
+ printf("abc%n", &i); printf("%d\n", i);
+ CLY_snprintf(holder, sizeof holder, "abc%n", &i);
+ printf("%s", holder); printf("%d\n\n", i);
+
+ printf("%%*.*s --> 10.10\n");
+ CLY_snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
+ printf("%*.*s\n", 10, 10, BLURB);
+ printf("%s\n", holder);
+
+ printf("%%%%%%%%\n");
+ CLY_snprintf(holder, sizeof holder, "%%%%\n");
+ printf("%%%%\n");
+ printf("%s\n", holder);
+
+#define BIG "Hello this is a too big string for the buffer"
+ printf("A buffer to small of 10, trying to put this:\n");
+ printf("<%%>, %s\n", BIG);
+ i = CLY_snprintf(holder, 10, "%s\n", BIG);
+ printf("<%s>\n", BIG);
+ printf("<%s>\n", holder);
+ printf("Value returned is %d\n",i);
+
+ return 0;
+}
+#endif
+
+#endif /* NEEDS_SNPRINTF */
+