1666 lines
		
	
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			1666 lines
		
	
	
	
		
			37 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  build a test version with | ||
|  |    gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o | ||
|  | */ | ||
|  |   | ||
|  | /*
 | ||
|  |    Unix snprintf implementation. | ||
|  |    derived from inetutils/libinetutils/snprintf.c Version 1.1 | ||
|  | 
 | ||
|  |    Copyright (C) 2001 Free Software Foundation, Inc. | ||
|  | 
 | ||
|  |    This program is free software; you can redistribute it and/or modify | ||
|  |    it under the terms of the GNU General 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 License for more details. | ||
|  |     | ||
|  |    You should have received a copy of the GNU General 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: | ||
|  |       *  support %s %c %d | ||
|  | 
 | ||
|  |  THANKS(for the patches and ideas): | ||
|  |      Miles Bader | ||
|  |      Cyrille Rustom | ||
|  |      Jacek Slabocewiz | ||
|  |      Mike Parker(mouse) | ||
|  | 
 | ||
|  | */ | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * Currently doesn't handle (and bash/readline doesn't use): | ||
|  |  *	*M$ width, precision specifications | ||
|  |  *	%N$ numbered argument conversions | ||
|  |  *	inf, nan floating values (could use isinf(), isnan()) | ||
|  |  *	`,', `'' flags  | ||
|  |  *	`C', `S' conversions | ||
|  |  *	support for `F' is imperfect, since underlying printf may not handle it | ||
|  |  */ | ||
|  | 
 | ||
|  | #define FLOATING_POINT
 | ||
|  | 
 | ||
|  | #ifdef HAVE_CONFIG_H
 | ||
|  | #  include <config.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if defined(DRIVER) && !defined(HAVE_CONFIG_H)
 | ||
|  | #define HAVE_LONG_LONG
 | ||
|  | #define HAVE_LONG_DOUBLE
 | ||
|  | #ifdef __linux__
 | ||
|  | #define HAVE_PRINTF_A_FORMAT
 | ||
|  | #endif
 | ||
|  | #define PREFER_STDARG
 | ||
|  | #define HAVE_STRINGIZE
 | ||
|  | #define HAVE_LIMITS_H
 | ||
|  | #define HAVE_STDDEF_H
 | ||
|  | #define intmax_t long
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if !defined (HAVE_SNPRINTF) || !defined (HAVE_ASPRINTF)
 | ||
|  | 
 | ||
|  | #include <bashtypes.h>
 | ||
|  | 
 | ||
|  | #if defined(PREFER_STDARG)
 | ||
|  | #  include <stdarg.h>
 | ||
|  | #else
 | ||
|  | #  include <varargs.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef HAVE_LIMITS_H
 | ||
|  | #  include <limits.h>
 | ||
|  | #endif
 | ||
|  | #include <bashansi.h>
 | ||
|  | #ifdef HAVE_STDDEF_H
 | ||
|  | #  include <stddef.h>
 | ||
|  | #endif
 | ||
|  | #include <chartypes.h>
 | ||
|  | 
 | ||
|  | #ifdef HAVE_STDINT_H
 | ||
|  | #  include <stdint.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | #  include <stdio.h>	/* for sprintf */
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #include <typemax.h>
 | ||
|  | 
 | ||
|  | #include "stdc.h"
 | ||
|  | 
 | ||
|  | #ifndef DRIVER
 | ||
|  | #  include "shell.h"
 | ||
|  | #else
 | ||
|  | #  define FL_PREFIX     0x01    /* add 0x, 0X, or 0 prefix as appropriate */
 | ||
|  | #  define FL_ADDBASE    0x02    /* add base# prefix to converted value */
 | ||
|  | #  define FL_HEXUPPER   0x04    /* use uppercase when converting to hex */
 | ||
|  | #  define FL_UNSIGNED   0x08    /* don't add any sign */
 | ||
|  | extern char *fmtulong __P((unsigned long int, int, char *, size_t, int)); | ||
|  | extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int)); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | /* Bound on length of the string representing an integer value of type T.
 | ||
|  |    Subtract one for the sign bit if T is signed; | ||
|  |    302 / 1000 is log10 (2) rounded up; | ||
|  |    add one for integer division truncation; | ||
|  |    add one more for a minus sign if t is signed.  */ | ||
|  | #define INT_STRLEN_BOUND(t) \
 | ||
|  |   ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \ | ||
|  |      + 1 + TYPE_SIGNED (t)) | ||
|  | 
 | ||
|  | /* conversion flags */ | ||
|  | #define PF_ALTFORM	0x00001		/* # */
 | ||
|  | #define PF_HEXPREFIX	0x00002		/* 0[Xx] */
 | ||
|  | #define PF_LADJUST	0x00004		/* - */
 | ||
|  | #define PF_ZEROPAD	0x00008		/* 0 */
 | ||
|  | #define PF_PLUS		0x00010		/* + */
 | ||
|  | #define PF_SPACE	0x00020		/* ' ' */
 | ||
|  | #define PF_COMMA	0x00040		/* , */
 | ||
|  | 
 | ||
|  | #define PF_DOT		0x00080		/* `.precision' */
 | ||
|  | #define PF_STAR_P	0x00100		/* `*' after precision */
 | ||
|  | #define PF_STAR_W	0x00200		/* `*' before or without precision */
 | ||
|  | 
 | ||
|  | /* length modifiers */ | ||
|  | #define PF_SIGNEDCHAR	0x00400		/* hh */
 | ||
|  | #define PF_SHORTINT	0x00800		/* h */
 | ||
|  | #define PF_LONGINT	0x01000		/* l */
 | ||
|  | #define PF_LONGLONG	0x02000		/* ll */
 | ||
|  | #define PF_LONGDBL	0x04000		/* L */
 | ||
|  | #define PF_INTMAX_T	0x08000		/* j */
 | ||
|  | #define PF_SIZE_T	0x10000		/* z */
 | ||
|  | #define PF_PTRDIFF_T	0x20000		/* t */
 | ||
|  | 
 | ||
|  | #define PF_ALLOCBUF	0x40000		/* for asprintf, vasprintf */
 | ||
|  | 
 | ||
|  | #define PFM_SN		0x01		/* snprintf, vsnprintf */
 | ||
|  | #define PFM_AS		0x02		/* asprintf, vasprintf */
 | ||
|  | 
 | ||
|  | #define ASBUFSIZE	128
 | ||
|  | 
 | ||
|  | #define x_digs	"0123456789abcdef"
 | ||
|  | #define X_digs	"0123456789ABCDEF"
 | ||
|  | 
 | ||
|  | static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1]; | ||
|  | 
 | ||
|  | /* 
 | ||
|  |  * 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 307 + 1
 | ||
|  | 
 | ||
|  | /* 
 | ||
|  |  * These functions use static buffers to store the results, | ||
|  |  * and so are not reentrant | ||
|  |  */ | ||
|  | #define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
 | ||
