11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright Patrick Powell 1995
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This code is based on code written by Patrick Powell (papowell@astart.com)
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * It may be used for any purpose as long as this notice remains intact
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * on all source code distributions
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/**************************************************************
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Original:
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * A bombproof version of doprnt (dopr) included.
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Sigh.  This sort of thing is always nasty do deal with.  Note that
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the version here does not include floating point...
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * snprintf() is used instead of sprintf() as it does limit checks
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * for string length.  This covers a nasty loophole.
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * The other functions are there to prevent NULL pointers from
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * causing nast effects.
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * More Recently:
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  This was ugly.  It is still ugly.  I opted out of floating point
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  numbers, but the formatter understands just about everything
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  from the normal C string format, at least as far as I can tell from
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  the Solaris 2.5 printf(3S) man page.
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    Ok, added some minimal floating point support, which means this
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    probably requires libm on most operating systems.  Don't yet
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint()
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    was pretty badly broken, it just wasn't being exercised in ways
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    which showed it, so that's been fixed.  Also, formated the code
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    to mutt conventions, and removed dead code left over from the
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    original.  Also, there is now a builtin-test, just compile with:
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    and run snprintf for results.
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    The PGP code was using unsigned hexadecimal formats.
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    Unfortunately, unsigned formats simply didn't work.
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    The original code assumed that both snprintf() and vsnprintf() were
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    missing.  Some systems only have snprintf() but not vsnprintf(), so
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *  Andrew Tridgell (tridge@samba.org) Oct 1998
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    fixed handling of %.0f
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    added test for HAVE_LONG_DOUBLE
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * tridge@samba.org, idra@samba.org, April 2001
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    got rid of fcvt code (twas buggy and made testing harder)
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    added C99 semantics
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * date: 2002/12/19 19:56:31;  author: herb;  state: Exp;  lines: +2 -0
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * actually print args for %g and %e
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * date: 2002/06/03 13:37:52;  author: jmcd;  state: Exp;  lines: +8 -0
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Since includes.h isn't included here, VA_COPY has to be defined here.  I don't
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * see any include file that is guaranteed to be here, so I'm defining it
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * locally.  Fixes AIX and Solaris builds.
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * date: 2002/06/03 03:07:24;  author: tridge;  state: Exp;  lines: +5 -13
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * put the ifdef for HAVE_VA_COPY in one place rather than in lots of
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * functions
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * date: 2002/05/17 14:51:22;  author: jmcd;  state: Exp;  lines: +21 -4
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Fix usage of va_list passed as an arg.  Use __va_copy before using it
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * when it exists.
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * date: 2002/04/16 22:38:04;  author: idra;  state: Exp;  lines: +20 -14
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Fix incorrect zpadlen handling in fmtfp.
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * few mods to make it easier to compile the tests.
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * addedd the "Ollie" test to the floating point ones.
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Martin Pool (mbp@samba.org) April 2003
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    Remove NO_CONFIG_H so that the test case can be built within a source
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    tree with less trouble.
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    Remove unnecessary SAFE_FREE() definition.
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Martin Pool (mbp@samba.org) May 2003
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    Put in a prototype for dummy_snprintf() to quiet compiler warnings.
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    if the C library has some snprintf functions already.
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Damien Miller (djm@mindrot.org) Jan 2007
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    Fix integer overflows in return value.
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    Make formatting quite a bit faster by inlining dopr_outch()
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood **************************************************************/
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(BROKEN_SNPRINTF)		/* For those with broken snprintf() */
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# undef HAVE_SNPRINTF
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# undef HAVE_VSNPRINTF
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef VA_COPY
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# ifdef HAVE_VA_COPY
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#  define VA_COPY(dest, src) va_copy(dest, src)
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# else
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#  ifdef HAVE___VA_COPY
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#   define VA_COPY(dest, src) __va_copy(dest, src)
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#  else
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#   define VA_COPY(dest, src) (dest) = (src)
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#  endif
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# endif
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <ctype.h>
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h>
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <limits.h>
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LONG_DOUBLE
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define LDOUBLE long double
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define LDOUBLE double
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LONG_LONG
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define LLONG long long
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define LLONG long
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * dopr(): poor man's version of doprintf
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* format read states */
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_S_DEFAULT 0
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_S_FLAGS   1
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_S_MIN     2
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_S_DOT     3
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_S_MAX     4
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_S_MOD     5
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_S_CONV    6
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_S_DONE    7
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* format flags - Bits */
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_F_MINUS 	(1 << 0)
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_F_PLUS  	(1 << 1)
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_F_SPACE 	(1 << 2)
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_F_NUM   	(1 << 3)
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_F_ZERO  	(1 << 4)
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_F_UP    	(1 << 5)
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_F_UNSIGNED 	(1 << 6)
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Conversion Flags */
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_C_SHORT   1
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_C_LONG    2
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_C_LDOUBLE 3
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DP_C_LLONG   4
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define char_to_int(p) ((p)- '0')
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef MAX
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# define MAX(p,q) (((p) >= (q)) ? (p) : (q))
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DOPR_OUTCH(buf, pos, buflen, thechar) \
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	do { \
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (pos + 1 >= INT_MAX) { \
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			errno = ERANGE; \
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1; \
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} \
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (pos < buflen) \
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buf[pos] = thechar; \
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(pos)++; \
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} while (0)
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int dopr(char *buffer, size_t maxlen, const char *format,
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    va_list args_in);
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fmtstr(char *buffer, size_t *currlen, size_t maxlen,
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    char *value, int flags, int min, int max);
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fmtint(char *buffer, size_t *currlen, size_t maxlen,
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    LLONG value, int base, int min, int max, int flags);
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int fmtfp(char *buffer, size_t *currlen, size_t maxlen,
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    LDOUBLE fvalue, int min, int max, int flags);
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char ch;
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	LLONG value;
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	LDOUBLE fvalue;
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *strvalue;
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int min;
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int max;
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int state;
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int flags;
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cflags;
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t currlen;
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_list args;
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	VA_COPY(args, args_in);
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	state = DP_S_DEFAULT;
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	currlen = flags = cflags = min = 0;
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	max = -1;
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ch = *format++;
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (state != DP_S_DONE) {
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (ch == '\0')
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			state = DP_S_DONE;
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch(state) {
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case DP_S_DEFAULT:
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ch == '%')
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				state = DP_S_FLAGS;
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				DOPR_OUTCH(buffer, currlen, maxlen, ch);
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ch = *format++;
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case DP_S_FLAGS:
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			switch (ch) {
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '-':
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_MINUS;
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '+':
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_PLUS;
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case ' ':
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_SPACE;
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '#':
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_NUM;
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '0':
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_ZERO;
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			default:
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				state = DP_S_MIN;
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case DP_S_MIN:
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (isdigit((unsigned char)ch)) {
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				min = 10*min + char_to_int (ch);
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else if (ch == '*') {
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				min = va_arg (args, int);
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				state = DP_S_DOT;
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else {
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				state = DP_S_DOT;
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case DP_S_DOT:
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (ch == '.') {
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				state = DP_S_MAX;
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else {
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				state = DP_S_MOD;
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case DP_S_MAX:
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (isdigit((unsigned char)ch)) {
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (max < 0)
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					max = 0;
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				max = 10*max + char_to_int (ch);
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else if (ch == '*') {
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				max = va_arg (args, int);
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				state = DP_S_MOD;
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else {
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				state = DP_S_MOD;
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case DP_S_MOD:
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			switch (ch) {
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'h':
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				cflags = DP_C_SHORT;
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'l':
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				cflags = DP_C_LONG;
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (ch == 'l') {	/* It's a long long */
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					cflags = DP_C_LLONG;
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					ch = *format++;
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'L':
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				cflags = DP_C_LDOUBLE;
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			default:
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			state = DP_S_CONV;
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case DP_S_CONV:
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			switch (ch) {
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'd':
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'i':
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (cflags == DP_C_SHORT)
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = va_arg (args, int);
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else if (cflags == DP_C_LONG)
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = va_arg (args, long int);
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else if (cflags == DP_C_LLONG)
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = va_arg (args, LLONG);
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = va_arg (args, int);
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtint(buffer, &currlen, maxlen,
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    value, 10, min, max, flags) == -1)
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'o':
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_UNSIGNED;
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (cflags == DP_C_SHORT)
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = va_arg (args, unsigned int);
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else if (cflags == DP_C_LONG)
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (long)va_arg (args, unsigned long int);
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else if (cflags == DP_C_LLONG)
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (long)va_arg (args, unsigned LLONG);
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (long)va_arg (args, unsigned int);
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtint(buffer, &currlen, maxlen, value,
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    8, min, max, flags) == -1)
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'u':
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_UNSIGNED;
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (cflags == DP_C_SHORT)
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = va_arg (args, unsigned int);
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else if (cflags == DP_C_LONG)
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (long)va_arg (args, unsigned long int);
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else if (cflags == DP_C_LLONG)
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (LLONG)va_arg (args, unsigned LLONG);
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (long)va_arg (args, unsigned int);
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtint(buffer, &currlen, maxlen, value,
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    10, min, max, flags) == -1)
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'X':
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_UP;
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'x':
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_UNSIGNED;
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (cflags == DP_C_SHORT)
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = va_arg (args, unsigned int);
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else if (cflags == DP_C_LONG)
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (long)va_arg (args, unsigned long int);
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else if (cflags == DP_C_LLONG)
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (LLONG)va_arg (args, unsigned LLONG);
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					value = (long)va_arg (args, unsigned int);
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtint(buffer, &currlen, maxlen, value,
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    16, min, max, flags) == -1)
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'f':
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (cflags == DP_C_LDOUBLE)
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					fvalue = va_arg (args, LDOUBLE);
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					fvalue = va_arg (args, double);
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtfp(buffer, &currlen, maxlen, fvalue,
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    min, max, flags) == -1)
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'E':
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_UP;
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'e':
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (cflags == DP_C_LDOUBLE)
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					fvalue = va_arg (args, LDOUBLE);
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					fvalue = va_arg (args, double);
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtfp(buffer, &currlen, maxlen, fvalue,
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    min, max, flags) == -1)
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'G':
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				flags |= DP_F_UP;
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'g':
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (cflags == DP_C_LDOUBLE)
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					fvalue = va_arg (args, LDOUBLE);
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				else
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					fvalue = va_arg (args, double);
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtfp(buffer, &currlen, maxlen, fvalue,
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    min, max, flags) == -1)
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'c':
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				DOPR_OUTCH(buffer, currlen, maxlen,
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    va_arg (args, int));
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 's':
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				strvalue = va_arg (args, char *);
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (!strvalue) strvalue = "(NULL)";
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (max == -1) {
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					max = strlen(strvalue);
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (min > 0 && max >= 0 && min > max) max = min;
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtstr(buffer, &currlen, maxlen,
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    strvalue, flags, min, max) == -1)
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'p':
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				strvalue = va_arg (args, void *);
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (fmtint(buffer, &currlen, maxlen,
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    (long) strvalue, 16, min, max, flags) == -1)
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					return -1;
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'n':
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (cflags == DP_C_SHORT) {
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					short int *num;
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					num = va_arg (args, short int *);
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					*num = currlen;
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				} else if (cflags == DP_C_LONG) {
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					long int *num;
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					num = va_arg (args, long int *);
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					*num = (long int)currlen;
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				} else if (cflags == DP_C_LLONG) {
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					LLONG *num;
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					num = va_arg (args, LLONG *);
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					*num = (LLONG)currlen;
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				} else {
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					int *num;
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					num = va_arg (args, int *);
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					*num = currlen;
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case '%':
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				DOPR_OUTCH(buffer, currlen, maxlen, ch);
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			case 'w':
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* not supported yet, treat as next char */
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ch = *format++;
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			default:
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* Unknown, skip */
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ch = *format++;
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			state = DP_S_DEFAULT;
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			flags = cflags = min = 0;
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			max = -1;
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case DP_S_DONE:
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* hmm? */
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break; /* some picky compilers need this */
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (maxlen != 0) {
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (currlen < maxlen - 1)
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer[currlen] = '\0';
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else if (maxlen > 0)
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer[maxlen - 1] = '\0';
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return currlen < INT_MAX ? (int)currlen : -1;
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfmtstr(char *buffer, size_t *currlen, size_t maxlen,
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    char *value, int flags, int min, int max)
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int padlen, strln;     /* amount to pad */
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int cnt = 0;
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_SNPRINTF
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (value == 0) {
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		value = "<NULL>";
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	padlen = min - strln;
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (padlen < 0)
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		padlen = 0;
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (flags & DP_F_MINUS)
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		padlen = -padlen; /* Left Justify */
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((padlen > 0) && (cnt < max)) {
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		--padlen;
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		++cnt;
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (*value && (cnt < max)) {
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, *value);
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*value++;
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		++cnt;
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((padlen < 0) && (cnt < max)) {
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		++padlen;
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		++cnt;
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfmtint(char *buffer, size_t *currlen, size_t maxlen,
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    LLONG value, int base, int min, int max, int flags)
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int signvalue = 0;
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	unsigned LLONG uvalue;
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char convert[20];
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int place = 0;
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int spadlen = 0; /* amount to space pad */
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int zpadlen = 0; /* amount to zero pad */
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int caps = 0;
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (max < 0)
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		max = 0;
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	uvalue = value;
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if(!(flags & DP_F_UNSIGNED)) {
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if( value < 0 ) {
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			signvalue = '-';
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			uvalue = -value;
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				signvalue = '+';
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else if (flags & DP_F_SPACE)
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				signvalue = ' ';
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	do {
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		convert[place++] =
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			(caps? "0123456789ABCDEF":"0123456789abcdef")
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			[uvalue % (unsigned)base  ];
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		uvalue = (uvalue / (unsigned)base );
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} while(uvalue && (place < 20));
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (place == 20) place--;
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	convert[place] = 0;
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	zpadlen = max - place;
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (zpadlen < 0) zpadlen = 0;
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (spadlen < 0) spadlen = 0;
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (flags & DP_F_ZERO) {
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		zpadlen = MAX(zpadlen, spadlen);
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		spadlen = 0;
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (flags & DP_F_MINUS)
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		spadlen = -spadlen; /* Left Justifty */
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_SNPRINTF
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	       zpadlen, spadlen, min, max, place);
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Spaces */
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (spadlen > 0) {
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		--spadlen;
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Sign */
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (signvalue)
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Zeros */
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (zpadlen > 0) {
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		while (zpadlen > 0) {
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			DOPR_OUTCH(buffer, *currlen, maxlen, '0');
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			--zpadlen;
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Digits */
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (place > 0) {
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		--place;
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, convert[place]);
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Left Justified spaces */
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (spadlen < 0) {
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		++spadlen;
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic LDOUBLE abs_val(LDOUBLE value)
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	LDOUBLE result = value;
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (value < 0)
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		result = -value;
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return result;
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic LDOUBLE POW10(int val)
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	LDOUBLE result = 1;
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (val) {
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		result *= 10;
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		val--;
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return result;
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic LLONG ROUND(LDOUBLE value)
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	LLONG intpart;
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	intpart = (LLONG)value;
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	value = value - intpart;
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (value >= 0.5) intpart++;
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return intpart;
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* a replacement for modf that doesn't need the math library. Should
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood   be portable, but slow */
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic double my_modf(double x0, double *iptr)
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	long l;
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	double x = x0;
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	double f = 1.0;
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i=0;i<100;i++) {
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		l = (long)x;
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (l <= (x+1) && l >= (x-1)) break;
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		x *= 0.1;
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		f *= 10.0;
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (i == 100) {
6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * yikes! the number is beyond what we can handle.
6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * What do we do?
6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(*iptr) = 0;
6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (i != 0) {
6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		double i2;
6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		double ret;
6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ret = my_modf(x0-l*f, &i2);
6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(*iptr) = l*f + i2;
6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return ret;
6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	(*iptr) = l;
6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return x - (*iptr);
6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfmtfp (char *buffer, size_t *currlen, size_t maxlen,
6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    LDOUBLE fvalue, int min, int max, int flags)
6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int signvalue = 0;
6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	double ufvalue;
6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char iconvert[311];
6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char fconvert[311];
6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int iplace = 0;
6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int fplace = 0;
6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int padlen = 0; /* amount to pad */
6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int zpadlen = 0;
6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int caps = 0;
6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int idx;
6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	double intpart;
6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	double fracpart;
6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	double temp;
6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * AIX manpage says the default is 0, but Solaris says the default
6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * is 6, and sprintf on AIX defaults to 6
6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (max < 0)
6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		max = 6;
6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ufvalue = abs_val (fvalue);
6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fvalue < 0) {
7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		signvalue = '-';
7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			signvalue = '+';
7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (flags & DP_F_SPACE)
7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				signvalue = ' ';
7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if 0
7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if 0
7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Sorry, we only support 16 digits past the decimal because of our
7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * conversion method
7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (max > 16)
7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		max = 16;
7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* We "cheat" by converting the fractional part to integer by
7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * multiplying by a factor of 10
7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	temp = ufvalue;
7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	my_modf(temp, &intpart);
7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fracpart >= POW10(max)) {
7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		intpart++;
7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fracpart -= POW10(max);
7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Convert integer part */
7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	do {
7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		temp = intpart*0.1;
7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		my_modf(temp, &intpart);
7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		idx = (int) ((temp -intpart +0.05)* 10.0);
7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* printf ("%llf, %f, %x\n", temp, intpart, idx); */
7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		iconvert[iplace++] =
7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} while (intpart && (iplace < 311));
7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (iplace == 311) iplace--;
7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	iconvert[iplace] = 0;
7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Convert fractional part */
7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fracpart)
7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{
7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		do {
7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			temp = fracpart*0.1;
7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			my_modf(temp, &fracpart);
7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			idx = (int) ((temp -fracpart +0.05)* 10.0);
7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fconvert[fplace++] =
7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} while(fracpart && (fplace < 311));
7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (fplace == 311) fplace--;
7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fconvert[fplace] = 0;
7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* -1 for decimal point, another -1 if we are printing a sign */
7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	zpadlen = max - fplace;
7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (zpadlen < 0) zpadlen = 0;
7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (padlen < 0)
7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		padlen = 0;
7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (flags & DP_F_MINUS)
7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		padlen = -padlen; /* Left Justifty */
7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((flags & DP_F_ZERO) && (padlen > 0)) {
7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (signvalue) {
7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			--padlen;
7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			signvalue = 0;
7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		while (padlen > 0) {
7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			DOPR_OUTCH(buffer, *currlen, maxlen, '0');
7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			--padlen;
7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (padlen > 0) {
7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		--padlen;
7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (signvalue)
7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (iplace > 0) {
7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		--iplace;
7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, iconvert[iplace]);
7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_SNPRINTF
8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Decimal point.  This should probably use locale to find the correct
8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * char to print out.
8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (max > 0) {
8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, '.');
8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		while (zpadlen > 0) {
8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			DOPR_OUTCH(buffer, *currlen, maxlen, '0');
8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			--zpadlen;
8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		while (fplace > 0) {
8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			--fplace;
8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			DOPR_OUTCH(buffer, *currlen, maxlen, fconvert[fplace]);
8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (padlen < 0) {
8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		++padlen;
8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if !defined(HAVE_VSNPRINTF)
8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvsnprintf (char *str, size_t count, const char *fmt, va_list args)
8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return dopr(str, count, fmt, args);
8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if !defined(HAVE_SNPRINTF)
8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsnprintf(char *str, size_t count, SNPRINTF_CONST char *fmt, ...)
8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t ret;
8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_list ap;
8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_start(ap, fmt);
8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = vsnprintf(str, count, fmt, ap);
8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	va_end(ap);
8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
851