[BACK]Return to strfmon.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / stdlib

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libc/stdlib/strfmon.c between version 1.1 and 1.12

version 1.1, 2005/04/03 20:09:29 version 1.12, 2017/11/27 22:43:07
Line 36  __RCSID("$NetBSD$");
Line 36  __RCSID("$NetBSD$");
 #endif  #endif
 #endif /* LIBC_SCCS and not lint */  #endif /* LIBC_SCCS and not lint */
   
 #if defined(__NetBSD__)  
 #include "namespace.h"  #include "namespace.h"
 #include <monetary.h>  
 #endif  
   
 #include <sys/types.h>  #include <sys/types.h>
   #include <assert.h>
 #include <ctype.h>  #include <ctype.h>
 #include <errno.h>  #include <errno.h>
 #include <limits.h>  #include <limits.h>
 #include <locale.h>  #include <locale.h>
   #include <monetary.h>
 #include <stdarg.h>  #include <stdarg.h>
   #include <stddef.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
   
   #include "setlocale_local.h"
   
 /* internal flags */  /* internal flags */
 #define NEED_GROUPING           0x01    /* print digits grouped (default) */  #define NEED_GROUPING           0x01    /* print digits grouped (default) */
 #define SIGN_POSN_USED          0x02    /* '+' or '(' usage flag */  #define SIGN_POSN_USED          0x02    /* '+' or '(' usage flag */
Line 61  __RCSID("$NetBSD$");
Line 63  __RCSID("$NetBSD$");
 #define USE_INTL_CURRENCY       0x40    /* use international currency symbol */  #define USE_INTL_CURRENCY       0x40    /* use international currency symbol */
 #define IS_NEGATIVE             0x80    /* is argument value negative ? */  #define IS_NEGATIVE             0x80    /* is argument value negative ? */
   
   #ifndef NBCHAR_MAX
   #define NBCHAR_MAX ((unsigned char)CHAR_MAX)
   #endif
   
 /* internal macros */  /* internal macros */
 #define PRINT(CH) do {                                          \  #define PRINT(CH) do {                                          \
         if (dst >= s + maxsize)                                 \          if (dst >= s + maxsize)                                 \
Line 69  __RCSID("$NetBSD$");
Line 75  __RCSID("$NetBSD$");
 } while (/* CONSTCOND */ 0)  } while (/* CONSTCOND */ 0)
   
 #define PRINTS(STR) do {                                        \  #define PRINTS(STR) do {                                        \
         char *tmps = STR;                                       \          const char *tmps = STR;                                 \
         while (*tmps != '\0')                                   \          while (*tmps != '\0')                                   \
                 PRINT(*tmps++);                                 \                  PRINT(*tmps++);                                 \
 } while (/* CONSTCOND */ 0)  } while (/* CONSTCOND */ 0)
Line 79  __RCSID("$NetBSD$");
Line 85  __RCSID("$NetBSD$");
         while (isdigit((unsigned char)*fmt)) {                  \          while (isdigit((unsigned char)*fmt)) {                  \
                 VAR *= 10;                                      \                  VAR *= 10;                                      \
                 VAR += *fmt - '0';                              \                  VAR += *fmt - '0';                              \
                   if (VAR > 0x00ffffff)                           \
                           goto e2big_error;                       \
                 fmt++;                                          \                  fmt++;                                          \
         }                                                       \          }                                                       \
 } while (/* CONSTCOND */ 0)  } while (/* CONSTCOND */ 0)