|  | #define dtoa(n, p, f) numtoa(n, 10, p, f)
 | ||
|  | 
 | ||
|  | #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
 | ||
|  | 
 | ||
|  | /* Macros that do proper sign extension and handle length modifiers.  Used
 | ||
|  |    for the integer conversion specifiers. */ | ||
|  | #define GETSIGNED(p) \
 | ||
|  |   (((p)->flags & PF_LONGINT) \ | ||
|  | 	? va_arg(args, long) \ | ||
|  |   	: (((p)->flags & PF_SHORTINT) ? (long)(short)va_arg(args, int) \ | ||
|  | 				      : (long)va_arg(args, int))) | ||
|  | 
 | ||
|  | #define GETUNSIGNED(p) \
 | ||
|  |   (((p)->flags & PF_LONGINT) \ | ||
|  | 	? va_arg(args, unsigned long) \ | ||
|  | 	: (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)va_arg(args, int) \ | ||
|  | 				      : (unsigned long)va_arg(args, unsigned int))) | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifdef HAVE_LONG_DOUBLE
 | ||
|  | #define GETLDOUBLE(p) va_arg(args, long double)
 | ||
|  | #endif
 | ||
|  | #define GETDOUBLE(p) va_arg(args, double)
 | ||
|  | 
 | ||
|  | #define SET_SIZE_FLAGS(p, type) \
 | ||
|  |   if (sizeof (type) > sizeof (int)) \ | ||
|  |     (p)->flags |= PF_LONGINT; \ | ||
|  |   if (sizeof (type) > sizeof (long)) \ | ||
|  |     (p)->flags |= PF_LONGLONG; | ||
|  | 
 | ||
|  | /* this struct holds everything we need */ | ||
|  | struct DATA | ||
|  | { | ||
|  |   int length; | ||
|  |   char *base;		/* needed for [v]asprintf */ | ||
|  |   char *holder; | ||
|  |   int counter; | ||
|  |   const char *pf; | ||
|  | 
 | ||
|  | /* FLAGS */ | ||
|  |   int flags; | ||
|  |   int justify; | ||
|  |   int width, precision; | ||
|  |   char pad; | ||
|  | }; | ||
|  | 
 | ||
|  | /* the floating point stuff */ | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | static double pow_10 __P((int)); | ||
|  | static int log_10 __P((double)); | ||
|  | static double integral __P((double, double *)); | ||
|  | static char *numtoa __P((double, int, int, char **)); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | static void init_data __P((struct DATA *, char *, size_t, const char *, int)); | ||
|  | static void init_conv_flag __P((struct DATA *)); | ||
|  | 
 | ||
|  | /* for the format */ | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | static void floating __P((struct DATA *, double)); | ||
|  | static void exponent __P((struct DATA *, double)); | ||
|  | #endif
 | ||
|  | static void number __P((struct DATA *, unsigned long, int)); | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  | static void lnumber __P((struct DATA *, unsigned long long, int)); | ||
|  | #endif
 | ||
|  | static void pointer __P((struct DATA *, unsigned long)); | ||
|  | static void strings __P((struct DATA *, char *)); | ||
|  | 
 | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | #  define FALLBACK_FMTSIZE	32
 | ||
|  | #  define FALLBACK_BASE		4096
 | ||
|  | #  define LFALLBACK_BASE	5120
 | ||
|  | #  ifdef HAVE_LONG_DOUBLE
 | ||
|  | static void ldfallback __P((struct DATA *, const char *, const char *, long double)); | ||
|  | #  endif
 | ||
|  | static void dfallback __P((struct DATA *, const char *, const char *, double)); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef DRIVER
 | ||
|  | static void memory_error_and_abort (); | ||
|  | static void *xmalloc __P((size_t)); | ||
|  | static void *xrealloc __P((void *, size_t)); | ||
|  | static void xfree __P((void *)); | ||
|  | #else
 | ||
|  | #  include <xmalloc.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | /* 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
 | ||
|  | 
 | ||
|  | /* 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.  increment the number of chars written even if we've exceeded
 | ||
|  |    the vsnprintf/snprintf buffer size (for the return value) */ | ||
|  | #define PUT_CHAR(c, p) \
 | ||
