bin/39116: /usr/bin/printf

Hiroo Ono hiroo at oikumene.gcd.org
Tue Jul 19 14:30:23 GMT 2005


The following reply was made to PR bin/39116; it has been noted by GNATS.

From: Hiroo Ono <hiroo at oikumene.gcd.org>
To: bug-followup at FreeBSD.org, egilb at ife.no
Cc:  
Subject: Re: bin/39116: /usr/bin/printf
Date: Tue, 19 Jul 2005 23:21:44 +0900

 This may be duplicated on freebsd-bugs. It seems that I should have
 sent it to bug-followup at FreeBSD.org, sorry.
 
 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