]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - lib_generic/vsprintf.c
Rename lib_generic/ to lib/
[karo-tx-uboot.git] / lib_generic / vsprintf.c
diff --git a/lib_generic/vsprintf.c b/lib_generic/vsprintf.c
deleted file mode 100644 (file)
index 8c58a93..0000000
+++ /dev/null
@@ -1,681 +0,0 @@
-/*
- *  linux/lib/vsprintf.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
-/*
- * Wirzenius wrote this portably, Torvalds fucked it up :-)
- */
-
-#include <stdarg.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-
-#include <common.h>
-#if !defined (CONFIG_PANIC_HANG)
-#include <command.h>
-/*cmd_boot.c*/
-extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
-#endif
-
-#include <div64.h>
-# define NUM_TYPE long long
-#define noinline __attribute__((noinline))
-
-const char hex_asc[] = "0123456789abcdef";
-#define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
-#define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
-
-static inline char *pack_hex_byte(char *buf, u8 byte)
-{
-       *buf++ = hex_asc_hi(byte);
-       *buf++ = hex_asc_lo(byte);
-       return buf;
-}
-
-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
-{
-       unsigned long result = 0,value;
-
-       if (*cp == '0') {
-               cp++;
-               if ((*cp == 'x') && isxdigit(cp[1])) {
-                       base = 16;
-                       cp++;
-               }
-               if (!base) {
-                       base = 8;
-               }
-       }
-       if (!base) {
-               base = 10;
-       }
-       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
-           ? toupper(*cp) : *cp)-'A'+10) < base) {
-               result = result*base + value;
-               cp++;
-       }
-       if (endp)
-               *endp = (char *)cp;
-       return result;
-}
-
-long simple_strtol(const char *cp,char **endp,unsigned int base)
-{
-       if(*cp=='-')
-               return -simple_strtoul(cp+1,endp,base);
-       return simple_strtoul(cp,endp,base);
-}
-
-int ustrtoul(const char *cp, char **endp, unsigned int base)
-{
-       unsigned long result = simple_strtoul(cp, endp, base);
-       switch (**endp) {
-       case 'G' :
-               result *= 1024;
-               /* fall through */
-       case 'M':
-               result *= 1024;
-               /* fall through */
-       case 'K':
-       case 'k':
-               result *= 1024;
-               if ((*endp)[1] == 'i') {
-                       if ((*endp)[2] == 'B')
-                               (*endp) += 3;
-                       else
-                               (*endp) += 2;
-               }
-       }
-       return result;
-}
-
-unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base)
-{
-       unsigned long long result = 0, value;
-
-       if (*cp == '0') {
-               cp++;
-               if ((*cp == 'x') && isxdigit (cp[1])) {
-                       base = 16;
-                       cp++;
-               }
-               if (!base) {
-                       base = 8;
-               }
-       }
-       if (!base) {
-               base = 10;
-       }
-       while (isxdigit (*cp) && (value = isdigit (*cp)
-                               ? *cp - '0'
-                               : (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base) {
-               result = result * base + value;
-               cp++;
-       }
-       if (endp)
-               *endp = (char *) cp;
-       return result;
-}
-
-/* we use this so that we can do without the ctype library */
-#define is_digit(c)    ((c) >= '0' && (c) <= '9')
-
-static int skip_atoi(const char **s)
-{
-       int i=0;
-
-       while (is_digit(**s))
-               i = i*10 + *((*s)++) - '0';
-       return i;
-}
-
-/* Decimal conversion is by far the most typical, and is used
- * for /proc and /sys data. This directly impacts e.g. top performance
- * with many processes running. We optimize it for speed
- * using code from
- * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
- * (with permission from the author, Douglas W. Jones). */
-
-/* Formats correctly any integer in [0,99999].
- * Outputs from one to five digits depending on input.
- * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
-static char* put_dec_trunc(char *buf, unsigned q)
-{
-       unsigned d3, d2, d1, d0;
-       d1 = (q>>4) & 0xf;
-       d2 = (q>>8) & 0xf;
-       d3 = (q>>12);
-
-       d0 = 6*(d3 + d2 + d1) + (q & 0xf);
-       q = (d0 * 0xcd) >> 11;
-       d0 = d0 - 10*q;
-       *buf++ = d0 + '0'; /* least significant digit */
-       d1 = q + 9*d3 + 5*d2 + d1;
-       if (d1 != 0) {
-               q = (d1 * 0xcd) >> 11;
-               d1 = d1 - 10*q;
-               *buf++ = d1 + '0'; /* next digit */
-
-               d2 = q + 2*d2;
-               if ((d2 != 0) || (d3 != 0)) {
-                       q = (d2 * 0xd) >> 7;
-                       d2 = d2 - 10*q;
-                       *buf++ = d2 + '0'; /* next digit */
-
-                       d3 = q + 4*d3;
-                       if (d3 != 0) {
-                               q = (d3 * 0xcd) >> 11;
-                               d3 = d3 - 10*q;
-                               *buf++ = d3 + '0';  /* next digit */
-                               if (q != 0)
-                                       *buf++ = q + '0';  /* most sign. digit */
-                       }
-               }
-       }
-       return buf;
-}
-/* Same with if's removed. Always emits five digits */
-static char* put_dec_full(char *buf, unsigned q)
-{
-       /* BTW, if q is in [0,9999], 8-bit ints will be enough, */
-       /* but anyway, gcc produces better code with full-sized ints */
-       unsigned d3, d2, d1, d0;
-       d1 = (q>>4) & 0xf;
-       d2 = (q>>8) & 0xf;
-       d3 = (q>>12);
-
-       /*
-        * Possible ways to approx. divide by 10
-        * gcc -O2 replaces multiply with shifts and adds
-        * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
-        * (x * 0x67) >> 10:  1100111
-        * (x * 0x34) >> 9:    110100 - same
-        * (x * 0x1a) >> 8:     11010 - same
-        * (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
-        */
-
-       d0 = 6*(d3 + d2 + d1) + (q & 0xf);
-       q = (d0 * 0xcd) >> 11;
-       d0 = d0 - 10*q;
-       *buf++ = d0 + '0';
-       d1 = q + 9*d3 + 5*d2 + d1;
-               q = (d1 * 0xcd) >> 11;
-               d1 = d1 - 10*q;
-               *buf++ = d1 + '0';
-
-               d2 = q + 2*d2;
-                       q = (d2 * 0xd) >> 7;
-                       d2 = d2 - 10*q;
-                       *buf++ = d2 + '0';
-
-                       d3 = q + 4*d3;
-                               q = (d3 * 0xcd) >> 11; /* - shorter code */
-                               /* q = (d3 * 0x67) >> 10; - would also work */
-                               d3 = d3 - 10*q;
-                               *buf++ = d3 + '0';
-                                       *buf++ = q + '0';
-       return buf;
-}
-/* No inlining helps gcc to use registers better */
-static noinline char* put_dec(char *buf, unsigned NUM_TYPE num)
-{
-       while (1) {
-               unsigned rem;
-               if (num < 100000)
-                       return put_dec_trunc(buf, num);
-               rem = do_div(num, 100000);
-               buf = put_dec_full(buf, rem);
-       }
-}
-
-#define ZEROPAD        1               /* pad with zero */
-#define SIGN   2               /* unsigned/signed long */
-#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 */
-
-static char *number(char *buf, unsigned NUM_TYPE num, int base, int size, int precision, int type)
-{
-       /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
-       static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
-
-       char tmp[66];
-       char sign;
-       char locase;
-       int need_pfx = ((type & SPECIAL) && 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;
-       sign = 0;
-       if (type & SIGN) {
-               if ((signed NUM_TYPE) num < 0) {
-                       sign = '-';
-                       num = - (signed NUM_TYPE) num;
-                       size--;
-               } else if (type & PLUS) {
-                       sign = '+';
-                       size--;
-               } else if (type & SPACE) {
-                       sign = ' ';
-                       size--;
-               }
-       }
-       if (need_pfx) {
-               size--;
-               if (base == 16)
-                       size--;
-       }
-
-       /* generate full string in tmp[], in reverse order */
-       i = 0;
-       if (num == 0)
-               tmp[i++] = '0';
-       /* Generic code, for any base:
-       else do {
-               tmp[i++] = (digits[do_div(num,base)] | locase);
-       } while (num != 0);
-       */
-       else if (base != 10) { /* 8 or 16 */
-               int mask = base - 1;
-               int shift = 3;
-               if (base == 16) shift = 4;
-               do {
-                       tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
-                       num >>= shift;
-               } while (num);
-       } else { /* base 10 */
-               i = put_dec(tmp, num) - tmp;
-       }
-
-       /* printing 100 using %2d gives "100", not "00" */
-       if (i > precision)
-               precision = i;
-       /* leading space padding */
-       size -= precision;
-       if (!(type & (ZEROPAD+LEFT)))
-               while(--size >= 0)
-                       *buf++ = ' ';
-       /* sign */
-       if (sign)
-               *buf++ = sign;
-       /* "0x" / "0" prefix */
-       if (need_pfx) {
-               *buf++ = '0';
-               if (base == 16)
-                       *buf++ = ('X' | locase);
-       }
-       /* zero or space padding */
-       if (!(type & LEFT)) {
-               char c = (type & ZEROPAD) ? '0' : ' ';
-               while (--size >= 0)
-                       *buf++ = c;
-       }
-       /* hmm even more zero padding? */
-       while (i <= --precision)
-               *buf++ = '0';
-       /* actual digits of result */
-       while (--i >= 0)
-               *buf++ = tmp[i];
-       /* trailing space padding */
-       while (--size >= 0)
-               *buf++ = ' ';
-       return buf;
-}
-
-static char *string(char *buf, char *s, int field_width, int precision, int flags)
-{
-       int len, i;
-
-       if (s == 0)
-               s = "<NULL>";
-
-       len = strnlen(s, precision);
-
-       if (!(flags & LEFT))
-               while (len < field_width--)
-                       *buf++ = ' ';
-       for (i = 0; i < len; ++i)
-               *buf++ = *s++;
-       while (len < field_width--)
-               *buf++ = ' ';
-       return buf;
-}
-
-#ifdef CONFIG_CMD_NET
-static char *mac_address_string(char *buf, u8 *addr, int field_width,
-                               int precision, int flags)
-{
-       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 (!(flags & SPECIAL) && i != 5)
-                       *p++ = ':';
-       }
-       *p = '\0';
-
-       return string(buf, mac_addr, field_width, precision, flags & ~SPECIAL);
-}
-
-static char *ip6_addr_string(char *buf, u8 *addr, int field_width,
-                        int precision, int flags)
-{
-       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 (!(flags & SPECIAL) && i != 7)
-                       *p++ = ':';
-       }
-       *p = '\0';
-
-       return string(buf, ip6_addr, field_width, precision, flags & ~SPECIAL);
-}
-
-static char *ip4_addr_string(char *buf, u8 *addr, int field_width,
-                        int precision, int flags)
-{
-       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';
-
-       return string(buf, ip4_addr, field_width, precision, flags & ~SPECIAL);
-}
-#endif
-
-/*
- * Show a '%p' thing.  A kernel extension is that the '%p' is followed
- * by an extra set of alphanumeric characters that are extended format
- * specifiers.
- *
- * Right now we handle:
- *
- * - '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, void *ptr, int field_width, int precision, int flags)
-{
-       if (!ptr)
-               return string(buf, "(null)", field_width, precision, flags);
-
-#ifdef CONFIG_CMD_NET
-       switch (*fmt) {
-       case 'm':
-               flags |= SPECIAL;
-               /* Fallthrough */
-       case 'M':
-               return mac_address_string(buf, ptr, field_width, precision, flags);
-       case 'i':
-               flags |= SPECIAL;
-               /* Fallthrough */
-       case 'I':
-               if (fmt[1] == '6')
-                       return ip6_addr_string(buf, ptr, field_width, precision, flags);
-               if (fmt[1] == '4')
-                       return ip4_addr_string(buf, ptr, field_width, precision, flags);
-               flags &= ~SPECIAL;
-               break;
-       }
-#endif
-       flags |= SMALL;
-       if (field_width == -1) {
-               field_width = 2*sizeof(void *);
-               flags |= ZEROPAD;
-       }
-       return number(buf, (unsigned long) ptr, 16, field_width, precision, flags);
-}
-
-/**
- * vsprintf - Format a string and place it in a buffer
- * @buf: The buffer to place the result into
- * @fmt: The format string to use
- * @args: Arguments for the format string
- *
- * This function follows C99 vsprintf, but has some extensions:
- * %pS output the name of a text symbol
- * %pF output the name of a function pointer
- * %pR output the address range in a struct resource
- *
- * The function returns the number of characters written
- * into @buf.
- *
- * Call this function if you are already dealing with a va_list.
- * You probably want sprintf() instead.
- */
-int vsprintf(char *buf, const char *fmt, va_list args)
-{
-       unsigned NUM_TYPE num;
-       int base;
-       char *str;
-
-       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 */
-
-       str = buf;
-
-       for (; *fmt ; ++fmt) {
-               if (*fmt != '%') {
-                       *str++ = *fmt;
-                       continue;
-               }
-
-               /* 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;
-                       }
-
-               /* get field width */
-               field_width = -1;
-               if (is_digit(*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;
-                       }
-               }
-
-               /* get the precision */
-               precision = -1;
-               if (*fmt == '.') {
-                       ++fmt;
-                       if (is_digit(*fmt))
-                               precision = skip_atoi(&fmt);
-                       else if (*fmt == '*') {
-                               ++fmt;
-                               /* it's the next argument */
-                               precision = va_arg(args, int);
-                       }
-                       if (precision < 0)
-                               precision = 0;
-               }
-
-               /* 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;
-                       }
-               }
-
-               /* default base */
-               base = 10;
-
-               switch (*fmt) {
-               case 'c':
-                       if (!(flags & LEFT))
-                               while (--field_width > 0)
-                                       *str++ = ' ';
-                       *str++ = (unsigned char) va_arg(args, int);
-                       while (--field_width > 0)
-                               *str++ = ' ';
-                       continue;
-
-               case 's':
-                       str = string(str, va_arg(args, char *), field_width, precision, flags);
-                       continue;
-
-               case 'p':
-                       str = pointer(fmt+1, str,
-                                       va_arg(args, void *),
-                                       field_width, precision, flags);
-                       /* Skip all alphanumeric pointer suffixes */
-                       while (isalnum(fmt[1]))
-                               fmt++;
-                       continue;
-
-               case 'n':
-                       if (qualifier == 'l') {
-                               long * ip = va_arg(args, long *);
-                               *ip = (str - buf);
-                       } else {
-                               int * ip = va_arg(args, int *);
-                               *ip = (str - buf);
-                       }
-                       continue;
-
-               case '%':
-                       *str++ = '%';
-                       continue;
-
-               /* integer number formats - set up the flags and "break" */
-               case 'o':
-                       base = 8;
-                       break;
-
-               case 'x':
-                       flags |= SMALL;
-               case 'X':
-                       base = 16;
-                       break;
-
-               case 'd':
-               case 'i':
-                       flags |= SIGN;
-               case 'u':
-                       break;
-
-               default:
-                       *str++ = '%';
-                       if (*fmt)
-                               *str++ = *fmt;
-                       else
-                               --fmt;
-                       continue;
-               }
-               if (qualifier == 'L')  /* "quad" for 64 bit variables */
-                       num = va_arg(args, unsigned 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;
-               }
-               str = number(str, num, base, field_width, precision, flags);
-       }
-       *str = '\0';
-       return str-buf;
-}
-
-/**
- * sprintf - Format a string and place it in a buffer
- * @buf: The buffer to place the result into
- * @fmt: The format string to use
- * @...: Arguments for the format string
- *
- * The function returns the number of characters written
- * into @buf.
- *
- * See the vsprintf() documentation for format string extensions over C99.
- */
-int sprintf(char * buf, const char *fmt, ...)
-{
-       va_list args;
-       int i;
-
-       va_start(args, fmt);
-       i=vsprintf(buf,fmt,args);
-       va_end(args);
-       return i;
-}
-
-void panic(const char *fmt, ...)
-{
-       va_list args;
-       va_start(args, fmt);
-       vprintf(fmt, args);
-       putc('\n');
-       va_end(args);
-#if defined (CONFIG_PANIC_HANG)
-       hang();
-#else
-       udelay (100000);        /* allow messages to go out */
-       do_reset (NULL, 0, 0, NULL);
-#endif
-}