xref: /freebsd/lib/libc/stdio/xprintf_int.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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