From 3fd3d028fb907b80d59b5635d83e82071c0fdd8a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 6 Feb 1999 21:51:03 +0000 Subject: [PATCH] Add floating-point support to our emulation of snprintf so that EXPLAIN works again. --- src/backend/port/snprintf.c | 146 ++++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 64 deletions(-) diff --git a/src/backend/port/snprintf.c b/src/backend/port/snprintf.c index 7c7a9105a3..1a9f87a7cc 100644 --- a/src/backend/port/snprintf.c +++ b/src/backend/port/snprintf.c @@ -40,15 +40,22 @@ #include "regex/cdefs.h" +#include #include #include #include -/* IRIX doesn't do 'long long' in va_arg(), so use a typedef */ +/* + * We do all internal arithmetic in the widest available integer type, + * here called long_long (or ulong_long for unsigned). + */ #ifdef HAVE_LONG_LONG_INT_64 -typedef long long long_long; -typedef unsigned long long ulong_long; +typedef long long long_long; +typedef unsigned long long ulong_long; +#else +typedef long long_long; +typedef unsigned long ulong_long; #endif /* @@ -64,7 +71,7 @@ typedef unsigned long long ulong_long; * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that - * the version here does not include floating point... + * the version here does not include floating point. (now it does ... tgl) * * snprintf() is used instead of sprintf() as it does limit checks * for string length. This covers a nasty loophole. @@ -73,7 +80,7 @@ typedef unsigned long long ulong_long; * causing nast effects. **************************************************************/ -/*static char _id[] = "$Id: snprintf.c,v 1.19 1999/02/03 21:17:00 momjian Exp $";*/ +/*static char _id[] = "$Id: snprintf.c,v 1.20 1999/02/06 21:51:03 tgl Exp $";*/ static char *end; static int SnprfOverflow; @@ -113,28 +120,22 @@ vsnprintf(char *str, size_t count, const char *fmt, va_list args) * dopr(): poor man's version of doprintf */ -static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth)); - -#ifndef HAVE_LONG_LONG_INT_64 -static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad)); -#else -static void fmtnum __P((long_long value, int base, int dosign, int ljust, int len, int zpad)); -#endif +static void fmtstr (char *value, int ljust, int len, int zpad, int maxwidth); +static void fmtnum (long_long value, int base, int dosign, int ljust, int len, int zpad); +static void fmtfloat (double value, char type, int ljust, int len, int precision, int pointflag); +static void dostr (char *str, int cut); +static void dopr_outch (int c); -static void dostr __P((char *, int)); static char *output; -static void dopr_outch __P((int c)); + static void dopr(char *buffer, const char *format, va_list args) { int ch; -#ifdef HAVE_LONG_LONG_INT_64 long_long value; + double fvalue; int longlongflag = 0; -#else - long value; -#endif int longflag = 0; int pointflag = 0; int maxwidth = 0; @@ -150,10 +151,7 @@ dopr(char *buffer, const char *format, va_list args) { case '%': ljust = len = zpad = maxwidth = 0; - longflag = pointflag = 0; -#ifdef HAVE_LONG_LONG_INT_64 - longlongflag = 0; -#endif + longflag = longlongflag = pointflag = 0; nextch: ch = *format++; switch (ch) @@ -191,11 +189,9 @@ dopr(char *buffer, const char *format, va_list args) pointflag = 1; goto nextch; case 'l': -#ifdef HAVE_LONG_LONG_INT_64 if (longflag) longlongflag = 1; else -#endif longflag = 1; goto nextch; case 'u': @@ -203,11 +199,9 @@ dopr(char *buffer, const char *format, va_list args) /* fmtnum(value,base,dosign,ljust,len,zpad) */ if (longflag) { -#ifdef HAVE_LONG_LONG_INT_64 if (longlongflag) value = va_arg(args, long_long); else -#endif value = va_arg(args, long); } else @@ -219,12 +213,10 @@ dopr(char *buffer, const char *format, va_list args) /* fmtnum(value,base,dosign,ljust,len,zpad) */ if (longflag) { -#ifdef HAVE_LONG_LONG_INT_64 if (longlongflag) value = va_arg(args, long_long); else -#endif - value = va_arg(args, long); + value = va_arg(args, long); } else value = va_arg(args, int); @@ -234,11 +226,9 @@ dopr(char *buffer, const char *format, va_list args) case 'D': if (longflag) { -#ifdef HAVE_LONG_LONG_INT_64 if (longlongflag) value = va_arg(args, long_long); else -#endif value = va_arg(args, long); } else @@ -249,12 +239,10 @@ dopr(char *buffer, const char *format, va_list args) case 'x': if (longflag) { -#ifdef HAVE_LONG_LONG_INT_64 if (longlongflag) value = va_arg(args, long_long); else -#endif - value = va_arg(args, long); + value = va_arg(args, long); } else value = va_arg(args, int); @@ -263,11 +251,9 @@ dopr(char *buffer, const char *format, va_list args) case 'X': if (longflag) { -#ifdef HAVE_LONG_LONG_INT_64 if (longlongflag) value = va_arg(args, long_long); else -#endif value = va_arg(args, long); } else @@ -287,6 +273,14 @@ dopr(char *buffer, const char *format, va_list args) ch = va_arg(args, int); dopr_outch(ch); break; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + fvalue = va_arg(args, double); + fmtfloat(fvalue, ch, ljust, len, maxwidth, pointflag); + break; case '%': dopr_outch(ch); continue; @@ -303,12 +297,7 @@ dopr(char *buffer, const char *format, va_list args) } static void -fmtstr(value, ljust, len, zpad, maxwidth) -char *value; -int ljust, - len, - zpad, - maxwidth; +fmtstr(char *value, int ljust, int len, int zpad, int maxwidth) { int padlen, strlen; /* amount to pad */ @@ -337,25 +326,11 @@ int ljust, } static void -fmtnum(value, base, dosign, ljust, len, zpad) -#ifdef HAVE_LONG_LONG_INT_64 - long_long value; -#else - long value; -#endif -int base, - dosign, - ljust, - len, - zpad; +fmtnum(long_long value, int base, int dosign, int ljust, int len, int zpad) { int signvalue = 0; -#ifdef HAVE_LONG_LONG_INT_64 - ulong_long uvalue; -#else - unsigned long uvalue; -#endif - char convert[20]; + ulong_long uvalue; + char convert[64]; int place = 0; int padlen = 0; /* amount to pad */ int caps = 0; @@ -385,6 +360,13 @@ int base, uvalue = (uvalue / (unsigned) base); } while (uvalue); convert[place] = 0; + + if (len < 0) + { + /* this could happen with a "*" width spec */ + ljust = 1; + len = -len; + } padlen = len - place; if (padlen < 0) padlen = 0; @@ -426,9 +408,46 @@ int base, } static void -dostr(str, cut) -char *str; -int cut; +fmtfloat (double value, char type, int ljust, int len, int precision, int pointflag) +{ + char fmt[32]; + char convert[512]; + int padlen = 0; /* amount to pad */ + + /* we rely on regular C library's sprintf to do the basic conversion */ + if (pointflag) + sprintf(fmt, "%%.%d%c", precision, type); + else + sprintf(fmt, "%%%c", type); + sprintf(convert, fmt, value); + + if (len < 0) + { + /* this could happen with a "*" width spec */ + ljust = 1; + len = -len; + } + padlen = len - strlen(convert); + if (padlen < 0) + padlen = 0; + if (ljust) + padlen = -padlen; + + while (padlen > 0) + { + dopr_outch(' '); + --padlen; + } + dostr(convert, 0); + while (padlen < 0) + { + dopr_outch(' '); + ++padlen; + } +} + +static void +dostr(char *str, int cut) { if (cut) { @@ -443,8 +462,7 @@ int cut; } static void -dopr_outch(c) -int c; +dopr_outch(int c) { #if 0 if (iscntrl(c) && c != '\n' && c != '\t') -- 2.40.0