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