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
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
55 union 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 */
88 static char *
__ultoa(u_long val,char * endp,int base,const char * xdigs,int needgrp,char thousep,const char * grp)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. */
164 static char *
__ujtoa(uintmax_t val,char * endp,int base,const char * xdigs,int needgrp,char thousep,const char * grp)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
231 int
__printf_arginfo_int(const struct printf_info * pi,size_t n,int * argt)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
255 int
__printf_render_int(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)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;
262 int l, ngrp, rdx, sign, zext;
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
440 int
__printf_arginfo_ptr(const struct printf_info * pi __unused,size_t n,int * argt)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
449 int
__printf_render_ptr(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)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