File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / compat / snprintf.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:23:02 2012 UTC (12 years, 4 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_5p1, v1_8_3p2, HEAD
sudo

    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>