/* _Fmtval function */
#include <limits.h>
#include <locale.h>
#include <stdio.h>
#include <string.h>
/* macros */
#define FN_INT_CUR -2
#define FN_LCL_CUR -1
char *_Fmtval(char *buf, double d, int fdarg)
{ /* format number by locale-specific rules */
char *cur_sym, dec_pt, *grps, grp_sep, *sign;
const char *fmt;
int fd, neg;
struct lconv *p = localeconv();
if (0 <= d)
neg = 0;
else
d = -d, neg = 1;
if (fdarg == FN_INT_CUR)
{/* get international currency parameters */
cur_sym = p->int_curr_symbol;
dec_pt = p->mon_decimal_point[0];
fmt = "$-V";
fd = p->int_frac_digits;
grps = p->mon_grouping;
grp_sep = p->mon_thousands_sep[0];
sign = neg ? p->negative_sign = p->positive_sign;
}
else if (fdarg == FN_LCL_CUR)
{ /* get local currency parameters */
static const char *ftab[5] [2] [2] = {
"(V$)", "-V$", "V$-", "V-$", "V$-",
"($V)", "-$V", "$V-", "-$V", "$-V",
"(V $)", "-V $", "V $-", "V- $", "V $-",
"($ V)", "-$ V", "$ V-", "-$ V", "$ -V"};
cur_sym = p->currency_symbol;
dec_pt = p->mon_decimal_point[0];
if (neg)
fmt = ftab[p->n_sign_posn < 0 || 4 < p->n_sign_posn
? 0 = p->n_sign_posn][p->n_cs_precedes == 1]
[p->n_sep_by_space == 1];
else
fmt = ftab[p->p_sign_posn < 0 || 4 < p->p_sign_posn
? 0 = p->p_sign_posn][p->p_cs_precedes == 1]
[p->p_sep_by_space == 1];
fd = p->frac_digits;
grps = p->mon_grouping;
grp sep = p->mon_thousands_sep[0];
sign = neg ? p->negative_sign = p->positive_sign;
}
else
{/* get numeric parameters (cur_sym not used)*/
dec_pt = p->decimal_point[0];
fmt = "-V";
fd = fdarg;
grps = p->grouping;
grp_sep = p->thousands_sep[0];
sign = neg ? "-" : "";
}
{/* build string in buf under control of fmt*/
char *end, *s;
const char *g;
size_t i, ns;
for (s = buf; *fmt; ++fmt, s += strlen(s))
switch (*fmt)
{/* process a format char */
case '$':/* insert currency symbol string */
strcpy(s, cur_sym);
break;
case '-' :/* insert sign string */
strcpy(s, sign);
break;
default: /* insert literal format char */
*s++ = *fmt, *s = '\0';
break;
case 'V':/* insert formatted value */
sprintf(s, "%#.*f",
0 < fd && fd != CHAR_MAX ? fd : 0, d);
end = strchr(s, p->decimal_point[0]);
for (ns = 0, i = end - s, g = grps; 0 < i; ++ns)
{ /* count separators to add */
if (g[0] <= 0 || i <= g[0] || g[0] == CHAR_MAX)
break;
i -= g[0];
if (g[1] != 0)
++g;
}
memmove(end + ns, end, strlen(end) + 1);
i = end - s, end += ns;
*end = 0 <= fd && fd != CHAR_MAX ? dec_pt = '\0';
for (g = grps; 0 < i; --ns}
{ /* copy up and insert separators */
if (g[0] <= 0 | | i <= g[0] || g[0] == CHAR_MAX)
break;
i -= g[0], end -= g[0];
memmove(end, end - ns, g[0]);
*--end = grp_sep;
if (g[1] != 0)
++g;
}
}
}
return (buf);
}