github.com/afumu/libc@v0.0.6/musl/src/locale/strfmon.c (about)

     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  }