Re: [pgsql-hackers-win32] [HACKERS] snprintf causes regression

Bruce Momjian <[email protected]> Wed, 16 Mar 2005 16:28:07 -0500 (EST)
Newsgroups gmane.comp.db.postgresql.devel.patches,gmane.comp.db.postgresql.devel.general,gmane.comp.db.postgresql.devel.win32
Message-ID <[email protected]>
Nicolai Tufar wrote:
> On Wed, 16 Mar 2005 01:00:21 -0500 (EST), Bruce Momjian
> <[email protected]> wrote:
> > 
> > I have applied a modified version of your patch, attached.
> 
> I am so sorry, I sent untested patch again.  Thank you very
> much for patience in fixing it. The patch looks perfectly
> fine and works under Solaris. 
> 

Here is another patch that adds sprintf() support, and support for '+',
'h', and fixes '%*s' support.

Applied.

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


---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
      joining column's datatypes do not match
/bjm/diff (text/plain, 15.1 KB)
Index: src/bin/psql/command.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.141
diff -c -c -r1.141 command.c
*** src/bin/psql/command.c	11 Mar 2005 17:20:34 -0000	1.141
--- src/bin/psql/command.c	16 Mar 2005 21:17:50 -0000
***************
*** 1574,1584 ****
  			shellName = DEFAULT_SHELL;
  
  		sys = pg_malloc(strlen(shellName) + 16);
  		sprintf(sys,
  		/* See EDITOR handling comment for an explaination */
- #ifndef WIN32
  				"exec %s", shellName);
  #else
  				"%s\"%s\"%s", SYSTEMQUOTE, shellName, SYSTEMQUOTE);
  #endif
  		result = system(sys);
--- 1574,1586 ----
  			shellName = DEFAULT_SHELL;
  
  		sys = pg_malloc(strlen(shellName) + 16);
+ #ifndef WIN32
  		sprintf(sys,
  		/* See EDITOR handling comment for an explaination */
  				"exec %s", shellName);
  #else
+ 		sprintf(sys,
+ 		/* See EDITOR handling comment for an explaination */
  				"%s\"%s\"%s", SYSTEMQUOTE, shellName, SYSTEMQUOTE);
  #endif
  		result = system(sys);
Index: src/include/port.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/port.h,v
retrieving revision 1.72
diff -c -c -r1.72 port.h
*** src/include/port.h	11 Mar 2005 19:13:42 -0000	1.72
--- src/include/port.h	16 Mar 2005 21:17:50 -0000
***************
*** 112,117 ****
--- 112,120 ----
  extern int pg_snprintf(char *str, size_t count, const char *fmt,...)
  /* This extension allows gcc to check the format string */
  __attribute__((format(printf, 3, 4)));
+ extern int pg_sprintf(char *str, const char *fmt,...)
+ /* This extension allows gcc to check the format string */
+ __attribute__((format(printf, 2, 3)));
  extern int pg_fprintf(FILE *stream, const char *fmt,...)
  /* This extension allows gcc to check the format string */
  __attribute__((format(printf, 2, 3)));
***************
*** 127,137 ****
--- 130,142 ----
  #ifdef __GNUC__
  #define	vsnprintf(...)	pg_vsnprintf(__VA_ARGS__)
  #define snprintf(...)	pg_snprintf(__VA_ARGS__)
+ #define sprintf(...)	pg_sprintf(__VA_ARGS__)
  #define fprintf(...)	pg_fprintf(__VA_ARGS__)
  #define printf(...)		pg_printf(__VA_ARGS__)
  #else
  #define vsnprintf		pg_vsnprintf
  #define snprintf		pg_snprintf
+ #define sprintf			pg_sprintf
  #define fprintf			pg_fprintf
  #define printf			pg_printf
  #endif
Index: src/port/snprintf.c
===================================================================
RCS file: /cvsroot/pgsql/src/port/snprintf.c,v
retrieving revision 1.22
diff -c -c -r1.22 snprintf.c
*** src/port/snprintf.c	16 Mar 2005 15:12:18 -0000	1.22
--- src/port/snprintf.c	16 Mar 2005 21:17:51 -0000
***************
*** 67,80 ****
  
  /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.22 2005/03/16 15:12:18 momjian Exp $";*/
  
