Skip site navigation (1) Skip section navigation (2)

Re: [PATCHES] [pgsql-hackers-win32] Repleacement for src/port/snprintf.c

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
Cc: Nicolai Tufar <ntufar(at)gmail(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>,Peter Eisentraut <peter_e(at)gmx(dot)net>,Magnus Hagander <mha(at)sollentuna(dot)net>, pgsql-hackers(at)postgresql(dot)org,pgsql-hackers-win32(at)postgresql(dot)org, pgsql-patches(at)postgresql(dot)org,devrim(at)gunduz(dot)org
Subject: Re: [PATCHES] [pgsql-hackers-win32] Repleacement for src/port/snprintf.c
Date: 2005-02-22 03:53:08
Message-ID: 200502220353.j1M3r8909318@candle.pha.pa.us (view raw or flat)
Thread:
Lists: pgsql-hackerspgsql-hackers-win32pgsql-patches
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(at)candle(dot)pha(dot)pa(dot)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(at)postgresql(dot)org)

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman(at)candle(dot)pha(dot)pa(dot)us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

In response to

Responses

pgsql-hackers by date

Next:From: Neil ConwayDate: 2005-02-22 04:08:35
Subject: left-deep plans?
Previous:From: Bruce MomjianDate: 2005-02-22 03:43:02
Subject: Re: [pgsql-hackers-win32] UNICODE/UTF-8 on win32

pgsql-patches by date

Next:From: Bruce MomjianDate: 2005-02-22 04:08:10
Subject: Re: Cleanup for gettext() calls
Previous:From: Bruce MomjianDate: 2005-02-22 03:08:25
Subject: Re: UTF8 or Unicode

pgsql-hackers-win32 by date

Next:From: Kurt RoeckxDate: 2005-02-22 18:57:15
Subject: Re: [PATCHES] [pgsql-hackers-win32] Repleacement for src/port/snprintf.c
Previous:From: Bruce MomjianDate: 2005-02-22 03:43:02
Subject: Re: [pgsql-hackers-win32] UNICODE/UTF-8 on win32

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group