]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add support to port/snprintf.c for position parameter specification:
authorBruce Momjian <bruce@momjian.us>
Tue, 22 Feb 2005 03:56:22 +0000 (03:56 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 22 Feb 2005 03:56:22 +0000 (03:56 +0000)
+ # 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.

config/c-library.m4
configure
configure.in
src/port/snprintf.c

index 679f3844b84ac1c769d52aaa12463f316246ff44..aa6aa397f150be0d1ea8e4cbc6ab1d42b1f49126 100644 (file)
@@ -1,5 +1,5 @@
 # Macros that test various C library quirks
-# $PostgreSQL: pgsql/config/c-library.m4,v 1.29 2004/12/16 17:48:26 momjian Exp $
+# $PostgreSQL: pgsql/config/c-library.m4,v 1.30 2005/02/22 03:55:50 momjian Exp $
 
 
 # PGAC_VAR_INT_TIMEZONE
@@ -266,3 +266,36 @@ case $pgac_cv_snprintf_long_long_int_format in
          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 4345e75d895fb59eb8c66f8178a8e0dc24a859aa..7f0835001745ed415e7abab21c00ffec59c72621 100755 (executable)
--- a/configure
+++ b/configure
 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 68ac785735d2fcf7d8d79195549f8808e53ca619..9c81ad5f5aa7d8a76ad55eb54de81c3a0e621b9c 100644 (file)
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $PostgreSQL: pgsql/configure.in,v 1.399 2005/01/18 05:23:36 momjian Exp $
+dnl $PostgreSQL: pgsql/configure.in,v 1.400 2005/02/22 03:55:12 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -881,6 +881,11 @@ pgac_need_repl_snprintf=no
 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,6 +1074,8 @@ AC_MSG_ERROR([[
 [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 9f3baec7dcae45577a48e304c1b123edc3793fda..00378213a4ca372eed480fcf8d922c43d2dde2f6 100644 (file)
@@ -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,14 +83,32 @@ 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,...)
 {
@@ -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';
 }