- int			pg_snprintf(char *str, size_t count, const char *fmt,...);
- int			pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
- int			pg_printf(const char *format,...);
  static void dopr(char *buffer, const char *format, va_list args, char *end);
  
  /* Prevent recursion */
  #undef	vsnprintf
  #undef	snprintf
  #undef	fprintf
  #undef	printf
  
--- 67,78 ----
  
  /*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.22 2005/03/16 15:12:18 momjian Exp $";*/
  
  static void dopr(char *buffer, const char *format, va_list args, char *end);
  
  /* Prevent recursion */
  #undef	vsnprintf
  #undef	snprintf
+ #undef	sprintf
  #undef	fprintf
  #undef	printf
  
***************
*** 104,121 ****
  }
  
  int
  pg_fprintf(FILE *stream, const char *fmt,...)
  {
  	int			len;
  	va_list		args;
! 	char	   *buffer[4096];
  	char	   *p;
  
  	va_start(args, fmt);
! 	len = pg_vsnprintf((char *) buffer, (size_t) 4096, fmt, args);
  	va_end(args);
! 	p = (char *) buffer;
! 	for (; *p; p++)
  		putc(*p, stream);
  	return len;
  }
--- 102,133 ----
  }
  
  int
+ pg_sprintf(char *str, const char *fmt,...)
+ {
+ 	int			len;
+ 	va_list		args;
+ 	char		buffer[4096];
+ 
+ 	va_start(args, fmt);
+ 	len = pg_vsnprintf(buffer, (size_t) 4096, fmt, args);
+ 	va_end(args);
+ 	/* limit output to string */
+ 	StrNCpy(str, buffer, (len + 1 < 4096) ? len + 1 : 4096);
+ 	return len;
+ }
+ 
+ int
  pg_fprintf(FILE *stream, const char *fmt,...)
  {
  	int			len;
  	va_list		args;
! 	char		buffer[4096];
  	char	   *p;
  
  	va_start(args, fmt);
! 	len = pg_vsnprintf(buffer, (size_t) 4096, fmt, args);
  	va_end(args);
! 	for (p = buffer; *p; p++)
  		putc(*p, stream);
  	return len;
  }
***************
*** 125,138 ****
  {
  	int			len;
  	va_list		args;
! 	char	   *buffer[4096];
  	char	   *p;
  
  	va_start(args, fmt);
! 	len = pg_vsnprintf((char *) buffer, (size_t) 4096, fmt, args);
  	va_end(args);
! 	p = (char *) buffer;
! 	for (; *p; p++)
  		putchar(*p);
  	return len;
  }
--- 137,150 ----
  {
  	int			len;
  	va_list		args;
! 	char		buffer[4096];
  	char	   *p;
  
  	va_start(args, fmt);
! 	len = pg_vsnprintf(buffer, (size_t) 4096, fmt, args);
  	va_end(args);
! 	
! 	for (p = buffer; *p; p++)
  		putchar(*p);
  	return len;
  }
***************
*** 141,152 ****
   * dopr(): poor man's version of doprintf
   */
  
! static void fmtstr(char *value, int ljust, int len, int zpad, int maxwidth,
  	   char *end, char **output);
! static void fmtnum(int64 value, int base, int dosign, int ljust, int len,
! 	   int zpad, char *end, char **output);
! static void fmtfloat(double value, char type, int ljust, int len,
! 		 int precision, int pointflag, char *end, char **output);
  static void dostr(char *str, int cut, char *end, char **output);
  static void dopr_outch(int c, char *end, char **output);
  
--- 153,165 ----
   * dopr(): poor man's version of doprintf
   */
  
! static void fmtstr(char *value, int ljust, int len, int maxwidth,
  	   char *end, char **output);
! static void fmtnum(int64 value, int base, int dosign, int forcesign,
! 	   int ljust, int len, int zpad, char *end, char **output);
! static void fmtfloat(double value, char type, int forcesign,
! 	   int ljust, int len, int zpad, int precision, int pointflag, char *end,
! 	   char **output);
  static void dostr(char *str, int cut, char *end, char **output);
  static void dopr_outch(int c, char *end, char **output);
  
