]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libc/stdio/xprintf_int.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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$
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 *
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 *
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
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
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
440 int
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
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 }