svn commit: r264743 - head/usr.bin/printf

Pedro F. Giffuni pfg at FreeBSD.org
Mon Apr 21 22:47:19 UTC 2014


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 == '*') {


More information about the svn-src-head mailing list