Annotation of embedaddon/sudo/compat/snprintf.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1999-2005, 2008, 2010-2011
3: * Todd C. Miller <Todd.Miller@courtesan.com>
4: * Copyright (c) 1990, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * Chris Torek.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * From: @(#)vfprintf.c 8.1 (Berkeley) 6/4/93
35: */
36:
37: /*
38: * v?snprintf/v?asprintf based on 4.4BSD stdio.
39: * NOTE: does not support floating point.
40: */
41:
42: #include <config.h>
43:
44: #include <sys/types.h>
45: #include <sys/param.h>
46:
47: #include <stdio.h>
48: #ifdef STDC_HEADERS
49: # include <stdlib.h>
50: # include <stddef.h>
51: #else
52: # ifdef HAVE_STDLIB_H
53: # include <stdlib.h>
54: # endif
55: #endif /* STDC_HEADERS */
56: #ifdef HAVE_STDINT_H
57: # include <stdint.h>
58: #endif
59: #ifdef HAVE_STRING_H
60: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
61: # include <memory.h>
62: # endif
63: # include <string.h>
64: #endif /* HAVE_STRING_H */
65: #ifdef HAVE_STRINGS_H
66: # include <strings.h>
67: #endif /* HAVE_STRINGS_H */
68: #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
69: # include <malloc.h>
70: #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
71: #include <limits.h>
72: #include <stdarg.h>
73:
74: #include "missing.h"
75:
76: static int xxxprintf(char **, size_t, int, const char *, va_list);
77:
78: /*
79: * Some systems may not have these defined in <limits.h>
80: */
81: #ifndef ULONG_MAX
82: # define ULONG_MAX ((unsigned long)-1)
83: #endif
84: #ifndef LONG_MAX
85: # define LONG_MAX (ULONG_MAX / 2)
86: #endif
87: #ifdef HAVE_LONG_LONG_INT
88: # ifndef ULLONG_MAX
89: # ifdef UQUAD_MAX
90: # define ULLONG_MAX UQUAD_MAX
91: # else
92: # define ULLONG_MAX ((unsigned long long)-1)
93: # endif
94: # endif
95: # ifndef LLONG_MAX
96: # ifdef QUAD_MAX
97: # define LLONG_MAX QUAD_MAX
98: # else
99: # define LLONG_MAX (ULLONG_MAX / 2)
100: # endif
101: # endif
102: #endif /* HAVE_LONG_LONG_INT */
103:
104: /*
105: * Macros for converting digits to letters and vice versa
106: */
107: #define to_digit(c) ((c) - '0')
108: #define is_digit(c) ((unsigned int)to_digit(c) <= 9)
109: #define to_char(n) ((n) + '0')
110:
111: /*
112: * Flags used during conversion.
113: */
114: #define ALT 0x001 /* alternate form */
115: #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
116: #define LADJUST 0x004 /* left adjustment */
117: #define LONGDBL 0x008 /* long double; unimplemented */
118: #define LONGINT 0x010 /* long integer */
119: #define QUADINT 0x020 /* quad integer */
120: #define SHORTINT 0x040 /* short integer */
121: #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
122:
123: #define BUF 68
124:
125: /*
126: * Convert an unsigned long to ASCII for printf purposes, returning
127: * a pointer to the first character of the string representation.
128: * Octal numbers can be forced to have a leading zero; hex numbers
129: * use the given digits.
130: */
131: static char *
132: __ultoa(unsigned long val, char *endp, int base, int octzero, char *xdigs)
133: {
134: char *cp = endp;
135: long sval;
136:
137: /*
138: * Handle the three cases separately, in the hope of getting
139: * better/faster code.
140: */
141: switch (base) {
142: case 10:
143: if (val < 10) { /* many numbers are 1 digit */
144: *--cp = to_char(val);
145: return cp;
146: }
147: /*
148: * On many machines, unsigned arithmetic is harder than
149: * signed arithmetic, so we do at most one unsigned mod and
150: * divide; this is sufficient to reduce the range of
151: * the incoming value to where signed arithmetic works.
152: */
153: if (val > LONG_MAX) {
154: *--cp = to_char(val % 10);
155: sval = val / 10;
156: } else
157: sval = val;
158: do {
159: *--cp = to_char(sval % 10);
160: sval /= 10;
161: } while (sval != 0);
162: break;
163:
164: case 8:
165: do {
166: *--cp = to_char(val & 7);
167: val >>= 3;
168: } while (val);
169: if (octzero && *cp != '0')
170: *--cp = '0';
171: break;
172:
173: case 16:
174: do {
175: *--cp = xdigs[val & 15];
176: val >>= 4;
177: } while (val);
178: break;
179:
180: default: /* oops */
181: abort();
182: }
183: return cp;
184: }
185:
186: /* Identical to __ultoa, but for quads. */
187: #ifdef HAVE_LONG_LONG_INT
188: # if SIZEOF_LONG_INT == 8
189: # define __uqtoa(v, e, b, o, x) __ultoa((unsigned long)(v), (e), (b), (o), (x))
190: # else
191: static char *
192: __uqtoa(unsigned long long val, char *endp, int base, int octzero, char *xdigs)
193: {
194: char *cp = endp;
195: long long sval;
196:
197: /* quick test for small values; __ultoa is typically much faster */
198: /* (perhaps instead we should run until small, then call __ultoa?) */
199: if (val <= (unsigned long long)ULONG_MAX)
200: return __ultoa((unsigned long)val, endp, base, octzero, xdigs);
201: switch (base) {
202: case 10:
203: if (val < 10) {
204: *--cp = to_char(val % 10);
205: return cp;
206: }
207: if (val > LLONG_MAX) {
208: *--cp = to_char(val % 10);
209: sval = val / 10;
210: } else
211: sval = val;
212: do {
213: *--cp = to_char(sval % 10);
214: sval /= 10;
215: } while (sval != 0);
216: break;
217:
218: case 8:
219: do {
220: *--cp = to_char(val & 7);
221: val >>= 3;
222: } while (val);
223: if (octzero && *cp != '0')
224: *--cp = '0';
225: break;
226:
227: case 16:
228: do {
229: *--cp = xdigs[val & 15];
230: val >>= 4;
231: } while (val);
232: break;
233:
234: default: /* oops */
235: abort();
236: }
237: return cp;
238: }
239: # endif /* !SIZEOF_LONG_INT */
240: #endif /* HAVE_LONG_LONG_INT */
241:
242: /*
243: * Actual printf innards.
244: */
245: static int
246: xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
247: {
248: char *fmt; /* format string */
249: int ch; /* character from fmt */
250: int n; /* handy integer (short term usage) */
251: char *cp; /* handy char pointer (short term usage) */
252: int flags; /* flags as above */
253: int ret; /* return value accumulator */
254: int width; /* width from format (%8d), or 0 */
255: int prec; /* precision from format (%.3d), or -1 */
256: char sign; /* sign prefix (' ', '+', '-', or \0) */
257: unsigned long ulval = 0; /* integer arguments %[diouxX] */
258: #ifdef HAVE_LONG_LONG_INT
259: unsigned long long uqval = 0; /* %q (quad) integers */
260: #endif
261: int base; /* base for [diouxX] conversion */
262: int dprec; /* a copy of prec if [diouxX], 0 otherwise */
263: int fieldsz; /* field size expanded by sign, etc */
264: int realsz; /* field size expanded by dprec */
265: int size; /* size of converted field or string */
266: char *xdigs = ""; /* digits for [xX] conversion */
267: char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
268: char ox[2]; /* space for 0x hex-prefix */
269: char *str; /* pointer to string to fill */
270: char *estr; /* pointer to last char in str */
271:
272: /*
273: * Choose PADSIZE to trade efficiency vs. size. If larger printf
274: * fields occur frequently, increase PADSIZE and make the initialisers
275: * below longer.
276: */
277: #define PADSIZE 16 /* pad chunk size */
278: static char blanks[PADSIZE] =
279: {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
280: static char zeroes[PADSIZE] =
281: {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
282:
283: /* Print chars to "str", (allocate as needed if alloc is set). */
284: #define PRINT(ptr, len) do { \
285: const char *p = ptr; \
286: const char *endp = ptr + len; \
287: while (p < endp && (str < estr || alloc)) { \
288: if (alloc && str >= estr) { \
289: char *t; \
290: strsize = (strsize << 1) + 1; \
291: if (!(t = (char *)realloc(*strp, strsize))) { \
292: free(str); \
293: *strp = NULL; \
294: ret = -1; \
295: goto done; \
296: } \
297: str = t + (str - *strp); \
298: estr = t + strsize - 1; \
299: *strp = t; \
300: } \
301: *str++ = *p++; \
302: } \
303: } while (0)
304:
305: /* BEWARE, PAD uses `n'. */
306: #define PAD(plen, pstr) do { \
307: if ((n = (plen)) > 0) { \
308: while (n > PADSIZE) { \
309: PRINT(pstr, PADSIZE); \
310: n -= PADSIZE; \
311: } \
312: PRINT(pstr, n); \
313: } \
314: } while (0)
315:
316: /*
317: * To extend shorts properly, we need both signed and unsigned
318: * argument extraction methods.
319: */
320: #define SARG() \
321: (flags&LONGINT ? va_arg(ap, long) : \
322: flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
323: (long)va_arg(ap, int))
324: #define UARG() \
325: (flags&LONGINT ? va_arg(ap, unsigned long) : \
326: flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
327: (unsigned long)va_arg(ap, unsigned int))
328:
329: fmt = (char *)fmt0;
330: ret = 0;
331:
332: if (alloc) {
333: strsize = 128;
334: *strp = str = (char *)malloc(strsize);
335: if (str == NULL) {
336: ret = -1;
337: goto done;
338: }
339: estr = str + 127;
340: } else {
341: str = *strp;
342: if (strsize)
343: estr = str + strsize - 1;
344: else
345: estr = NULL;
346: }
347:
348: /*
349: * Scan the format for conversions (`%' character).
350: */
351: for (;;) {
352: for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
353: /* void */;
354: if ((n = fmt - cp) != 0) {
355: PRINT(cp, n);
356: ret += n;
357: }
358: if (ch == '\0')
359: goto done;
360: fmt++; /* skip over '%' */
361:
362: flags = 0;
363: dprec = 0;
364: width = 0;
365: prec = -1;
366: sign = '\0';
367:
368: rflag: ch = *fmt++;
369: reswitch: switch (ch) {
370: case ' ':
371: /*
372: * ``If the space and + flags both appear, the space
373: * flag will be ignored.''
374: * -- ANSI X3J11
375: */
376: if (!sign)
377: sign = ' ';
378: goto rflag;
379: case '#':
380: flags |= ALT;
381: goto rflag;
382: case '*':
383: /*
384: * ``A negative field width argument is taken as a
385: * - flag followed by a positive field width.''
386: * -- ANSI X3J11
387: * They don't exclude field widths read from args.
388: */
389: if ((width = va_arg(ap, int)) >= 0)
390: goto rflag;
391: width = -width;
392: /* FALLTHROUGH */
393: case '-':
394: flags |= LADJUST;
395: goto rflag;
396: case '+':
397: sign = '+';
398: goto rflag;
399: case '.':
400: if ((ch = *fmt++) == '*') {
401: n = va_arg(ap, int);
402: prec = n < 0 ? -1 : n;
403: goto rflag;
404: }
405: n = 0;
406: while (is_digit(ch)) {
407: n = 10 * n + to_digit(ch);
408: ch = *fmt++;
409: }
410: prec = n < 0 ? -1 : n;
411: goto reswitch;
412: case '0':
413: /*
414: * ``Note that 0 is taken as a flag, not as the
415: * beginning of a field width.''
416: * -- ANSI X3J11
417: */
418: flags |= ZEROPAD;
419: goto rflag;
420: case '1': case '2': case '3': case '4':
421: case '5': case '6': case '7': case '8': case '9':
422: n = 0;
423: do {
424: n = 10 * n + to_digit(ch);
425: ch = *fmt++;
426: } while (is_digit(ch));
427: width = n;
428: goto reswitch;
429: case 'h':
430: flags |= SHORTINT;
431: goto rflag;
432: case 'l':
433: flags |= LONGINT;
434: goto rflag;
435: #ifdef HAVE_LONG_LONG_INT
436: case 'q':
437: flags |= QUADINT;
438: goto rflag;
439: #endif /* HAVE_LONG_LONG_INT */
440: case 'c':
441: *(cp = buf) = va_arg(ap, int);
442: size = 1;
443: sign = '\0';
444: break;
445: case 'D':
446: flags |= LONGINT;
447: /*FALLTHROUGH*/
448: case 'd':
449: case 'i':
450: #ifdef HAVE_LONG_LONG_INT
451: if (flags & QUADINT) {
452: uqval = va_arg(ap, long long);
453: if ((long long)uqval < 0) {
454: uqval = -uqval;
455: sign = '-';
456: }
457: }
458: else
459: #endif /* HAVE_LONG_LONG_INT */
460: {
461: ulval = SARG();
462: if ((long)ulval < 0) {
463: ulval = -ulval;
464: sign = '-';
465: }
466: }
467: base = 10;
468: goto number;
469: case 'n':
470: #ifdef HAVE_LONG_LONG_INT
471: if (flags & QUADINT)
472: *va_arg(ap, long long *) = ret;
473: else
474: #endif /* HAVE_LONG_LONG_INT */
475: if (flags & LONGINT)
476: *va_arg(ap, long *) = ret;
477: else if (flags & SHORTINT)
478: *va_arg(ap, short *) = ret;
479: else
480: *va_arg(ap, int *) = ret;
481: continue; /* no output */
482: case 'O':
483: flags |= LONGINT;
484: /*FALLTHROUGH*/
485: case 'o':
486: #ifdef HAVE_LONG_LONG_INT
487: if (flags & QUADINT)
488: uqval = va_arg(ap, unsigned long long);
489: else
490: #endif /* HAVE_LONG_LONG_INT */
491: ulval = UARG();
492: base = 8;
493: goto nosign;
494: case 'p':
495: /*
496: * ``The argument shall be a pointer to void. The
497: * value of the pointer is converted to a sequence
498: * of printable characters, in an implementation-
499: * defined manner.''
500: * -- ANSI X3J11
501: */
502: ulval = (unsigned long)va_arg(ap, void *);
503: base = 16;
504: xdigs = "0123456789abcdef";
505: flags = (flags & ~QUADINT) | HEXPREFIX;
506: ch = 'x';
507: goto nosign;
508: case 's':
509: if ((cp = va_arg(ap, char *)) == NULL)
510: cp = "(null)";
511: if (prec >= 0) {
512: /*
513: * can't use strlen; can only look for the
514: * NUL in the first `prec' characters, and
515: * strlen() will go further.
516: */
517: char *p = memchr(cp, 0, prec);
518:
519: if (p != NULL) {
520: size = p - cp;
521: if (size > prec)
522: size = prec;
523: } else
524: size = prec;
525: } else
526: size = strlen(cp);
527: sign = '\0';
528: break;
529: case 'U':
530: flags |= LONGINT;
531: /*FALLTHROUGH*/
532: case 'u':
533: #ifdef HAVE_LONG_LONG_INT
534: if (flags & QUADINT)
535: uqval = va_arg(ap, unsigned long long);
536: else
537: #endif /* HAVE_LONG_LONG_INT */
538: ulval = UARG();
539: base = 10;
540: goto nosign;
541: case 'X':
542: xdigs = "0123456789ABCDEF";
543: goto hex;
544: case 'x':
545: xdigs = "0123456789abcdef";
546: hex:
547: #ifdef HAVE_LONG_LONG_INT
548: if (flags & QUADINT)
549: uqval = va_arg(ap, unsigned long long);
550: else
551: #endif /* HAVE_LONG_LONG_INT */
552: ulval = UARG();
553: base = 16;
554: /* leading 0x/X only if non-zero */
555: if (flags & ALT &&
556: #ifdef HAVE_LONG_LONG_INT
557: (flags & QUADINT ? uqval != 0 : ulval != 0))
558: #else
559: ulval != 0)
560: #endif /* HAVE_LONG_LONG_INT */
561: flags |= HEXPREFIX;
562:
563: /* unsigned conversions */
564: nosign: sign = '\0';
565: /*
566: * ``... diouXx conversions ... if a precision is
567: * specified, the 0 flag will be ignored.''
568: * -- ANSI X3J11
569: */
570: number: if ((dprec = prec) >= 0)
571: flags &= ~ZEROPAD;
572:
573: /*
574: * ``The result of converting a zero value with an
575: * explicit precision of zero is no characters.''
576: * -- ANSI X3J11
577: */
578: cp = buf + BUF;
579: #ifdef HAVE_LONG_LONG_INT
580: if (flags & QUADINT) {
581: if (uqval != 0 || prec != 0)
582: cp = __uqtoa(uqval, cp, base,
583: flags & ALT, xdigs);
584: }
585: else
586: #endif /* HAVE_LONG_LONG_INT */
587: {
588: if (ulval != 0 || prec != 0)
589: cp = __ultoa(ulval, cp, base,
590: flags & ALT, xdigs);
591: }
592: size = buf + BUF - cp;
593: break;
594: default: /* "%?" prints ?, unless ? is NUL */
595: if (ch == '\0')
596: goto done;
597: /* pretend it was %c with argument ch */
598: cp = buf;
599: *cp = ch;
600: size = 1;
601: sign = '\0';
602: break;
603: }
604:
605: /*
606: * All reasonable formats wind up here. At this point, `cp'
607: * points to a string which (if not flags&LADJUST) should be
608: * padded out to `width' places. If flags&ZEROPAD, it should
609: * first be prefixed by any sign or other prefix; otherwise,
610: * it should be blank padded before the prefix is emitted.
611: * After any left-hand padding and prefixing, emit zeroes
612: * required by a decimal [diouxX] precision, then print the
613: * string proper, then emit zeroes required by any leftover
614: * floating precision; finally, if LADJUST, pad with blanks.
615: *
616: * Compute actual size, so we know how much to pad.
617: * fieldsz excludes decimal prec; realsz includes it.
618: */
619: fieldsz = size;
620: if (sign)
621: fieldsz++;
622: else if (flags & HEXPREFIX)
623: fieldsz += 2;
624: realsz = dprec > fieldsz ? dprec : fieldsz;
625:
626: /* right-adjusting blank padding */
627: if ((flags & (LADJUST|ZEROPAD)) == 0)
628: PAD(width - realsz, blanks);
629:
630: /* prefix */
631: if (sign) {
632: PRINT(&sign, 1);
633: } else if (flags & HEXPREFIX) {
634: ox[0] = '0';
635: ox[1] = ch;
636: PRINT(ox, 2);
637: }
638:
639: /* right-adjusting zero padding */
640: if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
641: PAD(width - realsz, zeroes);
642:
643: /* leading zeroes from decimal precision */
644: PAD(dprec - fieldsz, zeroes);
645:
646: /* the string or number proper */
647: PRINT(cp, size);
648:
649: /* left-adjusting padding (always blank) */
650: if (flags & LADJUST)
651: PAD(width - realsz, blanks);
652:
653: /* finally, adjust ret */
654: ret += width > realsz ? width : realsz;
655: }
656: done:
657: if (strsize)
658: *str = '\0';
659: return ret;
660: /* NOTREACHED */
661: }
662:
663: #ifndef HAVE_VSNPRINTF
664: int
665: vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
666: {
667:
668: return xxxprintf(&str, n, 0, fmt, ap);
669: }
670: #endif /* HAVE_VSNPRINTF */
671:
672: #ifndef HAVE_SNPRINTF
673: int
674: snprintf(char *str, size_t n, char const *fmt, ...)
675: {
676: int ret;
677: va_list ap;
678:
679: va_start(ap, fmt);
680: ret = xxxprintf(&str, n, 0, fmt, ap);
681: va_end(ap);
682: return ret;
683: }
684: #endif /* HAVE_SNPRINTF */
685:
686: #ifndef HAVE_VASPRINTF
687: int
688: vasprintf(char **str, const char *fmt, va_list ap)
689: {
690:
691: return xxxprintf(str, 0, 1, fmt, ap);
692: }
693: #endif /* HAVE_VASPRINTF */
694:
695: #ifndef HAVE_ASPRINTF
696: int
697: asprintf(char **str, char const *fmt, ...)
698: {
699: int ret;
700: va_list ap;
701:
702: va_start(ap, fmt);
703: ret = xxxprintf(str, 0, 1, fmt, ap);
704: va_end(ap);
705: return ret;
706: }
707: #endif /* HAVE_ASPRINTF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>