#include <namespace.h>
#include <err.h>
#include <sys/types.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <locale.h>
#include <stdint.h>
#include <assert.h>
#include <namespace.h>
#include <string.h>
#include <wchar.h>
#include <un-namespace.h>
#include "printf.h"
#include "xprintf_private.h"
union arg {
int intarg;
u_int uintarg;
long longarg;
u_long ulongarg;
intmax_t intmaxarg;
uintmax_t uintmaxarg;
};
#define to_char(n) ((n) + '0')
#define BUF 128
extern const char *__fix_nogrouping(const char *str);
static char *
__ultoa(u_long val, char *endp, int base, const char *xdigs,
int needgrp, const char *thousep, int thousep_len, const char *grp)
{
char *cp = endp;
long sval;
int ndig;
switch (base) {
case 10:
if (val < 10) {
*--cp = to_char(val);
return (cp);
}
ndig = 0;
if (val > LONG_MAX) {
*--cp = to_char(val % 10);
ndig++;
sval = val / 10;
} else
sval = val;
do {
*--cp = to_char(sval % 10);
ndig++;
if (needgrp && ndig == *grp && *grp != CHAR_MAX
&& sval > 9) {
cp -= thousep_len;
memcpy(cp, thousep, thousep_len);
ndig = 0;
if (*(grp+1) != '\0')
grp++;
}
sval /= 10;
} while (sval != 0);
break;
case 8:
do {
*--cp = to_char(val & 7);
val >>= 3;
} while (val);
break;
case 16:
do {
*--cp = xdigs[val & 15];
val >>= 4;
} while (val);
break;
default:
assert(base == 16);
}
return (cp);
}
static char *
__ujtoa(uintmax_t val, char *endp, int base, const char *xdigs,
int needgrp, const char *thousep, int thousep_len, const char *grp)
{
char *cp = endp;
intmax_t sval;
int ndig;
switch (base) {
case 10:
if (val < 10) {
*--cp = to_char(val % 10);
return (cp);
}
ndig = 0;
if (val > INTMAX_MAX) {
*--cp = to_char(val % 10);
ndig++;
sval = val / 10;
} else
sval = val;
do {
*--cp = to_char(sval % 10);
ndig++;
if (needgrp && *grp != CHAR_MAX && ndig == *grp
&& sval > 9) {
cp -= thousep_len;
memcpy(cp, thousep, thousep_len);
ndig = 0;
if (*(grp+1) != '\0')
grp++;
}
sval /= 10;
} while (sval != 0);
break;
case 8:
do {
*--cp = to_char(val & 7);
val >>= 3;
} while (val);
break;
case 16:
do {
*--cp = xdigs[val & 15];
val >>= 4;
} while (val);
break;
default:
abort();
}
return (cp);
}
__private_extern__ int
__printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
{
assert (n > 0);
argt[0] = PA_INT;
#ifdef VECTORS
if (pi->is_vec)
argt[0] = PA_VECTOR;
else
#endif
if (pi->is_ptrdiff)
argt[0] |= PA_FLAG_PTRDIFF;
else if (pi->is_size)
argt[0] |= PA_FLAG_SIZE;
else if (pi->is_long)
argt[0] |= PA_FLAG_LONG;
else if (pi->is_intmax)
argt[0] |= PA_FLAG_INTMAX;
else if (pi->is_quad)
argt[0] |= PA_FLAG_QUAD;
else if (pi->is_long_double)
argt[0] |= PA_FLAG_LONG_LONG;
else if (pi->is_short)
argt[0] |= PA_FLAG_SHORT;
else if (pi->is_char)
argt[0] = PA_CHAR;
return (1);
}
__private_extern__ int
__printf_render_int(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
{
const union arg *argp;
char buf[BUF];
char *p, *pe;
char ns, l;
int rdx, sign, zext, ngrp;
const char *nalt, *digit;
const char *thousands_sep;
int thousands_sep_len;
const char *grouping;
uintmax_t uu;
int ret;
#ifdef VECTORS
if (pi->is_vec) return __xprintf_vector(io, pi, arg);
#endif
ret = 0;
nalt = NULL;
digit = __lowercase_hex;
ns = '\0';
pe = buf + sizeof buf - 1;
if (pi->group) {
thousands_sep = localeconv_l(pi->loc)->thousands_sep;
thousands_sep_len = strlen(thousands_sep);
grouping = __fix_nogrouping(localeconv_l(pi->loc)->grouping);
ngrp = 1;
} else {
thousands_sep = NULL;
thousands_sep_len = 0;
grouping = NULL;
ngrp = 0;
}
switch(pi->spec) {
case 'd':
case 'i':
rdx = 10;
sign = 1;
break;
case 'X':
digit = __uppercase_hex;
case 'x':
rdx = 16;
sign = 0;
break;
case 'u':
case 'U':
rdx = 10;
sign = 0;
break;
case 'o':
case 'O':
rdx = 8;
sign = 0;
break;
default:
fprintf(stderr, "pi->spec = '%c'\n", pi->spec);
assert(1 == 0);
}
argp = arg[0];
if (sign)
ns = pi->signchar;
if (pi->is_long_double || pi->is_quad || pi->is_intmax ||
pi->is_size || pi->is_ptrdiff) {
if (sign && argp->intmaxarg < 0) {
uu = -argp->intmaxarg;
ns = '-';
} else
uu = argp->uintmaxarg;
} else if (pi->is_long) {
if (sign && argp->longarg < 0) {
uu = (u_long)-argp->longarg;
ns = '-';
} else
uu = argp->ulongarg;
} else if (pi->is_short) {
if (sign && (short)argp->intarg < 0) {
uu = -(short)argp->intarg;
ns = '-';
} else
uu = (unsigned short)argp->uintarg;
} else if (pi->is_char) {
if (sign && (signed char)argp->intarg < 0) {
uu = -(signed char)argp->intarg;
ns = '-';
} else
uu = (unsigned char)argp->uintarg;
} else {
if (sign && argp->intarg < 0) {
uu = (unsigned)-argp->intarg;
ns = '-';
} else
uu = argp->uintarg;
}
if (uu <= ULONG_MAX)
p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, thousands_sep_len, grouping);
else
p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, thousands_sep_len, grouping);
l = 0;
if (uu == 0) {
;
if (pi->prec == 0 && !(pi->alt && rdx == 8))
p = pe;
} else if (pi->alt) {
if (rdx == 8)
*--p = '0';
if (rdx == 16) {
if (pi->spec == 'x')
nalt = "0x";
else
nalt = "0X";
l += 2;
}
}
l += pe - p;
if (ns)
l++;
if (pi->prec > (pe - p))
zext = pi->prec - (pe - p);
else if (pi->prec != -1)
zext = 0;
else if (pi->pad == '0' && pi->width > l && !pi->left)
zext = pi->width - l;
else
zext = 0;
l += zext;
while (zext > 0 && p > buf) {
*--p = '0';
zext--;
}
if (l < BUF) {
if (ns) {
*--p = ns;
} else if (nalt != NULL) {
*--p = nalt[1];
*--p = nalt[0];
}
if (pi->width > (pe - p) && !pi->left) {
l = pi->width - (pe - p);
while (l > 0 && p > buf) {
*--p = ' ';
l--;
}
if (l)
ret += __printf_pad(io, l, 0);
}
} else {
if (!pi->left && pi->width > l)
ret += __printf_pad(io, pi->width - l, 0);
if (ns != '\0')
ret += __printf_puts(io, &ns, 1);
else if (nalt != NULL)
ret += __printf_puts(io, nalt, 2);
if (zext > 0)
ret += __printf_pad(io, zext, 1);
}
ret += __printf_puts(io, p, pe - p);
if (pi->width > ret && pi->left)
ret += __printf_pad(io, pi->width - ret, 0);
__printf_flush(io);
return (ret);
}
__private_extern__ int
__printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
{
assert (n > 0);
#ifdef VECTORS
if (pi->is_vec)
argt[0] = PA_VECTOR;
else
#endif
argt[0] = PA_POINTER;
return (1);
}
__private_extern__ int
__printf_render_ptr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
{
struct printf_info p2;
uintmax_t u;
const void *p;
#ifdef VECTORS
if (pi->is_vec) return __xprintf_vector(io, pi, arg);
#endif
u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
p2 = *pi;
p2.spec = 'x';
p2.alt = 1;
p2.is_long_double = 1;
p = &u;
return (__printf_render_int(io, &p2, &p));
}