diff options
author | Rich Felker <dalias@aerifal.cx> | 2012-03-21 00:47:37 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2012-03-21 00:47:37 -0400 |
commit | 25501c1079756c9b438842da649585c2a6983c24 (patch) | |
tree | 422642ec7a55231a10ea7cac5c45f73bd31656f5 /src/locale/strfmon.c | |
parent | 30df206cb0c66848142898115d301a0d80333d0f (diff) | |
download | musl-25501c1079756c9b438842da649585c2a6983c24.tar.gz |
initial, very primitive strfmon
Diffstat (limited to 'src/locale/strfmon.c')
-rw-r--r-- | src/locale/strfmon.c | 77 |
1 files changed, 77 insertions, 0 deletions
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; +} |