xref: /dflybsd-src/lib/libc/stdio/xprintf_int.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino  * Copyright (c) 2005 Poul-Henning Kamp
3*86d7f5d3SJohn Marino  * Copyright (c) 1990, 1993
4*86d7f5d3SJohn Marino  *	The Regents of the University of California.  All rights reserved.
5*86d7f5d3SJohn Marino  *
6*86d7f5d3SJohn Marino  * This code is derived from software contributed to Berkeley by
7*86d7f5d3SJohn Marino  * Chris Torek.
8*86d7f5d3SJohn Marino  *
9*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
10*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
11*86d7f5d3SJohn Marino  * are met:
12*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
13*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
14*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
15*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
16*86d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
17*86d7f5d3SJohn Marino  * 3. Neither the name of the University nor the names of its contributors
18*86d7f5d3SJohn Marino  *    may be used to endorse or promote products derived from this software
19*86d7f5d3SJohn Marino  *    without specific prior written permission.
20*86d7f5d3SJohn Marino  *
21*86d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22*86d7f5d3SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*86d7f5d3SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*86d7f5d3SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25*86d7f5d3SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*86d7f5d3SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*86d7f5d3SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*86d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*86d7f5d3SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*86d7f5d3SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*86d7f5d3SJohn Marino  * SUCH DAMAGE.
32*86d7f5d3SJohn Marino  *
33*86d7f5d3SJohn Marino  * $FreeBSD: src/lib/libc/stdio/xprintf_int.c,v 1.2 2005/12/22 14:23:54 cognet Exp $
34*86d7f5d3SJohn Marino  */
35*86d7f5d3SJohn Marino 
36*86d7f5d3SJohn Marino #include "namespace.h"
37*86d7f5d3SJohn Marino #include <err.h>
38*86d7f5d3SJohn Marino #include <sys/types.h>
39*86d7f5d3SJohn Marino #include <stddef.h>
40*86d7f5d3SJohn Marino #include <stdlib.h>
41*86d7f5d3SJohn Marino #include <stdio.h>
42*86d7f5d3SJohn Marino #include <limits.h>
43*86d7f5d3SJohn Marino #include <locale.h>
44*86d7f5d3SJohn Marino #include <stdint.h>
45*86d7f5d3SJohn Marino #include <assert.h>
46*86d7f5d3SJohn Marino #include <string.h>
47*86d7f5d3SJohn Marino #include <wchar.h>
48*86d7f5d3SJohn Marino #include "un-namespace.h"
49*86d7f5d3SJohn Marino 
50*86d7f5d3SJohn Marino #include "printf.h"
51*86d7f5d3SJohn Marino 
52*86d7f5d3SJohn Marino /* private stuff -----------------------------------------------------*/
53*86d7f5d3SJohn Marino 
54*86d7f5d3SJohn Marino union arg {
55*86d7f5d3SJohn Marino 	int			intarg;
56*86d7f5d3SJohn Marino 	u_int			uintarg;
57*86d7f5d3SJohn Marino 	long			longarg;
58*86d7f5d3SJohn Marino 	u_long			ulongarg;
59*86d7f5d3SJohn Marino 	intmax_t 		intmaxarg;
60*86d7f5d3SJohn Marino 	uintmax_t 		uintmaxarg;
61*86d7f5d3SJohn Marino };
62*86d7f5d3SJohn Marino 
63*86d7f5d3SJohn Marino /*
64*86d7f5d3SJohn Marino  * Macros for converting digits to letters and vice versa
65*86d7f5d3SJohn Marino  */
66*86d7f5d3SJohn Marino #define	to_char(n)	((n) + '0')
67*86d7f5d3SJohn Marino 
68*86d7f5d3SJohn Marino /* various globals ---------------------------------------------------*/
69*86d7f5d3SJohn Marino 
70*86d7f5d3SJohn Marino /*
71*86d7f5d3SJohn Marino  * The size of the buffer we use for integer conversions.
72*86d7f5d3SJohn Marino  * Technically, we would need the most space for base 10
73*86d7f5d3SJohn Marino  * conversions with thousands' grouping characters between
74*86d7f5d3SJohn Marino  * each pair of digits: 60 digits for 128 bit intmax_t.
75*86d7f5d3SJohn Marino  * Use a bit more for better alignment of stuff.
76*86d7f5d3SJohn Marino  */
77*86d7f5d3SJohn Marino #define	BUF	64
78*86d7f5d3SJohn Marino 
79*86d7f5d3SJohn Marino /* misc --------------------------------------------------------------*/
80*86d7f5d3SJohn Marino 
81*86d7f5d3SJohn Marino /*
82*86d7f5d3SJohn Marino  * Convert an unsigned long to ASCII for printf purposes, returning
83*86d7f5d3SJohn Marino  * a pointer to the first character of the string representation.
84*86d7f5d3SJohn Marino  * Octal numbers can be forced to have a leading zero; hex numbers
85*86d7f5d3SJohn Marino  * use the given digits.
86*86d7f5d3SJohn Marino  */
87*86d7f5d3SJohn Marino static char *
__ultoa(u_long val,char * endp,int base,const char * xdigs,int needgrp,char thousep,const char * grp)88*86d7f5d3SJohn Marino __ultoa(u_long val, char *endp, int base, const char *xdigs,
89*86d7f5d3SJohn Marino 	int needgrp, char thousep, const char *grp)
90*86d7f5d3SJohn Marino {
91*86d7f5d3SJohn Marino 	char *cp = endp;
92*86d7f5d3SJohn Marino 	long sval;
93*86d7f5d3SJohn Marino 	int ndig;
94*86d7f5d3SJohn Marino 
95*86d7f5d3SJohn Marino 	/*
96*86d7f5d3SJohn Marino 	 * Handle the three cases separately, in the hope of getting
97*86d7f5d3SJohn Marino 	 * better/faster code.
98*86d7f5d3SJohn Marino 	 */
99*86d7f5d3SJohn Marino 	switch (base) {
100*86d7f5d3SJohn Marino 	case 10:
101*86d7f5d3SJohn Marino 		if (val < 10) {	/* many numbers are 1 digit */
102*86d7f5d3SJohn Marino 			*--cp = to_char(val);
103*86d7f5d3SJohn Marino 			return (cp);
104*86d7f5d3SJohn Marino 		}
105*86d7f5d3SJohn Marino 		ndig = 0;
106*86d7f5d3SJohn Marino 		/*
107*86d7f5d3SJohn Marino 		 * On many machines, unsigned arithmetic is harder than
108*86d7f5d3SJohn Marino 		 * signed arithmetic, so we do at most one unsigned mod and
109*86d7f5d3SJohn Marino 		 * divide; this is sufficient to reduce the range of
110*86d7f5d3SJohn Marino 		 * the incoming value to where signed arithmetic works.
111*86d7f5d3SJohn Marino 		 */
112*86d7f5d3SJohn Marino 		if (val > LONG_MAX) {
113*86d7f5d3SJohn Marino 			*--cp = to_char(val % 10);
114*86d7f5d3SJohn Marino 			ndig++;
115*86d7f5d3SJohn Marino 			sval = val / 10;
116*86d7f5d3SJohn Marino 		} else {
117*86d7f5d3SJohn Marino 			sval = val;
118*86d7f5d3SJohn Marino 		}
119*86d7f5d3SJohn Marino 		do {
120*86d7f5d3SJohn Marino 			*--cp = to_char(sval % 10);
121*86d7f5d3SJohn Marino 			ndig++;
122*86d7f5d3SJohn Marino 			/*
123*86d7f5d3SJohn Marino 			 * If (*grp == CHAR_MAX) then no more grouping
124*86d7f5d3SJohn Marino 			 * should be performed.
125*86d7f5d3SJohn Marino 			 */
126*86d7f5d3SJohn Marino 			if (needgrp && ndig == *grp && *grp != CHAR_MAX
127*86d7f5d3SJohn Marino 					&& sval > 9) {
128*86d7f5d3SJohn Marino 				*--cp = thousep;
129*86d7f5d3SJohn Marino 				ndig = 0;
130*86d7f5d3SJohn Marino 				/*
131*86d7f5d3SJohn Marino 				 * If (*(grp+1) == '\0') then we have to
132*86d7f5d3SJohn Marino 				 * use *grp character (last grouping rule)
133*86d7f5d3SJohn Marino 				 * for all next cases
134*86d7f5d3SJohn Marino 				 */
135*86d7f5d3SJohn Marino 				if (*(grp+1) != '\0')
136*86d7f5d3SJohn Marino 					grp++;
137*86d7f5d3SJohn Marino 			}
138*86d7f5d3SJohn Marino 			sval /= 10;
139*86d7f5d3SJohn Marino 		} while (sval != 0);
140*86d7f5d3SJohn Marino 		break;
141*86d7f5d3SJohn Marino 
142*86d7f5d3SJohn Marino 	case 8:
143*86d7f5d3SJohn Marino 		do {
144*86d7f5d3SJohn Marino 			*--cp = to_char(val & 7);
145*86d7f5d3SJohn Marino 			val >>= 3;
146*86d7f5d3SJohn Marino 		} while (val);
147*86d7f5d3SJohn Marino 		break;
148*86d7f5d3SJohn Marino 
149*86d7f5d3SJohn Marino 	case 16:
150*86d7f5d3SJohn Marino 		do {
151*86d7f5d3SJohn Marino 			*--cp = xdigs[val & 15];
152*86d7f5d3SJohn Marino 			val >>= 4;
153*86d7f5d3SJohn Marino 		} while (val);
154*86d7f5d3SJohn Marino 		break;
155*86d7f5d3SJohn Marino 
156*86d7f5d3SJohn Marino 	default:			/* oops */
157*86d7f5d3SJohn Marino 		assert(base == 16);
158*86d7f5d3SJohn Marino 	}
159*86d7f5d3SJohn Marino 	return (cp);
160*86d7f5d3SJohn Marino }
161*86d7f5d3SJohn Marino 
162*86d7f5d3SJohn Marino 
163*86d7f5d3SJohn Marino /* Identical to __ultoa, but for intmax_t. */
164*86d7f5d3SJohn Marino static char *
__ujtoa(uintmax_t val,char * endp,int base,const char * xdigs,int needgrp,char thousep,const char * grp)165*86d7f5d3SJohn Marino __ujtoa(uintmax_t val, char *endp, int base, const char *xdigs,
166*86d7f5d3SJohn Marino 	int needgrp, char thousep, const char *grp)
167*86d7f5d3SJohn Marino {
168*86d7f5d3SJohn Marino 	char *cp = endp;
169*86d7f5d3SJohn Marino 	intmax_t sval;
170*86d7f5d3SJohn Marino 	int ndig;
171*86d7f5d3SJohn Marino 
172*86d7f5d3SJohn Marino 	switch (base) {
173*86d7f5d3SJohn Marino 	case 10:
174*86d7f5d3SJohn Marino 		if (val < 10) {
175*86d7f5d3SJohn Marino 			*--cp = to_char(val % 10);
176*86d7f5d3SJohn Marino 			return (cp);
177*86d7f5d3SJohn Marino 		}
178*86d7f5d3SJohn Marino 		ndig = 0;
179*86d7f5d3SJohn Marino 		if (val > INTMAX_MAX) {
180*86d7f5d3SJohn Marino 			*--cp = to_char(val % 10);
181*86d7f5d3SJohn Marino 			ndig++;
182*86d7f5d3SJohn Marino 			sval = val / 10;
183*86d7f5d3SJohn Marino 		} else {
184*86d7f5d3SJohn Marino 			sval = val;
185*86d7f5d3SJohn Marino 		}
186*86d7f5d3SJohn Marino 		do {
187*86d7f5d3SJohn Marino 			*--cp = to_char(sval % 10);
188*86d7f5d3SJohn Marino 			ndig++;
189*86d7f5d3SJohn Marino 			/*
190*86d7f5d3SJohn Marino 			 * If (*grp == CHAR_MAX) then no more grouping
191*86d7f5d3SJohn Marino 			 * should be performed.
192*86d7f5d3SJohn Marino 			 */
193*86d7f5d3SJohn Marino 			if (needgrp && *grp != CHAR_MAX && ndig == *grp
194*86d7f5d3SJohn Marino 					&& sval > 9) {
195*86d7f5d3SJohn Marino 				*--cp = thousep;
196*86d7f5d3SJohn Marino 				ndig = 0;
197*86d7f5d3SJohn Marino 				/*
198*86d7f5d3SJohn Marino 				 * If (*(grp+1) == '\0') then we have to
199*86d7f5d3SJohn Marino 				 * use *grp character (last grouping rule)
200*86d7f5d3SJohn Marino 				 * for all next cases
201*86d7f5d3SJohn Marino 				 */
202*86d7f5d3SJohn Marino 				if (*(grp+1) != '\0')
203*86d7f5d3SJohn Marino 					grp++;
204*86d7f5d3SJohn Marino 			}
205*86d7f5d3SJohn Marino 			sval /= 10;
206*86d7f5d3SJohn Marino 		} while (sval != 0);
207*86d7f5d3SJohn Marino 		break;
208*86d7f5d3SJohn Marino 
209*86d7f5d3SJohn Marino 	case 8:
210*86d7f5d3SJohn Marino 		do {
211*86d7f5d3SJohn Marino 			*--cp = to_char(val & 7);
212*86d7f5d3SJohn Marino 			val >>= 3;
213*86d7f5d3SJohn Marino 		} while (val);
214*86d7f5d3SJohn Marino 		break;
215*86d7f5d3SJohn Marino 
216*86d7f5d3SJohn Marino 	case 16:
217*86d7f5d3SJohn Marino 		do {
218*86d7f5d3SJohn Marino 			*--cp = xdigs[val & 15];
219*86d7f5d3SJohn Marino 			val >>= 4;
220*86d7f5d3SJohn Marino 		} while (val);
221*86d7f5d3SJohn Marino 		break;
222*86d7f5d3SJohn Marino 
223*86d7f5d3SJohn Marino 	default:
224*86d7f5d3SJohn Marino 		abort();
225*86d7f5d3SJohn Marino 	}
226*86d7f5d3SJohn Marino 	return (cp);
227*86d7f5d3SJohn Marino }
228*86d7f5d3SJohn Marino 
229*86d7f5d3SJohn Marino 
230*86d7f5d3SJohn Marino /* 'd' ---------------------------------------------------------------*/
231*86d7f5d3SJohn Marino 
232*86d7f5d3SJohn Marino int
__printf_arginfo_int(const struct printf_info * pi,size_t n,int * argt)233*86d7f5d3SJohn Marino __printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
234*86d7f5d3SJohn Marino {
235*86d7f5d3SJohn Marino 	assert (n > 0);
236*86d7f5d3SJohn Marino 	argt[0] = PA_INT;
237*86d7f5d3SJohn Marino 	if (pi->is_ptrdiff)
238*86d7f5d3SJohn Marino 		argt[0] |= PA_FLAG_PTRDIFF;
239*86d7f5d3SJohn Marino 	else if (pi->is_size)
240*86d7f5d3SJohn Marino 		argt[0] |= PA_FLAG_SIZE;
241*86d7f5d3SJohn Marino 	else if (pi->is_long)
242*86d7f5d3SJohn Marino 		argt[0] |= PA_FLAG_LONG;
243*86d7f5d3SJohn Marino 	else if (pi->is_intmax)
244*86d7f5d3SJohn Marino 		argt[0] |= PA_FLAG_INTMAX;
245*86d7f5d3SJohn Marino 	else if (pi->is_quad)
246*86d7f5d3SJohn Marino 		argt[0] |= PA_FLAG_QUAD;
247*86d7f5d3SJohn Marino 	else if (pi->is_long_double)
248*86d7f5d3SJohn Marino 		argt[0] |= PA_FLAG_LONG_LONG;
249*86d7f5d3SJohn Marino 	else if (pi->is_short)
250*86d7f5d3SJohn Marino 		argt[0] |= PA_FLAG_SHORT;
251*86d7f5d3SJohn Marino 	else if (pi->is_char)
252*86d7f5d3SJohn Marino 		argt[0] = PA_CHAR;
253*86d7f5d3SJohn Marino 	return (1);
254*86d7f5d3SJohn Marino }
255*86d7f5d3SJohn Marino 
256*86d7f5d3SJohn Marino int
__printf_render_int(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)257*86d7f5d3SJohn Marino __printf_render_int(struct __printf_io *io, const struct printf_info *pi,
258*86d7f5d3SJohn Marino 		    const void *const *arg)
259*86d7f5d3SJohn Marino {
260*86d7f5d3SJohn Marino 	const union arg *argp;
261*86d7f5d3SJohn Marino 	char buf[BUF];
262*86d7f5d3SJohn Marino 	char *p, *pe;
263*86d7f5d3SJohn Marino 	char ns, l;
264*86d7f5d3SJohn Marino 	int rdx, sign, zext, ngrp;
265*86d7f5d3SJohn Marino 	const char *nalt, *digit;
266*86d7f5d3SJohn Marino 	char thousands_sep;	/* locale specific thousands separator */
267*86d7f5d3SJohn Marino 	const char *grouping;	/* locale specific numeric grouping rules */
268*86d7f5d3SJohn Marino 	uintmax_t uu;
269*86d7f5d3SJohn Marino 	int ret;
270*86d7f5d3SJohn Marino 
271*86d7f5d3SJohn Marino 	ret = 0;
272*86d7f5d3SJohn Marino 	nalt = NULL;
273*86d7f5d3SJohn Marino 	digit = __lowercase_hex;
274*86d7f5d3SJohn Marino 	ns = '\0';
275*86d7f5d3SJohn Marino 	pe = buf + sizeof buf - 1;
276*86d7f5d3SJohn Marino 
277*86d7f5d3SJohn Marino 	if (pi->group) {
278*86d7f5d3SJohn Marino 		thousands_sep = *(localeconv()->thousands_sep);
279*86d7f5d3SJohn Marino 		grouping = localeconv()->grouping;
280*86d7f5d3SJohn Marino 		ngrp = 1;
281*86d7f5d3SJohn Marino 	} else {
282*86d7f5d3SJohn Marino 		thousands_sep = 0;
283*86d7f5d3SJohn Marino 		grouping = NULL;
284*86d7f5d3SJohn Marino 		ngrp = 0;
285*86d7f5d3SJohn Marino 	}
286*86d7f5d3SJohn Marino 
287*86d7f5d3SJohn Marino 	switch(pi->spec) {
288*86d7f5d3SJohn Marino 	case 'd':
289*86d7f5d3SJohn Marino 	case 'i':
290*86d7f5d3SJohn Marino 		rdx = 10;
291*86d7f5d3SJohn Marino 		sign = 1;
292*86d7f5d3SJohn Marino 		break;
293*86d7f5d3SJohn Marino 	case 'X':
294*86d7f5d3SJohn Marino 		digit = __uppercase_hex;
295*86d7f5d3SJohn Marino 		/*FALLTHOUGH*/
296*86d7f5d3SJohn Marino 	case 'x':
297*86d7f5d3SJohn Marino 		rdx = 16;
298*86d7f5d3SJohn Marino 		sign = 0;
299*86d7f5d3SJohn Marino 		break;
300*86d7f5d3SJohn Marino 	case 'u':
301*86d7f5d3SJohn Marino 	case 'U':
302*86d7f5d3SJohn Marino 		rdx = 10;
303*86d7f5d3SJohn Marino 		sign = 0;
304*86d7f5d3SJohn Marino 		break;
305*86d7f5d3SJohn Marino 	case 'o':
306*86d7f5d3SJohn Marino 	case 'O':
307*86d7f5d3SJohn Marino 		rdx = 8;
308*86d7f5d3SJohn Marino 		sign = 0;
309*86d7f5d3SJohn Marino 		break;
310*86d7f5d3SJohn Marino 	default:
311*86d7f5d3SJohn Marino 		fprintf(stderr, "pi->spec = '%c'\n", pi->spec);
312*86d7f5d3SJohn Marino 		assert(1 == 0);
313*86d7f5d3SJohn Marino 	}
314*86d7f5d3SJohn Marino 	argp = arg[0];
315*86d7f5d3SJohn Marino 
316*86d7f5d3SJohn Marino 	if (sign)
317*86d7f5d3SJohn Marino 		ns = pi->showsign;
318*86d7f5d3SJohn Marino 
319*86d7f5d3SJohn Marino 	if (pi->is_long_double || pi->is_quad || pi->is_intmax ||
320*86d7f5d3SJohn Marino 	    pi->is_size || pi->is_ptrdiff) {
321*86d7f5d3SJohn Marino 		if (sign && argp->intmaxarg < 0) {
322*86d7f5d3SJohn Marino 			uu = -argp->intmaxarg;
323*86d7f5d3SJohn Marino 			ns = '-';
324*86d7f5d3SJohn Marino 		} else {
325*86d7f5d3SJohn Marino 			uu = argp->uintmaxarg;
326*86d7f5d3SJohn Marino 		}
327*86d7f5d3SJohn Marino 	} else if (pi->is_long) {
328*86d7f5d3SJohn Marino 		if (sign && argp->longarg < 0) {
329*86d7f5d3SJohn Marino 			uu = (u_long)-argp->longarg;
330*86d7f5d3SJohn Marino 			ns = '-';
331*86d7f5d3SJohn Marino 		} else {
332*86d7f5d3SJohn Marino 			uu = argp->ulongarg;
333*86d7f5d3SJohn Marino 		}
334*86d7f5d3SJohn Marino 	} else if (pi->is_short) {
335*86d7f5d3SJohn Marino 		if (sign && (short)argp->intarg < 0) {
336*86d7f5d3SJohn Marino 			uu = -(short)argp->intarg;
337*86d7f5d3SJohn Marino 			ns = '-';
338*86d7f5d3SJohn Marino 		} else {
339*86d7f5d3SJohn Marino 			uu = (unsigned short)argp->uintarg;
340*86d7f5d3SJohn Marino 		}
341*86d7f5d3SJohn Marino 	} else if (pi->is_char) {
342*86d7f5d3SJohn Marino 		if (sign && (signed char)argp->intarg < 0) {
343*86d7f5d3SJohn Marino 			uu = -(signed char)argp->intarg;
344*86d7f5d3SJohn Marino 			ns = '-';
345*86d7f5d3SJohn Marino 		} else {
346*86d7f5d3SJohn Marino 			uu = (unsigned char)argp->uintarg;
347*86d7f5d3SJohn Marino 		}
348*86d7f5d3SJohn Marino 	} else {
349*86d7f5d3SJohn Marino 		if (sign && argp->intarg < 0) {
350*86d7f5d3SJohn Marino 			uu = (unsigned)-argp->intarg;
351*86d7f5d3SJohn Marino 			ns = '-';
352*86d7f5d3SJohn Marino 		} else {
353*86d7f5d3SJohn Marino 			uu = argp->uintarg;
354*86d7f5d3SJohn Marino 		}
355*86d7f5d3SJohn Marino 	}
356*86d7f5d3SJohn Marino 	if (uu <= ULONG_MAX)
357*86d7f5d3SJohn Marino 		p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
358*86d7f5d3SJohn Marino 	else
359*86d7f5d3SJohn Marino 		p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
360*86d7f5d3SJohn Marino 
361*86d7f5d3SJohn Marino 	l = 0;
362*86d7f5d3SJohn Marino 	if (uu == 0) {
363*86d7f5d3SJohn Marino 		/*-
364*86d7f5d3SJohn Marino 		 * ``The result of converting a zero value with an
365*86d7f5d3SJohn Marino 		 * explicit precision of zero is no characters.''
366*86d7f5d3SJohn Marino 		 *      -- ANSI X3J11
367*86d7f5d3SJohn Marino 		 *
368*86d7f5d3SJohn Marino 		 * ``The C Standard is clear enough as is.  The call
369*86d7f5d3SJohn Marino 		 * printf("%#.0o", 0) should print 0.''
370*86d7f5d3SJohn Marino 		 *      -- Defect Report #151
371*86d7f5d3SJohn Marino 		 */
372*86d7f5d3SJohn Marino 		if (pi->prec == 0 && !(pi->alt && rdx == 8))
373*86d7f5d3SJohn Marino 			p = pe;
374*86d7f5d3SJohn Marino 	} else if (pi->alt) {
375*86d7f5d3SJohn Marino 		if (rdx == 8)
376*86d7f5d3SJohn Marino 			*--p = '0';
377*86d7f5d3SJohn Marino 		if (rdx == 16) {
378*86d7f5d3SJohn Marino 			if (pi->spec == 'x')
379*86d7f5d3SJohn Marino 				nalt = "0x";
380*86d7f5d3SJohn Marino 			else
381*86d7f5d3SJohn Marino 				nalt = "0X";
382*86d7f5d3SJohn Marino 			l += 2;
383*86d7f5d3SJohn Marino 		}
384*86d7f5d3SJohn Marino 	}
385*86d7f5d3SJohn Marino 	l += pe - p;
386*86d7f5d3SJohn Marino 	if (ns)
387*86d7f5d3SJohn Marino 		l++;
388*86d7f5d3SJohn Marino 
389*86d7f5d3SJohn Marino 	/*-
390*86d7f5d3SJohn Marino 	 * ``... diouXx conversions ... if a precision is
391*86d7f5d3SJohn Marino 	 * specified, the 0 flag will be ignored.''
392*86d7f5d3SJohn Marino 	 *      -- ANSI X3J11
393*86d7f5d3SJohn Marino 	 */
394*86d7f5d3SJohn Marino 	if (pi->prec > (pe - p))
395*86d7f5d3SJohn Marino 		zext = pi->prec - (pe - p);
396*86d7f5d3SJohn Marino 	else if (pi->prec != -1)
397*86d7f5d3SJohn Marino 		zext = 0;
398*86d7f5d3SJohn Marino 	else if (pi->pad == '0' && pi->width > l && !pi->left)
399*86d7f5d3SJohn Marino 		zext = pi->width - l;
400*86d7f5d3SJohn Marino 	else
401*86d7f5d3SJohn Marino 		zext = 0;
402*86d7f5d3SJohn Marino 
403*86d7f5d3SJohn Marino 	l += zext;
404*86d7f5d3SJohn Marino 
405*86d7f5d3SJohn Marino 	while (zext > 0 && p > buf) {
406*86d7f5d3SJohn Marino 		*--p = '0';
407*86d7f5d3SJohn Marino 		zext--;
408*86d7f5d3SJohn Marino 	}
409*86d7f5d3SJohn Marino 
410*86d7f5d3SJohn Marino 	if (l < BUF) {
411*86d7f5d3SJohn Marino 		if (ns) {
412*86d7f5d3SJohn Marino 			*--p = ns;
413*86d7f5d3SJohn Marino 		} else if (nalt != NULL) {
414*86d7f5d3SJohn Marino 			*--p = nalt[1];
415*86d7f5d3SJohn Marino 			*--p = nalt[0];
416*86d7f5d3SJohn Marino 		}
417*86d7f5d3SJohn Marino 		if (pi->width > (pe - p) && !pi->left) {
418*86d7f5d3SJohn Marino 			l = pi->width - (pe - p);
419*86d7f5d3SJohn Marino 			while (l > 0 && p > buf) {
420*86d7f5d3SJohn Marino 				*--p = ' ';
421*86d7f5d3SJohn Marino 				l--;
422*86d7f5d3SJohn Marino 			}
423*86d7f5d3SJohn Marino 			if (l)
424*86d7f5d3SJohn Marino 				ret += __printf_pad(io, l, 0);
425*86d7f5d3SJohn Marino 		}
426*86d7f5d3SJohn Marino 	} else {
427*86d7f5d3SJohn Marino 		if (!pi->left && pi->width > l)
428*86d7f5d3SJohn Marino 			ret += __printf_pad(io, pi->width - l, 0);
429*86d7f5d3SJohn Marino 		if (ns != '\0')
430*86d7f5d3SJohn Marino 			ret += __printf_puts(io, &ns, 1);
431*86d7f5d3SJohn Marino 		else if (nalt != NULL)
432*86d7f5d3SJohn Marino 			ret += __printf_puts(io, nalt, 2);
433*86d7f5d3SJohn Marino 		if (zext > 0)
434*86d7f5d3SJohn Marino 			ret += __printf_pad(io, zext, 1);
435*86d7f5d3SJohn Marino 	}
436*86d7f5d3SJohn Marino 
437*86d7f5d3SJohn Marino 	ret += __printf_puts(io, p, pe - p);
438*86d7f5d3SJohn Marino 	if (pi->width > ret && pi->left)
439*86d7f5d3SJohn Marino 		ret += __printf_pad(io, pi->width - ret, 0);
440*86d7f5d3SJohn Marino 	__printf_flush(io);
441*86d7f5d3SJohn Marino 	return (ret);
442*86d7f5d3SJohn Marino }
443*86d7f5d3SJohn Marino 
444*86d7f5d3SJohn Marino /* 'p' ---------------------------------------------------------------*/
445*86d7f5d3SJohn Marino 
446*86d7f5d3SJohn Marino int
__printf_arginfo_ptr(const struct printf_info * pi __unused,size_t n,int * argt)447*86d7f5d3SJohn Marino __printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
448*86d7f5d3SJohn Marino {
449*86d7f5d3SJohn Marino 
450*86d7f5d3SJohn Marino 	assert (n > 0);
451*86d7f5d3SJohn Marino 	argt[0] = PA_POINTER;
452*86d7f5d3SJohn Marino 	return (1);
453*86d7f5d3SJohn Marino }
454*86d7f5d3SJohn Marino 
455*86d7f5d3SJohn Marino int
__printf_render_ptr(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)456*86d7f5d3SJohn Marino __printf_render_ptr(struct __printf_io *io, const struct printf_info *pi,
457*86d7f5d3SJohn Marino 		    const void *const *arg)
458*86d7f5d3SJohn Marino {
459*86d7f5d3SJohn Marino 	struct printf_info p2;
460*86d7f5d3SJohn Marino 	uintmax_t u;
461*86d7f5d3SJohn Marino 	const void *p;
462*86d7f5d3SJohn Marino 
463*86d7f5d3SJohn Marino 	/*-
464*86d7f5d3SJohn Marino 	 * ``The argument shall be a pointer to void.  The
465*86d7f5d3SJohn Marino 	 * value of the pointer is converted to a sequence
466*86d7f5d3SJohn Marino 	 * of printable characters, in an implementation-
467*86d7f5d3SJohn Marino 	 * defined manner.''
468*86d7f5d3SJohn Marino 	 *      -- ANSI X3J11
469*86d7f5d3SJohn Marino 	 */
470*86d7f5d3SJohn Marino 	u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
471*86d7f5d3SJohn Marino 	p2 = *pi;
472*86d7f5d3SJohn Marino 
473*86d7f5d3SJohn Marino 	p2.spec = 'x';
474*86d7f5d3SJohn Marino 	p2.alt = 1;
475*86d7f5d3SJohn Marino 	p2.is_long_double = 1;
476*86d7f5d3SJohn Marino 	p = &u;
477*86d7f5d3SJohn Marino 	return (__printf_render_int(io, &p2, &p));
478*86d7f5d3SJohn Marino }
479