Listing 3 (_Fmtval)
/* _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); }