This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] printf: Enable grouping decimal values


On 01/02/10 03:47 PM, Corinna Vinschen wrote:
Hi,

the below patch is derived from NetBSD code.  It enables printf/wprintf
grouping using the thousands' grouping character from the locale
information when the ' (single quote) flag character has been specified
in decimal conversions (i, d, u, f, F, g, G), as specified by POSIX-1.2008.

The grouping flag character was originally guarded by the
_WANT_IO_C99_FORMATS macro, so I left that intact.  The entire grouping
code is still only available with _WANT_IO_C99_FORMATS set.

A new macro has been introduced from the NetBSD code, called PRINTANDPAD.
It allowed to simplify printing of float values and taking over the
NetBSD code almost unchanged.  The most important change was to allow
thousands_sep to be a multibyte character in _VFPRINTF_R.  NetBSD erroneously
assumes that thousands_sep is a singlebyte char.

Tested on Cygwin using different locales using different decimal points,
thousands separators (including multibyte), and different groupings.

Ok to apply?


This is a tough patch to review because of all the format changes and ifdefs in the patch itself.


I did notice one spot where the size is being calculated and the grouping ptr is moved to do this calculation. I can't see anywhere where you are resetting grouping before the output is written. This seems like a mistake, but perhaps I am missing something.

-- Jeff J.

Thanks,
Corinna


* libc/stdio/vfprintf.c: Include locale.h also if _WANT_IO_C99_FORMATS is defined. Raise conversion buffer size to make sure it has enough room for numbers plus grouping character. Define GROUPING flag. (_VFPRINTF_R): Add PRINTANDPAD macro. Handle grouping flag character. Handle grouping for decimal integer and float values. * libc/stdio/vfwprintf.c: Ditto.


Index: libc/stdio/vfprintf.c =================================================================== RCS file: /cvs/src/src/newlib/libc/stdio/vfprintf.c,v retrieving revision 1.77 diff -u -p -r1.77 vfprintf.c --- libc/stdio/vfprintf.c 14 Jan 2010 12:48:58 -0000 1.77 +++ libc/stdio/vfprintf.c 1 Feb 2010 20:40:44 -0000 @@ -375,8 +375,10 @@ _DEFUN(__sbprintf, (rptr, fp, fmt, ap), #endif /* !STRING_ONLY */


-#ifdef FLOATING_POINT +#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS) # include<locale.h> +#endif +#ifdef FLOATING_POINT # include<math.h>

  /* For %La, an exponent of 15 bits occupies the exponent character, a
@@ -423,8 +425,16 @@ static int exponent(char *, int, int);
     reentrant storage shared with mprec.  All other formats that use
     buf get by with fewer characters.  Making BUF slightly bigger
     reduces the need for malloc in %.*a and %S, when large precision or
-   long strings are processed.  */
+   long strings are processed.
+   The bigger size of 100 bytes is used on systems which allow number
+   strings using the locale's grouping character.  Since that's a multibyte
+   value, we should use a conservative value.
+   */
+#ifdef _WANT_IO_C99_FORMATS
+#define	BUF		100
+#else
  #define	BUF		40
+#endif
  #if defined _MB_CAPABLE&&  MB_LEN_MAX>  BUF
  # undef BUF
  # define BUF MB_LEN_MAX
@@ -508,6 +518,9 @@ _EXFUN(get_arg, (struct _reent *data, in
  #else /* define as 0, to make SARG and UARG occupy fewer instructions  */
  # define CHARINT	0
  #endif
+#ifdef _WANT_IO_C99_FORMATS
+# define GROUPING	0x400		/* use grouping ("'" flag) */
+#endif

int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));

@@ -552,6 +565,12 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap)
  	int width;		/* width from format (%8d), or 0 */
  	int prec;		/* precision from format (%.3d), or -1 */
  	char sign;		/* sign prefix (' ', '+', '-', or \0) */
