bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: printf '\41' erroneously fails


From: Paul Eggert
Subject: Re: printf '\41' erroneously fails
Date: Sun, 20 Apr 2003 23:40:07 -0700 (PDT)

> From: Ben Harris <address@hidden>
> Date: Sat, 19 Apr 2003 13:51:08 +0100 (BST)

> The version of printf build into GNU Bash 2.05b seems to behave correctly,
> as does that shipped with NetBSD 1.6.

Good catch.  Here's a proposed patch, relative to the CVS version of
coreutils.

2003-04-20  Paul Eggert  <address@hidden>

        Fix printf POSIX compatibility bug reported by Ben Harris in
        <http://mail.gnu.org/archive/html/bug-coreutils/2003-04/msg00070.html>.
        * doc/coreutils.texi (printf invocation): It's \NNN in the format,
        \0NNN in the %b operand.
        * src/printf.c (usage): Likewise.
        (print_esc): New arg OCTAL0 to specify whether \0NNN or \NNN
        is desired.  All uses changed.  Behave like Bash printf if %b
        operand uses \NNN where the initial N is not 0.

Index: doc/coreutils.texi
===================================================================
RCS file: /home/m/meyering/fetish/cu/doc/coreutils.texi,v
retrieving revision 1.106
diff -p -u -r1.106 coreutils.texi
--- doc/coreutils.texi  10 Apr 2003 16:41:14 -0000      1.106
+++ doc/coreutils.texi  21 Apr 2003 06:35:38 -0000
@@ -8475,13 +8475,14 @@ all of the given @var{argument}s.
 
 @command{printf} has one additional directive, @samp{%b}, which prints its
 argument string with @samp{\} escapes interpreted in the same way as in
-the @var{format} string.
+the @var{format} string, except that octal escapes are of the form
address@hidden@var{ooo}} where @var{ooo} is 0 to 3 octal digits.
 
 @kindex address@hidden
 @kindex address@hidden
 
 @command{printf} interprets @address@hidden in @var{format} as an octal number
-(if @var{ooo} is 0 to 3 octal digits) specifying a character to print,
+(if @var{ooo} is 1 to 3 octal digits) specifying a character to print,
 and @address@hidden as a hexadecimal number (if @var{hh} is 1 to 2 hex
 digits) specifying a character to print.
 
Index: src/printf.c
===================================================================
RCS file: /home/m/meyering/fetish/cu/src/printf.c,v
retrieving revision 1.75
diff -p -u -r1.75 printf.c
--- src/printf.c.~1.75.~        2003-03-27 06:59:26.000000000 -0800
+++ src/printf.c        2003-04-20 23:36:58.295001000 -0700
@@ -31,14 +31,15 @@
    \r = carriage return
    \t = horizontal tab
    \v = vertical tab
-   \0ooo = octal number (ooo is 0 to 3 digits)
+   \ooo = octal number (ooo is 1 to 3 digits)
    \xhh = hexadecimal number (hhh is 1 to 2 digits)
    \uhhhh = 16-bit Unicode character (hhhh is 4 digits)
    \Uhhhhhhhh = 32-bit Unicode character (hhhhhhhh is 8 digits)
 
    Additional directive:
 
-   %b = print an argument string, interpreting backslash escapes
+   %b = print an argument string, interpreting backslash escapes,
+     except that octal escapes are of the form \0 or \0ooo.
 
    The `format' argument is re-used as many times as necessary
    to convert all of the given arguments.
@@ -113,7 +114,7 @@ Print ARGUMENT(s) according to FORMAT.\n
 FORMAT controls the output as in C printf.  Interpreted sequences are:\n\
 \n\
   \\\"      double quote\n\
-  \\0NNN   character with octal value NNN (0 to 3 digits)\n\
+  \\NNN    character with octal value NNN (1 to 3 digits)\n\
   \\\\      backslash\n\
 "), stdout);
       fputs (_("\
@@ -136,7 +137,8 @@ FORMAT controls the output as in C print
 "), stdout);
       fputs (_("\
   %%      a single %\n\
-  %b      ARGUMENT as a string with `\\' escapes interpreted\n\
+  %b      ARGUMENT as a string with `\\' escapes interpreted,\n\
+            except that octal escapes are of the form \\0 or \\0NNN\n\
 \n\
 and all C format specifications ending with one of diouxXfeEgGcs, with\n\
 ARGUMENTs converted to proper type first.  Variable widths are handled.\n\
@@ -234,10 +236,12 @@ print_esc_char (int c)
 
 /* Print a \ escape sequence starting at ESCSTART.
    Return the number of characters in the escape sequence
-   besides the backslash. */
+   besides the backslash.
+   If OCTAL0 is nonzero, octal escapes are of the form \0ooo, where o
+   is an octal digit; otherwise they are of the form \ooo.  */
 
 static int
-print_esc (const char *escstart)
+print_esc (const char *escstart, bool octal0)
 {
   register const char *p = escstart + 1;
   int esc_value = 0;           /* Value of \nnn escape. */
@@ -254,11 +258,12 @@ print_esc (const char *escstart)
        error (EXIT_FAILURE, 0, _("missing hexadecimal number in escape"));
       putchar (esc_value);
     }
-  else if (*p == '0')
+  else if (isodigit (*p))
     {
-      /* An octal \0ooo escape sequence has 0 to 3 octal digits
-        after the leading \0.  */
-      for (esc_length = 0, ++p;
+      /* Parse \0ooo (if octal0 && *p == '0') or \ooo (otherwise).
+         Allow \ooo if octal0 && *p != '0'; this is an undocumented
+         extension to POSIX that is compatible with Bash 2.05b.  */
+      for (esc_length = 0, p += octal0 && *p == '0';
           esc_length < 3 && isodigit (*p);
           ++esc_length, ++p)
        esc_value = esc_value * 8 + octtobin (*p);
@@ -313,7 +318,7 @@ print_esc_string (const char *str)
 {
   for (; *str; str++)
     if (*str == '\\')
-      str += print_esc (str);
+      str += print_esc (str, true);
     else
       putchar (*str);
 }
@@ -531,7 +536,7 @@ print_formatted (const char *format, int
          break;
 
        case '\\':
-         f += print_esc (f);
+         f += print_esc (f, false);
          break;
 
        default:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]