|  | 	do \ | ||
|  | 	  { \ | ||
|  | 	    if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \ | ||
|  | 	      { \ | ||
|  | 		(p)->length += ASBUFSIZE; \ | ||
|  | 		(p)->base = (char *)xrealloc((p)->base, (p)->length); \ | ||
|  | 		(p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \ | ||
|  | 	      } \ | ||
|  | 	    if ((p)->counter < (p)->length) \ | ||
|  | 	      *(p)->holder++ = (c); \ | ||
|  | 	    (p)->counter++; \ | ||
|  | 	  } \ | ||
|  | 	while (0) | ||
|  | 
 | ||
|  | #define PUT_PLUS(d, p, zero) \
 | ||
|  | 	    if ((d) > zero && (p)->justify == RIGHT) \ | ||
|  | 	      PUT_CHAR('+', p) | ||
|  | 
 | ||
|  | #define PUT_SPACE(d, p, zero) \
 | ||
|  | 	    if (((p)->flags & PF_SPACE) && (d) > zero) \ | ||
|  | 	      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)->flags & PF_STAR_W) \ | ||
|  | 	      (p)->width = va_arg(args, int); \ | ||
|  | 	    if ((p)->flags & PF_STAR_P) \ | ||
|  | 	      (p)->precision = va_arg(args, int) | ||
|  | 
 | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | /*
 | ||
|  |  * Find the nth power of 10 | ||
|  |  */ | ||
|  | static double | ||
|  | pow_10(n) | ||
|  |      int n; | ||
|  | {  | ||
|  |   double P; | ||
|  | 
 | ||
|  |   /* handle common cases with fast switch statement. */ | ||
|  |   switch (n) | ||
|  |     { | ||
|  |     case -3:	return .001; | ||
|  |     case -2:	return .01; | ||
|  |     case -1:	return .1; | ||
|  |     case 0:	return 1.; | ||
|  |     case 1:	return 10.; | ||
|  |     case 2:	return 100.; | ||
|  |     case 3:	return 1000.; | ||
|  |     } | ||
|  | 
 | ||
|  |   if (n < 0) | ||
|  |     { | ||
|  |       P = .0001; | ||
|  |       for (n += 4; n < 0; n++) | ||
|  | 	P /= 10.; | ||
|  |     } | ||
|  |   else | ||
|  |     { | ||
|  |       P = 10000.; | ||
|  |       for (n -= 4; n > 0; n--) | ||
|  | 	P *= 10.; | ||
|  |     } | ||
|  | 
 | ||
|  |   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; | ||
|  |  */ | ||
|  | static int | ||
|  | log_10(r) | ||
|  |      double r; | ||
|  | {  | ||
|  |   int i = 0; | ||
|  |   double result = 1.; | ||
|  | 
 | ||
|  |   if (r < 0.) | ||
|  |     r = -r; | ||
|  | 
 | ||
|  |   if (r < 1.) | ||
|  |     { | ||
|  |       while (result >= r) | ||
|  | 	{ | ||
|  | 	  result /= 10.; | ||
|  | 	  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 | ||
|  |  */ | ||
|  | static double | ||
|  | integral(real, ip) | ||
|  |      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  | ||
|  |  */ | ||
|  | static char * | ||
|  | numtoa(number, base, precision, fract) | ||
|  |      double number; | ||
|  |      int base, 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((unsigned char)integral_part[i])) | ||
|  | 	    break;	/* bail out overflow !! */ | ||
|  | 	  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 fractional part */ | ||
|  |   for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--) | ||
|  |     { | ||
|  |       fraction_part[i] = (int)((fp + PRECISION)*10. + '0'); | ||
|  |       if (! DIGIT(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; | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | /* for %d and friends, it puts in holder
 | ||
|  |  * the representation with the right padding | ||
|  |  */ | ||
|  | static void | ||
|  | number(p, d, base) | ||
|  |      struct DATA *p; | ||
|  |      unsigned long d; | ||
|  |      int base; | ||
|  | { | ||
|  |   char *tmp; | ||
|  |   long sd; | ||
|  |   int flags; | ||
|  | 
 | ||
|  |   sd = d;	/* signed for ' ' padding in base 10 */ | ||
|  |   flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; | ||
|  |   if (*p->pf == 'X') | ||
|  |     flags |= FL_HEXUPPER; | ||
|  | 
 | ||
|  |   tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags); | ||
|  |   p->width -= strlen(tmp); | ||
|  |   PAD_RIGHT(p); | ||
|  | 
 | ||
|  |   switch (base) | ||
|  |     { | ||
|  |     case 10: | ||
|  |       PUT_PLUS(sd, p, 0); | ||
|  |       PUT_SPACE(sd, p, 0); | ||
|  |       break; | ||
|  |     case 8: | ||
|  |       if (p->flags & PF_ALTFORM) | ||
|  | 	PUT_CHAR('0', p); | ||
|  |       break; | ||
|  |     case 16: | ||
|  |       if (p->flags & PF_ALTFORM) | ||
|  | 	{ | ||
|  | 	  PUT_CHAR('0', p); | ||
|  | 	  PUT_CHAR(*p->pf, p); | ||
|  | 	} | ||
|  |       break; | ||
|  |     } | ||
|  | 
 | ||
|  |   while (*tmp) | ||
|  |     { | ||
|  |       PUT_CHAR(*tmp, p); | ||
|  |       tmp++; | ||
|  |     } | ||
|  | 
 | ||
|  |   PAD_LEFT(p); | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  | /*
 | ||
|  |  * identical to number() but works for `long long' | ||
|  |  */ | ||
|  | static void | ||
|  | lnumber(p, d, base) | ||
|  |      struct DATA *p; | ||
|  |      unsigned long long d; | ||
|  |      int base; | ||
|  | { | ||
|  |   char *tmp; | ||
|  |   long long sd; | ||
|  |   int flags; | ||
|  | 
 | ||
|  |   sd = d;	/* signed for ' ' padding in base 10 */ | ||
|  |   flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; | ||
|  |   if (*p->pf == 'X') | ||
|  |     flags |= FL_HEXUPPER; | ||
|  | 
 | ||
|  |   tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags); | ||
|  |   p->width -= strlen(tmp); | ||
|  |   PAD_RIGHT(p); | ||
|  | 
 | ||
|  |   switch (base) | ||
|  |     { | ||
|  |     case 10: | ||
|  |       PUT_PLUS(sd, p, 0); | ||
|  |       PUT_SPACE(sd, p, 0); | ||
|  |       break; | ||
|  |     case 8: | ||
|  |       if (p->flags & PF_ALTFORM) | ||
|  | 	PUT_CHAR('0', p); | ||
|  |       break; | ||
|  |     case 16: | ||
|  |       if (p->flags & PF_ALTFORM) | ||
|  | 	{ | ||
|  | 	  PUT_CHAR('0', p); | ||
|  | 	  PUT_CHAR(*p->pf, p); | ||
|  | 	} | ||
|  |       break; | ||
|  |     } | ||
|  | 
 | ||
|  |   while (*tmp) | ||
|  |     { | ||
|  |       PUT_CHAR(*tmp, p); | ||
|  |       tmp++; | ||
|  |     } | ||
|  | 
 | ||
|  |   PAD_LEFT(p); | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | static void | ||
|  | pointer(p, d) | ||
|  |      struct DATA *p; | ||
|  |      unsigned long d; | ||
|  | { | ||
|  |   char *tmp; | ||
|  | 
 | ||
|  |   tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0); | ||
|  |   p->width -= strlen(tmp); | ||
|  |   PAD_RIGHT(p); | ||
|  | 
 | ||
|  |   /* prefix '0x' for pointers */ | ||
|  |   PUT_CHAR('0', p); | ||
|  |   PUT_CHAR('x', p); | ||
|  | 
 | ||
|  |   while (*tmp) | ||
|  |     { | ||
|  |       PUT_CHAR(*tmp, p); | ||
|  |       tmp++; | ||
|  |     } | ||
|  |   PAD_LEFT(p); | ||
|  | } | ||
|  | 
 | ||
|  | /* %s strings */ | ||
|  | static void | ||
|  | strings(p, tmp) | ||
|  |      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); | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | /* %f %F %g %G floating point representation */ | ||
|  | static void | ||
|  | floating(p, d) | ||
|  |      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->flags & PF_SPACE) ? 1:0) - | ||
|  | 	    strlen(tmp) - p->precision - 1; | ||
|  |   PAD_RIGHT(p);   | ||
|  |   PUT_PLUS(d, p, 0.); | ||
|  |   PUT_SPACE(d, p, 0.); | ||
|  |   while (*tmp) | ||
|  |     { /* the integral */ | ||
|  |       PUT_CHAR(*tmp, p); | ||
|  |       tmp++; | ||
|  |     } | ||
|  |   if (p->precision != 0 || (p->flags & PF_ALTFORM)) | ||
|  |     PUT_CHAR('.', p);  /* put the '.' */ | ||
|  |   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0) | ||
|  |     /* smash the trailing zeros unless altform */ | ||
|  |     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 %G exponent representation */ | ||
|  | static void | ||
|  | exponent(p, d) | ||
|  |      struct DATA *p; | ||
|  |      double d; | ||
|  | { | ||
|  |   char *tmp, *tmp2; | ||
|  |   int j, i, nsig, ndig; | ||
|  | 
 | ||
|  |   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 '+|-', 2 for 'exp' */ | ||
|  |   /* calculate how much padding need */ | ||
|  |   p->width = p->width -  | ||
|  | 	     ((d > 0. && p->justify == RIGHT) ? 1:0) - | ||
|  | 	     ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6; | ||
|  |   PAD_RIGHT(p); | ||
|  |   PUT_PLUS(d, p, 0.); | ||
|  |   PUT_SPACE(d, p, 0.); | ||
|  |   /*
 | ||
|  |    * When supplied %g or %G, an optional precision is the number of | ||
|  |    * significant digits to print. | ||
|  |    * | ||
|  |    * nsig = number of significant digits we've printed (leading zeros are | ||
|  |    *	    never significant) | ||
|  |    * ndig = if non-zero, max number of significant digits to print (only | ||
|  |    *	    applicable to %g/%G) | ||
|  |    */ | ||
|  |   nsig = ndig = 0; | ||
|  |   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_DOT)) | ||
|  |     ndig = (p->precision == 0) ? 1 : p->precision; | ||
|  | 
 | ||
