Re: [HACKERS] snprintf() argument reordering not working under Windows - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: [HACKERS] snprintf() argument reordering not working under Windows |
Date | |
Msg-id | 200512031616.jB3GG3A19977@candle.pha.pa.us Whole thread Raw |
Responses |
Re: [HACKERS] snprintf() argument reordering not working under Windows
Re: [HACKERS] snprintf() argument reordering not working under Windows in 8.1 |
List | pgsql-patches |
Nicolai Tufar wrote: > Greetings, > > Last April we have made some changes to src/ports/snprintf.c so that it > would support argument reordering like %2$s, %1$d and such on > platforms where original snprintf() does not support it, like Windows, > HP-UX or NetBSD. Sure, I remember. So glad you returned at this time. I found a design limitation in that file yesterday. It can not output more then 4096 characters, and there are some cases with NUMERIC that try to output more than that. For example: SELECT pow(10::numeric, 10000) + 1; should show a '1' at the end of the number, but with the existing code you will just see 4095 0's and no more. I am attaching the new snprintf.c and the patch itself for your review. The change is to pass 'stream' down into the routines and output to the FILE* right from inside the routine, rather than using a string. This fixes the problem. I am also thinking of modifying the code so if we are using snprintf.c only because we need positional parameter control, we check for '$' in the string and only use snprintf.c in those cases. > NLS messages of some languages, like Turkish, rely heavily on argument > reordering because of the language structure. In 8.1 Turkish messages > in Windows version are all broken because argument reordering is not there. Really? I have not heard any report of that but this is new code in 8.1. > I examined commit logs and came to conclusion that src/port/snprintf.c > is not included in server when compiling under Windows because of change > to src/port/Makefile made in revision 1.28 by Bruce Momjian. See here: > > http://developer.postgresql.org/cvsweb.cgi/pgsql/src/port/Makefile > > Comment to the commit says: > `No server version of snprintf needed, so remove Makefile rule.' > In fact I think we need snprintf in server because NLS messages are > printed by the server. Actually, that changes means that there was nothing backend-specific in snprintf.c so we don't need a _special_ version for the backend. The real change not to use snprintf.c on Win32 is in configure.in with this comment: # Force use of our snprintf if system's doesn't do arg control # This feature is used by NLS if test "$enable_nls" = yes && test $pgac_need_repl_snprintf = no && # On Win32, libintl replaces snprintf() with its own version that # understands arg control, so we don't need our own. In fact, it # also uses macros that conflict with ours, so we _can't_ use # our own. test "$PORTNAME" != "win32"; then PGAC_FUNC_PRINTF_ARG_CONTROL if test $pgac_cv_printf_arg_control != yes ; then pgac_need_repl_snprintf=yes fi fi Here is the commit: revision 1.409 date: 2005/05/05 19:15:54; author: momjian; state: Exp; lines: +8 -2 On Win32, libintl replaces snprintf() with its own version that understands arg control, so we don't need our own. In fact, it also uses macros that conflict with ours, so we _can't_ use our own. So, I think it was Magnus who said that Win32 didn' need and couldn't use our snprintf. Magnus, any ideas? -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 /* * Copyright (c) 1983, 1995, 1996 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "c.h" #ifndef WIN32 #include <sys/ioctl.h> #endif #include <sys/param.h> /* ** SNPRINTF, VSNPRINT -- counted versions of printf ** ** These versions have been grabbed off the net. They have been ** cleaned up to compile properly and support for .precision and ** %lx has been added. */ /************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that * the version here does not include floating point. (now it does ... tgl) * * snprintf() is used instead of sprintf() as it does limit checks * for string length. This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nasty effects. **************************************************************/ /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.29 2005/10/15 02:49:51 momjian Exp $";*/ static int dopr(FILE *stream, char *buffer, const char *format, va_list args, char *end); /* Prevent recursion */ #undef vsnprintf #undef snprintf #undef sprintf #undef fprintf #undef printf static int pg_fvsnprintf(FILE *stream, char *str, size_t count, const char *fmt, va_list args) { char *end = NULL; int len; if (str) { str[0] = '\0'; end = str + count - 1; } len = dopr(stream, str, fmt, args, end); if (str && count > 0) end[0] = '\0'; return len; } int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args) { return pg_fvsnprintf(NULL, str, count, fmt, args); } int pg_snprintf(char *str, size_t count, const char *fmt,...) { int len; va_list args; va_start(args, fmt); len = pg_fvsnprintf(NULL, str, count, fmt, args); va_end(args); return len; } int pg_sprintf(char *str, const char *fmt,...) { int len; va_list args; char buffer[8192]; /* arbitrary limit */ va_start(args, fmt); len = pg_fvsnprintf(NULL, buffer, (size_t) 4096, fmt, args); va_end(args); /* limit output to string */ StrNCpy(str, buffer, (len + 1 < 8192) ? len + 1 : 8192); return len; } int pg_fprintf(FILE *stream, const char *fmt,...) { int len; va_list args; va_start(args, fmt); len = pg_fvsnprintf(stream, NULL, 0, fmt, args); va_end(args); return len; } int pg_printf(const char *fmt,...) { int len; va_list args; va_start(args, fmt); len = pg_fvsnprintf(stdout, NULL, 0, fmt, args); va_end(args); return len; } 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, FILE *stream, int *outlen); static void trailing_pad(int *padlen, char *end, char **output, FILE *stream, int *outlen); static void fmtstr(char *value, int leftjust, int minlen, int maxwidth, char *end, char **output, FILE *stream, int *outlen); static void fmtint(int64 value, int base, int dosign, int forcesign, int leftjust, int minlen, int zpad, char *end, char **output, FILE *stream, int *outlen); static void fmtfloat(double value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, char *end, char **output, FILE *stream, int *outlen); static void dostr(char *str, int cut, char *end, char **output, FILE *stream, int *outlen); static void dopr_outch(int c, char *end, char **output, FILE *stream, int *outlen); #define FMTSTR 1 #define FMTNUM 2 #define FMTNUM_U 3 #define FMTFLOAT 4 #define FMTCHAR 5 #define FMTWIDTH 6 #define FMTLEN 7 /* * dopr(): poor man's version of doprintf */ static int dopr(FILE *stream, char *buffer, const char *format, va_list args, char *end) { int ch; int longlongflag; int longflag; int pointflag; int maxwidth; int leftjust; int minlen; int zpad; int forcesign; int i; const char *format_save; const char *fmtbegin; int fmtpos = 1; int realpos = 0; int precision; int position; char *output; int nargs = 1; int outlen = 0; const char *p; struct fmtpar { const char *fmtbegin; const char *fmtend; void *value; int64 numvalue; double fvalue; int charvalue; int leftjust; int minlen; int zpad; int maxwidth; int base; int dosign; int forcesign; char type; int precision; int pointflag; char func; int realpos; int longflag; int longlongflag; } *fmtpar, **fmtparptr; /* * Create enough structures to hold all arguments. This overcounts, eg * not all '*' characters are necessarily arguments, but it's not worth * being exact. */ for (p = format; *p != '\0'; p++) if (*p == '%' || *p == '*') nargs++; /* Need to use malloc() because memory system might not be started yet. */ if ((fmtpar = malloc(sizeof(struct fmtpar) * nargs)) == NULL) { fprintf(stderr, _("out of memory\n")); exit(1); } if ((fmtparptr = malloc(sizeof(struct fmtpar *) * nargs)) == NULL) { fprintf(stderr, _("out of memory\n")); exit(1); } format_save = format; output = buffer; while ((ch = *format++)) { if (ch == '%') { leftjust = minlen = zpad = forcesign = maxwidth = 0; longflag = longlongflag = pointflag = 0; fmtbegin = format - 1; realpos = 0; position = precision = 0; nextch: ch = *format++; switch (ch) { case '\0': goto performpr; case '-': leftjust = 1; goto nextch; case '+': forcesign = 1; goto nextch; case '0': /* set zero padding if minlen not set */ if (minlen == 0 && !pointflag) zpad = '0'; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (!pointflag) { minlen = minlen * 10 + ch - '0'; position = position * 10 + ch - '0'; } else { maxwidth = maxwidth * 10 + ch - '0'; precision = precision * 10 + ch - '0'; } goto nextch; case '$': realpos = position; minlen = 0; goto nextch; case '*': MemSet(&fmtpar[fmtpos], 0, sizeof(fmtpar[fmtpos])); if (!pointflag) fmtpar[fmtpos].func = FMTLEN; else fmtpar[fmtpos].func = FMTWIDTH; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; goto nextch; case '.': pointflag = 1; goto nextch; case 'l': if (longflag) longlongflag = 1; else longflag = 1; goto nextch; case 'h': /* ignore */ goto nextch; #ifdef NOT_USED /* * We might export this to client apps so we should * support 'qd' and 'I64d'(MinGW) also in case the * native version does. */ case 'q': longlongflag = 1; longflag = 1; goto nextch; case 'I': if (*format == '6' && *(format + 1) == '4') { format += 2; longlongflag = 1; longflag = 1; goto nextch; } break; #endif case 'u': case 'U': fmtpar[fmtpos].longflag = longflag; fmtpar[fmtpos].longlongflag = longlongflag; fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].base = 10; fmtpar[fmtpos].dosign = 0; fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].leftjust = leftjust; fmtpar[fmtpos].minlen = minlen; fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].func = FMTNUM_U; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; break; case 'o': case 'O': fmtpar[fmtpos].longflag = longflag; fmtpar[fmtpos].longlongflag = longlongflag; fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].base = 8; fmtpar[fmtpos].dosign = 0; fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].leftjust = leftjust; fmtpar[fmtpos].minlen = minlen; fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].func = FMTNUM_U; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; break; case 'd': case 'D': fmtpar[fmtpos].longflag = longflag; fmtpar[fmtpos].longlongflag = longlongflag; fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].base = 10; fmtpar[fmtpos].dosign = 1; fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].leftjust = leftjust; fmtpar[fmtpos].minlen = minlen; fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].func = FMTNUM; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; break; case 'x': fmtpar[fmtpos].longflag = longflag; fmtpar[fmtpos].longlongflag = longlongflag; fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].base = 16; fmtpar[fmtpos].dosign = 0; fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].leftjust = leftjust; fmtpar[fmtpos].minlen = minlen; fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].func = FMTNUM_U; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; break; case 'X': fmtpar[fmtpos].longflag = longflag; fmtpar[fmtpos].longlongflag = longlongflag; fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].base = -16; fmtpar[fmtpos].dosign = 1; fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].leftjust = leftjust; fmtpar[fmtpos].minlen = minlen; fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].func = FMTNUM_U; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; break; case 's': fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].leftjust = leftjust; fmtpar[fmtpos].minlen = minlen; fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].maxwidth = maxwidth; fmtpar[fmtpos].func = FMTSTR; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; break; case 'c': fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].func = FMTCHAR; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; break; case 'e': case 'E': case 'f': case 'g': case 'G': fmtpar[fmtpos].fmtbegin = fmtbegin; fmtpar[fmtpos].fmtend = format; fmtpar[fmtpos].type = ch; fmtpar[fmtpos].forcesign = forcesign; fmtpar[fmtpos].leftjust = leftjust; fmtpar[fmtpos].minlen = minlen; fmtpar[fmtpos].zpad = zpad; fmtpar[fmtpos].precision = precision; fmtpar[fmtpos].pointflag = pointflag; fmtpar[fmtpos].func = FMTFLOAT; fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; fmtpos++; break; case '%': break; } } } performpr: /* 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: { 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) fmtparptr[i + 1]->maxwidth = fmtparptr[i + 1]->precision = va_arg(args, int); break; } } /* do the output */ output = buffer; format = format_save; while ((ch = *format++)) { bool skip_output = false; 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]->leftjust, fmtparptr[i]->minlen, fmtparptr[i]->maxwidth, end, (output) ? &output : NULL, stream, &outlen); break; case FMTNUM: case FMTNUM_U: fmtint(fmtparptr[i]->numvalue, fmtparptr[i]->base, fmtparptr[i]->dosign, fmtparptr[i]->forcesign, fmtparptr[i]->leftjust, fmtparptr[i]->minlen, fmtparptr[i]->zpad, end, (output) ? &output : NULL, stream, &outlen); break; case FMTFLOAT: fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type, fmtparptr[i]->forcesign, fmtparptr[i]->leftjust, fmtparptr[i]->minlen, fmtparptr[i]->zpad, fmtparptr[i]->precision, fmtparptr[i]->pointflag, end, (output) ? &output : NULL, stream, &outlen); break; case FMTCHAR: dopr_outch(fmtparptr[i]->charvalue, end, (output) ? &output : NULL, stream, &outlen); break; } format = fmtpar[i].fmtend; skip_output = true; break; } } if (!skip_output) dopr_outch(ch, end, (output) ? &output : NULL, stream, &outlen); } if (output) *output = '\0'; free(fmtpar); free(fmtparptr); return outlen; } static void fmtstr(char *value, int leftjust, int minlen, int maxwidth, char *end, char **output, FILE *stream, int *outlen) { int padlen, vallen; /* amount to pad */ if (value == NULL) value = "<NULL>"; vallen = strlen(value); if (maxwidth && vallen > maxwidth) vallen = maxwidth; adjust_padlen(minlen, vallen, leftjust, &padlen); while (padlen > 0) { dopr_outch(' ', end, output, stream, outlen); --padlen; } dostr(value, maxwidth, end, output, stream, outlen); trailing_pad(&padlen, end, output, stream, outlen); } static void fmtint(int64 value, int base, int dosign, int forcesign, int leftjust, int minlen, int zpad, char *end, char **output, FILE *stream, int *outlen) { int signvalue = 0; char convert[64]; int vallen = 0; int padlen = 0; /* amount to pad */ int caps = 0; /* 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[vallen++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") [value % (unsigned) base]; value = (value / (unsigned) base); } while (value); convert[vallen] = 0; adjust_padlen(minlen, vallen, leftjust, &padlen); leading_pad(zpad, &signvalue, &padlen, end, output, stream, outlen); while (vallen > 0) dopr_outch(convert[--vallen], end, output, stream, outlen); trailing_pad(&padlen, end, output, stream, outlen); } static void fmtfloat(double value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, char *end, char **output, FILE *stream, int *outlen) { int signvalue = 0; int vallen; char fmt[32]; char convert[512]; int padlen = 0; /* amount to pad */ /* 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 (adjust_sign((value < 0), forcesign, &signvalue)) value = -value; vallen = sprintf(convert, fmt, value); adjust_padlen(minlen, vallen, leftjust, &padlen); leading_pad(zpad, &signvalue, &padlen, end, output, stream, outlen); dostr(convert, 0, end, output, stream, outlen); trailing_pad(&padlen, end, output, stream, outlen); } static void dostr(char *str, int cut, char *end, char **output, FILE *stream, int *outlen) { if (cut) while (*str && cut-- > 0) dopr_outch(*str++, end, output, stream, outlen); else while (*str) dopr_outch(*str++, end, output, stream, outlen); } static void dopr_outch(int c, char *end, char **output, FILE *stream, int *outlen) { #ifdef NOT_USED if (iscntrl((unsigned char) c) && c != '\n' && c != '\t') { c = '@' + (c & 0x1F); if (output) { if (end == 0 || *output < end) { *(*output)++ = '^'; (*outlen)++; } } else { putc(c, stream); (*outlen)++; } } #endif if (output) { if (end == 0 || *output < end) { *(*output)++ = c; (*outlen)++; } } else { putc(c, stream); (*outlen)++; } } 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, FILE *stream, int *outlen) { if (*padlen > 0 && zpad) { if (*signvalue) { dopr_outch(*signvalue, end, output, stream, outlen); --*padlen; *signvalue = 0; } while (*padlen > 0) { dopr_outch(zpad, end, output, stream, outlen); --*padlen; } } while (*padlen > 0 + (*signvalue != 0)) { dopr_outch(' ', end, output, stream, outlen); --*padlen; } if (*signvalue) { dopr_outch(*signvalue, end, output, stream, outlen); if (*padlen > 0) --* padlen; if (padlen < 0) ++padlen; } } static void trailing_pad(int *padlen, char *end, char **output, FILE *stream, int *outlen) { while (*padlen < 0) { dopr_outch(' ', end, output, stream, outlen); ++*padlen; } } Index: src/port/snprintf.c =================================================================== RCS file: /cvsroot/pgsql/src/port/snprintf.c,v retrieving revision 1.29 diff -c -c -r1.29 snprintf.c *** src/port/snprintf.c 15 Oct 2005 02:49:51 -0000 1.29 --- src/port/snprintf.c 3 Dec 2005 05:01:16 -0000 *************** *** 64,70 **** /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.29 2005/10/15 02:49:51 momjian Exp $";*/ ! static void dopr(char *buffer, const char *format, va_list args, char *end); /* Prevent recursion */ #undef vsnprintf --- 64,70 ---- /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.29 2005/10/15 02:49:51 momjian Exp $";*/ ! static int dopr(FILE *stream, char *buffer, const char *format, va_list args, char *end); /* Prevent recursion */ #undef vsnprintf *************** *** 73,89 **** #undef fprintf #undef printf ! int ! pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args) { ! char *end; ! str[0] = '\0'; ! end = str + count - 1; ! dopr(str, fmt, args, end); ! if (count > 0) end[0] = '\0'; ! return strlen(str); } int --- 73,100 ---- #undef fprintf #undef printf ! ! static int ! pg_fvsnprintf(FILE *stream, char *str, size_t count, const char *fmt, va_list args) { ! char *end = NULL; ! int len; ! if (str) ! { ! str[0] = '\0'; ! end = str + count - 1; ! } ! len = dopr(stream, str, fmt, args, end); ! if (str && count > 0) end[0] = '\0'; ! return len; ! } ! ! int ! pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args) ! { ! return pg_fvsnprintf(NULL, str, count, fmt, args); } int *************** *** 93,99 **** va_list args; va_start(args, fmt); ! len = pg_vsnprintf(str, count, fmt, args); va_end(args); return len; } --- 104,110 ---- va_list args; va_start(args, fmt); ! len = pg_fvsnprintf(NULL, str, count, fmt, args); va_end(args); return len; } *************** *** 103,115 **** { int len; va_list args; ! char buffer[4096]; va_start(args, fmt); ! len = pg_vsnprintf(buffer, (size_t) 4096, fmt, args); va_end(args); /* limit output to string */ ! StrNCpy(str, buffer, (len + 1 < 4096) ? len + 1 : 4096); return len; } --- 114,126 ---- { int len; va_list args; ! char buffer[8192]; /* arbitrary limit */ va_start(args, fmt); ! len = pg_fvsnprintf(NULL, buffer, (size_t) 4096, fmt, args); va_end(args); /* limit output to string */ ! StrNCpy(str, buffer, (len + 1 < 8192) ? len + 1 : 8192); return len; } *************** *** 118,131 **** { int len; va_list args; - char buffer[4096]; - char *p; va_start(args, fmt); ! len = pg_vsnprintf(buffer, (size_t) 4096, fmt, args); va_end(args); - for (p = buffer; *p; p++) - putc(*p, stream); return len; } --- 129,138 ---- { int len; va_list args; va_start(args, fmt); ! len = pg_fvsnprintf(stream, NULL, 0, fmt, args); va_end(args); return len; } *************** *** 134,166 **** { int len; va_list args; - char buffer[4096]; - char *p; va_start(args, fmt); ! len = pg_vsnprintf(buffer, (size_t) 4096, fmt, args); va_end(args); - for (p = buffer; *p; p++) - putchar(*p); return len; } 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 leftjust, int minlen, int maxwidth, ! 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 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 FMTSTR 1 #define FMTNUM 2 --- 141,172 ---- { int len; va_list args; va_start(args, fmt); ! len = pg_fvsnprintf(stdout, NULL, 0, fmt, args); va_end(args); return len; } 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, FILE *stream, int *outlen); ! static void trailing_pad(int *padlen, char *end, char **output, ! FILE *stream, int *outlen); static void fmtstr(char *value, int leftjust, int minlen, int maxwidth, ! char *end, char **output, FILE *stream, int *outlen); static void fmtint(int64 value, int base, int dosign, int forcesign, ! int leftjust, int minlen, int zpad, char *end, char **output, ! FILE *stream, int *outlen); static void fmtfloat(double value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, char *end, ! char **output, FILE *stream, int *outlen); ! static void dostr(char *str, int cut, char *end, char **output, FILE *stream, ! int *outlen); ! static void dopr_outch(int c, char *end, char **output, FILE *stream, int *outlen); #define FMTSTR 1 #define FMTNUM 2 *************** *** 174,181 **** * dopr(): poor man's version of doprintf */ ! static void ! dopr(char *buffer, const char *format, va_list args, char *end) { int ch; int longlongflag; --- 180,187 ---- * dopr(): poor man's version of doprintf */ ! static int ! dopr(FILE *stream, char *buffer, const char *format, va_list args, char *end) { int ch; int longlongflag; *************** *** 195,200 **** --- 201,207 ---- int position; char *output; int nargs = 1; + int outlen = 0; const char *p; struct fmtpar { *************** *** 246,463 **** output = buffer; while ((ch = *format++)) { ! switch (ch) { ! case '%': ! leftjust = minlen = zpad = forcesign = maxwidth = 0; ! longflag = longlongflag = pointflag = 0; ! fmtbegin = format - 1; ! realpos = 0; ! position = precision = 0; ! nextch: ! ch = *format++; ! switch (ch) ! { ! case '\0': ! goto performpr; ! case '-': ! leftjust = 1; ! goto nextch; ! case '+': ! forcesign = 1; ! goto nextch; ! case '0': /* set zero padding if minlen not set */ ! if (minlen == 0 && !pointflag) ! zpad = '0'; ! case '1': ! case '2': ! case '3': ! case '4': ! case '5': ! case '6': ! case '7': ! case '8': ! case '9': ! if (!pointflag) ! { ! minlen = minlen * 10 + ch - '0'; ! position = position * 10 + ch - '0'; ! } ! else ! { ! maxwidth = maxwidth * 10 + ch - '0'; ! precision = precision * 10 + ch - '0'; ! } ! goto nextch; ! case '$': ! realpos = position; ! minlen = 0; ! goto nextch; ! case '*': ! MemSet(&fmtpar[fmtpos], 0, sizeof(fmtpar[fmtpos])); ! if (!pointflag) ! fmtpar[fmtpos].func = FMTLEN; ! else ! fmtpar[fmtpos].func = FMTWIDTH; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! goto nextch; ! case '.': ! pointflag = 1; ! goto nextch; ! case 'l': ! if (longflag) ! longlongflag = 1; ! else ! longflag = 1; ! goto nextch; ! case 'h': ! /* ignore */ ! goto nextch; #ifdef NOT_USED ! /* ! * We might export this to client apps so we should ! * support 'qd' and 'I64d'(MinGW) also in case the ! * native version does. ! */ ! case 'q': longlongflag = 1; longflag = 1; goto nextch; ! case 'I': ! if (*format == '6' && *(format + 1) == '4') ! { ! format += 2; ! longlongflag = 1; ! longflag = 1; ! goto nextch; ! } ! break; #endif ! case 'u': ! case 'U': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = 10; ! fmtpar[fmtpos].dosign = 0; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM_U; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'o': ! case 'O': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = 8; ! fmtpar[fmtpos].dosign = 0; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM_U; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'd': ! case 'D': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = 10; ! fmtpar[fmtpos].dosign = 1; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'x': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = 16; ! fmtpar[fmtpos].dosign = 0; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM_U; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'X': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = -16; ! fmtpar[fmtpos].dosign = 1; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM_U; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 's': ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].maxwidth = maxwidth; ! fmtpar[fmtpos].func = FMTSTR; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'c': ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].func = FMTCHAR; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'e': ! case 'E': ! case 'f': ! case 'g': ! case 'G': ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].type = ch; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].precision = precision; ! fmtpar[fmtpos].pointflag = pointflag; ! fmtpar[fmtpos].func = FMTFLOAT; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case '%': ! break; ! default: ! dostr("???????", 0, end, &output); ! } ! break; ! default: ! dopr_outch(ch, end, &output); ! break; } } --- 253,463 ---- output = buffer; while ((ch = *format++)) { ! if (ch == '%') { ! leftjust = minlen = zpad = forcesign = maxwidth = 0; ! longflag = longlongflag = pointflag = 0; ! fmtbegin = format - 1; ! realpos = 0; ! position = precision = 0; ! nextch: ! ch = *format++; ! switch (ch) ! { ! case '\0': ! goto performpr; ! case '-': ! leftjust = 1; ! goto nextch; ! case '+': ! forcesign = 1; ! goto nextch; ! case '0': /* set zero padding if minlen not set */ ! if (minlen == 0 && !pointflag) ! zpad = '0'; ! case '1': ! case '2': ! case '3': ! case '4': ! case '5': ! case '6': ! case '7': ! case '8': ! case '9': ! if (!pointflag) ! { ! minlen = minlen * 10 + ch - '0'; ! position = position * 10 + ch - '0'; ! } ! else ! { ! maxwidth = maxwidth * 10 + ch - '0'; ! precision = precision * 10 + ch - '0'; ! } ! goto nextch; ! case '$': ! realpos = position; ! minlen = 0; ! goto nextch; ! case '*': ! MemSet(&fmtpar[fmtpos], 0, sizeof(fmtpar[fmtpos])); ! if (!pointflag) ! fmtpar[fmtpos].func = FMTLEN; ! else ! fmtpar[fmtpos].func = FMTWIDTH; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! goto nextch; ! case '.': ! pointflag = 1; ! goto nextch; ! case 'l': ! if (longflag) ! longlongflag = 1; ! else ! longflag = 1; ! goto nextch; ! case 'h': ! /* ignore */ ! goto nextch; #ifdef NOT_USED ! /* ! * We might export this to client apps so we should ! * support 'qd' and 'I64d'(MinGW) also in case the ! * native version does. ! */ ! case 'q': ! longlongflag = 1; ! longflag = 1; ! goto nextch; ! case 'I': ! if (*format == '6' && *(format + 1) == '4') ! { ! format += 2; longlongflag = 1; longflag = 1; goto nextch; ! } ! break; #endif ! case 'u': ! case 'U': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = 10; ! fmtpar[fmtpos].dosign = 0; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM_U; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'o': ! case 'O': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = 8; ! fmtpar[fmtpos].dosign = 0; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM_U; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'd': ! case 'D': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = 10; ! fmtpar[fmtpos].dosign = 1; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'x': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = 16; ! fmtpar[fmtpos].dosign = 0; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM_U; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'X': ! fmtpar[fmtpos].longflag = longflag; ! fmtpar[fmtpos].longlongflag = longlongflag; ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].base = -16; ! fmtpar[fmtpos].dosign = 1; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].func = FMTNUM_U; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 's': ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].maxwidth = maxwidth; ! fmtpar[fmtpos].func = FMTSTR; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'c': ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].func = FMTCHAR; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case 'e': ! case 'E': ! case 'f': ! case 'g': ! case 'G': ! fmtpar[fmtpos].fmtbegin = fmtbegin; ! fmtpar[fmtpos].fmtend = format; ! fmtpar[fmtpos].type = ch; ! fmtpar[fmtpos].forcesign = forcesign; ! fmtpar[fmtpos].leftjust = leftjust; ! fmtpar[fmtpos].minlen = minlen; ! fmtpar[fmtpos].zpad = zpad; ! fmtpar[fmtpos].precision = precision; ! fmtpar[fmtpos].pointflag = pointflag; ! fmtpar[fmtpos].func = FMTFLOAT; ! fmtpar[fmtpos].realpos = realpos ? realpos : fmtpos; ! fmtpos++; ! break; ! case '%': ! break; ! } } } *************** *** 538,543 **** --- 538,545 ---- format = format_save; while ((ch = *format++)) { + bool skip_output = false; + for (i = 1; i < fmtpos; i++) { if (ch == '%' && *format == '%') *************** *** 552,596 **** case FMTSTR: fmtstr(fmtparptr[i]->value, fmtparptr[i]->leftjust, fmtparptr[i]->minlen, fmtparptr[i]->maxwidth, ! end, &output); break; case FMTNUM: case FMTNUM_U: fmtint(fmtparptr[i]->numvalue, fmtparptr[i]->base, fmtparptr[i]->dosign, fmtparptr[i]->forcesign, 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]->leftjust, fmtparptr[i]->minlen, fmtparptr[i]->zpad, fmtparptr[i]->precision, fmtparptr[i]->pointflag, ! end, &output); break; case FMTCHAR: ! dopr_outch(fmtparptr[i]->charvalue, end, &output); break; } format = fmtpar[i].fmtend; ! goto nochar; } } ! dopr_outch(ch, end, &output); ! nochar: ! /* nothing */ ! ; /* semicolon required because a goto has to be ! * attached to a statement */ } ! *output = '\0'; free(fmtpar); free(fmtparptr); } static void fmtstr(char *value, int leftjust, int minlen, int maxwidth, char *end, ! char **output) { int padlen, vallen; /* amount to pad */ --- 554,601 ---- case FMTSTR: fmtstr(fmtparptr[i]->value, fmtparptr[i]->leftjust, fmtparptr[i]->minlen, fmtparptr[i]->maxwidth, ! end, (output) ? &output : NULL, stream, &outlen); break; case FMTNUM: case FMTNUM_U: fmtint(fmtparptr[i]->numvalue, fmtparptr[i]->base, fmtparptr[i]->dosign, fmtparptr[i]->forcesign, fmtparptr[i]->leftjust, fmtparptr[i]->minlen, ! fmtparptr[i]->zpad, end, ! (output) ? &output : NULL, stream, &outlen); break; case FMTFLOAT: fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type, fmtparptr[i]->forcesign, fmtparptr[i]->leftjust, fmtparptr[i]->minlen, fmtparptr[i]->zpad, fmtparptr[i]->precision, fmtparptr[i]->pointflag, ! end, (output) ? &output : NULL, stream, &outlen); break; case FMTCHAR: ! dopr_outch(fmtparptr[i]->charvalue, end, ! (output) ? &output : NULL, stream, &outlen); break; } format = fmtpar[i].fmtend; ! skip_output = true; ! break; } } ! if (!skip_output) ! dopr_outch(ch, end, (output) ? &output : NULL, stream, &outlen); } ! if (output) ! *output = '\0'; free(fmtpar); free(fmtparptr); + + return outlen; } static void fmtstr(char *value, int leftjust, int minlen, int maxwidth, char *end, ! char **output, FILE *stream, int *outlen) { int padlen, vallen; /* amount to pad */ *************** *** 606,622 **** while (padlen > 0) { ! dopr_outch(' ', end, output); --padlen; } ! dostr(value, maxwidth, end, output); ! trailing_pad(&padlen, end, output); } static void fmtint(int64 value, int base, int dosign, int forcesign, int leftjust, ! int minlen, int zpad, char *end, char **output) { int signvalue = 0; char convert[64]; --- 611,628 ---- while (padlen > 0) { ! dopr_outch(' ', end, output, stream, outlen); --padlen; } ! dostr(value, maxwidth, end, output, stream, outlen); ! trailing_pad(&padlen, end, output, stream, outlen); } static void fmtint(int64 value, int base, int dosign, int forcesign, int leftjust, ! int minlen, int zpad, char *end, char **output, FILE *stream, ! int *outlen) { int signvalue = 0; char convert[64]; *************** *** 644,661 **** 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 leftjust, int minlen, int zpad, int precision, int pointflag, char *end, ! char **output) { int signvalue = 0; int vallen; --- 650,667 ---- adjust_padlen(minlen, vallen, leftjust, &padlen); ! leading_pad(zpad, &signvalue, &padlen, end, output, stream, outlen); while (vallen > 0) ! dopr_outch(convert[--vallen], end, output, stream, outlen); ! trailing_pad(&padlen, end, output, stream, outlen); } static void fmtfloat(double value, char type, int forcesign, int leftjust, int minlen, int zpad, int precision, int pointflag, char *end, ! char **output, FILE *stream, int *outlen) { int signvalue = 0; int vallen; *************** *** 676,712 **** adjust_padlen(minlen, vallen, leftjust, &padlen); ! leading_pad(zpad, &signvalue, &padlen, end, output); ! dostr(convert, 0, end, output); ! trailing_pad(&padlen, end, output); } static void ! dostr(char *str, int cut, char *end, char **output) { if (cut) while (*str && cut-- > 0) ! dopr_outch(*str++, end, output); else while (*str) ! dopr_outch(*str++, end, output); } static void ! dopr_outch(int c, char *end, char **output) { #ifdef NOT_USED if (iscntrl((unsigned char) c) && c != '\n' && c != '\t') { c = '@' + (c & 0x1F); ! if (end == 0 || *output < end) ! *(*output)++ = '^'; } #endif ! if (end == 0 || *output < end) ! *(*output)++ = c; } --- 682,740 ---- adjust_padlen(minlen, vallen, leftjust, &padlen); ! leading_pad(zpad, &signvalue, &padlen, end, output, stream, outlen); ! dostr(convert, 0, end, output, stream, outlen); ! trailing_pad(&padlen, end, output, stream, outlen); } static void ! dostr(char *str, int cut, char *end, char **output, FILE *stream, int *outlen) { if (cut) while (*str && cut-- > 0) ! dopr_outch(*str++, end, output, stream, outlen); else while (*str) ! dopr_outch(*str++, end, output, stream, outlen); } static void ! dopr_outch(int c, char *end, char **output, FILE *stream, int *outlen) { #ifdef NOT_USED if (iscntrl((unsigned char) c) && c != '\n' && c != '\t') { c = '@' + (c & 0x1F); ! if (output) ! { ! if (end == 0 || *output < end) ! { ! *(*output)++ = '^'; ! (*outlen)++; ! } ! } ! else ! { ! putc(c, stream); ! (*outlen)++; ! } } #endif ! if (output) ! { ! if (end == 0 || *output < end) ! { ! *(*output)++ = c; ! (*outlen)++; ! } ! } ! else ! { ! putc(c, stream); ! (*outlen)++; ! } } *************** *** 736,765 **** 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) --- 764,794 ---- static void ! leading_pad(int zpad, int *signvalue, int *padlen, char *end, char **output, ! FILE *stream, int *outlen) { if (*padlen > 0 && zpad) { if (*signvalue) { ! dopr_outch(*signvalue, end, output, stream, outlen); --*padlen; *signvalue = 0; } while (*padlen > 0) { ! dopr_outch(zpad, end, output, stream, outlen); --*padlen; } } while (*padlen > 0 + (*signvalue != 0)) { ! dopr_outch(' ', end, output, stream, outlen); --*padlen; } if (*signvalue) { ! dopr_outch(*signvalue, end, output, stream, outlen); if (*padlen > 0) --* padlen; if (padlen < 0) *************** *** 769,779 **** static void ! trailing_pad(int *padlen, char *end, char **output) { while (*padlen < 0) { ! dopr_outch(' ', end, output); ++*padlen; } } --- 798,808 ---- static void ! trailing_pad(int *padlen, char *end, char **output, FILE *stream, int *outlen) { while (*padlen < 0) { ! dopr_outch(' ', end, output, stream, outlen); ++*padlen; } }
pgsql-patches by date: