Add floating-point support to our emulation of snprintf
so that EXPLAIN works again.
This commit is contained in:
parent
fd1afb7453
commit
3fd3d028fb
@ -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;
|
|||||||
* 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;
|
|||||||
* 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)
|
|||||||
* 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);
|
||||||
|
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 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
/* 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,11 +213,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
|
||||||
@ -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,11 +239,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
|
||||||
@ -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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
#else
|
char convert[64];
|
||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|||||||
}
|
}
|
||||||
|
|
||||||
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')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user