diff options
author | Bruce Momjian <bruce@momjian.us> | 2005-02-22 03:56:22 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2005-02-22 03:56:22 +0000 |
commit | b4feafb6ffdc8417abb167f5d3297428dc465b03 (patch) | |
tree | 6046bd0a507a4fbc7e2b92d4ae2f0d59223da94f /src | |
parent | 78bb800bc288f141e04411de278b6f55547a775d (diff) | |
download | postgresql-b4feafb6ffdc8417abb167f5d3297428dc465b03.tar.gz postgresql-b4feafb6ffdc8417abb167f5d3297428dc465b03.zip |
Add support to port/snprintf.c for position parameter specification:
+ # Determine if printf supports %1$ argument selection, e.g. %5$ selects
+ # the fifth argument after the printf print string.
+ # This is not in the C99 standard, but in the Single Unix Specification (SUS).
+ # It is used in our langauge translation strings.
Nicolai Tufar with configure changes by Bruce.
Diffstat (limited to 'src')
-rw-r--r-- | src/port/snprintf.c | 211 |
1 files changed, 196 insertions, 15 deletions
diff --git a/src/port/snprintf.c b/src/port/snprintf.c index 9f3baec7dca..00378213a4c 100644 --- a/src/port/snprintf.c +++ b/src/port/snprintf.c @@ -57,6 +57,10 @@ typedef long long_long; typedef unsigned long ulong_long; #endif +#ifndef NL_ARGMAX +#define NL_ARGMAX 4096 +#endif + /* ** SNPRINTF, VSNPRINT -- counted versions of printf ** @@ -79,15 +83,33 @@ typedef unsigned long ulong_long; * causing nast effects. **************************************************************/ -/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.4 2004/08/29 05:07:02 momjian Exp $";*/ +/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.5 2005/02/22 03:56:22 momjian Exp $";*/ static char *end; static int SnprfOverflow; int snprintf(char *str, size_t count, const char *fmt,...); int vsnprintf(char *str, size_t count, const char *fmt, va_list args); +int printf(const char *format, ...); static void dopr(char *buffer, const char *format, va_list args); int +printf(const char *fmt,...) +{ + int len; + va_list args; + static char* buffer[4096]; + char* p; + + va_start(args, fmt); + len = vsnprintf((char*)buffer, (size_t)4096, fmt, args); + va_end(args); + p = (char*)buffer; + for(;*p;p++) + putchar(*p); + return len; +} + +int snprintf(char *str, size_t count, const char *fmt,...) { int len; @@ -124,6 +146,10 @@ static void dopr_outch(int c); static char *output; +#define FMTSTR 1 +#define FMTNUM 2 +#define FMTFLOAT 3 +#define FMTCHAR 4 static void dopr(char *buffer, const char *format, va_list args) @@ -139,7 +165,34 @@ dopr(char *buffer, const char *format, va_list args) int ljust; int len; int zpad; - + int i; + const char* format_save; + const char* fmtbegin; + int fmtpos = 1; + int realpos = 0; + int position; + static struct{ + const char* fmtbegin; + const char* fmtend; + void* value; + long_long numvalue; + double fvalue; + int charvalue; + int ljust; + int len; + int zpad; + int maxwidth; + int base; + int dosign; + char type; + int precision; + int pointflag; + char func; + int realpos; + } fmtpar[NL_ARGMAX+1], *fmtparptr[NL_ARGMAX+1]; + + + format_save = format; output = buffer; while ((ch = *format++)) { @@ -148,14 +201,15 @@ dopr(char *buffer, const char *format, va_list args) case '%': ljust = len = zpad = maxwidth = 0; longflag = longlongflag = pointflag = 0; + fmtbegin = format - 1; + realpos = 0; + position = 0; nextch: ch = *format++; switch (ch) { case 0: - dostr("**end of format**", 0); - *output = '\0'; - return; + goto performpr; case '-': ljust = 1; goto nextch; @@ -174,7 +228,14 @@ dopr(char *buffer, const char *format, va_list args) if (pointflag) maxwidth = maxwidth * 10 + ch - '0'; else + { len = len * 10 + ch - '0'; + position = position * 10 + ch - '0'; + } + goto nextch; + case '$': + realpos = position; + len = 0; goto nextch; case '*': if (pointflag) @@ -203,7 +264,17 @@ dopr(char *buffer, const char *format, va_list args) } else value = va_arg(args, unsigned int); - fmtnum(value, 10, 0, ljust, len, zpad); + 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].realpos = realpos?realpos:fmtpos; + fmtpos++; break; case 'o': case 'O': @@ -217,7 +288,17 @@ dopr(char *buffer, const char *format, va_list args) } else value = va_arg(args, unsigned int); - fmtnum(value, 8, 0, ljust, len, zpad); + 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].realpos = realpos?realpos:fmtpos; + fmtpos++; break; case 'd': case 'D': @@ -230,7 +311,17 @@ dopr(char *buffer, const char *format, va_list args) } else value = va_arg(args, int); - fmtnum(value, 10, 1, ljust, len, zpad); + fmtpar[fmtpos].fmtbegin = fmtbegin; + fmtpar[fmtpos].fmtend = format; + fmtpar[fmtpos].numvalue = value; + fmtpar[fmtpos].base = 10; + fmtpar[fmtpos].dosign = 1; + fmtpar[fmtpos].ljust = ljust; + fmtpar[fmtpos].len = len; + fmtpar[fmtpos].zpad = zpad; + fmtpar[fmtpos].func = FMTNUM; + fmtpar[fmtpos].realpos = realpos?realpos:fmtpos; + fmtpos++; break; case 'x': if (longflag) @@ -242,7 +333,17 @@ dopr(char *buffer, const char *format, va_list args) } else value = va_arg(args, unsigned int); - fmtnum(value, 16, 0, ljust, len, zpad); + 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].realpos = realpos?realpos:fmtpos; + fmtpos++; break; case 'X': if (longflag) @@ -254,7 +355,17 @@ dopr(char *buffer, const char *format, va_list args) } else value = va_arg(args, unsigned int); - fmtnum(value, -16, 0, ljust, len, zpad); + 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].realpos = realpos?realpos:fmtpos; + fmtpos++; break; case 's': strvalue = va_arg(args, char *); @@ -262,12 +373,26 @@ dopr(char *buffer, const char *format, va_list args) { if (pointflag && len > maxwidth) len = maxwidth; /* Adjust padding */ - fmtstr(strvalue, ljust, len, zpad, maxwidth); + 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++; } break; case 'c': ch = va_arg(args, int); - dopr_outch(ch); + fmtpar[fmtpos].fmtbegin = fmtbegin; + fmtpar[fmtpos].fmtend = format; + fmtpar[fmtpos].charvalue = ch; + fmtpar[fmtpos].func = FMTCHAR; + fmtpar[fmtpos].realpos = realpos?realpos:fmtpos; + fmtpos++; break; case 'e': case 'E': @@ -275,11 +400,20 @@ dopr(char *buffer, const char *format, va_list args) case 'g': case 'G': fvalue = va_arg(args, double); - fmtfloat(fvalue, ch, ljust, len, maxwidth, pointflag); + 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].pointflag = pointflag; + fmtpar[fmtpos].func = FMTFLOAT; + fmtpar[fmtpos].realpos = realpos?realpos:fmtpos; + fmtpos++; break; case '%': - dopr_outch(ch); - continue; + break; default: dostr("???????", 0); } @@ -289,6 +423,53 @@ dopr(char *buffer, const char *format, va_list args) break; } } +performpr: + /* shuffle pointers */ + for(i = 1; i < fmtpos; i++) + { + fmtparptr[i] = &fmtpar[fmtpar[i].realpos]; + } + output = buffer; + format = format_save; + while ((ch = *format++)) + { + for(i = 1; i < fmtpos; i++) + { + if(ch == '%' && *format == '%') + { + format++; + continue; + } + if(fmtpar[i].fmtbegin == format - 1) + { + switch(fmtparptr[i]->func){ + case FMTSTR: + fmtstr(fmtparptr[i]->value, fmtparptr[i]->ljust, + fmtparptr[i]->len, fmtparptr[i]->zpad, + fmtparptr[i]->maxwidth); + break; + case FMTNUM: + fmtnum(fmtparptr[i]->numvalue, fmtparptr[i]->base, + fmtparptr[i]->dosign, fmtparptr[i]->ljust, + fmtparptr[i]->len, fmtparptr[i]->zpad); + break; + case FMTFLOAT: + fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type, + fmtparptr[i]->ljust, fmtparptr[i]->len, + fmtparptr[i]->precision, fmtparptr[i]->pointflag); + break; + case FMTCHAR: + dopr_outch(fmtparptr[i]->charvalue); + break; + } + format = fmtpar[i].fmtend; + goto nochar; + } + } + dopr_outch(ch); +nochar: + /* nothing */ + } *output = '\0'; } |