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