From nobody@FreeBSD.org  Wed Dec  8 19:29:27 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 0A05A106564A
	for <freebsd-gnats-submit@FreeBSD.org>; Wed,  8 Dec 2010 19:29:27 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (unknown [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id D31918FC12
	for <freebsd-gnats-submit@FreeBSD.org>; Wed,  8 Dec 2010 19:29:26 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.4/8.14.4) with ESMTP id oB8JTQT6062823
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 8 Dec 2010 19:29:26 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.4/8.14.4/Submit) id oB8JTQDV062822;
	Wed, 8 Dec 2010 19:29:26 GMT
	(envelope-from nobody)
Message-Id: <201012081929.oB8JTQDV062822@red.freebsd.org>
Date: Wed, 8 Dec 2010 19:29:26 GMT
From: "Pedro F. Giffuni" <giffunip@tutopia.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Enhancements to printf(1)
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         152934
>Category:       bin
>Synopsis:       [patch] Enhancements to printf(1)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    pfg
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Dec 08 19:30:19 UTC 2010
>Closed-Date:    Thu May 29 01:33:39 UTC 2014
>Last-Modified:  Thu May 29 01:33:39 UTC 2014
>Originator:     Pedro F. Giffuni
>Release:        8.1-RELEASE
>Organization:
>Environment:
FreeBSD mogwai.giffuni.net 8.1-RELEASE FreeBSD 8.1-RELEASE #0: Mon Jul  19
02:55:53 UTC 2010      root@almeida.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC 
i386
>Description:
I took an Illumos patch from Garret D'Amore and back ported it to FreeBSD:

From Garret's blog:
http://gdamore.blogspot.com/2010/10/new-implementation-of-printf.html

"Specifically, I added handling of %n$ processing to get parameterized position handling. This is needed for internationalization -- it allows you to change the order of output as part of the output from something like gettext(1). (This is needed when you have to change word order to accommodate different natural language grammars.)"

The patch includes:
- Removal of 3rd Berkeley clause and added Nexenta's copyright.
- Some style fixes.
- Use char in all arguments of mknum.
- Accomodate "--" per a POSIX requirement.
- Contrary to the illumos patch, I preserved the shell/builtin mode.
>How-To-Repeat:

>Fix:
Patch attached.

Patch attached with submission follows:

diff -ru printf.orig/printf.c printf/printf.c
--- printf.orig/printf.c	2010-12-08 14:03:49.000000000 +0000
+++ printf/printf.c	2010-12-08 14:22:10.000000000 +0000
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 1989, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -10,10 +11,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
@@ -72,22 +69,30 @@
 #ifndef BUILTIN
 #include <locale.h>
 #endif
+#define	_(x)	gettext(x)
 
-#define PF(f, func) do { \
-	char *b = NULL; \
-	if (havewidth) \
-		if (haveprec) \
-			(void)asprintf(&b, f, fieldwidth, precision, func); \
-		else \
-			(void)asprintf(&b, f, fieldwidth, func); \
-	else if (haveprec) \
-		(void)asprintf(&b, f, precision, func); \
-	else \
-		(void)asprintf(&b, f, func); \
-	if (b) { \
-		(void)fputs(b, stdout); \
-		free(b); \
-	} \
+#define	PF(f, func) do {						\
+	char *b = NULL;							\
+	int dollar = 0;							\
+	if (*f == '$') 	{						\
+		dollar++;						\
+		*f = '%';						\
+	} 								\
+	if (havewidth)							\
+		if (haveprec)						\
+			(void) asprintf(&b, f, fieldwidth, precision, func); \
+		else							\
+			(void) asprintf(&b, f, fieldwidth, func);	\
+	else if (haveprec)						\
+		(void) asprintf(&b, f, precision, func);		\
+	else								\
+		(void) asprintf(&b, f, func);				\
+	if (b) {							\
+		(void) fputs(b, stdout);				\
+		free(b);						\
+	}								\
+	if (dollar)							\
+		*f = '$';						\
 } while (0)
 
 static int	 asciicode(void);
@@ -99,9 +104,11 @@
 static int	 getnum(intmax_t *, uintmax_t *, int);
 static const char
 		*getstr(void);
-static char	*mknum(char *, int);
+static char	*mknum(char *,  char);
 static void	 usage(void);
 
+static int  myargc;
+static char **myargv;
 static char **gargv;
 
 int
