#include <namespace.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdint.h>
#include <assert.h>
#include <wchar.h>
#include "printf.h"
#include "xprintf_private.h"
static char *
__wcsconv(wchar_t *wcsarg, int prec, locale_t loc)
{
static const mbstate_t initial;
mbstate_t mbs;
char buf[MB_LEN_MAX];
wchar_t *p;
char *convbuf;
size_t clen, nbytes;
if (prec < 0) {
p = wcsarg;
mbs = initial;
nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
if (nbytes == (size_t)-1)
return (NULL);
} else {
if (prec < 128)
nbytes = prec;
else {
nbytes = 0;
p = wcsarg;
mbs = initial;
for (;;) {
clen = wcrtomb_l(buf, *p++, &mbs, loc);
if (clen == 0 || clen == (size_t)-1 ||
(int)(nbytes + clen) > prec)
break;
nbytes += clen;
}
}
}
if ((convbuf = MALLOC(nbytes + 1)) == NULL)
return (NULL);
p = wcsarg;
mbs = initial;
if ((nbytes = wcsrtombs_l(convbuf, (const wchar_t **)&p,
nbytes, &mbs, loc)) == (size_t)-1) {
free(convbuf);
return (NULL);
}
convbuf[nbytes] = '\0';
return (convbuf);
}
__private_extern__ int
__printf_arginfo_str(const struct printf_info *pi, size_t n, int *argt)
{
assert (n > 0);
if (pi->is_long || pi->spec == 'C')
argt[0] = PA_WSTRING;
else
argt[0] = PA_STRING;
return (1);
}
__private_extern__ int
__printf_render_str(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
{
const char *p;
wchar_t *wcp;
char *convbuf;
int l;
if (pi->is_long || pi->spec == 'S') {
wcp = *((wint_t **)arg[0]);
if (wcp == NULL)
return (__printf_out(io, pi, "(null)", 6));
convbuf = __wcsconv(wcp, pi->prec, pi->loc);
if (convbuf == NULL)
return (-1);
l = __printf_out(io, pi, convbuf, strlen(convbuf));
__printf_flush(io);
free(convbuf);
return (l);
}
p = *((char **)arg[0]);
if (p == NULL)
return (__printf_out(io, pi, "(null)", 6));
l = strlen(p);
if (pi->prec >= 0 && pi->prec < l)
l = pi->prec;
return (__printf_out(io, pi, p, l));
}
__private_extern__ int
__printf_arginfo_chr(const struct printf_info *pi, size_t n, int *argt)
{
assert (n > 0);
#ifdef VECTORS
if (pi->is_vec)
argt[0] = PA_VECTOR;
else
#endif
if (pi->is_long || pi->spec == 'C')
argt[0] = PA_WCHAR;
else
argt[0] = PA_INT;
return (1);
}
__private_extern__ int
__printf_render_chr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
{
int i;
wint_t ii;
unsigned char c;
static const mbstate_t initial;
mbstate_t mbs;
size_t mbseqlen;
char buf[MB_CUR_MAX_L(pi->loc)];
#ifdef VECTORS
if (pi->is_vec) return __xprintf_vector(io, pi, arg);
#endif
if (pi->is_long || pi->spec == 'C') {
int ret;
ii = *((wint_t *)arg[0]);
mbs = initial;
mbseqlen = wcrtomb_l(buf, (wchar_t)ii, &mbs, pi->loc);
if (mbseqlen == (size_t) -1)
return (-1);
ret = __printf_out(io, pi, buf, mbseqlen);
__printf_flush(io);
return ret;
}
i = *((int *)arg[0]);
c = i;
i = __printf_out(io, pi, &c, 1);
__printf_flush(io);
return (i);
}