Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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. #define likely(x)       __builtin_expect(!!(x), 1)
  20. #define unlikely(x)     __builtin_expect(!!(x), 0)
  21.  
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <stdarg.h>
  25. #include <stdint.h>
  26.  
  27. //#include <linux/module.h>
  28. //#include <types.h>
  29. //#include <linux/kernel.h>
  30. //#include <linux/kallsyms.h>
  31. //#include <linux/uaccess.h>
  32. //#include <linux/ioport.h>
  33.  
  34. //#include <asm/page.h>      /* for PAGE_SIZE */
  35. //#include <asm/div64.h>
  36. //#include <asm/sections.h>  /* for dereference_function_descriptor() */
  37.  
  38. #define do_div(n, base)                     \
  39. ({                              \
  40.     unsigned long __upper, __low, __high, __mod, __base;    \
  41.     __base = (base);                    \
  42.     asm("":"=a" (__low), "=d" (__high) : "A" (n));      \
  43.     __upper = __high;                   \
  44.     if (__high) {                       \
  45.         __upper = __high % (__base);            \
  46.         __high = __high / (__base);         \
  47.     }                           \
  48.     asm("divl %2":"=a" (__low), "=d" (__mod)        \
  49.         : "rm" (__base), "0" (__low), "1" (__upper));   \
  50.     asm("":"=A" (n) : "a" (__low), "d" (__high));       \
  51.     __mod;                          \
  52. })
  53.  
  54. #define EPERM        1  /* Operation not permitted */
  55. #define ENOENT       2  /* No such file or directory */
  56. #define ESRCH        3  /* No such process */
  57. #define EINTR        4  /* Interrupted system call */
  58. #define EIO          5  /* I/O error */
  59. #define ENXIO        6  /* No such device or address */
  60. #define E2BIG        7  /* Argument list too long */
  61. #define ENOEXEC      8  /* Exec format error */
  62. #define EBADF        9  /* Bad file number */
  63. #define ECHILD      10  /* No child processes */
  64. #define EAGAIN      11  /* Try again */
  65. #define ENOMEM      12  /* Out of memory */
  66. #define EACCES      13  /* Permission denied */
  67. #define EFAULT      14  /* Bad address */
  68. #define ENOTBLK     15  /* Block device required */
  69. #define EBUSY       16  /* Device or resource busy */
  70. #define EEXIST      17  /* File exists */
  71. #define EXDEV       18  /* Cross-device link */
  72. #define ENODEV      19  /* No such device */
  73. #define ENOTDIR     20  /* Not a directory */
  74. #define EISDIR      21  /* Is a directory */
  75. #define EINVAL      22  /* Invalid argument */
  76. #define ENFILE      23  /* File table overflow */
  77. #define EMFILE      24  /* Too many open files */
  78. #define ENOTTY      25  /* Not a typewriter */
  79. #define ETXTBSY     26  /* Text file busy */
  80. #define EFBIG       27  /* File too large */
  81. #define ENOSPC      28  /* No space left on device */
  82. #define ESPIPE      29  /* Illegal seek */
  83. #define EROFS       30  /* Read-only file system */
  84. #define EMLINK      31  /* Too many links */
  85. #define EPIPE       32  /* Broken pipe */
  86. #define EDOM        33  /* Math argument out of domain of func */
  87. #define ERANGE      34  /* Math result not representable */
  88.  
  89. #define PAGE_SIZE 4096
  90.  
  91. /* Works only for digits and letters, but small and fast */
  92. #define TOLOWER(x) ((x) | 0x20)
  93.  
  94. static unsigned int simple_guess_base(const char *cp)
  95. {
  96.         if (cp[0] == '0') {
  97.                 if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
  98.                         return 16;
  99.                 else
  100.                         return 8;
  101.         } else {
  102.                 return 10;
  103.         }
  104. }
  105.  
  106. /**
  107.  * simple_strtoul - convert a string to an unsigned long
  108.  * @cp: The start of the string
  109.  * @endp: A pointer to the end of the parsed string will be placed here
  110.  * @base: The number base to use
  111.  */
  112. unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
  113. {
  114.         unsigned long result = 0;
  115.  
  116.         if (!base)
  117.                 base = simple_guess_base(cp);
  118.  
  119.         if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
  120.                 cp += 2;
  121.  
  122.         while (isxdigit(*cp)) {
  123.                 unsigned int value;
  124.  
  125.                 value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
  126.                 if (value >= base)
  127.                         break;
  128.                 result = result * base + value;
  129.                 cp++;
  130.         }
  131.  
  132.         if (endp)
  133.                 *endp = (char *)cp;
  134.         return result;
  135. }
  136.  
  137. /**
  138.  * simple_strtol - convert a string to a signed long
  139.  * @cp: The start of the string
  140.  * @endp: A pointer to the end of the parsed string will be placed here
  141.  * @base: The number base to use
  142.  */
  143. long simple_strtol(const char *cp, char **endp, unsigned int base)
  144. {
  145.         if(*cp == '-')
  146.                 return -simple_strtoul(cp + 1, endp, base);
  147.         return simple_strtoul(cp, endp, base);
  148. }
  149.  
  150. /**
  151.  * simple_strtoull - convert a string to an unsigned long long
  152.  * @cp: The start of the string
  153.  * @endp: A pointer to the end of the parsed string will be placed here
  154.  * @base: The number base to use
  155.  */
  156. unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
  157. {
  158.         unsigned long long result = 0;
  159.  
  160.         if (!base)
  161.                 base = simple_guess_base(cp);
  162.  
  163.         if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
  164.                 cp += 2;
  165.  
  166.         while (isxdigit(*cp)) {
  167.                 unsigned int value;
  168.  
  169.                 value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
  170.                 if (value >= base)
  171.                         break;
  172.                 result = result * base + value;
  173.                 cp++;
  174.         }
  175.  
  176.         if (endp)
  177.                 *endp = (char *)cp;
  178.         return result;
  179. }
  180.  
  181. /**
  182.  * simple_strtoll - convert a string to a signed long long
  183.  * @cp: The start of the string
  184.  * @endp: A pointer to the end of the parsed string will be placed here
  185.  * @base: The number base to use
  186.  */
  187. long long simple_strtoll(const char *cp, char **endp, unsigned int base)
  188. {
  189.         if(*cp=='-')
  190.                 return -simple_strtoull(cp + 1, endp, base);
  191.         return simple_strtoull(cp, endp, base);
  192. }
  193.  
  194. /**
  195.  * strict_strtoul - convert a string to an unsigned long strictly
  196.  * @cp: The string to be converted
  197.  * @base: The number base to use
  198.  * @res: The converted result value
  199.  *
  200.  * strict_strtoul converts a string to an unsigned long only if the
  201.  * string is really an unsigned long string, any string containing
  202.  * any invalid char at the tail will be rejected and -EINVAL is returned,
  203.  * only a newline char at the tail is acceptible because people generally
  204.  * change a module parameter in the following way:
  205.  *
  206.  *      echo 1024 > /sys/module/e1000/parameters/copybreak
  207.  *
  208.  * echo will append a newline to the tail.
  209.  *
  210.  * It returns 0 if conversion is successful and *res is set to the converted
  211.  * value, otherwise it returns -EINVAL and *res is set to 0.
  212.  *
  213.  * simple_strtoul just ignores the successive invalid characters and
  214.  * return the converted value of prefix part of the string.
  215.  */
  216. int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
  217. {
  218.         char *tail;
  219.         unsigned long val;
  220.         size_t len;
  221.  
  222.         *res = 0;
  223.         len = strlen(cp);
  224.         if (len == 0)
  225.                 return -EINVAL;
  226.  
  227.         val = simple_strtoul(cp, &tail, base);
  228.         if (tail == cp)
  229.                 return -EINVAL;
  230.         if ((*tail == '\0') ||
  231.                 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
  232.                 *res = val;
  233.                 return 0;
  234.         }
  235.  
  236.         return -EINVAL;
  237. }
  238.  
  239. /**
  240.  * strict_strtol - convert a string to a long strictly
  241.  * @cp: The string to be converted
  242.  * @base: The number base to use
  243.  * @res: The converted result value
  244.  *
  245.  * strict_strtol is similiar to strict_strtoul, but it allows the first
  246.  * character of a string is '-'.
  247.  *
  248.  * It returns 0 if conversion is successful and *res is set to the converted
  249.  * value, otherwise it returns -EINVAL and *res is set to 0.
  250.  */
  251. int strict_strtol(const char *cp, unsigned int base, long *res)
  252. {
  253.         int ret;
  254.         if (*cp == '-') {
  255.                 ret = strict_strtoul(cp + 1, base, (unsigned long *)res);
  256.                 if (!ret)
  257.                         *res = -(*res);
  258.         } else {
  259.                 ret = strict_strtoul(cp, base, (unsigned long *)res);
  260.         }
  261.  
  262.         return ret;
  263. }
  264.  
  265. /**
  266.  * strict_strtoull - convert a string to an unsigned long long strictly
  267.  * @cp: The string to be converted
  268.  * @base: The number base to use
  269.  * @res: The converted result value
  270.  *
  271.  * strict_strtoull converts a string to an unsigned long long only if the
  272.  * string is really an unsigned long long string, any string containing
  273.  * any invalid char at the tail will be rejected and -EINVAL is returned,
  274.  * only a newline char at the tail is acceptible because people generally
  275.  * change a module parameter in the following way:
  276.  *
  277.  *      echo 1024 > /sys/module/e1000/parameters/copybreak
  278.  *
  279.  * echo will append a newline to the tail of the string.
  280.  *
  281.  * It returns 0 if conversion is successful and *res is set to the converted
  282.  * value, otherwise it returns -EINVAL and *res is set to 0.
  283.  *
  284.  * simple_strtoull just ignores the successive invalid characters and
  285.  * return the converted value of prefix part of the string.
  286.  */
  287. int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)
  288. {
  289.         char *tail;
  290.         unsigned long long val;
  291.         size_t len;
  292.  
  293.         *res = 0;
  294.         len = strlen(cp);
  295.         if (len == 0)
  296.                 return -EINVAL;
  297.  
  298.         val = simple_strtoull(cp, &tail, base);
  299.         if (tail == cp)
  300.                 return -EINVAL;
  301.         if ((*tail == '\0') ||
  302.                 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
  303.                 *res = val;
  304.                 return 0;
  305.         }
  306.  
  307.         return -EINVAL;
  308. }
  309.  
  310. /**
  311.  * strict_strtoll - convert a string to a long long strictly
  312.  * @cp: The string to be converted
  313.  * @base: The number base to use
  314.  * @res: The converted result value
  315.  *
  316.  * strict_strtoll is similiar to strict_strtoull, but it allows the first
  317.  * character of a string is '-'.
  318.  *
  319.  * It returns 0 if conversion is successful and *res is set to the converted
  320.  * value, otherwise it returns -EINVAL and *res is set to 0.
  321.  */
  322. int strict_strtoll(const char *cp, unsigned int base, long long *res)
  323. {
  324.         int ret;
  325.         if (*cp == '-') {
  326.                 ret = strict_strtoull(cp + 1, base, (unsigned long long *)res);
  327.                 if (!ret)
  328.                         *res = -(*res);
  329.         } else {
  330.                 ret = strict_strtoull(cp, base, (unsigned long long *)res);
  331.         }
  332.  
  333.         return ret;
  334. }
  335.  
  336. static int skip_atoi(const char **s)
  337. {
  338.         int i=0;
  339.  
  340.         while (isdigit(**s))
  341.                 i = i*10 + *((*s)++) - '0';
  342.         return i;
  343. }
  344.  
  345. /* Decimal conversion is by far the most typical, and is used
  346.  * for /proc and /sys data. This directly impacts e.g. top performance
  347.  * with many processes running. We optimize it for speed
  348.  * using code from
  349.  * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
  350.  * (with permission from the author, Douglas W. Jones). */
  351.  
  352. /* Formats correctly any integer in [0,99999].
  353.  * Outputs from one to five digits depending on input.
  354.  * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
  355. static char* put_dec_trunc(char *buf, unsigned q)
  356. {
  357.         unsigned d3, d2, d1, d0;
  358.         d1 = (q>>4) & 0xf;
  359.         d2 = (q>>8) & 0xf;
  360.         d3 = (q>>12);
  361.  
  362.         d0 = 6*(d3 + d2 + d1) + (q & 0xf);
  363.         q = (d0 * 0xcd) >> 11;
  364.         d0 = d0 - 10*q;
  365.         *buf++ = d0 + '0'; /* least significant digit */
  366.         d1 = q + 9*d3 + 5*d2 + d1;
  367.         if (d1 != 0) {
  368.                 q = (d1 * 0xcd) >> 11;
  369.                 d1 = d1 - 10*q;
  370.                 *buf++ = d1 + '0'; /* next digit */
  371.  
  372.                 d2 = q + 2*d2;
  373.                 if ((d2 != 0) || (d3 != 0)) {
  374.                         q = (d2 * 0xd) >> 7;
  375.                         d2 = d2 - 10*q;
  376.                         *buf++ = d2 + '0'; /* next digit */
  377.  
  378.                         d3 = q + 4*d3;
  379.                         if (d3 != 0) {
  380.                                 q = (d3 * 0xcd) >> 11;
  381.                                 d3 = d3 - 10*q;
  382.                                 *buf++ = d3 + '0';  /* next digit */
  383.                                 if (q != 0)
  384.                                         *buf++ = q + '0';  /* most sign. digit */
  385.                         }
  386.                 }
  387.         }
  388.         return buf;
  389. }
  390. /* Same with if's removed. Always emits five digits */
  391. static char* put_dec_full(char *buf, unsigned q)
  392. {
  393.         /* BTW, if q is in [0,9999], 8-bit ints will be enough, */
  394.         /* but anyway, gcc produces better code with full-sized ints */
  395.         unsigned d3, d2, d1, d0;
  396.         d1 = (q>>4) & 0xf;
  397.         d2 = (q>>8) & 0xf;
  398.         d3 = (q>>12);
  399.  
  400.         /* Possible ways to approx. divide by 10 */
  401.         /* gcc -O2 replaces multiply with shifts and adds */
  402.         // (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
  403.         // (x * 0x67) >> 10:  1100111
  404.         // (x * 0x34) >> 9:    110100 - same
  405.         // (x * 0x1a) >> 8:     11010 - same
  406.         // (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
  407.  
  408.         d0 = 6*(d3 + d2 + d1) + (q & 0xf);
  409.         q = (d0 * 0xcd) >> 11;
  410.         d0 = d0 - 10*q;
  411.         *buf++ = d0 + '0';
  412.         d1 = q + 9*d3 + 5*d2 + d1;
  413.                 q = (d1 * 0xcd) >> 11;
  414.                 d1 = d1 - 10*q;
  415.                 *buf++ = d1 + '0';
  416.  
  417.                 d2 = q + 2*d2;
  418.                         q = (d2 * 0xd) >> 7;
  419.                         d2 = d2 - 10*q;
  420.                         *buf++ = d2 + '0';
  421.  
  422.                         d3 = q + 4*d3;
  423.                                 q = (d3 * 0xcd) >> 11; /* - shorter code */
  424.                                 /* q = (d3 * 0x67) >> 10; - would also work */
  425.                                 d3 = d3 - 10*q;
  426.                                 *buf++ = d3 + '0';
  427.                                         *buf++ = q + '0';
  428.         return buf;
  429. }
  430. /* No inlining helps gcc to use registers better */
  431. static char* put_dec(char *buf, unsigned long long num)
  432. {
  433.         while (1) {
  434.                 unsigned rem;
  435.                 if (num < 100000)
  436.                         return put_dec_trunc(buf, num);
  437.                 rem = do_div(num, 100000);
  438.                 buf = put_dec_full(buf, rem);
  439.         }
  440. }
  441.  
  442. #define ZEROPAD 1               /* pad with zero */
  443. #define SIGN    2               /* unsigned/signed long */
  444. #define PLUS    4               /* show plus */
  445. #define SPACE   8               /* space if plus */
  446. #define LEFT    16              /* left justified */
  447. #define SMALL   32              /* Must be 32 == 0x20 */
  448. #define SPECIAL 64              /* 0x */
  449.  
  450. enum format_type {
  451.         FORMAT_TYPE_NONE, /* Just a string part */
  452.         FORMAT_TYPE_WIDTH,
  453.         FORMAT_TYPE_PRECISION,
  454.         FORMAT_TYPE_CHAR,
  455.         FORMAT_TYPE_STR,
  456.         FORMAT_TYPE_PTR,
  457.         FORMAT_TYPE_PERCENT_CHAR,
  458.         FORMAT_TYPE_INVALID,
  459.         FORMAT_TYPE_LONG_LONG,
  460.         FORMAT_TYPE_ULONG,
  461.         FORMAT_TYPE_LONG,
  462.         FORMAT_TYPE_UBYTE,
  463.         FORMAT_TYPE_BYTE,
  464.         FORMAT_TYPE_USHORT,
  465.         FORMAT_TYPE_SHORT,
  466.         FORMAT_TYPE_UINT,
  467.         FORMAT_TYPE_INT,
  468.         FORMAT_TYPE_NRCHARS,
  469.         FORMAT_TYPE_SIZE_T,
  470.         FORMAT_TYPE_PTRDIFF
  471. };
  472.  
  473. struct printf_spec {
  474.         enum format_type        type;
  475.         int                     flags;          /* flags to number() */
  476.         int                     field_width;    /* width of output field */
  477.         int                     base;
  478.         int                     precision;      /* # of digits/chars */
  479.         int                     qualifier;
  480. };
  481.  
  482. static char *number(char *buf, char *end, unsigned long long num,
  483.                         struct printf_spec spec)
  484. {
  485.         /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
  486.         static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
  487.  
  488.         char tmp[66];
  489.         char sign;
  490.         char locase;
  491.         int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
  492.         int i;
  493.  
  494.         /* locase = 0 or 0x20. ORing digits or letters with 'locase'
  495.          * produces same digits or (maybe lowercased) letters */
  496.         locase = (spec.flags & SMALL);
  497.         if (spec.flags & LEFT)
  498.                 spec.flags &= ~ZEROPAD;
  499.         sign = 0;
  500.         if (spec.flags & SIGN) {
  501.                 if ((signed long long) num < 0) {
  502.                         sign = '-';
  503.                         num = - (signed long long) num;
  504.                         spec.field_width--;
  505.                 } else if (spec.flags & PLUS) {
  506.                         sign = '+';
  507.                         spec.field_width--;
  508.                 } else if (spec.flags & SPACE) {
  509.                         sign = ' ';
  510.                         spec.field_width--;
  511.                 }
  512.         }
  513.         if (need_pfx) {
  514.                 spec.field_width--;
  515.                 if (spec.base == 16)
  516.                         spec.field_width--;
  517.         }
  518.  
  519.         /* generate full string in tmp[], in reverse order */
  520.         i = 0;
  521.         if (num == 0)
  522.                 tmp[i++] = '0';
  523.         /* Generic code, for any base:
  524.         else do {
  525.                 tmp[i++] = (digits[do_div(num,base)] | locase);
  526.         } while (num != 0);
  527.         */
  528.         else if (spec.base != 10) { /* 8 or 16 */
  529.                 int mask = spec.base - 1;
  530.                 int shift = 3;
  531.                 if (spec.base == 16) shift = 4;
  532.                 do {
  533.                         tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
  534.                         num >>= shift;
  535.                 } while (num);
  536.         } else { /* base 10 */
  537.                 i = put_dec(tmp, num) - tmp;
  538.         }
  539.  
  540.         /* printing 100 using %2d gives "100", not "00" */
  541.         if (i > spec.precision)
  542.                 spec.precision = i;
  543.         /* leading space padding */
  544.         spec.field_width -= spec.precision;
  545.         if (!(spec.flags & (ZEROPAD+LEFT))) {
  546.                 while(--spec.field_width >= 0) {
  547.                         if (buf < end)
  548.                                 *buf = ' ';
  549.                         ++buf;
  550.                 }
  551.         }
  552.         /* sign */
  553.         if (sign) {
  554.                 if (buf < end)
  555.                         *buf = sign;
  556.                 ++buf;
  557.         }
  558.         /* "0x" / "0" prefix */
  559.         if (need_pfx) {
  560.                 if (buf < end)
  561.                         *buf = '0';
  562.                 ++buf;
  563.                 if (spec.base == 16) {
  564.                         if (buf < end)
  565.                                 *buf = ('X' | locase);
  566.                         ++buf;
  567.                 }
  568.         }
  569.         /* zero or space padding */
  570.         if (!(spec.flags & LEFT)) {
  571.                 char c = (spec.flags & ZEROPAD) ? '0' : ' ';
  572.                 while (--spec.field_width >= 0) {
  573.                         if (buf < end)
  574.                                 *buf = c;
  575.                         ++buf;
  576.                 }
  577.         }
  578.         /* hmm even more zero padding? */
  579.         while (i <= --spec.precision) {
  580.                 if (buf < end)
  581.                         *buf = '0';
  582.                 ++buf;
  583.         }
  584.         /* actual digits of result */
  585.         while (--i >= 0) {
  586.                 if (buf < end)
  587.                         *buf = tmp[i];
  588.                 ++buf;
  589.         }
  590.         /* trailing space padding */
  591.         while (--spec.field_width >= 0) {
  592.                 if (buf < end)
  593.                         *buf = ' ';
  594.                 ++buf;
  595.         }
  596.         return buf;
  597. }
  598.  
  599. static char *string(char *buf, char *end, char *s, struct printf_spec spec)
  600. {
  601.         int len, i;
  602.  
  603.         if ((unsigned long)s < PAGE_SIZE)
  604.                 s = "<NULL>";
  605.  
  606.         len = strnlen(s, spec.precision);
  607.  
  608.         if (!(spec.flags & LEFT)) {
  609.                 while (len < spec.field_width--) {
  610.                         if (buf < end)
  611.                                 *buf = ' ';
  612.                         ++buf;
  613.                 }
  614.         }
  615.         for (i = 0; i < len; ++i) {
  616.                 if (buf < end)
  617.                         *buf = *s;
  618.                 ++buf; ++s;
  619.         }
  620.         while (len < spec.field_width--) {
  621.                 if (buf < end)
  622.                         *buf = ' ';
  623.                 ++buf;
  624.         }
  625.         return buf;
  626. }
  627.  
  628.  
  629. /*
  630.  * Show a '%p' thing.
  631.  */
  632. static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
  633.                         struct printf_spec spec)
  634. {
  635.         if (!ptr)
  636.                 return string(buf, end, "(null)", spec);
  637.  
  638.     spec.flags |= SMALL;
  639.         if (spec.field_width == -1) {
  640.                 spec.field_width = 2*sizeof(void *);
  641.                 spec.flags |= ZEROPAD;
  642.         }
  643.         spec.base = 16;
  644.  
  645.         return number(buf, end, (unsigned long) ptr, spec);
  646. }
  647.  
  648. /*
  649.  * Helper function to decode printf style format.
  650.  * Each call decode a token from the format and return the
  651.  * number of characters read (or likely the delta where it wants
  652.  * to go on the next call).
  653.  * The decoded token is returned through the parameters
  654.  *
  655.  * 'h', 'l', or 'L' for integer fields
  656.  * 'z' support added 23/7/1999 S.H.
  657.  * 'z' changed to 'Z' --davidm 1/25/99
  658.  * 't' added for ptrdiff_t
  659.  *
  660.  * @fmt: the format string
  661.  * @type of the token returned
  662.  * @flags: various flags such as +, -, # tokens..
  663.  * @field_width: overwritten width
  664.  * @base: base of the number (octal, hex, ...)
  665.  * @precision: precision of a number
  666.  * @qualifier: qualifier of a number (long, size_t, ...)
  667.  */
  668. static int format_decode(const char *fmt, struct printf_spec *spec)
  669. {
  670.         const char *start = fmt;
  671.  
  672.         /* we finished early by reading the field width */
  673.         if (spec->type == FORMAT_TYPE_WIDTH) {
  674.                 if (spec->field_width < 0) {
  675.                         spec->field_width = -spec->field_width;
  676.                         spec->flags |= LEFT;
  677.                 }
  678.                 spec->type = FORMAT_TYPE_NONE;
  679.                 goto precision;
  680.         }
  681.  
  682.         /* we finished early by reading the precision */
  683.         if (spec->type == FORMAT_TYPE_PRECISION) {
  684.                 if (spec->precision < 0)
  685.                         spec->precision = 0;
  686.  
  687.                 spec->type = FORMAT_TYPE_NONE;
  688.                 goto qualifier;
  689.         }
  690.  
  691.         /* By default */
  692.         spec->type = FORMAT_TYPE_NONE;
  693.  
  694.         for (; *fmt ; ++fmt) {
  695.                 if (*fmt == '%')
  696.                         break;
  697.         }
  698.  
  699.         /* Return the current non-format string */
  700.         if (fmt != start || !*fmt)
  701.                 return fmt - start;
  702.  
  703.         /* Process flags */
  704.         spec->flags = 0;
  705.  
  706.         while (1) { /* this also skips first '%' */
  707.         int found = 1;
  708.  
  709.                 ++fmt;
  710.  
  711.                 switch (*fmt) {
  712.                 case '-': spec->flags |= LEFT;    break;
  713.                 case '+': spec->flags |= PLUS;    break;
  714.                 case ' ': spec->flags |= SPACE;   break;
  715.                 case '#': spec->flags |= SPECIAL; break;
  716.                 case '0': spec->flags |= ZEROPAD; break;
  717.         default:  found = 0;
  718.                 }
  719.  
  720.                 if (!found)
  721.                         break;
  722.         }
  723.  
  724.         /* get field width */
  725.         spec->field_width = -1;
  726.  
  727.         if (isdigit(*fmt))
  728.                 spec->field_width = skip_atoi(&fmt);
  729.         else if (*fmt == '*') {
  730.                 /* it's the next argument */
  731.                 spec->type = FORMAT_TYPE_WIDTH;
  732.                 return ++fmt - start;
  733.         }
  734.  
  735. precision:
  736.         /* get the precision */
  737.         spec->precision = -1;
  738.         if (*fmt == '.') {
  739.                 ++fmt;
  740.                 if (isdigit(*fmt)) {
  741.                         spec->precision = skip_atoi(&fmt);
  742.                         if (spec->precision < 0)
  743.                                 spec->precision = 0;
  744.                 } else if (*fmt == '*') {
  745.                         /* it's the next argument */
  746.                         spec->type = FORMAT_TYPE_PRECISION;
  747.                         return ++fmt - start;
  748.                 }
  749.         }
  750.  
  751. qualifier:
  752.         /* get the conversion qualifier */
  753.         spec->qualifier = -1;
  754.         if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
  755.             *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
  756.                 spec->qualifier = *fmt++;
  757.                 if (unlikely(spec->qualifier == *fmt)) {
  758.                         if (spec->qualifier == 'l') {
  759.                                 spec->qualifier = 'L';
  760.                                 ++fmt;
  761.                         } else if (spec->qualifier == 'h') {
  762.                                 spec->qualifier = 'H';
  763.                                 ++fmt;
  764.                         }
  765.                 }
  766.         }
  767.  
  768.         /* default base */
  769.         spec->base = 10;
  770.         switch (*fmt) {
  771.         case 'c':
  772.                 spec->type = FORMAT_TYPE_CHAR;
  773.                 return ++fmt - start;
  774.  
  775.         case 's':
  776.                 spec->type = FORMAT_TYPE_STR;
  777.                 return ++fmt - start;
  778.  
  779.         case 'p':
  780.                 spec->type = FORMAT_TYPE_PTR;
  781.                 return fmt - start;
  782.                 /* skip alnum */
  783.  
  784.         case 'n':
  785.                 spec->type = FORMAT_TYPE_NRCHARS;
  786.                 return ++fmt - start;
  787.  
  788.         case '%':
  789.                 spec->type = FORMAT_TYPE_PERCENT_CHAR;
  790.                 return ++fmt - start;
  791.  
  792.         /* integer number formats - set up the flags and "break" */
  793.         case 'o':
  794.                 spec->base = 8;
  795.                 break;
  796.  
  797.         case 'x':
  798.                 spec->flags |= SMALL;
  799.  
  800.         case 'X':
  801.                 spec->base = 16;
  802.                 break;
  803.  
  804.         case 'd':
  805.         case 'i':
  806.                 spec->flags |= SIGN;
  807.         case 'u':
  808.                 break;
  809.  
  810.         default:
  811.                 spec->type = FORMAT_TYPE_INVALID;
  812.                 return fmt - start;
  813.         }
  814.  
  815.         if (spec->qualifier == 'L')
  816.                 spec->type = FORMAT_TYPE_LONG_LONG;
  817.         else if (spec->qualifier == 'l') {
  818.                 if (spec->flags & SIGN)
  819.                         spec->type = FORMAT_TYPE_LONG;
  820.                 else
  821.                         spec->type = FORMAT_TYPE_ULONG;
  822.         } else if (spec->qualifier == 'Z' || spec->qualifier == 'z') {
  823.                 spec->type = FORMAT_TYPE_SIZE_T;
  824.         } else if (spec->qualifier == 't') {
  825.                 spec->type = FORMAT_TYPE_PTRDIFF;
  826.         } else if (spec->qualifier == 'H') {
  827.                 if (spec->flags & SIGN)
  828.                         spec->type = FORMAT_TYPE_BYTE;
  829.                 else
  830.                         spec->type = FORMAT_TYPE_UBYTE;
  831.         } else if (spec->qualifier == 'h') {
  832.                 if (spec->flags & SIGN)
  833.                         spec->type = FORMAT_TYPE_SHORT;
  834.                 else
  835.                         spec->type = FORMAT_TYPE_USHORT;
  836.         } else {
  837.                 if (spec->flags & SIGN)
  838.                         spec->type = FORMAT_TYPE_INT;
  839.                 else
  840.                         spec->type = FORMAT_TYPE_UINT;
  841.         }
  842.  
  843.         return ++fmt - start;
  844. }
  845.  
  846. /**
  847.  * vsnprintf - Format a string and place it in a buffer
  848.  * @buf: The buffer to place the result into
  849.  * @size: The size of the buffer, including the trailing null space
  850.  * @fmt: The format string to use
  851.  * @args: Arguments for the format string
  852.  *
  853.  *
  854.  * The return value is the number of characters which would
  855.  * be generated for the given input, excluding the trailing
  856.  * '\0', as per ISO C99. If you want to have the exact
  857.  * number of characters written into @buf as return value
  858.  * (not including the trailing '\0'), use vscnprintf(). If the
  859.  * return is greater than or equal to @size, the resulting
  860.  * string is truncated.
  861.  *
  862.  * Call this function if you are already dealing with a va_list.
  863.  * You probably want snprintf() instead.
  864.  */
  865. int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
  866. {
  867.         unsigned long long num;
  868.         char *str, *end, c;
  869.         int read;
  870.         struct printf_spec spec = {0};
  871.  
  872.         /* Reject out-of-range values early.  Large positive sizes are
  873.            used for unknown buffer sizes. */
  874.         if (unlikely((int) size < 0)) {
  875.                 /* There can be only one.. */
  876.                 static char warn = 1;
  877. //       WARN_ON(warn);
  878.                 warn = 0;
  879.                 return 0;
  880.         }
  881.  
  882.         str = buf;
  883.         end = buf + size;
  884.  
  885.         /* Make sure end is always >= buf */
  886.         if (end < buf) {
  887.                 end = ((void *)-1);
  888.                 size = end - buf;
  889.         }
  890.  
  891.         while (*fmt) {
  892.                 const char *old_fmt = fmt;
  893.  
  894.                 read = format_decode(fmt, &spec);
  895.  
  896.                 fmt += read;
  897.  
  898.                 switch (spec.type) {
  899.                 case FORMAT_TYPE_NONE: {
  900.                         int copy = read;
  901.                         if (str < end) {
  902.                                 if (copy > end - str)
  903.                                         copy = end - str;
  904.                                 memcpy(str, old_fmt, copy);
  905.                         }
  906.                         str += read;
  907.                         break;
  908.                 }
  909.  
  910.                 case FORMAT_TYPE_WIDTH:
  911.                         spec.field_width = va_arg(args, int);
  912.                         break;
  913.  
  914.                 case FORMAT_TYPE_PRECISION:
  915.                         spec.precision = va_arg(args, int);
  916.                         break;
  917.  
  918.                 case FORMAT_TYPE_CHAR:
  919.                         if (!(spec.flags & LEFT)) {
  920.                                 while (--spec.field_width > 0) {
  921.                                         if (str < end)
  922.                                                 *str = ' ';
  923.                                         ++str;
  924.  
  925.                                 }
  926.                         }
  927.                         c = (unsigned char) va_arg(args, int);
  928.                         if (str < end)
  929.                                 *str = c;
  930.                         ++str;
  931.                         while (--spec.field_width > 0) {
  932.                                 if (str < end)
  933.                                         *str = ' ';
  934.                                 ++str;
  935.                         }
  936.                         break;
  937.  
  938.                 case FORMAT_TYPE_STR:
  939.                         str = string(str, end, va_arg(args, char *), spec);
  940.                         break;
  941.  
  942.                 case FORMAT_TYPE_PTR:
  943.                         str = pointer(fmt+1, str, end, va_arg(args, void *),
  944.                                       spec);
  945.                         while (isalnum(*fmt))
  946.                                 fmt++;
  947.                         break;
  948.  
  949.                 case FORMAT_TYPE_PERCENT_CHAR:
  950.                         if (str < end)
  951.                                 *str = '%';
  952.                         ++str;
  953.                         break;
  954.  
  955.                 case FORMAT_TYPE_INVALID:
  956.                         if (str < end)
  957.                                 *str = '%';
  958.                         ++str;
  959.                         break;
  960.  
  961.                 case FORMAT_TYPE_NRCHARS: {
  962.                         int qualifier = spec.qualifier;
  963.  
  964.                         if (qualifier == 'l') {
  965.                                 long *ip = va_arg(args, long *);
  966.                                 *ip = (str - buf);
  967.                         } else if (qualifier == 'Z' ||
  968.                                         qualifier == 'z') {
  969.                                 size_t *ip = va_arg(args, size_t *);
  970.                                 *ip = (str - buf);
  971.                         } else {
  972.                                 int *ip = va_arg(args, int *);
  973.                                 *ip = (str - buf);
  974.                         }
  975.                         break;
  976.                 }
  977.  
  978.                 default:
  979.                         switch (spec.type) {
  980.                         case FORMAT_TYPE_LONG_LONG:
  981.                                 num = va_arg(args, long long);
  982.                                 break;
  983.                         case FORMAT_TYPE_ULONG:
  984.                                 num = va_arg(args, unsigned long);
  985.                                 break;
  986.                         case FORMAT_TYPE_LONG:
  987.                                 num = va_arg(args, long);
  988.                                 break;
  989.                         case FORMAT_TYPE_SIZE_T:
  990.                                 num = va_arg(args, size_t);
  991.                                 break;
  992. //           case FORMAT_TYPE_PTRDIFF:
  993. //               num = va_arg(args, ptrdiff_t);
  994. //               break;
  995.                         case FORMAT_TYPE_UBYTE:
  996.                                 num = (unsigned char) va_arg(args, int);
  997.                                 break;
  998.                         case FORMAT_TYPE_BYTE:
  999.                                 num = (signed char) va_arg(args, int);
  1000.                                 break;
  1001.                         case FORMAT_TYPE_USHORT:
  1002.                                 num = (unsigned short) va_arg(args, int);
  1003.                                 break;
  1004.                         case FORMAT_TYPE_SHORT:
  1005.                                 num = (short) va_arg(args, int);
  1006.                                 break;
  1007.                         case FORMAT_TYPE_INT:
  1008.                                 num = (int) va_arg(args, int);
  1009.                                 break;
  1010.                         default:
  1011.                                 num = va_arg(args, unsigned int);
  1012.                         }
  1013.  
  1014.                         str = number(str, end, num, spec);
  1015.                 }
  1016.         }
  1017.  
  1018.         if (size > 0) {
  1019.                 if (str < end)
  1020.                         *str = '\0';
  1021.                 else
  1022.                         end[-1] = '\0';
  1023.         }
  1024.  
  1025.         /* the trailing null byte doesn't count towards the total */
  1026.         return str-buf;
  1027.  
  1028. }
  1029.  
  1030. /**
  1031.  * snprintf - Format a string and place it in a buffer
  1032.  * @buf: The buffer to place the result into
  1033.  * @size: The size of the buffer, including the trailing null space
  1034.  * @fmt: The format string to use
  1035.  * @...: Arguments for the format string
  1036.  *
  1037.  * The return value is the number of characters which would be
  1038.  * generated for the given input, excluding the trailing null,
  1039.  * as per ISO C99.  If the return is greater than or equal to
  1040.  * @size, the resulting string is truncated.
  1041.  *
  1042.  * See the vsnprintf() documentation for format string extensions over C99.
  1043.  */
  1044. int snprintf(char * buf, size_t size, const char *fmt, ...)
  1045. {
  1046.         va_list args;
  1047.         int i;
  1048.  
  1049.         va_start(args, fmt);
  1050.         i=vsnprintf(buf,size,fmt,args);
  1051.         va_end(args);
  1052.         return i;
  1053. }
  1054.  
  1055. /**
  1056.  * scnprintf - Format a string and place it in a buffer
  1057.  * @buf: The buffer to place the result into
  1058.  * @size: The size of the buffer, including the trailing null space
  1059.  * @fmt: The format string to use
  1060.  * @...: Arguments for the format string
  1061.  *
  1062.  * The return value is the number of characters written into @buf not including
  1063.  * the trailing '\0'. If @size is <= 0 the function returns 0.
  1064.  */
  1065.  
  1066. int scnprintf(char * buf, size_t size, const char *fmt, ...)
  1067. {
  1068.         va_list args;
  1069.         int i;
  1070.  
  1071.         va_start(args, fmt);
  1072.         i = vsnprintf(buf, size, fmt, args);
  1073.         va_end(args);
  1074.         return (i >= size) ? (size - 1) : i;
  1075. }
  1076.  
  1077. /**
  1078.  * vsprintf - Format a string and place it in a buffer
  1079.  * @buf: The buffer to place the result into
  1080.  * @fmt: The format string to use
  1081.  * @args: Arguments for the format string
  1082.  *
  1083.  * The function returns the number of characters written
  1084.  * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
  1085.  * buffer overflows.
  1086.  *
  1087.  * Call this function if you are already dealing with a va_list.
  1088.  * You probably want sprintf() instead.
  1089.  *
  1090.  * See the vsnprintf() documentation for format string extensions over C99.
  1091.  */
  1092. int vsprintf(char *buf, const char *fmt, va_list args)
  1093. {
  1094.     return vsnprintf(buf, __INT_MAX__, fmt, args);
  1095. }
  1096.  
  1097. /**
  1098.  * sprintf - Format a string and place it in a buffer
  1099.  * @buf: The buffer to place the result into
  1100.  * @fmt: The format string to use
  1101.  * @...: Arguments for the format string
  1102.  *
  1103.  * The function returns the number of characters written
  1104.  * into @buf. Use snprintf() or scnprintf() in order to avoid
  1105.  * buffer overflows.
  1106.  *
  1107.  * See the vsnprintf() documentation for format string extensions over C99.
  1108.  */
  1109. int sprintf(char * buf, const char *fmt, ...)
  1110. {
  1111.         va_list args;
  1112.         int i;
  1113.  
  1114.         va_start(args, fmt);
  1115.     i=vsnprintf(buf, __INT_MAX__, fmt, args);
  1116.         va_end(args);
  1117.         return i;
  1118. }
  1119.  
  1120. static inline
  1121. void api_putc(char c)
  1122. {
  1123.     if (c == '\n') api_putc('\r');
  1124.  
  1125.     __asm__ __volatile__(
  1126.     "int $0x40"
  1127.     ::"a"(63),"b"(1),"c"(c));
  1128. }
  1129.  
  1130. int API print(const char *fmt,...)
  1131. {
  1132.     char buf[256];
  1133.     va_list args;
  1134.     int retval;
  1135.     int i;
  1136.  
  1137.     va_start(args, fmt);
  1138.     i = vsnprintf(buf, 256, fmt, args);
  1139.     va_end(args);
  1140.  
  1141.     retval = (i >= 256) ? (256 - 1) : i;
  1142.  
  1143.     for(i = 0; i< retval; i++)
  1144.         api_putc(buf[i]);
  1145.  
  1146.     return retval;
  1147. };
  1148.  
  1149.  
  1150.  
  1151. #if 0
  1152. /**
  1153.  * vsscanf - Unformat a buffer into a list of arguments
  1154.  * @buf:        input buffer
  1155.  * @fmt:        format of buffer
  1156.  * @args:       arguments
  1157.  */
  1158. int vsscanf(const char * buf, const char * fmt, va_list args)
  1159. {
  1160.         const char *str = buf;
  1161.         char *next;
  1162.         char digit;
  1163.         int num = 0;
  1164.         int qualifier;
  1165.         int base;
  1166.         int field_width;
  1167.         int is_sign = 0;
  1168.  
  1169.         while(*fmt && *str) {
  1170.                 /* skip any white space in format */
  1171.                 /* white space in format matchs any amount of
  1172.                  * white space, including none, in the input.
  1173.                  */
  1174.                 if (isspace(*fmt)) {
  1175.                         while (isspace(*fmt))
  1176.                                 ++fmt;
  1177.                         while (isspace(*str))
  1178.                                 ++str;
  1179.                 }
  1180.  
  1181.                 /* anything that is not a conversion must match exactly */
  1182.                 if (*fmt != '%' && *fmt) {
  1183.                         if (*fmt++ != *str++)
  1184.                                 break;
  1185.                         continue;
  1186.                 }
  1187.  
  1188.                 if (!*fmt)
  1189.                         break;
  1190.                 ++fmt;
  1191.  
  1192.                 /* skip this conversion.
  1193.                  * advance both strings to next white space
  1194.                  */
  1195.                 if (*fmt == '*') {
  1196.                         while (!isspace(*fmt) && *fmt)
  1197.                                 fmt++;
  1198.                         while (!isspace(*str) && *str)
  1199.                                 str++;
  1200.                         continue;
  1201.                 }
  1202.  
  1203.                 /* get field width */
  1204.                 field_width = -1;
  1205.                 if (isdigit(*fmt))
  1206.                         field_width = skip_atoi(&fmt);
  1207.  
  1208.                 /* get conversion qualifier */
  1209.                 qualifier = -1;
  1210.                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
  1211.                     *fmt == 'Z' || *fmt == 'z') {
  1212.                         qualifier = *fmt++;
  1213.                         if (unlikely(qualifier == *fmt)) {
  1214.                                 if (qualifier == 'h') {
  1215.                                         qualifier = 'H';
  1216.                                         fmt++;
  1217.                                 } else if (qualifier == 'l') {
  1218.                                         qualifier = 'L';
  1219.                                         fmt++;
  1220.                                 }
  1221.                         }
  1222.                 }
  1223.                 base = 10;
  1224.                 is_sign = 0;
  1225.  
  1226.                 if (!*fmt || !*str)
  1227.                         break;
  1228.  
  1229.                 switch(*fmt++) {
  1230.                 case 'c':
  1231.                 {
  1232.                         char *s = (char *) va_arg(args,char*);
  1233.                         if (field_width == -1)
  1234.                                 field_width = 1;
  1235.                         do {
  1236.                                 *s++ = *str++;
  1237.                         } while (--field_width > 0 && *str);
  1238.                         num++;
  1239.                 }
  1240.                 continue;
  1241.                 case 's':
  1242.                 {
  1243.                         char *s = (char *) va_arg(args, char *);
  1244.                         if(field_width == -1)
  1245.                                 field_width = INT_MAX;
  1246.                         /* first, skip leading white space in buffer */
  1247.                         while (isspace(*str))
  1248.                                 str++;
  1249.  
  1250.                         /* now copy until next white space */
  1251.                         while (*str && !isspace(*str) && field_width--) {
  1252.                                 *s++ = *str++;
  1253.                         }
  1254.                         *s = '\0';
  1255.                         num++;
  1256.                 }
  1257.                 continue;
  1258.                 case 'n':
  1259.                         /* return number of characters read so far */
  1260.                 {
  1261.                         int *i = (int *)va_arg(args,int*);
  1262.                         *i = str - buf;
  1263.                 }
  1264.                 continue;
  1265.                 case 'o':
  1266.                         base = 8;
  1267.                         break;
  1268.                 case 'x':
  1269.                 case 'X':
  1270.                         base = 16;
  1271.                         break;
  1272.                 case 'i':
  1273.                         base = 0;
  1274.                 case 'd':
  1275.                         is_sign = 1;
  1276.                 case 'u':
  1277.                         break;
  1278.                 case '%':
  1279.                         /* looking for '%' in str */
  1280.                         if (*str++ != '%')
  1281.                                 return num;
  1282.                         continue;
  1283.                 default:
  1284.                         /* invalid format; stop here */
  1285.                         return num;
  1286.                 }
  1287.  
  1288.                 /* have some sort of integer conversion.
  1289.                  * first, skip white space in buffer.
  1290.                  */
  1291.                 while (isspace(*str))
  1292.                         str++;
  1293.  
  1294.                 digit = *str;
  1295.                 if (is_sign && digit == '-')
  1296.                         digit = *(str + 1);
  1297.  
  1298.                 if (!digit
  1299.                     || (base == 16 && !isxdigit(digit))
  1300.                     || (base == 10 && !isdigit(digit))
  1301.                     || (base == 8 && (!isdigit(digit) || digit > '7'))
  1302.                     || (base == 0 && !isdigit(digit)))
  1303.                                 break;
  1304.  
  1305.                 switch(qualifier) {
  1306.                 case 'H':       /* that's 'hh' in format */
  1307.                         if (is_sign) {
  1308.                                 signed char *s = (signed char *) va_arg(args,signed char *);
  1309.                                 *s = (signed char) simple_strtol(str,&next,base);
  1310.                         } else {
  1311.                                 unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
  1312.                                 *s = (unsigned char) simple_strtoul(str, &next, base);
  1313.                         }
  1314.                         break;
  1315.                 case 'h':
  1316.                         if (is_sign) {
  1317.                                 short *s = (short *) va_arg(args,short *);
  1318.                                 *s = (short) simple_strtol(str,&next,base);
  1319.                         } else {
  1320.                                 unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
  1321.                                 *s = (unsigned short) simple_strtoul(str, &next, base);
  1322.                         }
  1323.                         break;
  1324.                 case 'l':
  1325.                         if (is_sign) {
  1326.                                 long *l = (long *) va_arg(args,long *);
  1327.                                 *l = simple_strtol(str,&next,base);
  1328.                         } else {
  1329.                                 unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
  1330.                                 *l = simple_strtoul(str,&next,base);
  1331.                         }
  1332.                         break;
  1333.                 case 'L':
  1334.                         if (is_sign) {
  1335.                                 long long *l = (long long*) va_arg(args,long long *);
  1336.                                 *l = simple_strtoll(str,&next,base);
  1337.                         } else {
  1338.                                 unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
  1339.                                 *l = simple_strtoull(str,&next,base);
  1340.                         }
  1341.                         break;
  1342.                 case 'Z':
  1343.                 case 'z':
  1344.                 {
  1345.                         size_t *s = (size_t*) va_arg(args,size_t*);
  1346.                         *s = (size_t) simple_strtoul(str,&next,base);
  1347.                 }
  1348.                 break;
  1349.                 default:
  1350.                         if (is_sign) {
  1351.                                 int *i = (int *) va_arg(args, int*);
  1352.                                 *i = (int) simple_strtol(str,&next,base);
  1353.                         } else {
  1354.                                 unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
  1355.                                 *i = (unsigned int) simple_strtoul(str,&next,base);
  1356.                         }
  1357.                         break;
  1358.                 }
  1359.                 num++;
  1360.  
  1361.                 if (!next)
  1362.                         break;
  1363.                 str = next;
  1364.         }
  1365.  
  1366.         /*
  1367.          * Now we've come all the way through so either the input string or the
  1368.          * format ended. In the former case, there can be a %n at the current
  1369.          * position in the format that needs to be filled.
  1370.          */
  1371.         if (*fmt == '%' && *(fmt + 1) == 'n') {
  1372.                 int *p = (int *)va_arg(args, int *);
  1373.                 *p = str - buf;
  1374.         }
  1375.  
  1376.         return num;
  1377. }
  1378. #endif
  1379.  
  1380.