@@ -112,7 +119,7 @@
 #endif
 {
 	size_t len;
-	int ch, chopped, end, rval;
+	int chopped, end, rval;
 	char *format, *fmt, *start;
 
 #if !defined(BUILTIN) && !defined(SHELL)
@@ -121,15 +128,19 @@
 #ifdef SHELL
 	optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
 #endif
-	while ((ch = getopt(argc, argv, "")) != -1)
-		switch (ch) {
-		case '?':
-		default:
-			usage();
-			return (1);
-		}
-	argc -= optind;
-	argv += optind;
+ 
+	argv++;
+	argc--;
+
+	/*
+	 * POSIX says: Standard utilities that do not accept options,
+	 * but that do accept operands, shall recognize "--" as a
+	 * first argument to be discarded.
+	 */
+	if (strcmp(argv[0], "--") == 0) {
+		argc--;
+		argv++;
+	}
 
 	if (argc < 1) {
 		usage();
@@ -151,14 +162,22 @@
 	chopped = escape(fmt, 1, &len);		/* backslash interpretation */
 	rval = end = 0;
 	gargv = ++argv;
+
 	for (;;) {
+		char **maxargv = gargv;
+
+		myargv = gargv;
+		for (myargc = 0; gargv[myargc]; myargc++)
+			/* nop */;
 		start = fmt;
 		while (fmt < format + len) {
 			if (fmt[0] == '%') {
-				fwrite(start, 1, fmt - start, stdout);
+				(void) fwrite(start, 1,
+				    (uintptr_t)fmt - (uintptr_t)start, stdout);
+
 				if (fmt[1] == '%') {
 					/* %% prints a % */
-					putchar('%');
+					(void) putchar('%');
 					fmt += 2;
 				} else {
 					fmt = printf_doformat(fmt, &rval);
@@ -173,7 +192,10 @@
 				start = fmt;
 			} else
 				fmt++;
+			if (gargv > maxargv)
+				maxargv = gargv;
 		}
+		gargv = maxargv;
 
 		if (end == 1) {
 			warnx1("missing format character", NULL, NULL);
@@ -182,7 +204,8 @@
 #endif
 			return (1);
 		}
-		fwrite(start, 1, fmt - start, stdout);
+		(void) fwrite(start, 1, (uintptr_t)fmt - (uintptr_t)start,
+		     stdout);
 		if (chopped || !*gargv) {
 #ifdef SHELL
 			INTON;
@@ -207,6 +230,22 @@
 	char convch, nextch;
 
 	fmt = start + 1;
+
+	/* look for "n$" field index specifier */
+	fmt += strspn(fmt, skip2);
+	if ((*fmt == '$') && (fmt != (start + 1))) {
+		int idx = atoi(start + 1);
+		if (idx <= myargc) {
+			gargv = &myargv[idx - 1];
+		} else {
+			gargv = &myargv[myargc];
+		}
+		start = fmt;
+		fmt++;
+	} else {
+		fmt = start + 1;
+	}
+
 	/* skip to field width */
 	fmt += strspn(fmt, skip1);
 	if (*fmt == '*') {
@@ -347,7 +386,7 @@
 }
 
 static char *
-mknum(char *str, int ch)
+mknum(char *str, char ch)
 {
 	static char *copy;
 	static size_t copy_size;
@@ -370,7 +409,7 @@
 		copy_size = newlen;
 	}
 
-	memmove(copy, str, len - 3);
+	(void) memmove(copy, str, len - 3);
 	copy[len - 3] = 'j';
 	copy[len - 2] = ch;
 	copy[len - 1] = '\0';
@@ -380,10 +419,10 @@
 static int
 escape(char *fmt, int percent, size_t *len)
 {
-	char *save, *store;
-	int value, c;
+	char *save, *store,  c;
+	int value;
 
-	for (save = store = fmt; (c = *fmt); ++fmt, ++store) {
+	for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) {
 		if (c != '\\') {
 			*store = c;
 			continue;
@@ -392,7 +431,7 @@
 		case '\0':		/* EOS, user error */
 			*store = '\\';
 			*++store = '\0';
-			*len = store - save;
+			*len = (uintptr_t)store - (uintptr_t)save;
 			return (0);
 		case '\\':		/* backslash */
 		case '\'':		/* single quote */
@@ -406,7 +445,7 @@
 			break;
 		case 'c':
 			*store = '\0';
-			*len = store - save;
+			*len = (uintptr_t)store - (uintptr_t)save;
 			return (1);
 		case 'f':		/* form-feed */
 			*store = '\f';
@@ -437,7 +476,7 @@
 				*store++ = '%';
 				*store = '%';
 			} else
-				*store = value;
+				*store = (char)value;
 			break;
 		default:
 			*store = *fmt;
@@ -445,7 +484,7 @@
 		}
 	}
 	*store = '\0';
-	*len = store - save;
+	*len = (uintptr_t)store - (uintptr_t)save;
 	return (0);
 }
 
@@ -572,5 +611,5 @@
 static void
 usage(void)
 {
-	(void)fprintf(stderr, "usage: printf format [arguments ...]\n");
+	(void) fprintf(stderr, "usage: printf format [arguments ...]\n");
 }


>Release-Note:
>Audit-Trail:

From: "Pedro F. Giffuni" <giffunip@tutopia.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/152934: Enhancements to printf(1)
Date: Wed, 8 Dec 2010 12:10:02 -0800 (PST)

 Ugh.. Now calling printf without arguments produces a coredump!=0A=0AI'll h=
 ave to investigate why.. sorry!=0A=0A=0A      

From: "Pedro F. Giffuni" <giffunip@tutopia.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/152934: Enhancements to printf(1)
Date: Thu, 9 Dec 2010 08:05:34 -0800 (PST)

 --0-763593055-1291910734=:99324
 Content-Type: text/plain; charset=us-ascii
 
 Updated patch from the latest illumos source.
 I also reduced the diff wrt updated FreeBSD source.
 
 
 
       
 --0-763593055-1291910734=:99324
 Content-Type: text/plain; name="patch-printf.txt"
 Content-Transfer-Encoding: base64
 Content-Disposition: attachment; filename="patch-printf.txt"
 
 ZGlmZiAtcnUgcHJpbnRmLm9yaWcvcHJpbnRmLmMgcHJpbnRmL3ByaW50Zi5j
 Ci0tLSBwcmludGYub3JpZy9wcmludGYuYwkyMDEwLTEyLTA4IDIxOjI0OjU5
 LjAwMDAwMDAwMCArMDAwMAorKysgcHJpbnRmL3ByaW50Zi5jCTIwMTAtMTIt
 MDkgMTA6Mzk6MTkuMDAwMDAwMDAwICswMDAwCkBAIC0xLDQgKzEsNSBAQAog
 LyoKKyAqIENvcHlyaWdodCAyMDEwIE5leGVudGEgU3lzdGVtcywgSW5jLiAg
 QWxsIHJpZ2h0cyByZXNlcnZlZC4KICAqIENvcHlyaWdodCAoYykgMTk4OSwg
 MTk5MwogICoJVGhlIFJlZ2VudHMgb2YgdGhlIFVuaXZlcnNpdHkgb2YgQ2Fs
 aWZvcm5pYS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuCiAgKgpAQCAtMTAsMTAg
 KzExLDYgQEAKICAqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9y
 bSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0CiAgKiAgICBu
 b3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93
 aW5nIGRpc2NsYWltZXIgaW4gdGhlCiAgKiAgICBkb2N1bWVudGF0aW9uIGFu
 ZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJp
 YnV0aW9uLgotICogMy4gQWxsIGFkdmVydGlzaW5nIG1hdGVyaWFscyBtZW50
 aW9uaW5nIGZlYXR1cmVzIG9yIHVzZSBvZiB0aGlzIHNvZnR3YXJlCi0gKiAg
 ICBtdXN0IGRpc3BsYXkgdGhlIGZvbGxvd2luZyBhY2tub3dsZWRnZW1lbnQ6
 Ci0gKglUaGlzIHByb2R1Y3QgaW5jbHVkZXMgc29mdHdhcmUgZGV2ZWxvcGVk
 IGJ5IHRoZSBVbml2ZXJzaXR5IG9mCi0gKglDYWxpZm9ybmlhLCBCZXJrZWxl
 eSBhbmQgaXRzIGNvbnRyaWJ1dG9ycy4KICAqIDQuIE5laXRoZXIgdGhlIG5h
 bWUgb2YgdGhlIFVuaXZlcnNpdHkgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29u
 dHJpYnV0b3JzCiAgKiAgICBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHBy
 b21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUKICAq
 ICAgIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9u
 LgpAQCAtNzMsNiArNzAsMTEgQEAKIAogI2RlZmluZSBQRihmLCBmdW5jKSBk
 byB7IFwKIAljaGFyICpiID0gTlVMTDsgXAorCWludCBkb2xsYXIgPSAwOwlc
 CisJaWYgKCpmID09ICckJykgCXsgXAorCQlkb2xsYXIrKzsgXAorCQkqZiA9
 ICclJzsgXAorCX0gXAogCWlmIChoYXZld2lkdGgpIFwKIAkJaWYgKGhhdmVw
 cmVjKSBcCiAJCQkodm9pZClhc3ByaW50ZigmYiwgZiwgZmllbGR3aWR0aCwg
 cHJlY2lzaW9uLCBmdW5jKTsgXApAQCAtODYsNiArODgsOCBAQAogCQkodm9p
 ZClmcHV0cyhiLCBzdGRvdXQpOyBcCiAJCWZyZWUoYik7IFwKIAl9IFwKKwlp
 ZiAoZG9sbGFyKSBcCisJCSpmID0gJyQnOyBcCiB9IHdoaWxlICgwKQogCiBz
 dGF0aWMgaW50CSBhc2NpaWNvZGUodm9pZCk7CkBAIC05NywzMyArMTAxLDI4
 IEBACiBzdGF0aWMgaW50CSBnZXRudW0oaW50bWF4X3QgKiwgdWludG1heF90
 ICosIGludCk7CiBzdGF0aWMgY29uc3QgY2hhcgogCQkqZ2V0c3RyKHZvaWQp
 Owotc3RhdGljIGNoYXIJKm1rbnVtKGNoYXIgKiwgaW50KTsKK3N0YXRpYyBj
 aGFyCSpta251bShjaGFyICosIGNoYXIpOwogc3RhdGljIHZvaWQJIHVzYWdl
 KHZvaWQpOwogCitzdGF0aWMgaW50ICBteWFyZ2M7CitzdGF0aWMgY2hhciAq
 Km15YXJndjsKIHN0YXRpYyBjaGFyICoqZ2FyZ3Y7CiAKIGludAogbWFpbihp
 bnQgYXJnYywgY2hhciAqYXJndltdKQogewogCXNpemVfdCBsZW47Ci0JaW50
 IGNoLCBjaG9wcGVkLCBlbmQsIHJ2YWw7CisJaW50IGNob3BwZWQsIGVuZCwg
 cnZhbDsKIAljaGFyICpmb3JtYXQsICpmbXQsICpzdGFydDsKIAogI2lmbmRl
 ZiBTSEVMTAogCSh2b2lkKSBzZXRsb2NhbGUoTENfTlVNRVJJQywgIiIpOwot
 I2VuZGlmCi0jaWZkZWYgU0hFTEwKKyNlbHNlCiAJb3B0cmVzZXQgPSAxOyBv
 cHRpbmQgPSAxOyBvcHRlcnIgPSAwOyAvKiBpbml0aWFsaXplIGdldG9wdCAq
 LwogI2VuZGlmCi0Jd2hpbGUgKChjaCA9IGdldG9wdChhcmdjLCBhcmd2LCAi
 IikpICE9IC0xKQotCQlzd2l0Y2ggKGNoKSB7Ci0JCWNhc2UgJz8nOgotCQlk
 ZWZhdWx0OgotCQkJdXNhZ2UoKTsKLQkJCXJldHVybiAoMSk7Ci0JCX0KLQlh
 cmdjIC09IG9wdGluZDsKLQlhcmd2ICs9IG9wdGluZDsKKyAKKwlhcmd2Kys7
 CisJYXJnYy0tOwogCiAJaWYgKGFyZ2MgPCAxKSB7CiAJCXVzYWdlKCk7CkBA
 IC0xNDUsMTQgKzE0NCwyMiBAQAogCWNob3BwZWQgPSBlc2NhcGUoZm10LCAx
 LCAmbGVuKTsJCS8qIGJhY2tzbGFzaCBpbnRlcnByZXRhdGlvbiAqLwogCXJ2
 YWwgPSBlbmQgPSAwOwogCWdhcmd2ID0gKythcmd2OworCiAJZm9yICg7Oykg
 eworCQljaGFyICoqbWF4YXJndiA9IGdhcmd2OworCisJCW15YXJndiA9IGdh
 cmd2OworCQlmb3IgKG15YXJnYyA9IDA7IGdhcmd2W215YXJnY107IG15YXJn
 YysrKQorCQkJLyogbm9wICovOwogCQlzdGFydCA9IGZtdDsKIAkJd2hpbGUg
 KGZtdCA8IGZvcm1hdCArIGxlbikgewogCQkJaWYgKGZtdFswXSA9PSAnJScp
 IHsKLQkJCQlmd3JpdGUoc3RhcnQsIDEsIGZtdCAtIHN0YXJ0LCBzdGRvdXQp
 OworCQkJCSh2b2lkKWZ3cml0ZShzdGFydCwgMSwKKwkJCQkgICAgKHVpbnRw
 dHJfdClmbXQgLSAodWludHB0cl90KXN0YXJ0LCBzdGRvdXQpOworCiAJCQkJ
 aWYgKGZtdFsxXSA9PSAnJScpIHsKIAkJCQkJLyogJSUgcHJpbnRzIGEgJSAq
 LwotCQkJCQlwdXRjaGFyKCclJyk7CisJCQkJCSh2b2lkKXB1dGNoYXIoJyUn
 KTsKIAkJCQkJZm10ICs9IDI7CiAJCQkJfSBlbHNlIHsKIAkJCQkJZm10ID0g
 cHJpbnRmX2RvZm9ybWF0KGZtdCwgJnJ2YWwpOwpAQCAtMTY3LDcgKzE3NCwx
 MCBAQAogCQkJCXN0YXJ0ID0gZm10OwogCQkJfSBlbHNlCiAJCQkJZm10Kys7
 CisJCQlpZiAoZ2FyZ3YgPiBtYXhhcmd2KQorCQkJCW1heGFyZ3YgPSBnYXJn
 djsKIAkJfQorCQlnYXJndiA9IG1heGFyZ3Y7CiAKIAkJaWYgKGVuZCA9PSAx
 KSB7CiAJCQl3YXJueDEoIm1pc3NpbmcgZm9ybWF0IGNoYXJhY3RlciIsIE5V
 TEwsIE5VTEwpOwpAQCAtMTc2LDcgKzE4Niw4IEBACiAjZW5kaWYKIAkJCXJl
 dHVybiAoMSk7CiAJCX0KLQkJZndyaXRlKHN0YXJ0LCAxLCBmbXQgLSBzdGFy
 dCwgc3Rkb3V0KTsKKwkJKHZvaWQpZndyaXRlKHN0YXJ0LCAxLCAodWludHB0
 cl90KWZtdCAtICh1aW50cHRyX3Qpc3RhcnQsCisJCSAgICAgc3Rkb3V0KTsK
 IAkJaWYgKGNob3BwZWQgfHwgISpnYXJndikgewogI2lmZGVmIFNIRUxMCiAJ
 CQlJTlRPTjsKQEAgLTIwMSw2ICsyMTIsMjIgQEAKIAljaGFyIGNvbnZjaCwg
 bmV4dGNoOwogCiAJZm10ID0gc3RhcnQgKyAxOworCisJLyogbG9vayBmb3Ig
 Im4kIiBmaWVsZCBpbmRleCBzcGVjaWZpZXIgKi8KKwlmbXQgKz0gc3Ryc3Bu
 KGZtdCwgc2tpcDIpOworCWlmICgoKmZtdCA9PSAnJCcpICYmIChmbXQgIT0g
 KHN0YXJ0ICsgMSkpKSB7CisJCWludCBpZHggPSBhdG9pKHN0YXJ0ICsgMSk7
 CisJCWlmIChpZHggPD0gbXlhcmdjKSB7CisJCQlnYXJndiA9ICZteWFyZ3Zb
 aWR4IC0gMV07CisJCX0gZWxzZSB7CisJCQlnYXJndiA9ICZteWFyZ3ZbbXlh
 cmdjXTsKKwkJfQorCQlzdGFydCA9IGZtdDsKKwkJZm10Kys7CisJfSBlbHNl
 IHsKKwkJZm10ID0gc3RhcnQgKyAxOworCX0KKwogCS8qIHNraXAgdG8gZmll
 bGQgd2lkdGggKi8KIAlmbXQgKz0gc3Ryc3BuKGZtdCwgc2tpcDEpOwogCWlm
 ICgqZm10ID09ICcqJykgewpAQCAtMzQxLDcgKzM2OCw3IEBACiB9CiAKIHN0
 YXRpYyBjaGFyICoKLW1rbnVtKGNoYXIgKnN0ciwgaW50IGNoKQorbWtudW0o
 Y2hhciAqc3RyLCBjaGFyIGNoKQogewogCXN0YXRpYyBjaGFyICpjb3B5Owog
 CXN0YXRpYyBzaXplX3QgY29weV9zaXplOwpAQCAtMzY0LDcgKzM5MSw3IEBA
 CiAJCWNvcHlfc2l6ZSA9IG5ld2xlbjsKIAl9CiAKLQltZW1tb3ZlKGNvcHks
 IHN0ciwgbGVuIC0gMyk7CisJKHZvaWQpbWVtbW92ZShjb3B5LCBzdHIsIGxl
 biAtIDMpOwogCWNvcHlbbGVuIC0gM10gPSAnaic7CiAJY29weVtsZW4gLSAy
 XSA9IGNoOwogCWNvcHlbbGVuIC0gMV0gPSAnXDAnOwpAQCAtMzc0LDEwICs0
 MDEsMTAgQEAKIHN0YXRpYyBpbnQKIGVzY2FwZShjaGFyICpmbXQsIGludCBw
 ZXJjZW50LCBzaXplX3QgKmxlbikKIHsKLQljaGFyICpzYXZlLCAqc3RvcmU7
 Ci0JaW50IHZhbHVlLCBjOworCWNoYXIgKnNhdmUsICpzdG9yZSwgIGM7CisJ
 aW50IHZhbHVlOwogCi0JZm9yIChzYXZlID0gc3RvcmUgPSBmbXQ7IChjID0g
 KmZtdCk7ICsrZm10LCArK3N0b3JlKSB7CisJZm9yIChzYXZlID0gc3RvcmUg
 PSBmbXQ7ICgoYyA9ICpmbXQpICE9IDApOyArK2ZtdCwgKytzdG9yZSkgewog
 CQlpZiAoYyAhPSAnXFwnKSB7CiAJCQkqc3RvcmUgPSBjOwogCQkJY29udGlu
 dWU7CkBAIC0zODYsNyArNDEzLDcgQEAKIAkJY2FzZSAnXDAnOgkJLyogRU9T
 LCB1c2VyIGVycm9yICovCiAJCQkqc3RvcmUgPSAnXFwnOwogCQkJKisrc3Rv
 cmUgPSAnXDAnOwotCQkJKmxlbiA9IHN0b3JlIC0gc2F2ZTsKKwkJCSpsZW4g
 PSAodWludHB0cl90KXN0b3JlIC0gKHVpbnRwdHJfdClzYXZlOwogCQkJcmV0
 dXJuICgwKTsKIAkJY2FzZSAnXFwnOgkJLyogYmFja3NsYXNoICovCiAJCWNh
 c2UgJ1wnJzoJCS8qIHNpbmdsZSBxdW90ZSAqLwpAQCAtNDAwLDcgKzQyNyw3
 IEBACiAJCQlicmVhazsKIAkJY2FzZSAnYyc6CiAJCQkqc3RvcmUgPSAnXDAn
 OwotCQkJKmxlbiA9IHN0b3JlIC0gc2F2ZTsKKwkJCSpsZW4gPSAodWludHB0
 cl90KXN0b3JlIC0gKHVpbnRwdHJfdClzYXZlOwogCQkJcmV0dXJuICgxKTsK
 IAkJY2FzZSAnZic6CQkvKiBmb3JtLWZlZWQgKi8KIAkJCSpzdG9yZSA9ICdc
 Zic7CkBAIC00MzEsNyArNDU4LDcgQEAKIAkJCQkqc3RvcmUrKyA9ICclJzsK
 IAkJCQkqc3RvcmUgPSAnJSc7CiAJCQl9IGVsc2UKLQkJCQkqc3RvcmUgPSB2
 YWx1ZTsKKwkJCQkqc3RvcmUgPSAoY2hhcil2YWx1ZTsKIAkJCWJyZWFrOwog
 CQlkZWZhdWx0OgogCQkJKnN0b3JlID0gKmZtdDsKQEAgLTQzOSw3ICs0NjYs
 NyBAQAogCQl9CiAJfQogCSpzdG9yZSA9ICdcMCc7Ci0JKmxlbiA9IHN0b3Jl
 IC0gc2F2ZTsKKwkqbGVuID0gKHVpbnRwdHJfdClzdG9yZSAtICh1aW50cHRy
 X3Qpc2F2ZTsKIAlyZXR1cm4gKDApOwogfQogCg==
 
 --0-763593055-1291910734=:99324--
Responsible-Changed-From-To: freebsd-bugs->delphij 
Responsible-Changed-By: delphij 
Responsible-Changed-When: Thu Dec 9 19:42:30 UTC 2010 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=152934 

From: Jilles Tjoelker <jilles@stack.nl>
To: "Pedro F. Giffuni" <giffunip@tutopia.com>, delphij@freebsd.org
Cc: bug-followup@freebsd.org
Subject: Re: bin/152934: Enhancements to printf(1)
Date: Fri, 10 Dec 2010 00:38:17 +0100

 On Wed, Dec 08, 2010 at 02:24:16PM -0800, Pedro F. Giffuni wrote:
 > I attempted to port the illumos patches respecting
 > the builtin shell stuff (they removed it) and now
 > you removed it all together :).
 
 I only removed the BUILTIN stuff (for csh). The SHELL stuff (for sh) is
 in active use and will remain, although I plan to rework it a bit later
 on (this will make it look more normal and fix some minor bugs with use
 as a builtin). I think the Illumos changes should be handled first
 though.
 
 > Perhaps you'd like to take over this PR?
 > There's still a core dump when calling printf
 > without arguments, but it shouldn't be too
 > difficult to fix.
 
 I think the n$ part of this patch is very nice and the advertising
 clause should be removed, but some other parts are a bit questionable.
 
 Casts to void on functions like memmove() (whose return value is only
 meant as a convenience) make no sense to me.
 
 A change like
 -        *len = store - save;
 +        *len = (uintptr_t)store - (uintptr_t)save;
 seems to make things less portable. Subtracting two pointers (part of
 the same array or pointing just beyond it) is a defined operation in C,
 but the relation between multiple pointers converted to uintptr_t is not
 specified. If a cast is deemed necessary (from ptrdiff_t to size_t),
 then cast the result of the pointer subtraction and not the pointers
 themselves. But if the linting tool allows an uintptr_t to be assigned
 to a size_t, why would a ptrdiff_t not be allowed?
 
 A few of the other style changes make sense (but should be in a separate
 commit/patch).
 
 I think the option handling needs no changes for FreeBSD (this has come
 up recently). Disallowing unknown (i.e. all) options allows us to add
 options in future without breaking any application, and because it has
 been that way for fifteen years there are no working scripts on FreeBSD
 that use an unprotected format string starting with '-'. On the other
 hand, on OpenSolaris/Illumos there are working scripts that use such
 format strings and so it makes sense for them to allow it. (This cannot
 be very common because their /bin/sh (ksh93) has a printf builtin which
 requires '--' for such format strings.)
 
 -- 
 Jilles Tjoelker

From: "Pedro F. Giffuni" <giffunip@tutopia.com>
To: delphij@freebsd.org, Jilles Tjoelker <jilles@stack.nl>
Cc: bug-followup@freebsd.org
Subject: Re: bin/152934: Enhancements to printf(1)
Date: Thu, 9 Dec 2010 17:41:30 -0800 (PST)

 Hello again;
 
 I am sorry for the mess my mailer is making: hopefully this time
 the patch will come out fine.
 Thanks for the feedback. I did rework the patch removing
 most of those ugly castings. This has made the patch a lot smaller.
 
 I didn't separate the copyright change but that is trivial.
 
 I am not sure either that we are handling the "--" correctly: a first patch had something for that but it was causing coredumps when using printf without any parameters and it was removed upstream.
 
 Pedro.
 
 diff -ru printf.orig/printf.c printf/printf.c
 --- printf.orig/printf.c	2010-12-08 21:24:59.000000000 +0000
 +++ printf/printf.c	2010-12-09 20:39:03.000000000 +0000
 @@ -1,4 +1,5 @@
  /*
 + * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   * Copyright (c) 1989, 1993
   *	The Regents of the University of California.  All rights reserved.
   *
 @@ -10,10 +11,6 @@
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
 - * 3. All advertising materials mentioning features or use of this software
 - *    must display the following acknowledgement:
 - *	This product includes software developed by the University of
 - *	California, Berkeley and its contributors.
   * 4. Neither the name of the University nor the names of its contributors
   *    may be used to endorse or promote products derived from this software
   *    without specific prior written permission.
 @@ -73,6 +70,11 @@
  
  #define PF(f, func) do { \
  	char *b = NULL; \
 +	int dollar = 0;	\
 +	if (*f == '$') 	{ \
 +		dollar++; \
 +		*f = '%'; \
 +	} \
  	if (havewidth) \
  		if (haveprec) \
  			(void)asprintf(&b, f, fieldwidth, precision, func); \
 @@ -86,6 +88,8 @@
  		(void)fputs(b, stdout); \
  		free(b); \
  	} \
 +	if (dollar) \
 +		*f = '$'; \
  } while (0)
  
  static int	 asciicode(void);
 @@ -97,16 +101,18 @@
  static int	 getnum(intmax_t *, uintmax_t *, int);
  static const char
  		*getstr(void);
 -static char	*mknum(char *, int);
 +static char	*mknum(char *, char);
  static void	 usage(void);
  
 +static int  myargc;
 +static char **myargv;
  static char **gargv;
  
  int
  main(int argc, char *argv[])
  {
  	size_t len;
 -	int ch, chopped, end, rval;
 +	int chopped, end, rval;
  	char *format, *fmt, *start;
  
  #ifndef SHELL
 @@ -115,15 +121,9 @@
  #ifdef SHELL
  	optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
  #endif
 -	while ((ch = getopt(argc, argv, "")) != -1)
 -		switch (ch) {
 -		case '?':
 -		default:
 -			usage();
 -			return (1);
 -		}
 -	argc -= optind;
 -	argv += optind;
 +
 +	argv++;
 +	argc--;
  
  	if (argc < 1) {
  		usage();
 @@ -145,7 +145,13 @@
  	chopped = escape(fmt, 1, &len);		/* backslash interpretation */
  	rval = end = 0;
  	gargv = ++argv;
 +
  	for (;;) {
 +		char **maxargv = gargv;
 +
 +		myargv = gargv;
 +		for (myargc = 0; gargv[myargc]; myargc++)
 +			/* nop */;
  		start = fmt;
  		while (fmt < format + len) {
  			if (fmt[0] == '%') {
 @@ -167,7 +173,10 @@
  				start = fmt;
  			} else
  				fmt++;
 +			if (gargv > maxargv)
 +				maxargv = gargv;
  		}
 +		gargv = maxargv;
  
  		if (end == 1) {
  			warnx1("missing format character", NULL, NULL);
 @@ -201,6 +210,22 @@
  	char convch, nextch;
  
  	fmt = start + 1;
 +
 +	/* look for "n$" field index specifier */
 +	fmt += strspn(fmt, skip2);
 +	if ((*fmt == '$') && (fmt != (start + 1))) {
 +		int idx = atoi(start + 1);
 +		if (idx <= myargc) {
 +			gargv = &myargv[idx - 1];
 +		} else {
 +			gargv = &myargv[myargc];
 +		}
 +		start = fmt;
 +		fmt++;
 +	} else {
 +		fmt = start + 1;
 +	}
 +
  	/* skip to field width */
  	fmt += strspn(fmt, skip1);
  	if (*fmt == '*') {
 @@ -341,7 +366,7 @@
  }
  
  static char *
 -mknum(char *str, int ch)
 +mknum(char *str, char ch)
  {
  	static char *copy;
  	static size_t copy_size;
 @@ -374,10 +399,10 @@
  static int
  escape(char *fmt, int percent, size_t *len)
  {
 -	char *save, *store;
 -	int value, c;
 +	char *save, *store,  c;
 +	int value;
  
 -	for (save = store = fmt; (c = *fmt); ++fmt, ++store) {
 +	for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) {
  		if (c != '\\') {
  			*store = c;
  			continue;
 @@ -431,7 +456,7 @@
  				*store++ = '%';
  				*store = '%';
  			} else
 -				*store = value;
 +				*store = (char)value;
  			break;
  		default:
  			*store = *fmt;
 
 
 
       

From: "Pedro F. Giffuni" <giffunip@tutopia.com>
To: delphij@freebsd.org, Jilles Tjoelker <jilles@stack.nl>
Cc: bug-followup@freebsd.org
Subject: Re: bin/152934: Enhancements to printf(1)
Date: Fri, 10 Dec 2010 10:35:35 -0800 (PST)

 Minor locale adjustment:
 
 diff -ru printf.orig/printf.c printf/printf.c
 --- printf.orig/printf.c	2010-12-08 21:24:59.000000000 +0000
 +++ printf/printf.c	2010-12-10 13:15:11.000000000 +0000
 @@ -1,4 +1,5 @@
  /*
 + * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   * Copyright (c) 1989, 1993
   *	The Regents of the University of California.  All rights reserved.
   *
 @@ -10,10 +11,6 @@
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
 - * 3. All advertising materials mentioning features or use of this software
 - *    must display the following acknowledgement:
 - *	This product includes software developed by the University of
 - *	California, Berkeley and its contributors.
   * 4. Neither the name of the University nor the names of its contributors
   *    may be used to endorse or promote products derived from this software
   *    without specific prior written permission.
 @@ -57,6 +54,7 @@
  #include <stdlib.h>
  #include <string.h>
  #include <unistd.h>
 +#include <locale.h>
  
  #ifdef SHELL
  #define main printfcmd
 @@ -69,10 +67,13 @@
  #define	warnx3(a, b, c)		warnx(a, b, c)
  #endif
  
 -#include <locale.h>
 -
  #define PF(f, func) do { \
  	char *b = NULL; \
 +	int dollar = 0;	\
 +	if (*f == '$') 	{ \
 +		dollar++; \
 +		*f = '%'; \
 +	} \
  	if (havewidth) \
  		if (haveprec) \
  			(void)asprintf(&b, f, fieldwidth, precision, func); \
 @@ -86,6 +87,8 @@
  		(void)fputs(b, stdout); \
  		free(b); \
  	} \
 +	if (dollar) \
 +		*f = '$'; \
  } while (0)
  
  static int	 asciicode(void);
 @@ -97,33 +100,29 @@
  static int	 getnum(intmax_t *, uintmax_t *, int);
  static const char
  		*getstr(void);
 -static char	*mknum(char *, int);
 +static char	*mknum(char *, char);
  static void	 usage(void);
  
 +static int  myargc;
 +static char **myargv;
  static char **gargv;
  
  int
  main(int argc, char *argv[])
  {
  	size_t len;
 -	int ch, chopped, end, rval;
 +	int chopped, end, rval;
  	char *format, *fmt, *start;
  
  #ifndef SHELL
 -	(void) setlocale(LC_NUMERIC, "");
 +	(void) setlocale(LC_ALL, "");
  #endif
  #ifdef SHELL
  	optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
  #endif
 -	while ((ch = getopt(argc, argv, "")) != -1)
 -		switch (ch) {
 -		case '?':
 -		default:
 -			usage();
 -			return (1);
 -		}
 -	argc -= optind;
 -	argv += optind;
 +
 +	argv++;
 +	argc--;
  
  	if (argc < 1) {
  		usage();
 @@ -145,7 +144,13 @@
  	chopped = escape(fmt, 1, &len);		/* backslash interpretation */
  	rval = end = 0;
  	gargv = ++argv;
 +
  	for (;;) {
 +		char **maxargv = gargv;
 +
 +		myargv = gargv;
 +		for (myargc = 0; gargv[myargc]; myargc++)
 +			/* nop */;
  		start = fmt;
  		while (fmt < format + len) {
  			if (fmt[0] == '%') {
 @@ -167,7 +172,10 @@
  				start = fmt;
  			} else
  				fmt++;
 +			if (gargv > maxargv)
 +				maxargv = gargv;
  		}
 +		gargv = maxargv;
  
  		if (end == 1) {
  			warnx1("missing format character", NULL, NULL);
 @@ -201,6 +209,22 @@
  	char convch, nextch;
  
  	fmt = start + 1;
 +
 +	/* look for "n$" field index specifier */
 +	fmt += strspn(fmt, skip2);
 +	if ((*fmt == '$') && (fmt != (start + 1))) {
 +		int idx = atoi(start + 1);
 +		if (idx <= myargc) {
 +			gargv = &myargv[idx - 1];
 +		} else {
 +			gargv = &myargv[myargc];
 +		}
 +		start = fmt;
 +		fmt++;
 +	} else {
 +		fmt = start + 1;
 +	}
 +
  	/* skip to field width */
  	fmt += strspn(fmt, skip1);
  	if (*fmt == '*') {
 @@ -341,7 +365,7 @@
  }
  
  static char *
 -mknum(char *str, int ch)
 +mknum(char *str, char ch)
  {
  	static char *copy;
  	static size_t copy_size;
 @@ -374,10 +398,10 @@
  static int
  escape(char *fmt, int percent, size_t *len)
  {
 -	char *save, *store;
 -	int value, c;
 +	char *save, *store,  c;
 +	int value;
  
 -	for (save = store = fmt; (c = *fmt); ++fmt, ++store) {
 +	for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) {
  		if (c != '\\') {
  			*store = c;
  			continue;
 @@ -431,7 +455,7 @@
  				*store++ = '%';
  				*store = '%';
  			} else
 -				*store = value;
 +				*store = (char)value;
  			break;
  		default:
  			*store = *fmt;
 
 
 
 
       

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/152934: commit references a PR
Date: Mon, 13 Dec 2010 19:54:49 +0000 (UTC)

 Author: delphij
 Date: Mon Dec 13 19:54:42 2010
 New Revision: 216418
 URL: http://svn.freebsd.org/changeset/base/216418
 
 Log:
   The only caller of mknum() provides a char instead of an int, so make it
   match the definition.
   
   PR:		bin/152934
   Submitted by:	Pedro F. Giffuni <giffunip tutopia.com>
   Obtained from:	Illumos
 
 Modified:
   head/usr.bin/printf/printf.c
 
 Modified: head/usr.bin/printf/printf.c
 ==============================================================================
 --- head/usr.bin/printf/printf.c	Mon Dec 13 19:50:12 2010	(r216417)
 +++ head/usr.bin/printf/printf.c	Mon Dec 13 19:54:42 2010	(r216418)
 @@ -92,7 +92,7 @@ static int	 getint(int *);
  static int	 getnum(intmax_t *, uintmax_t *, int);
  static const char
  		*getstr(void);
 -static char	*mknum(char *, int);
 +static char	*mknum(char *, char);
  static void	 usage(void);
  
  static char **gargv;
 @@ -336,7 +336,7 @@ printf_doformat(char *start, int *rval)
  }
  
  static char *
 -mknum(char *str, int ch)
 +mknum(char *str, char ch)
  {
  	static char *copy;
  	static size_t copy_size;
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/152934: commit references a PR
Date: Tue, 14 Dec 2010 01:28:41 +0000 (UTC)

 Author: delphij
 Date: Tue Dec 14 01:28:33 2010
 New Revision: 216424
 URL: http://svn.freebsd.org/changeset/base/216424
 
 Log:
   We work on ctype's and not only on numbers so set LC_ALL instead of
   LC_NUMERIC.
   
   PR:		bin/152934
   Submitted by:	Pedro F. Giffuni <giffunip tutopia.com>
   Obtained from:	Illumos
 
 Modified:
   head/usr.bin/printf/printf.c
 
 Modified: head/usr.bin/printf/printf.c
 ==============================================================================
 --- head/usr.bin/printf/printf.c	Tue Dec 14 01:16:56 2010	(r216423)
 +++ head/usr.bin/printf/printf.c	Tue Dec 14 01:28:33 2010	(r216424)
 @@ -106,7 +106,7 @@ main(int argc, char *argv[])
  	char *format, *fmt, *start;
  
  #ifndef SHELL
 -	(void) setlocale(LC_NUMERIC, "");
 +	(void) setlocale(LC_ALL, "");
  #endif
  #ifdef SHELL
  	optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: eadler 
State-Changed-When: Tue Mar 1 10:14:08 EST 2011 
State-Changed-Why:  
committed in head 

http://www.freebsd.org/cgi/query-pr.cgi?pr=152934 
State-Changed-From-To: patched->open 
State-Changed-By: eadler 
State-Changed-When: Tue Mar 1 14:49:14 EST 2011 
State-Changed-Why:  
This has not been fully patched 

http://www.freebsd.org/cgi/query-pr.cgi?pr=152934 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/152934: commit references a PR
Date: Thu, 12 Jan 2012 20:30:36 +0000 (UTC)

 Author: pfg
 Date: Thu Jan 12 20:30:20 2012
 New Revision: 230027
 URL: http://svn.freebsd.org/changeset/base/230027
 
 Log:
   Style cleanups for printf.
   
   PR:		bin/152934
   Approved by:	jhb (mentor)
   Obtained from:	Illumos
   MFC after:	2 weeks
 
 Modified:
   head/usr.bin/printf/printf.c
 
 Modified: head/usr.bin/printf/printf.c
 ==============================================================================
 --- head/usr.bin/printf/printf.c	Thu Jan 12 18:39:37 2012	(r230026)
 +++ head/usr.bin/printf/printf.c	Thu Jan 12 20:30:20 2012	(r230027)
 @@ -66,21 +66,21 @@ static const char rcsid[] =
  #include "error.h"
  #endif
  
 -#define PF(f, func) do { \
 -	char *b = NULL; \
 -	if (havewidth) \
 -		if (haveprec) \
 +#define PF(f, func) do {						\
 +	char *b = NULL;							\
 +	if (havewidth)							\
 +		if (haveprec)						\
  			(void)asprintf(&b, f, fieldwidth, precision, func); \
 -		else \
 -			(void)asprintf(&b, f, fieldwidth, func); \
 -	else if (haveprec) \
 -		(void)asprintf(&b, f, precision, func); \
 -	else \
 -		(void)asprintf(&b, f, func); \
 -	if (b) { \
 -		(void)fputs(b, stdout); \
 -		free(b); \
 -	} \
 +		else							\
 +			(void)asprintf(&b, f, fieldwidth, func);	\
 +	else if (haveprec)						\
 +		(void)asprintf(&b, f, precision, func);			\
 +	else								\
 +		(void)asprintf(&b, f, func);				\
 +	if (b) {							\
 +		(void)fputs(b, stdout);					\
 +		free(b);						\
 +	}								\
  } while (0)
  
  static int	 asciicode(void);
 @@ -357,10 +357,10 @@ mknum(char *str, char ch)
  static int
  escape(char *fmt, int percent, size_t *len)
  {
 -	char *save, *store;
 -	int value, c;
 +	char *save, *store, c;
 +	int value;
  
 -	for (save = store = fmt; (c = *fmt); ++fmt, ++store) {
 +	for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) {
  		if (c != '\\') {
  			*store = c;
  			continue;
 @@ -414,7 +414,7 @@ escape(char *fmt, int percent, size_t *l
  				*store++ = '%';
  				*store = '%';
  			} else
 -				*store = value;
 +				*store = (char)value;
  			break;
  		default:
  			*store = *fmt;
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/152934: commit references a PR
Date: Fri,  3 Feb 2012 21:38:32 +0000 (UTC)

 Author: pfg
 Date: Fri Feb  3 21:38:23 2012
 New Revision: 230961
 URL: http://svn.freebsd.org/changeset/base/230961
 
 Log:
   MFC:	r230027
   
   Style cleanups for printf.
   
   PR:		bin/152934
   Approved by:	jhb (mentor)
   Obtained from:	Illumos
 
 Modified:
   stable/9/usr.bin/printf/printf.c
 Directory Properties:
   stable/9/usr.bin/printf/   (props changed)
 
 Modified: stable/9/usr.bin/printf/printf.c
 ==============================================================================
 --- stable/9/usr.bin/printf/printf.c	Fri Feb  3 21:30:31 2012	(r230960)
 +++ stable/9/usr.bin/printf/printf.c	Fri Feb  3 21:38:23 2012	(r230961)
 @@ -66,21 +66,21 @@ static const char rcsid[] =
  #include "error.h"
  #endif
  
 -#define PF(f, func) do { \
 -	char *b = NULL; \
 -	if (havewidth) \
 -		if (haveprec) \
 +#define PF(f, func) do {						\
 +	char *b = NULL;							\
 +	if (havewidth)							\
 +		if (haveprec)						\
  			(void)asprintf(&b, f, fieldwidth, precision, func); \
 -		else \
 -			(void)asprintf(&b, f, fieldwidth, func); \
 -	else if (haveprec) \
 -		(void)asprintf(&b, f, precision, func); \
 -	else \
 -		(void)asprintf(&b, f, func); \
 -	if (b) { \
 -		(void)fputs(b, stdout); \
 -		free(b); \
 -	} \
 +		else							\
 +			(void)asprintf(&b, f, fieldwidth, func);	\
 +	else if (haveprec)						\
 +		(void)asprintf(&b, f, precision, func);			\
 +	else								\
 +		(void)asprintf(&b, f, func);				\
 +	if (b) {							\
 +		(void)fputs(b, stdout);					\
 +		free(b);						\
 +	}								\
  } while (0)
  
  static int	 asciicode(void);
 @@ -357,10 +357,10 @@ mknum(char *str, char ch)
  static int
  escape(char *fmt, int percent, size_t *len)
  {
 -	char *save, *store;
 -	int value, c;
 +	char *save, *store, c;
 +	int value;
  
 -	for (save = store = fmt; (c = *fmt); ++fmt, ++store) {
 +	for (save = store = fmt; ((c = *fmt) != 0); ++fmt, ++store) {
  		if (c != '\\') {
  			*store = c;
  			continue;
 @@ -414,7 +414,7 @@ escape(char *fmt, int percent, size_t *l
  				*store++ = '%';
  				*store = '%';
  			} else
 -				*store = value;
 +				*store = (char)value;
  			break;
  		default:
  			*store = *fmt;
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
Responsible-Changed-From-To: delphij->pfg 
Responsible-Changed-By: delphij 
Responsible-Changed-When: Tue Mar 18 20:09:52 UTC 2014 
Responsible-Changed-Why:  
Don't pretend as working on this issue when pfg@ have done a 
majority of the work... 

http://www.freebsd.org/cgi/query-pr.cgi?pr=152934 

From: Pedro Giffuni <pfg@freebsd.org>
To: "bug-followup@FreeBSD.org" <bug-followup@FreeBSD.org>
Cc:  
Subject: Re: bin/152934: [patch] Enhancements to printf(1)
Date: Wed, 16 Apr 2014 21:31:40 -0500

 This is a multi-part message in MIME format.
 --------------000709020303010608010407
 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Updated printf(1) patch, as seen in illumos.
 
 --------------000709020303010608010407
 Content-Type: text/plain; charset=us-ascii;
  name="patch-printf.txt"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="patch-printf.txt"
 
 Index: usr.bin/printf/printf.c
 ===================================================================
 --- usr.bin/printf/printf.c	(revision 264581)
 +++ usr.bin/printf/printf.c	(working copy)
 @@ -1,4 +1,5 @@
  /*-
 + * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   * Copyright (c) 1989, 1993
   *	The Regents of the University of California.  All rights reserved.
   *
 @@ -69,6 +70,11 @@
  
  #define	PF(f, func) do {						\
  	char *b = NULL;							\
 +	int dollar = 0;							\
 +	if (*f == '$') 	{						\
 +		dollar++;						\
 +		*f = '%';						\
 +	} 								\
  	if (havewidth)							\
  		if (haveprec)						\
  			(void)asprintf(&b, f, fieldwidth, precision, func); \
 @@ -82,6 +88,8 @@
  		(void)fputs(b, stdout);					\
  		free(b);						\
  	}								\
 +	if (dollar)							\
 +		*f = '$';						\
  } while (0)
  
  static int	 asciicode(void);
 @@ -96,6 +104,8 @@
  static char	*mknum(char *, char);
  static void	 usage(void);
  
 +static int  myargc;
 +static char **myargv;
  static char **gargv;
  
  int
 @@ -105,8 +115,6 @@
  	int chopped, end, rval;
  	char *format, *fmt, *start;
  #ifndef SHELL
 -	int ch;
 -
  	(void) setlocale(LC_ALL, "");
  #endif
  
 @@ -115,15 +123,18 @@
  	argc -= argptr - argv;
  	argv = argptr;
  #else
 -	while ((ch = getopt(argc, argv, "")) != -1)
 -		switch (ch) {
 -		case '?':
 -		default:
 -			usage();
 -			return (1);
 -		}
 -	argc -= optind;
 -	argv += optind;
 +	argv++;
 +	argc--;
 +
 +	/*
 +	 * POSIX says: Standard utilities that do not accept options,
 +	 * but that do accept operands, shall recognize "--" as a
 +	 * first argument to be discarded.
 +	 */
 +	if (argc && strcmp(argv[0], "--") == 0) {
 +		argc--;
 +		argv++;
 +	}
  #endif
  
  	if (argc < 1) {
 @@ -146,7 +157,13 @@
  	chopped = escape(fmt, 1, &len);		/* backslash interpretation */
  	rval = end = 0;
  	gargv = ++argv;
 +
  	for (;;) {
 +		char **maxargv = gargv;
 +
 +		myargv = gargv;
 +		for (myargc = 0; gargv[myargc]; myargc++)
 +			/* nop */;
  		start = fmt;
  		while (fmt < format + len) {
  			if (fmt[0] == '%') {
 @@ -168,7 +185,10 @@
  				start = fmt;
  			} else
  				fmt++;
 +			if (gargv > maxargv)
 +				maxargv = gargv;
  		}
 +		gargv = maxargv;
  
  		if (end == 1) {
  			warnx("missing format character");
 @@ -202,6 +222,22 @@
  	char convch, nextch;
  
  	fmt = start + 1;
 +
 +	/* look for "n$" field index specifier */
 +	fmt += strspn(fmt, skip2);
 +	if ((*fmt == '$') && (fmt != (start + 1))) {
 +		int idx = atoi(start + 1);
 +		if (idx <= myargc) {
 +			gargv = &myargv[idx - 1];
 +		} else {
 +			gargv = &myargv[myargc];
 +		}
 +		start = fmt;
 +		fmt++;
 +	} else {
 +		fmt = start + 1;
 +	}
 +
  	/* skip to field width */
  	fmt += strspn(fmt, skip1);
  	if (*fmt == '*') {
 
 --------------000709020303010608010407--

From: Jilles Tjoelker <jilles@stack.nl>
To: Pedro Giffuni <pfg@freebsd.org>
Cc: "bug-followup@FreeBSD.org" <bug-followup@FreeBSD.org>
Subject: Re: bin/152934: [patch] Enhancements to printf(1)
Date: Thu, 17 Apr 2014 20:31:30 +0200

 On Wed, Apr 16, 2014 at 09:31:40PM -0500, Pedro Giffuni wrote:
 > Updated printf(1) patch, as seen in illumos.
 
 > Index: usr.bin/printf/printf.c
 > ===================================================================
 > --- usr.bin/printf/printf.c	(revision 264581)
 > +++ usr.bin/printf/printf.c	(working copy)
 > @@ -1,4 +1,5 @@
 >  /*-
 > + * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
 >   * Copyright (c) 1989, 1993
 >   *	The Regents of the University of California.  All rights reserved.
 >   *
 > @@ -69,6 +70,11 @@
 >  
 >  #define	PF(f, func) do {						\
 >  	char *b = NULL;							\
 > +	int dollar = 0;							\
 > +	if (*f == '$') 	{						\
 > +		dollar++;						\
 > +		*f = '%';						\
 > +	} 								\
 >  	if (havewidth)							\
 >  		if (haveprec)						\
 >  			(void)asprintf(&b, f, fieldwidth, precision, func); \
 > @@ -82,6 +88,8 @@
 >  		(void)fputs(b, stdout);					\
 >  		free(b);						\
 >  	}								\
 > +	if (dollar)							\
 > +		*f = '$';						\
 >  } while (0)
 >  
 >  static int	 asciicode(void);
 
 This looks useful, but is incomplete. The n$ syntax can also be used
 after an asterisk, and in fact this is required: positional (n$) and
 non-positional arguments may not be mixed in a single format directive.
 
 For example:
   printf '[%3$*1$.*2$s]\n' 20 10 abcdefghijklmn
 and
   printf '[%1$*2$.*3$s]\n' abcdefghijklmn 20 10
 do the same thing as
   printf '[%*.*s]\n' 20 10 abcdefghijklmn
 
 Of the printf(1)s I have tried, this works in zsh's and ksh93's builtin.
 
 This certainly needs quite a bit of additional code, but I think the n$
 and * syntaxes are most useful together, since they are both meant for
 situations where the format string is translated. If the format string
 is not translated, * can be replaced by a parameter substitution (or
 even hard-coding) and n$ can be replaced by reordering the arguments.
 
 > [snip]
 
 > @@ -105,8 +115,6 @@
 >  	int chopped, end, rval;
 >  	char *format, *fmt, *start;
 >  #ifndef SHELL
 > -	int ch;
 > -
 >  	(void) setlocale(LC_ALL, "");
 >  #endif
 >  
 > @@ -115,15 +123,18 @@
 >  	argc -= argptr - argv;
 >  	argv = argptr;
 >  #else
 > -	while ((ch = getopt(argc, argv, "")) != -1)
 > -		switch (ch) {
 > -		case '?':
 > -		default:
 > -			usage();
 > -			return (1);
 > -		}
 > -	argc -= optind;
 > -	argv += optind;
 > +	argv++;
 > +	argc--;
 > +
 > +	/*
 > +	 * POSIX says: Standard utilities that do not accept options,
 > +	 * but that do accept operands, shall recognize "--" as a
 > +	 * first argument to be discarded.
 > +	 */
 > +	if (argc && strcmp(argv[0], "--") == 0) {
 > +		argc--;
 > +		argv++;
 > +	}
 >  #endif
 >  
 >  	if (argc < 1) {
 
 Please leave this part out. Unknown options should continue to cause an
 error, so that we can add options later with minimal compatibility
 problems.
 
 As I noted in http://www.freebsd.org/cgi/query-pr.cgi?pr=152934#reply3
 this is a valid Illumos local change.
 
 > [snip]
 
 -- 
 Jilles Tjoelker

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/152934: commit references a PR
Date: Mon, 21 Apr 2014 22:47:21 +0000 (UTC)

 Author: pfg
 Date: Mon Apr 21 22:47:18 2014
 New Revision: 264743
 URL: http://svnweb.freebsd.org/changeset/base/264743
 
 Log:
   Add parameterized position handling to printf(1).
   
   Add a new %n$ option to change the order of the parameters as
   done in the ksh93 builtin printf (among others).
   
   For example:
   %printf '%2$1d %1$s\n' one 2 three 4
   2 one
   4 three
   
   The feature was written by Garret D'Amore under a
   BSD license for Nexenta/illumos.
   
   Reference:
   http://garrett.damore.org/2010/10/new-implementation-of-printf.html
   
   PR:		bin/152934
   Obtained from:	Illumos
   MFC after:	2 weeks
 
 Modified:
   head/usr.bin/printf/printf.1
   head/usr.bin/printf/printf.c
 
 Modified: head/usr.bin/printf/printf.1
 ==============================================================================
 --- head/usr.bin/printf/printf.1	Mon Apr 21 22:36:31 2014	(r264742)
 +++ head/usr.bin/printf/printf.1	Mon Apr 21 22:47:18 2014	(r264743)
 @@ -31,7 +31,7 @@
  .\"	@(#)printf.1	8.1 (Berkeley) 6/6/93
  .\" $FreeBSD$
  .\"
 -.Dd May 28, 2011
 +.Dd April 21, 2014
  .Dt PRINTF 1
  .Os
  .Sh NAME
 @@ -290,6 +290,9 @@ octal escapes are
  .Cm \e0 Ns Ar num
  instead of
  .Cm \e Ns Ar num .
 +.It Cm n$
 +Allows reordering of the output according to
 +.Ar argument .
  .It Cm \&%
  Print a `%'; no argument is used.
  .El
 
 Modified: head/usr.bin/printf/printf.c
 ==============================================================================
 --- head/usr.bin/printf/printf.c	Mon Apr 21 22:36:31 2014	(r264742)
 +++ head/usr.bin/printf/printf.c	Mon Apr 21 22:47:18 2014	(r264743)
 @@ -1,4 +1,5 @@
  /*-
 + * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   * Copyright (c) 1989, 1993
   *	The Regents of the University of California.  All rights reserved.
   *
 @@ -69,6 +70,11 @@ static const char rcsid[] =
  
  #define	PF(f, func) do {						\
  	char *b = NULL;							\
 +	int dollar = 0;							\
 +	if (*f == '$') 	{						\
 +		dollar++;						\
 +		*f = '%';						\
 +	} 								\
  	if (havewidth)							\
  		if (haveprec)						\
  			(void)asprintf(&b, f, fieldwidth, precision, func); \
 @@ -82,6 +88,8 @@ static const char rcsid[] =
  		(void)fputs(b, stdout);					\
  		free(b);						\
  	}								\
 +	if (dollar)							\
 +		*f = '$';						\
  } while (0)
  
  static int	 asciicode(void);
 @@ -96,6 +104,8 @@ static const char
  static char	*mknum(char *, char);
  static void	 usage(void);
  
 +static int  myargc;
 +static char **myargv;
  static char **gargv;
  
  int
 @@ -146,7 +156,13 @@ main(int argc, char *argv[])
  	chopped = escape(fmt, 1, &len);		/* backslash interpretation */
  	rval = end = 0;
  	gargv = ++argv;
 +
  	for (;;) {
 +		char **maxargv = gargv;
 +
 +		myargv = gargv;
 +		for (myargc = 0; gargv[myargc]; myargc++)
 +			/* nop */;
  		start = fmt;
  		while (fmt < format + len) {
  			if (fmt[0] == '%') {
 @@ -168,7 +184,10 @@ main(int argc, char *argv[])
  				start = fmt;
  			} else
  				fmt++;
 +			if (gargv > maxargv)
 +				maxargv = gargv;
  		}
 +		gargv = maxargv;
  
  		if (end == 1) {
  			warnx("missing format character");
 @@ -202,6 +221,22 @@ printf_doformat(char *start, int *rval)
  	char convch, nextch;
  
  	fmt = start + 1;
 +
 +	/* look for "n$" field index specifier */
 +	fmt += strspn(fmt, skip2);
 +	if ((*fmt == '$') && (fmt != (start + 1))) {
 +		int idx = atoi(start + 1);
 +		if (idx <= myargc) {
 +			gargv = &myargv[idx - 1];
 +		} else {
 +			gargv = &myargv[myargc];
 +		}
 +		start = fmt;
 +		fmt++;
 +	} else {
 +		fmt = start + 1;
 +	}
 +
  	/* skip to field width */
  	fmt += strspn(fmt, skip1);
  	if (*fmt == '*') {
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: pfg 
State-Changed-When: Thu May 29 01:30:36 UTC 2014 
State-Changed-Why:  
The features have been merged and further completed by working 
along with Garrett D'Amore. 
We still have to figure out some issues with kyua before the 
change can be merged but the coding part is done already. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=152934 
>Unformatted:
