initial, very primitive strfmon
authorRich Felker <dalias@aerifal.cx>
Wed, 21 Mar 2012 04:47:37 +0000 (00:47 -0400)
committerRich Felker <dalias@aerifal.cx>
Wed, 21 Mar 2012 04:47:37 +0000 (00:47 -0400)
include/monetary.h [new file with mode: 0644]
src/locale/strfmon.c [new file with mode: 0644]

diff --git a/include/monetary.h b/include/monetary.h
new file mode 100644 (file)
index 0000000..df904eb
--- /dev/null
@@ -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 (file)
index 0000000..66bee48
--- /dev/null
@@ -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;
+}