bin/39116: /usr/bin/printf

Hiroo Ono hiroo+freebsd at oikumene.gcd.org
Tue Jul 19 16:58:55 GMT 2005


The fix for this PR is done in HEAD
src/usr.bin/printf/printf.c rev.1.22 to 1.25
I made a MFC patch for this, and tested on RELENG_4,
FreeBSD 4.11-STABLE #26: Sat Jul  2 02:02:27 JST 2005.

Tested with the three cases in this PR. The results are same as on
FreeBSD 5.4R-p4.

chrysanthe% ./printf '\45\n'
%
chrysanthe% ./printf '%%%s\n' a b c
%a
%b
%c
chrysanthe% ./printf '%*i\n'
0

Would somebody commit it to RELENG_4 and close this PR?

PR:             39116
Submitted by:   Egil Brendsdal <egilb at ife.no>
1.25
Fix duplicate % in %b format introduced in rev 1.22.
1.24
Let printf(1) tell the difference between zero width/precision and
unspecified width/precision.
1.23
Allow format strings containing "%%" to be reused.
1.22
Allow `%' to be written out with an octal escape (\45 or \045).

----------
--- printf.c.orig	2005-07-19 12:58:43.513437500 +0900
+++ printf.c	2005-07-19 11:04:20.013437500 +0900
@@ -73,12 +73,12 @@
 
 #define PF(f, func) do { \
 	char *b = NULL; \
-	if (fieldwidth) \
-		if (precision) \
+	if (havewidth) \
+		if (haveprec) \
 			(void)asprintf(&b, f, fieldwidth, precision, func); \
 		else \
 			(void)asprintf(&b, f, fieldwidth, func); \
-	else if (precision) \
+	else if (haveprec) \
 		(void)asprintf(&b, f, precision, func); \
 	else \
 		(void)asprintf(&b, f, func); \
@@ -89,7 +89,7 @@
 } while (0)
 
 static int	 asciicode(void);
-static int	 escape(char *);
+static int	 escape(char *, int);
 static int	 getchr(void);
 static int	 getdouble(double *);
 static int	 getint(int *);
@@ -111,7 +111,7 @@
 	char *argv[];
 {
 	static const char *skip1, *skip2;
-	int ch, chopped, end, fieldwidth, precision, rval;
+	int ch, chopped, end, fieldwidth, haveprec, havewidth, precision, rval;
 	char convch, nextch, *format, *fmt, *start;
 
 #ifndef BUILTIN
@@ -143,7 +143,7 @@
 	skip1 = "#-+ 0";
 	skip2 = "0123456789";
 
-	chopped = escape(fmt = format = *argv);	/* backslash interpretation */
+	chopped = escape(fmt = format = *argv, 1);/* backslash interpretation */
 	rval = 0;
 	gargv = ++argv;
 	for (;;) {
@@ -173,8 +173,8 @@
 			if (*fmt == '%') {
 				if (*++fmt != '%')
 					break;
-				*fmt++ = '\0';
-				(void)printf("%s", start);
+				(void)printf("%.*s", (int)(fmt - start), start);
+				fmt++;
 				goto next;
 			}
 		}
@@ -184,9 +184,10 @@
 		if (*fmt == '*') {
 			if (getint(&fieldwidth))
 				return (1);
+			havewidth = 1;
 			++fmt;
 		} else {
-			fieldwidth = 0;
+			havewidth = 0;
 
 			/* skip to possible '.', get following precision */
 			for (; strchr(skip2, *fmt); ++fmt);
@@ -197,15 +198,16 @@
 			if (*fmt == '*') {
 				if (getint(&precision))
 					return (1);
+				haveprec = 1;
 				++fmt;
 			} else {
-				precision = 0;
+				haveprec = 0;
 
 				/* skip to conversion char */
 				for (; strchr(skip2, *fmt); ++fmt);
 			}
 		} else
-			precision = 0;
+			haveprec = 0;
 		if (!*fmt) {
 			warnx1("missing format character", NULL, NULL);
 			return (1);
@@ -228,7 +230,7 @@
 				warnx2("%s", strerror(ENOMEM), NULL);
 				return (1);
 			}
-			getout = escape(p);
+			getout = escape(p, 0);
 			*(fmt - 1) = 's';
 			PF(start, p);
 			*(fmt - 1) = 'b';
@@ -323,8 +325,9 @@
 }
 
 static int
-escape(fmt)
+escape(fmt, percent)
 	register char *fmt;
+	int percent;
 {
 	register char *store;
 	register int value, c;
@@ -376,7 +379,11 @@
 				value += *fmt - '0';
 			}
 			--fmt;
-			*store = value;
+			if (percent && value == '%') {
+				*store++ = '%';
+				*store = '%';
+			} else
+				*store = value;
 			break;
 		default:
 			*store = *fmt;
----------


More information about the freebsd-bugs mailing list