1153486Sphk/*-
2153486Sphk * Copyright (c) 2005 Poul-Henning Kamp
3153486Sphk * Copyright (c) 1990, 1993
4153486Sphk *	The Regents of the University of California.  All rights reserved.
5153486Sphk *
6153486Sphk * This code is derived from software contributed to Berkeley by
7153486Sphk * Chris Torek.
8153486Sphk *
9153486Sphk * Redistribution and use in source and binary forms, with or without
10153486Sphk * modification, are permitted provided that the following conditions
11153486Sphk * are met:
12153486Sphk * 1. Redistributions of source code must retain the above copyright
13153486Sphk *    notice, this list of conditions and the following disclaimer.
14153486Sphk * 2. Redistributions in binary form must reproduce the above copyright
15153486Sphk *    notice, this list of conditions and the following disclaimer in the
16153486Sphk *    documentation and/or other materials provided with the distribution.
17153486Sphk * 3. Neither the name of the University nor the names of its contributors
18153486Sphk *    may be used to endorse or promote products derived from this software
19153486Sphk *    without specific prior written permission.
20153486Sphk *
21153486Sphk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22153486Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23153486Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24153486Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25153486Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26153486Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27153486Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28153486Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29153486Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30153486Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31153486Sphk * SUCH DAMAGE.
32153486Sphk *
33153486Sphk * $FreeBSD$
34153486Sphk */
35153486Sphk
36153486Sphk#include <namespace.h>
37153486Sphk#include <err.h>
38153486Sphk#include <sys/types.h>
39153486Sphk#include <stddef.h>
40153486Sphk#include <stdlib.h>
41153486Sphk#include <stdio.h>
42153486Sphk#include <limits.h>
43153486Sphk#include <locale.h>
44153486Sphk#include <stdint.h>
45153486Sphk#include <assert.h>
46153486Sphk#include <namespace.h>
47153486Sphk#include <string.h>
48153486Sphk#include <wchar.h>
49153486Sphk#include <un-namespace.h>
50153486Sphk
51153486Sphk#include "printf.h"
52153486Sphk
53153486Sphk/* private stuff -----------------------------------------------------*/
54153486Sphk
55153486Sphkunion arg {
56153486Sphk	int			intarg;
57153486Sphk	u_int			uintarg;
58153486Sphk	long			longarg;
59153486Sphk	u_long			ulongarg;
60153486Sphk	intmax_t 		intmaxarg;
61153486Sphk	uintmax_t 		uintmaxarg;
62153486Sphk};
63153486Sphk
64153486Sphk/*
65153486Sphk * Macros for converting digits to letters and vice versa
66153486Sphk */
67153486Sphk#define	to_char(n)	((n) + '0')
68153486Sphk
69153486Sphk/* various globals ---------------------------------------------------*/
70153486Sphk
71153486Sphk/*
72153486Sphk * The size of the buffer we use for integer conversions.
73153486Sphk * Technically, we would need the most space for base 10
74153486Sphk * conversions with thousands' grouping characters between
75153486Sphk * each pair of digits: 60 digits for 128 bit intmax_t.
76153486Sphk * Use a bit more for better alignment of stuff.
77153486Sphk */
78153486Sphk#define	BUF	64
79153486Sphk
80153486Sphk/* misc --------------------------------------------------------------*/
81153486Sphk
82153486Sphk/*
83153486Sphk * Convert an unsigned long to ASCII for printf purposes, returning
84153486Sphk * a pointer to the first character of the string representation.
85153486Sphk * Octal numbers can be forced to have a leading zero; hex numbers
86153486Sphk * use the given digits.
87153486Sphk */
88153486Sphkstatic char *
89153486Sphk__ultoa(u_long val, char *endp, int base, const char *xdigs,
90153486Sphk	int needgrp, char thousep, const char *grp)
91153486Sphk{
92153486Sphk	char *cp = endp;
93153486Sphk	long sval;
94153486Sphk	int ndig;
95153486Sphk
96153486Sphk	/*
97153486Sphk	 * Handle the three cases separately, in the hope of getting
98153486Sphk	 * better/faster code.
99153486Sphk	 */
100153486Sphk	switch (base) {
101153486Sphk	case 10:
102153486Sphk		if (val < 10) {	/* many numbers are 1 digit */
103153486Sphk			*--cp = to_char(val);
104153486Sphk			return (cp);
105153486Sphk		}
106153486Sphk		ndig = 0;
107153486Sphk		/*
108153486Sphk		 * On many machines, unsigned arithmetic is harder than
109153486Sphk		 * signed arithmetic, so we do at most one unsigned mod and
110153486Sphk		 * divide; this is sufficient to reduce the range of
111153486Sphk		 * the incoming value to where signed arithmetic works.
112153486Sphk		 */
113153486Sphk		if (val > LONG_MAX) {
114153486Sphk			*--cp = to_char(val % 10);
115153486Sphk			ndig++;
116153486Sphk			sval = val / 10;
117153486Sphk		} else
118153486Sphk			sval = val;
119153486Sphk		do {
120153486Sphk			*--cp = to_char(sval % 10);
121153486Sphk			ndig++;
122153486Sphk			/*
123153486Sphk			 * If (*grp == CHAR_MAX) then no more grouping
124153486Sphk			 * should be performed.
125153486Sphk			 */
126153486Sphk			if (needgrp && ndig == *grp && *grp != CHAR_MAX
127153486Sphk					&& sval > 9) {
128153486Sphk				*--cp = thousep;
129153486Sphk				ndig = 0;
130153486Sphk				/*
131153486Sphk				 * If (*(grp+1) == '\0') then we have to
132153486Sphk				 * use *grp character (last grouping rule)
133153486Sphk				 * for all next cases
134153486Sphk				 */
135153486Sphk				if (*(grp+1) != '\0')
136153486Sphk					grp++;
137153486Sphk			}
138153486Sphk			sval /= 10;
139153486Sphk		} while (sval != 0);
140153486Sphk		break;
141153486Sphk
142153486Sphk	case 8:
143153486Sphk		do {
144153486Sphk			*--cp = to_char(val & 7);
145153486Sphk			val >>= 3;
146153486Sphk		} while (val);
147153486Sphk		break;
148153486Sphk
149153486Sphk	case 16:
150153486Sphk		do {
151153486Sphk			*--cp = xdigs[val & 15];
152153486Sphk			val >>= 4;
153153486Sphk		} while (val);
154153486Sphk		break;
155153486Sphk
156153486Sphk	default:			/* oops */
157153486Sphk		assert(base == 16);
158153486Sphk	}
159153486Sphk	return (cp);
160153486Sphk}
161153486Sphk
162153486Sphk
163153486Sphk/* Identical to __ultoa, but for intmax_t. */
164153486Sphkstatic char *
165153486Sphk__ujtoa(uintmax_t val, char *endp, int base, const char *xdigs,
166153486Sphk	int needgrp, char thousep, const char *grp)
167153486Sphk{
168153486Sphk	char *cp = endp;
169153486Sphk	intmax_t sval;
170153486Sphk	int ndig;
171153486Sphk
172153486Sphk	switch (base) {
173153486Sphk	case 10:
174153486Sphk		if (val < 10) {
175153486Sphk			*--cp = to_char(val % 10);
176153486Sphk			return (cp);
177153486Sphk		}
178153486Sphk		ndig = 0;
179153486Sphk		if (val > INTMAX_MAX) {
180153486Sphk			*--cp = to_char(val % 10);
181153486Sphk			ndig++;
182153486Sphk			sval = val / 10;
183153486Sphk		} else
184153486Sphk			sval = val;
185153486Sphk		do {
186153486Sphk			*--cp = to_char(sval % 10);
187153486Sphk			ndig++;
188153486Sphk			/*
189153486Sphk			 * If (*grp == CHAR_MAX) then no more grouping
190153486Sphk			 * should be performed.
191153486Sphk			 */
192153486Sphk			if (needgrp && *grp != CHAR_MAX && ndig == *grp
193153486Sphk					&& sval > 9) {
194153486Sphk				*--cp = thousep;
195153486Sphk				ndig = 0;
196153486Sphk				/*
197153486Sphk				 * If (*(grp+1) == '\0') then we have to
198153486Sphk				 * use *grp character (last grouping rule)
199153486Sphk				 * for all next cases
200153486Sphk				 */
201153486Sphk				if (*(grp+1) != '\0')
202153486Sphk					grp++;
203153486Sphk			}
204153486Sphk			sval /= 10;
205153486Sphk		} while (sval != 0);
206153486Sphk		break;
207153486Sphk
208153486Sphk	case 8:
209153486Sphk		do {
210153486Sphk			*--cp = to_char(val & 7);
211153486Sphk			val >>= 3;
212153486Sphk		} while (val);
213153486Sphk		break;
214153486Sphk
215153486Sphk	case 16:
216153486Sphk		do {
217153486Sphk			*--cp = xdigs[val & 15];
218153486Sphk			val >>= 4;
219153486Sphk		} while (val);
220153486Sphk		break;
221153486Sphk
222153486Sphk	default:
223153486Sphk		abort();
224153486Sphk	}
225153486Sphk	return (cp);
226153486Sphk}
227153486Sphk
228153486Sphk
229153486Sphk/* 'd' ---------------------------------------------------------------*/
230153486Sphk
231153486Sphkint
232153486Sphk__printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
233153486Sphk{
234153486Sphk	assert (n > 0);
235153486Sphk	argt[0] = PA_INT;
236153486Sphk	if (pi->is_ptrdiff)
237153486Sphk		argt[0] |= PA_FLAG_PTRDIFF;
238153486Sphk	else if (pi->is_size)
239153486Sphk		argt[0] |= PA_FLAG_SIZE;
240153486Sphk	else if (pi->is_long)
241153486Sphk		argt[0] |= PA_FLAG_LONG;
242153486Sphk	else if (pi->is_intmax)
243153486Sphk		argt[0] |= PA_FLAG_INTMAX;
244153486Sphk	else if (pi->is_quad)
245153486Sphk		argt[0] |= PA_FLAG_QUAD;
246153486Sphk	else if (pi->is_long_double)
247153486Sphk		argt[0] |= PA_FLAG_LONG_LONG;
248153486Sphk	else if (pi->is_short)
249153486Sphk		argt[0] |= PA_FLAG_SHORT;
250153486Sphk	else if (pi->is_char)
251153486Sphk		argt[0] = PA_CHAR;
252153486Sphk	return (1);
253153486Sphk}
254153486Sphk
255153486Sphkint
256153486Sphk__printf_render_int(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
257153486Sphk{
258153486Sphk	const union arg *argp;
259153486Sphk	char buf[BUF];
260153486Sphk	char *p, *pe;
261153486Sphk	char ns, l;
262153486Sphk	int rdx, sign, zext, ngrp;
263153486Sphk	const char *nalt, *digit;
264153486Sphk	char thousands_sep;	/* locale specific thousands separator */
265153486Sphk	const char *grouping;	/* locale specific numeric grouping rules */
266153486Sphk	uintmax_t uu;
267153486Sphk	int ret;
268153486Sphk
269153486Sphk	ret = 0;
270153486Sphk	nalt = NULL;
271153486Sphk	digit = __lowercase_hex;
272153486Sphk	ns = '\0';
273153486Sphk	pe = buf + sizeof buf - 1;
274153486Sphk
275153486Sphk	if (pi->group) {
276153486Sphk		thousands_sep = *(localeconv()->thousands_sep);
277153486Sphk		grouping = localeconv()->grouping;
278153486Sphk		ngrp = 1;
279153486Sphk	} else {
280153486Sphk		thousands_sep = 0;
281153486Sphk		grouping = NULL;
282153486Sphk		ngrp = 0;
283153486Sphk	}
284153486Sphk
285153486Sphk	switch(pi->spec) {
286153486Sphk	case 'd':
287153486Sphk	case 'i':
288153486Sphk		rdx = 10;
289153486Sphk		sign = 1;
290153486Sphk		break;
291153486Sphk	case 'X':
292153486Sphk		digit = __uppercase_hex;
293153486Sphk		/*FALLTHOUGH*/
294153486Sphk	case 'x':
295153486Sphk		rdx = 16;
296153486Sphk		sign = 0;
297153486Sphk		break;
298153486Sphk	case 'u':
299153486Sphk	case 'U':
300153486Sphk		rdx = 10;
301153486Sphk		sign = 0;
302153486Sphk		break;
303153486Sphk	case 'o':
304153486Sphk	case 'O':
305153486Sphk		rdx = 8;
306153486Sphk		sign = 0;
307153486Sphk		break;
308153486Sphk	default:
309153486Sphk		fprintf(stderr, "pi->spec = '%c'\n", pi->spec);
310153486Sphk		assert(1 == 0);
311153486Sphk	}
312153486Sphk	argp = arg[0];
313153486Sphk
314153486Sphk	if (sign)
315153486Sphk		ns = pi->showsign;
316153486Sphk
317153486Sphk	if (pi->is_long_double || pi->is_quad || pi->is_intmax ||
318153486Sphk	    pi->is_size || pi->is_ptrdiff) {
319153486Sphk		if (sign && argp->intmaxarg < 0) {
320153486Sphk			uu = -argp->intmaxarg;
321153486Sphk			ns = '-';
322153486Sphk		} else
323153486Sphk			uu = argp->uintmaxarg;
324153486Sphk	} else if (pi->is_long) {
325153486Sphk		if (sign && argp->longarg < 0) {
326153486Sphk			uu = (u_long)-argp->longarg;
327153486Sphk			ns = '-';
328153486Sphk		} else
329153486Sphk			uu = argp->ulongarg;
330153486Sphk	} else if (pi->is_short) {
331153486Sphk		if (sign && (short)argp->intarg < 0) {
332153486Sphk			uu = -(short)argp->intarg;
333153486Sphk			ns = '-';
334153486Sphk		} else
335153486Sphk			uu = (unsigned short)argp->uintarg;
336153486Sphk	} else if (pi->is_char) {
337153641Scognet		if (sign && (signed char)argp->intarg < 0) {
338153641Scognet			uu = -(signed char)argp->intarg;
339153486Sphk			ns = '-';
340153486Sphk		} else
341153486Sphk			uu = (unsigned char)argp->uintarg;
342153486Sphk	} else {
343153486Sphk		if (sign && argp->intarg < 0) {
344153486Sphk			uu = (unsigned)-argp->intarg;
345153486Sphk			ns = '-';
346153486Sphk		} else
347153486Sphk			uu = argp->uintarg;
348153486Sphk	}
349153486Sphk	if (uu <= ULONG_MAX)
350153486Sphk		p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
351153486Sphk	else
352153486Sphk		p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
353153486Sphk
354153486Sphk	l = 0;
355153486Sphk	if (uu == 0) {
356153486Sphk		/*-
357153486Sphk		 * ``The result of converting a zero value with an
358153486Sphk		 * explicit precision of zero is no characters.''
359153486Sphk		 *      -- ANSI X3J11
360153486Sphk		 *
361153486Sphk		 * ``The C Standard is clear enough as is.  The call
362153486Sphk		 * printf("%#.0o", 0) should print 0.''
363153486Sphk		 *      -- Defect Report #151
364153486Sphk		 */
365153486Sphk			;
366153486Sphk		if (pi->prec == 0 && !(pi->alt && rdx == 8))
367153486Sphk			p = pe;
368153486Sphk	} else if (pi->alt) {
369153486Sphk		if (rdx == 8)
370153486Sphk			*--p = '0';
371153486Sphk		if (rdx == 16) {
372153486Sphk			if (pi->spec == 'x')
373153486Sphk				nalt = "0x";
374153486Sphk			else
375153486Sphk				nalt = "0X";
376153486Sphk			l += 2;
377153486Sphk		}
378153486Sphk	}
379153486Sphk	l += pe - p;
380153486Sphk	if (ns)
381153486Sphk		l++;
382153486Sphk
383153486Sphk	/*-
384153486Sphk	 * ``... diouXx conversions ... if a precision is
385153486Sphk	 * specified, the 0 flag will be ignored.''
386153486Sphk	 *      -- ANSI X3J11
387153486Sphk	 */
388153486Sphk	if (pi->prec > (pe - p))
389153486Sphk		zext = pi->prec - (pe - p);
390153486Sphk	else if (pi->prec != -1)
391153486Sphk		zext = 0;
392153486Sphk	else if (pi->pad == '0' && pi->width > l && !pi->left)
393153486Sphk		zext = pi->width - l;
394153486Sphk	else
395153486Sphk		zext = 0;
396153486Sphk
397153486Sphk	l += zext;
398153486Sphk
399153486Sphk	while (zext > 0 && p > buf) {
400153486Sphk		*--p = '0';
401153486Sphk		zext--;
402153486Sphk	}
403153486Sphk
404153486Sphk	if (l < BUF) {
405153486Sphk		if (ns) {
406153486Sphk			*--p = ns;
407153486Sphk		} else if (nalt != NULL) {
408153486Sphk			*--p = nalt[1];
409153486Sphk			*--p = nalt[0];
410153486Sphk		}
411153486Sphk		if (pi->width > (pe - p) && !pi->left) {
412153486Sphk			l = pi->width - (pe - p);
413153486Sphk			while (l > 0 && p > buf) {
414153486Sphk				*--p = ' ';
415153486Sphk				l--;
416153486Sphk			}
417153486Sphk			if (l)
418153486Sphk				ret += __printf_pad(io, l, 0);
419153486Sphk		}
420153486Sphk	} else {
421153486Sphk		if (!pi->left && pi->width > l)
422153486Sphk			ret += __printf_pad(io, pi->width - l, 0);
423153486Sphk		if (ns != '\0')
424153486Sphk			ret += __printf_puts(io, &ns, 1);
425153486Sphk		else if (nalt != NULL)
426153486Sphk			ret += __printf_puts(io, nalt, 2);
427153486Sphk		if (zext > 0)
428153486Sphk			ret += __printf_pad(io, zext, 1);
429153486Sphk	}
430153486Sphk
431153486Sphk	ret += __printf_puts(io, p, pe - p);
432153486Sphk	if (pi->width > ret && pi->left)
433153486Sphk		ret += __printf_pad(io, pi->width - ret, 0);
434153486Sphk	__printf_flush(io);
435153486Sphk	return (ret);
436153486Sphk}
437153486Sphk
438153486Sphk/* 'p' ---------------------------------------------------------------*/
439153486Sphk
440153486Sphkint
441153486Sphk__printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
442153486Sphk{
443153486Sphk
444153486Sphk	assert (n > 0);
445153486Sphk	argt[0] = PA_POINTER;
446153486Sphk	return (1);
447153486Sphk}
448153486Sphk
449153486Sphkint
450153486Sphk__printf_render_ptr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
451153486Sphk{
452153486Sphk	struct printf_info p2;
453153486Sphk	uintmax_t u;
454153486Sphk	const void *p;
455153486Sphk
456153486Sphk	/*-
457153486Sphk	 * ``The argument shall be a pointer to void.  The
458153486Sphk	 * value of the pointer is converted to a sequence
459153486Sphk	 * of printable characters, in an implementation-
460153486Sphk	 * defined manner.''
461153486Sphk	 *      -- ANSI X3J11
462153486Sphk	 */
463153486Sphk	u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
464153486Sphk	p2 = *pi;
465153486Sphk
466153486Sphk	p2.spec = 'x';
467153486Sphk	p2.alt = 1;
468153486Sphk	p2.is_long_double = 1;
469153486Sphk	p = &u;
470153486Sphk	return (__printf_render_int(io, &p2, &p));
471153486Sphk}
472