+#ifdef _WANT_IO_C99_FORMATS
+				/* locale specific numeric grouping */
+	char *thousands_sep;
+	size_t thsnd_len;
+	const char *grouping;
+#endif
  #ifdef FLOATING_POINT
  	char *decimal_point = _localeconv_r (data)->decimal_point;
  	size_t decp_len = strlen (decimal_point);
@@ -560,9 +579,16 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap)
  # define _fpvalue (_double_.fp)
  	int expt;		/* integer value of exponent */
  	int expsize = 0;	/* character count for expstr */
-	int ndig = 0;		/* actual number of digits returned by cvt */
  	char expstr[MAXEXPLEN];	/* buffer for exponent string */
+	int lead;		/* sig figs before decimal or group sep */
  #endif /* FLOATING_POINT */
+#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
+	int ndig = 0;		/* actual number of digits returned by cvt */
+#endif
+#ifdef _WANT_IO_C99_FORMATS
+	int nseps;		/* number of group separators with ' */
+	int nrepeats;		/* number of repeats of the last group */
+#endif
  	u_quad_t _uquad;	/* integer arguments %[diouxX] */
  	enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
  	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
@@ -617,6 +643,14 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap)
  		PRINT (with, n); \
  	} \
  }
+#define PRINTANDPAD(p, ep, len, with) { \
+	int n = (ep) - (p); \
+	if (n>  (len)) \
+		n = (len); \
+	if (n>  0) \
+		PRINT((p), n); \
+	PAD((len) - (n>  0 ? n : 0), (with)); \
+}
  #define	FLUSH() { \
  	if (uio.uio_resid&&  __SPRINT(data, fp,&uio)) \
  		goto error; \
@@ -757,6 +791,12 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap)
  		width = 0;
  		prec = -1;
  		sign = '\0';
+#ifdef FLOATING_POINT
+		lead = 0;
+#endif
+#ifdef _WANT_IO_C99_FORMATS
+		nseps = nrepeats = 0;
+#endif
  #ifndef _NO_POS_ARGS
  		N = arg_index;
  		is_pos_arg = 0;
@@ -766,12 +806,12 @@ rflag:		ch = *fmt++;
  reswitch:	switch (ch) {
  #ifdef _WANT_IO_C99_FORMATS
  		case '\'':
-		  /* The ' flag is required by POSIX, but not C99.
-		     In the C locale, LC_NUMERIC requires
-		     thousands_sep to be the empty string.  And since
-		     no other locales are supported (yet), this flag
-		     is currently a no-op.  */
-		  goto rflag;
+			thousands_sep = _localeconv_r (data)->thousands_sep;
+			thsnd_len = strlen (thousands_sep);
+			grouping = _localeconv_r (data)->grouping;
+			if (thsnd_len>  0&&  grouping&&  *grouping)
+			  flags |= GROUPING;
+			goto rflag;
  #endif
  		case ' ':
  			/*
@@ -1140,22 +1180,46 @@ reswitch:	switch (ch) {
  				size = expsize + ndig;
  				if (ndig>  1 || flags&  ALT)
  					++size;
-			} else if (ch == 'f') {		/* f fmt */
-				if (expt>  0) {
+# ifdef _WANT_IO_C99_FORMATS
+				flags&= ~GROUPING;
+# endif
+			} else {
+				if (ch == 'f') {		/* f fmt */
+					if (expt>  0) {
+						size = expt;
+						if (prec || flags&  ALT)
+							size += prec + 1;
+					} else	/* "0.X" */
+						size = (prec || flags&  ALT)
+							  ? prec + 2
+							  : 1;
+				} else if (expt>= ndig) { /* fixed g fmt */
  					size = expt;
-					if (prec || flags&  ALT)
-						size += prec + 1;
-				} else	/* "0.X" */
-					size = (prec || flags&  ALT)
-						  ? prec + 2
-						  : 1;
-			} else if (expt>= ndig) {	/* fixed g fmt */
-				size = expt;
-				if (flags&  ALT)
-					++size;
-			} else
-				size = ndig + (expt>  0 ?
-					1 : 2 - expt);
+					if (flags&  ALT)
+						++size;
+				} else
+					size = ndig + (expt>  0 ?
+						1 : 2 - expt);
+# ifdef _WANT_IO_C99_FORMATS
+				if ((flags&  GROUPING)&&  expt>  0) {
+					/* space for thousands' grouping */
+					nseps = nrepeats = 0;
+					lead = expt;
+					while (*grouping != CHAR_MAX) {
+						if (lead<= *grouping)
+							break;
+						lead -= *grouping;
+						if (grouping[1]) {
+							nseps++;
+							grouping++;

********** here you are altering "grouping", but only size is being calculated. ************************
+						} else
+							nrepeats++;
+					}
+					size += (nseps + nrepeats) * thsnd_len;
+				} else
+# endif
+					lead = expt;
+			}

  			if (softsign)
  				sign = '-';
