summaryrefslogtreecommitdiff
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
parent30df206cb0c66848142898115d301a0d80333d0f (diff)
downloadmusl-25501c1079756c9b438842da649585c2a6983c24.tar.gz
initial, very primitive strfmon
-rw-r--r--include/monetary.h21
-rw-r--r--src/locale/strfmon.c77
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;
+}