version 1.9, 2012/03/13 21:13:48 |
version 1.11, 2017/08/16 13:53:20 |
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 <assert.h> |
Line 47 __RCSID("$NetBSD$"); |
|
Line 44 __RCSID("$NetBSD$"); |
|
#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 <stddef.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) */ |
Line 63 __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 100 __RCSID("$NetBSD$"); |
|
Line 104 __RCSID("$NetBSD$"); |
|
groups++; \ |
groups++; \ |
} while (/* CONSTCOND */ 0) |
} while (/* CONSTCOND */ 0) |
|
|
static void __setup_vars(int, char *, char *, char *, const 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 132 strfmon(char * __restrict s, size_t maxs |
|
Line 135 strfmon(char * __restrict s, size_t maxs |
|
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 259 strfmon(char * __restrict s, size_t maxs |
|
Line 260 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 388 strfmon(char * __restrict s, size_t maxs |
|
Line 389 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' */ |
|
|
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, const 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; |
Line 443 __setup_vars(int flags, char *cs_precede |
|
Line 441 __setup_vars(int flags, char *cs_precede |
|
/* Set defult values for unspecified information. */ |
/* Set defult 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 = 0; |
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; |
char cs_precedes, sep_by_space, sign_posn; |
const char *signstr; |
const char *signstr; |
size_t left_chars = 0; |
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 482 get_groups(int size, char *grouping) { |
|
Line 480 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 502 get_groups(int size, char *grouping) { |
|
Line 500 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; |
Line 514 __format_grouped_double(double value, in |
|
Line 512 __format_grouped_double(double value, in |
|
|
|
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 581 __format_grouped_double(double value, in |
|
Line 578 __format_grouped_double(double value, in |
|
/* XXX: Why not use %' instead? */ |
/* 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 589 __format_grouped_double(double value, in |
|
Line 586 __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 623 __format_grouped_double(double value, in |
|
Line 620 __format_grouped_double(double value, in |
|
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; |
|
} |