Line 96  __RCSID("$NetBSD$");
Line 104  __RCSID("$NetBSD$");
         groups++;                                               \          groups++;                                               \
 } while (/* CONSTCOND */ 0)  } while (/* CONSTCOND */ 0)
   
 static void __setup_vars(int, char *, char *, char *, char **);  static void __setup_vars(struct lconv *, int, char *, char *, char *, const char **);
 static int __calc_left_pad(int, char *);  static int __calc_left_pad(struct lconv *, int, char *);
 static char *__format_grouped_double(double, int *, int, int, int);  static char *__format_grouped_double(struct lconv *, double, int *, int, int, int);
   
 ssize_t  static ssize_t
 strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,  vstrfmon_l(char * __restrict s, size_t maxsize, locale_t loc,
     ...)      const char * __restrict format, va_list ap)
 {  {
         va_list         ap;  
         char            *dst;           /* output destination pointer */          char            *dst;           /* output destination pointer */
         const char      *fmt;           /* current format poistion pointer */          const char      *fmt;           /* current format poistion pointer */
         struct lconv    *lc;            /* pointer to lconv structure */          struct lconv    *lc;            /* pointer to lconv structure */
Line 122  strfmon(char * __restrict s, size_t maxs
Line 129  strfmon(char * __restrict s, size_t maxs
         char            cs_precedes,    /* values gathered from struct lconv */          char            cs_precedes,    /* values gathered from struct lconv */
                         sep_by_space,                          sep_by_space,
                         sign_posn,                          sign_posn,
                         *signstr,  
                         *currency_symbol;                          *currency_symbol;
           const char      *signstr;
   
         char            *tmpptr;        /* temporary vars */          char            *tmpptr;        /* temporary vars */
         int             sverrno;          int             sverrno;
   
         va_start(ap, format);          lc = localeconv_l(loc);
   
         lc = localeconv();  
         dst = s;          dst = s;
         fmt = format;          fmt = format;
         asciivalue = NULL;          asciivalue = NULL;
Line 195  strfmon(char * __restrict s, size_t maxs
Line 200  strfmon(char * __restrict s, size_t maxs
   
                 /* field Width */                  /* field Width */
                 if (isdigit((unsigned char)*fmt)) {                  if (isdigit((unsigned char)*fmt)) {
                           ptrdiff_t d = dst - s;
                         GET_NUMBER(width);                          GET_NUMBER(width);
                         /* Do we have enough space to put number with                          /* Do we have enough space to put number with
                          * required width ?                           * required width ?
                          */                           */
                         if (dst + width >= s + maxsize)  
                           if ((size_t)(d + width) >= maxsize)
                                 goto e2big_error;                                  goto e2big_error;
                 }                  }
   
Line 230  strfmon(char * __restrict s, size_t maxs
Line 237  strfmon(char * __restrict s, size_t maxs
                                 goto format_error;                                  goto format_error;
                 }                  }
   
                   if (currency_symbol)
                           free(currency_symbol);
                 if (flags & USE_INTL_CURRENCY) {                  if (flags & USE_INTL_CURRENCY) {
                         currency_symbol = strdup(lc->int_curr_symbol);                          currency_symbol = strdup(lc->int_curr_symbol);
                         if (currency_symbol != NULL)                          if (currency_symbol != NULL &&
                                 space_char = *(currency_symbol+3);                              strlen(currency_symbol) > 3) {
                                   space_char = currency_symbol[3];
                                   currency_symbol[3] = '\0';
                           }
   
                 } else                  } else
                         currency_symbol = strdup(lc->currency_symbol);                          currency_symbol = strdup(lc->currency_symbol);
   
Line 251  strfmon(char * __restrict s, size_t maxs
Line 264  strfmon(char * __restrict s, size_t maxs
   
                 /* fill left_prec with amount of padding chars */                  /* fill left_prec with amount of padding chars */
                 if (left_prec >= 0) {                  if (left_prec >= 0) {
                         pad_size = __calc_left_pad((flags ^ IS_NEGATIVE),                          pad_size = __calc_left_pad(lc, (flags ^ IS_NEGATIVE),
                                                         currency_symbol) -                                                          currency_symbol) -
                                    __calc_left_pad(flags, currency_symbol);                                     __calc_left_pad(lc, flags, currency_symbol);
                         if (pad_size < 0)                          if (pad_size < 0)
                                 pad_size = 0;                                  pad_size = 0;
                 }                  }
   
                 asciivalue = __format_grouped_double(value, &flags,                  asciivalue = __format_grouped_double(lc, value, &flags,
                                 left_prec, right_prec, pad_char);                                  left_prec, right_prec, pad_char);
                 if (asciivalue == NULL)                  if (asciivalue == NULL)
                         goto end_error;         /* errno already set     */                          goto end_error;         /* errno already set     */
                                                 /* to ENOMEM by malloc() */                                                  /* to ENOMEM by malloc() */
   
                 /* set some variables for later use */                  /* set some variables for later use */
                 __setup_vars(flags, &cs_precedes, &sep_by_space,                  __setup_vars(lc, flags, &cs_precedes, &sep_by_space,
                                 &sign_posn, &signstr);                                  &sign_posn, &signstr);
   
                 /*                  /*
Line 369  strfmon(char * __restrict s, size_t maxs
Line 382  strfmon(char * __restrict s, size_t maxs
                                 while (dst - tmpptr < width)                                  while (dst - tmpptr < width)
                                         PRINT(' ');                                          PRINT(' ');
                         } else {                          } else {
                                 pad_size = dst-tmpptr;                                  _DIAGASSERT(__type_fit(int, dst - tmpptr));
                                   pad_size = dst - tmpptr;
                                 memmove(tmpptr + width-pad_size, tmpptr,                                  memmove(tmpptr + width-pad_size, tmpptr,
                                     (size_t) pad_size);                                      (size_t) pad_size);
                                 memset(tmpptr, ' ', (size_t) width-pad_size);                                  memset(tmpptr, ' ', (size_t) width-pad_size);
Line 379  strfmon(char * __restrict s, size_t maxs
Line 393  strfmon(char * __restrict s, size_t maxs
         }          }
   
         PRINT('\0');          PRINT('\0');
         va_end(ap);  
         free(asciivalue);          free(asciivalue);
         free(currency_symbol);          free(currency_symbol);
         return (dst - s - 1);   /* return size of put data except trailing '\0' */          return (dst - s - 1);   /* return size of put data except trailing '\0' */
Line 398  end_error:
Line 411  end_error:
         if (currency_symbol != NULL)          if (currency_symbol != NULL)
                 free(currency_symbol);                  free(currency_symbol);
         errno = sverrno;          errno = sverrno;
         va_end(ap);  
         return (-1);          return (-1);
 }  }
   
 static void  static void
 __setup_vars(int flags, char *cs_precedes, char *sep_by_space,  __setup_vars(struct lconv *lc, int flags, char *cs_precedes, char *sep_by_space,
                 char *sign_posn, char **signstr) {                  char *sign_posn, const char **signstr) {
   
         struct lconv *lc = localeconv();  
   
         if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) {          if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) {
                 *cs_precedes = lc->int_n_cs_precedes;                  *cs_precedes = lc->int_n_cs_precedes;
                 *sep_by_space = lc->int_n_sep_by_space;                  *sep_by_space = lc->int_n_sep_by_space;
                 *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_n_sign_posn;                  *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_n_sign_posn;
                 *signstr = (lc->negative_sign == '\0') ? "-"                  *signstr = (*lc->negative_sign == '\0') ? "-"
                     : lc->negative_sign;                      : lc->negative_sign;
         } else if (flags & USE_INTL_CURRENCY) {          } else if (flags & USE_INTL_CURRENCY) {
                 *cs_precedes = lc->int_p_cs_precedes;                  *cs_precedes = lc->int_p_cs_precedes;
Line 423  __setup_vars(int flags, char *cs_precede
Line 433  __setup_vars(int flags, char *cs_precede
                 *cs_precedes = lc->n_cs_precedes;                  *cs_precedes = lc->n_cs_precedes;
                 *sep_by_space = lc->n_sep_by_space;                  *sep_by_space = lc->n_sep_by_space;
                 *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->n_sign_posn;                  *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->n_sign_posn;
                 *signstr = (lc->negative_sign == '\0') ? "-"                  *signstr = (*lc->negative_sign == '\0') ? "-"
                     : lc->negative_sign;                      : lc->negative_sign;
         } else {          } else {
                 *cs_precedes = lc->p_cs_precedes;                  *cs_precedes = lc->p_cs_precedes;
Line 432  __setup_vars(int flags, char *cs_precede
Line 442  __setup_vars(int flags, char *cs_precede
                 *signstr = lc->positive_sign;                  *signstr = lc->positive_sign;
         }          }
   
         /* Set defult values for unspecified information. */          /* Set default values for unspecified information. */
         if (*cs_precedes != 0)          if (*cs_precedes != 0)
                 *cs_precedes = 1;                  *cs_precedes = 1;
         if (*sep_by_space == CHAR_MAX)          if ((unsigned char)*sep_by_space == NBCHAR_MAX)
                 *sep_by_space = 0;                  *sep_by_space = 1;
         if (*sign_posn == CHAR_MAX)          if ((unsigned char)*sign_posn == NBCHAR_MAX)
                 *sign_posn = 0;                  *sign_posn = 0;
 }  }
   
 static int  static int
 __calc_left_pad(int flags, char *cur_symb) {  __calc_left_pad(struct lconv *lc, int flags, char *cur_symb) {
   
         char cs_precedes, sep_by_space, sign_posn, *signstr;          char cs_precedes, sep_by_space, sign_posn;
         int left_chars = 0;          const char *signstr;
           size_t left_chars = 0;
   
         __setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr);          __setup_vars(lc, flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr);
   
         if (cs_precedes != 0) {          if (cs_precedes != 0) {
                 left_chars += strlen(cur_symb);                  left_chars += strlen(cur_symb);
Line 464  __calc_left_pad(int flags, char *cur_sym
Line 475  __calc_left_pad(int flags, char *cur_sym
                         if (cs_precedes != 0)                          if (cs_precedes != 0)
                                 left_chars += strlen(signstr);                                  left_chars += strlen(signstr);
         }          }
         return (left_chars);          _DIAGASSERT(__type_fit(int, left_chars));
           return (int)left_chars;
 }  }
   
 static int  static int
Line 472  get_groups(int size, char *grouping) {
Line 484  get_groups(int size, char *grouping) {
   
         int     chars = 0;          int     chars = 0;
   
         if (*grouping == CHAR_MAX || *grouping <= 0)    /* no grouping ? */          if ((unsigned char)*grouping == NBCHAR_MAX || *grouping <= 0)   /* no grouping ? */
                 return (0);                  return (0);
   
         while (size > (int)*grouping) {          while (size > (int)*grouping) {
                 chars++;                  chars++;
                 size -= (int)*grouping++;                  size -= (int)*grouping++;
                 /* no more grouping ? */                  /* no more grouping ? */
                 if (*grouping == CHAR_MAX)                  if ((unsigned char)*grouping == NBCHAR_MAX)
                         break;                          break;
                 /* rest grouping with same value ? */                  /* rest grouping with same value ? */
                 if (*grouping == 0) {                  if (*grouping == 0) {
Line 492  get_groups(int size, char *grouping) {
Line 504  get_groups(int size, char *grouping) {
   
 /* convert double to ASCII */  /* convert double to ASCII */
 static char *  static char *
 __format_grouped_double(double value, int *flags,  __format_grouped_double(struct lconv *lc, double value, int *flags,
                         int left_prec, int right_prec, int pad_char) {                          int left_prec, int right_prec, int pad_char) {
   
         char            *rslt;          char            *rslt;
         char            *avalue;          char            *avalue;
         int             avalue_size;          int             avalue_size;
         char            fmt[32];  
   
         size_t          bufsize;          size_t          bufsize;
         char            *bufend;          char            *bufend;
   
         int             padded;          int             padded;
   
         struct lconv    *lc = localeconv();  
         char            *grouping;          char            *grouping;
         char            decimal_point;          char            decimal_point;
         char            thousands_sep;          char            thousands_sep;
Line 539  __format_grouped_double(double value, in
Line 549  __format_grouped_double(double value, in
                 left_prec += get_groups(left_prec, grouping);                  left_prec += get_groups(left_prec, grouping);
   
         /* convert to string */          /* convert to string */
         snprintf(fmt, sizeof(fmt), "%%%d.%df", left_prec + right_prec + 1,          avalue_size = asprintf(&avalue, "%*.*f", left_prec + right_prec + 1,
             right_prec);              right_prec, value);
         avalue_size = asprintf(&avalue, fmt, value);  
         if (avalue_size < 0)          if (avalue_size < 0)
                 return (NULL);                  return (NULL);
   
         /* make sure that we've enough space for result string */          /* make sure that we've enough space for result string */
         bufsize = strlen(avalue)*2+1;          bufsize = avalue_size * 2 + 1;
         rslt = malloc(bufsize);          rslt = malloc(bufsize);
         if (rslt == NULL) {          if (rslt == NULL) {
                 free(avalue);                  free(avalue);
Line 570  __format_grouped_double(double value, in
Line 579  __format_grouped_double(double value, in
                 avalue_size -= (right_prec + 1);                  avalue_size -= (right_prec + 1);
         }          }
   
           /* XXX: Why not use %' instead? */
         if ((*flags & NEED_GROUPING) &&          if ((*flags & NEED_GROUPING) &&
             thousands_sep != '\0' &&    /* XXX: need investigation */              thousands_sep != '\0' &&    /* XXX: need investigation */
             *grouping != CHAR_MAX &&              (unsigned char)*grouping != NBCHAR_MAX &&
             *grouping > 0) {              *grouping > 0) {
                 while (avalue_size > (int)*grouping) {                  while (avalue_size > (int)*grouping) {
                         GRPCPY(*grouping);                          GRPCPY(*grouping);
Line 580  __format_grouped_double(double value, in
Line 590  __format_grouped_double(double value, in
                         grouping++;                          grouping++;
   
                         /* no more grouping ? */                          /* no more grouping ? */
                         if (*grouping == CHAR_MAX)                          if ((unsigned char)*grouping == NBCHAR_MAX)
                                 break;                                  break;
   
                         /* rest grouping with same value ? */                          /* rest grouping with same value ? */
Line 609  __format_grouped_double(double value, in
Line 619  __format_grouped_double(double value, in
                 memset(bufend, pad_char, (size_t) padded);                  memset(bufend, pad_char, (size_t) padded);
         }          }
   
         bufsize = bufsize - (bufend - rslt) + 1;          memmove(rslt, bufend, bufend - rslt + 1);
         memmove(rslt, bufend, bufsize);  
         free(avalue);          free(avalue);
         return (rslt);          return (rslt);
 }  }
   
   ssize_t
   strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,
       ...)
   {
           ssize_t rv;
           va_list ap;
   
           va_start(ap, format);
           rv = vstrfmon_l(s, maxsize, _current_locale(), format, ap);
           va_end(ap);
   
           return rv;
   }
   
   ssize_t
   strfmon_l(char * __restrict s, size_t maxsize, locale_t loc,
       const char * __restrict format, ...)
   {
           ssize_t rv;
           va_list ap;
   
           va_start(ap, format);
           rv = vstrfmon_l(s, maxsize, loc, format, ap);
           va_end(ap);
   
           return rv;
   }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.12

CVSweb <webmaster@jp.NetBSD.org>