From 712f053587b552769d1d3f6fe0ec03ab79c05d26 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Wed, 16 Mar 2005 21:27:23 +0000
Subject: [PATCH] Add sprintf support, that were were missing.

Add support for snprintf '+', 'h', and %* length settings.
---
 src/bin/psql/command.c |   6 +-
 src/include/port.h     |   7 +-
 src/port/snprintf.c    | 154 +++++++++++++++++++++++++++++------------
 3 files changed, 118 insertions(+), 49 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 01ff7fb3957..351813feb8e 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.141 2005/03/11 17:20:34 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.142 2005/03/16 21:27:23 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "command.h"
@@ -1574,11 +1574,13 @@ do_shell(const char *command)
 			shellName = DEFAULT_SHELL;
 
 		sys = pg_malloc(strlen(shellName) + 16);
+#ifndef WIN32
 		sprintf(sys,
 		/* See EDITOR handling comment for an explaination */
-#ifndef WIN32
 				"exec %s", shellName);
 #else
+		sprintf(sys,
+		/* See EDITOR handling comment for an explaination */
 				"%s\"%s\"%s", SYSTEMQUOTE, shellName, SYSTEMQUOTE);
 #endif
 		result = system(sys);
diff --git a/src/include/port.h b/src/include/port.h
index 169ee7ac150..5a3a46ec016 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/port.h,v 1.72 2005/03/11 19:13:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/port.h,v 1.73 2005/03/16 21:27:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -112,6 +112,9 @@ extern int pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
 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,11 +130,13 @@ __attribute__((format(printf, 1, 2)));
 #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
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 5ed6f78cd7e..e50555df62e 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -65,16 +65,14 @@
  * causing nasty effects.
  **************************************************************/
 
-/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.22 2005/03/16 15:12:18 momjian Exp $";*/
+/*static char _id[] = "$PostgreSQL: pgsql/src/port/snprintf.c,v 1.23 2005/03/16 21:27:23 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	sprintf
 #undef	fprintf
 #undef	printf
 
@@ -103,19 +101,33 @@ pg_snprintf(char *str, size_t count, const char *fmt,...)
 	return len;
 }
 
+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		buffer[4096];
 	char	   *p;
 
 	va_start(args, fmt);
-	len = pg_vsnprintf((char *) buffer, (size_t) 4096, fmt, args);
+	len = pg_vsnprintf(buffer, (size_t) 4096, fmt, args);
 	va_end(args);
-	p = (char *) buffer;
-	for (; *p; p++)
+	for (p = buffer; *p; p++)
 		putc(*p, stream);
 	return len;
 }
@@ -125,14 +137,14 @@ pg_printf(const char *fmt,...)
 {
 	int			len;
 	va_list		args;
-	char	   *buffer[4096];
+	char		buffer[4096];
 	char	   *p;
 
 	va_start(args, fmt);
-	len = pg_vsnprintf((char *) buffer, (size_t) 4096, fmt, args);
+	len = pg_vsnprintf(buffer, (size_t) 4096, fmt, args);
 	va_end(args);
-	p = (char *) buffer;
-	for (; *p; p++)
+	
+	for (p = buffer; *p; p++)
 		putchar(*p);
 	return len;
 }
@@ -141,12 +153,13 @@ pg_printf(const char *fmt,...)
  * dopr(): poor man's version of doprintf
  */
 
-static void fmtstr(char *value, int ljust, int len, int zpad, int maxwidth,
+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 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 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,13 +175,14 @@ static void
 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			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,6 +207,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 		int			maxwidth;
 		int			base;
 		int			dosign;
+		int			forcesign;
 		char		type;
 		int			precision;
 		int			pointflag;
@@ -230,7 +245,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 		switch (ch)
 		{
 			case '%':
-				ljust = len = zpad = maxwidth = 0;
+				ljust = len = zpad = forcesign = maxwidth = 0;
 				longflag = longlongflag = pointflag = 0;
 				fmtbegin = format - 1;
 				realpos = 0;
@@ -244,6 +259,9 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 					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,6 +307,9 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 						else
 							longflag = 1;
 						goto nextch;
+					case 'h':
+						/* ignore */
+						goto nextch;
 #ifdef NOT_USED
 
 						/*
@@ -318,6 +339,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 						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,6 +355,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 						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,6 +371,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 						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,6 +386,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 						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,6 +401,7 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 						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,9 +435,10 @@ dopr(char *buffer, const char *format, va_list args, char *end)
 						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].maxwidth = maxwidth;
+						fmtpar[fmtpos].zpad = zpad;
 						fmtpar[fmtpos].precision = precision;
 						fmtpar[fmtpos].pointflag = pointflag;
 						fmtpar[fmtpos].func = FMTFLOAT;
@@ -504,20 +531,22 @@ performpr:
 				{
 					case FMTSTR:
 						fmtstr(fmtparptr[i]->value, fmtparptr[i]->ljust,
-							   fmtparptr[i]->len, fmtparptr[i]->zpad,
-							   fmtparptr[i]->maxwidth, end, &output);
+							   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]->ljust,
-						fmtparptr[i]->len, fmtparptr[i]->zpad, end, &output);
+							   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]->ljust, fmtparptr[i]->len,
-							fmtparptr[i]->precision, fmtparptr[i]->pointflag,
-								 end, &output);
+							   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,18 +574,24 @@ nochar:
 }
 
 static void
-fmtstr(char *value, int ljust, int len, int zpad, int maxwidth, char *end,
+fmtstr(char *value, int ljust, int len, int maxwidth, char *end,
 	   char **output)
 {
 	int			padlen,
-				strlen;			/* amount to pad */
+				vallen;			/* amount to pad */
 
-	if (value == 0)
+	if (value == NULL)
 		value = "<NULL>";
-	for (strlen = 0; value[strlen]; ++strlen);	/* strlen */
-	if (strlen > maxwidth && maxwidth)
-		strlen = maxwidth;
-	padlen = len - strlen;
+	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,8 +610,8 @@ fmtstr(char *value, int ljust, int len, int zpad, int maxwidth, char *end,
 }
 
 static void
-fmtnum(int64 value, int base, int dosign, int ljust, int len, int zpad,
-	   char *end, char **output)
+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,6 +632,8 @@ fmtnum(int64 value, int base, int dosign, int ljust, int len, int zpad,
 			signvalue = '-';
 			uvalue = -value;
 		}
+		else if (forcesign)
+			signvalue = '+';
 	}
 	if (base < 0)
 	{
@@ -658,19 +695,32 @@ fmtnum(int64 value, int base, int dosign, int ljust, int len, int zpad,
 }
 
 static void
-fmtfloat(double value, char type, int ljust, int len, int precision,
-		 int pointflag, char *end, char **output)
+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);
-	sprintf(convert, fmt, value);
+
+	if (value < 0)
+	{
+		signvalue = '-';
+		uvalue = -value;
+	}
+	else if (forcesign)
+		signvalue = '+';
+
+	sprintf(convert, fmt, uvalue);
 
 	if (len < 0)
 	{
@@ -684,11 +734,27 @@ fmtfloat(double value, char type, int ljust, int len, int precision,
 	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,15 +767,11 @@ static void
 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
-- 
GitLab