Skip to content

Commit 3fd3d02

Browse files
committed
Add floating-point support to our emulation of snprintf
so that EXPLAIN works again.
1 parent fd1afb7 commit 3fd3d02

File tree

1 file changed

+82
-64
lines changed

1 file changed

+82
-64
lines changed

src/backend/port/snprintf.c

Lines changed: 82 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,22 @@
4040

4141
#include "regex/cdefs.h"
4242

43+
#include <stdio.h>
4344
#include <stdarg.h>
4445

4546
#include <sys/ioctl.h>
4647
#include <sys/param.h>
4748

48-
/* IRIX doesn't do 'long long' in va_arg(), so use a typedef */
49+
/*
50+
* We do all internal arithmetic in the widest available integer type,
51+
* here called long_long (or ulong_long for unsigned).
52+
*/
4953
#ifdef HAVE_LONG_LONG_INT_64
50-
typedef long long long_long;
51-
typedef unsigned long long ulong_long;
54+
typedef long long long_long;
55+
typedef unsigned long long ulong_long;
56+
#else
57+
typedef long long_long;
58+
typedef unsigned long ulong_long;
5259
#endif
5360

5461
/*
@@ -64,7 +71,7 @@ typedef unsigned long long ulong_long;
6471
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
6572
* A bombproof version of doprnt (dopr) included.
6673
* Sigh. This sort of thing is always nasty do deal with. Note that
67-
* the version here does not include floating point...
74+
* the version here does not include floating point. (now it does ... tgl)
6875
*
6976
* snprintf() is used instead of sprintf() as it does limit checks
7077
* for string length. This covers a nasty loophole.
@@ -73,7 +80,7 @@ typedef unsigned long long ulong_long;
7380
* causing nast effects.
7481
**************************************************************/
7582

76-
/*static char _id[] = "$Id: snprintf.c,v 1.19 1999/02/03 21:17:00 momjian Exp $";*/
83+
/*static char _id[] = "$Id: snprintf.c,v 1.20 1999/02/06 21:51:03 tgl Exp $";*/
7784
static char *end;
7885
static int SnprfOverflow;
7986

@@ -113,28 +120,22 @@ vsnprintf(char *str, size_t count, const char *fmt, va_list args)
113120
* dopr(): poor man's version of doprintf
114121
*/
115122

116-
static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
117-
118-
#ifndef HAVE_LONG_LONG_INT_64
119-
static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
120-
#else
121-
static void fmtnum __P((long_long value, int base, int dosign, int ljust, int len, int zpad));
122-
#endif
123+
static void fmtstr (char *value, int ljust, int len, int zpad, int maxwidth);
124+
static void fmtnum (long_long value, int base, int dosign, int ljust, int len, int zpad);
125+
static void fmtfloat (double value, char type, int ljust, int len, int precision, int pointflag);
126+
static void dostr (char *str, int cut);
127+
static void dopr_outch (int c);
123128

124-
static void dostr __P((char *, int));
125129
static char *output;
126-
static void dopr_outch __P((int c));
130+
127131

