switch ixp4xx and ubicom32 to 2.6.30, get rid of 2.6.28 files
[openwrt.git] / target / linux / generic-2.6 / patches-2.6.28 / 981-vsprintf_backport.patch
diff --git a/target/linux/generic-2.6/patches-2.6.28/981-vsprintf_backport.patch b/target/linux/generic-2.6/patches-2.6.28/981-vsprintf_backport.patch
deleted file mode 100644 (file)
index 37589b1..0000000
+++ /dev/null
@@ -1,888 +0,0 @@
---- a/lib/vsprintf.c
-+++ b/lib/vsprintf.c
-@@ -170,6 +170,8 @@ int strict_strtoul(const char *cp, unsig
-               return -EINVAL;
-       val = simple_strtoul(cp, &tail, base);
-+      if (tail == cp)
-+              return -EINVAL;
-       if ((*tail == '\0') ||
-               ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
-               *res = val;
-@@ -241,6 +243,8 @@ int strict_strtoull(const char *cp, unsi
-               return -EINVAL;
-       val = simple_strtoull(cp, &tail, base);
-+      if (tail == cp)
-+              return -EINVAL;
-       if ((*tail == '\0') ||
-               ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
-               *res = val;
-@@ -392,7 +396,38 @@ static noinline char* put_dec(char *buf,
- #define SMALL 32              /* Must be 32 == 0x20 */
- #define SPECIAL       64              /* 0x */
--static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
-+enum format_type {
-+      FORMAT_TYPE_NONE, /* Just a string part */
-+      FORMAT_TYPE_WIDTH,
-+      FORMAT_TYPE_PRECISION,
-+      FORMAT_TYPE_CHAR,
-+      FORMAT_TYPE_STR,
-+      FORMAT_TYPE_PTR,
-+      FORMAT_TYPE_PERCENT_CHAR,
-+      FORMAT_TYPE_INVALID,
-+      FORMAT_TYPE_LONG_LONG,
-+      FORMAT_TYPE_ULONG,
-+      FORMAT_TYPE_LONG,
-+      FORMAT_TYPE_USHORT,
-+      FORMAT_TYPE_SHORT,
-+      FORMAT_TYPE_UINT,
-+      FORMAT_TYPE_INT,
-+      FORMAT_TYPE_NRCHARS,
-+      FORMAT_TYPE_SIZE_T,
-+      FORMAT_TYPE_PTRDIFF
-+};
-+
-+struct printf_spec {
-+      enum format_type        type;
-+      int                     flags;          /* flags to number() */
-+      int                     field_width;    /* width of output field */
-+      int                     base;
-+      int                     precision;      /* # of digits/chars */
-+      int                     qualifier;
-+};
-+
-+static char *number(char *buf, char *end, unsigned long long num,
-+                      struct printf_spec spec)
- {
-       /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
-       static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
-@@ -400,32 +435,32 @@ static char *number(char *buf, char *end
-       char tmp[66];
-       char sign;
-       char locase;
--      int need_pfx = ((type & SPECIAL) && base != 10);
-+      int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
-       int i;
-       /* locase = 0 or 0x20. ORing digits or letters with 'locase'
-        * produces same digits or (maybe lowercased) letters */
--      locase = (type & SMALL);
--      if (type & LEFT)
--              type &= ~ZEROPAD;
-+      locase = (spec.flags & SMALL);
-+      if (spec.flags & LEFT)
-+              spec.flags &= ~ZEROPAD;
-       sign = 0;
--      if (type & SIGN) {
-+      if (spec.flags & SIGN) {
-               if ((signed long long) num < 0) {
-                       sign = '-';
-                       num = - (signed long long) num;
--                      size--;
--              } else if (type & PLUS) {
-+                      spec.field_width--;
-+              } else if (spec.flags & PLUS) {
-                       sign = '+';
--                      size--;
--              } else if (type & SPACE) {
-+                      spec.field_width--;
-+              } else if (spec.flags & SPACE) {
-                       sign = ' ';
--                      size--;
-+                      spec.field_width--;
-               }
-       }
-       if (need_pfx) {
--              size--;
--              if (base == 16)
--                      size--;
-+              spec.field_width--;
-+              if (spec.base == 16)
-+                      spec.field_width--;
-       }
-       /* generate full string in tmp[], in reverse order */
-@@ -437,10 +472,10 @@ static char *number(char *buf, char *end
-               tmp[i++] = (digits[do_div(num,base)] | locase);
-       } while (num != 0);
-       */
--      else if (base != 10) { /* 8 or 16 */
--              int mask = base - 1;
-+      else if (spec.base != 10) { /* 8 or 16 */
-+              int mask = spec.base - 1;
-               int shift = 3;
--              if (base == 16) shift = 4;
-+              if (spec.base == 16) shift = 4;
-               do {
-                       tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
-                       num >>= shift;
-@@ -450,12 +485,12 @@ static char *number(char *buf, char *end
-       }
-       /* printing 100 using %2d gives "100", not "00" */
--      if (i > precision)
--              precision = i;
-+      if (i > spec.precision)
-+              spec.precision = i;
-       /* leading space padding */
--      size -= precision;
--      if (!(type & (ZEROPAD+LEFT))) {
--              while(--size >= 0) {
-+      spec.field_width -= spec.precision;
-+      if (!(spec.flags & (ZEROPAD+LEFT))) {
-+              while(--spec.field_width >= 0) {
-                       if (buf < end)
-                               *buf = ' ';
-                       ++buf;
-@@ -472,23 +507,23 @@ static char *number(char *buf, char *end
-               if (buf < end)
-                       *buf = '0';
-               ++buf;
--              if (base == 16) {
-+              if (spec.base == 16) {
-                       if (buf < end)
-                               *buf = ('X' | locase);
-                       ++buf;
-               }
-       }
-       /* zero or space padding */
--      if (!(type & LEFT)) {
--              char c = (type & ZEROPAD) ? '0' : ' ';
--              while (--size >= 0) {
-+      if (!(spec.flags & LEFT)) {
-+              char c = (spec.flags & ZEROPAD) ? '0' : ' ';
-+              while (--spec.field_width >= 0) {
-                       if (buf < end)
-                               *buf = c;
-                       ++buf;
-               }
-       }
-       /* hmm even more zero padding? */
--      while (i <= --precision) {
-+      while (i <= --spec.precision) {
-               if (buf < end)
-                       *buf = '0';
-               ++buf;
-@@ -500,7 +535,7 @@ static char *number(char *buf, char *end
-               ++buf;
-       }
-       /* trailing space padding */
--      while (--size >= 0) {
-+      while (--spec.field_width >= 0) {
-               if (buf < end)
-                       *buf = ' ';
-               ++buf;
-@@ -508,17 +543,17 @@ static char *number(char *buf, char *end
-       return buf;
- }
--static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags)
-+static char *string(char *buf, char *end, char *s, struct printf_spec spec)
- {
-       int len, i;
-       if ((unsigned long)s < PAGE_SIZE)
-               s = "<NULL>";
--      len = strnlen(s, precision);
-+      len = strnlen(s, spec.precision);
--      if (!(flags & LEFT)) {
--              while (len < field_width--) {
-+      if (!(spec.flags & LEFT)) {
-+              while (len < spec.field_width--) {
-                       if (buf < end)
-                               *buf = ' ';
-                       ++buf;
-@@ -529,7 +564,7 @@ static char *string(char *buf, char *end
-                       *buf = *s;
-               ++buf; ++s;
-       }
--      while (len < field_width--) {
-+      while (len < spec.field_width--) {
-               if (buf < end)
-                       *buf = ' ';
-               ++buf;
-@@ -537,21 +572,24 @@ static char *string(char *buf, char *end
-       return buf;
- }
--static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags)
-+static char *symbol_string(char *buf, char *end, void *ptr,
-+                              struct printf_spec spec)
- {
-       unsigned long value = (unsigned long) ptr;
- #ifdef CONFIG_KALLSYMS
-       char sym[KSYM_SYMBOL_LEN];
-       sprint_symbol(sym, value);
--      return string(buf, end, sym, field_width, precision, flags);
-+      return string(buf, end, sym, spec);
- #else
--      field_width = 2*sizeof(void *);
--      flags |= SPECIAL | SMALL | ZEROPAD;
--      return number(buf, end, value, 16, field_width, precision, flags);
-+      spec.field_width = 2*sizeof(void *);
-+      spec.flags |= SPECIAL | SMALL | ZEROPAD;
-+      spec.base = 16;
-+      return number(buf, end, value, spec);
- #endif
- }
--static char *resource_string(char *buf, char *end, struct resource *res, int field_width, int precision, int flags)
-+static char *resource_string(char *buf, char *end, struct resource *res,
-+                              struct printf_spec spec)
- {
- #ifndef IO_RSRC_PRINTK_SIZE
- #define IO_RSRC_PRINTK_SIZE   4
-@@ -560,7 +598,11 @@ static char *resource_string(char *buf, 
- #ifndef MEM_RSRC_PRINTK_SIZE
- #define MEM_RSRC_PRINTK_SIZE  8
- #endif
--
-+      struct printf_spec num_spec = {
-+              .base = 16,
-+              .precision = -1,
-+              .flags = SPECIAL | SMALL | ZEROPAD,
-+      };
-       /* room for the actual numbers, the two "0x", -, [, ] and the final zero */
-       char sym[4*sizeof(resource_size_t) + 8];
-       char *p = sym, *pend = sym + sizeof(sym);
-@@ -572,13 +614,73 @@ static char *resource_string(char *buf, 
-               size = MEM_RSRC_PRINTK_SIZE;
-       *p++ = '[';
--      p = number(p, pend, res->start, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
-+      num_spec.field_width = size;
-+      p = number(p, pend, res->start, num_spec);
-       *p++ = '-';
--      p = number(p, pend, res->end, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
-+      p = number(p, pend, res->end, num_spec);
-       *p++ = ']';
-       *p = 0;
--      return string(buf, end, sym, field_width, precision, flags);
-+      return string(buf, end, sym, spec);
-+}
-+
-+static char *mac_address_string(char *buf, char *end, u8 *addr,
-+                              struct printf_spec spec)
-+{
-+      char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */
-+      char *p = mac_addr;
-+      int i;
-+
-+      for (i = 0; i < 6; i++) {
-+              p = pack_hex_byte(p, addr[i]);
-+              if (!(spec.flags & SPECIAL) && i != 5)
-+                      *p++ = ':';
-+      }
-+      *p = '\0';
-+      spec.flags &= ~SPECIAL;
-+
-+      return string(buf, end, mac_addr, spec);
-+}
-+
-+static char *ip6_addr_string(char *buf, char *end, u8 *addr,
-+                              struct printf_spec spec)
-+{
-+      char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
-+      char *p = ip6_addr;
-+      int i;
-+
-+      for (i = 0; i < 8; i++) {
-+              p = pack_hex_byte(p, addr[2 * i]);
-+              p = pack_hex_byte(p, addr[2 * i + 1]);
-+              if (!(spec.flags & SPECIAL) && i != 7)
-+                      *p++ = ':';
-+      }
-+      *p = '\0';
-+      spec.flags &= ~SPECIAL;
-+
-+      return string(buf, end, ip6_addr, spec);
-+}
-+
-+static char *ip4_addr_string(char *buf, char *end, u8 *addr,
-+                              struct printf_spec spec)
-+{
-+      char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */
-+      char temp[3];   /* hold each IP quad in reverse order */
-+      char *p = ip4_addr;
-+      int i, digits;
-+
-+      for (i = 0; i < 4; i++) {
-+              digits = put_dec_trunc(temp, addr[i]) - temp;
-+              /* reverse the digits in the quad */
-+              while (digits--)
-+                      *p++ = temp[digits];
-+              if (i != 3)
-+                      *p++ = '.';
-+      }
-+      *p = '\0';
-+      spec.flags &= ~SPECIAL;
-+
-+      return string(buf, end, ip4_addr, spec);
- }
- /*
-@@ -592,28 +694,244 @@ static char *resource_string(char *buf, 
-  * - 'S' For symbolic direct pointers
-  * - 'R' For a struct resource pointer, it prints the range of
-  *       addresses (not the name nor the flags)
-+ * - 'M' For a 6-byte MAC address, it prints the address in the
-+ *       usual colon-separated hex notation
-+ * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated
-+ *       decimal for v4 and colon separated network-order 16 bit hex for v6)
-+ * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
-+ *       currently the same
-  *
-  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
-  * function pointers are really function descriptors, which contain a
-  * pointer to the real address.
-  */
--static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags)
-+static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
-+                      struct printf_spec spec)
- {
-+      if (!ptr)
-+              return string(buf, end, "(null)", spec);
-+
-       switch (*fmt) {
-       case 'F':
-               ptr = dereference_function_descriptor(ptr);
-               /* Fallthrough */
-       case 'S':
--              return symbol_string(buf, end, ptr, field_width, precision, flags);
-+              return symbol_string(buf, end, ptr, spec);
-       case 'R':
--              return resource_string(buf, end, ptr, field_width, precision, flags);
-+              return resource_string(buf, end, ptr, spec);
-+      case 'm':
-+              spec.flags |= SPECIAL;
-+              /* Fallthrough */
-+      case 'M':
-+              return mac_address_string(buf, end, ptr, spec);
-+      case 'i':
-+              spec.flags |= SPECIAL;
-+              /* Fallthrough */
-+      case 'I':
-+              if (fmt[1] == '6')
-+                      return ip6_addr_string(buf, end, ptr, spec);
-+              if (fmt[1] == '4')
-+                      return ip4_addr_string(buf, end, ptr, spec);
-+              spec.flags &= ~SPECIAL;
-+              break;
-       }
--      flags |= SMALL;
--      if (field_width == -1) {
--              field_width = 2*sizeof(void *);
--              flags |= ZEROPAD;
-+      spec.flags |= SMALL;
-+      if (spec.field_width == -1) {
-+              spec.field_width = 2*sizeof(void *);
-+              spec.flags |= ZEROPAD;
-       }
--      return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags);
-+      spec.base = 16;
-+
-+      return number(buf, end, (unsigned long) ptr, spec);
-+}
-+
-+/*
-+ * Helper function to decode printf style format.
-+ * Each call decode a token from the format and return the
-+ * number of characters read (or likely the delta where it wants
-+ * to go on the next call).
-+ * The decoded token is returned through the parameters
-+ *
-+ * 'h', 'l', or 'L' for integer fields
-+ * 'z' support added 23/7/1999 S.H.
-+ * 'z' changed to 'Z' --davidm 1/25/99
-+ * 't' added for ptrdiff_t
-+ *
-+ * @fmt: the format string
-+ * @type of the token returned
-+ * @flags: various flags such as +, -, # tokens..
-+ * @field_width: overwritten width
-+ * @base: base of the number (octal, hex, ...)
-+ * @precision: precision of a number
-+ * @qualifier: qualifier of a number (long, size_t, ...)
-+ */
-+static int format_decode(const char *fmt, struct printf_spec *spec)
-+{
-+      const char *start = fmt;
-+
-+      /* we finished early by reading the field width */
-+      if (spec->type == FORMAT_TYPE_WIDTH) {
-+              if (spec->field_width < 0) {
-+                      spec->field_width = -spec->field_width;
-+                      spec->flags |= LEFT;
-+              }
-+              spec->type = FORMAT_TYPE_NONE;
-+              goto precision;
-+      }
-+
-+      /* we finished early by reading the precision */
-+      if (spec->type == FORMAT_TYPE_PRECISION) {
-+              if (spec->precision < 0)
-+                      spec->precision = 0;
-+
-+              spec->type = FORMAT_TYPE_NONE;
-+              goto qualifier;
-+      }
-+
-+      /* By default */
-+      spec->type = FORMAT_TYPE_NONE;
-+
-+      for (; *fmt ; ++fmt) {
-+              if (*fmt == '%')
-+                      break;
-+      }
-+
-+      /* Return the current non-format string */
-+      if (fmt != start || !*fmt)
-+              return fmt - start;
-+
-+      /* Process flags */
-+      spec->flags = 0;
-+
-+      while (1) { /* this also skips first '%' */
-+              bool found = true;
-+
-+              ++fmt;
-+
-+              switch (*fmt) {
-+              case '-': spec->flags |= LEFT;    break;
-+              case '+': spec->flags |= PLUS;    break;
-+              case ' ': spec->flags |= SPACE;   break;
-+              case '#': spec->flags |= SPECIAL; break;
-+              case '0': spec->flags |= ZEROPAD; break;
-+              default:  found = false;
-+              }
-+
-+              if (!found)
-+                      break;
-+      }
-+
-+      /* get field width */
-+      spec->field_width = -1;
-+
-+      if (isdigit(*fmt))
-+              spec->field_width = skip_atoi(&fmt);
-+      else if (*fmt == '*') {
-+              /* it's the next argument */
-+              spec->type = FORMAT_TYPE_WIDTH;
-+              return ++fmt - start;
-+      }
-+
-+precision:
-+      /* get the precision */
-+      spec->precision = -1;
-+      if (*fmt == '.') {
-+              ++fmt;
-+              if (isdigit(*fmt)) {
-+                      spec->precision = skip_atoi(&fmt);
-+                      if (spec->precision < 0)
-+                              spec->precision = 0;
-+              } else if (*fmt == '*') {
-+                      /* it's the next argument */
-+                      spec->type = FORMAT_TYPE_PRECISION;
-+                      return ++fmt - start;
-+              }
-+      }
-+
-+qualifier:
-+      /* get the conversion qualifier */
-+      spec->qualifier = -1;
-+      if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
-+          *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
-+              spec->qualifier = *fmt;
-+              ++fmt;
-+              if (spec->qualifier == 'l' && *fmt == 'l') {
-+                      spec->qualifier = 'L';
-+                      ++fmt;
-+              }
-+      }
-+
-+      /* default base */
-+      spec->base = 10;
-+      switch (*fmt) {
-+      case 'c':
-+              spec->type = FORMAT_TYPE_CHAR;
-+              return ++fmt - start;
-+
-+      case 's':
-+              spec->type = FORMAT_TYPE_STR;
-+              return ++fmt - start;
-+
-+      case 'p':
-+              spec->type = FORMAT_TYPE_PTR;
-+              return fmt - start;
-+              /* skip alnum */
-+
-+      case 'n':
-+              spec->type = FORMAT_TYPE_NRCHARS;
-+              return ++fmt - start;
-+
-+      case '%':
-+              spec->type = FORMAT_TYPE_PERCENT_CHAR;
-+              return ++fmt - start;
-+
-+      /* integer number formats - set up the flags and "break" */
-+      case 'o':
-+              spec->base = 8;
-+              break;
-+
-+      case 'x':
-+              spec->flags |= SMALL;
-+
-+      case 'X':
-+              spec->base = 16;
-+              break;
-+
-+      case 'd':
-+      case 'i':
-+              spec->flags |= SIGN;
-+      case 'u':
-+              break;
-+
-+      default:
-+              spec->type = FORMAT_TYPE_INVALID;
-+              return fmt - start;
-+      }
-+
-+      if (spec->qualifier == 'L')
-+              spec->type = FORMAT_TYPE_LONG_LONG;
-+      else if (spec->qualifier == 'l') {
-+              if (spec->flags & SIGN)
-+                      spec->type = FORMAT_TYPE_LONG;
-+              else
-+                      spec->type = FORMAT_TYPE_ULONG;
-+      } else if (spec->qualifier == 'Z' || spec->qualifier == 'z') {
-+              spec->type = FORMAT_TYPE_SIZE_T;
-+      } else if (spec->qualifier == 't') {
-+              spec->type = FORMAT_TYPE_PTRDIFF;
-+      } else if (spec->qualifier == 'h') {
-+              if (spec->flags & SIGN)
-+                      spec->type = FORMAT_TYPE_SHORT;
-+              else
-+                      spec->type = FORMAT_TYPE_USHORT;
-+      } else {
-+              if (spec->flags & SIGN)
-+                      spec->type = FORMAT_TYPE_INT;
-+              else
-+                      spec->type = FORMAT_TYPE_UINT;
-+      }
-+
-+      return ++fmt - start;
- }
- /**
-@@ -642,18 +960,9 @@ static char *pointer(const char *fmt, ch
- int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
- {
-       unsigned long long num;
--      int base;
-       char *str, *end, c;
--
--      int flags;              /* flags to number() */
--
--      int field_width;        /* width of output field */
--      int precision;          /* min. # of digits for integers; max
--                                 number of chars for from string */
--      int qualifier;          /* 'h', 'l', or 'L' for integer fields */
--                              /* 'z' support added 23/7/1999 S.H.    */
--                              /* 'z' changed to 'Z' --davidm 1/25/99 */
--                              /* 't' added for ptrdiff_t */
-+      int read;
-+      struct printf_spec spec = {0};
-       /* Reject out-of-range values early.  Large positive sizes are
-          used for unknown buffer sizes. */
-@@ -674,184 +983,137 @@ int vsnprintf(char *buf, size_t size, co
-               size = end - buf;
-       }
--      for (; *fmt ; ++fmt) {
--              if (*fmt != '%') {
--                      if (str < end)
--                              *str = *fmt;
--                      ++str;
--                      continue;
--              }
-+      while (*fmt) {
-+              const char *old_fmt = fmt;
--              /* process flags */
--              flags = 0;
--              repeat:
--                      ++fmt;          /* this also skips first '%' */
--                      switch (*fmt) {
--                              case '-': flags |= LEFT; goto repeat;
--                              case '+': flags |= PLUS; goto repeat;
--                              case ' ': flags |= SPACE; goto repeat;
--                              case '#': flags |= SPECIAL; goto repeat;
--                              case '0': flags |= ZEROPAD; goto repeat;
--                      }
-+              read = format_decode(fmt, &spec);
--              /* get field width */
--              field_width = -1;
--              if (isdigit(*fmt))
--                      field_width = skip_atoi(&fmt);
--              else if (*fmt == '*') {
--                      ++fmt;
--                      /* it's the next argument */
--                      field_width = va_arg(args, int);
--                      if (field_width < 0) {
--                              field_width = -field_width;
--                              flags |= LEFT;
--                      }
--              }
-+              fmt += read;
--              /* get the precision */
--              precision = -1;
--              if (*fmt == '.') {
--                      ++fmt;  
--                      if (isdigit(*fmt))
--                              precision = skip_atoi(&fmt);
--                      else if (*fmt == '*') {
--                              ++fmt;
--                              /* it's the next argument */
--                              precision = va_arg(args, int);
-+              switch (spec.type) {
-+              case FORMAT_TYPE_NONE: {
-+                      int copy = read;
-+                      if (str < end) {
-+                              if (copy > end - str)
-+                                      copy = end - str;
-+                              memcpy(str, old_fmt, copy);
-                       }
--                      if (precision < 0)
--                              precision = 0;
-+                      str += read;
-+                      break;
-               }
--              /* get the conversion qualifier */
--              qualifier = -1;
--              if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
--                  *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
--                      qualifier = *fmt;
--                      ++fmt;
--                      if (qualifier == 'l' && *fmt == 'l') {
--                              qualifier = 'L';
--                              ++fmt;
--                      }
--              }
-+              case FORMAT_TYPE_WIDTH:
-+                      spec.field_width = va_arg(args, int);
-+                      break;
--              /* default base */
--              base = 10;
-+              case FORMAT_TYPE_PRECISION:
-+                      spec.precision = va_arg(args, int);
-+                      break;
--              switch (*fmt) {
--                      case 'c':
--                              if (!(flags & LEFT)) {
--                                      while (--field_width > 0) {
--                                              if (str < end)
--                                                      *str = ' ';
--                                              ++str;
--                                      }
--                              }
--                              c = (unsigned char) va_arg(args, int);
--                              if (str < end)
--                                      *str = c;
--                              ++str;
--                              while (--field_width > 0) {
-+              case FORMAT_TYPE_CHAR:
-+                      if (!(spec.flags & LEFT)) {
-+                              while (--spec.field_width > 0) {
-                                       if (str < end)
-                                               *str = ' ';
-                                       ++str;
--                              }
--                              continue;
--
--                      case 's':
--                              str = string(str, end, va_arg(args, char *), field_width, precision, flags);
--                              continue;
--
--                      case 'p':
--                              str = pointer(fmt+1, str, end,
--                                              va_arg(args, void *),
--                                              field_width, precision, flags);
--                              /* Skip all alphanumeric pointer suffixes */
--                              while (isalnum(fmt[1]))
--                                      fmt++;
--                              continue;
--                      case 'n':
--                              /* FIXME:
--                              * What does C99 say about the overflow case here? */
--                              if (qualifier == 'l') {
--                                      long * ip = va_arg(args, long *);
--                                      *ip = (str - buf);
--                              } else if (qualifier == 'Z' || qualifier == 'z') {
--                                      size_t * ip = va_arg(args, size_t *);
--                                      *ip = (str - buf);
--                              } else {
--                                      int * ip = va_arg(args, int *);
--                                      *ip = (str - buf);
-                               }
--                              continue;
--
--                      case '%':
-+                      }
-+                      c = (unsigned char) va_arg(args, int);
-+                      if (str < end)
-+                              *str = c;
-+                      ++str;
-+                      while (--spec.field_width > 0) {
-                               if (str < end)
--                                      *str = '%';
-+                                      *str = ' ';
-                               ++str;
--                              continue;
-+                      }
-+                      break;
--                              /* integer number formats - set up the flags and "break" */
--                      case 'o':
--                              base = 8;
--                              break;
-+              case FORMAT_TYPE_STR:
-+                      str = string(str, end, va_arg(args, char *), spec);
-+                      break;
--                      case 'x':
--                              flags |= SMALL;
--                      case 'X':
--                              base = 16;
--                              break;
-+              case FORMAT_TYPE_PTR:
-+                      str = pointer(fmt+1, str, end, va_arg(args, void *),
-+                                    spec);
-+                      while (isalnum(*fmt))
-+                              fmt++;
-+                      break;
--                      case 'd':
--                      case 'i':
--                              flags |= SIGN;
--                      case 'u':
--                              break;
-+              case FORMAT_TYPE_PERCENT_CHAR:
-+                      if (str < end)
-+                              *str = '%';
-+                      ++str;
-+                      break;
--                      default:
--                              if (str < end)
--                                      *str = '%';
--                              ++str;
--                              if (*fmt) {
--                                      if (str < end)
--                                              *str = *fmt;
--                                      ++str;
--                              } else {
--                                      --fmt;
--                              }
--                              continue;
-+              case FORMAT_TYPE_INVALID:
-+                      if (str < end)
-+                              *str = '%';
-+                      ++str;
-+                      break;
-+
-+              case FORMAT_TYPE_NRCHARS: {
-+                      int qualifier = spec.qualifier;
-+
-+                      if (qualifier == 'l') {
-+                              long *ip = va_arg(args, long *);
-+                              *ip = (str - buf);
-+                      } else if (qualifier == 'Z' ||
-+                                      qualifier == 'z') {
-+                              size_t *ip = va_arg(args, size_t *);
-+                              *ip = (str - buf);
-+                      } else {
-+                              int *ip = va_arg(args, int *);
-+                              *ip = (str - buf);
-+                      }
-+                      break;
-               }
--              if (qualifier == 'L')
--                      num = va_arg(args, long long);
--              else if (qualifier == 'l') {
--                      num = va_arg(args, unsigned long);
--                      if (flags & SIGN)
--                              num = (signed long) num;
--              } else if (qualifier == 'Z' || qualifier == 'z') {
--                      num = va_arg(args, size_t);
--              } else if (qualifier == 't') {
--                      num = va_arg(args, ptrdiff_t);
--              } else if (qualifier == 'h') {
--                      num = (unsigned short) va_arg(args, int);
--                      if (flags & SIGN)
--                              num = (signed short) num;
--              } else {
--                      num = va_arg(args, unsigned int);
--                      if (flags & SIGN)
--                              num = (signed int) num;
-+
-+              default:
-+                      switch (spec.type) {
-+                      case FORMAT_TYPE_LONG_LONG:
-+                              num = va_arg(args, long long);
-+                              break;
-+                      case FORMAT_TYPE_ULONG:
-+                              num = va_arg(args, unsigned long);
-+                              break;
-+                      case FORMAT_TYPE_LONG:
-+                              num = va_arg(args, long);
-+                              break;
-+                      case FORMAT_TYPE_SIZE_T:
-+                              num = va_arg(args, size_t);
-+                              break;
-+                      case FORMAT_TYPE_PTRDIFF:
-+                              num = va_arg(args, ptrdiff_t);
-+                              break;
-+                      case FORMAT_TYPE_USHORT:
-+                              num = (unsigned short) va_arg(args, int);
-+                              break;
-+                      case FORMAT_TYPE_SHORT:
-+                              num = (short) va_arg(args, int);
-+                              break;
-+                      case FORMAT_TYPE_INT:
-+                              num = (int) va_arg(args, int);
-+                              break;
-+                      default:
-+                              num = va_arg(args, unsigned int);
-+                      }
-+
-+                      str = number(str, end, num, spec);
-               }
--              str = number(str, end, num, base,
--                              field_width, precision, flags);
-       }
-+
-       if (size > 0) {
-               if (str < end)
-                       *str = '\0';
-               else
-                       end[-1] = '\0';
-       }
-+
-       /* the trailing null byte doesn't count towards the total */
-       return str-buf;
-+
- }
- EXPORT_SYMBOL(vsnprintf);