xref: /freebsd/lib/libc/stdio/xprintf_int.c (revision 8a16b7a18f5d0b031f09832fd7752fba717e2a97)
175067f4fSPoul-Henning Kamp /*-
2*8a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3*8a16b7a1SPedro 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  * $FreeBSD$
3675067f4fSPoul-Henning Kamp  */
3775067f4fSPoul-Henning Kamp 
3875067f4fSPoul-Henning Kamp #include <namespace.h>
3975067f4fSPoul-Henning Kamp #include <err.h>
4075067f4fSPoul-Henning Kamp #include <sys/types.h>
4175067f4fSPoul-Henning Kamp #include <stddef.h>
4275067f4fSPoul-Henning Kamp #include <stdlib.h>
4375067f4fSPoul-Henning Kamp #include <stdio.h>
4475067f4fSPoul-Henning Kamp #include <limits.h>
4575067f4fSPoul-Henning Kamp #include <locale.h>
4675067f4fSPoul-Henning Kamp #include <stdint.h>
4775067f4fSPoul-Henning Kamp #include <assert.h>
4875067f4fSPoul-Henning Kamp #include <namespace.h>
4975067f4fSPoul-Henning Kamp #include <string.h>
5075067f4fSPoul-Henning Kamp #include <wchar.h>
5175067f4fSPoul-Henning Kamp #include <un-namespace.h>
5275067f4fSPoul-Henning Kamp 
5375067f4fSPoul-Henning Kamp #include "printf.h"
5475067f4fSPoul-Henning Kamp 
5575067f4fSPoul-Henning Kamp /* private stuff -----------------------------------------------------*/
5675067f4fSPoul-Henning Kamp 
5775067f4fSPoul-Henning Kamp union arg {
5875067f4fSPoul-Henning Kamp 	int			intarg;
5975067f4fSPoul-Henning Kamp 	u_int			uintarg;
6075067f4fSPoul-Henning Kamp 	long			longarg;
6175067f4fSPoul-Henning Kamp 	u_long			ulongarg;
6275067f4fSPoul-Henning Kamp 	intmax_t 		intmaxarg;
6375067f4fSPoul-Henning Kamp 	uintmax_t 		uintmaxarg;
6475067f4fSPoul-Henning Kamp };
6575067f4fSPoul-Henning Kamp 
6675067f4fSPoul-Henning Kamp /*
6775067f4fSPoul-Henning Kamp  * Macros for converting digits to letters and vice versa
6875067f4fSPoul-Henning Kamp  */
6975067f4fSPoul-Henning Kamp #define	to_char(n)	((n) + '0')
7075067f4fSPoul-Henning Kamp 
7175067f4fSPoul-Henning Kamp /* various globals ---------------------------------------------------*/
7275067f4fSPoul-Henning Kamp 
7375067f4fSPoul-Henning Kamp /*
7475067f4fSPoul-Henning Kamp  * The size of the buffer we use for integer conversions.
7575067f4fSPoul-Henning Kamp  * Technically, we would need the most space for base 10
7675067f4fSPoul-Henning Kamp  * conversions with thousands' grouping characters between
7775067f4fSPoul-Henning Kamp  * each pair of digits: 60 digits for 128 bit intmax_t.
7875067f4fSPoul-Henning Kamp  * Use a bit more for better alignment of stuff.
7975067f4fSPoul-Henning Kamp  */
8075067f4fSPoul-Henning Kamp #define	BUF	64
8175067f4fSPoul-Henning Kamp 
8275067f4fSPoul-Henning Kamp /* misc --------------------------------------------------------------*/
8375067f4fSPoul-Henning Kamp 
8475067f4fSPoul-Henning Kamp /*
8575067f4fSPoul-Henning Kamp  * Convert an unsigned long to ASCII for printf purposes, returning
8675067f4fSPoul-Henning Kamp  * a pointer to the first character of the string representation.
8775067f4fSPoul-Henning Kamp  * Octal numbers can be forced to have a leading zero; hex numbers
8875067f4fSPoul-Henning Kamp  * use the given digits.
8975067f4fSPoul-Henning Kamp  */
9075067f4fSPoul-Henning Kamp static char *
9175067f4fSPoul-Henning Kamp __ultoa(u_long val, char *endp, int base, const char *xdigs,
9275067f4fSPoul-Henning Kamp 	int needgrp, char thousep, const char *grp)
9375067f4fSPoul-Henning Kamp {
9475067f4fSPoul-Henning Kamp 	char *cp = endp;
9575067f4fSPoul-Henning Kamp 	long sval;
9675067f4fSPoul-Henning Kamp 	int ndig;
9775067f4fSPoul-Henning Kamp 
9875067f4fSPoul-Henning Kamp 	/*
9975067f4fSPoul-Henning Kamp 	 * Handle the three cases separately, in the hope of getting
10075067f4fSPoul-Henning Kamp 	 * better/faster code.
10175067f4fSPoul-Henning Kamp 	 */
10275067f4fSPoul-Henning Kamp 	switch (base) {
10375067f4fSPoul-Henning Kamp 	case 10:
10475067f4fSPoul-Henning Kamp 		if (val < 10) {	/* many numbers are 1 digit */
10575067f4fSPoul-Henning Kamp 			*--cp = to_char(val);
10675067f4fSPoul-Henning Kamp 			return (cp);
10775067f4fSPoul-Henning Kamp 		}
10875067f4fSPoul-Henning Kamp 		ndig = 0;
10975067f4fSPoul-Henning Kamp 		/*
11075067f4fSPoul-Henning Kamp 		 * On many machines, unsigned arithmetic is harder than
11175067f4fSPoul-Henning Kamp 		 * signed arithmetic, so we do at most one unsigned mod and
11275067f4fSPoul-Henning Kamp 		 * divide; this is sufficient to reduce the range of
11375067f4fSPoul-Henning Kamp 		 * the incoming value to where signed arithmetic works.
11475067f4fSPoul-Henning Kamp 		 */
11575067f4fSPoul-Henning Kamp 		if (val > LONG_MAX) {
11675067f4fSPoul-Henning Kamp 			*--cp = to_char(val % 10);
11775067f4fSPoul-Henning Kamp 			ndig++;
11875067f4fSPoul-Henning Kamp 			sval = val / 10;
11975067f4fSPoul-Henning Kamp 		} else
12075067f4fSPoul-Henning Kamp 			sval = val;
12175067f4fSPoul-Henning Kamp 		do {
12275067f4fSPoul-Henning Kamp 			*--cp = to_char(sval % 10);
12375067f4fSPoul-Henning Kamp 			ndig++;
12475067f4fSPoul-Henning Kamp 			/*
12575067f4fSPoul-Henning Kamp 			 * If (*grp == CHAR_MAX) then no more grouping
12675067f4fSPoul-Henning Kamp 			 * should be performed.
12775067f4fSPoul-Henning Kamp 			 */
12875067f4fSPoul-Henning Kamp 			if (needgrp && ndig == *grp && *grp != CHAR_MAX
12975067f4fSPoul-Henning Kamp 					&& sval > 9) {
13075067f4fSPoul-Henning Kamp 				*--cp = thousep;
13175067f4fSPoul-Henning Kamp 				ndig = 0;
13275067f4fSPoul-Henning Kamp 				/*
13375067f4fSPoul-Henning Kamp 				 * If (*(grp+1) == '\0') then we have to
13475067f4fSPoul-Henning Kamp 				 * use *grp character (last grouping rule)
13575067f4fSPoul-Henning Kamp 				 * for all next cases
13675067f4fSPoul-Henning Kamp 				 */
13775067f4fSPoul-Henning Kamp 				if (*(grp+1) != '\0')
13875067f4fSPoul-Henning Kamp 					grp++;
13975067f4fSPoul-Henning Kamp 			}
14075067f4fSPoul-Henning Kamp 			sval /= 10;
14175067f4fSPoul-Henning Kamp 		} while (sval != 0);
14275067f4fSPoul-Henning Kamp 		break;
14375067f4fSPoul-Henning Kamp 
14475067f4fSPoul-Henning Kamp 	case 8:
14575067f4fSPoul-Henning Kamp 		do {
14675067f4fSPoul-Henning Kamp 			*--cp = to_char(val & 7);
14775067f4fSPoul-Henning Kamp 			val >>= 3;
14875067f4fSPoul-Henning Kamp 		} while (val);
14975067f4fSPoul-Henning Kamp 		break;
15075067f4fSPoul-Henning Kamp 
15175067f4fSPoul-Henning Kamp 	case 16:
15275067f4fSPoul-Henning Kamp 		do {
15375067f4fSPoul-Henning Kamp 			*--cp = xdigs[val & 15];
15475067f4fSPoul-Henning Kamp 			val >>= 4;
15575067f4fSPoul-Henning Kamp 		} while (val);
15675067f4fSPoul-Henning Kamp 		break;
15775067f4fSPoul-Henning Kamp 
15875067f4fSPoul-Henning Kamp 	default:			/* oops */
15975067f4fSPoul-Henning Kamp 		assert(base == 16);
16075067f4fSPoul-Henning Kamp 	}
16175067f4fSPoul-Henning Kamp 	return (cp);
16275067f4fSPoul-Henning Kamp }
16375067f4fSPoul-Henning Kamp 
16475067f4fSPoul-Henning Kamp 
16575067f4fSPoul-Henning Kamp /* Identical to __ultoa, but for intmax_t. */
16675067f4fSPoul-Henning Kamp static char *
16775067f4fSPoul-Henning Kamp __ujtoa(uintmax_t val, char *endp, int base, const char *xdigs,
16875067f4fSPoul-Henning Kamp 	int needgrp, char thousep, const char *grp)
16975067f4fSPoul-Henning Kamp {
17075067f4fSPoul-Henning Kamp 	char *cp = endp;
17175067f4fSPoul-Henning Kamp 	intmax_t sval;
17275067f4fSPoul-Henning Kamp 	int ndig;
17375067f4fSPoul-Henning Kamp 
17475067f4fSPoul-Henning Kamp 	switch (base) {
17575067f4fSPoul-Henning Kamp 	case 10:
17675067f4fSPoul-Henning Kamp 		if (val < 10) {
17775067f4fSPoul-Henning Kamp 			*--cp = to_char(val % 10);
17875067f4fSPoul-Henning Kamp 			return (cp);
17975067f4fSPoul-Henning Kamp 		}
18075067f4fSPoul-Henning Kamp 		ndig = 0;
18175067f4fSPoul-Henning Kamp 		if (val > INTMAX_MAX) {
18275067f4fSPoul-Henning Kamp 			*--cp = to_char(val % 10);
18375067f4fSPoul-Henning Kamp 			ndig++;
18475067f4fSPoul-Henning Kamp 			sval = val / 10;
18575067f4fSPoul-Henning Kamp 		} else
18675067f4fSPoul-Henning Kamp 			sval = val;
18775067f4fSPoul-Henning Kamp 		do {
18875067f4fSPoul-Henning Kamp 			*--cp = to_char(sval % 10);
18975067f4fSPoul-Henning Kamp 			ndig++;
19075067f4fSPoul-Henning Kamp 			/*
19175067f4fSPoul-Henning Kamp 			 * If (*grp == CHAR_MAX) then no more grouping
19275067f4fSPoul-Henning Kamp 			 * should be performed.
19375067f4fSPoul-Henning Kamp 			 */
19475067f4fSPoul-Henning Kamp 			if (needgrp && *grp != CHAR_MAX && ndig == *grp
19575067f4fSPoul-Henning Kamp 					&& sval > 9) {
19675067f4fSPoul-Henning Kamp 				*--cp = thousep;
19775067f4fSPoul-Henning Kamp 				ndig = 0;
19875067f4fSPoul-Henning Kamp 				/*
19975067f4fSPoul-Henning Kamp 				 * If (*(grp+1) == '\0') then we have to
20075067f4fSPoul-Henning Kamp 				 * use *grp character (last grouping rule)
20175067f4fSPoul-Henning Kamp 				 * for all next cases
20275067f4fSPoul-Henning Kamp 				 */
20375067f4fSPoul-Henning Kamp 				if (*(grp+1) != '\0')
20475067f4fSPoul-Henning Kamp 					grp++;
20575067f4fSPoul-Henning Kamp 			}
20675067f4fSPoul-Henning Kamp 			sval /= 10;
20775067f4fSPoul-Henning Kamp 		} while (sval != 0);
20875067f4fSPoul-Henning Kamp 		break;
20975067f4fSPoul-Henning Kamp 
21075067f4fSPoul-Henning Kamp 	case 8:
21175067f4fSPoul-Henning Kamp 		do {
21275067f4fSPoul-Henning Kamp 			*--cp = to_char(val & 7);
21375067f4fSPoul-Henning Kamp 			val >>= 3;
21475067f4fSPoul-Henning Kamp 		} while (val);
21575067f4fSPoul-Henning Kamp 		break;
21675067f4fSPoul-Henning Kamp 
21775067f4fSPoul-Henning Kamp 	case 16:
21875067f4fSPoul-Henning Kamp 		do {
21975067f4fSPoul-Henning Kamp 			*--cp = xdigs[val & 15];
22075067f4fSPoul-Henning Kamp 			val >>= 4;
22175067f4fSPoul-Henning Kamp 		} while (val);
22275067f4fSPoul-Henning Kamp 		break;
22375067f4fSPoul-Henning Kamp 
22475067f4fSPoul-Henning Kamp 	default:
22575067f4fSPoul-Henning Kamp 		abort();
22675067f4fSPoul-Henning Kamp 	}
22775067f4fSPoul-Henning Kamp 	return (cp);
22875067f4fSPoul-Henning Kamp }
22975067f4fSPoul-Henning Kamp 
23075067f4fSPoul-Henning Kamp 
23175067f4fSPoul-Henning Kamp /* 'd' ---------------------------------------------------------------*/
23275067f4fSPoul-Henning Kamp 
23375067f4fSPoul-Henning Kamp int
23475067f4fSPoul-Henning Kamp __printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
23575067f4fSPoul-Henning Kamp {
23675067f4fSPoul-Henning Kamp 	assert (n > 0);
23775067f4fSPoul-Henning Kamp 	argt[0] = PA_INT;
23875067f4fSPoul-Henning Kamp 	if (pi->is_ptrdiff)
23975067f4fSPoul-Henning Kamp 		argt[0] |= PA_FLAG_PTRDIFF;
24075067f4fSPoul-Henning Kamp 	else if (pi->is_size)
24175067f4fSPoul-Henning Kamp 		argt[0] |= PA_FLAG_SIZE;
24275067f4fSPoul-Henning Kamp 	else if (pi->is_long)
24375067f4fSPoul-Henning Kamp 		argt[0] |= PA_FLAG_LONG;
24475067f4fSPoul-Henning Kamp 	else if (pi->is_intmax)
24575067f4fSPoul-Henning Kamp 		argt[0] |= PA_FLAG_INTMAX;
24675067f4fSPoul-Henning Kamp 	else if (pi->is_quad)
24775067f4fSPoul-Henning Kamp 		argt[0] |= PA_FLAG_QUAD;
24875067f4fSPoul-Henning Kamp 	else if (pi->is_long_double)
24975067f4fSPoul-Henning Kamp 		argt[0] |= PA_FLAG_LONG_LONG;
25075067f4fSPoul-Henning Kamp 	else if (pi->is_short)
25175067f4fSPoul-Henning Kamp 		argt[0] |= PA_FLAG_SHORT;
25275067f4fSPoul-Henning Kamp 	else if (pi->is_char)
25375067f4fSPoul-Henning Kamp 		argt[0] = PA_CHAR;
25475067f4fSPoul-Henning Kamp 	return (1);
25575067f4fSPoul-Henning Kamp }
25675067f4fSPoul-Henning Kamp 
25775067f4fSPoul-Henning Kamp int
25875067f4fSPoul-Henning Kamp __printf_render_int(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
25975067f4fSPoul-Henning Kamp {
26075067f4fSPoul-Henning Kamp 	const union arg *argp;
26175067f4fSPoul-Henning Kamp 	char buf[BUF];
26275067f4fSPoul-Henning Kamp 	char *p, *pe;
26375067f4fSPoul-Henning Kamp 	char ns, l;
26475067f4fSPoul-Henning Kamp 	int rdx, sign, zext, ngrp;
26575067f4fSPoul-Henning Kamp 	const char *nalt, *digit;
26675067f4fSPoul-Henning Kamp 	char thousands_sep;	/* locale specific thousands separator */
26775067f4fSPoul-Henning Kamp 	const char *grouping;	/* locale specific numeric grouping rules */
26875067f4fSPoul-Henning Kamp 	uintmax_t uu;
26975067f4fSPoul-Henning Kamp 	int ret;
27075067f4fSPoul-Henning Kamp 
27175067f4fSPoul-Henning Kamp 	ret = 0;
27275067f4fSPoul-Henning Kamp 	nalt = NULL;
27375067f4fSPoul-Henning Kamp 	digit = __lowercase_hex;
27475067f4fSPoul-Henning Kamp 	ns = '\0';
27575067f4fSPoul-Henning Kamp 	pe = buf + sizeof buf - 1;
27675067f4fSPoul-Henning Kamp 
27775067f4fSPoul-Henning Kamp 	if (pi->group) {
27875067f4fSPoul-Henning Kamp 		thousands_sep = *(localeconv()->thousands_sep);
27975067f4fSPoul-Henning Kamp 		grouping = localeconv()->grouping;
28075067f4fSPoul-Henning Kamp 		ngrp = 1;
28175067f4fSPoul-Henning Kamp 	} else {
28275067f4fSPoul-Henning Kamp 		thousands_sep = 0;
28375067f4fSPoul-Henning Kamp 		grouping = NULL;
28475067f4fSPoul-Henning Kamp 		ngrp = 0;
28575067f4fSPoul-Henning Kamp 	}
28675067f4fSPoul-Henning Kamp 
28775067f4fSPoul-Henning Kamp 	switch(pi->spec) {
28875067f4fSPoul-Henning Kamp 	case 'd':
28975067f4fSPoul-Henning Kamp 	case 'i':
29075067f4fSPoul-Henning Kamp 		rdx = 10;
29175067f4fSPoul-Henning Kamp 		sign = 1;
29275067f4fSPoul-Henning Kamp 		break;
29375067f4fSPoul-Henning Kamp 	case 'X':
29475067f4fSPoul-Henning Kamp 		digit = __uppercase_hex;
29575067f4fSPoul-Henning Kamp 		/*FALLTHOUGH*/
29675067f4fSPoul-Henning Kamp 	case 'x':
29775067f4fSPoul-Henning Kamp 		rdx = 16;
29875067f4fSPoul-Henning Kamp 		sign = 0;
29975067f4fSPoul-Henning Kamp 		break;
30075067f4fSPoul-Henning Kamp 	case 'u':
30175067f4fSPoul-Henning Kamp 	case 'U':
30275067f4fSPoul-Henning Kamp 		rdx = 10;
30375067f4fSPoul-Henning Kamp 		sign = 0;
30475067f4fSPoul-Henning Kamp 		break;
30575067f4fSPoul-Henning Kamp 	case 'o':
30675067f4fSPoul-Henning Kamp 	case 'O':
30775067f4fSPoul-Henning Kamp 		rdx = 8;
30875067f4fSPoul-Henning Kamp 		sign = 0;
30975067f4fSPoul-Henning Kamp 		break;
31075067f4fSPoul-Henning Kamp 	default:
31175067f4fSPoul-Henning Kamp 		fprintf(stderr, "pi->spec = '%c'\n", pi->spec);
31275067f4fSPoul-Henning Kamp 		assert(1 == 0);
31375067f4fSPoul-Henning Kamp 	}
31475067f4fSPoul-Henning Kamp 	argp = arg[0];
31575067f4fSPoul-Henning Kamp 
31675067f4fSPoul-Henning Kamp 	if (sign)
31775067f4fSPoul-Henning Kamp 		ns = pi->showsign;
31875067f4fSPoul-Henning Kamp 
31975067f4fSPoul-Henning Kamp 	if (pi->is_long_double || pi->is_quad || pi->is_intmax ||
32075067f4fSPoul-Henning Kamp 	    pi->is_size || pi->is_ptrdiff) {
32175067f4fSPoul-Henning Kamp 		if (sign && argp->intmaxarg < 0) {
32275067f4fSPoul-Henning Kamp 			uu = -argp->intmaxarg;
32375067f4fSPoul-Henning Kamp 			ns = '-';
32475067f4fSPoul-Henning Kamp 		} else
32575067f4fSPoul-Henning Kamp 			uu = argp->uintmaxarg;
32675067f4fSPoul-Henning Kamp 	} else if (pi->is_long) {
32775067f4fSPoul-Henning Kamp 		if (sign && argp->longarg < 0) {
32875067f4fSPoul-Henning Kamp 			uu = (u_long)-argp->longarg;
32975067f4fSPoul-Henning Kamp 			ns = '-';
33075067f4fSPoul-Henning Kamp 		} else
33175067f4fSPoul-Henning Kamp 			uu = argp->ulongarg;
33275067f4fSPoul-Henning Kamp 	} else if (pi->is_short) {
33375067f4fSPoul-Henning Kamp 		if (sign && (short)argp->intarg < 0) {
33475067f4fSPoul-Henning Kamp 			uu = -(short)argp->intarg;
33575067f4fSPoul-Henning Kamp 			ns = '-';
33675067f4fSPoul-Henning Kamp 		} else
33775067f4fSPoul-Henning Kamp 			uu = (unsigned short)argp->uintarg;
33875067f4fSPoul-Henning Kamp 	} else if (pi->is_char) {
33980c276c1SOlivier Houchard 		if (sign && (signed char)argp->intarg < 0) {
34080c276c1SOlivier Houchard 			uu = -(signed char)argp->intarg;
34175067f4fSPoul-Henning Kamp 			ns = '-';
34275067f4fSPoul-Henning Kamp 		} else
34375067f4fSPoul-Henning Kamp 			uu = (unsigned char)argp->uintarg;
34475067f4fSPoul-Henning Kamp 	} else {
34575067f4fSPoul-Henning Kamp 		if (sign && argp->intarg < 0) {
34675067f4fSPoul-Henning Kamp 			uu = (unsigned)-argp->intarg;
34775067f4fSPoul-Henning Kamp 			ns = '-';
34875067f4fSPoul-Henning Kamp 		} else
34975067f4fSPoul-Henning Kamp 			uu = argp->uintarg;
35075067f4fSPoul-Henning Kamp 	}
35175067f4fSPoul-Henning Kamp 	if (uu <= ULONG_MAX)
35275067f4fSPoul-Henning Kamp 		p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
35375067f4fSPoul-Henning Kamp 	else
35475067f4fSPoul-Henning Kamp 		p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
35575067f4fSPoul-Henning Kamp 
35675067f4fSPoul-Henning Kamp 	l = 0;
35775067f4fSPoul-Henning Kamp 	if (uu == 0) {
35875067f4fSPoul-Henning Kamp 		/*-
35975067f4fSPoul-Henning Kamp 		 * ``The result of converting a zero value with an
36075067f4fSPoul-Henning Kamp 		 * explicit precision of zero is no characters.''
36175067f4fSPoul-Henning Kamp 		 *      -- ANSI X3J11
36275067f4fSPoul-Henning Kamp 		 *
36375067f4fSPoul-Henning Kamp 		 * ``The C Standard is clear enough as is.  The call
36475067f4fSPoul-Henning Kamp 		 * printf("%#.0o", 0) should print 0.''
36575067f4fSPoul-Henning Kamp 		 *      -- Defect Report #151
36675067f4fSPoul-Henning Kamp 		 */
36775067f4fSPoul-Henning Kamp 			;
36875067f4fSPoul-Henning Kamp 		if (pi->prec == 0 && !(pi->alt && rdx == 8))
36975067f4fSPoul-Henning Kamp 			p = pe;
37075067f4fSPoul-Henning Kamp 	} else if (pi->alt) {
37175067f4fSPoul-Henning Kamp 		if (rdx == 8)
37275067f4fSPoul-Henning Kamp 			*--p = '0';
37375067f4fSPoul-Henning Kamp 		if (rdx == 16) {
37475067f4fSPoul-Henning Kamp 			if (pi->spec == 'x')
37575067f4fSPoul-Henning Kamp 				nalt = "0x";
37675067f4fSPoul-Henning Kamp 			else
37775067f4fSPoul-Henning Kamp 				nalt = "0X";
37875067f4fSPoul-Henning Kamp 			l += 2;
37975067f4fSPoul-Henning Kamp 		}
38075067f4fSPoul-Henning Kamp 	}
38175067f4fSPoul-Henning Kamp 	l += pe - p;
38275067f4fSPoul-Henning Kamp 	if (ns)
38375067f4fSPoul-Henning Kamp 		l++;
38475067f4fSPoul-Henning Kamp 
38575067f4fSPoul-Henning Kamp 	/*-
38675067f4fSPoul-Henning Kamp 	 * ``... diouXx conversions ... if a precision is
38775067f4fSPoul-Henning Kamp 	 * specified, the 0 flag will be ignored.''
38875067f4fSPoul-Henning Kamp 	 *      -- ANSI X3J11
38975067f4fSPoul-Henning Kamp 	 */
39075067f4fSPoul-Henning Kamp 	if (pi->prec > (pe - p))
39175067f4fSPoul-Henning Kamp 		zext = pi->prec - (pe - p);
39275067f4fSPoul-Henning Kamp 	else if (pi->prec != -1)
39375067f4fSPoul-Henning Kamp 		zext = 0;
39475067f4fSPoul-Henning Kamp 	else if (pi->pad == '0' && pi->width > l && !pi->left)
39575067f4fSPoul-Henning Kamp 		zext = pi->width - l;
39675067f4fSPoul-Henning Kamp 	else
39775067f4fSPoul-Henning Kamp 		zext = 0;
39875067f4fSPoul-Henning Kamp 
39975067f4fSPoul-Henning Kamp 	l += zext;
40075067f4fSPoul-Henning Kamp 
40175067f4fSPoul-Henning Kamp 	while (zext > 0 && p > buf) {
40275067f4fSPoul-Henning Kamp 		*--p = '0';
40375067f4fSPoul-Henning Kamp 		zext--;
40475067f4fSPoul-Henning Kamp 	}
40575067f4fSPoul-Henning Kamp 
40675067f4fSPoul-Henning Kamp 	if (l < BUF) {
40775067f4fSPoul-Henning Kamp 		if (ns) {
40875067f4fSPoul-Henning Kamp 			*--p = ns;
40975067f4fSPoul-Henning Kamp 		} else if (nalt != NULL) {
41075067f4fSPoul-Henning Kamp 			*--p = nalt[1];
41175067f4fSPoul-Henning Kamp 			*--p = nalt[0];
41275067f4fSPoul-Henning Kamp 		}
41375067f4fSPoul-Henning Kamp 		if (pi->width > (pe - p) && !pi->left) {
41475067f4fSPoul-Henning Kamp 			l = pi->width - (pe - p);
41575067f4fSPoul-Henning Kamp 			while (l > 0 && p > buf) {
41675067f4fSPoul-Henning Kamp 				*--p = ' ';
41775067f4fSPoul-Henning Kamp 				l--;
41875067f4fSPoul-Henning Kamp 			}
41975067f4fSPoul-Henning Kamp 			if (l)
42075067f4fSPoul-Henning Kamp 				ret += __printf_pad(io, l, 0);
42175067f4fSPoul-Henning Kamp 		}
42275067f4fSPoul-Henning Kamp 	} else {
42375067f4fSPoul-Henning Kamp 		if (!pi->left && pi->width > l)
42475067f4fSPoul-Henning Kamp 			ret += __printf_pad(io, pi->width - l, 0);
42575067f4fSPoul-Henning Kamp 		if (ns != '\0')
42675067f4fSPoul-Henning Kamp 			ret += __printf_puts(io, &ns, 1);
42775067f4fSPoul-Henning Kamp 		else if (nalt != NULL)
42875067f4fSPoul-Henning Kamp 			ret += __printf_puts(io, nalt, 2);
42975067f4fSPoul-Henning Kamp 		if (zext > 0)
43075067f4fSPoul-Henning Kamp 			ret += __printf_pad(io, zext, 1);
43175067f4fSPoul-Henning Kamp 	}
43275067f4fSPoul-Henning Kamp 
43375067f4fSPoul-Henning Kamp 	ret += __printf_puts(io, p, pe - p);
43475067f4fSPoul-Henning Kamp 	if (pi->width > ret && pi->left)
43575067f4fSPoul-Henning Kamp 		ret += __printf_pad(io, pi->width - ret, 0);
43675067f4fSPoul-Henning Kamp 	__printf_flush(io);
43775067f4fSPoul-Henning Kamp 	return (ret);
43875067f4fSPoul-Henning Kamp }
43975067f4fSPoul-Henning Kamp 
44075067f4fSPoul-Henning Kamp /* 'p' ---------------------------------------------------------------*/
44175067f4fSPoul-Henning Kamp 
44275067f4fSPoul-Henning Kamp int
44375067f4fSPoul-Henning Kamp __printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
44475067f4fSPoul-Henning Kamp {
44575067f4fSPoul-Henning Kamp 
44675067f4fSPoul-Henning Kamp 	assert (n > 0);
44775067f4fSPoul-Henning Kamp 	argt[0] = PA_POINTER;
44875067f4fSPoul-Henning Kamp 	return (1);
44975067f4fSPoul-Henning Kamp }
45075067f4fSPoul-Henning Kamp 
45175067f4fSPoul-Henning Kamp int
45275067f4fSPoul-Henning Kamp __printf_render_ptr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
45375067f4fSPoul-Henning Kamp {
45475067f4fSPoul-Henning Kamp 	struct printf_info p2;
45575067f4fSPoul-Henning Kamp 	uintmax_t u;
45675067f4fSPoul-Henning Kamp 	const void *p;
45775067f4fSPoul-Henning Kamp 
45875067f4fSPoul-Henning Kamp 	/*-
45975067f4fSPoul-Henning Kamp 	 * ``The argument shall be a pointer to void.  The
46075067f4fSPoul-Henning Kamp 	 * value of the pointer is converted to a sequence
46175067f4fSPoul-Henning Kamp 	 * of printable characters, in an implementation-
46275067f4fSPoul-Henning Kamp 	 * defined manner.''
46375067f4fSPoul-Henning Kamp 	 *      -- ANSI X3J11
46475067f4fSPoul-Henning Kamp 	 */
46575067f4fSPoul-Henning Kamp 	u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
46675067f4fSPoul-Henning Kamp 	p2 = *pi;
46775067f4fSPoul-Henning Kamp 
46875067f4fSPoul-Henning Kamp 	p2.spec = 'x';
46975067f4fSPoul-Henning Kamp 	p2.alt = 1;
47075067f4fSPoul-Henning Kamp 	p2.is_long_double = 1;
47175067f4fSPoul-Henning Kamp 	p = &u;
47275067f4fSPoul-Henning Kamp 	return (__printf_render_int(io, &p2, &p));
47375067f4fSPoul-Henning Kamp }
474