Add floating-point support to our emulation of snprintf

so that EXPLAIN works again.
This commit is contained in:
Tom Lane 1999-02-06 21:51:03 +00:00
parent fd1afb7453
commit 3fd3d028fb
1 changed files with 82 additions and 64 deletions

View File

@ -40,15 +40,22 @@
#include "regex/cdefs.h"
#include <stdio.h>
#include <stdarg.h>
#include <sys/ioctl.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
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));
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);
#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 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')