File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / compat / snprintf.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 10:46:11 2013 UTC (10 years, 11 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_8p0, v1_8_8, v1_8_7p0, v1_8_7, HEAD
1.8.7

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>