@@ -1184,6 +1248,9 @@ reswitch:	switch (ch) {
  		case 'o':
  			_uquad = UARG ();
  			base = OCT;
+#ifdef _WANT_IO_C99_FORMATS
+			flags&= ~GROUPING;
+#endif
  			goto nosign;
  		case 'p':
  			/*
@@ -1320,6 +1387,9 @@ hex:			_uquad = UARG ();
  				flags |= HEXPREFIX;
  			}

+#ifdef _WANT_IO_C99_FORMATS
+			flags&= ~GROUPING;
+#endif
  			/* unsigned conversions */
  nosign:			sign = '\0';
  			/*
@@ -1355,11 +1425,37 @@ number:			if ((dprec = prec)>= 0)

  				case DEC:
  					/* many numbers are 1 digit */
-					while (_uquad>= 10) {
-						*--cp = to_char (_uquad % 10);
-						_uquad /= 10;
+					if (_uquad<  10) {
+						*--cp = to_char(_uquad);
+						break;
  					}
-					*--cp = to_char (_uquad);
+#ifdef _WANT_IO_C99_FORMATS
+					ndig = 0;
+#endif
+					do {
+					  *--cp = to_char (_uquad % 10);
+#ifdef _WANT_IO_C99_FORMATS
+					  ndig++;
+					  /* If (*grouping == CHAR_MAX) then no
+					     more grouping */
+					  if ((flags&  GROUPING)
+					&&  ndig == *grouping
+					&&  *grouping != CHAR_MAX
+					&&  _uquad>  9) {
+					    cp -= thsnd_len;
+					    strncpy (cp, thousands_sep,
+						     thsnd_len);
+					    ndig = 0;
+					    /* If (grouping[1] == '\0') then we
+					       have to use *grouping character
+					       (last grouping rule) for all
+					       next cases. */
+					    if (grouping[1] != '\0')
+					      grouping++;
+					  }
+#endif
+					  _uquad /= 10;
+					} while (_uquad != 0);
  					break;

  				case HEX:
@@ -1459,16 +1555,33 @@ number:			if ((dprec = prec)>= 0)
  						PAD (-expt, zeroes);
  						PRINT (cp, ndig);
  					}
-				} else if (expt>= ndig) {
-					PRINT (cp, ndig);
-					PAD (expt - ndig, zeroes);
-					if (flags&  ALT)
-						PRINT (decimal_point, decp_len);
  				} else {
-					PRINT (cp, expt);
-					cp += expt;
-					PRINT (decimal_point, decp_len);
-					PRINT (cp, ndig - expt);
+					char *convbuf = cp;
+					PRINTANDPAD(cp, convbuf + ndig,
+						    lead, zeroes);
+					cp += lead;
+#ifdef _WANT_IO_C99_FORMATS
+					if (flags&  GROUPING) {
+					    while (nseps>  0 || nrepeats>  0) {
+						if (nrepeats>  0)
+						    nrepeats--;
+						else {
+						    grouping--;
+						    nseps--;
+						}
+						PRINT(thousands_sep, thsnd_len);
+						PRINTANDPAD (cp, convbuf + ndig,
+							     *grouping, zeroes);
+						cp += *grouping;
+					    }
+					    if (cp>  convbuf + ndig)
+						cp = convbuf + ndig;
+					}
+#endif
+					if (prec || flags&  ALT)
+					    PRINT (decimal_point, decp_len);
+					PRINTANDPAD (cp, convbuf + ndig,
+						     ndig - expt, zeroes);
  				}
  			} else {	/* 'a', 'A', 'e', or 'E' */
  				if (ndig>  1 || flags&  ALT) {
Index: libc/stdio/vfwprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfwprintf.c,v
retrieving revision 1.2
diff -u -p -r1.2 vfwprintf.c
--- libc/stdio/vfwprintf.c	12 Mar 2009 10:27:10 -0000	1.2
+++ libc/stdio/vfwprintf.c	1 Feb 2010 20:40:44 -0000
@@ -201,8 +201,10 @@ _DEFUN(__sbwprintf, (rptr, fp, fmt, ap),
  #endif /* !STRING_ONLY */


-#ifdef FLOATING_POINT +#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS) # include<locale.h> +#endif +#ifdef FLOATING_POINT # include<math.h>

  /* For %La, an exponent of 15 bits occupies the exponent character, a
@@ -249,8 +251,16 @@ static int wexponent(wchar_t *, int, int
     reentrant storage shared with mprec.  All other formats that use
     buf get by with fewer characters.  Making BUF slightly bigger
     reduces the need for malloc in %.*a and %ls/%S, when large precision or
-   long strings are processed.  */
+   long strings are processed.
+   The bigger size of 100 bytes is used on systems which allow number
+   strings using the locale's grouping character.  Since that's a multibyte
+   value, we should use a conservative value.
+   */
+#ifdef _WANT_IO_C99_FORMATS
+#define BUF             100
+#else
  #define	BUF		40
+#endif
  #if defined _MB_CAPABLE&&  MB_LEN_MAX>  BUF
  # undef BUF
  # define BUF MB_LEN_MAX
@@ -336,6 +346,9 @@ _EXFUN(get_arg, (struct _reent *data, in
  #else /* define as 0, to make SARG and UARG occupy fewer instructions  */
  # define CHARINT	0
  #endif
+#ifdef _WANT_IO_C99_FORMATS
+# define GROUPING	0x400		/* use grouping ("'" flag) */
+#endif

  #ifndef STRING_ONLY
  int
@@ -378,19 +391,31 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap
  	int width;		/* width from format (%8d), or 0 */
  	int prec;		/* precision from format (%.3d), or -1 */
  	wchar_t sign;		/* sign prefix (' ', '+', '-', or \0) */
-#ifdef FLOATING_POINT
-	wchar_t decimal_point;
+#ifdef _WANT_IO_C99_FORMATS
+				/* locale specific numeric grouping */
+	wchar_t thousands_sep;
+	const char *grouping;
+#endif
  #ifdef _MB_CAPABLE
  	mbstate_t state;        /* mbtowc calls from library must not change state */
  #endif
+#ifdef FLOATING_POINT
+	wchar_t decimal_point;
  	wchar_t softsign;		/* temporary negative sign for floats */
  	union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
  # define _fpvalue (_double_.fp)
  	int expt;		/* integer value of exponent */
  	int expsize = 0;	/* character count for expstr */
-	int ndig = 0;		/* actual number of digits returned by wcvt */
  	wchar_t expstr[MAXEXPLEN];	/* buffer for exponent string */
+	int lead;		/* sig figs before decimal or group sep */
  #endif /* FLOATING_POINT */
+#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
+	int ndig = 0;		/* actual number of digits returned by cvt */
+#endif
+#ifdef _WANT_IO_C99_FORMATS
+	int nseps;		/* number of group separators with ' */
+	int nrepeats;		/* number of repeats of the last group */
+#endif
  	u_quad_t _uquad;	/* integer arguments %[diouxX] */
  	enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
  	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
@@ -419,9 +444,16 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap

  #ifdef FLOATING_POINT
  #ifdef _MB_CAPABLE
-	memset (&state, '\0', sizeof (state));
-	_mbrtowc_r (data,&decimal_point, _localeconv_r (data)->decimal_point,
-		    MB_CUR_MAX,&state);
+	{
+	  size_t nconv;
+
+	  memset (&state, '\0', sizeof (state));
+	  nconv = _mbrtowc_r (data,&decimal_point,
+			      _localeconv_r (data)->decimal_point,
+			      MB_CUR_MAX,&state);
+	  if (nconv == (size_t) -1 || nconv == (size_t) -2)
+	    decimal_point = L'.';
+	}
  #else
  	decimal_point = (wchar_t) *_localeconv_r (data)->decimal_point;
  #endif
@@ -449,6 +481,14 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap
  		PRINT (with, n); \
  	} \
  }
+#define PRINTANDPAD(p, ep, len, with) { \
+	int n = (ep) - (p); \
+	if (n>  (len)) \
+		n = (len); \
+	if (n>  0) \
+		PRINT((p), n); \
+	PAD((len) - (n>  0 ? n : 0), (with)); \
+}
  #define	FLUSH() { \
  	if (uio.uio_resid&&  __SPRINT(data, fp,&uio)) \
  		goto error; \
@@ -570,6 +610,12 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap
  		width = 0;
  		prec = -1;
  		sign = L'\0';
+#ifdef FLOATING_POINT
+		lead = 0;
+#endif
+#ifdef _WANT_IO_C99_FORMATS
+		nseps = nrepeats = 0;
+#endif
  #ifndef _NO_POS_ARGS
  		N = arg_index;
  		is_pos_arg = 0;
@@ -579,8 +625,23 @@ rflag:		ch = *fmt++;
  reswitch:	switch (ch) {
  #ifdef _WANT_IO_C99_FORMATS
  		case L'\'':
-		  /* The ' flag is required by POSIX, but not C99.
-		     FIXME:  this flag is currently a no-op.  */
+#ifdef _MB_CAPABLE
+		  {
+		    size_t nconv;
+
+		    memset (&state, '\0', sizeof (state));
+		    nconv = _mbrtowc_r (data,&thousands_sep,
+					_localeconv_r (data)->thousands_sep,
+					MB_CUR_MAX,&state);
+		    if (nconv == (size_t) -1 || nconv == (size_t) -2)
+		      thousands_sep = L'\0';
+		  }
+#else
+		  thousands_sep = (wchar_t) *_localeconv_r(data)->thousands_sep;
+#endif
+		  grouping = _localeconv_r (data)->grouping;
+		  if (thousands_sep&&  grouping&&  *grouping)
+		    flags |= GROUPING;
  		  goto rflag;
  #endif
  		case L' ':
@@ -942,23 +1003,46 @@ reswitch:	switch (ch) {
  				size = expsize + ndig;
  				if (ndig>  1 || flags&  ALT)
  					++size;
-			} else if (ch == L'f') {		/* f fmt */
-				if (expt>  0) {
+# ifdef _WANT_IO_C99_FORMATS
+				flags&= ~GROUPING;
+# endif
+			} else {
+				if (ch == L'f') {		/* f fmt */
+					if (expt>  0) {
+						size = expt;
+						if (prec || flags&  ALT)
+							size += prec + 1;
+					} else	/* "0.X" */
+						size = (prec || flags&  ALT)
+							  ? prec + 2
+							  : 1;
+				} else if (expt>= ndig) { /* fixed g fmt */
  					size = expt;
-					if (prec || flags&  ALT)
-						size += prec + 1;
-				} else	/* "0.X" */
-					size = (prec || flags&  ALT)
-						  ? prec + 2
-						  : 1;
-			} else if (expt>= ndig) {	/* fixed g fmt */
-				size = expt;
-				if (flags&  ALT)
-					++size;
-			} else
-				size = ndig + (expt>  0 ?
-					1 : 2 - expt);
-
+					if (flags&  ALT)
+						++size;
+				} else
+					size = ndig + (expt>  0 ?
+						1 : 2 - expt);
+# ifdef _WANT_IO_C99_FORMATS
+				if ((flags&  GROUPING)&&  expt>  0) {
+					/* space for thousands' grouping */
+					nseps = nrepeats = 0;
+					lead = expt;
+					while (*grouping != CHAR_MAX) {
+						if (lead<= *grouping)
+							break;
+						lead -= *grouping;
+						if (grouping[1]) {
+							nseps++;
+							grouping++;
+						} else
+							nrepeats++;
+					}
+					size += nseps + nrepeats;
+				} else
+# endif
+				lead = expt;
+			}
  			if (softsign)
  				sign = L'-';
  			break;
@@ -983,6 +1067,9 @@ reswitch:	switch (ch) {
  		case L'o':
  			_uquad = UARG ();
  			base = OCT;
+#ifdef _WANT_IO_C99_FORMATS
+			flags&= ~GROUPING;
+#endif
  			goto nosign;
  		case L'p':
  			/*
@@ -1106,6 +1193,9 @@ hex:			_uquad = UARG ();
  				flags |= HEXPREFIX;
  			}

+#ifdef _WANT_IO_C99_FORMATS
+			flags&= ~GROUPING;
+#endif
  			/* unsigned conversions */
  nosign:			sign = L'\0';
  			/*
@@ -1141,11 +1231,35 @@ number:			if ((dprec = prec)>= 0)

  				case DEC:
  					/* many numbers are 1 digit */
-					while (_uquad>= 10) {
-						*--cp = to_char (_uquad % 10);
-						_uquad /= 10;
+					if (_uquad<  10) {
+						*--cp = to_char(_uquad);
+						break;
  					}
-					*--cp = to_char (_uquad);
+#ifdef _WANT_IO_C99_FORMATS
+					ndig = 0;
+#endif
+					do {
+					  *--cp = to_char (_uquad % 10);
+#ifdef _WANT_IO_C99_FORMATS
+					  ndig++;
+					  /* If (*grouping == CHAR_MAX) then no
+					     more grouping */
+					  if ((flags&  GROUPING)
+					&&  ndig == *grouping
+					&&  *grouping != CHAR_MAX
+					&&  _uquad>  9) {
+					    *--cp = thousands_sep;
+					    ndig = 0;
+					    /* If (grouping[1] == '\0') then we
+					       have to use *grouping character
+					       (last grouping rule) for all
+					       next cases. */
+					    if (grouping[1] != '\0')
+					      grouping++;
+					  }
+#endif
+					  _uquad /= 10;
+					} while (_uquad != 0);
  					break;

  				case HEX:
@@ -1245,17 +1359,35 @@ number:			if ((dprec = prec)>= 0)
  						PAD (-expt, zeroes);
  						PRINT (cp, ndig);
  					}
-				} else if (expt>= ndig) {
-					PRINT (cp, ndig);
-					PAD (expt - ndig, zeroes);
-					if (flags&  ALT)
-						PRINT (&decimal_point, 1);
  				} else {
-					PRINT (cp, expt);
-					cp += expt;
-					PRINT (&decimal_point, 1);
-					PRINT (cp, ndig - expt);
+					wchar_t *convbuf = cp;
+					PRINTANDPAD(cp, convbuf + ndig,
+						    lead, zeroes);
+					cp += lead;
+#ifdef _WANT_IO_C99_FORMATS
+					if (flags&  GROUPING) {
+					    while (nseps>  0 || nrepeats>  0) {
+						if (nrepeats>  0)
+						    nrepeats--;
+						else {
+						    grouping--;
+						    nseps--;
+						}
+						PRINT (&thousands_sep, 1);
+						PRINTANDPAD (cp, convbuf + ndig,
+							     *grouping, zeroes);
+						cp += *grouping;
+					    }
+					    if (cp>  convbuf + ndig)
+						cp = convbuf + ndig;
+					}
+#endif
+					if (prec || flags&  ALT)
+					    PRINT (&decimal_point, 1);
+					PRINTANDPAD (cp, convbuf + ndig,
+						     ndig - expt, zeroes);
  				}
+
  			} else {	/* 'a', 'A', 'e', or 'E' */
  				if (ndig>  1 || flags&  ALT) {
  					PRINT (cp, 1);




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]