diff options
| -rw-r--r-- | include/monetary.h | 21 | ||||
| -rw-r--r-- | src/locale/strfmon.c | 77 | 
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; +} | 
