block: Fix overrun in lcm() and move it to lib
[safe/jmp/linux-2.6] / lib / vsprintf.c
index add0446..0d461c7 100644 (file)
@@ -381,8 +381,8 @@ static noinline char *put_dec(char *buf, unsigned long long num)
 #define PLUS   4               /* show plus */
 #define SPACE  8               /* space if plus */
 #define LEFT   16              /* left justified */
-#define SMALL  32              /* Must be 32 == 0x20 */
-#define SPECIAL        64              /* 0x */
+#define SMALL  32              /* use lowercase in hex (must be 32 == 0x20) */
+#define SPECIAL        64              /* prefix hex with "0x", octal with "0" */
 
 enum format_type {
        FORMAT_TYPE_NONE, /* Just a string part */
@@ -408,12 +408,12 @@ enum format_type {
 };
 
 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;
+       u16     type;
+       s16     field_width;    /* width of output field */
+       u8      flags;          /* flags to number() */
+       u8      base;
+       s8      precision;      /* # of digits/chars */
+       u8      qualifier;
 };
 
 static char *number(char *buf, char *end, unsigned long long num,
@@ -597,22 +597,29 @@ static char *resource_string(char *buf, char *end, struct resource *res,
 #ifndef MEM_RSRC_PRINTK_SIZE
 #define MEM_RSRC_PRINTK_SIZE   10
 #endif
-       struct printf_spec hex_spec = {
+       static const struct printf_spec io_spec = {
                .base = 16,
+               .field_width = IO_RSRC_PRINTK_SIZE,
                .precision = -1,
                .flags = SPECIAL | SMALL | ZEROPAD,
        };
-       struct printf_spec dec_spec = {
+       static const struct printf_spec mem_spec = {
+               .base = 16,
+               .field_width = MEM_RSRC_PRINTK_SIZE,
+               .precision = -1,
+               .flags = SPECIAL | SMALL | ZEROPAD,
+       };
+       static const struct printf_spec dec_spec = {
                .base = 10,
                .precision = -1,
                .flags = 0,
        };
-       struct printf_spec str_spec = {
+       static const struct printf_spec str_spec = {
                .field_width = -1,
                .precision = 10,
                .flags = LEFT,
        };
-       struct printf_spec flag_spec = {
+       static const struct printf_spec flag_spec = {
                .base = 16,
                .precision = -1,
                .flags = SPECIAL | SMALL,
@@ -628,35 +635,31 @@ static char *resource_string(char *buf, char *end, struct resource *res,
                     2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
 
        char *p = sym, *pend = sym + sizeof(sym);
-       int size = -1, addr = 0;
        int decode = (fmt[0] == 'R') ? 1 : 0;
-
-       if (res->flags & IORESOURCE_IO) {
-               size = IO_RSRC_PRINTK_SIZE;
-               addr = 1;
-       } else if (res->flags & IORESOURCE_MEM) {
-               size = MEM_RSRC_PRINTK_SIZE;
-               addr = 1;
-       }
+       const struct printf_spec *specp;
 
        *p++ = '[';
-       if (res->flags & IORESOURCE_IO)
+       if (res->flags & IORESOURCE_IO) {
                p = string(p, pend, "io  ", str_spec);
-       else if (res->flags & IORESOURCE_MEM)
+               specp = &io_spec;
+       } else if (res->flags & IORESOURCE_MEM) {
                p = string(p, pend, "mem ", str_spec);
-       else if (res->flags & IORESOURCE_IRQ)
+               specp = &mem_spec;
+       } else if (res->flags & IORESOURCE_IRQ) {
                p = string(p, pend, "irq ", str_spec);
-       else if (res->flags & IORESOURCE_DMA)
+               specp = &dec_spec;
+       } else if (res->flags & IORESOURCE_DMA) {
                p = string(p, pend, "dma ", str_spec);
-       else {
+               specp = &dec_spec;
+       } else {
                p = string(p, pend, "??? ", str_spec);
+               specp = &mem_spec;
                decode = 0;
        }
-       hex_spec.field_width = size;
-       p = number(p, pend, res->start, addr ? hex_spec : dec_spec);
+       p = number(p, pend, res->start, *specp);
        if (res->start != res->end) {
                *p++ = '-';
-               p = number(p, pend, res->end, addr ? hex_spec : dec_spec);
+               p = number(p, pend, res->end, *specp);
        }
        if (decode) {
                if (res->flags & IORESOURCE_MEM_64)
@@ -938,7 +941,7 @@ static char *uuid_string(char *buf, char *end, const u8 *addr,
  *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
  * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
  * - 'I6c' for IPv6 addresses printed as specified by
- *       http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ *       http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
  * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
  *       "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  *       Options for %pU are:
@@ -1224,7 +1227,7 @@ qualifier:
  * %pI6 print an IPv6 address with colons
  * %pi6 print an IPv6 address without colons
  * %pI6c print an IPv6 address as specified by
- *   http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ *   http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
  * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
  *   case.
  * %n is ignored
@@ -1333,7 +1336,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                        break;
 
                case FORMAT_TYPE_NRCHARS: {
-                       int qualifier = spec.qualifier;
+                       u8 qualifier = spec.qualifier;
 
                        if (qualifier == 'l') {
                                long *ip = va_arg(args, long *);
@@ -1619,7 +1622,7 @@ do {                                                                      \
 
                case FORMAT_TYPE_NRCHARS: {
                        /* skip %n 's argument */
-                       int qualifier = spec.qualifier;
+                       u8 qualifier = spec.qualifier;
                        void *skip_arg;
                        if (qualifier == 'l')
                                skip_arg = va_arg(args, long *);
@@ -1885,7 +1888,9 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
        char *next;
        char digit;
        int num = 0;
-       int qualifier, base, field_width;
+       u8 qualifier;
+       u8 base;
+       s16 field_width;
        bool is_sign;
 
        while (*fmt && *str) {
@@ -1963,7 +1968,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
                {
                        char *s = (char *)va_arg(args, char *);
                        if (field_width == -1)
-                               field_width = INT_MAX;
+                               field_width = SHORT_MAX;
                        /* first, skip leading white space in buffer */
                        str = skip_spaces(str);