linux/lib/vsprintf.c
<<
>>
Prefs
   1/*
   2 *  linux/lib/vsprintf.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
   8/*
   9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
  10 */
  11
  12/* 
  13 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
  14 * - changed to provide snprintf and vsnprintf functions
  15 * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
  16 * - scnprintf and vscnprintf
  17 */
  18
  19#include <stdarg.h>
  20#include <linux/module.h>
  21#include <linux/types.h>
  22#include <linux/string.h>
  23#include <linux/ctype.h>
  24#include <linux/kernel.h>
  25#include <linux/kallsyms.h>
  26#include <linux/uaccess.h>
  27
  28#include <asm/page.h>           /* for PAGE_SIZE */
  29#include <asm/div64.h>
  30
  31/* Works only for digits and letters, but small and fast */
  32#define TOLOWER(x) ((x) | 0x20)
  33
  34/**
  35 * simple_strtoul - convert a string to an unsigned long
  36 * @cp: The start of the string
  37 * @endp: A pointer to the end of the parsed string will be placed here
  38 * @base: The number base to use
  39 */
  40unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
  41{
  42        unsigned long result = 0,value;
  43
  44        if (!base) {
  45                base = 10;
  46                if (*cp == '0') {
  47                        base = 8;
  48                        cp++;
  49                        if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
  50                                cp++;
  51                                base = 16;
  52                        }
  53                }
  54        } else if (base == 16) {
  55                if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
  56                        cp += 2;
  57        }
  58        while (isxdigit(*cp) &&
  59               (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
  60                result = result*base + value;
  61                cp++;
  62        }
  63        if (endp)
  64                *endp = (char *)cp;
  65        return result;
  66}
  67
  68EXPORT_SYMBOL(simple_strtoul);
  69
  70/**
  71 * simple_strtol - convert a string to a signed long
  72 * @cp: The start of the string
  73 * @endp: A pointer to the end of the parsed string will be placed here
  74 * @base: The number base to use
  75 */
  76long simple_strtol(const char *cp,char **endp,unsigned int base)
  77{
  78        if(*cp=='-')
  79                return -simple_strtoul(cp+1,endp,base);
  80        return simple_strtoul(cp,endp,base);
  81}
  82
  83EXPORT_SYMBOL(simple_strtol);
  84
  85/**
  86 * simple_strtoull - convert a string to an unsigned long long
  87 * @cp: The start of the string
  88 * @endp: A pointer to the end of the parsed string will be placed here
  89 * @base: The number base to use
  90 */
  91unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
  92{
  93        unsigned long long result = 0,value;
  94
  95        if (!base) {
  96                base = 10;
  97                if (*cp == '0') {
  98                        base = 8;
  99                        cp++;
 100                        if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
 101                                cp++;
 102                                base = 16;
 103                        }
 104                }
 105        } else if (base == 16) {
 106                if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
 107                        cp += 2;
 108        }
 109        while (isxdigit(*cp)
 110         && (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
 111                result = result*base + value;
 112                cp++;
 113        }
 114        if (endp)
 115                *endp = (char *)cp;
 116        return result;
 117}
 118
 119EXPORT_SYMBOL(simple_strtoull);
 120
 121/**
 122 * simple_strtoll - convert a string to a signed long long
 123 * @cp: The start of the string
 124 * @endp: A pointer to the end of the parsed string will be placed here
 125 * @base: The number base to use
 126 */
 127long long simple_strtoll(const char *cp,char **endp,unsigned int base)
 128{
 129        if(*cp=='-')
 130                return -simple_strtoull(cp+1,endp,base);
 131        return simple_strtoull(cp,endp,base);
 132}
 133
 134
 135/**
 136 * strict_strtoul - convert a string to an unsigned long strictly
 137 * @cp: The string to be converted
 138 * @base: The number base to use
 139 * @res: The converted result value
 140 *
 141 * strict_strtoul converts a string to an unsigned long only if the
 142 * string is really an unsigned long string, any string containing
 143 * any invalid char at the tail will be rejected and -EINVAL is returned,
 144 * only a newline char at the tail is acceptible because people generally
 145 * change a module parameter in the following way:
 146 *
 147 *      echo 1024 > /sys/module/e1000/parameters/copybreak
 148 *
 149 * echo will append a newline to the tail.
 150 *
 151 * It returns 0 if conversion is successful and *res is set to the converted
 152 * value, otherwise it returns -EINVAL and *res is set to 0.
 153 *
 154 * simple_strtoul just ignores the successive invalid characters and
 155 * return the converted value of prefix part of the string.
 156 */
 157int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
 158
 159/**
 160 * strict_strtol - convert a string to a long strictly
 161 * @cp: The string to be converted
 162 * @base: The number base to use
 163 * @res: The converted result value
 164 *
 165 * strict_strtol is similiar to strict_strtoul, but it allows the first
 166 * character of a string is '-'.
 167 *
 168 * It returns 0 if conversion is successful and *res is set to the converted
 169 * value, otherwise it returns -EINVAL and *res is set to 0.
 170 */
 171int strict_strtol(const char *cp, unsigned int base, long *res);
 172
 173/**
 174 * strict_strtoull - convert a string to an unsigned long long strictly
 175 * @cp: The string to be converted
 176 * @base: The number base to use
 177 * @res: The converted result value
 178 *
 179 * strict_strtoull converts a string to an unsigned long long only if the
 180 * string is really an unsigned long long string, any string containing
 181 * any invalid char at the tail will be rejected and -EINVAL is returned,
 182 * only a newline char at the tail is acceptible because people generally
 183 * change a module parameter in the following way:
 184 *
 185 *      echo 1024 > /sys/module/e1000/parameters/copybreak
 186 *
 187 * echo will append a newline to the tail of the string.
 188 *
 189 * It returns 0 if conversion is successful and *res is set to the converted
 190 * value, otherwise it returns -EINVAL and *res is set to 0.
 191 *
 192 * simple_strtoull just ignores the successive invalid characters and
 193 * return the converted value of prefix part of the string.
 194 */
 195int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res);
 196
 197/**
 198 * strict_strtoll - convert a string to a long long strictly
 199 * @cp: The string to be converted
 200 * @base: The number base to use
 201 * @res: The converted result value
 202 *
 203 * strict_strtoll is similiar to strict_strtoull, but it allows the first
 204 * character of a string is '-'.
 205 *
 206 * It returns 0 if conversion is successful and *res is set to the converted
 207 * value, otherwise it returns -EINVAL and *res is set to 0.
 208 */
 209int strict_strtoll(const char *cp, unsigned int base, long long *res);
 210
 211#define define_strict_strtoux(type, valtype)                            \
 212int strict_strtou##type(const char *cp, unsigned int base, valtype *res)\
 213{                                                                       \
 214        char *tail;                                                     \
 215        valtype val;                                                    \
 216        size_t len;                                                     \
 217                                                                        \
 218        *res = 0;                                                       \
 219        len = strlen(cp);                                               \
 220        if (len == 0)                                                   \
 221                return -EINVAL;                                         \
 222                                                                        \
 223        val = simple_strtoul(cp, &tail, base);                          \
 224        if ((*tail == '\0') ||                                          \
 225                ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {\
 226                *res = val;                                             \
 227                return 0;                                               \
 228        }                                                               \
 229                                                                        \
 230        return -EINVAL;                                                 \
 231}                                                                       \
 232
 233#define define_strict_strtox(type, valtype)                             \
 234int strict_strto##type(const char *cp, unsigned int base, valtype *res) \
 235{                                                                       \
 236        int ret;                                                        \
 237        if (*cp == '-') {                                               \
 238                ret = strict_strtou##type(cp+1, base, res);             \
 239                if (!ret)                                               \
 240                        *res = -(*res);                                 \
 241        } else                                                          \
 242                ret = strict_strtou##type(cp, base, res);               \
 243                                                                        \
 244        return ret;                                                     \
 245}                                                                       \
 246
 247define_strict_strtoux(l, unsigned long)
 248define_strict_strtox(l, long)
 249define_strict_strtoux(ll, unsigned long long)
 250define_strict_strtox(ll, long long)
 251
 252EXPORT_SYMBOL(strict_strtoul);
 253EXPORT_SYMBOL(strict_strtol);
 254EXPORT_SYMBOL(strict_strtoll);
 255EXPORT_SYMBOL(strict_strtoull);
 256
 257static int skip_atoi(const char **s)
 258{
 259        int i=0;
 260
 261        while (isdigit(**s))
 262                i = i*10 + *((*s)++) - '0';
 263        return i;
 264}
 265
 266/* Decimal conversion is by far the most typical, and is used
 267 * for /proc and /sys data. This directly impacts e.g. top performance
 268 * with many processes running. We optimize it for speed
 269 * using code from
 270 * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
 271 * (with permission from the author, Douglas W. Jones). */
 272
 273/* Formats correctly any integer in [0,99999].
 274 * Outputs from one to five digits depending on input.
 275 * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
 276static char* put_dec_trunc(char *buf, unsigned q)
 277{
 278        unsigned d3, d2, d1, d0;
 279        d1 = (q>>4) & 0xf;
 280        d2 = (q>>8) & 0xf;
 281        d3 = (q>>12);
 282
 283        d0 = 6*(d3 + d2 + d1) + (q & 0xf);
 284        q = (d0 * 0xcd) >> 11;
 285        d0 = d0 - 10*q;
 286        *buf++ = d0 + '0'; /* least significant digit */
 287        d1 = q + 9*d3 + 5*d2 + d1;
 288        if (d1 != 0) {
 289                q = (d1 * 0xcd) >> 11;
 290                d1 = d1 - 10*q;
 291                *buf++ = d1 + '0'; /* next digit */
 292
 293                d2 = q + 2*d2;
 294                if ((d2 != 0) || (d3 != 0)) {
 295                        q = (d2 * 0xd) >> 7;
 296                        d2 = d2 - 10*q;
 297                        *buf++ = d2 + '0'; /* next digit */
 298
 299                        d3 = q + 4*d3;
 300                        if (d3 != 0) {
 301                                q = (d3 * 0xcd) >> 11;
 302                                d3 = d3 - 10*q;
 303                                *buf++ = d3 + '0';  /* next digit */
 304                                if (q != 0)
 305                                        *buf++ = q + '0';  /* most sign. digit */
 306                        }
 307                }
 308        }
 309        return buf;
 310}
 311/* Same with if's removed. Always emits five digits */
 312static char* put_dec_full(char *buf, unsigned q)
 313{
 314        /* BTW, if q is in [0,9999], 8-bit ints will be enough, */
 315        /* but anyway, gcc produces better code with full-sized ints */
 316        unsigned d3, d2, d1, d0;
 317        d1 = (q>>4) & 0xf;
 318        d2 = (q>>8) & 0xf;
 319        d3 = (q>>12);
 320
 321        /* Possible ways to approx. divide by 10 */
 322        /* gcc -O2 replaces multiply with shifts and adds */
 323        // (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
 324        // (x * 0x67) >> 10:  1100111
 325        // (x * 0x34) >> 9:    110100 - same
 326        // (x * 0x1a) >> 8:     11010 - same
 327        // (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
 328
 329        d0 = 6*(d3 + d2 + d1) + (q & 0xf);
 330        q = (d0 * 0xcd) >> 11;
 331        d0 = d0 - 10*q;
 332        *buf++ = d0 + '0';
 333        d1 = q + 9*d3 + 5*d2 + d1;
 334                q = (d1 * 0xcd) >> 11;
 335                d1 = d1 - 10*q;
 336                *buf++ = d1 + '0';
 337
 338                d2 = q + 2*d2;
 339                        q = (d2 * 0xd) >> 7;
 340                        d2 = d2 - 10*q;
 341                        *buf++ = d2 + '0';
 342
 343                        d3 = q + 4*d3;
 344                                q = (d3 * 0xcd) >> 11; /* - shorter code */
 345                                /* q = (d3 * 0x67) >> 10; - would also work */
 346                                d3 = d3 - 10*q;
 347                                *buf++ = d3 + '0';
 348                                        *buf++ = q + '0';
 349        return buf;
 350}
 351/* No inlining helps gcc to use registers better */
 352static noinline char* put_dec(char *buf, unsigned long long num)
 353{
 354        while (1) {
 355                unsigned rem;
 356                if (num < 100000)
 357                        return put_dec_trunc(buf, num);
 358                rem = do_div(num, 100000);
 359                buf = put_dec_full(buf, rem);
 360        }
 361}
 362
 363#define ZEROPAD 1               /* pad with zero */
 364#define SIGN    2               /* unsigned/signed long */
 365#define PLUS    4               /* show plus */
 366#define SPACE   8               /* space if plus */
 367#define LEFT    16              /* left justified */
 368#define SMALL   32              /* Must be 32 == 0x20 */
 369#define SPECIAL 64              /* 0x */
 370
 371static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
 372{
 373        /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
 374        static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
 375
 376        char tmp[66];
 377        char sign;
 378        char locase;
 379        int need_pfx = ((type & SPECIAL) && base != 10);
 380        int i;
 381
 382        /* locase = 0 or 0x20. ORing digits or letters with 'locase'
 383         * produces same digits or (maybe lowercased) letters */
 384        locase = (type & SMALL);
 385        if (type & LEFT)
 386                type &= ~ZEROPAD;
 387        sign = 0;
 388        if (type & SIGN) {
 389                if ((signed long long) num < 0) {
 390                        sign = '-';
 391                        num = - (signed long long) num;
 392                        size--;
 393                } else if (type & PLUS) {
 394                        sign = '+';
 395                        size--;
 396                } else if (type & SPACE) {
 397                        sign = ' ';
 398                        size--;
 399                }
 400        }
 401        if (need_pfx) {
 402                size--;
 403                if (base == 16)
 404                        size--;
 405        }
 406
 407        /* generate full string in tmp[], in reverse order */
 408        i = 0;
 409        if (num == 0)
 410                tmp[i++] = '0';
 411        /* Generic code, for any base:
 412        else do {
 413                tmp[i++] = (digits[do_div(num,base)] | locase);
 414        } while (num != 0);
 415        */
 416        else if (base != 10) { /* 8 or 16 */
 417                int mask = base - 1;
 418                int shift = 3;
 419                if (base == 16) shift = 4;
 420                do {
 421                        tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
 422                        num >>= shift;
 423                } while (num);
 424        } else { /* base 10 */
 425                i = put_dec(tmp, num) - tmp;
 426        }
 427
 428        /* printing 100 using %2d gives "100", not "00" */
 429        if (i > precision)
 430                precision = i;
 431        /* leading space padding */
 432        size -= precision;
 433        if (!(type & (ZEROPAD+LEFT))) {
 434                while(--size >= 0) {
 435                        if (buf < end)
 436                                *buf = ' ';
 437                        ++buf;
 438                }
 439        }
 440        /* sign */
 441        if (sign) {
 442                if (buf < end)
 443                        *buf = sign;
 444                ++buf;
 445        }
 446        /* "0x" / "0" prefix */
 447        if (need_pfx) {
 448                if (buf < end)
 449                        *buf = '0';
 450                ++buf;
 451                if (base == 16) {
 452                        if (buf < end)
 453                                *buf = ('X' | locase);
 454                        ++buf;
 455                }
 456        }
 457        /* zero or space padding */
 458        if (!(type & LEFT)) {
 459                char c = (type & ZEROPAD) ? '0' : ' ';
 460                while (--size >= 0) {
 461                        if (buf < end)
 462                                *buf = c;
 463                        ++buf;
 464                }
 465        }
 466        /* hmm even more zero padding? */
 467        while (i <= --precision) {
 468                if (buf < end)
 469                        *buf = '0';
 470                ++buf;
 471        }
 472        /* actual digits of result */
 473        while (--i >= 0) {
 474                if (buf < end)
 475                        *buf = tmp[i];
 476                ++buf;
 477        }
 478        /* trailing space padding */
 479        while (--size >= 0) {
 480                if (buf < end)
 481                        *buf = ' ';
 482                ++buf;
 483        }
 484        return buf;
 485}
 486
 487static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags)
 488{
 489        int len, i;
 490
 491        if ((unsigned long)s < PAGE_SIZE)
 492                s = "<NULL>";
 493
 494        len = strnlen(s, precision);
 495
 496        if (!(flags & LEFT)) {
 497                while (len < field_width--) {
 498                        if (buf < end)
 499                                *buf = ' ';
 500                        ++buf;
 501                }
 502        }
 503        for (i = 0; i < len; ++i) {
 504                if (buf < end)
 505                        *buf = *s;
 506                ++buf; ++s;
 507        }
 508        while (len < field_width--) {
 509                if (buf < end)
 510                        *buf = ' ';
 511                ++buf;
 512        }
 513        return buf;
 514}
 515
 516static inline void *dereference_function_descriptor(void *ptr)
 517{
 518#if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
 519        void *p;
 520        if (!probe_kernel_address(ptr, p))
 521                ptr = p;
 522#endif
 523        return ptr;
 524}
 525
 526static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags)
 527{
 528        unsigned long value = (unsigned long) ptr;
 529#ifdef CONFIG_KALLSYMS
 530        char sym[KSYM_SYMBOL_LEN];
 531        sprint_symbol(sym, value);
 532        return string(buf, end, sym, field_width, precision, flags);
 533#else
 534        field_width = 2*sizeof(void *);
 535        flags |= SPECIAL | SMALL | ZEROPAD;
 536        return number(buf, end, value, 16, field_width, precision, flags);
 537#endif
 538}
 539
 540/*
 541 * Show a '%p' thing.  A kernel extension is that the '%p' is followed
 542 * by an extra set of alphanumeric characters that are extended format
 543 * specifiers.
 544 *
 545 * Right now we just handle 'F' (for symbolic Function descriptor pointers)
 546 * and 'S' (for Symbolic direct pointers), but this can easily be
 547 * extended in the future (network address types etc).
 548 *
 549 * The difference between 'S' and 'F' is that on ia64 and ppc64 function
 550 * pointers are really function descriptors, which contain a pointer the
 551 * real address. 
 552 */
 553static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags)
 554{
 555        switch (*fmt) {
 556        case 'F':
 557                ptr = dereference_function_descriptor(ptr);
 558                /* Fallthrough */
 559        case 'S':
 560                return symbol_string(buf, end, ptr, field_width, precision, flags);
 561        }
 562        flags |= SMALL;
 563        if (field_width == -1) {
 564                field_width = 2*sizeof(void *);
 565                flags |= ZEROPAD;
 566        }
 567        return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags);
 568}
 569
 570/**
 571 * vsnprintf - Format a string and place it in a buffer
 572 * @buf: The buffer to place the result into
 573 * @size: The size of the buffer, including the trailing null space
 574 * @fmt: The format string to use
 575 * @args: Arguments for the format string
 576 *
 577 * The return value is the number of characters which would
 578 * be generated for the given input, excluding the trailing
 579 * '\0', as per ISO C99. If you want to have the exact
 580 * number of characters written into @buf as return value
 581 * (not including the trailing '\0'), use vscnprintf(). If the
 582 * return is greater than or equal to @size, the resulting
 583 * string is truncated.
 584 *
 585 * Call this function if you are already dealing with a va_list.
 586 * You probably want snprintf() instead.
 587 */
 588int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 589{
 590        unsigned long long num;
 591        int base;
 592        char *str, *end, c;
 593
 594        int flags;              /* flags to number() */
 595
 596        int field_width;        /* width of output field */
 597        int precision;          /* min. # of digits for integers; max
 598                                   number of chars for from string */
 599        int qualifier;          /* 'h', 'l', or 'L' for integer fields */
 600                                /* 'z' support added 23/7/1999 S.H.    */
 601                                /* 'z' changed to 'Z' --davidm 1/25/99 */
 602                                /* 't' added for ptrdiff_t */
 603
 604        /* Reject out-of-range values early.  Large positive sizes are
 605           used for unknown buffer sizes. */
 606        if (unlikely((int) size < 0)) {
 607                /* There can be only one.. */
 608                static char warn = 1;
 609                WARN_ON(warn);
 610                warn = 0;
 611                return 0;
 612        }
 613
 614        str = buf;
 615        end = buf + size;
 616
 617        /* Make sure end is always >= buf */
 618        if (end < buf) {
 619                end = ((void *)-1);
 620                size = end - buf;
 621        }
 622
 623        for (; *fmt ; ++fmt) {
 624                if (*fmt != '%') {
 625                        if (str < end)
 626                                *str = *fmt;
 627                        ++str;
 628                        continue;
 629                }
 630
 631                /* process flags */
 632                flags = 0;
 633                repeat:
 634                        ++fmt;          /* this also skips first '%' */
 635                        switch (*fmt) {
 636                                case '-': flags |= LEFT; goto repeat;
 637                                case '+': flags |= PLUS; goto repeat;
 638                                case ' ': flags |= SPACE; goto repeat;
 639                                case '#': flags |= SPECIAL; goto repeat;
 640                                case '0': flags |= ZEROPAD; goto repeat;
 641                        }
 642
 643                /* get field width */
 644                field_width = -1;
 645                if (isdigit(*fmt))
 646                        field_width = skip_atoi(&fmt);
 647                else if (*fmt == '*') {
 648                        ++fmt;
 649                        /* it's the next argument */
 650                        field_width = va_arg(args, int);
 651                        if (field_width < 0) {
 652                                field_width = -field_width;
 653                                flags |= LEFT;
 654                        }
 655                }
 656
 657                /* get the precision */
 658                precision = -1;
 659                if (*fmt == '.') {
 660                        ++fmt;  
 661                        if (isdigit(*fmt))
 662                                precision = skip_atoi(&fmt);
 663                        else if (*fmt == '*') {
 664                                ++fmt;
 665                                /* it's the next argument */
 666                                precision = va_arg(args, int);
 667                        }
 668                        if (precision < 0)
 669                                precision = 0;
 670                }
 671
 672                /* get the conversion qualifier */
 673                qualifier = -1;
 674                if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
 675                    *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
 676                        qualifier = *fmt;
 677                        ++fmt;
 678                        if (qualifier == 'l' && *fmt == 'l') {
 679                                qualifier = 'L';
 680                                ++fmt;
 681                        }
 682                }
 683
 684                /* default base */
 685                base = 10;
 686
 687                switch (*fmt) {
 688                        case 'c':
 689                                if (!(flags & LEFT)) {
 690                                        while (--field_width > 0) {
 691                                                if (str < end)
 692                                                        *str = ' ';
 693                                                ++str;
 694                                        }
 695                                }
 696                                c = (unsigned char) va_arg(args, int);
 697                                if (str < end)
 698                                        *str = c;
 699                                ++str;
 700                                while (--field_width > 0) {
 701                                        if (str < end)
 702                                                *str = ' ';
 703                                        ++str;
 704                                }
 705                                continue;
 706
 707                        case 's':
 708                                str = string(str, end, va_arg(args, char *), field_width, precision, flags);
 709                                continue;
 710
 711                        case 'p':
 712                                str = pointer(fmt+1, str, end,
 713                                                va_arg(args, void *),
 714                                                field_width, precision, flags);
 715                                /* Skip all alphanumeric pointer suffixes */
 716                                while (isalnum(fmt[1]))
 717                                        fmt++;
 718                                continue;
 719
 720                        case 'n':
 721                                /* FIXME:
 722                                * What does C99 say about the overflow case here? */
 723                                if (qualifier == 'l') {
 724                                        long * ip = va_arg(args, long *);
 725                                        *ip = (str - buf);
 726                                } else if (qualifier == 'Z' || qualifier == 'z') {
 727                                        size_t * ip = va_arg(args, size_t *);
 728                                        *ip = (str - buf);
 729                                } else {
 730                                        int * ip = va_arg(args, int *);
 731                                        *ip = (str - buf);
 732                                }
 733                                continue;
 734
 735                        case '%':
 736                                if (str < end)
 737                                        *str = '%';
 738                                ++str;
 739                                continue;
 740
 741                                /* integer number formats - set up the flags and "break" */
 742                        case 'o':
 743                                base = 8;
 744                                break;
 745
 746                        case 'x':
 747                                flags |= SMALL;
 748                        case 'X':
 749                                base = 16;
 750                                break;
 751
 752                        case 'd':
 753                        case 'i':
 754                                flags |= SIGN;
 755                        case 'u':
 756                                break;
 757
 758                        default:
 759                                if (str < end)
 760                                        *str = '%';
 761                                ++str;
 762                                if (*fmt) {
 763                                        if (str < end)
 764                                                *str = *fmt;
 765                                        ++str;
 766                                } else {
 767                                        --fmt;
 768                                }
 769                                continue;
 770                }
 771                if (qualifier == 'L')
 772                        num = va_arg(args, long long);
 773                else if (qualifier == 'l') {
 774                        num = va_arg(args, unsigned long);
 775                        if (flags & SIGN)
 776                                num = (signed long) num;
 777                } else if (qualifier == 'Z' || qualifier == 'z') {
 778                        num = va_arg(args, size_t);
 779                } else if (qualifier == 't') {
 780                        num = va_arg(args, ptrdiff_t);
 781                } else if (qualifier == 'h') {
 782                        num = (unsigned short) va_arg(args, int);
 783                        if (flags & SIGN)
 784                                num = (signed short) num;
 785                } else {
 786                        num = va_arg(args, unsigned int);
 787                        if (flags & SIGN)
 788                                num = (signed int) num;
 789                }
 790                str = number(str, end, num, base,
 791                                field_width, precision, flags);
 792        }
 793        if (size > 0) {
 794                if (str < end)
 795                        *str = '\0';
 796                else
 797                        end[-1] = '\0';
 798        }
 799        /* the trailing null byte doesn't count towards the total */
 800        return str-buf;
 801}
 802
 803EXPORT_SYMBOL(vsnprintf);
 804
 805/**
 806 * vscnprintf - Format a string and place it in a buffer
 807 * @buf: The buffer to place the result into
 808 * @size: The size of the buffer, including the trailing null space
 809 * @fmt: The format string to use
 810 * @args: Arguments for the format string
 811 *
 812 * The return value is the number of characters which have been written into
 813 * the @buf not including the trailing '\0'. If @size is <= 0 the function
 814 * returns 0.
 815 *
 816 * Call this function if you are already dealing with a va_list.
 817 * You probably want scnprintf() instead.
 818 */
 819int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
 820{
 821        int i;
 822
 823        i=vsnprintf(buf,size,fmt,args);
 824        return (i >= size) ? (size - 1) : i;
 825}
 826
 827EXPORT_SYMBOL(vscnprintf);
 828
 829/**
 830 * snprintf - Format a string and place it in a buffer
 831 * @buf: The buffer to place the result into
 832 * @size: The size of the buffer, including the trailing null space
 833 * @fmt: The format string to use
 834 * @...: Arguments for the format string
 835 *
 836 * The return value is the number of characters which would be
 837 * generated for the given input, excluding the trailing null,
 838 * as per ISO C99.  If the return is greater than or equal to
 839 * @size, the resulting string is truncated.
 840 */
 841int snprintf(char * buf, size_t size, const char *fmt, ...)
 842{
 843        va_list args;
 844        int i;
 845
 846        va_start(args, fmt);
 847        i=vsnprintf(buf,size,fmt,args);
 848        va_end(args);
 849        return i;
 850}
 851
 852EXPORT_SYMBOL(snprintf);
 853
 854/**
 855 * scnprintf - Format a string and place it in a buffer
 856 * @buf: The buffer to place the result into
 857 * @size: The size of the buffer, including the trailing null space
 858 * @fmt: The format string to use
 859 * @...: Arguments for the format string
 860 *
 861 * The return value is the number of characters written into @buf not including
 862 * the trailing '\0'. If @size is <= 0 the function returns 0.
 863 */
 864
 865int scnprintf(char * buf, size_t size, const char *fmt, ...)
 866{
 867        va_list args;
 868        int i;
 869
 870        va_start(args, fmt);
 871        i = vsnprintf(buf, size, fmt, args);
 872        va_end(args);
 873        return (i >= size) ? (size - 1) : i;
 874}
 875EXPORT_SYMBOL(scnprintf);
 876
 877/**
 878 * vsprintf - Format a string and place it in a buffer
 879 * @buf: The buffer to place the result into
 880 * @fmt: The format string to use
 881 * @args: Arguments for the format string
 882 *
 883 * The function returns the number of characters written
 884 * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
 885 * buffer overflows.
 886 *
 887 * Call this function if you are already dealing with a va_list.
 888 * You probably want sprintf() instead.
 889 */
 890int vsprintf(char *buf, const char *fmt, va_list args)
 891{
 892        return vsnprintf(buf, INT_MAX, fmt, args);
 893}
 894
 895EXPORT_SYMBOL(vsprintf);
 896
 897/**
 898 * sprintf - Format a string and place it in a buffer
 899 * @buf: The buffer to place the result into
 900 * @fmt: The format string to use
 901 * @...: Arguments for the format string
 902 *
 903 * The function returns the number of characters written
 904 * into @buf. Use snprintf() or scnprintf() in order to avoid
 905 * buffer overflows.
 906 */
 907int sprintf(char * buf, const char *fmt, ...)
 908{
 909        va_list args;
 910        int i;
 911
 912        va_start(args, fmt);
 913        i=vsnprintf(buf, INT_MAX, fmt, args);
 914        va_end(args);
 915        return i;
 916}
 917
 918EXPORT_SYMBOL(sprintf);
 919
 920/**
 921 * vsscanf - Unformat a buffer into a list of arguments
 922 * @buf:        input buffer
 923 * @fmt:        format of buffer
 924 * @args:       arguments
 925 */
 926int vsscanf(const char * buf, const char * fmt, va_list args)
 927{
 928        const char *str = buf;
 929        char *next;
 930        char digit;
 931        int num = 0;
 932        int qualifier;
 933        int base;
 934        int field_width;
 935        int is_sign = 0;
 936
 937        while(*fmt && *str) {
 938                /* skip any white space in format */
 939                /* white space in format matchs any amount of
 940                 * white space, including none, in the input.
 941                 */
 942                if (isspace(*fmt)) {
 943                        while (isspace(*fmt))
 944                                ++fmt;
 945                        while (isspace(*str))
 946                                ++str;
 947                }
 948
 949                /* anything that is not a conversion must match exactly */
 950                if (*fmt != '%' && *fmt) {
 951                        if (*fmt++ != *str++)
 952                                break;
 953                        continue;
 954                }
 955
 956                if (!*fmt)
 957                        break;
 958                ++fmt;
 959                
 960                /* skip this conversion.
 961                 * advance both strings to next white space
 962                 */
 963                if (*fmt == '*') {
 964                        while (!isspace(*fmt) && *fmt)
 965                                fmt++;
 966                        while (!isspace(*str) && *str)
 967                                str++;
 968                        continue;
 969                }
 970
 971                /* get field width */
 972                field_width = -1;
 973                if (isdigit(*fmt))
 974                        field_width = skip_atoi(&fmt);
 975
 976                /* get conversion qualifier */
 977                qualifier = -1;
 978                if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
 979                    *fmt == 'Z' || *fmt == 'z') {
 980                        qualifier = *fmt++;
 981                        if (unlikely(qualifier == *fmt)) {
 982                                if (qualifier == 'h') {
 983                                        qualifier = 'H';
 984                                        fmt++;
 985                                } else if (qualifier == 'l') {
 986                                        qualifier = 'L';
 987                                        fmt++;
 988                                }
 989                        }
 990                }
 991                base = 10;
 992                is_sign = 0;
 993
 994                if (!*fmt || !*str)
 995                        break;
 996
 997                switch(*fmt++) {
 998                case 'c':
 999                {
1000                        char *s = (char *) va_arg(args,char*);
1001                        if (field_width == -1)
1002                                field_width = 1;
1003                        do {
1004                                *s++ = *str++;
1005                        } while (--field_width > 0 && *str);
1006                        num++;
1007                }
1008                continue;
1009                case 's':
1010                {
1011                        char *s = (char *) va_arg(args, char *);
1012                        if(field_width == -1)
1013                                field_width = INT_MAX;
1014                        /* first, skip leading white space in buffer */
1015                        while (isspace(*str))
1016                                str++;
1017
1018                        /* now copy until next white space */
1019                        while (*str && !isspace(*str) && field_width--) {
1020                                *s++ = *str++;
1021                        }
1022                        *s = '\0';
1023                        num++;
1024                }
1025                continue;
1026                case 'n':
1027                        /* return number of characters read so far */
1028                {
1029                        int *i = (int *)va_arg(args,int*);
1030                        *i = str - buf;
1031                }
1032                continue;
1033                case 'o':
1034                        base = 8;
1035                        break;
1036                case 'x':
1037                case 'X':
1038                        base = 16;
1039                        break;
1040                case 'i':
1041                        base = 0;
1042                case 'd':
1043                        is_sign = 1;
1044                case 'u':
1045                        break;
1046                case '%':
1047                        /* looking for '%' in str */
1048                        if (*str++ != '%') 
1049                                return num;
1050                        continue;
1051                default:
1052                        /* invalid format; stop here */
1053                        return num;
1054                }
1055
1056                /* have some sort of integer conversion.
1057                 * first, skip white space in buffer.
1058                 */
1059                while (isspace(*str))
1060                        str++;
1061
1062                digit = *str;
1063                if (is_sign && digit == '-')
1064                        digit = *(str + 1);
1065
1066                if (!digit
1067                    || (base == 16 && !isxdigit(digit))
1068                    || (base == 10 && !isdigit(digit))
1069                    || (base == 8 && (!isdigit(digit) || digit > '7'))
1070                    || (base == 0 && !isdigit(digit)))
1071                                break;
1072
1073                switch(qualifier) {
1074                case 'H':       /* that's 'hh' in format */
1075                        if (is_sign) {
1076                                signed char *s = (signed char *) va_arg(args,signed char *);
1077                                *s = (signed char) simple_strtol(str,&next,base);
1078                        } else {
1079                                unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
1080                                *s = (unsigned char) simple_strtoul(str, &next, base);
1081                        }
1082                        break;
1083                case 'h':
1084                        if (is_sign) {
1085                                short *s = (short *) va_arg(args,short *);
1086                                *s = (short) simple_strtol(str,&next,base);
1087                        } else {
1088                                unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
1089                                *s = (unsigned short) simple_strtoul(str, &next, base);
1090                        }
1091                        break;
1092                case 'l':
1093                        if (is_sign) {
1094                                long *l = (long *) va_arg(args,long *);
1095                                *l = simple_strtol(str,&next,base);
1096                        } else {
1097                                unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
1098                                *l = simple_strtoul(str,&next,base);
1099                        }
1100                        break;
1101                case 'L':
1102                        if (is_sign) {
1103                                long long *l = (long long*) va_arg(args,long long *);
1104                                *l = simple_strtoll(str,&next,base);
1105                        } else {
1106                                unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
1107                                *l = simple_strtoull(str,&next,base);
1108                        }
1109                        break;
1110                case 'Z':
1111                case 'z':
1112                {
1113                        size_t *s = (size_t*) va_arg(args,size_t*);
1114                        *s = (size_t) simple_strtoul(str,&next,base);
1115                }
1116                break;
1117                default:
1118                        if (is_sign) {
1119                                int *i = (int *) va_arg(args, int*);
1120                                *i = (int) simple_strtol(str,&next,base);
1121                        } else {
1122                                unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
1123                                *i = (unsigned int) simple_strtoul(str,&next,base);
1124                        }
1125                        break;
1126                }
1127                num++;
1128
1129                if (!next)
1130                        break;
1131                str = next;
1132        }
1133
1134        /*
1135         * Now we've come all the way through so either the input string or the
1136         * format ended. In the former case, there can be a %n at the current
1137         * position in the format that needs to be filled.
1138         */
1139        if (*fmt == '%' && *(fmt + 1) == 'n') {
1140                int *p = (int *)va_arg(args, int *);
1141                *p = str - buf;
1142        }
1143
1144        return num;
1145}
1146
1147EXPORT_SYMBOL(vsscanf);
1148
1149/**
1150 * sscanf - Unformat a buffer into a list of arguments
1151 * @buf:        input buffer
1152 * @fmt:        formatting of buffer
1153 * @...:        resulting arguments
1154 */
1155int sscanf(const char * buf, const char * fmt, ...)
1156{
1157        va_list args;
1158        int i;
1159
1160        va_start(args,fmt);
1161        i = vsscanf(buf,fmt,args);
1162        va_end(args);
1163        return i;
1164}
1165
1166EXPORT_SYMBOL(sscanf);
1167
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.