* 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);
return len;
}
-/*
- * dopr(): poor man's version of doprintf
- */
+static int adjust_sign(int is_negative, int forcesign, int *signvalue);
+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);
-static void fmtnum(int64 value, int base, int dosign, int forcesign,
- int ljust, int len, int zpad, char *end, char **output);
+static void fmtint(int64 value, int base, int dosign, int forcesign,
+ int leftjust, int minlen, int zpad, char *end, char **output);
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);
static void dostr(char *str, int cut, char *end, char **output);
static void dopr_outch(int c, char *end, char **output);
#define FMTWIDTH 6
#define FMTLEN 7
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
static void
dopr(char *buffer, const char *format, va_list args, char *end)
{
int longflag;
int pointflag;
int maxwidth;
- int ljust;
- int len;
+ int leftjust;
+ int minlen;
int zpad;
int forcesign;
int i;
int64 numvalue;
double fvalue;
int charvalue;
- int ljust;
- int len;
+ int leftjust;
+ int minlen;
int zpad;
int maxwidth;
int base;
switch (ch)
{
case '%':
- ljust = len = zpad = forcesign = maxwidth = 0;
+ leftjust = minlen = zpad = forcesign = maxwidth = 0;
longflag = longlongflag = pointflag = 0;
fmtbegin = format - 1;
realpos = 0;
case '\0':
goto performpr;
case '-':
- ljust = 1;
+ leftjust = 1;
goto nextch;
case '+':
forcesign = 1;
goto nextch;
- case '0': /* set zero padding if len not set */
- if (len == 0 && !pointflag)
+ case '0': /* set zero padding if minlen not set */
+ if (minlen == 0 && !pointflag)
zpad = '0';
case '1':
case '2':
case '9':
if (!pointflag)
{
- len = len * 10 + ch - '0';
+ minlen = minlen * 10 + ch - '0';
position = position * 10 + ch - '0';
}
else
goto nextch;
case '$':
realpos = position;
- len = 0;
+ minlen = 0;
goto nextch;
case '*':
MemSet(&fmtpar[fmtpos], 0, sizeof(fmtpar[fmtpos]));
fmtpar[fmtpos].base = 10;
fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].forcesign = forcesign;
- fmtpar[fmtpos].ljust = ljust;
- fmtpar[fmtpos].len = len;
+ fmtpar[fmtpos].leftjust = leftjust;
+ fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
fmtpar[fmtpos].base = 8;
fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].forcesign = forcesign;
- fmtpar[fmtpos].ljust = ljust;
- fmtpar[fmtpos].len = len;
+ fmtpar[fmtpos].leftjust = leftjust;
+ fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
fmtpar[fmtpos].base = 10;
fmtpar[fmtpos].dosign = 1;
fmtpar[fmtpos].forcesign = forcesign;
- fmtpar[fmtpos].ljust = ljust;
- fmtpar[fmtpos].len = len;
+ fmtpar[fmtpos].leftjust = leftjust;
+ fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
fmtpar[fmtpos].base = 16;
fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].forcesign = forcesign;
- fmtpar[fmtpos].ljust = ljust;
- fmtpar[fmtpos].len = len;
+ fmtpar[fmtpos].leftjust = leftjust;
+ fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
fmtpar[fmtpos].base = -16;
fmtpar[fmtpos].dosign = 1;
fmtpar[fmtpos].forcesign = forcesign;
- fmtpar[fmtpos].ljust = ljust;
- fmtpar[fmtpos].len = len;
+ fmtpar[fmtpos].leftjust = leftjust;
+ fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos;
case 's':
fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].ljust = ljust;
- fmtpar[fmtpos].len = len;
+ fmtpar[fmtpos].leftjust = leftjust;
+ fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].maxwidth = maxwidth;
fmtpar[fmtpos].func = FMTSTR;
fmtpar[fmtpos].fmtend = format;
fmtpar[fmtpos].type = ch;
fmtpar[fmtpos].forcesign = forcesign;
- fmtpar[fmtpos].ljust = ljust;
- fmtpar[fmtpos].len = len;
+ fmtpar[fmtpos].leftjust = leftjust;
+ fmtpar[fmtpos].minlen = minlen;
fmtpar[fmtpos].zpad = zpad;
fmtpar[fmtpos].precision = precision;
fmtpar[fmtpos].pointflag = pointflag;
fmtparptr[i]->charvalue = va_arg(args, int);
break;
case FMTLEN:
- if (i + 1 < fmtpos && fmtparptr[i + 1]->func != FMTWIDTH)
- fmtparptr[i + 1]->len = va_arg(args, int);
- /* For "%*.*f", use the second arg */
- if (i + 2 < fmtpos && fmtparptr[i + 1]->func == FMTWIDTH)
- fmtparptr[i + 2]->len = va_arg(args, int);
+ {
+ int minlen = va_arg(args, int);
+ int leftjust = 0;
+
+ 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;
case FMTWIDTH:
if (i + 1 < fmtpos)
switch (fmtparptr[i]->func)
{
case FMTSTR:
- fmtstr(fmtparptr[i]->value, fmtparptr[i]->ljust,
- fmtparptr[i]->len, fmtparptr[i]->maxwidth,
+ fmtstr(fmtparptr[i]->value, fmtparptr[i]->leftjust,
+ fmtparptr[i]->minlen, fmtparptr[i]->maxwidth,
end, &output);
break;
case FMTNUM:
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]->ljust, fmtparptr[i]->len,
+ fmtparptr[i]->leftjust, fmtparptr[i]->minlen,
fmtparptr[i]->zpad, end, &output);
break;
case FMTFLOAT:
fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type,
- fmtparptr[i]->forcesign, fmtparptr[i]->ljust,
- fmtparptr[i]->len, fmtparptr[i]->zpad,
+ fmtparptr[i]->forcesign, fmtparptr[i]->leftjust,
+ fmtparptr[i]->minlen, fmtparptr[i]->zpad,
fmtparptr[i]->precision, fmtparptr[i]->pointflag,
end, &output);
break;
}
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)
{
int padlen,
if (value == NULL)
value = "<NULL>";
+
vallen = strlen(value);
- if (vallen > maxwidth && maxwidth)
+ if (maxwidth && vallen > maxwidth)
vallen = maxwidth;
- if (len < 0)
- {
- /* this could happen with a "*" width spec */
- ljust = 1;
- len = -len;
- }
- padlen = len - vallen;
- if (padlen < 0)
- padlen = 0;
- if (ljust)
- padlen = -padlen;
+
+ adjust_padlen(minlen, vallen, leftjust, &padlen);
+
while (padlen > 0)
{
dopr_outch(' ', end, output);
--padlen;
}
dostr(value, maxwidth, end, output);
- while (padlen < 0)
- {
- dopr_outch(' ', end, output);
- ++padlen;
- }
+
+ trailing_pad(&padlen, end, output);
}
static void
-fmtnum(int64 value, int base, int dosign, int forcesign, int ljust,
- int len, int zpad, char *end, char **output)
+fmtint(int64 value, int base, int dosign, int forcesign, int leftjust,
+ int minlen, int zpad, char *end, char **output)
{
int signvalue = 0;
- uint64 uvalue;
char convert[64];
- int place = 0;
+ int vallen = 0;
int padlen = 0; /* amount to pad */
int caps = 0;
- /*
- * DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
- * value, base, dosign, ljust, len, zpad ));
- */
- uvalue = value;
- if (dosign)
- {
- if (value < 0)
- {
- signvalue = '-';
- uvalue = -value;
- }
- else if (forcesign)
- signvalue = '+';
- }
+ /* Handle +/- and %X (uppercase hex) */
+ if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
+ value = -value;
if (base < 0)
{
caps = 1;
base = -base;
}
+
+ /* make integer string */
do
{
- convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
- [uvalue % (unsigned) base];
- uvalue = (uvalue / (unsigned) base);
- } while (uvalue);
- convert[place] = 0;
+ convert[vallen++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [value % (unsigned) base];
+ value = (value / (unsigned) base);
+ } while (value);
+ convert[vallen] = 0;
- if (len < 0)
- {
- /* this could happen with a "*" width spec */
- ljust = 1;
- len = -len;
- }
- padlen = len - place;
- if (padlen < 0)
- 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;
- }
+ adjust_padlen(minlen, vallen, leftjust, &padlen);
+
+ leading_pad(zpad, &signvalue, &padlen, end, output);
+
+ while (vallen > 0)
+ dopr_outch(convert[--vallen], end, output);
+
+ trailing_pad(&padlen, end, output);
}
static void
-fmtfloat(double value, char type, int forcesign, int ljust,
- int len, int zpad, int precision, int pointflag, char *end,
+fmtfloat(double value, char type, int forcesign, int leftjust,
+ int minlen, int zpad, int precision, int pointflag, char *end,
char **output)
{
int signvalue = 0;
- double uvalue;
+ int vallen;
char fmt[32];
char convert[512];
int padlen = 0; /* amount to pad */
- uvalue = value;
/* 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);
- if (value < 0)
- {
- signvalue = '-';
- uvalue = -value;
- }
- else if (forcesign)
- signvalue = '+';
+ if (adjust_sign((value < 0), forcesign, &signvalue))
+ value = -value;
- sprintf(convert, fmt, uvalue);
+ vallen = 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;
+ adjust_padlen(minlen, vallen, leftjust, &padlen);
+
+ leading_pad(zpad, &signvalue, &padlen, end, output);
- 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);
- while (padlen < 0)
- {
- dopr_outch(' ', end, output);
- ++padlen;
- }
+
+ trailing_pad(&padlen, end, output);
}
static void
if (end == 0 || *output < end)
*(*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;
+ }
+}
+