OSDN Git Service

Fix a bug (octal digits are 0-7, not 0-8) and deal with a case where posix
authorRob Landley <rob@landley.net>
Mon, 4 Jul 2016 07:59:09 +0000 (02:59 -0500)
committerRob Landley <rob@landley.net>
Mon, 4 Jul 2016 07:59:09 +0000 (02:59 -0500)
is explicitly outright insane (%b handles octal escapes differently for no
obvious reason).

tests/printf.test
toys/posix/printf.c

index 7b077f0..a333174 100755 (executable)
@@ -59,3 +59,9 @@ testing "'%g %G' 78 79" "$PRINTF '%g %G' 78 79" "78 79" "" ""
 testing "'%s %s' 78 79" "$PRINTF '%s %s' 78 79" "78 79" "" ""
 
 testing "%.s acts like %.0s" "$PRINTF %.s_ 1 2 3 4 5" "_____" "" ""
+testing "corner case" "$PRINTF '\\8'" '\8' '' ''
+
+# The posix spec explicitly specifies inconsistent behavior,
+# so treating the \0066 in %b like the \0066 not in %b is wrong because posix.
+testing "printf posix inconsistency" "$PRINTF '\\0066-%b' '\\0066'" "\x066-6" \
+  "" ""
index 365b8f3..2dd1e2f 100644 (file)
@@ -33,7 +33,7 @@ static int eat(char **s, char c)
 }
 
 // Parse escape sequences.
-static int handle_slash(char **esc_val)
+static int handle_slash(char **esc_val, int posix)
 {
   char *ptr = *esc_val;
   int len, base = 0;
@@ -43,7 +43,10 @@ static int handle_slash(char **esc_val)
 
   // 0x12 hex escapes have 1-2 digits, \123 octal escapes have 1-3 digits.
   if (eat(&ptr, 'x')) base = 16;
-  else if (*ptr >= '0' && *ptr <= '8') base = 8;
+  else {
+    if (posix && *ptr=='0') ptr++;
+    if (*ptr >= '0' && *ptr <= '7') base = 8;
+  }
   len = (char []){0,3,2}[base/8];
 
   // Not a hex or octal escape? (This catches trailing \)
@@ -85,7 +88,7 @@ void printf_main(void)
 
     // Loop through characters in format
     while (*f) {
-      if (eat(&f, '\\')) putchar(handle_slash(&f));
+      if (eat(&f, '\\')) putchar(handle_slash(&f, 0));
       else if (!eat(&f, '%') || *f == '%') putchar(*f++);
 
       // Handle %escape
@@ -110,7 +113,7 @@ void printf_main(void)
 
         // Output %esc using parsed format string
         if (c == 'b') {
-          while (*aa) putchar(eat(&aa, '\\') ? handle_slash(&aa) : *aa++);
+          while (*aa) putchar(eat(&aa, '\\') ? handle_slash(&aa, 1) : *aa++);
 
           continue;
         } else if (c == 'c') printf(toybuf, wp[0], wp[1], *aa);