|  |   while (*tmp) | ||
|  |     { | ||
|  |       PUT_CHAR(*tmp, p); | ||
|  |       tmp++; | ||
|  |       if (ndig && (++nsig >= ndig)) | ||
|  | 	break; | ||
|  |     } | ||
|  | 
 | ||
|  |   if ((p->precision != 0 || (p->flags & PF_ALTFORM)) && (ndig == 0 || nsig < ndig)) | ||
|  |       PUT_CHAR('.', p);  /* the '.' */ | ||
|  |   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0) | ||
|  |     /* smash the trailing zeros unless altform */ | ||
|  |     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--) | ||
|  |        tmp2[i] = '\0';  | ||
|  |   for (; *tmp2; tmp2++) | ||
|  |     { | ||
|  |       if (ndig && (nsig++ >= ndig)) | ||
|  | 	break; | ||
|  |       PUT_CHAR(*tmp2, p); /* the fraction */ | ||
|  |     } | ||
|  | 
 | ||
|  |   /* the exponent put the 'e|E' */ | ||
|  |   if (*p->pf == 'g' || *p->pf == 'e') | ||
|  |     { | ||
|  |       PUT_CHAR('e', p); | ||
|  |     } | ||
|  |   else | ||
|  |      PUT_CHAR('E', p); | ||
|  | 
 | ||
|  |   /* the sign of the exp */ | ||
|  |   if (j > 0) | ||
|  |     { | ||
|  |       PUT_CHAR('+', p); | ||
|  |     } | ||
|  |   else | ||
|  |     { | ||
|  |       PUT_CHAR('-', p); | ||
|  |       j = -j; | ||
|  |     } | ||
|  | 
 | ||
|  |    tmp = itoa(j); | ||
|  |    /* pad out to at least two spaces.  pad with `0' if the exponent is a
 | ||
|  |       single digit. */ | ||
|  |    if (j <= 9) | ||
|  |      { | ||
|  |        PUT_CHAR('0', p); | ||
|  |      } | ||
|  | 
 | ||
|  |    /* the exponent */ | ||
|  |    while (*tmp) | ||
|  |      { | ||
|  |        PUT_CHAR(*tmp, p); | ||
|  |        tmp++; | ||
|  |      } | ||
|  |    PAD_LEFT(p); | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | /* initialize the conversion specifiers */ | ||
|  | static void | ||
|  | init_conv_flag (p) | ||
|  |      struct DATA *p; | ||
|  | { | ||
|  |   p->flags &= PF_ALLOCBUF;		/* preserve PF_ALLOCBUF flag */ | ||
|  |   p->precision = p->width = NOT_FOUND; | ||
|  |   p->justify = NOT_FOUND; | ||
|  |   p->pad = ' '; | ||
|  | } | ||
|  | 
 | ||
|  | static void | ||
|  | init_data (p, string, length, format, mode) | ||
|  |      struct DATA *p; | ||
|  |      char *string; | ||
|  |      size_t length; | ||
|  |      const char *format; | ||
|  |      int mode; | ||
|  | { | ||
|  |   p->length = length - 1; /* leave room for '\0' */ | ||
|  |   p->holder = p->base = string; | ||
|  |   p->pf = format; | ||
|  |   p->counter = 0; | ||
|  |   p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0; | ||
|  | } | ||
|  | 
 | ||
|  | static int | ||
|  | #if defined (__STDC__)
 | ||
|  | vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args) | ||
|  | #else
 | ||
|  | vsnprintf_internal(data, string, length, format, args) | ||
|  |      struct DATA *data; | ||
|  |      char *string; | ||
|  |      size_t length; | ||
|  |      const char *format; | ||
|  |      va_list args; | ||
|  | #endif
 | ||
