about summary refs log tree commit diff
diff options
context:
space:
mode:
-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;
+}