Thread: Repleacement for src/port/snprintf.c
Greetings, I would like to submit my changes to src/port/snprintf.c to enable %n$ format placeholder replacement in snprintf() and vsnprintf(). Additionally I implemented a trivial printf(). I also attach a diff for configure.in to include snprintf.o in pgport but I am sure it is not the right thing to do. Could someone give a hint on where I need to place such a definition. Best regards, Nicolai Tufar
Attachment
Hello all, I would like to submit my changes to src/port/snprintf.c to enable %n$ format placeholder replacement in snprintf() and vsnprintf(). Additionally I implemented a trivial printf(). I also attach a diff for configure.in to include snprintf.o in pgport but I am sure it is not the right thing to do. Could someone give a hint on where I need to place such a definition. Please review my patch. as Tom Lane pointed out there are 150 messages in the following files that do not print properly: src/backend/po/pt_BR.po src/backend/po/de.po src/backend/po/es.po src/backend/po/zh_CN.po src/backend/po/tr.po src/bin/pg_dump/po/zh_CN.po src/bin/pg_dump/po/tr.po src/bin/psql/po/zh_CN.po src/bin/psql/po/zh_TW.po src/bin/psql/po/tr.po src/bin/scripts/po/zh_CN.po we need to fix snprintf.c before next release Best regards, Nicolai Tufar
Attachment
Nicolai Tufar wrote: > Hello all, > > I would like to submit my changes to src/port/snprintf.c to > enable %n$ format placeholder replacement in snprintf() and > vsnprintf(). Additionally I implemented a trivial printf(). > > I also attach a diff for configure.in to include snprintf.o > in pgport but I am sure it is not the right thing to do. > Could someone give a hint on where I need to place such a > definition. > > Please review my patch. as Tom Lane pointed out there > are 150 messages in the following files that do not print > properly: It took me a while to understand this but I get it now. This is the best explanation I have seen, from Linux 2.6: One can also specify explicitly which argument is taken, at each place where an argument is required, by writing '%m$' instead of '%' and '*m$' instead of '*', where the decimal integer m denotes the position in the argument list of the desired argument, indexed starting from 1. Thus, printf("%*d", width, num); and printf("%2$*1$d", width, num); are equivalent. The second style allows repeated references to the same argument. The C99 standard does not include the style using '$', which comes from the Single Unix Specification. If the style using '$' is used, it must be used throughout for all conversions taking an argument and all width and precision arguments, but it may be mixed with '%%' formats which do not consume an argument. There may be no gaps in the numbers of arguments specified using '$'; for example, if arguments 1 and 3 are specified, argument 2 must also be specified somewhere in the format string. I can see why this would be useful for translations because it uncouples the order of the printf arguments from the printf string. However, I have learned that Win32, HP-UX, NetBSD 2.0, and BSD/OS do not support this. This is probably because it is not in C99 but in SUS (see above). Anyway, this is too large to put into 8.0, but I am attaching a patch for 8.1 that has the proper configure tests to check if the C library supports this behavior. If it does not, the build will use our port/snprintf.c. One problem with that is that our snprintf.c is not thread-safe. Seems the increases use of it will require us to fix this soon. I have added to TODO: * Make src/port/snprintf.c thread-safe One change to the original port is that there was a define of a union with no name: + union{ + void* value; + long_long numvalue; + double fvalue; + int charvalue; + }; As far as I know a union with no name is illegal. I just removed the "union {" and the closing brace. -- 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 Index: configure =================================================================== RCS file: /cvsroot/pgsql/configure,v retrieving revision 1.425 diff -c -c -r1.425 configure *** configure 18 Jan 2005 05:23:35 -0000 1.425 --- configure 13 Feb 2005 23:50:46 -0000 *************** *** 12162,12167 **** --- 12162,12224 ---- done + echo "$as_me:$LINENO: checking printf supports argument control" >&5 + echo $ECHO_N "checking printf supports argument control... $ECHO_C" >&6 + if test "${pgac_cv_printf_arg_control+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + if test "$cross_compiling" = yes; then + pgac_cv_printf_arg_control=cross + else + cat >conftest.$ac_ext <<_ACEOF + #line $LINENO "configure" + #include "confdefs.h" + #include <stdio.h> + + int does_printf_have_arg_control() + { + char buf[100]; + + /* can it swap arguments? */ + snprintf(buf, 100, "%2$d|%1$d", 3, 4); + if (strcmp(buf, "4|3") != 0) + return 0; + return 1; + } + main() { + exit(! does_printf_have_arg_control()); + } + _ACEOF + rm -f conftest$ac_exeext + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pgac_cv_printf_arg_control=yes + else + echo "$as_me: program exited with status $ac_status" >&5 + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ( exit $ac_status ) + pgac_cv_printf_arg_control=no + fi + rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext + fi + + fi + echo "$as_me:$LINENO: result: $pgac_cv_printf_arg_control" >&5 + echo "${ECHO_T}$pgac_cv_printf_arg_control" >&6 + + # cross compiler should use our snprintf too + if test $pgac_cv_printf_arg_control != yes ; then + pgac_need_repl_snprintf=yes + fi # Check whether <stdio.h> declares snprintf() and vsnprintf(); if not, # include/c.h will provide declarations. Note this is a separate test Index: configure.in =================================================================== RCS file: /cvsroot/pgsql/configure.in,v retrieving revision 1.399 diff -c -c -r1.399 configure.in *** configure.in 18 Jan 2005 05:23:36 -0000 1.399 --- configure.in 13 Feb 2005 23:50:47 -0000 *************** *** 881,886 **** --- 881,891 ---- AC_CHECK_FUNCS(snprintf, [], pgac_need_repl_snprintf=yes) AC_CHECK_FUNCS(vsnprintf, [], pgac_need_repl_snprintf=yes) + PGAC_FUNC_PRINTF_ARG_CONTROL + # cross compiler should use our snprintf too + if test $pgac_cv_printf_arg_control != yes ; then + pgac_need_repl_snprintf=yes + fi # Check whether <stdio.h> declares snprintf() and vsnprintf(); if not, # include/c.h will provide declarations. Note this is a separate test *************** *** 1069,1074 **** --- 1074,1081 ---- [AC_MSG_RESULT([cross-compiling])]) + dnl 64-bit section + dnl dnl Check to see if we have a working 64-bit integer type. dnl This breaks down into two steps: dnl (1) figure out if the compiler has a 64-bit int type with working Index: config/c-library.m4 =================================================================== RCS file: /cvsroot/pgsql/config/c-library.m4,v retrieving revision 1.29 diff -c -c -r1.29 c-library.m4 *** config/c-library.m4 16 Dec 2004 17:48:26 -0000 1.29 --- config/c-library.m4 13 Feb 2005 23:50:48 -0000 *************** *** 266,268 **** --- 266,301 ---- LONG_LONG_INT_FORMAT=$pgac_cv_snprintf_long_long_int_format;; *) AC_MSG_RESULT(none);; esac])# PGAC_FUNC_SNPRINTF_LONG_LONG_INT_FORMAT + + + # PGAC_FUNC_PRINTF_ARG_CONTROL + # --------------------------------------- + # 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. + # + AC_DEFUN([PGAC_FUNC_PRINTF_ARG_CONTROL], + [AC_MSG_CHECKING([printf supports argument control]) + AC_CACHE_VAL(pgac_cv_printf_arg_control, + [AC_TRY_RUN([#include <stdio.h> + + int does_printf_have_arg_control() + { + char buf[100]; + + /* can it swap arguments? */ + snprintf(buf, 100, "%2$d|%1$d", 3, 4); + if (strcmp(buf, "4|3") != 0) + return 0; + return 1; + } + main() { + exit(! does_printf_have_arg_control()); + }], + [pgac_cv_printf_arg_control=yes], + [pgac_cv_printf_arg_control=no], + [pgac_cv_printf_arg_control=cross]) + ])dnl AC_CACHE_VAL + AC_MSG_RESULT([$pgac_cv_printf_arg_control]) + ])# PGAC_FUNC_PRINTF_ARG_CONTROL Index: src/port/snprintf.c =================================================================== RCS file: /cvsroot/pgsql/src/port/snprintf.c,v retrieving revision 1.4 diff -c -c -r1.4 snprintf.c *** src/port/snprintf.c 29 Aug 2004 05:07:02 -0000 1.4 --- src/port/snprintf.c 13 Feb 2005 23:50:56 -0000 *************** *** 57,62 **** --- 57,66 ---- typedef unsigned long ulong_long; #endif + #ifndef NL_ARGMAX + #define NL_ARGMAX 4096 + #endif + /* ** SNPRINTF, VSNPRINT -- counted versions of printf ** *************** *** 85,93 **** --- 89,115 ---- 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,129 **** --- 146,155 ---- 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,145 **** --- 165,198 ---- 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,161 **** case '%': ljust = len = zpad = maxwidth = 0; longflag = longlongflag = pointflag = 0; nextch: ch = *format++; switch (ch) { case 0: ! dostr("**end of format**", 0); ! *output = '\0'; ! return; case '-': ljust = 1; goto nextch; --- 201,215 ---- case '%': ljust = len = zpad = maxwidth = 0; longflag = longlongflag = pointflag = 0; + fmtbegin = format - 1; + realpos = 0; + position = 0; nextch: ch = *format++; switch (ch) { case 0: ! goto performpr; case '-': ljust = 1; goto nextch; *************** *** 174,180 **** --- 228,241 ---- 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,209 **** } else value = va_arg(args, unsigned int); ! fmtnum(value, 10, 0, ljust, len, zpad); break; case 'o': case 'O': --- 264,280 ---- } else value = va_arg(args, unsigned int); ! 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,223 **** } else value = va_arg(args, unsigned int); ! fmtnum(value, 8, 0, ljust, len, zpad); break; case 'd': case 'D': --- 288,304 ---- } else value = va_arg(args, unsigned int); ! 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,236 **** } else value = va_arg(args, int); ! fmtnum(value, 10, 1, ljust, len, zpad); break; case 'x': if (longflag) --- 311,327 ---- } else value = va_arg(args, int); ! 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,248 **** } else value = va_arg(args, unsigned int); ! fmtnum(value, 16, 0, ljust, len, zpad); break; case 'X': if (longflag) --- 333,349 ---- } else value = va_arg(args, unsigned int); ! 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,260 **** } else value = va_arg(args, unsigned int); ! fmtnum(value, -16, 0, ljust, len, zpad); break; case 's': strvalue = va_arg(args, char *); --- 355,371 ---- } else value = va_arg(args, unsigned int); ! 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,273 **** { if (pointflag && len > maxwidth) len = maxwidth; /* Adjust padding */ ! fmtstr(strvalue, ljust, len, zpad, maxwidth); } break; case 'c': ch = va_arg(args, int); ! dopr_outch(ch); break; case 'e': case 'E': --- 373,398 ---- { 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++; } 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++; break; case 'e': case 'E': *************** *** 275,285 **** case 'g': case 'G': fvalue = va_arg(args, double); ! fmtfloat(fvalue, ch, ljust, len, maxwidth, pointflag); break; case '%': ! dopr_outch(ch); ! continue; default: dostr("???????", 0); } --- 400,419 ---- 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].pointflag = pointflag; ! fmtpar[fmtpos].func = FMTFLOAT; ! fmtpar[fmtpos].realpos = realpos?realpos:fmtpos; ! fmtpos++; break; case '%': ! break; default: dostr("???????", 0); } *************** *** 289,294 **** --- 423,475 ---- 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'; }
On Sun, 13 Feb 2005 19:06:34 -0500 (EST), Bruce Momjian <pgman@candle.pha.pa.us> wrote: > Anyway, this is too large to put into 8.0, but I am attaching a patch > for 8.1 that has the proper configure tests to check if the C library > supports this behavior. If it does not, the build will use our > port/snprintf.c. > One problem with that is that our snprintf.c is not thread-safe. Seems > the increases use of it will require us to fix this soon. I have added > to TODO: > > * Make src/port/snprintf.c thread-safe Okay, I am applying your patch to CVS HEAD and getting hands on making snprintf.c thread-safe. I will submit a roll up pathch in a day or two. Regards, Nicolai
Applied. --------------------------------------------------------------------------- Bruce Momjian wrote: > Nicolai Tufar wrote: > > Hello all, > > > > I would like to submit my changes to src/port/snprintf.c to > > enable %n$ format placeholder replacement in snprintf() and > > vsnprintf(). Additionally I implemented a trivial printf(). > > > > I also attach a diff for configure.in to include snprintf.o > > in pgport but I am sure it is not the right thing to do. > > Could someone give a hint on where I need to place such a > > definition. > > > > Please review my patch. as Tom Lane pointed out there > > are 150 messages in the following files that do not print > > properly: > > It took me a while to understand this but I get it now. This is the > best explanation I have seen, from Linux 2.6: > > One can also specify explicitly which argument is taken, at each place > where an argument is required, by writing '%m$' instead of '%' and '*m$' > instead of '*', where the decimal integer m denotes the position in the > argument list of the desired argument, indexed starting from 1. Thus, > > printf("%*d", width, num); > > and > > printf("%2$*1$d", width, num); > > are equivalent. The second style allows repeated references to the > same argument. The C99 standard does not include the style using '$', > which comes from the Single Unix Specification. If the style using '$' > is used, it must be used throughout for all conversions taking an > argument and all width and precision arguments, but it may be mixed with > '%%' formats which do not consume an argument. There may be no gaps in > the numbers of arguments specified using '$'; for example, if > arguments 1 and 3 are specified, argument 2 must also be specified > somewhere in the format string. > > I can see why this would be useful for translations because it uncouples > the order of the printf arguments from the printf string. However, I > have learned that Win32, HP-UX, NetBSD 2.0, and BSD/OS do not support > this. This is probably because it is not in C99 but in SUS (see above). > > Anyway, this is too large to put into 8.0, but I am attaching a patch > for 8.1 that has the proper configure tests to check if the C library > supports this behavior. If it does not, the build will use our > port/snprintf.c. > > One problem with that is that our snprintf.c is not thread-safe. Seems > the increases use of it will require us to fix this soon. I have added > to TODO: > > * Make src/port/snprintf.c thread-safe > > One change to the original port is that there was a define of a union > with no name: > > + union{ > + void* value; > + long_long numvalue; > + double fvalue; > + int charvalue; > + }; > > As far as I know a union with no name is illegal. I just removed the > "union {" and the closing brace. > > -- > 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 > Index: configure > =================================================================== > RCS file: /cvsroot/pgsql/configure,v > retrieving revision 1.425 > diff -c -c -r1.425 configure > *** configure 18 Jan 2005 05:23:35 -0000 1.425 > --- configure 13 Feb 2005 23:50:46 -0000 > *************** > *** 12162,12167 **** > --- 12162,12224 ---- > done > > > + echo "$as_me:$LINENO: checking printf supports argument control" >&5 > + echo $ECHO_N "checking printf supports argument control... $ECHO_C" >&6 > + if test "${pgac_cv_printf_arg_control+set}" = set; then > + echo $ECHO_N "(cached) $ECHO_C" >&6 > + else > + if test "$cross_compiling" = yes; then > + pgac_cv_printf_arg_control=cross > + else > + cat >conftest.$ac_ext <<_ACEOF > + #line $LINENO "configure" > + #include "confdefs.h" > + #include <stdio.h> > + > + int does_printf_have_arg_control() > + { > + char buf[100]; > + > + /* can it swap arguments? */ > + snprintf(buf, 100, "%2$d|%1$d", 3, 4); > + if (strcmp(buf, "4|3") != 0) > + return 0; > + return 1; > + } > + main() { > + exit(! does_printf_have_arg_control()); > + } > + _ACEOF > + rm -f conftest$ac_exeext > + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 > + (eval $ac_link) 2>&5 > + ac_status=$? > + echo "$as_me:$LINENO: \$? = $ac_status" >&5 > + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' > + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 > + (eval $ac_try) 2>&5 > + ac_status=$? > + echo "$as_me:$LINENO: \$? = $ac_status" >&5 > + (exit $ac_status); }; }; then > + pgac_cv_printf_arg_control=yes > + else > + echo "$as_me: program exited with status $ac_status" >&5 > + echo "$as_me: failed program was:" >&5 > + cat conftest.$ac_ext >&5 > + ( exit $ac_status ) > + pgac_cv_printf_arg_control=no > + fi > + rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext > + fi > + > + fi > + echo "$as_me:$LINENO: result: $pgac_cv_printf_arg_control" >&5 > + echo "${ECHO_T}$pgac_cv_printf_arg_control" >&6 > + > + # cross compiler should use our snprintf too > + if test $pgac_cv_printf_arg_control != yes ; then > + pgac_need_repl_snprintf=yes > + fi > > # Check whether <stdio.h> declares snprintf() and vsnprintf(); if not, > # include/c.h will provide declarations. Note this is a separate test > Index: configure.in > =================================================================== > RCS file: /cvsroot/pgsql/configure.in,v > retrieving revision 1.399 > diff -c -c -r1.399 configure.in > *** configure.in 18 Jan 2005 05:23:36 -0000 1.399 > --- configure.in 13 Feb 2005 23:50:47 -0000 > *************** > *** 881,886 **** > --- 881,891 ---- > AC_CHECK_FUNCS(snprintf, [], pgac_need_repl_snprintf=yes) > AC_CHECK_FUNCS(vsnprintf, [], pgac_need_repl_snprintf=yes) > > + PGAC_FUNC_PRINTF_ARG_CONTROL > + # cross compiler should use our snprintf too > + if test $pgac_cv_printf_arg_control != yes ; then > + pgac_need_repl_snprintf=yes > + fi > > # Check whether <stdio.h> declares snprintf() and vsnprintf(); if not, > # include/c.h will provide declarations. Note this is a separate test > *************** > *** 1069,1074 **** > --- 1074,1081 ---- > [AC_MSG_RESULT([cross-compiling])]) > > > + dnl 64-bit section > + dnl > dnl Check to see if we have a working 64-bit integer type. > dnl This breaks down into two steps: > dnl (1) figure out if the compiler has a 64-bit int type with working > Index: config/c-library.m4 > =================================================================== > RCS file: /cvsroot/pgsql/config/c-library.m4,v > retrieving revision 1.29 > diff -c -c -r1.29 c-library.m4 > *** config/c-library.m4 16 Dec 2004 17:48:26 -0000 1.29 > --- config/c-library.m4 13 Feb 2005 23:50:48 -0000 > *************** > *** 266,268 **** > --- 266,301 ---- > LONG_LONG_INT_FORMAT=$pgac_cv_snprintf_long_long_int_format;; > *) AC_MSG_RESULT(none);; > esac])# PGAC_FUNC_SNPRINTF_LONG_LONG_INT_FORMAT > + > + > + # PGAC_FUNC_PRINTF_ARG_CONTROL > + # --------------------------------------- > + # 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. > + # > + AC_DEFUN([PGAC_FUNC_PRINTF_ARG_CONTROL], > + [AC_MSG_CHECKING([printf supports argument control]) > + AC_CACHE_VAL(pgac_cv_printf_arg_control, > + [AC_TRY_RUN([#include <stdio.h> > + > + int does_printf_have_arg_control() > + { > + char buf[100]; > + > + /* can it swap arguments? */ > + snprintf(buf, 100, "%2$d|%1$d", 3, 4); > + if (strcmp(buf, "4|3") != 0) > + return 0; > + return 1; > + } > + main() { > + exit(! does_printf_have_arg_control()); > + }], > + [pgac_cv_printf_arg_control=yes], > + [pgac_cv_printf_arg_control=no], > + [pgac_cv_printf_arg_control=cross]) > + ])dnl AC_CACHE_VAL > + AC_MSG_RESULT([$pgac_cv_printf_arg_control]) > + ])# PGAC_FUNC_PRINTF_ARG_CONTROL > Index: src/port/snprintf.c > =================================================================== > RCS file: /cvsroot/pgsql/src/port/snprintf.c,v > retrieving revision 1.4 > diff -c -c -r1.4 snprintf.c > *** src/port/snprintf.c 29 Aug 2004 05:07:02 -0000 1.4 > --- src/port/snprintf.c 13 Feb 2005 23:50:56 -0000 > *************** > *** 57,62 **** > --- 57,66 ---- > typedef unsigned long ulong_long; > #endif > > + #ifndef NL_ARGMAX > + #define NL_ARGMAX 4096 > + #endif > + > /* > ** SNPRINTF, VSNPRINT -- counted versions of printf > ** > *************** > *** 85,93 **** > --- 89,115 ---- > > 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,129 **** > --- 146,155 ---- > > 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,145 **** > --- 165,198 ---- > 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,161 **** > case '%': > ljust = len = zpad = maxwidth = 0; > longflag = longlongflag = pointflag = 0; > nextch: > ch = *format++; > switch (ch) > { > case 0: > ! dostr("**end of format**", 0); > ! *output = '\0'; > ! return; > case '-': > ljust = 1; > goto nextch; > --- 201,215 ---- > case '%': > ljust = len = zpad = maxwidth = 0; > longflag = longlongflag = pointflag = 0; > + fmtbegin = format - 1; > + realpos = 0; > + position = 0; > nextch: > ch = *format++; > switch (ch) > { > case 0: > ! goto performpr; > case '-': > ljust = 1; > goto nextch; > *************** > *** 174,180 **** > --- 228,241 ---- > 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,209 **** > } > else > value = va_arg(args, unsigned int); > ! fmtnum(value, 10, 0, ljust, len, zpad); > break; > case 'o': > case 'O': > --- 264,280 ---- > } > else > value = va_arg(args, unsigned int); > ! 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,223 **** > } > else > value = va_arg(args, unsigned int); > ! fmtnum(value, 8, 0, ljust, len, zpad); > break; > case 'd': > case 'D': > --- 288,304 ---- > } > else > value = va_arg(args, unsigned int); > ! 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,236 **** > } > else > value = va_arg(args, int); > ! fmtnum(value, 10, 1, ljust, len, zpad); > break; > case 'x': > if (longflag) > --- 311,327 ---- > } > else > value = va_arg(args, int); > ! 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,248 **** > } > else > value = va_arg(args, unsigned int); > ! fmtnum(value, 16, 0, ljust, len, zpad); > break; > case 'X': > if (longflag) > --- 333,349 ---- > } > else > value = va_arg(args, unsigned int); > ! 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,260 **** > } > else > value = va_arg(args, unsigned int); > ! fmtnum(value, -16, 0, ljust, len, zpad); > break; > case 's': > strvalue = va_arg(args, char *); > --- 355,371 ---- > } > else > value = va_arg(args, unsigned int); > ! 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,273 **** > { > if (pointflag && len > maxwidth) > len = maxwidth; /* Adjust padding */ > ! fmtstr(strvalue, ljust, len, zpad, maxwidth); > } > break; > case 'c': > ch = va_arg(args, int); > ! dopr_outch(ch); > break; > case 'e': > case 'E': > --- 373,398 ---- > { > 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++; > } > 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++; > break; > case 'e': > case 'E': > *************** > *** 275,285 **** > case 'g': > case 'G': > fvalue = va_arg(args, double); > ! fmtfloat(fvalue, ch, ljust, len, maxwidth, pointflag); > break; > case '%': > ! dopr_outch(ch); > ! continue; > default: > dostr("???????", 0); > } > --- 400,419 ---- > 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].pointflag = pointflag; > ! fmtpar[fmtpos].func = FMTFLOAT; > ! fmtpar[fmtpos].realpos = realpos?realpos:fmtpos; > ! fmtpos++; > break; > case '%': > ! break; > default: > dostr("???????", 0); > } > *************** > *** 289,294 **** > --- 423,475 ---- > 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'; > } > > > ---------------------------(end of broadcast)--------------------------- > TIP 2: you can get off all lists at once with the unregister command > (send "unregister YourEmailAddressHere" to majordomo@postgresql.org) -- 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
> On Mon, Feb 21, 2005 at 10:53:08PM -0500, Bruce Momjian wrote: > > Applied. Thanks a lot. The patch attached solves the tread safety problem. Please review it before applying, I am not sure I am doing the right thing On Tue, 22 Feb 2005 19:57:15 +0100, Kurt Roeckx <kurt@roeckx.be> wrote: > The configure test is a little broken. It needs to quote the > $'s. > > I've rewritten the test a little. This one needs applying too. $'s do get scrambled. Best regards, Nicolai.
Attachment
On Mon, Feb 21, 2005 at 10:53:08PM -0500, Bruce Momjian wrote: > > Applied. The configure test is a little broken. It needs to quote the $'s. I've rewritten the test a little. Kurt
Attachment
Kurt Roeckx <kurt@roeckx.be> writes: > The configure test is a little broken. It needs to quote the > $'s. > I've rewritten the test a little. Applied, thanks. regards, tom lane
Oh, thanks. That is a great fix. Applied. Glad you could test it on a machine that supports positional parameters. --------------------------------------------------------------------------- Kurt Roeckx wrote: > On Mon, Feb 21, 2005 at 10:53:08PM -0500, Bruce Momjian wrote: > > > > Applied. > > The configure test is a little broken. It needs to quote the > $'s. > > I've rewritten the test a little. > > > Kurt > [ Attachment, skipping... ] > > ---------------------------(end of broadcast)--------------------------- > TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org -- 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
Tom Lane wrote: > Kurt Roeckx <kurt@roeckx.be> writes: > > The configure test is a little broken. It needs to quote the > > $'s. > > > I've rewritten the test a little. > > Applied, thanks. Oops, Tom got to it first. (Darn!) :-) -- 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
Your patch has been added to the PostgreSQL unapplied patches list at: http://momjian.postgresql.org/cgi-bin/pgpatches It will be applied as soon as one of the PostgreSQL committers reviews and approves it. --------------------------------------------------------------------------- Nicolai Tufar wrote: > > On Mon, Feb 21, 2005 at 10:53:08PM -0500, Bruce Momjian wrote: > > > > Applied. > > Thanks a lot. The patch attached solves the tread > safety problem. Please review it before applying, > I am not sure I am doing the right thing > > > On Tue, 22 Feb 2005 19:57:15 +0100, Kurt Roeckx <kurt@roeckx.be> wrote: > > The configure test is a little broken. It needs to quote the > > $'s. > > > > I've rewritten the test a little. > > This one needs applying too. $'s do get scrambled. > > Best regards, > Nicolai. [ Attachment, skipping... ] > > ---------------------------(end of broadcast)--------------------------- > TIP 7: don't forget to increase your free space map settings -- 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
Bruce Momjian <pgman@candle.pha.pa.us> writes: > Your patch has been added to the PostgreSQL unapplied patches list at: Didn't we do that already? regards, tom lane
Tom Lane wrote: > Bruce Momjian <pgman@candle.pha.pa.us> writes: > > Your patch has been added to the PostgreSQL unapplied patches list at: > > Didn't we do that already? This patch is for thread safety: > Thanks a lot. The patch attached solves the tread > safety problem. Please review it before applying, > I am not sure I am doing the right thing -- 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
On Thu, 24 Feb 2005 22:18:11 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Didn't we do that already? No :( I promised to do it a couple of weeks ago but could not get to do it. Now with Magnus's help I finaly did it. The last patch should be fine. > regards, tom lane Nicolai
Would you please check current CVS? I think I addressed most of these issues already. --------------------------------------------------------------------------- Nicolai Tufar wrote: > > On Mon, Feb 21, 2005 at 10:53:08PM -0500, Bruce Momjian wrote: > > > > Applied. > > Thanks a lot. The patch attached solves the tread > safety problem. Please review it before applying, > I am not sure I am doing the right thing > > > On Tue, 22 Feb 2005 19:57:15 +0100, Kurt Roeckx <kurt@roeckx.be> wrote: > > The configure test is a little broken. It needs to quote the > > $'s. > > > > I've rewritten the test a little. > > This one needs applying too. $'s do get scrambled. > > Best regards, > Nicolai. [ Attachment, skipping... ] > > ---------------------------(end of broadcast)--------------------------- > TIP 7: don't forget to increase your free space map settings -- 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
I have reviewed this patch, and I already added these changes myself in CVS. Thanks. --------------------------------------------------------------------------- Nicolai Tufar wrote: > > On Mon, Feb 21, 2005 at 10:53:08PM -0500, Bruce Momjian wrote: > > > > Applied. > > Thanks a lot. The patch attached solves the tread > safety problem. Please review it before applying, > I am not sure I am doing the right thing > > > On Tue, 22 Feb 2005 19:57:15 +0100, Kurt Roeckx <kurt@roeckx.be> wrote: > > The configure test is a little broken. It needs to quote the > > $'s. > > > > I've rewritten the test a little. > > This one needs applying too. $'s do get scrambled. > > Best regards, > Nicolai. [ Attachment, skipping... ] > > ---------------------------(end of broadcast)--------------------------- > TIP 7: don't forget to increase your free space map settings -- 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