|  | { | ||
|  |   double d; /* temporary holder */ | ||
|  | #ifdef HAVE_LONG_DOUBLE
 | ||
|  |   long double ld;	/* for later */ | ||
|  | #endif
 | ||
|  |   unsigned long ul; | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  |   unsigned long long ull; | ||
|  | #endif
 | ||
|  |   int state, i, c, n; | ||
|  |   char *s; | ||
|  |   const char *convstart; | ||
|  | 
 | ||
|  |   /* Sanity check, the string must be > 1.  C99 actually says that LENGTH
 | ||
|  |      can be zero here, in the case of snprintf/vsnprintf (it's never 0 in | ||
|  |      the case of asprintf/vasprintf), and the return value is the number | ||
|  |      of characters that would have been written. */ | ||
|  |   if (length < 1) | ||
|  |     return -1; | ||
|  | 
 | ||
|  |   if (format == 0) | ||
|  |     return 0; | ||
|  | 
 | ||
|  |   for (; c = *(data->pf); data->pf++) | ||
|  |     { | ||
|  |       if (c != '%') | ||
|  | 	{ | ||
|  | 	  PUT_CHAR (c, data); | ||
|  | 	  continue; | ||
|  | 	} | ||
|  | 
 | ||
|  |       convstart = data->pf; | ||
|  |       init_conv_flag (data); /* initialise format flags */ | ||
|  | 
 | ||
|  |       state = 1; | ||
|  |       for (state = 1; state && *data->pf; ) | ||
|  | 	{ | ||
|  | 	  c = *(++data->pf); | ||
|  | 	      /* fmtend = data->pf */ | ||
|  | #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
 | ||
|  | 	  if (data->flags & PF_LONGDBL) | ||
|  | 	    { | ||
|  | 	      switch (c) | ||
|  | 		{ | ||
|  | 		case 'f': case 'F': | ||
|  | 		case 'e': case 'E': | ||
|  | 		case 'g': case 'G': | ||
|  | #  ifdef HAVE_PRINTF_A_FORMAT
 | ||
|  | 		case 'a': case 'A': | ||
|  | #  endif
 | ||
|  | 		  STAR_ARGS (data); | ||
|  | 		  ld = GETLDOUBLE (data); | ||
|  | 		  ldfallback (data, convstart, data->pf, ld); | ||
|  | 		  goto conv_break; | ||
|  | 		} | ||
|  | 	    } | ||
|  | #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
 | ||
|  | 
 | ||
|  | 	  switch (c) | ||
|  | 	    { | ||
|  | 	      /* Parse format flags */ | ||
|  | 	      case '\0': /* a NULL here ? ? bail out */ | ||
|  | 		*data->holder = '\0'; | ||
|  | 		return data->counter; | ||
|  | 		break; | ||
|  | 	      case '#': | ||
|  | 		data->flags |= PF_ALTFORM; | ||
|  | 		continue; | ||
|  | 	      case '0': | ||
|  | 		data->flags |= PF_ZEROPAD; | ||
|  | 		data->pad = '0'; | ||
|  | 		continue; | ||
|  | 	      case '*': | ||
|  | 		if (data->flags & PF_DOT) | ||
|  | 		  data->flags |= PF_STAR_P; | ||
|  | 		else | ||
|  | 		  data->flags |= PF_STAR_W; | ||
|  | 		continue; | ||
|  | 	      case '-': | ||
|  | 		data->flags |= PF_LADJUST; | ||
|  | 		data->justify = LEFT; | ||
|  | 		continue; | ||
|  | 	      case ' ': | ||
|  | 		if ((data->flags & PF_PLUS) == 0) | ||
|  | 		  data->flags |= PF_SPACE; | ||
|  | 		continue; | ||
|  | 	      case '+': | ||
|  | 		data->flags |= PF_PLUS; | ||
|  | 		data->justify = RIGHT; | ||
|  | 		continue; | ||
|  | 	      case ',': | ||
|  | 		data->flags |= PF_COMMA;		/* not implemented yet */ | ||
|  | 		continue; | ||
|  | 
 | ||
|  | 	      case '1': case '2': case '3': | ||
|  | 	      case '4': case '5': case '6': | ||
|  | 	      case '7': case '8': case '9': | ||
|  | 		n = 0; | ||
|  | 		do | ||
|  | 		  { | ||
|  | 		    n = n * 10 + TODIGIT(c); | ||
|  | 		    c = *(++data->pf); | ||
|  | 		  } | ||
|  | 		while (DIGIT(c)); | ||
|  | 		data->pf--;		/* went too far */ | ||
|  | 		if (n < 0) | ||
|  | 		  n = 0; | ||
|  | 		if (data->flags & PF_DOT) | ||
|  | 		  data->precision = n; | ||
|  | 		else | ||
|  | 		  data->width = n; | ||
|  | 		continue; | ||
|  | 
 | ||
|  | 	      /* optional precision */ | ||
|  | 	      case '.': | ||
|  | 		data->flags |= PF_DOT; | ||
|  | 		data->precision = 0; | ||
|  | 		continue; | ||
|  | 
 | ||
|  | 	      /* length modifiers */ | ||
|  | 	      case 'h': | ||
|  | 		data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT; | ||
|  | 		continue; | ||
|  | 	      case 'l': | ||
|  | 		data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT; | ||
|  | 		continue; | ||
|  | 	      case 'L': | ||
|  | 		data->flags |= PF_LONGDBL; | ||
|  | 		continue; | ||
|  | 	      case 'q': | ||
|  | 		data->flags |= PF_LONGLONG; | ||
|  | 		continue; | ||
|  | 	      case 'j': | ||
|  | 		data->flags |= PF_INTMAX_T; | ||
|  | 		SET_SIZE_FLAGS(data, intmax_t); | ||
|  | 		continue; | ||
|  | 	      case 'z': | ||
|  | 		data->flags |= PF_SIZE_T; | ||
|  | 		SET_SIZE_FLAGS(data, size_t); | ||
|  | 		continue; | ||
|  | 	      case 't': | ||
|  | 		data->flags |= PF_PTRDIFF_T; | ||
|  | 		SET_SIZE_FLAGS(data, ptrdiff_t); | ||
|  | 		continue; | ||
|  | 		 | ||
|  | 	      /* Conversion specifiers */ | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | 	      case 'f':  /* float, double */ | ||
|  | 	      case 'F': | ||
|  | 		STAR_ARGS(data); | ||
|  | 		d = GETDOUBLE(data); | ||
|  | 		floating(data, d); | ||
|  | conv_break:		 | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case 'g':  | ||
|  | 	      case 'G': | ||
|  | 		STAR_ARGS(data); | ||
|  | 		DEF_PREC(data); | ||
|  | 		d = GETDOUBLE(data); | ||
|  | 		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 = GETDOUBLE(data); | ||
|  | 		exponent(data, d); | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | #  ifdef HAVE_PRINTF_A_FORMAT
 | ||
|  | 	      case 'a': | ||
|  | 	      case 'A': | ||
|  | 		STAR_ARGS(data); | ||
|  | 		d = GETDOUBLE(data); | ||
|  | 		dfallback(data, convstart, data->pf, d); | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | #  endif /* HAVE_PRINTF_A_FORMAT */
 | ||
|  | #endif /* FLOATING_POINT */
 | ||
|  | 	      case 'U': | ||
|  | 		data->flags |= PF_LONGINT; | ||
|  | 		/* FALLTHROUGH */ | ||
|  | 	      case 'u': | ||
|  | 		STAR_ARGS(data); | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  | 		if (data->flags & PF_LONGLONG) | ||
|  | 		  { | ||
|  | 		    ull = va_arg(args, unsigned long long); | ||
|  | 		    lnumber(data, ull, 10); | ||
|  | 		  } | ||
|  | 		else | ||
|  | #endif
 | ||
|  | 		  { | ||
|  | 		    ul = GETUNSIGNED(data); | ||
|  | 		    number(data, ul, 10); | ||
|  | 		  } | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case 'D': | ||
|  | 		data->flags |= PF_LONGINT; | ||
|  | 		/* FALLTHROUGH */ | ||
|  | 	      case 'd':  /* decimal */ | ||
|  | 	      case 'i': | ||
|  | 		STAR_ARGS(data); | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  | 		if (data->flags & PF_LONGLONG) | ||
|  | 		  { | ||
|  | 		    ull = va_arg(args, long long); | ||
|  | 		    lnumber(data, ull, 10); | ||
|  | 		  } | ||
|  | 		else | ||
|  | #endif
 | ||
|  | 		  { | ||
|  | 		    ul = GETSIGNED(data); | ||
|  | 		    number(data, ul, 10); | ||
|  | 		  } | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case 'o':  /* octal */ | ||
|  | 		STAR_ARGS(data); | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  | 		if (data->flags & PF_LONGLONG) | ||
|  | 		  { | ||
|  | 		    ull = va_arg(args, unsigned long long); | ||
|  | 		    lnumber(data, ull, 8); | ||
|  | 		  } | ||
|  | 		else | ||
|  | #endif
 | ||
|  | 		  { | ||
|  | 		    ul = GETUNSIGNED(data); | ||
|  | 		    number(data, ul, 8); | ||
|  | 		  } | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case 'x':  | ||
|  | 	      case 'X':  /* hexadecimal */ | ||
|  | 		STAR_ARGS(data); | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  | 		if (data->flags & PF_LONGLONG) | ||
|  | 		  { | ||
|  | 		    ull = va_arg(args, unsigned long long); | ||
|  | 		    lnumber(data, ull, 16); | ||
|  | 		  } | ||
|  | 		else | ||
|  | #endif
 | ||
|  | 		  { | ||
|  | 		    ul = GETUNSIGNED(data); | ||
|  | 		    number(data, ul, 16); | ||
|  | 		  } | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case 'p': | ||
|  | 		STAR_ARGS(data); | ||
|  | 		ul = (unsigned long)va_arg(args, void *); | ||
|  | 		pointer(data, ul); | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case 'c': /* character */ | ||
|  | 		ul = va_arg(args, int); | ||
|  | 		PUT_CHAR(ul, data); | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case 's':  /* string */ | ||
|  | 		STAR_ARGS(data); | ||
|  | 		s = va_arg(args, char *); | ||
|  | 		strings(data, s); | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case 'n': | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  | 		if (data->flags & PF_LONGLONG) | ||
|  | 		  *(va_arg(args, long long *)) = data->counter; | ||
|  | 		else | ||
|  | #endif
 | ||
|  | 		if (data->flags & PF_LONGINT) | ||
|  | 		  *(va_arg(args, long *)) = data->counter; | ||
|  | 		else if (data->flags & PF_SHORTINT) | ||
|  | 		  *(va_arg(args, short *)) = data->counter; | ||
|  | 		else | ||
|  | 		  *(va_arg(args, int *)) = data->counter; | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	      case '%':  /* nothing just % */ | ||
|  | 		PUT_CHAR('%', data); | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  |   	      default: | ||
|  | 		/* is this an error ? maybe bail out */ | ||
|  | 		state = 0; | ||
|  | 		break; | ||
|  | 	} /* end switch */ | ||
|  |       } /* end of `%' for loop */ | ||
|  |     } /* end of format string for loop */ | ||
|  | 
 | ||
|  |   if (data->length >= 0) | ||
|  |     *data->holder = '\0'; /* the end ye ! */ | ||
|  | 
 | ||
|  |   return data->counter; | ||
|  | } | ||
|  | 
 | ||
|  | #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
 | ||
|  | /*
 | ||
|  |  * Printing floating point numbers accurately is an art.  I'm not good | ||
|  |  * at it.  Fall back to sprintf for long double formats. | ||
|  |  */ | ||
|  | static void | ||
|  | ldfallback (data, fs, fe, ld) | ||
|  |      struct DATA *data; | ||
|  |      const char *fs, *fe; | ||
|  |      long double ld; | ||
|  | { | ||
|  |   register char *x; | ||
|  |   char fmtbuf[FALLBACK_FMTSIZE], *obuf; | ||
|  |   int fl; | ||
|  | 
 | ||
|  |   obuf = xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2); | ||
|  |   fl = fe - fs + 1; | ||
|  |   strncpy (fmtbuf, fs, fl); | ||
|  |   fmtbuf[fl] = '\0'; | ||
|  |   sprintf (obuf, fmtbuf, ld); | ||
|  |   for (x = obuf; *x; x++) | ||
|  |     PUT_CHAR (*x, data);     | ||
|  |   xfree (obuf); | ||
|  | } | ||
|  | #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
 | ||
|  | 
 | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | /* Used for %a, %A if the libc printf supports them. */ | ||
|  | static void | ||
|  | dfallback (data, fs, fe, d) | ||
|  |      struct DATA *data; | ||
|  |      const char *fs, *fe; | ||
|  |      double d; | ||
|  | { | ||
|  |   register char *x; | ||
|  |   char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE]; | ||
|  |   int fl; | ||
|  | 
 | ||
|  |   fl = fe - fs + 1; | ||
|  |   strncpy (fmtbuf, fs, fl); | ||
|  |   fmtbuf[fl] = '\0'; | ||
|  |   sprintf (obuf, fmtbuf, d); | ||
|  |   for (x = obuf; *x; x++) | ||
|  |     PUT_CHAR (*x, data);     | ||
|  | } | ||
|  | #endif /* FLOATING_POINT */
 | ||
|  | 
 | ||
|  | #ifndef HAVE_SNPRINTF
 | ||
|  | 
 | ||
|  | int | ||
|  | #if defined (__STDC__)
 | ||
|  | vsnprintf(char *string, size_t length, const char *format, va_list args) | ||
|  | #else
 | ||
|  | vsnprintf(string, length, format, args) | ||
|  |      char *string; | ||
|  |      size_t length; | ||
|  |      const char *format; | ||
|  |      va_list args; | ||
|  | #endif
 | ||
|  | { | ||
|  |   struct DATA data; | ||
|  | 
 | ||
|  |   init_data (&data, string, length, format, PFM_SN); | ||
|  |   return (vsnprintf_internal(&data, string, length, format, args)); | ||
|  | } | ||
|  | 
 | ||
|  | int | ||
|  | #if defined(PREFER_STDARG)
 | ||
|  | snprintf(char *string, size_t length, const char * format, ...) | ||
|  | #else
 | ||
|  | snprintf(string, length, format, va_alist) | ||
|  |      char *string; | ||
|  |      size_t length; | ||
|  |      const char *format; | ||
|  |      va_dcl | ||
|  | #endif
 | ||
|  | { | ||
|  |   struct DATA data; | ||
|  |   int rval; | ||
|  |   va_list args; | ||
|  | 
 | ||
|  | #if defined(PREFER_STDARG)
 | ||
|  |   va_start(args, format); | ||
|  | #else
 | ||
|  |   va_start(args); | ||
|  | #endif
 | ||
|  | 
 | ||
|  |   init_data (&data, string, length, format, PFM_SN); | ||
|  |   rval = vsnprintf_internal (&data, string, length, format, args); | ||
|  | 
 | ||
|  |   va_end(args); | ||
|  | 
 | ||
|  |   return rval; | ||
|  | } | ||
|  | 
 | ||
|  | #endif /* HAVE_SNPRINTF */
 | ||