128132
static void
129133
dopr(char *buffer, const char *format, va_list args)
130134
{
131135
int ch;
132-
#ifdef HAVE_LONG_LONG_INT_64
133136
long_long value;
137+
double fvalue;
134138
int longlongflag = 0;
135-
#else
136-
long value;
137-
#endif
138139
int longflag = 0;
139140
int pointflag = 0;
140141
int maxwidth = 0;
@@ -150,10 +151,7 @@ dopr(char *buffer, const char *format, va_list args)
150151
{
151152
case '%':
152153
ljust = len = zpad = maxwidth = 0;
153-
longflag = pointflag = 0;
154-
#ifdef HAVE_LONG_LONG_INT_64
155-
longlongflag = 0;
156-
#endif
154+
longflag = longlongflag = pointflag = 0;
157155
nextch:
158156
ch = *format++;
159157
switch (ch)
@@ -191,23 +189,19 @@ dopr(char *buffer, const char *format, va_list args)
191189
pointflag = 1;
192190
goto nextch;
193191
case 'l':
194-
#ifdef HAVE_LONG_LONG_INT_64
195192
if (longflag)
196193
longlongflag = 1;
197194
else
198-
#endif
199195
longflag = 1;
200196
goto nextch;
201197
case 'u':
202198
case 'U':
203199
/* fmtnum(value,base,dosign,ljust,len,zpad) */
204200
if (longflag)
205201
{
206-
#ifdef HAVE_LONG_LONG_INT_64
207202
if (longlongflag)
208203
value = va_arg(args, long_long);
209204
else
210-
#endif
211205
value = va_arg(args, long);
212206
}
213207
else
@@ -219,12 +213,10 @@ dopr(char *buffer, const char *format, va_list args)
219213
/* fmtnum(value,base,dosign,ljust,len,zpad) */
220214
if (longflag)
221215
{
222-
#ifdef HAVE_LONG_LONG_INT_64
223216
if (longlongflag)
224217
value = va_arg(args, long_long);
225218
else
226-
#endif
227-
value = va_arg(args, long);
219+
value = va_arg(args, long);
228220
}
229221
else
230222
value = va_arg(args, int);
@@ -234,11 +226,9 @@ dopr(char *buffer, const char *format, va_list args)
234226
case 'D':
235227
if (longflag)
236228
{
237-
#ifdef HAVE_LONG_LONG_INT_64
238229
if (longlongflag)
239230
value = va_arg(args, long_long);
240231
else
241-
#endif
242232
value = va_arg(args, long);
243233
}
244234
else
@@ -249,12 +239,10 @@ dopr(char *buffer, const char *format, va_list args)
249239
case 'x':
250240
if (longflag)
251241
{
252-
#ifdef HAVE_LONG_LONG_INT_64
253242
if (longlongflag)
254243
value = va_arg(args, long_long);
255244
else
256-
#endif
257-
value = va_arg(args, long);
245+
value = va_arg(args, long);
258246
}
259247
else
260248
value = va_arg(args, int);
@@ -263,11 +251,9 @@ dopr(char *buffer, const char *format, va_list args)
263251
case 'X':
264252
if (longflag)
265253
{
266-
#ifdef HAVE_LONG_LONG_INT_64
267254
if (longlongflag)
268255
value = va_arg(args, long_long);
269256
else
270-
#endif
271257
value = va_arg(args, long);
272258
}
273259
else
@@ -287,6 +273,14 @@ dopr(char *buffer, const char *format, va_list args)
287273
ch = va_arg(args, int);
288274
dopr_outch(ch);
289275
break;
276+
case 'e':
277+
case 'E':
278+
case 'f':
279+
case 'g':
280+
case 'G':
281+
fvalue = va_arg(args, double);
282+
fmtfloat(fvalue, ch, ljust, len, maxwidth, pointflag);
283+
break;
290284
case '%':
291285
dopr_outch(ch);
292286
continue;
@@ -303,12 +297,7 @@ dopr(char *buffer, const char *format, va_list args)
303297
}
304298

305299
static void
306-
fmtstr(value, ljust, len, zpad, maxwidth)
307-
char *value;
308-
int ljust,
309-
len,
310-
zpad,
311-
maxwidth;
300+
fmtstr(char *value, int ljust, int len, int zpad, int maxwidth)
312301
{
313302
int padlen,
314303
strlen; /* amount to pad */
@@ -337,25 +326,11 @@ int ljust,
337326
}
338327

339328
static void
340-
fmtnum(value, base, dosign, ljust, len, zpad)
341-
#ifdef HAVE_LONG_LONG_INT_64
342-
long_long value;
343-
#else
344-
long value;
345-
#endif
346-
int base,
347-
dosign,
348-
ljust,
349-
len,
350-
zpad;
329+
fmtnum(long_long value, int base, int dosign, int ljust, int len, int zpad)
351330
{
352331
int signvalue = 0;
353-
#ifdef HAVE_LONG_LONG_INT_64
354-
ulong_long uvalue;
355-
#else
356-
unsigned long uvalue;
357-
#endif
358-
char convert[20];
332+
ulong_long uvalue;
333+
char convert[64];
359334
int place = 0;
360335
int padlen = 0; /* amount to pad */
361336
int caps = 0;
@@ -385,6 +360,13 @@ int base,
385360
uvalue = (uvalue / (unsigned) base);
386361
} while (uvalue);
387362
convert[place] = 0;
363+
364+
if (len < 0)
365+
{
366+
/* this could happen with a "*" width spec */
367+
ljust = 1;
368+
len = -len;
369+
}
388370
padlen = len - place;
389371
if (padlen < 0)
390372
padlen = 0;
@@ -426,9 +408,46 @@ int base,
426408
}
427409

428410
static void
429-
dostr(str, cut)
430-
char *str;
431-
int cut;
411+
fmtfloat (double value, char type, int ljust, int len, int precision, int pointflag)
412+
{
413+
char fmt[32];
414+
char convert[512];
415+
int padlen = 0; /* amount to pad */
416+
417+
/* we rely on regular C library's sprintf to do the basic conversion */
418+
if (pointflag)
419+
sprintf(fmt, "%%.%d%c", precision, type);
420+
else
421+
sprintf(fmt, "%%%c", type);
422+
sprintf(convert, fmt, value);
423+
424+
if (len < 0)
425+
{
426+
/* this could happen with a "*" width spec */
427+
ljust = 1;
428+
len = -len;
429+
}
430+
padlen = len - strlen(convert);
431+
if (padlen < 0)
432+
padlen = 0;
433+
if (ljust)
434+
padlen = -padlen;
435+
436+
while (padlen > 0)
437+
{
438+
dopr_outch(' ');
439+
--padlen;
440+
}
441+
dostr(convert, 0);
442+
while (padlen < 0)
443+
{
444+
dopr_outch(' ');
445+
++padlen;
446+
}
447+
}
448+
449+
static void
450+
dostr(char *str, int cut)
432451
{
433452
if (cut)
434453
{
@@ -443,8 +462,7 @@ int cut;
443462
}
444463

445464
static void
446-
dopr_outch(c)
447-
int c;
465+
dopr_outch(int c)
448466
{
449467
#if 0
450468
if (iscntrl(c) && c != '\n' && c != '\t')

0 commit comments

Comments
 (0)