Upgrade awk(1). 1/2
[dragonfly.git] / lib / libc / stdio / xprintf_int.c
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: src/lib/libc/stdio/xprintf_int.c,v 1.2 2005/12/22 14:23:54 cognet Exp $
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 <string.h>
47 #include <wchar.h>
48 #include "un-namespace.h"
49
50 #include "printf.h"
51
52 /* private stuff -----------------------------------------------------*/
53
54 union arg {
55         int                     intarg;
56         u_int                   uintarg;
57         long                    longarg;
58         u_long                  ulongarg;
59         intmax_t                intmaxarg;
60         uintmax_t               uintmaxarg;
61 };
62
63 /*
64  * Macros for converting digits to letters and vice versa
65  */
66 #define to_char(n)      ((n) + '0')
67
68 /* various globals ---------------------------------------------------*/
69
70 /*
71  * The size of the buffer we use for integer conversions.
72  * Technically, we would need the most space for base 10
73  * conversions with thousands' grouping characters between
74  * each pair of digits: 60 digits for 128 bit intmax_t.
75  * Use a bit more for better alignment of stuff.
76  */
77 #define BUF     64
78
79 /* misc --------------------------------------------------------------*/
80
81 /*
82  * Convert an unsigned long to ASCII for printf purposes, returning
83  * a pointer to the first character of the string representation.
84  * Octal numbers can be forced to have a leading zero; hex numbers
85  * use the given digits.
86  */
87 static char *
88 __ultoa(u_long val, char *endp, int base, const char *xdigs,
89         int needgrp, char thousep, const char *grp)
90 {
91         char *cp = endp;
92         long sval;
93         int ndig;
94
95         /*
96          * Handle the three cases separately, in the hope of getting
97          * better/faster code.
98          */
99         switch (base) {
100         case 10:
101                 if (val < 10) { /* many numbers are 1 digit */
102                         *--cp = to_char(val);
103                         return (cp);
104                 }
105                 ndig = 0;
106                 /*
107                  * On many machines, unsigned arithmetic is harder than
108                  * signed arithmetic, so we do at most one unsigned mod and
109                  * divide; this is sufficient to reduce the range of
110                  * the incoming value to where signed arithmetic works.
111                  */
112                 if (val > LONG_MAX) {
113                         *--cp = to_char(val % 10);
114                         ndig++;
115                         sval = val / 10;
116                 } else {
117                         sval = val;
118                 }
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 *
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                 }
186                 do {
187                         *--cp = to_char(sval % 10);
188                         ndig++;
189                         /*
190                          * If (*grp == CHAR_MAX) then no more grouping
191                          * should be performed.
192                          */
193                         if (needgrp && *grp != CHAR_MAX && ndig == *grp
194                                         && sval > 9) {
195                                 *--cp = thousep;
196                                 ndig = 0;
197                                 /*
198                                  * If (*(grp+1) == '\0') then we have to
199                                  * use *grp character (last grouping rule)
200                                  * for all next cases
201                                  */
202                                 if (*(grp+1) != '\0')
203                                         grp++;
204                         }
205                         sval /= 10;
206                 } while (sval != 0);
207                 break;
208
209         case 8:
210                 do {
211                         *--cp = to_char(val & 7);
212                         val >>= 3;
213                 } while (val);
214                 break;
215
216         case 16:
217                 do {
218                         *--cp = xdigs[val & 15];
219                         val >>= 4;
220                 } while (val);
221                 break;
222
223         default:
224                 abort();
225         }
226         return (cp);
227 }
228
229
230 /* 'd' ---------------------------------------------------------------*/
231
232 int
233 __printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
234 {
235         assert (n > 0);
236         argt[0] = PA_INT;
237         if (pi->is_ptrdiff)
238                 argt[0] |= PA_FLAG_PTRDIFF;
239         else if (pi->is_size)
240                 argt[0] |= PA_FLAG_SIZE;
241         else if (pi->is_long)
242                 argt[0] |= PA_FLAG_LONG;
243         else if (pi->is_intmax)
244                 argt[0] |= PA_FLAG_INTMAX;
245         else if (pi->is_quad)
246                 argt[0] |= PA_FLAG_QUAD;
247         else if (pi->is_long_double)
248                 argt[0] |= PA_FLAG_LONG_LONG;
249         else if (pi->is_short)
250                 argt[0] |= PA_FLAG_SHORT;
251         else if (pi->is_char)
252                 argt[0] = PA_CHAR;
253         return (1);
254 }
255
256 int
257 __printf_render_int(struct __printf_io *io, const struct printf_info *pi,
258                     const void *const *arg)
259 {
260         const union arg *argp;
261         char buf[BUF];
262         char *p, *pe;
263         char ns, l;
264         int rdx, sign, zext, ngrp;
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                 }
327         } else if (pi->is_long) {
328                 if (sign && argp->longarg < 0) {
329                         uu = (u_long)-argp->longarg;
330                         ns = '-';
331                 } else {
332                         uu = argp->ulongarg;
333                 }
334         } else if (pi->is_short) {
335                 if (sign && (short)argp->intarg < 0) {
336                         uu = -(short)argp->intarg;
337                         ns = '-';
338                 } else {
339                         uu = (unsigned short)argp->uintarg;
340                 }
341         } else if (pi->is_char) {
342                 if (sign && (signed char)argp->intarg < 0) {
343                         uu = -(signed char)argp->intarg;
344                         ns = '-';
345                 } else {
346                         uu = (unsigned char)argp->uintarg;
347                 }
348         } else {
349                 if (sign && argp->intarg < 0) {
350                         uu = (unsigned)-argp->intarg;
351                         ns = '-';
352                 } else {
353                         uu = argp->uintarg;
354                 }
355         }
356         if (uu <= ULONG_MAX)
357                 p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
358         else
359                 p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
360
361         l = 0;
362         if (uu == 0) {
363                 /*-
364                  * ``The result of converting a zero value with an
365                  * explicit precision of zero is no characters.''
366                  *      -- ANSI X3J11
367                  *
368                  * ``The C Standard is clear enough as is.  The call
369                  * printf("%#.0o", 0) should print 0.''
370                  *      -- Defect Report #151
371                  */
372                 if (pi->prec == 0 && !(pi->alt && rdx == 8))
373                         p = pe;
374         } else if (pi->alt) {
375                 if (rdx == 8)
376                         *--p = '0';
377                 if (rdx == 16) {
378                         if (pi->spec == 'x')
379                                 nalt = "0x";
380                         else
381                                 nalt = "0X";
382                         l += 2;
383                 }
384         }
385         l += pe - p;
386         if (ns)
387                 l++;
388
389         /*-
390          * ``... diouXx conversions ... if a precision is
391          * specified, the 0 flag will be ignored.''
392          *      -- ANSI X3J11
393          */
394         if (pi->prec > (pe - p))
395                 zext = pi->prec - (pe - p);
396         else if (pi->prec != -1)
397                 zext = 0;
398         else if (pi->pad == '0' && pi->width > l && !pi->left)
399                 zext = pi->width - l;
400         else
401                 zext = 0;
402
403         l += zext;
404
405         while (zext > 0 && p > buf) {
406                 *--p = '0';
407                 zext--;
408         }
409
410         if (l < BUF) {
411                 if (ns) {
412                         *--p = ns;
413                 } else if (nalt != NULL) {
414                         *--p = nalt[1];
415                         *--p = nalt[0];
416                 }
417                 if (pi->width > (pe - p) && !pi->left) {
418                         l = pi->width - (pe - p);
419                         while (l > 0 && p > buf) {
420                                 *--p = ' ';
421                                 l--;
422                         }
423                         if (l)
424                                 ret += __printf_pad(io, l, 0);
425                 }
426         } else {
427                 if (!pi->left && pi->width > l)
428                         ret += __printf_pad(io, pi->width - l, 0);
429                 if (ns != '\0')
430                         ret += __printf_puts(io, &ns, 1);
431                 else if (nalt != NULL)
432                         ret += __printf_puts(io, nalt, 2);
433                 if (zext > 0)
434                         ret += __printf_pad(io, zext, 1);
435         }
436
437         ret += __printf_puts(io, p, pe - p);
438         if (pi->width > ret && pi->left)
439                 ret += __printf_pad(io, pi->width - ret, 0);
440         __printf_flush(io);
441         return (ret);
442 }
443
444 /* 'p' ---------------------------------------------------------------*/
445
446 int
447 __printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
448 {
449
450         assert (n > 0);
451         argt[0] = PA_POINTER;
452         return (1);
453 }
454
455 int
456 __printf_render_ptr(struct __printf_io *io, const struct printf_info *pi,
457                     const void *const *arg)
458 {
459         struct printf_info p2;
460         uintmax_t u;
461         const void *p;
462
463         /*-
464          * ``The argument shall be a pointer to void.  The
465          * value of the pointer is converted to a sequence
466          * of printable characters, in an implementation-
467          * defined manner.''
468          *      -- ANSI X3J11
469          */
470         u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
471         p2 = *pi;
472
473         p2.spec = 'x';
474         p2.alt = 1;
475         p2.is_long_double = 1;
476         p = &u;
477         return (__printf_render_int(io, &p2, &p));
478 }