Commit 3fd3d028 authored by Tom Lane's avatar Tom Lane

Add floating-point support to our emulation of snprintf

so that EXPLAIN works again.
parent fd1afb74
...@@ -40,15 +40,22 @@ ...@@ -40,15 +40,22 @@
#include "regex/cdefs.h" #include "regex/cdefs.h"
#include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/param.h> #include <sys/param.h>
/* 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 #ifdef HAVE_LONG_LONG_INT_64
typedef long long long_long; typedef long long long_long;
typedef unsigned long long ulong_long; typedef unsigned long long ulong_long;
#else
typedef long long_long;
typedef unsigned long ulong_long;
#endif #endif
/* /*
...@@ -64,7 +71,7 @@ typedef unsigned long long ulong_long; ...@@ -64,7 +71,7 @@ typedef unsigned long long ulong_long;
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included. * A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that * 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 * snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole. * for string length. This covers a nasty loophole.
...@@ -73,7 +80,7 @@ typedef unsigned long long ulong_long; ...@@ -73,7 +80,7 @@ typedef unsigned long long ulong_long;
* causing nast effects. * 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 char *end;
static int SnprfOverflow; static int SnprfOverflow;
...@@ -113,28 +120,22 @@ vsnprintf(char *str, size_t count, const char *fmt, va_list args) ...@@ -113,28 +120,22 @@ vsnprintf(char *str, size_t count, const char *fmt, va_list args)
* dopr(): poor man's version of doprintf * dopr(): poor man's version of doprintf
*/ */
static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth)); 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);
#ifndef HAVE_LONG_LONG_INT_64 static void fmtfloat (double value, char type, int ljust, int len, int precision, int pointflag);
static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad)); static void dostr (char *str, int cut);
#else static void dopr_outch (int c);
static void fmtnum __P((long_long value, int base, int dosign, int ljust, int len, int zpad));
#endif
static void dostr __P((char *, int));
static char *output; static char *output;
static void dopr_outch __P((int c));
static void static void
dopr(char *buffer, const char *format, va_list args) dopr(char *buffer, const char *format, va_list args)
{ {
int ch; int ch;
#ifdef HAVE_LONG_LONG_INT_64
long_long value; long_long value;
double fvalue;
int longlongflag = 0; int longlongflag = 0;
#else
long value;
#endif
int longflag = 0; int longflag = 0;
int pointflag = 0; int pointflag = 0;
int maxwidth = 0; int maxwidth = 0;
...@@ -150,10 +151,7 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -150,10 +151,7 @@ dopr(char *buffer, const char *format, va_list args)
{ {
case '%': case '%':
ljust = len = zpad = maxwidth = 0; ljust = len = zpad = maxwidth = 0;
longflag = pointflag = 0; longflag = longlongflag = pointflag = 0;
#ifdef HAVE_LONG_LONG_INT_64
longlongflag = 0;
#endif
nextch: nextch:
ch = *format++; ch = *format++;
switch (ch) switch (ch)
...@@ -191,11 +189,9 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -191,11 +189,9 @@ dopr(char *buffer, const char *format, va_list args)
pointflag = 1; pointflag = 1;
goto nextch; goto nextch;
case 'l': case 'l':
#ifdef HAVE_LONG_LONG_INT_64
if (longflag) if (longflag)
longlongflag = 1; longlongflag = 1;
else else
#endif
longflag = 1; longflag = 1;
goto nextch; goto nextch;
case 'u': case 'u':
...@@ -203,11 +199,9 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -203,11 +199,9 @@ dopr(char *buffer, const char *format, va_list args)
/* fmtnum(value,base,dosign,ljust,len,zpad) */ /* fmtnum(value,base,dosign,ljust,len,zpad) */
if (longflag) if (longflag)
{ {
#ifdef HAVE_LONG_LONG_INT_64
if (longlongflag) if (longlongflag)
value = va_arg(args, long_long); value = va_arg(args, long_long);
else else
#endif
value = va_arg(args, long); value = va_arg(args, long);
} }
else else
...@@ -219,12 +213,10 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -219,12 +213,10 @@ dopr(char *buffer, const char *format, va_list args)
/* fmtnum(value,base,dosign,ljust,len,zpad) */ /* fmtnum(value,base,dosign,ljust,len,zpad) */
if (longflag) if (longflag)
{ {
#ifdef HAVE_LONG_LONG_INT_64
if (longlongflag) if (longlongflag)
value = va_arg(args, long_long); value = va_arg(args, long_long);
else else
#endif value = va_arg(args, long);
value = va_arg(args, long);
} }
else else
value = va_arg(args, int); value = va_arg(args, int);
...@@ -234,11 +226,9 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -234,11 +226,9 @@ dopr(char *buffer, const char *format, va_list args)
case 'D': case 'D':
if (longflag) if (longflag)
{ {
#ifdef HAVE_LONG_LONG_INT_64
if (longlongflag) if (longlongflag)
value = va_arg(args, long_long); value = va_arg(args, long_long);
else else
#endif
value = va_arg(args, long); value = va_arg(args, long);
} }
else else
...@@ -249,12 +239,10 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -249,12 +239,10 @@ dopr(char *buffer, const char *format, va_list args)
case 'x': case 'x':
if (longflag) if (longflag)
{ {
#ifdef HAVE_LONG_LONG_INT_64
if (longlongflag) if (longlongflag)
value = va_arg(args, long_long); value = va_arg(args, long_long);
else else
#endif value = va_arg(args, long);
value = va_arg(args, long);
} }
else else
value = va_arg(args, int); value = va_arg(args, int);
...@@ -263,11 +251,9 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -263,11 +251,9 @@ dopr(char *buffer, const char *format, va_list args)
case 'X': case 'X':
if (longflag) if (longflag)
{ {
#ifdef HAVE_LONG_LONG_INT_64
if (longlongflag) if (longlongflag)
value = va_arg(args, long_long); value = va_arg(args, long_long);
else else
#endif
value = va_arg(args, long); value = va_arg(args, long);
} }
else else
...@@ -287,6 +273,14 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -287,6 +273,14 @@ dopr(char *buffer, const char *format, va_list args)
ch = va_arg(args, int); ch = va_arg(args, int);
dopr_outch(ch); dopr_outch(ch);
break; 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 '%': case '%':
dopr_outch(ch); dopr_outch(ch);
continue; continue;
...@@ -303,12 +297,7 @@ dopr(char *buffer, const char *format, va_list args) ...@@ -303,12 +297,7 @@ dopr(char *buffer, const char *format, va_list args)
} }
static void static void
fmtstr(value, ljust, len, zpad, maxwidth) fmtstr(char *value, int ljust, int len, int zpad, int maxwidth)
char *value;
int ljust,
len,
zpad,
maxwidth;
{ {
int padlen, int padlen,
strlen; /* amount to pad */ strlen; /* amount to pad */
...@@ -337,25 +326,11 @@ int ljust, ...@@ -337,25 +326,11 @@ int ljust,
} }
static void static void
fmtnum(value, base, dosign, ljust, len, zpad) fmtnum(long_long value, int base, int dosign, int ljust, int len, int zpad)
#ifdef HAVE_LONG_LONG_INT_64
long_long value;
#else
long value;
#endif
int base,
dosign,
ljust,
len,
zpad;
{ {
int signvalue = 0; int signvalue = 0;
#ifdef HAVE_LONG_LONG_INT_64 ulong_long uvalue;
ulong_long uvalue; char convert[64];
#else
unsigned long uvalue;
#endif
char convert[20];
int place = 0; int place = 0;
int padlen = 0; /* amount to pad */ int padlen = 0; /* amount to pad */
int caps = 0; int caps = 0;
...@@ -385,6 +360,13 @@ int base, ...@@ -385,6 +360,13 @@ int base,
uvalue = (uvalue / (unsigned) base); uvalue = (uvalue / (unsigned) base);
} while (uvalue); } while (uvalue);
convert[place] = 0; convert[place] = 0;
if (len < 0)
{
/* this could happen with a "*" width spec */
ljust = 1;
len = -len;
}
padlen = len - place; padlen = len - place;
if (padlen < 0) if (padlen < 0)
padlen = 0; padlen = 0;
...@@ -426,9 +408,46 @@ int base, ...@@ -426,9 +408,46 @@ int base,
} }
static void static void
dostr(str, cut) fmtfloat (double value, char type, int ljust, int len, int precision, int pointflag)
char *str; {
int cut; 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) if (cut)
{ {
...@@ -443,8 +462,7 @@ int cut; ...@@ -443,8 +462,7 @@ int cut;
} }
static void static void
dopr_outch(c) dopr_outch(int c)
int c;
{ {
#if 0 #if 0
if (iscntrl(c) && c != '\n' && c != '\t') if (iscntrl(c) && c != '\n' && c != '\t')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment