175067f4fSPoul-Henning Kamp /*-
28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni *
475067f4fSPoul-Henning Kamp * Copyright (c) 2005 Poul-Henning Kamp
575067f4fSPoul-Henning Kamp * Copyright (c) 1990, 1993
675067f4fSPoul-Henning Kamp * The Regents of the University of California. All rights reserved.
775067f4fSPoul-Henning Kamp *
875067f4fSPoul-Henning Kamp * This code is derived from software contributed to Berkeley by
975067f4fSPoul-Henning Kamp * Chris Torek.
1075067f4fSPoul-Henning Kamp *
1175067f4fSPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without
1275067f4fSPoul-Henning Kamp * modification, are permitted provided that the following conditions
1375067f4fSPoul-Henning Kamp * are met:
1475067f4fSPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright
1575067f4fSPoul-Henning Kamp * notice, this list of conditions and the following disclaimer.
1675067f4fSPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright
1775067f4fSPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the
1875067f4fSPoul-Henning Kamp * documentation and/or other materials provided with the distribution.
1975067f4fSPoul-Henning Kamp * 3. Neither the name of the University nor the names of its contributors
2075067f4fSPoul-Henning Kamp * may be used to endorse or promote products derived from this software
2175067f4fSPoul-Henning Kamp * without specific prior written permission.
2275067f4fSPoul-Henning Kamp *
2375067f4fSPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2475067f4fSPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2575067f4fSPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2675067f4fSPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2775067f4fSPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2875067f4fSPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2975067f4fSPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3075067f4fSPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3175067f4fSPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3275067f4fSPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3375067f4fSPoul-Henning Kamp * SUCH DAMAGE.
3475067f4fSPoul-Henning Kamp */
3575067f4fSPoul-Henning Kamp
3675067f4fSPoul-Henning Kamp #include <namespace.h>
3775067f4fSPoul-Henning Kamp #include <err.h>
3875067f4fSPoul-Henning Kamp #include <sys/types.h>
3975067f4fSPoul-Henning Kamp #include <stddef.h>
4075067f4fSPoul-Henning Kamp #include <stdlib.h>
4175067f4fSPoul-Henning Kamp #include <stdio.h>
4275067f4fSPoul-Henning Kamp #include <limits.h>
4375067f4fSPoul-Henning Kamp #include <locale.h>
4475067f4fSPoul-Henning Kamp #include <stdint.h>
4575067f4fSPoul-Henning Kamp #include <assert.h>
4675067f4fSPoul-Henning Kamp #include <namespace.h>
4775067f4fSPoul-Henning Kamp #include <string.h>
4875067f4fSPoul-Henning Kamp #include <wchar.h>
4975067f4fSPoul-Henning Kamp #include <un-namespace.h>
5075067f4fSPoul-Henning Kamp
5175067f4fSPoul-Henning Kamp #include "printf.h"
5275067f4fSPoul-Henning Kamp
5375067f4fSPoul-Henning Kamp /* private stuff -----------------------------------------------------*/
5475067f4fSPoul-Henning Kamp
5575067f4fSPoul-Henning Kamp union arg {
5675067f4fSPoul-Henning Kamp int intarg;
5775067f4fSPoul-Henning Kamp u_int uintarg;
5875067f4fSPoul-Henning Kamp long longarg;
5975067f4fSPoul-Henning Kamp u_long ulongarg;
6075067f4fSPoul-Henning Kamp intmax_t intmaxarg;
6175067f4fSPoul-Henning Kamp uintmax_t uintmaxarg;
6275067f4fSPoul-Henning Kamp };
6375067f4fSPoul-Henning Kamp
6475067f4fSPoul-Henning Kamp /*
6575067f4fSPoul-Henning Kamp * Macros for converting digits to letters and vice versa
6675067f4fSPoul-Henning Kamp */
6775067f4fSPoul-Henning Kamp #define to_char(n) ((n) + '0')
6875067f4fSPoul-Henning Kamp
6975067f4fSPoul-Henning Kamp /* various globals ---------------------------------------------------*/
7075067f4fSPoul-Henning Kamp
7175067f4fSPoul-Henning Kamp /*
7275067f4fSPoul-Henning Kamp * The size of the buffer we use for integer conversions.
7375067f4fSPoul-Henning Kamp * Technically, we would need the most space for base 10
7475067f4fSPoul-Henning Kamp * conversions with thousands' grouping characters between
7575067f4fSPoul-Henning Kamp * each pair of digits: 60 digits for 128 bit intmax_t.
7675067f4fSPoul-Henning Kamp * Use a bit more for better alignment of stuff.
7775067f4fSPoul-Henning Kamp */
7875067f4fSPoul-Henning Kamp #define BUF 64
7975067f4fSPoul-Henning Kamp
8075067f4fSPoul-Henning Kamp /* misc --------------------------------------------------------------*/
8175067f4fSPoul-Henning Kamp
8275067f4fSPoul-Henning Kamp /*
8375067f4fSPoul-Henning Kamp * Convert an unsigned long to ASCII for printf purposes, returning
8475067f4fSPoul-Henning Kamp * a pointer to the first character of the string representation.
8575067f4fSPoul-Henning Kamp * Octal numbers can be forced to have a leading zero; hex numbers
8675067f4fSPoul-Henning Kamp * use the given digits.
8775067f4fSPoul-Henning Kamp */
8875067f4fSPoul-Henning Kamp static char *
__ultoa(u_long val,char * endp,int base,const char * xdigs,int needgrp,char thousep,const char * grp)8975067f4fSPoul-Henning Kamp __ultoa(u_long val, char *endp, int base, const char *xdigs,
9075067f4fSPoul-Henning Kamp int needgrp, char thousep, const char *grp)
9175067f4fSPoul-Henning Kamp {
9275067f4fSPoul-Henning Kamp char *cp = endp;
9375067f4fSPoul-Henning Kamp long sval;
9475067f4fSPoul-Henning Kamp int ndig;
9575067f4fSPoul-Henning Kamp
9675067f4fSPoul-Henning Kamp /*
9775067f4fSPoul-Henning Kamp * Handle the three cases separately, in the hope of getting
9875067f4fSPoul-Henning Kamp * better/faster code.
9975067f4fSPoul-Henning Kamp */
10075067f4fSPoul-Henning Kamp switch (base) {
10175067f4fSPoul-Henning Kamp case 10:
10275067f4fSPoul-Henning Kamp if (val < 10) { /* many numbers are 1 digit */
10375067f4fSPoul-Henning Kamp *--cp = to_char(val);
10475067f4fSPoul-Henning Kamp return (cp);
10575067f4fSPoul-Henning Kamp }
10675067f4fSPoul-Henning Kamp ndig = 0;
10775067f4fSPoul-Henning Kamp /*
10875067f4fSPoul-Henning Kamp * On many machines, unsigned arithmetic is harder than
10975067f4fSPoul-Henning Kamp * signed arithmetic, so we do at most one unsigned mod and
11075067f4fSPoul-Henning Kamp * divide; this is sufficient to reduce the range of
11175067f4fSPoul-Henning Kamp * the incoming value to where signed arithmetic works.
11275067f4fSPoul-Henning Kamp */
11375067f4fSPoul-Henning Kamp if (val > LONG_MAX) {
11475067f4fSPoul-Henning Kamp *--cp = to_char(val % 10);
11575067f4fSPoul-Henning Kamp ndig++;
11675067f4fSPoul-Henning Kamp sval = val / 10;
11775067f4fSPoul-Henning Kamp } else
11875067f4fSPoul-Henning Kamp sval = val;
11975067f4fSPoul-Henning Kamp do {
12075067f4fSPoul-Henning Kamp *--cp = to_char(sval % 10);
12175067f4fSPoul-Henning Kamp ndig++;
12275067f4fSPoul-Henning Kamp /*
12375067f4fSPoul-Henning Kamp * If (*grp == CHAR_MAX) then no more grouping
12475067f4fSPoul-Henning Kamp * should be performed.
12575067f4fSPoul-Henning Kamp */
12675067f4fSPoul-Henning Kamp if (needgrp && ndig == *grp && *grp != CHAR_MAX
12775067f4fSPoul-Henning Kamp && sval > 9) {
12875067f4fSPoul-Henning Kamp *--cp = thousep;
12975067f4fSPoul-Henning Kamp ndig = 0;
13075067f4fSPoul-Henning Kamp /*
13175067f4fSPoul-Henning Kamp * If (*(grp+1) == '\0') then we have to
13275067f4fSPoul-Henning Kamp * use *grp character (last grouping rule)
13375067f4fSPoul-Henning Kamp * for all next cases
13475067f4fSPoul-Henning Kamp */
13575067f4fSPoul-Henning Kamp if (*(grp+1) != '\0')
13675067f4fSPoul-Henning Kamp grp++;
13775067f4fSPoul-Henning Kamp }
13875067f4fSPoul-Henning Kamp sval /= 10;
13975067f4fSPoul-Henning Kamp } while (sval != 0);
14075067f4fSPoul-Henning Kamp break;
14175067f4fSPoul-Henning Kamp
14275067f4fSPoul-Henning Kamp case 8:
14375067f4fSPoul-Henning Kamp do {
14475067f4fSPoul-Henning Kamp *--cp = to_char(val & 7);
14575067f4fSPoul-Henning Kamp val >>= 3;
14675067f4fSPoul-Henning Kamp } while (val);
14775067f4fSPoul-Henning Kamp break;
14875067f4fSPoul-Henning Kamp
14975067f4fSPoul-Henning Kamp case 16:
15075067f4fSPoul-Henning Kamp do {
15175067f4fSPoul-Henning Kamp *--cp = xdigs[val & 15];
15275067f4fSPoul-Henning Kamp val >>= 4;
15375067f4fSPoul-Henning Kamp } while (val);
15475067f4fSPoul-Henning Kamp break;
15575067f4fSPoul-Henning Kamp
15675067f4fSPoul-Henning Kamp default: /* oops */
15775067f4fSPoul-Henning Kamp assert(base == 16);
15875067f4fSPoul-Henning Kamp }
15975067f4fSPoul-Henning Kamp return (cp);
16075067f4fSPoul-Henning Kamp }
16175067f4fSPoul-Henning Kamp
16275067f4fSPoul-Henning Kamp
16375067f4fSPoul-Henning Kamp /* Identical to __ultoa, but for intmax_t. */
16475067f4fSPoul-Henning Kamp static char *
__ujtoa(uintmax_t val,char * endp,int base,const char * xdigs,int needgrp,char thousep,const char * grp)16575067f4fSPoul-Henning Kamp __ujtoa(uintmax_t val, char *endp, int base, const char *xdigs,
16675067f4fSPoul-Henning Kamp int needgrp, char thousep, const char *grp)
16775067f4fSPoul-Henning Kamp {
16875067f4fSPoul-Henning Kamp char *cp = endp;
16975067f4fSPoul-Henning Kamp intmax_t sval;
17075067f4fSPoul-Henning Kamp int ndig;
17175067f4fSPoul-Henning Kamp
17275067f4fSPoul-Henning Kamp switch (base) {
17375067f4fSPoul-Henning Kamp case 10:
17475067f4fSPoul-Henning Kamp if (val < 10) {
17575067f4fSPoul-Henning Kamp *--cp = to_char(val % 10);
17675067f4fSPoul-Henning Kamp return (cp);
17775067f4fSPoul-Henning Kamp }
17875067f4fSPoul-Henning Kamp ndig = 0;
17975067f4fSPoul-Henning Kamp if (val > INTMAX_MAX) {
18075067f4fSPoul-Henning Kamp *--cp = to_char(val % 10);
18175067f4fSPoul-Henning Kamp ndig++;
18275067f4fSPoul-Henning Kamp sval = val / 10;
18375067f4fSPoul-Henning Kamp } else
18475067f4fSPoul-Henning Kamp sval = val;
18575067f4fSPoul-Henning Kamp do {
18675067f4fSPoul-Henning Kamp *--cp = to_char(sval % 10);
18775067f4fSPoul-Henning Kamp ndig++;
18875067f4fSPoul-Henning Kamp /*
18975067f4fSPoul-Henning Kamp * If (*grp == CHAR_MAX) then no more grouping
19075067f4fSPoul-Henning Kamp * should be performed.
19175067f4fSPoul-Henning Kamp */
19275067f4fSPoul-Henning Kamp if (needgrp && *grp != CHAR_MAX && ndig == *grp
19375067f4fSPoul-Henning Kamp && sval > 9) {
19475067f4fSPoul-Henning Kamp *--cp = thousep;
19575067f4fSPoul-Henning Kamp ndig = 0;
19675067f4fSPoul-Henning Kamp /*
19775067f4fSPoul-Henning Kamp * If (*(grp+1) == '\0') then we have to
19875067f4fSPoul-Henning Kamp * use *grp character (last grouping rule)
19975067f4fSPoul-Henning Kamp * for all next cases
20075067f4fSPoul-Henning Kamp */
20175067f4fSPoul-Henning Kamp if (*(grp+1) != '\0')
20275067f4fSPoul-Henning Kamp grp++;
20375067f4fSPoul-Henning Kamp }
20475067f4fSPoul-Henning Kamp sval /= 10;
20575067f4fSPoul-Henning Kamp } while (sval != 0);
20675067f4fSPoul-Henning Kamp break;
20775067f4fSPoul-Henning Kamp
20875067f4fSPoul-Henning Kamp case 8:
20975067f4fSPoul-Henning Kamp do {
21075067f4fSPoul-Henning Kamp *--cp = to_char(val & 7);
21175067f4fSPoul-Henning Kamp val >>= 3;
21275067f4fSPoul-Henning Kamp } while (val);
21375067f4fSPoul-Henning Kamp break;
21475067f4fSPoul-Henning Kamp
21575067f4fSPoul-Henning Kamp case 16:
21675067f4fSPoul-Henning Kamp do {
21775067f4fSPoul-Henning Kamp *--cp = xdigs[val & 15];
21875067f4fSPoul-Henning Kamp val >>= 4;
21975067f4fSPoul-Henning Kamp } while (val);
22075067f4fSPoul-Henning Kamp break;
22175067f4fSPoul-Henning Kamp
22275067f4fSPoul-Henning Kamp default:
22375067f4fSPoul-Henning Kamp abort();
22475067f4fSPoul-Henning Kamp }
22575067f4fSPoul-Henning Kamp return (cp);
22675067f4fSPoul-Henning Kamp }
22775067f4fSPoul-Henning Kamp
22875067f4fSPoul-Henning Kamp
22975067f4fSPoul-Henning Kamp /* 'd' ---------------------------------------------------------------*/
23075067f4fSPoul-Henning Kamp
23175067f4fSPoul-Henning Kamp int
__printf_arginfo_int(const struct printf_info * pi,size_t n,int * argt)23275067f4fSPoul-Henning Kamp __printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
23375067f4fSPoul-Henning Kamp {
23475067f4fSPoul-Henning Kamp assert (n > 0);
23575067f4fSPoul-Henning Kamp argt[0] = PA_INT;
23675067f4fSPoul-Henning Kamp if (pi->is_ptrdiff)
23775067f4fSPoul-Henning Kamp argt[0] |= PA_FLAG_PTRDIFF;
23875067f4fSPoul-Henning Kamp else if (pi->is_size)
23975067f4fSPoul-Henning Kamp argt[0] |= PA_FLAG_SIZE;
24075067f4fSPoul-Henning Kamp else if (pi->is_long)
24175067f4fSPoul-Henning Kamp argt[0] |= PA_FLAG_LONG;
24275067f4fSPoul-Henning Kamp else if (pi->is_intmax)
24375067f4fSPoul-Henning Kamp argt[0] |= PA_FLAG_INTMAX;
24475067f4fSPoul-Henning Kamp else if (pi->is_quad)
24575067f4fSPoul-Henning Kamp argt[0] |= PA_FLAG_QUAD;
24675067f4fSPoul-Henning Kamp else if (pi->is_long_double)
24775067f4fSPoul-Henning Kamp argt[0] |= PA_FLAG_LONG_LONG;
24875067f4fSPoul-Henning Kamp else if (pi->is_short)
24975067f4fSPoul-Henning Kamp argt[0] |= PA_FLAG_SHORT;
25075067f4fSPoul-Henning Kamp else if (pi->is_char)
25175067f4fSPoul-Henning Kamp argt[0] = PA_CHAR;
25275067f4fSPoul-Henning Kamp return (1);
25375067f4fSPoul-Henning Kamp }
25475067f4fSPoul-Henning Kamp
25575067f4fSPoul-Henning Kamp int
__printf_render_int(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)25675067f4fSPoul-Henning Kamp __printf_render_int(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
25775067f4fSPoul-Henning Kamp {
25875067f4fSPoul-Henning Kamp const union arg *argp;
25975067f4fSPoul-Henning Kamp char buf[BUF];
26075067f4fSPoul-Henning Kamp char *p, *pe;
261*bc86c883SPedro F. Giffuni char ns;
262*bc86c883SPedro F. Giffuni int l, ngrp, rdx, sign, zext;
26375067f4fSPoul-Henning Kamp const char *nalt, *digit;
26475067f4fSPoul-Henning Kamp char thousands_sep; /* locale specific thousands separator */
26575067f4fSPoul-Henning Kamp const char *grouping; /* locale specific numeric grouping rules */
26675067f4fSPoul-Henning Kamp uintmax_t uu;
26775067f4fSPoul-Henning Kamp int ret;
26875067f4fSPoul-Henning Kamp
26975067f4fSPoul-Henning Kamp ret = 0;
27075067f4fSPoul-Henning Kamp nalt = NULL;
27175067f4fSPoul-Henning Kamp digit = __lowercase_hex;
27275067f4fSPoul-Henning Kamp ns = '\0';
27375067f4fSPoul-Henning Kamp pe = buf + sizeof buf - 1;
27475067f4fSPoul-Henning Kamp
27575067f4fSPoul-Henning Kamp if (pi->group) {
27675067f4fSPoul-Henning Kamp thousands_sep = *(localeconv()->thousands_sep);
27775067f4fSPoul-Henning Kamp grouping = localeconv()->grouping;
27875067f4fSPoul-Henning Kamp ngrp = 1;
27975067f4fSPoul-Henning Kamp } else {
28075067f4fSPoul-Henning Kamp thousands_sep = 0;
28175067f4fSPoul-Henning Kamp grouping = NULL;
28275067f4fSPoul-Henning Kamp ngrp = 0;
28375067f4fSPoul-Henning Kamp }
28475067f4fSPoul-Henning Kamp
28575067f4fSPoul-Henning Kamp switch(pi->spec) {
28675067f4fSPoul-Henning Kamp case 'd':
28775067f4fSPoul-Henning Kamp case 'i':
28875067f4fSPoul-Henning Kamp rdx = 10;
28975067f4fSPoul-Henning Kamp sign = 1;
29075067f4fSPoul-Henning Kamp break;
29175067f4fSPoul-Henning Kamp case 'X':
29275067f4fSPoul-Henning Kamp digit = __uppercase_hex;
29375067f4fSPoul-Henning Kamp /*FALLTHOUGH*/
29475067f4fSPoul-Henning Kamp case 'x':
29575067f4fSPoul-Henning Kamp rdx = 16;
29675067f4fSPoul-Henning Kamp sign = 0;
29775067f4fSPoul-Henning Kamp break;
29875067f4fSPoul-Henning Kamp case 'u':
29975067f4fSPoul-Henning Kamp case 'U':
30075067f4fSPoul-Henning Kamp rdx = 10;
30175067f4fSPoul-Henning Kamp sign = 0;
30275067f4fSPoul-Henning Kamp break;
30375067f4fSPoul-Henning Kamp case 'o':
30475067f4fSPoul-Henning Kamp case 'O':
30575067f4fSPoul-Henning Kamp rdx = 8;
30675067f4fSPoul-Henning Kamp sign = 0;
30775067f4fSPoul-Henning Kamp break;
30875067f4fSPoul-Henning Kamp default:
30975067f4fSPoul-Henning Kamp fprintf(stderr, "pi->spec = '%c'\n", pi->spec);
31075067f4fSPoul-Henning Kamp assert(1 == 0);
31175067f4fSPoul-Henning Kamp }
31275067f4fSPoul-Henning Kamp argp = arg[0];
31375067f4fSPoul-Henning Kamp
31475067f4fSPoul-Henning Kamp if (sign)
31575067f4fSPoul-Henning Kamp ns = pi->showsign;
31675067f4fSPoul-Henning Kamp
31775067f4fSPoul-Henning Kamp if (pi->is_long_double || pi->is_quad || pi->is_intmax ||
31875067f4fSPoul-Henning Kamp pi->is_size || pi->is_ptrdiff) {
31975067f4fSPoul-Henning Kamp if (sign && argp->intmaxarg < 0) {
32075067f4fSPoul-Henning Kamp uu = -argp->intmaxarg;
32175067f4fSPoul-Henning Kamp ns = '-';
32275067f4fSPoul-Henning Kamp } else
32375067f4fSPoul-Henning Kamp uu = argp->uintmaxarg;
32475067f4fSPoul-Henning Kamp } else if (pi->is_long) {
32575067f4fSPoul-Henning Kamp if (sign && argp->longarg < 0) {
32675067f4fSPoul-Henning Kamp uu = (u_long)-argp->longarg;
32775067f4fSPoul-Henning Kamp ns = '-';
32875067f4fSPoul-Henning Kamp } else
32975067f4fSPoul-Henning Kamp uu = argp->ulongarg;
33075067f4fSPoul-Henning Kamp } else if (pi->is_short) {
33175067f4fSPoul-Henning Kamp if (sign && (short)argp->intarg < 0) {
33275067f4fSPoul-Henning Kamp uu = -(short)argp->intarg;
33375067f4fSPoul-Henning Kamp ns = '-';
33475067f4fSPoul-Henning Kamp } else
33575067f4fSPoul-Henning Kamp uu = (unsigned short)argp->uintarg;
33675067f4fSPoul-Henning Kamp } else if (pi->is_char) {
33780c276c1SOlivier Houchard if (sign && (signed char)argp->intarg < 0) {
33880c276c1SOlivier Houchard uu = -(signed char)argp->intarg;
33975067f4fSPoul-Henning Kamp ns = '-';
34075067f4fSPoul-Henning Kamp } else
34175067f4fSPoul-Henning Kamp uu = (unsigned char)argp->uintarg;
34275067f4fSPoul-Henning Kamp } else {
34375067f4fSPoul-Henning Kamp if (sign && argp->intarg < 0) {
34475067f4fSPoul-Henning Kamp uu = (unsigned)-argp->intarg;
34575067f4fSPoul-Henning Kamp ns = '-';
34675067f4fSPoul-Henning Kamp } else
34775067f4fSPoul-Henning Kamp uu = argp->uintarg;
34875067f4fSPoul-Henning Kamp }
34975067f4fSPoul-Henning Kamp if (uu <= ULONG_MAX)
35075067f4fSPoul-Henning Kamp p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
35175067f4fSPoul-Henning Kamp else
35275067f4fSPoul-Henning Kamp p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
35375067f4fSPoul-Henning Kamp
35475067f4fSPoul-Henning Kamp l = 0;
35575067f4fSPoul-Henning Kamp if (uu == 0) {
35675067f4fSPoul-Henning Kamp /*-
35775067f4fSPoul-Henning Kamp * ``The result of converting a zero value with an
35875067f4fSPoul-Henning Kamp * explicit precision of zero is no characters.''
35975067f4fSPoul-Henning Kamp * -- ANSI X3J11
36075067f4fSPoul-Henning Kamp *
36175067f4fSPoul-Henning Kamp * ``The C Standard is clear enough as is. The call
36275067f4fSPoul-Henning Kamp * printf("%#.0o", 0) should print 0.''
36375067f4fSPoul-Henning Kamp * -- Defect Report #151
36475067f4fSPoul-Henning Kamp */
36575067f4fSPoul-Henning Kamp ;
36675067f4fSPoul-Henning Kamp if (pi->prec == 0 && !(pi->alt && rdx == 8))
36775067f4fSPoul-Henning Kamp p = pe;
36875067f4fSPoul-Henning Kamp } else if (pi->alt) {
36975067f4fSPoul-Henning Kamp if (rdx == 8)
37075067f4fSPoul-Henning Kamp *--p = '0';
37175067f4fSPoul-Henning Kamp if (rdx == 16) {
37275067f4fSPoul-Henning Kamp if (pi->spec == 'x')
37375067f4fSPoul-Henning Kamp nalt = "0x";
37475067f4fSPoul-Henning Kamp else
37575067f4fSPoul-Henning Kamp nalt = "0X";
37675067f4fSPoul-Henning Kamp l += 2;
37775067f4fSPoul-Henning Kamp }
37875067f4fSPoul-Henning Kamp }
37975067f4fSPoul-Henning Kamp l += pe - p;
38075067f4fSPoul-Henning Kamp if (ns)
38175067f4fSPoul-Henning Kamp l++;
38275067f4fSPoul-Henning Kamp
38375067f4fSPoul-Henning Kamp /*-
38475067f4fSPoul-Henning Kamp * ``... diouXx conversions ... if a precision is
38575067f4fSPoul-Henning Kamp * specified, the 0 flag will be ignored.''
38675067f4fSPoul-Henning Kamp * -- ANSI X3J11
38775067f4fSPoul-Henning Kamp */
38875067f4fSPoul-Henning Kamp if (pi->prec > (pe - p))
38975067f4fSPoul-Henning Kamp zext = pi->prec - (pe - p);
39075067f4fSPoul-Henning Kamp else if (pi->prec != -1)
39175067f4fSPoul-Henning Kamp zext = 0;
39275067f4fSPoul-Henning Kamp else if (pi->pad == '0' && pi->width > l && !pi->left)
39375067f4fSPoul-Henning Kamp zext = pi->width - l;
39475067f4fSPoul-Henning Kamp else
39575067f4fSPoul-Henning Kamp zext = 0;
39675067f4fSPoul-Henning Kamp
39775067f4fSPoul-Henning Kamp l += zext;
39875067f4fSPoul-Henning Kamp
39975067f4fSPoul-Henning Kamp while (zext > 0 && p > buf) {
40075067f4fSPoul-Henning Kamp *--p = '0';
40175067f4fSPoul-Henning Kamp zext--;
40275067f4fSPoul-Henning Kamp }
40375067f4fSPoul-Henning Kamp
40475067f4fSPoul-Henning Kamp if (l < BUF) {
40575067f4fSPoul-Henning Kamp if (ns) {
40675067f4fSPoul-Henning Kamp *--p = ns;
40775067f4fSPoul-Henning Kamp } else if (nalt != NULL) {
40875067f4fSPoul-Henning Kamp *--p = nalt[1];
40975067f4fSPoul-Henning Kamp *--p = nalt[0];
41075067f4fSPoul-Henning Kamp }
41175067f4fSPoul-Henning Kamp if (pi->width > (pe - p) && !pi->left) {
41275067f4fSPoul-Henning Kamp l = pi->width - (pe - p);
41375067f4fSPoul-Henning Kamp while (l > 0 && p > buf) {
41475067f4fSPoul-Henning Kamp *--p = ' ';
41575067f4fSPoul-Henning Kamp l--;
41675067f4fSPoul-Henning Kamp }
41775067f4fSPoul-Henning Kamp if (l)
41875067f4fSPoul-Henning Kamp ret += __printf_pad(io, l, 0);
41975067f4fSPoul-Henning Kamp }
42075067f4fSPoul-Henning Kamp } else {
42175067f4fSPoul-Henning Kamp if (!pi->left && pi->width > l)
42275067f4fSPoul-Henning Kamp ret += __printf_pad(io, pi->width - l, 0);
42375067f4fSPoul-Henning Kamp if (ns != '\0')
42475067f4fSPoul-Henning Kamp ret += __printf_puts(io, &ns, 1);
42575067f4fSPoul-Henning Kamp else if (nalt != NULL)
42675067f4fSPoul-Henning Kamp ret += __printf_puts(io, nalt, 2);
42775067f4fSPoul-Henning Kamp if (zext > 0)
42875067f4fSPoul-Henning Kamp ret += __printf_pad(io, zext, 1);
42975067f4fSPoul-Henning Kamp }
43075067f4fSPoul-Henning Kamp
43175067f4fSPoul-Henning Kamp ret += __printf_puts(io, p, pe - p);
43275067f4fSPoul-Henning Kamp if (pi->width > ret && pi->left)
43375067f4fSPoul-Henning Kamp ret += __printf_pad(io, pi->width - ret, 0);
43475067f4fSPoul-Henning Kamp __printf_flush(io);
43575067f4fSPoul-Henning Kamp return (ret);
43675067f4fSPoul-Henning Kamp }
43775067f4fSPoul-Henning Kamp
43875067f4fSPoul-Henning Kamp /* 'p' ---------------------------------------------------------------*/
43975067f4fSPoul-Henning Kamp
44075067f4fSPoul-Henning Kamp int
__printf_arginfo_ptr(const struct printf_info * pi __unused,size_t n,int * argt)44175067f4fSPoul-Henning Kamp __printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
44275067f4fSPoul-Henning Kamp {
44375067f4fSPoul-Henning Kamp
44475067f4fSPoul-Henning Kamp assert (n > 0);
44575067f4fSPoul-Henning Kamp argt[0] = PA_POINTER;
44675067f4fSPoul-Henning Kamp return (1);
44775067f4fSPoul-Henning Kamp }
44875067f4fSPoul-Henning Kamp
44975067f4fSPoul-Henning Kamp int
__printf_render_ptr(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)45075067f4fSPoul-Henning Kamp __printf_render_ptr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
45175067f4fSPoul-Henning Kamp {
45275067f4fSPoul-Henning Kamp struct printf_info p2;
45375067f4fSPoul-Henning Kamp uintmax_t u;
45475067f4fSPoul-Henning Kamp const void *p;
45575067f4fSPoul-Henning Kamp
45675067f4fSPoul-Henning Kamp /*-
45775067f4fSPoul-Henning Kamp * ``The argument shall be a pointer to void. The
45875067f4fSPoul-Henning Kamp * value of the pointer is converted to a sequence
45975067f4fSPoul-Henning Kamp * of printable characters, in an implementation-
46075067f4fSPoul-Henning Kamp * defined manner.''
46175067f4fSPoul-Henning Kamp * -- ANSI X3J11
46275067f4fSPoul-Henning Kamp */
46375067f4fSPoul-Henning Kamp u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
46475067f4fSPoul-Henning Kamp p2 = *pi;
46575067f4fSPoul-Henning Kamp
46675067f4fSPoul-Henning Kamp p2.spec = 'x';
46775067f4fSPoul-Henning Kamp p2.alt = 1;
46875067f4fSPoul-Henning Kamp p2.is_long_double = 1;
46975067f4fSPoul-Henning Kamp p = &u;
47075067f4fSPoul-Henning Kamp return (__printf_render_int(io, &p2, &p));
47175067f4fSPoul-Henning Kamp }
472