Add support to port/snprintf.c for position parameter specification:
+ # Determine if printf supports %1$ argument selection, e.g. %5$ selects + # the fifth argument after the printf print string. + # This is not in the C99 standard, but in the Single Unix Specification (SUS). + # It is used in our langauge translation strings. Nicolai Tufar with configure changes by Bruce.
This commit is contained in:
parent
78bb800bc2
commit
b4feafb6ff
@ -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
|
||||
|
57
configure
vendored
57
configure
vendored
@ -12162,6 +12162,63 @@ fi
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user