***************
*** 162,174 ****
  dopr(char *buffer, const char *format, va_list args, char *end)
  {
  	int			ch;
! 	int			longlongflag = 0;
! 	int			longflag = 0;
! 	int			pointflag = 0;
! 	int			maxwidth = 0;
  	int			ljust;
  	int			len;
  	int			zpad;
  	int			i;
  	const char *format_save;
  	const char *fmtbegin;
--- 175,188 ----
  dopr(char *buffer, const char *format, va_list args, char *end)
  {
  	int			ch;
! 	int			longlongflag;
! 	int			longflag;
! 	int			pointflag;
! 	int			maxwidth;
  	int			ljust;
  	int			len;
  	int			zpad;
+ 	int			forcesign;
  	int			i;
  	const char *format_save;
  	const char *fmtbegin;
***************
*** 193,198 ****
--- 207,213 ----
  		int			maxwidth;
  		int			base;
  		int			dosign;
+ 		int			forcesign;
  		char		type;
  		int			precision;
  		int			pointflag;
***************
*** 230,236 ****
  		switch (ch)
  		{
  			case '%':
! 				ljust = len = zpad = maxwidth = 0;
  				longflag = longlongflag = pointflag = 0;
  				fmtbegin = format - 1;
  				realpos = 0;
--- 245,251 ----
  		switch (ch)
  		{
  			case '%':
! 				ljust = len = zpad = forcesign = maxwidth = 0;
  				longflag = longlongflag = pointflag = 0;
  				fmtbegin = format - 1;
  				realpos = 0;
***************
*** 244,249 ****
--- 259,267 ----
  					case '-':
  						ljust = 1;
  						goto nextch;
+ 					case '+':
+ 						forcesign = 1;
+ 						goto nextch;
  					case '0':	/* set zero padding if len not set */
  						if (len == 0 && !pointflag)
  							zpad = '0';
***************
*** 289,294 ****
--- 307,315 ----
  						else
  							longflag = 1;
  						goto nextch;
+ 					case 'h':
+ 						/* ignore */
+ 						goto nextch;
  #ifdef NOT_USED
  
  						/*
***************
*** 318,323 ****
--- 339,345 ----
  						fmtpar[fmtpos].fmtend = format;
  						fmtpar[fmtpos].base = 10;
  						fmtpar[fmtpos].dosign = 0;
+ 						fmtpar[fmtpos].forcesign = forcesign;
  						fmtpar[fmtpos].ljust = ljust;
  						fmtpar[fmtpos].len = len;
  						fmtpar[fmtpos].zpad = zpad;
***************
*** 333,338 ****
--- 355,361 ----
  						fmtpar[fmtpos].fmtend = format;
  						fmtpar[fmtpos].base = 8;
  						fmtpar[fmtpos].dosign = 0;
+ 						fmtpar[fmtpos].forcesign = forcesign;
  						fmtpar[fmtpos].ljust = ljust;
  						fmtpar[fmtpos].len = len;
  						fmtpar[fmtpos].zpad = zpad;
***************
*** 348,353 ****
--- 371,377 ----
  						fmtpar[fmtpos].fmtend = format;
  						fmtpar[fmtpos].base = 10;
  						fmtpar[fmtpos].dosign = 1;
+ 						fmtpar[fmtpos].forcesign = forcesign;
  						fmtpar[fmtpos].ljust = ljust;
  						fmtpar[fmtpos].len = len;
  						fmtpar[fmtpos].zpad = zpad;
***************
*** 362,367 ****
--- 386,392 ----
  						fmtpar[fmtpos].fmtend = format;
  						fmtpar[fmtpos].base = 16;
  						fmtpar[fmtpos].dosign = 0;
+ 						fmtpar[fmtpos].forcesign = forcesign;
  						fmtpar[fmtpos].ljust = ljust;
  						fmtpar[fmtpos].len = len;
  						fmtpar[fmtpos].zpad = zpad;
***************
*** 376,381 ****
--- 401,407 ----
  						fmtpar[fmtpos].fmtend = format;
  						fmtpar[fmtpos].base = -16;
  						fmtpar[fmtpos].dosign = 1;
+ 						fmtpar[fmtpos].forcesign = forcesign;
  						fmtpar[fmtpos].ljust = ljust;
  						fmtpar[fmtpos].len = len;
  						fmtpar[fmtpos].zpad = zpad;
***************
*** 409,417 ****
  						fmtpar[fmtpos].fmtbegin = fmtbegin;
  						fmtpar[fmtpos].fmtend = format;
  						fmtpar[fmtpos].type = ch;
  						fmtpar[fmtpos].ljust = ljust;
  						fmtpar[fmtpos].len = len;
! 						fmtpar[fmtpos].maxwidth = maxwidth;
  						fmtpar[fmtpos].precision = precision;
  						fmtpar[fmtpos].pointflag = pointflag;
  						fmtpar[fmtpos].func = FMTFLOAT;
--- 435,444 ----
  						fmtpar[fmtpos].fmtbegin = fmtbegin;
  						fmtpar[fmtpos].fmtend = format;
  						fmtpar[fmtpos].type = ch;
+ 						fmtpar[fmtpos].forcesign = forcesign;
  						fmtpar[fmtpos].ljust = ljust;
  						fmtpar[fmtpos].len = len;
! 						fmtpar[fmtpos].zpad = zpad;
  						fmtpar[fmtpos].precision = precision;
  						fmtpar[fmtpos].pointflag = pointflag;
  						fmtpar[fmtpos].func = FMTFLOAT;
***************
*** 504,523 ****
  				{
  					case FMTSTR:
  						fmtstr(fmtparptr[i]->value, fmtparptr[i]->ljust,
! 							   fmtparptr[i]->len, fmtparptr[i]->zpad,
! 							   fmtparptr[i]->maxwidth, end, &output);
  						break;
  					case FMTNUM:
  					case FMTNUM_U:
  						fmtnum(fmtparptr[i]->numvalue, fmtparptr[i]->base,
! 							   fmtparptr[i]->dosign, fmtparptr[i]->ljust,
! 						fmtparptr[i]->len, fmtparptr[i]->zpad, end, &output);
  						break;
  					case FMTFLOAT:
  						fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type,
! 								 fmtparptr[i]->ljust, fmtparptr[i]->len,
! 							fmtparptr[i]->precision, fmtparptr[i]->pointflag,
! 								 end, &output);
  						break;
  					case FMTCHAR:
  						dopr_outch(fmtparptr[i]->charvalue, end, &output);
--- 531,552 ----
  				{
  					case FMTSTR:
  						fmtstr(fmtparptr[i]->value, fmtparptr[i]->ljust,
! 							   fmtparptr[i]->len, fmtparptr[i]->maxwidth,
! 							   end, &output);
  						break;
  					case FMTNUM:
  					case FMTNUM_U:
  						fmtnum(fmtparptr[i]->numvalue, fmtparptr[i]->base,
! 							   fmtparptr[i]->dosign, fmtparptr[i]->forcesign,
! 							   fmtparptr[i]->ljust, fmtparptr[i]->len,
! 							   fmtparptr[i]->zpad, end, &output);
  						break;
  					case FMTFLOAT:
  						fmtfloat(fmtparptr[i]->fvalue, fmtparptr[i]->type,
! 							   fmtparptr[i]->forcesign, fmtparptr[i]->ljust,
! 							   fmtparptr[i]->len, fmtparptr[i]->zpad,
! 							   fmtparptr[i]->precision, fmtparptr[i]->pointflag,
! 							   end, &output);
  						break;
  					case FMTCHAR:
  						dopr_outch(fmtparptr[i]->charvalue, end, &output);
***************
*** 545,562 ****
  }
  
  static void
! fmtstr(char *value, int ljust, int len, int zpad, int maxwidth, char *end,
  	   char **output)
  {
  	int			padlen,
! 				strlen;			/* amount to pad */
  
! 	if (value == 0)
  		value = "<NULL>";
! 	for (strlen = 0; value[strlen]; ++strlen);	/* strlen */
! 	if (strlen > maxwidth && maxwidth)
! 		strlen = maxwidth;
! 	padlen = len - strlen;
  	if (padlen < 0)
  		padlen = 0;
  	if (ljust)
--- 574,597 ----
  }
  
  static void
! fmtstr(char *value, int ljust, int len, int maxwidth, char *end,
  	   char **output)
  {
  	int			padlen,
! 				vallen;			/* amount to pad */
  
! 	if (value == NULL)
  		value = "<NULL>";
! 	vallen = strlen(value);
! 	if (vallen > maxwidth && maxwidth)
! 		vallen = maxwidth;
! 	if (len < 0)
! 	{
! 		/* this could happen with a "*" width spec */
! 		ljust = 1;
! 		len = -len;
! 	}
! 	padlen = len - vallen;
  	if (padlen < 0)
  		padlen = 0;
  	if (ljust)
***************
*** 575,582 ****
  }
  
  static void
! fmtnum(int64 value, int base, int dosign, int ljust, int len, int zpad,
! 	   char *end, char **output)
  {
  	int			signvalue = 0;
  	uint64		uvalue;
--- 610,617 ----
  }
  
  static void
! fmtnum(int64 value, int base, int dosign, int forcesign, int ljust,
! 	   int len, int zpad, char *end, char **output)
  {
  	int			signvalue = 0;
  	uint64		uvalue;
***************
*** 597,602 ****
--- 632,639 ----
  			signvalue = '-';
  			uvalue = -value;
  		}
+ 		else if (forcesign)
+ 			signvalue = '+';
  	}
  	if (base < 0)
  	{
***************
*** 658,676 ****
  }
  
  static void
! fmtfloat(double value, char type, int ljust, int len, int precision,
! 		 int pointflag, char *end, char **output)
  {
  	char		fmt[32];
  	char		convert[512];
  	int			padlen = 0;		/* amount to pad */
  
  	/* we rely on regular C library's sprintf to do the basic conversion */
  	if (pointflag)
  		sprintf(fmt, "%%.%d%c", precision, type);
  	else
  		sprintf(fmt, "%%%c", type);
! 	sprintf(convert, fmt, value);
  
  	if (len < 0)
  	{
--- 695,726 ----
  }
  
  static void
! fmtfloat(double value, char type, int forcesign, int ljust,
! 		 int len, int zpad, int precision, int pointflag, char *end,
! 		 char **output)
  {
+ 	int			signvalue = 0;
+ 	double		uvalue;
  	char		fmt[32];
  	char		convert[512];
  	int			padlen = 0;		/* amount to pad */
  
+ 	uvalue = value;
  	/* we rely on regular C library's sprintf to do the basic conversion */
  	if (pointflag)
  		sprintf(fmt, "%%.%d%c", precision, type);
  	else
  		sprintf(fmt, "%%%c", type);
! 
! 	if (value < 0)
! 	{
! 		signvalue = '-';
! 		uvalue = -value;
! 	}
! 	else if (forcesign)
! 		signvalue = '+';
! 
! 	sprintf(convert, fmt, uvalue);
  
  	if (len < 0)
  	{
***************
*** 684,694 ****
--- 734,760 ----
  	if (ljust)
  		padlen = -padlen;
  
+ 	if (zpad && padlen > 0)
+ 	{
+ 		if (signvalue)
+ 		{
+ 			dopr_outch(signvalue, end, output);
+ 			--padlen;
+ 			signvalue = 0;
+ 		}
+ 		while (padlen > 0)
+ 		{
+ 			dopr_outch(zpad, end, output);
+ 			--padlen;
+ 		}
+ 	}
  	while (padlen > 0)
  	{
  		dopr_outch(' ', end, output);
  		--padlen;
  	}
+ 	if (signvalue)
+ 		dopr_outch(signvalue, end, output);
  	dostr(convert, 0, end, output);
  	while (padlen < 0)
  	{
***************
*** 701,715 ****
  dostr(char *str, int cut, char *end, char **output)
  {
  	if (cut)
- 	{
  		while (*str && cut-- > 0)
  			dopr_outch(*str++, end, output);
- 	}
  	else
- 	{
  		while (*str)
  			dopr_outch(*str++, end, output);
- 	}
  }
  
  static void
--- 767,777 ----