Commit 7111a14f authored by Bruce Momjian's avatar Bruce Momjian

Factor duplicate snprintf code into functions.

parent 957f51ea
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
* causing nasty effects. * causing nasty effects.
**************************************************************/ **************************************************************/
/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.23 2005/03/16 21:27:23 momjian Exp $";*/ /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.24 2005/03/17 03:18:14 momjian Exp $";*/
static void dopr(char *buffer, const char *format, va_list args, char *end); static void dopr(char *buffer, const char *format, va_list args, char *end);
...@@ -149,16 +149,18 @@ pg_printf(const char *fmt,...) ...@@ -149,16 +149,18 @@ pg_printf(const char *fmt,...)
return len; return len;
} }
/* static int adjust_sign(int is_negative, int forcesign, int *signvalue);
* dopr(): poor man's version of doprintf static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen);
*/ static void leading_pad(int zpad, int *signvalue, int *padlen, char *end,
char **output);
static void trailing_pad(int *padlen, char *end, char **output);
static void fmtstr(char *value, int ljust, int len, int maxwidth, static void fmtstr(char *value, int leftjust, int minlen, int maxwidth,
char *end, char **output); char *end, char **output);
static void fmtnum(int64 value, int base, int dosign, int forcesign, static void fmtint(int64 value, int base, int dosign, int forcesign,
int ljust, int len, int zpad, char *end, char **output); int leftjust, int minlen, int zpad, char *end, char **output);
static void fmtfloat(double value, char type, int forcesign, static void fmtfloat(double value, char type, int forcesign,
int ljust, int len, int zpad, int precision, int pointflag, char *end, int leftjust, int minlen, int zpad, int precision, int pointflag, char *end,
char **output); char **output);
static void dostr(char *str, int cut, char *end, char **output); static void dostr(char *str, int cut, char *end, char **output);
static void dopr_outch(int c, char *end, char **output); static void dopr_outch(int c, char *end, char **output);
...@@ -171,6 +173,10 @@ static void dopr_outch(int c, char *end, char **output); ...@@ -171,6 +173,10 @@ static void dopr_outch(int c, char *end, char **output);
#define FMTWIDTH 6 #define FMTWIDTH 6
#define FMTLEN 7 #define FMTLEN 7
/*
* dopr(): poor man's version of doprintf
*/
static void static void
dopr(char *buffer, const char *format, va_list args, char *end) dopr(char *buffer, const char *format, va_list args, char *end)
{ {
...@@ -179,8 +185,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -179,8 +185,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
int longflag; int longflag;
int pointflag; int pointflag;
int maxwidth; int maxwidth;
int ljust; int leftjust;
int len; int minlen;
int zpad; int zpad;
int forcesign; int forcesign;
int i; int i;
...@@ -201,8 +207,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -201,8 +207,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
int64 numvalue; int64 numvalue;
double fvalue; double fvalue;
int charvalue; int charvalue;
int ljust; int leftjust;
int len; int minlen;
int zpad; int zpad;
int maxwidth; int maxwidth;
int base; int base;
...@@ -245,7 +251,7 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -245,7 +251,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
switch (ch) switch (ch)
{ {
case '%': case '%':
ljust = len = zpad = forcesign = maxwidth = 0; leftjust = minlen = zpad = forcesign = maxwidth = 0;
longflag = longlongflag = pointflag = 0; longflag = longlongflag = pointflag = 0;
fmtbegin = format - 1; fmtbegin = format - 1;
realpos = 0; realpos = 0;
...@@ -257,13 +263,13 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -257,13 +263,13 @@ dopr(char *buffer, const char *format, va_list args, char *end)
case '\0': case '\0':
goto performpr; goto performpr;
case '-': case '-':
ljust = 1; leftjust = 1;
goto nextch; goto nextch;
case '+': case '+':
forcesign = 1; forcesign = 1;
goto nextch; goto nextch;
case '0': /* set zero padding if len not set */ case '0': /* set zero padding if minlen not set */
if (len == 0 && !pointflag) if (minlen == 0 && !pointflag)
zpad = '0'; zpad = '0';
case '1': case '1':
case '2': case '2':
...@@ -276,7 +282,7 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -276,7 +282,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
case '9': case '9':
if (!pointflag) if (!pointflag)
{ {
len = len * 10 + ch - '0'; minlen = minlen * 10 + ch - '0';
position = position * 10 + ch - '0'; position = position * 10 + ch - '0';
} }
else else
...@@ -287,7 +293,7 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -287,7 +293,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
goto nextch; goto nextch;
case '$': case '$':
realpos = position; realpos = position;
len = 0; minlen = 0;
goto nextch; goto nextch;
case '*': case '*':
MemSet(&fmtpar[fmtpos], 0, sizeof(fmtpar[fmtpos])); MemSet(&fmtpar[fmtpos], 0, sizeof(fmtpar[fmtpos]));
...@@ -340,8 +346,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -340,8 +346,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
fmtpar[fmtpos].base = 10; fmtpar[fmtpos].base = 10;
fmtpar[fmtpos].dosign = 0; fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].forcesign = forcesign;
fmtpar[fmtpos].ljust = ljust; fmtpar[fmtpos].leftjust = leftjust;
fmtpar[fmtpos].len = len; fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM_U; fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
...@@ -356,8 +362,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -356,8 +362,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
fmtpar[fmtpos].base = 8; fmtpar[fmtpos].base = 8;
fmtpar[fmtpos].dosign = 0; fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].forcesign = forcesign;
fmtpar[fmtpos].ljust = ljust; fmtpar[fmtpos].leftjust = leftjust;
fmtpar[fmtpos].len = len; fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM_U; fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
...@@ -372,8 +378,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -372,8 +378,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
fmtpar[fmtpos].base = 10; fmtpar[fmtpos].base = 10;
fmtpar[fmtpos].dosign = 1; fmtpar[fmtpos].dosign = 1;
fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].forcesign = forcesign;
fmtpar[fmtpos].ljust = ljust; fmtpar[fmtpos].leftjust = leftjust;
fmtpar[fmtpos].len = len; fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM; fmtpar[fmtpos].func = FMTNUM;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
...@@ -387,8 +393,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -387,8 +393,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
fmtpar[fmtpos].base = 16; fmtpar[fmtpos].base = 16;
fmtpar[fmtpos].dosign = 0; fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].forcesign = forcesign;
fmtpar[fmtpos].ljust = ljust; fmtpar[fmtpos].leftjust = leftjust;
fmtpar[fmtpos].len = len; fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM_U; fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
...@@ -402,8 +408,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -402,8 +408,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
fmtpar[fmtpos].base = -16; fmtpar[fmtpos].base = -16;
fmtpar[fmtpos].dosign = 1; fmtpar[fmtpos].dosign = 1;
fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].forcesign = forcesign;
fmtpar[fmtpos].ljust = ljust; fmtpar[fmtpos].leftjust = leftjust;
fmtpar[fmtpos].len = len; fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM_U; fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
...@@ -412,8 +418,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -412,8 +418,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
case 's': case 's':
fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].fmtend = format;
fmtpar[fmtpos].ljust = ljust; fmtpar[fmtpos].leftjust = leftjust;
fmtpar[fmtpos].len = len; fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].maxwidth = maxwidth; fmtpar[fmtpos].maxwidth = maxwidth;
fmtpar[fmtpos].func = FMTSTR; fmtpar[fmtpos].func = FMTSTR;
...@@ -436,8 +442,8 @@ dopr(char *buffer, const char *format, va_list args, char *end) ...@@ -436,8 +442,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].fmtend = format;
fmtpar[fmtpos].type = ch; fmtpar[fmtpos].type = ch;
fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].forcesign = forcesign;
fmtpar[fmtpos].ljust = ljust; fmtpar[fmtpos].leftjust = leftjust;
fmtpar[fmtpos].len = len; fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].precision = precision; fmtpar[fmtpos].precision = precision;
fmtpar[fmtpos].pointflag = pointflag; fmtpar[fmtpos].pointflag = pointflag;
...@@ -499,11 +505,27 @@ performpr: ...@@ -499,11 +505,27 @@ performpr:
fmtparptr[i]->charvalue = va_arg(args, int); fmtparptr[i]->charvalue = va_arg(args, int);
break; break;
case FMTLEN: case FMTLEN:
if (i + 1 < fmtpos && fmtparptr[i + 1]->func != FMTWIDTH) {
fmtparptr[i + 1]->len = va_arg(args, int); int minlen = va_arg(args, int);
/* For "%*.*f", use the second arg */ int leftjust = 0;
if (i + 2 < fmtpos && fmtparptr[i + 1]->func == FMTWIDTH)
fmtparptr[i + 2]->len = va_arg(args, int); if (minlen < 0)
{
minlen = -minlen;
leftjust = 1;
}
if (i + 1 < fmtpos && fmtparptr[i + 1]->func != FMTWIDTH)
{
fmtparptr[i + 1]->minlen = minlen;
fmtparptr[i + 1]->leftjust |= leftjust;
}
/* For "%*.*f", use the second arg */
if (i + 2 < fmtpos && fmtparptr[i + 1]->func == FMTWIDTH)
{
fmtparptr[i + 2]->minlen = minlen;
fmtparptr[i + 2]->leftjust |= leftjust;
}
}
break; break;
case FMTWIDTH: case FMTWIDTH:
if (i + 1 < fmtpos) if (i + 1 < fmtpos)
...@@ -530,21 +552,21 @@ performpr: ...@@ -530,21 +552,21 @@ performpr:
switch (fmtparptr[i]->func) switch (fmtparptr[i]->func)
{ {
case FMTSTR: case FMTSTR:
fmtstr(fmtparptr[i]->value, fmtparptr[i]->ljust, fmtstr(fmtparptr[i]->value, fmtparptr[i]->leftjust,
fmtparptr[i]->len, fmtparptr[i]->maxwidth, fmtparptr[i]->minlen, fmtparptr[i]->maxwidth,
end, &output); end, &output);
break; break;
case FMTNUM: case FMTNUM:
case FMTNUM_U: case FMTNUM_U:
fmtnum(fmtparptr[i]->numvalue, fmtparptr[i]->base, fmtint(fmtparptr[i]->numvalue, fmtparptr[i]->base,
fmtparptr[i]->dosign, fmtparptr[i]->forcesign, fmtparptr[i]->dosign, fmtparptr[i]->forcesign,
fmtparptr[i]->ljust, fmtparptr[i]->len, fmtparptr[i]->leftjust, fmtparptr[i]->minlen,
fmtparptr[i]->zpad, end, &output); fmtparptr[i]->zpad, end, &output);
break; break;
case FMTFLOAT: case FMTFLOAT:
fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type, fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type,
fmtparptr[i]->forcesign, fmtparptr[i]->ljust, fmtparptr[i]->forcesign, fmtparptr[i]->leftjust,
fmtparptr[i]->len, fmtparptr[i]->zpad, fmtparptr[i]->minlen, fmtparptr[i]->zpad,
fmtparptr[i]->precision, fmtparptr[i]->pointflag, fmtparptr[i]->precision, fmtparptr[i]->pointflag,
end, &output); end, &output);
break; break;
...@@ -574,7 +596,7 @@ nochar: ...@@ -574,7 +596,7 @@ nochar:
} }
static void static void
fmtstr(char *value, int ljust, int len, int maxwidth, char *end, fmtstr(char *value, int leftjust, int minlen, int maxwidth, char *end,
char **output) char **output)
{ {
int padlen, int padlen,
...@@ -582,185 +604,90 @@ fmtstr(char *value, int ljust, int len, int maxwidth, char *end, ...@@ -582,185 +604,90 @@ fmtstr(char *value, int ljust, int len, int maxwidth, char *end,
if (value == NULL) if (value == NULL)
value = "<NULL>"; value = "<NULL>";
vallen = strlen(value); vallen = strlen(value);
if (vallen > maxwidth && maxwidth) if (maxwidth && vallen > maxwidth)
vallen = maxwidth; vallen = maxwidth;
if (len < 0)
{ adjust_padlen(minlen, vallen, leftjust, &padlen);
/* this could happen with a "*" width spec */
ljust = 1;
len = -len;
}
padlen = len - vallen;
if (padlen < 0)
padlen = 0;
if (ljust)
padlen = -padlen;
while (padlen > 0) while (padlen > 0)
{ {
dopr_outch(' ', end, output); dopr_outch(' ', end, output);
--padlen; --padlen;
} }
dostr(value, maxwidth, end, output); dostr(value, maxwidth, end, output);
while (padlen < 0)
{ trailing_pad(&padlen, end, output);
dopr_outch(' ', end, output);
++padlen;
}
} }
static void static void
fmtnum(int64 value, int base, int dosign, int forcesign, int ljust, fmtint(int64 value, int base, int dosign, int forcesign, int leftjust,
int len, int zpad, char *end, char **output) int minlen, int zpad, char *end, char **output)
{ {
int signvalue = 0; int signvalue = 0;
uint64 uvalue;
char convert[64]; char convert[64];
int place = 0; int vallen = 0;
int padlen = 0; /* amount to pad */ int padlen = 0; /* amount to pad */
int caps = 0; int caps = 0;
/* /* Handle +/- and %X (uppercase hex) */
* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
* value, base, dosign, ljust, len, zpad )); value = -value;
*/
uvalue = value;
if (dosign)
{
if (value < 0)
{
signvalue = '-';
uvalue = -value;
}
else if (forcesign)
signvalue = '+';
}
if (base < 0) if (base < 0)
{ {
caps = 1; caps = 1;
base = -base; base = -base;
} }
/* make integer string */
do do
{ {
convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") convert[vallen++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
[uvalue % (unsigned) base]; [value % (unsigned) base];
uvalue = (uvalue / (unsigned) base); value = (value / (unsigned) base);
} while (uvalue); } while (value);
convert[place] = 0; convert[vallen] = 0;
if (len < 0) adjust_padlen(minlen, vallen, leftjust, &padlen);
{
/* this could happen with a "*" width spec */ leading_pad(zpad, &signvalue, &padlen, end, output);
ljust = 1;
len = -len; while (vallen > 0)
} dopr_outch(convert[--vallen], end, output);
padlen = len - place;
if (padlen < 0) trailing_pad(&padlen, end, output);
padlen = 0;
if (ljust)
padlen = -padlen;
/*
* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
* convert,place,signvalue,padlen));
*/
if (zpad && padlen > 0)
{
if (signvalue)
{
dopr_outch(signvalue, end, output);
--padlen;
signvalue = 0;
}
while (padlen > 0)
{
dopr_outch(zpad, end, output);
--padlen;
}
}
while (padlen > 0)
{
dopr_outch(' ', end, output);
--padlen;
}
if (signvalue)
dopr_outch(signvalue, end, output);
while (place > 0)
dopr_outch(convert[--place], end, output);
while (padlen < 0)
{
dopr_outch(' ', end, output);
++padlen;
}
} }
static void static void
fmtfloat(double value, char type, int forcesign, int ljust, fmtfloat(double value, char type, int forcesign, int leftjust,
int len, int zpad, int precision, int pointflag, char *end, int minlen, int zpad, int precision, int pointflag, char *end,
char **output) char **output)
{ {
int signvalue = 0; int signvalue = 0;
double uvalue; int vallen;
char fmt[32]; char fmt[32];
char convert[512]; char convert[512];
int padlen = 0; /* amount to pad */ int padlen = 0; /* amount to pad */
uvalue = value;
/* we rely on regular C library's sprintf to do the basic conversion */ /* we rely on regular C library's sprintf to do the basic conversion */
if (pointflag) if (pointflag)
sprintf(fmt, "%%.%d%c", precision, type); sprintf(fmt, "%%.%d%c", precision, type);
else else
sprintf(fmt, "%%%c", type); sprintf(fmt, "%%%c", type);
if (value < 0) if (adjust_sign((value < 0), forcesign, &signvalue))
{ value = -value;
signvalue = '-';
uvalue = -value;
}
else if (forcesign)
signvalue = '+';
sprintf(convert, fmt, uvalue); vallen = sprintf(convert, fmt, value);
if (len < 0) adjust_padlen(minlen, vallen, leftjust, &padlen);
{
/* this could happen with a "*" width spec */ leading_pad(zpad, &signvalue, &padlen, end, output);
ljust = 1;
len = -len;
}
padlen = len - strlen(convert);
if (padlen < 0)
padlen = 0;
if (ljust)
padlen = -padlen;
if (zpad && padlen > 0)
{
if (signvalue)
{
dopr_outch(signvalue, end, output);
--padlen;
signvalue = 0;
}
while (padlen > 0)
{
dopr_outch(zpad, end, output);
--padlen;
}
}
while (padlen > 0)
{
dopr_outch(' ', end, output);
--padlen;
}
if (signvalue)
dopr_outch(signvalue, end, output);
dostr(convert, 0, end, output); dostr(convert, 0, end, output);
while (padlen < 0)
{ trailing_pad(&padlen, end, output);
dopr_outch(' ', end, output);
++padlen;
}
} }
static void static void
...@@ -788,3 +715,73 @@ dopr_outch(int c, char *end, char **output) ...@@ -788,3 +715,73 @@ dopr_outch(int c, char *end, char **output)
if (end == 0 || *output < end) if (end == 0 || *output < end)
*(*output)++ = c; *(*output)++ = c;
} }
static int
adjust_sign(int is_negative, int forcesign, int *signvalue)
{
if (is_negative)
{
*signvalue = '-';
return true;
}
else if (forcesign)
*signvalue = '+';
return false;
}
static void
adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
{
*padlen = minlen - vallen;
if (*padlen < 0)
*padlen = 0;
if (leftjust)
*padlen = -*padlen;
}
static void
leading_pad(int zpad, int *signvalue, int *padlen, char *end, char **output)
{
if (*padlen > 0 && zpad)
{
if (*signvalue)
{
dopr_outch(*signvalue, end, output);
--*padlen;
*signvalue = 0;
}
while (*padlen > 0)
{
dopr_outch(zpad, end, output);
--*padlen;
}
}
while (*padlen > 0 + (*signvalue != 0))
{
dopr_outch(' ', end, output);
--*padlen;
}
if (*signvalue)
{
dopr_outch(*signvalue, end, output);
if (*padlen > 0)
--*padlen;
if (padlen < 0)
++padlen;
}
}
static void
trailing_pad(int *padlen, char *end, char **output)
{
while (*padlen < 0)
{
dopr_outch(' ', end, output);
++*padlen;
}
}
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