diff options
-rw-r--r-- | include/monetary.h | 21 | ||||
-rw-r--r-- | src/locale/strfmon.c | 77 |
2 files changed, 98 insertions, 0 deletions
diff --git a/include/monetary.h b/include/monetary.h new file mode 100644 index 00000000..df904eb0 --- /dev/null +++ b/include/monetary.h @@ -0,0 +1,21 @@ +#ifndef _MONETARY_H +#define _MONETARY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_ssize_t +#define __NEED_size_t +#define __NEED_locale_t + +#include <bits/alltypes.h> + +ssize_t strfmon(char *, size_t, const char *, ...); +ssize_t strfmon_l(char *, size_t, locale_t, const char *, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/locale/strfmon.c b/src/locale/strfmon.c new file mode 100644 index 00000000..66bee482 --- /dev/null +++ b/src/locale/strfmon.c @@ -0,0 +1,77 @@ +#include <stdio.h> +#include <ctype.h> +#include <stdarg.h> +#include <monetary.h> +#include <errno.h> + +ssize_t strfmon(char *s, size_t n, const char *fmt, ...) +{ + size_t l; + double x; + int fill, nogrp, negpar, nosym, left, intl; + int lp, rp, w, fw; + char *s0=s; + va_list ap; + va_start(ap, fmt); + for (; n && *fmt; ) { + if (*fmt != '%') { + literal: + *s++ = *fmt++; + n--; + continue; + } + fmt++; + if (*fmt == '%') goto literal; + + fill = ' '; + nogrp = 0; + negpar = 0; + nosym = 0; + left = 0; + for (; ; fmt++) { + switch (*fmt) { + case '=': + fill = *++fmt; + continue; + case '^': + nogrp = 1; + continue; + case '(': + negpar = 1; + case '+': + continue; + case '!': + nosym = 1; + continue; + case '-': + left = 1; + continue; + } + break; + } + + for (fw=0; isdigit(*fmt); fmt++) + fw = 10*fw + (*fmt-'0'); + lp = 0; + rp = 2; + if (*fmt=='#') for (lp=0, fmt++; isdigit(*fmt); fmt++) + lp = 10*lp + (*fmt-'0'); + if (*fmt=='.') for (rp=0, fmt++; isdigit(*fmt); fmt++) + rp = 10*rp + (*fmt-'0'); + + intl = *fmt++ == 'i'; + + w = lp + 1 + rp; + if (!left && fw>w) w = fw; + + x = va_arg(ap, double); + l = snprintf(s, n, "%*.*f", w, rp, x); + if (l >= n) { + errno = E2BIG; + return -1; + } + s += l; + n -= l; + } + return s-s0; +} |