aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2005-03-16 06:00:58 +0000
committerBruce Momjian <bruce@momjian.us>2005-03-16 06:00:58 +0000
commit888271ed1526c26786ed6290ddfb996167699849 (patch)
tree3fad943ee3f6faf0d36c3c3b6c2e18d516b41e6f /src
parent83e87e6f2e1a6ec294d4448e0681661cb711405d (diff)
downloadpostgresql-888271ed1526c26786ed6290ddfb996167699849.tar.gz
postgresql-888271ed1526c26786ed6290ddfb996167699849.zip
Fix snprintf to handle %$ properly by storing and reordering the
arguments. Nicolai Tufar
Diffstat (limited to 'src')
-rw-r--r--src/port/snprintf.c200
1 files changed, 103 insertions, 97 deletions
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 7a7aa91d65a..815a860d944 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -65,7 +65,7 @@
* causing nasty effects.
**************************************************************/
-/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.19 2005/03/12 04:00:56 momjian Exp $";*/
+/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.20 2005/03/16 06:00:58 momjian Exp $";*/
int pg_snprintf(char *str, size_t count, const char *fmt,...);
int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
@@ -151,20 +151,20 @@ static void dopr_outch(int c, char *end, char **output);
#define FMTSTR 1
#define FMTNUM 2
-#define FMTFLOAT 3
-#define FMTCHAR 4
+#define FMTNUM_U 3
+#define FMTFLOAT 4
+#define FMTCHAR 5
+#define FMTWIDTH 6
+#define FMTLEN 7
static void
dopr(char *buffer, const char *format, va_list args, char *end)
{
int ch;
- int64 value;
- double fvalue;
int longlongflag = 0;
int longflag = 0;
int pointflag = 0;
int maxwidth = 0;
- char *strvalue;
int ljust;
int len;
int zpad;
@@ -173,6 +173,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
const char* fmtbegin;
int fmtpos = 1;
int realpos = 0;
+ int precision;
int position;
char *output;
int percents = 1;
@@ -195,6 +196,8 @@ dopr(char *buffer, const char *format, va_list args, char *end)
int pointflag;
char func;
int realpos;
+ int longflag;
+ int longlongflag;
} *fmtpar, **fmtparptr;
/* Create enough structures to hold all arguments */
@@ -229,12 +232,12 @@ dopr(char *buffer, const char *format, va_list args, char *end)
longflag = longlongflag = pointflag = 0;
fmtbegin = format - 1;
realpos = 0;
- position = 0;
+ position = precision = 0;
nextch:
ch = *format++;
switch (ch)
{
- case 0:
+ case '\0':
goto performpr;
case '-':
ljust = 1;
@@ -251,24 +254,29 @@ dopr(char *buffer, const char *format, va_list args, char *end)
case '7':
case '8':
case '9':
- if (pointflag)
- /* could also be precision */
- maxwidth = maxwidth * 10 + ch - '0';
- else
+ if (!pointflag)
{
len = len * 10 + ch - '0';
position = position * 10 + ch - '0';
}
+ else
+ {
+ maxwidth = maxwidth * 10 + ch - '0';
+ precision = precision * 10 + ch - '0';
+ }
goto nextch;
case '$':
realpos = position;
len = 0;
goto nextch;
case '*':
- if (pointflag)
- maxwidth = va_arg(args, int);
+ MemSet(&fmtpar[fmtpos], 0, sizeof(fmtpar[fmtpos]));
+ if (!pointflag)
+ fmtpar[fmtpos].func = FMTLEN;
else
- len = va_arg(args, int);
+ fmtpar[fmtpos].func = FMTWIDTH;
+ fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
+ fmtpos++;
goto nextch;
case '.':
pointflag = 1;
@@ -301,68 +309,40 @@ dopr(char *buffer, const char *format, va_list args, char *end)
#endif
case 'u':
case 'U':
- /* fmtnum(value,base,dosign,ljust,len,zpad,&output) */
- if (longflag)
- {
- if (longlongflag)
- value = va_arg(args, uint64);
- else
- value = va_arg(args, unsigned long);
- }
- else
- value = va_arg(args, unsigned int);
+ fmtpar[fmtpos].longflag = longflag;
+ fmtpar[fmtpos].longlongflag = longlongflag;
fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].numvalue = value;
fmtpar[fmtpos].base = 10;
fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].ljust = ljust;
fmtpar[fmtpos].len = len;
fmtpar[fmtpos].zpad = zpad;
- fmtpar[fmtpos].func = FMTNUM;
+ fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
fmtpos++;
break;
case 'o':
case 'O':
- /* fmtnum(value,base,dosign,ljust,len,zpad,&output) */
- if (longflag)
- {
- if (longlongflag)
- value = va_arg(args, uint64);
- else
- value = va_arg(args, unsigned long);
- }
- else
- value = va_arg(args, unsigned int);
+ fmtpar[fmtpos].longflag = longflag;
+ fmtpar[fmtpos].longlongflag = longlongflag;
fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].numvalue = value;
fmtpar[fmtpos].base = 8;
fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].ljust = ljust;
fmtpar[fmtpos].len = len;
fmtpar[fmtpos].zpad = zpad;
- fmtpar[fmtpos].func = FMTNUM;
+ fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
fmtpos++;
break;
case 'd':
case 'D':
- if (longflag)
- {
- if (longlongflag)
- {
- value = va_arg(args, int64);
- }
- else
- value = va_arg(args, long);
- }
- else
- value = va_arg(args, int);
+ fmtpar[fmtpos].longflag = longflag;
+ fmtpar[fmtpos].longlongflag = longlongflag;
fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].numvalue = value;
fmtpar[fmtpos].base = 10;
fmtpar[fmtpos].dosign = 1;
fmtpar[fmtpos].ljust = ljust;
@@ -373,72 +353,47 @@ dopr(char *buffer, const char *format, va_list args, char *end)
fmtpos++;
break;
case 'x':
- if (longflag)
- {
- if (longlongflag)
- value = va_arg(args, uint64);
- else
- value = va_arg(args, unsigned long);
- }
- else
- value = va_arg(args, unsigned int);
+ fmtpar[fmtpos].longflag = longflag;
+ fmtpar[fmtpos].longlongflag = longlongflag;
fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].numvalue = value;
fmtpar[fmtpos].base = 16;
fmtpar[fmtpos].dosign = 0;
fmtpar[fmtpos].ljust = ljust;
fmtpar[fmtpos].len = len;
fmtpar[fmtpos].zpad = zpad;
- fmtpar[fmtpos].func = FMTNUM;
+ fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
fmtpos++;
break;
case 'X':
- if (longflag)
- {
- if (longlongflag)
- value = va_arg(args, uint64);
- else
- value = va_arg(args, unsigned long);
- }
- else
- value = va_arg(args, unsigned int);
+ fmtpar[fmtpos].longflag = longflag;
+ fmtpar[fmtpos].longlongflag = longlongflag;
fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].numvalue = value;
fmtpar[fmtpos].base = -16;
fmtpar[fmtpos].dosign = 1;
fmtpar[fmtpos].ljust = ljust;
fmtpar[fmtpos].len = len;
fmtpar[fmtpos].zpad = zpad;
- fmtpar[fmtpos].func = FMTNUM;
+ fmtpar[fmtpos].func = FMTNUM_U;
fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
fmtpos++;
break;
case 's':
- strvalue = va_arg(args, char *);
- if (maxwidth > 0 || !pointflag)
- {
- if (pointflag && len > maxwidth)
- len = maxwidth; /* Adjust padding */
- fmtpar[fmtpos].fmtbegin = fmtbegin;
- fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].value = strvalue;
- fmtpar[fmtpos].ljust = ljust;
- fmtpar[fmtpos].len = len;
- fmtpar[fmtpos].zpad = zpad;
- fmtpar[fmtpos].maxwidth = maxwidth;
- fmtpar[fmtpos].func = FMTSTR;
- fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
- fmtpos++;
- }
+ fmtpar[fmtpos].fmtbegin = fmtbegin;
+ fmtpar[fmtpos].fmtend = format;
+ fmtpar[fmtpos].ljust = ljust;
+ fmtpar[fmtpos].len = len;
+ fmtpar[fmtpos].zpad = zpad;
+ fmtpar[fmtpos].maxwidth = maxwidth;
+ fmtpar[fmtpos].func = FMTSTR;
+ fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
+ fmtpos++;
break;
case 'c':
- ch = va_arg(args, int);
fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].charvalue = ch;
fmtpar[fmtpos].func = FMTCHAR;
fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
fmtpos++;
@@ -448,15 +403,13 @@ dopr(char *buffer, const char *format, va_list args, char *end)
case 'f':
case 'g':
case 'G':
- fvalue = va_arg(args, double);
fmtpar[fmtpos].fmtbegin = fmtbegin;
fmtpar[fmtpos].fmtend = format;
- fmtpar[fmtpos].fvalue = fvalue;
fmtpar[fmtpos].type = ch;
fmtpar[fmtpos].ljust = ljust;
fmtpar[fmtpos].len = len;
fmtpar[fmtpos].maxwidth = maxwidth;
- fmtpar[fmtpos].precision = position;
+ fmtpar[fmtpos].precision = precision;
fmtpar[fmtpos].pointflag = pointflag;
fmtpar[fmtpos].func = FMTFLOAT;
fmtpar[fmtpos].realpos = realpos?realpos:fmtpos;
@@ -473,22 +426,74 @@ dopr(char *buffer, const char *format, va_list args, char *end)
break;
}
}
+
performpr:
- /* shuffle pointers */
+ /* reorder pointers */
for(i = 1; i < fmtpos; i++)
fmtparptr[i] = &fmtpar[fmtpar[i].realpos];
+
+ /* assign values */
+ for(i = 1; i < fmtpos; i++){
+ switch(fmtparptr[i]->func){
+ case FMTSTR:
+ fmtparptr[i]->value = va_arg(args, char *);
+ break;
+ case FMTNUM:
+ if (fmtparptr[i]->longflag)
+ {
+ if (fmtparptr[i]->longlongflag)
+ fmtparptr[i]->numvalue = va_arg(args, int64);
+ else
+ fmtparptr[i]->numvalue = va_arg(args, long);
+ }
+ else
+ fmtparptr[i]->numvalue = va_arg(args, int);
+ break;
+ case FMTNUM_U:
+ if (fmtparptr[i]->longflag)
+ {
+ if (fmtparptr[i]->longlongflag)
+ fmtparptr[i]->numvalue = va_arg(args, uint64);
+ else
+ fmtparptr[i]->numvalue = va_arg(args, unsigned long);
+ }
+ else
+ fmtparptr[i]->numvalue = va_arg(args, unsigned int);
+ break;
+ case FMTFLOAT:
+ fmtparptr[i]->fvalue = va_arg(args, double);
+ break;
+ case FMTCHAR:
+ fmtparptr[i]->charvalue = va_arg(args, int);
+ break;
+ case FMTLEN:
+ if (i + 1 < fmtpos && fmtpar[i + 1].func != FMTWIDTH)
+ fmtpar[i + 1].len = va_arg(args, int);
+ /* For "%*.*f", use the second arg */
+ if (i + 2 < fmtpos && fmtpar[i + 1].func == FMTWIDTH)
+ fmtpar[i + 2].len = va_arg(args, int);
+ break;
+ case FMTWIDTH:
+ if (i + 1 < fmtpos)
+ fmtpar[i + 1].maxwidth = fmtpar[i + 1].precision =
+ va_arg(args, int);
+ break;
+ }
+ }
+
+ /* do the output */
output = buffer;
format = format_save;
while ((ch = *format++))
{
for(i = 1; i < fmtpos; i++)
{
- if(ch == '%' && *format == '%')
+ if (ch == '%' && *format == '%')
{
format++;
continue;
}
- if(fmtpar[i].fmtbegin == format - 1)
+ if (fmtpar[i].fmtbegin == format - 1)
{
switch(fmtparptr[i]->func){
case FMTSTR:
@@ -497,6 +502,7 @@ performpr:
fmtparptr[i]->maxwidth, end, &output);
break;
case FMTNUM:
+ case FMTNUM_U:
fmtnum(fmtparptr[i]->numvalue, fmtparptr[i]->base,
fmtparptr[i]->dosign, fmtparptr[i]->ljust,
fmtparptr[i]->len, fmtparptr[i]->zpad, end, &output);