|  | 
 | ||
|  | #ifndef HAVE_ASPRINTF
 | ||
|  | 
 | ||
|  | int | ||
|  | #if defined (__STDC__)
 | ||
|  | vasprintf(char **stringp, const char *format, va_list args) | ||
|  | #else
 | ||
|  | vasprintf(stringp, format, args) | ||
|  |      char **stringp; | ||
|  |      const char *format; | ||
|  |      va_list args; | ||
|  | #endif
 | ||
|  | { | ||
|  |   struct DATA data; | ||
|  |   char *string; | ||
|  |   int r; | ||
|  | 
 | ||
|  |   string = (char *)xmalloc(ASBUFSIZE); | ||
|  |   init_data (&data, string, ASBUFSIZE, format, PFM_AS); | ||
|  |   r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args); | ||
|  |   *stringp = data.base;		/* not string in case reallocated */ | ||
|  |   return r; | ||
|  | } | ||
|  | 
 | ||
|  | int | ||
|  | #if defined(PREFER_STDARG)
 | ||
|  | asprintf(char **stringp, const char * format, ...) | ||
|  | #else
 | ||
|  | asprintf(stringp, format, va_alist) | ||
|  |      char **stringp; | ||
|  |      const char *format; | ||
|  |      va_dcl | ||
|  | #endif
 | ||
|  | { | ||
|  |   int rval; | ||
|  |   va_list args; | ||
|  | 
 | ||
|  | #if defined(PREFER_STDARG)
 | ||
|  |   va_start(args, format); | ||
|  | #else
 | ||
|  |   va_start(args); | ||
|  | #endif
 | ||
|  | 
 | ||
|  |   rval = vasprintf (stringp, format, args); | ||
|  | 
 | ||
|  |   va_end(args); | ||
|  | 
 | ||
|  |   return rval; | ||
|  | } | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef DRIVER
 | ||
|  | 
 | ||
|  | static void | ||
|  | memory_error_and_abort () | ||
|  | { | ||
|  |   write (2, "out of virtual memory\n", 22); | ||
|  |   abort (); | ||
|  | } | ||
|  | 
 | ||
|  | static void * | ||
|  | xmalloc(bytes) | ||
|  |      size_t bytes; | ||
|  | { | ||
|  |   void *ret; | ||
|  | 
 | ||
|  |   ret = malloc(bytes); | ||
|  |   if (ret == 0) | ||
|  |     memory_error_and_abort (); | ||
|  |   return ret; | ||
|  | } | ||
|  | 
 | ||
|  | static void * | ||
|  | xrealloc (pointer, bytes) | ||
|  |      void *pointer; | ||
|  |      size_t bytes; | ||
|  | { | ||
|  |   void *ret; | ||
|  | 
 | ||
|  |   ret = pointer ? realloc(pointer, bytes) : malloc(bytes); | ||
|  |   if (ret == 0) | ||
|  |     memory_error_and_abort (); | ||
|  |   return ret; | ||
|  | } | ||
|  | 
 | ||
|  | static void | ||
|  | xfree(x) | ||
|  |      void *x; | ||
|  | { | ||
|  |   if (x) | ||
|  |     free (x); | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef FLOATING_POINT
 | ||
|  | #  include <float.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | /* set of small tests for snprintf() */ | ||
|  | main() | ||
|  | { | ||
|  |   char holder[100]; | ||
|  |   char *h; | ||
|  |   int i, si, ai; | ||
|  | 
 | ||
|  | /*
 | ||
|  |   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("/%%ld %%ld/, 336, 336\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336); | ||
|  |   asprintf(&h, "/%ld %ld/\n", 336, 336); | ||
|  |   printf("/%ld %ld/\n", 336, 336); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%d/, 336\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%d/\n", 336); | ||
|  |   asprintf(&h, "/%d/\n", 336); | ||
|  |   printf("/%d/\n", 336); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%2d/, 336\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%2d/\n", 336); | ||
|  |   asprintf(&h, "/%2d/\n", 336); | ||
|  |   printf("/%2d/\n", 336); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%10d/, 336\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%10d/\n", 336); | ||
|  |   asprintf(&h, "/%10d/\n", 336); | ||
|  |   printf("/%10d/\n", 336); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%-10d/, 336\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%-10d/\n", 336); | ||
|  |   asprintf(&h, "/%-10d/\n", 336); | ||
|  |   printf("/%-10d/\n", 336); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  | 
 | ||
|  | /* floating points */ | ||
|  | 
 | ||
|  |   printf("/%%f/, 1234.56\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%f/\n", 1234.56); | ||
|  |   asprintf(&h, "/%f/\n", 1234.56); | ||
|  |   printf("/%f/\n", 1234.56); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%e/, 1234.56\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%e/\n", 1234.56); | ||
|  |   asprintf(&h, "/%e/\n", 1234.56); | ||
|  |   printf("/%e/\n", 1234.56); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%4.2f/, 1234.56\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56); | ||
|  |   asprintf(&h, "/%4.2f/\n", 1234.56); | ||
|  |   printf("/%4.2f/\n", 1234.56); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%3.1f/, 1234.56\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56); | ||
|  |   asprintf(&h, "/%3.1f/\n", 1234.56); | ||
|  |   printf("/%3.1f/\n", 1234.56); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%10.3f/, 1234.56\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56); | ||
|  |   asprintf(&h, "/%10.3f/\n", 1234.56); | ||
|  |   printf("/%10.3f/\n", 1234.56); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%10.3e/, 1234.56\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56); | ||
|  |   asprintf(&h, "/%10.3e/\n", 1234.56); | ||
|  |   printf("/%10.3e/\n", 1234.56); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%+4.2f/, 1234.56\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56); | ||
|  |   asprintf(&h, "/%+4.2f/\n", 1234.56); | ||
|  |   printf("/%+4.2f/\n", 1234.56); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%010.2f/, 1234.56\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56); | ||
|  |   asprintf(&h, "/%010.2f/\n", 1234.56); | ||
|  |   printf("/%010.2f/\n", 1234.56); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  | #define BLURB "Outstanding acting !"
 | ||
|  | /* strings precisions */ | ||
|  | 
 | ||
|  |   printf("/%%2s/, \"%s\"\n", BLURB); | ||
|  |   snprintf(holder, sizeof holder, "/%2s/\n", BLURB); | ||
|  |   asprintf(&h, "/%2s/\n", BLURB); | ||
|  |   printf("/%2s/\n", BLURB); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%22s/ %s\n", BLURB); | ||
|  |   snprintf(holder, sizeof holder, "/%22s/\n", BLURB); | ||
|  |   asprintf(&h, "/%22s/\n", BLURB); | ||
|  |   printf("/%22s/\n", BLURB); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%22.5s/ %s\n", BLURB); | ||
|  |   snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB); | ||
|  |   asprintf(&h, "/%22.5s/\n", BLURB); | ||
|  |   printf("/%22.5s/\n", BLURB); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%-22.5s/ %s\n", BLURB); | ||
|  |   snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB); | ||
|  |   asprintf(&h, "/%-22.5s/\n", BLURB); | ||
|  |   printf("/%-22.5s/\n", BLURB); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  | /* see some flags */ | ||
|  | 
 | ||
