summaryrefslogtreecommitdiff
path: root/src/locale/strfmon.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-03-21 00:47:37 -0400
committerRich Felker <dalias@aerifal.cx>2012-03-21 00:47:37 -0400
commit25501c1079756c9b438842da649585c2a6983c24 (patch)
tree422642ec7a55231a10ea7cac5c45f73bd31656f5 /src/locale/strfmon.c
parent30df206cb0c66848142898115d301a0d80333d0f (diff)
downloadmusl-25501c1079756c9b438842da649585c2a6983c24.tar.gz
initial, very primitive strfmon
Diffstat (limited to 'src/locale/strfmon.c')
-rw-r--r--src/locale/strfmon.c77
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;
+}