>Number:         152934
>Category:       bin
>Synopsis:       Enhancements to printf(1)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Dec 08 19:30:19 UTC 2010
>Closed-Date:
>Last-Modified:
>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      
r...@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:
>Unformatted:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to