|  |   printf("%%x %%X %%#x, 31, 31, 31\n"); | ||
|  |   snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31); | ||
|  |   asprintf(&h, "%x %X %#x\n", 31, 31, 31); | ||
|  |   printf("%x %X %#x\n", 31, 31, 31); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("**%%d**%% d**%% d**, 42, 42, -42\n"); | ||
|  |   snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42); | ||
|  |   asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42); | ||
|  |   printf("**%d**% d**% d**\n", 42, 42, -42); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  | /* other flags */ | ||
|  | 
 | ||
|  |   printf("/%%g/, 31.4\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%g/\n", 31.4); | ||
|  |   asprintf(&h, "/%g/\n", 31.4); | ||
|  |   printf("/%g/\n", 31.4); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%.6g/, 31.4\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%.6g/\n", 31.4); | ||
|  |   asprintf(&h, "/%.6g/\n", 31.4); | ||
|  |   printf("/%.6g/\n", 31.4); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%.1G/, 31.4\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%.1G/\n", 31.4); | ||
|  |   asprintf(&h, "/%.1G/\n", 31.4); | ||
|  |   printf("/%.1G/\n", 31.4); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("/%%.1G/, 3100000000.4\n"); | ||
|  |   snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);   | ||
|  |   asprintf(&h, "/%.1G/\n", 3100000000.4);   | ||
|  |   printf("/%.1G/\n", 3100000000.4);  | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("abc%%n\n"); | ||
|  |   printf("abc%n", &i); printf("%d\n", i); | ||
|  |   snprintf(holder, sizeof holder, "abc%n", &i); | ||
|  |   printf("%s", holder); printf("%d\n\n", i); | ||
|  |   asprintf(&h, "abc%n", &i); | ||
|  |   printf("%s", h); printf("%d\n\n", i); | ||
|  |    | ||
|  |   printf("%%*.*s --> 10.10\n"); | ||
|  |   snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB); | ||
|  |   asprintf(&h, "%*.*s\n", 10, 10, BLURB); | ||
|  |   printf("%*.*s\n", 10, 10, BLURB); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  |   printf("%%%%%%%%\n"); | ||
|  |   snprintf(holder, sizeof holder, "%%%%\n"); | ||
|  |   asprintf(&h, "%%%%\n"); | ||
|  |   printf("%%%%\n"); | ||
|  |   printf("%s", holder); | ||
|  |   printf("%s\n", h); | ||
|  | 
 | ||
|  | #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 = snprintf(holder, 10, "%s\n", BIG); | ||
|  |   i = asprintf(&h, "%s", BIG); | ||
|  |   printf("<%s>\n", BIG); | ||
|  |   printf("<%s>\n", holder); | ||
|  |   printf("<%s>\n\n", h); | ||
|  | 
 | ||
|  |   printf ("<%%p> vsnprintf\n"); | ||
|  |   i = snprintf(holder, 100, "%p", vsnprintf); | ||
|  |   i = asprintf(&h, "%p", vsnprintf); | ||
|  |   printf("<%p>\n", vsnprintf); | ||
|  |   printf("<%s>\n", holder);   | ||
|  |   printf("<%s>\n\n", h); | ||
|  | 
 | ||
|  |   printf ("<%%lu> LONG_MAX+1\n"); | ||
|  |   i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1); | ||
|  |   i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1); | ||
|  |   printf("<%lu>\n", (unsigned long)(LONG_MAX)+1); | ||
|  |   printf("<%s>\n", holder); | ||
|  |   printf("<%s>\n\n", h); | ||
|  | 
 | ||
|  | #ifdef HAVE_LONG_LONG
 | ||
|  |   printf ("<%%llu> LLONG_MAX+1\n"); | ||
|  |   i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1); | ||
|  |   i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1); | ||
|  |   printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1); | ||
|  |   printf("<%s>\n", holder); | ||
|  |   printf("<%s>\n\n", h); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef HAVE_LONG_DOUBLE
 | ||
|  |   printf ("<%%6.2LE> 42.42\n"); | ||
|  |   i = snprintf(holder, 100, "%6.2LE", (long double)42.42); | ||
|  |   i = asprintf(&h, "%6.2LE", (long double)42.42); | ||
|  |   printf ("<%6.2LE>\n", (long double)42.42); | ||
|  |   printf ("<%s>\n", holder); | ||
|  |   printf ("<%s>\n\n", h); | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifdef HAVE_PRINTF_A_FORMAT
 | ||
|  |   printf ("<%%6.2A> 42.42\n"); | ||
|  |   i = snprintf(holder, 100, "%6.2A", 42.42); | ||
|  |   i = asprintf(&h, "%6.2A", 42.42); | ||
|  |   printf ("<%6.2A>\n", 42.42); | ||
|  |   printf ("<%s>\n", holder); | ||
|  |   printf ("<%s>\n\n", h); | ||
|  | 
 | ||
|  |   printf ("<%%6.2LA> 42.42\n"); | ||
|  |   i = snprintf(holder, 100, "%6.2LA", (long double)42.42); | ||
|  |   i = asprintf(&h, "%6.2LA", (long double)42.42); | ||
|  |   printf ("<%6.2LA>\n", (long double)42.42); | ||
|  |   printf ("<%s>\n", holder); | ||
|  |   printf ("<%s>\n\n", h); | ||
|  | #endif
 | ||
|  | 
 | ||
|  |   printf ("<%%.10240f> DBL_MAX\n"); | ||
|  |   si = snprintf(holder, 100, "%.10240f", DBL_MAX); | ||
|  |   ai = asprintf(&h, "%.10240f", DBL_MAX); | ||
|  |   printf ("<%.10240f>\n", DBL_MAX); | ||
|  |   printf ("<%d> <%s>\n", si, holder); | ||
|  |   printf ("<%d> <%s>\n\n", ai, h); | ||
|  | 
 | ||
|  |   printf ("<%%.10240Lf> LDBL_MAX\n"); | ||
|  |   si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX); | ||
|  |   ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX); | ||
|  |   printf ("<%.10240Lf>\n", (long double)LDBL_MAX); | ||
|  |   printf ("<%d> <%s>\n", si, holder); | ||
|  |   printf ("<%d> <%s>\n\n", ai, h); | ||
|  | 
 | ||
|  |   exit (0); | ||
|  | } | ||
|  | #endif
 |