strfmon.c raw

   1  #include <stdio.h>
   2  #include <ctype.h>
   3  #include <stdarg.h>
   4  #include <monetary.h>
   5  #include <errno.h>
   6  #include "locale_impl.h"
   7  
   8  static ssize_t vstrfmon_l(char *s, size_t n, locale_t loc, const char *fmt, va_list ap)
   9  {
  10  	size_t l;
  11  	double x;
  12  	int fill, nogrp, negpar, nosym, left, intl;
  13  	int lp, rp, w, fw;
  14  	char *s0=s;
  15  	for (; n && *fmt; ) {
  16  		if (*fmt != '%') {
  17  		literal:
  18  			*s++ = *fmt++;
  19  			n--;
  20  			continue;
  21  		}
  22  		fmt++;
  23  		if (*fmt == '%') goto literal;
  24  
  25  		fill = ' ';
  26  		nogrp = 0;
  27  		negpar = 0;
  28  		nosym = 0;
  29  		left = 0;
  30  		for (; ; fmt++) {
  31  			switch (*fmt) {
  32  			case '=':
  33  				fill = *++fmt;
  34  				continue;
  35  			case '^':
  36  				nogrp = 1;
  37  				continue;
  38  			case '(':
  39  				negpar = 1;
  40  			case '+':
  41  				continue;
  42  			case '!':
  43  				nosym = 1;
  44  				continue;
  45  			case '-':
  46  				left = 1;
  47  				continue;
  48  			}
  49  			break;
  50  		}
  51  
  52  		for (fw=0; isdigit(*fmt); fmt++)
  53  			fw = 10*fw + (*fmt-'0');
  54  		lp = 0;
  55  		rp = 2;
  56  		if (*fmt=='#') for (lp=0, fmt++; isdigit(*fmt); fmt++)
  57  			lp = 10*lp + (*fmt-'0');
  58  		if (*fmt=='.') for (rp=0, fmt++; isdigit(*fmt); fmt++)
  59  			rp = 10*rp + (*fmt-'0');
  60  
  61  		intl = *fmt++ == 'i';
  62  
  63  		w = lp + 1 + rp;
  64  		if (!left && fw>w) w = fw;
  65  
  66  		x = va_arg(ap, double);
  67  		l = snprintf(s, n, "%*.*f", w, rp, x);
  68  		if (l >= n) {
  69  			errno = E2BIG;
  70  			return -1;
  71  		}
  72  		s += l;
  73  		n -= l;
  74  	}
  75  	return s-s0;
  76  }
  77  
  78  ssize_t strfmon_l(char *restrict s, size_t n, locale_t loc, const char *restrict fmt, ...)
  79  {
  80  	va_list ap;
  81  	ssize_t ret;
  82  
  83  	va_start(ap, fmt);
  84  	ret = vstrfmon_l(s, n, loc, fmt, ap);
  85  	va_end(ap);
  86  
  87  	return ret;
  88  }
  89  
  90  
  91  ssize_t strfmon(char *restrict s, size_t n, const char *restrict fmt, ...)
  92  {
  93  	va_list ap;
  94  	ssize_t ret;
  95  
  96  	va_start(ap, fmt);
  97  	ret = vstrfmon_l(s, n, CURRENT_LOCALE, fmt, ap);
  98  	va_end(ap);
  99  
 100  	return ret;
 101  }
 102