diff options
author | pfg <pfg@FreeBSD.org> | 2014-04-21 22:47:18 +0000 |
---|---|---|
committer | pfg <pfg@FreeBSD.org> | 2014-04-21 22:47:18 +0000 |
commit | 540cea4ebc7db0a742da16bad4078a2fdfc50695 (patch) | |
tree | fff855d4510018bbb09fc9de05fda6039dad40e5 /usr.bin/printf | |
parent | 534840ba27f335f1e9ce6b8fb70f43a9f0cd3a0c (diff) | |
download | FreeBSD-src-540cea4ebc7db0a742da16bad4078a2fdfc50695.zip FreeBSD-src-540cea4ebc7db0a742da16bad4078a2fdfc50695.tar.gz |
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
Diffstat (limited to 'usr.bin/printf')
-rw-r--r-- | usr.bin/printf/printf.1 | 5 | ||||
-rw-r--r-- | usr.bin/printf/printf.c | 35 |
2 files changed, 39 insertions, 1 deletions
diff --git a/usr.bin/printf/printf.1 b/usr.bin/printf/printf.1 index c5bba97..7256b53d 100644 --- a/usr.bin/printf/printf.1 +++ b/usr.bin/printf/printf.1 @@ -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 diff --git a/usr.bin/printf/printf.c b/usr.bin/printf/printf.c index 8569f5f..7ed0c21 100644 --- a/usr.bin/printf/printf.c +++ b/usr.bin/printf/printf.c @@ -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 == '*') { |