xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] mini-os: replace lib/printf.c with a version not under GPL
@ 2016-07-04  9:16 Juergen Gross
  2016-07-12  8:48 ` Samuel Thibault
  0 siblings, 1 reply; 4+ messages in thread
From: Juergen Gross @ 2016-07-04  9:16 UTC (permalink / raw)
  To: minios-devel, xen-devel; +Cc: Juergen Gross, samuel.thibault, andrew.cooper3

Instead of a Linux kernel based implementation use one from freeBSD.

As a result some of the printings will change due to more posix like
behavior of %p format (omitting leading zeroes, prepending "0x").

Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2: remove include/lib-gpl.h as requested by Samuel Thibault
---
 blkfront.c        |    4 -
 include/lib-gpl.h |   59 --
 include/lib.h     |   27 +-
 lib/printf.c      | 1744 +++++++++++++++++++++++++++++++++--------------------
 tpmback.c         |    4 -
 5 files changed, 1119 insertions(+), 719 deletions(-)
 delete mode 100644 include/lib-gpl.h

diff --git a/blkfront.c b/blkfront.c
index bdb7765..f747216 100644
--- a/blkfront.c
+++ b/blkfront.c
@@ -17,10 +17,6 @@
 #include <mini-os/lib.h>
 #include <fcntl.h>
 
-#ifndef HAVE_LIBC
-#define strtoul simple_strtoul
-#endif
-
 /* Note: we generally don't need to disable IRQs since we hardly do anything in
  * the interrupt handler.  */
 
diff --git a/include/lib-gpl.h b/include/lib-gpl.h
deleted file mode 100644
index d5602b2..0000000
--- a/include/lib-gpl.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- *        File: lib.h
- *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- *     Changes: 
- *              
- *        Date: Aug 2003
- * 
- * Environment: Xen Minimal OS
- * Description: Random useful library functions, from Linux'
- * include/linux/kernel.h
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef _LIB_GPL_H_
-#define _LIB_GPL_H_
-
-#ifndef HAVE_LIBC
-/* printing */
-extern unsigned long simple_strtoul(const char *,char **,unsigned int);
-extern long simple_strtol(const char *,char **,unsigned int);
-extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
-extern long long simple_strtoll(const char *,char **,unsigned int);
-
-extern int sprintf(char * buf, const char * fmt, ...)
-	__attribute__ ((format (printf, 2, 3)));
-extern int vsprintf(char *buf, const char *, va_list)
-	__attribute__ ((format (printf, 2, 0)));
-extern int snprintf(char * buf, size_t size, const char * fmt, ...)
-	__attribute__ ((format (printf, 3, 4)));
-extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
-	__attribute__ ((format (printf, 3, 0)));
-extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
-	__attribute__ ((format (printf, 3, 4)));
-extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
-	__attribute__ ((format (printf, 3, 0)));
-extern int sscanf(const char *, const char *, ...)
-	__attribute__ ((format (scanf, 2, 3)));
-extern int vsscanf(const char *, const char *, va_list)
-	__attribute__ ((format (scanf, 2, 0)));
-#endif
-
-#endif /* _LIB_GPL_H_ */
diff --git a/include/lib.h b/include/lib.h
index 62836c7..39d6a18 100644
--- a/include/lib.h
+++ b/include/lib.h
@@ -66,11 +66,6 @@
 #ifdef HAVE_LIBC
 #include <sys/queue.h>
 #include <stdio.h>
-#else
-#include <lib-gpl.h>
-#endif
-
-#ifdef HAVE_LIBC
 #include <string.h>
 #else
 /* string and memory manipulation */
@@ -107,6 +102,28 @@ char *strrchr(const char *p, int ch);
 void	*memcpy(void *to, const void *from, size_t len);
 
 size_t strnlen(const char *, size_t);
+
+unsigned long strtoul(const char *nptr, char **endptr, int base);
+int64_t strtoq(const char *nptr, char **endptr, int base);
+uint64_t strtouq(const char *nptr, char **endptr, int base);
+
+extern int sprintf(char * buf, const char * fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int vsprintf(char *buf, const char *, va_list)
+        __attribute__ ((format (printf, 2, 0)));
+extern int snprintf(char * buf, size_t size, const char * fmt, ...)
+        __attribute__ ((format (printf, 3, 4)));
+extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+        __attribute__ ((format (printf, 3, 0)));
+extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
+        __attribute__ ((format (printf, 3, 4)));
+extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+        __attribute__ ((format (printf, 3, 0)));
+extern int sscanf(const char *, const char *, ...)
+        __attribute__ ((format (scanf, 2, 3)));
+extern int vsscanf(const char *, const char *, va_list)
+        __attribute__ ((format (scanf, 2, 0)));
+
 #endif
 
 #include <mini-os/console.h>
diff --git a/lib/printf.c b/lib/printf.c
index 40f92fc..e48ab61 100644
--- a/lib/printf.c
+++ b/lib/printf.c
@@ -1,50 +1,53 @@
 /*
  ****************************************************************************
- * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
  *
  *        File: printf.c
- *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- *     Changes: Grzegorz Milos (gm281@cam.ac.uk) 
+ *      Author: Juergen Gross <jgross@suse.com>
  *
- *        Date: Aug 2003, Aug 2005
+ *        Date: Jun 2016
  *
  * Environment: Xen Minimal OS
  * Description: Library functions for printing
- *              (Linux port, mainly lib/vsprintf.c)
+ *              (freeBSD port)
  *
  ****************************************************************************
  */
 
-/*
- * Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
-/*
- * Wirzenius wrote this portably, Torvalds fucked it up :-)
- */
-
-/*
- * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
- * - changed to provide snprintf and vsnprintf functions
- * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
- * - scnprintf and vscnprintf
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
  *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #if !defined HAVE_LIBC
@@ -57,449 +60,529 @@
 #include <mini-os/ctype.h>
 #include <mini-os/posix/limits.h>
 
-/**
- * simple_strtoul - convert a string to an unsigned long
- * @cp: The start of the string
- * @endp: A pointer to the end of the parsed string will be placed here
- * @base: The number base to use
+#define __DECONST(type, var)    ((type)(uintptr_t)(const void *)(var))
+/* 64 bits + 0-Byte at end */
+#define MAXNBUF	65
+
+static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+/*
+ * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
+ * order; return an optional length and a pointer to the last character
+ * written in the buffer (i.e., the first character of the string).
+ * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
  */
-unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+static char *
+ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
 {
-    unsigned long result = 0,value;
-
-    if (!base) {
-        base = 10;
-        if (*cp == '0') {
-            base = 8;
-            cp++;
-            if ((*cp == 'x') && isxdigit(cp[1])) {
-                cp++;
-                base = 16;
-            }
-        }
-    }
-    while (isxdigit(*cp) &&
-           (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
-        result = result*base + value;
-        cp++;
-    }
-    if (endp)
-        *endp = (char *)cp;
-    return result;
-}
-
-/**
- * simple_strtol - convert a string to a signed long
- * @cp: The start of the string
- * @endp: A pointer to the end of the parsed string will be placed here
- * @base: The number base to use
- */
-long simple_strtol(const char *cp,char **endp,unsigned int base)
-{
-    if(*cp=='-')
-        return -simple_strtoul(cp+1,endp,base);
-    return simple_strtoul(cp,endp,base);
+	char *p, c;
+
+	p = nbuf;
+	*p = '\0';
+	do {
+		c = hex2ascii_data[num % base];
+		*++p = upper ? toupper(c) : c;
+	} while (num /= base);
+	if (lenp)
+		*lenp = p - nbuf;
+	return (p);
 }
 
-/**
- * simple_strtoull - convert a string to an unsigned long long
- * @cp: The start of the string
- * @endp: A pointer to the end of the parsed string will be placed here
- * @base: The number base to use
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
  */
-unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
+unsigned long
+strtoul(const char *nptr, char **endptr, int base)
 {
-    unsigned long long result = 0,value;
-
-    if (!base) {
-        base = 10;
-        if (*cp == '0') {
-            base = 8;
-            cp++;
-            if ((*cp == 'x') && isxdigit(cp[1])) {
-                cp++;
+        const char *s = nptr;
+        unsigned long acc;
+        unsigned char c;
+        unsigned long cutoff;
+        int neg = 0, any, cutlim;
+
+        /*
+         * See strtol for comments as to the logic used.
+         */
+        do {
+                c = *s++;
+        } while (isspace(c));
+        if (c == '-') {
+                neg = 1;
+                c = *s++;
+        } else if (c == '+')
+                c = *s++;
+        if ((base == 0 || base == 16) &&
+            c == '0' && (*s == 'x' || *s == 'X')) {
+                c = s[1];
+                s += 2;
                 base = 16;
-            }
         }
-    }
-    while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
-                                                               ? toupper(*cp) : *cp)-'A'+10) < base) {
-        result = result*base + value;
-        cp++;
-    }
-    if (endp)
-        *endp = (char *)cp;
-    return result;
+        if (base == 0)
+                base = c == '0' ? 8 : 10;
+        cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+        cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+        for (acc = 0, any = 0;; c = *s++) {
+                if (!isascii(c))
+                        break;
+                if (isdigit(c))
+                        c -= '0';
+                else if (isalpha(c))
+                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+                else
+                        break;
+                if (c >= base)
+                        break;
+                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+                        any = -1;
+                else {
+                        any = 1;
+                        acc *= base;
+                        acc += c;
+                }
+        }
+        if (any < 0) {
+                acc = ULONG_MAX;
+        } else if (neg)
+                acc = -acc;
+        if (endptr != 0)
+                *endptr = __DECONST(char *, any ? s - 1 : nptr);
+        return (acc);
 }
 
-/**
- * simple_strtoll - convert a string to a signed long long
- * @cp: The start of the string
- * @endp: A pointer to the end of the parsed string will be placed here
- * @base: The number base to use
+/*
+ * Convert a string to a quad integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
  */
-long long simple_strtoll(const char *cp,char **endp,unsigned int base)
-{
-    if(*cp=='-')
-        return -simple_strtoull(cp+1,endp,base);
-    return simple_strtoull(cp,endp,base);
-}
-
-static int skip_atoi(const char **s)
-{
-    int i=0;
-
-    while (isdigit(**s))
-        i = i*10 + *((*s)++) - '0';
-    return i;
-}
-
-#define ZEROPAD 1               /* pad with zero */
-#define SIGN    2               /* unsigned/signed long */
-#define PLUS    4               /* show plus */
-#define SPACE   8               /* space if plus */
-#define LEFT    16              /* left justified */
-#define SPECIAL 32              /* 0x */
-#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
-
-static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
+int64_t
+strtoq(const char *nptr, char **endptr, int base)
 {
-    char c,sign,tmp[66];
-    const char *digits;
-    const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-    const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-    int i;
-
-    digits = (type & LARGE) ? large_digits : small_digits;
-    if (type & LEFT)
-        type &= ~ZEROPAD;
-    if (base < 2 || base > 36)
-        return buf;
-    c = (type & ZEROPAD) ? '0' : ' ';
-    sign = 0;
-    if (type & SIGN) {
-        if (num < 0) {
-            sign = '-';
-            num = -num;
-            size--;
-        } else if (type & PLUS) {
-            sign = '+';
-            size--;
-        } else if (type & SPACE) {
-            sign = ' ';
-            size--;
-        }
-    }
-    if (type & SPECIAL) {
-        if (base == 16)
-            size -= 2;
-        else if (base == 8)
-            size--;
-    }
-    i = 0;
-    if (num == 0)
-        tmp[i++]='0';
-    else 
-    {
-        /* XXX KAF: force unsigned mod and div. */
-        unsigned long long num2=(unsigned long long)num;
-        unsigned int base2=(unsigned int)base;
-        while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }
-    }
-    if (i > precision)
-        precision = i;
-    size -= precision;
-    if (!(type&(ZEROPAD+LEFT))) {
-        while(size-->0) {
-            if (buf <= end)
-                *buf = ' ';
-            ++buf;
+        const char *s;
+        uint64_t acc;
+        unsigned char c;
+        uint64_t qbase, cutoff;
+        int neg, any, cutlim;
+
+        /*
+         * Skip white space and pick up leading +/- sign if any.
+         * If base is 0, allow 0x for hex and 0 for octal, else
+         * assume decimal; if base is already 16, allow 0x.
+         */
+        s = nptr;
+        do {
+                c = *s++;
+        } while (isspace(c));
+        if (c == '-') {
+                neg = 1;
+                c = *s++;
+        } else {
+                neg = 0;
+                if (c == '+')
+                        c = *s++;
         }
-    }
-    if (sign) {
-        if (buf <= end)
-            *buf = sign;
-        ++buf;
-    }
-    if (type & SPECIAL) {
-        if (base==8) {
-            if (buf <= end)
-                *buf = '0';
-            ++buf;
-        } else if (base==16) {
-            if (buf <= end)
-                *buf = '0';
-            ++buf;
-            if (buf <= end)
-                *buf = digits[33];
-            ++buf;
+        if ((base == 0 || base == 16) &&
+            c == '0' && (*s == 'x' || *s == 'X')) {
+                c = s[1];
+                s += 2;
+                base = 16;
         }
-    }
-    if (!(type & LEFT)) {
-        while (size-- > 0) {
-            if (buf <= end)
-                *buf = c;
-            ++buf;
+        if (base == 0)
+                base = c == '0' ? 8 : 10;
+
+        /*
+         * Compute the cutoff value between legal numbers and illegal
+         * numbers.  That is the largest legal value, divided by the
+         * base.  An input number that is greater than this value, if
+         * followed by a legal input character, is too big.  One that
+         * is equal to this value may be valid or not; the limit
+         * between valid and invalid numbers is then based on the last
+         * digit.  For instance, if the range for quads is
+         * [-9223372036854775808..9223372036854775807] and the input base
+         * is 10, cutoff will be set to 922337203685477580 and cutlim to
+         * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+         * accumulated a value > 922337203685477580, or equal but the
+         * next digit is > 7 (or 8), the number is too big, and we will
+         * return a range error.
+         *
+         * Set any if any `digits' consumed; make it negative to indicate
+         * overflow.
+         */
+        qbase = (unsigned)base;
+        cutoff = neg ? (uint64_t)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX : LLONG_MAX;
+        cutlim = cutoff % qbase;
+        cutoff /= qbase;
+        for (acc = 0, any = 0;; c = *s++) {
+                if (!isascii(c))
+                        break;
+                if (isdigit(c))
+                        c -= '0';
+                else if (isalpha(c))
+                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+                else
+                        break;
+                if (c >= base)
+                        break;
+                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+                        any = -1;
+                else {
+                        any = 1;
+                        acc *= qbase;
+                        acc += c;
+                }
         }
-    }
-    while (i < precision--) {
-        if (buf <= end)
-            *buf = '0';
-        ++buf;
-    }
-    while (i-- > 0) {
-        if (buf <= end)
-            *buf = tmp[i];
-        ++buf;
-    }
-    while (size-- > 0) {
-        if (buf <= end)
-            *buf = ' ';
-        ++buf;
-    }
-    return buf;
+        if (any < 0) {
+                acc = neg ? LLONG_MIN : LLONG_MAX;
+        } else if (neg)
+                acc = -acc;
+        if (endptr != 0)
+                *endptr = __DECONST(char *, any ? s - 1 : nptr);
+        return (acc);
 }
 
-/**
-* vsnprintf - Format a string and place it in a buffer
-* @buf: The buffer to place the result into
-* @size: The size of the buffer, including the trailing null space
-* @fmt: The format string to use
-* @args: Arguments for the format string
-*
-* Call this function if you are already dealing with a va_list.
-* You probably want snprintf instead.
+/*
+ * Convert a string to an unsigned quad integer.
+ *
+ * Ignores `locale' stuff.  Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
  */
-int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+uint64_t
+strtouq(const char *nptr, char **endptr, int base)
 {
-    int len;
-    unsigned long long num;
-    int i, base;
-    char *str, *end, c;
-    const char *s;
-
-    int flags;          /* flags to number() */
-
-    int field_width;    /* width of output field */
-    int precision;              /* min. # of digits for integers; max
-                                   number of chars for from string */
-    int qualifier;              /* 'h', 'l', or 'L' for integer fields */
-                                /* 'z' support added 23/7/1999 S.H.    */
-                                /* 'z' changed to 'Z' --davidm 1/25/99 */
-
-    str = buf;
-    end = buf + size - 1;
-
-    if (end < buf - 1) {
-        end = ((void *) -1);
-        size = end - buf + 1;
-    }
-
-    for (; *fmt ; ++fmt) {
-        if (*fmt != '%') {
-            if (str <= end)
-                *str = *fmt;
-            ++str;
-            continue;
-        }
-
-        /* process flags */
-        flags = 0;
-    repeat:
-        ++fmt;          /* this also skips first '%' */
-        switch (*fmt) {
-        case '-': flags |= LEFT; goto repeat;
-        case '+': flags |= PLUS; goto repeat;
-        case ' ': flags |= SPACE; goto repeat;
-        case '#': flags |= SPECIAL; goto repeat;
-        case '0': flags |= ZEROPAD; goto repeat;
-        }
-
-        /* get field width */
-        field_width = -1;
-        if (isdigit(*fmt))
-            field_width = skip_atoi(&fmt);
-        else if (*fmt == '*') {
-            ++fmt;
-            /* it's the next argument */
-            field_width = va_arg(args, int);
-            if (field_width < 0) {
-                field_width = -field_width;
-                flags |= LEFT;
-            }
-        }
-
-        /* get the precision */
-        precision = -1;
-        if (*fmt == '.') {
-            ++fmt;
-            if (isdigit(*fmt))
-                precision = skip_atoi(&fmt);
-            else if (*fmt == '*') {
-                ++fmt;
-                          /* it's the next argument */
-                precision = va_arg(args, int);
-            }
-            if (precision < 0)
-                precision = 0;
+        const char *s = nptr;
+        uint64_t acc;
+        unsigned char c;
+        uint64_t qbase, cutoff;
+        int neg, any, cutlim;
+
+        /*
+         * See strtoq for comments as to the logic used.
+         */
+        do {
+                c = *s++;
+        } while (isspace(c));
+        if (c == '-') {
+                neg = 1;
+                c = *s++;
+        } else {
+                neg = 0;
+                if (c == '+')
+                        c = *s++;
         }
-
-        /* get the conversion qualifier */
-        qualifier = -1;
-        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z' || *fmt == 'z') {
-            qualifier = *fmt;
-            ++fmt;
-            if (qualifier == 'l' && *fmt == 'l') {
-                qualifier = 'L';
-                ++fmt;
-            } else if (qualifier == 'z') {
-                qualifier = 'Z';
-            }
+        if ((base == 0 || base == 16) &&
+            c == '0' && (*s == 'x' || *s == 'X')) {
+                c = s[1];
+                s += 2;
+                base = 16;
         }
-        if (*fmt == 'q') {
-            qualifier = 'L';
-            ++fmt;
+        if (base == 0)
+                base = c == '0' ? 8 : 10;
+        qbase = (unsigned)base;
+        cutoff = (uint64_t)ULLONG_MAX / qbase;
+        cutlim = (uint64_t)ULLONG_MAX % qbase;
+        for (acc = 0, any = 0;; c = *s++) {
+                if (!isascii(c))
+                        break;
+                if (isdigit(c))
+                        c -= '0';
+                else if (isalpha(c))
+                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+                else
+                        break;
+                if (c >= base)
+                        break;
+                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+                        any = -1;
+                else {
+                        any = 1;
+                        acc *= qbase;
+                        acc += c;
+                }
         }
+        if (any < 0) {
+                acc = ULLONG_MAX;
+        } else if (neg)
+                acc = -acc;
+        if (endptr != 0)
+                *endptr = __DECONST(char *, any ? s - 1 : nptr);
+        return (acc);
+}
 
-        /* default base */
-        base = 10;
-
-        switch (*fmt) {
-        case 'c':
-            if (!(flags & LEFT)) {
-                while (--field_width > 0) {
-                    if (str <= end)
-                        *str = ' ';
-                    ++str;
+/*
+ * Scaled down version of printf(3).
+ */
+int
+vsnprintf(char *str, size_t size, char const *fmt, va_list ap)
+{
+#define PCHAR(c) { if (size >= 2) { *str++ = c; size--; } retval++; }
+        char nbuf[MAXNBUF];
+        const char *p, *percent;
+        int ch, n;
+        uintmax_t num;
+        int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
+        int cflag, hflag, jflag, tflag, zflag;
+        int dwidth, upper;
+        char padc;
+        int stop = 0, retval = 0;
+
+        num = 0;
+
+        if (fmt == NULL)
+                fmt = "(fmt null)\n";
+
+        for (;;) {
+                padc = ' ';
+                width = 0;
+                while ((ch = (u_char)*fmt++) != '%' || stop) {
+                        if (ch == '\0') {
+                                if (size >= 1)
+                                        *str++ = '\0';
+                                return (retval);
+                        }
+                        PCHAR(ch);
                 }
-            }
-            c = (unsigned char) va_arg(args, int);
-            if (str <= end)
-                *str = c;
-            ++str;
-            while (--field_width > 0) {
-                if (str <= end)
-                    *str = ' ';
-                ++str;
-            }
-            continue;
-
-        case 's':
-            s = va_arg(args, char *);
-            if (!s)
-                s = "<NULL>";
-
-            len = strnlen(s, precision);
-
-            if (!(flags & LEFT)) {
-                while (len < field_width--) {
-                    if (str <= end)
-                        *str = ' ';
-                    ++str;
+                percent = fmt - 1;
+                qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
+                sign = 0; dot = 0; dwidth = 0; upper = 0;
+                cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
+reswitch:       switch (ch = (u_char)*fmt++) {
+                case '.':
+                        dot = 1;
+                        goto reswitch;
+                case '#':
+                        sharpflag = 1;
+                        goto reswitch;
+                case '+':
+                        sign = 1;
+                        goto reswitch;
+                case '-':
+                        ladjust = 1;
+                        goto reswitch;
+                case '%':
+                        PCHAR(ch);
+                        break;
+                case '*':
+                        if (!dot) {
+                                width = va_arg(ap, int);
+                                if (width < 0) {
+                                        ladjust = !ladjust;
+                                        width = -width;
+                                }
+                        } else {
+                                dwidth = va_arg(ap, int);
+                        }
+                        goto reswitch;
+                case '0':
+                        if (!dot) {
+                                padc = '0';
+                                goto reswitch;
+                        }
+                case '1': case '2': case '3': case '4':
+                case '5': case '6': case '7': case '8': case '9':
+                                for (n = 0;; ++fmt) {
+                                        n = n * 10 + ch - '0';
+                                        ch = *fmt;
+                                        if (ch < '0' || ch > '9')
+                                                break;
+                                }
+                        if (dot)
+                                dwidth = n;
+                        else
+                                width = n;
+                        goto reswitch;
+                case 'c':
+                        PCHAR(va_arg(ap, int));
+                        break;
+                case 'd':
+                case 'i':
+                        base = 10;
+                        sign = 1;
+                        goto handle_sign;
+                case 'h':
+                        if (hflag) {
+                                hflag = 0;
+                                cflag = 1;
+                        } else
+                                hflag = 1;
+                        goto reswitch;
+                case 'j':
+                        jflag = 1;
+                        goto reswitch;
+                case 'l':
+                        if (lflag) {
+                                lflag = 0;
+                                qflag = 1;
+                        } else
+                                lflag = 1;
+                        goto reswitch;
+                case 'n':
+                        if (jflag)
+                                *(va_arg(ap, intmax_t *)) = retval;
+                        else if (qflag)
+                                *(va_arg(ap, int64_t *)) = retval;
+                        else if (lflag)
+                                *(va_arg(ap, long *)) = retval;
+                        else if (zflag)
+                                *(va_arg(ap, size_t *)) = retval;
+                        else if (hflag)
+                                *(va_arg(ap, short *)) = retval;
+                        else if (cflag)
+                                *(va_arg(ap, char *)) = retval;
+                        else
+                                *(va_arg(ap, int *)) = retval;
+                        break;
+                case 'o':
+                        base = 8;
+                        goto handle_nosign;
+                case 'p':
+                        base = 16;
+                        sharpflag = (width == 0);
+                        sign = 0;
+                        num = (uintptr_t)va_arg(ap, void *);
+                        goto number;
+                case 'q':
+                        qflag = 1;
+                        goto reswitch;
+                case 'r':
+                        base = 10;
+                        if (sign)
+                                goto handle_sign;
+                        goto handle_nosign;
+                case 's':
+                        p = va_arg(ap, char *);
+                        if (p == NULL)
+                                p = "(null)";
+                        if (!dot)
+                                n = strlen (p);
+                        else
+                                for (n = 0; n < dwidth && p[n]; n++)
+                                        continue;
+
+                        width -= n;
+
+                        if (!ladjust && width > 0)
+                                while (width--)
+                                        PCHAR(padc);
+                        while (n--)
+                                PCHAR(*p++);
+                        if (ladjust && width > 0)
+                                while (width--)
+                                        PCHAR(padc);
+                        break;
+                case 't':
+                        tflag = 1;
+                        goto reswitch;
+                case 'u':
+                        base = 10;
+                        goto handle_nosign;
+                case 'X':
+                        upper = 1;
+                case 'x':
+                        base = 16;
+                        goto handle_nosign;
+                case 'y':
+                        base = 16;
+                        sign = 1;
+                        goto handle_sign;
+                case 'z':
+                        zflag = 1;
+                        goto reswitch;
+handle_nosign:
+                        sign = 0;
+                        if (jflag)
+                                num = va_arg(ap, uintmax_t);
+                        else if (qflag)
+                                num = va_arg(ap, uint64_t);
+                        else if (tflag)
+                                num = va_arg(ap, ptrdiff_t);
+                        else if (lflag)
+                                num = va_arg(ap, u_long);
+                        else if (zflag)
+                                num = va_arg(ap, size_t);
+                        else if (hflag)
+                                num = (unsigned short)va_arg(ap, int);
+                        else if (cflag)
+                                num = (u_char)va_arg(ap, int);
+                        else
+                                num = va_arg(ap, u_int);
+                        goto number;
+handle_sign:
+                        if (jflag)
+                                num = va_arg(ap, intmax_t);
+                        else if (qflag)
+                                num = va_arg(ap, int64_t);
+                        else if (tflag)
+                                num = va_arg(ap, ptrdiff_t);
+                        else if (lflag)
+                                num = va_arg(ap, long);
+                        else if (zflag)
+                                num = va_arg(ap, ssize_t);
+                        else if (hflag)
+                                num = (short)va_arg(ap, int);
+                        else if (cflag)
+                                num = (char)va_arg(ap, int);
+                        else
+                                num = va_arg(ap, int);
+number:
+                        if (sign && (intmax_t)num < 0) {
+                                neg = 1;
+                                num = -(intmax_t)num;
+                        }
+                        p = ksprintn(nbuf, num, base, &n, upper);
+                        tmp = 0;
+                        if (sharpflag && num != 0) {
+                                if (base == 8)
+                                        tmp++;
+                                else if (base == 16)
+                                        tmp += 2;
+                        }
+                        if (neg)
+                                tmp++;
+
+                        if (!ladjust && padc == '0')
+                                dwidth = width - tmp;
+                        width -= tmp + (dwidth > n ? dwidth : n);
+                        dwidth -= n;
+                        if (!ladjust)
+                                while (width-- > 0)
+                                        PCHAR(' ');
+                        if (neg)
+                                PCHAR('-');
+                        if (sharpflag && num != 0) {
+                                if (base == 8) {
+                                        PCHAR('0');
+                                } else if (base == 16) {
+                                        PCHAR('0');
+                                        PCHAR('x');
+                                }
+                        }
+                        while (dwidth-- > 0)
+                                PCHAR('0');
+
+                        while (*p)
+                                PCHAR(*p--);
+
+                        if (ladjust)
+                                while (width-- > 0)
+                                        PCHAR(' ');
+
+                        break;
+                default:
+                        while (percent < fmt)
+                                PCHAR(*percent++);
+                        /*
+                         * Since we ignore a formatting argument it is no
+                         * longer safe to obey the remaining formatting
+                         * arguments as the arguments will no longer match
+                         * the format specs.
+                         */
+                        stop = 1;
+                        break;
                 }
-            }
-            for (i = 0; i < len; ++i) {
-                if (str <= end)
-                    *str = *s;
-                ++str; ++s;
-            }
-            while (len < field_width--) {
-                if (str <= end)
-                    *str = ' ';
-                ++str;
-            }
-            continue;
-
-        case 'p':
-            if (field_width == -1) {
-                field_width = 2*sizeof(void *);
-                flags |= ZEROPAD;
-            }
-            str = number(str, end,
-                         (unsigned long) va_arg(args, void *),
-                         16, field_width, precision, flags);
-            continue;
-
-
-        case 'n':
-            if (qualifier == 'l') {
-                long * ip = va_arg(args, long *);
-                *ip = (str - buf);
-            } else if (qualifier == 'Z') {
-                size_t * ip = va_arg(args, size_t *);
-                *ip = (str - buf);
-            } else {
-                int * ip = va_arg(args, int *);
-                *ip = (str - buf);
-            }
-            continue;
-
-        case '%':
-            if (str <= end)
-                *str = '%';
-            ++str;
-            continue;
-
-            /* integer number formats - set up the flags and "break" */
-        case 'o':
-            base = 8;
-            break;
-
-        case 'X':
-            flags |= LARGE;
-        case 'x':
-            base = 16;
-            break;
-
-        case 'd':
-        case 'i':
-            flags |= SIGN;
-        case 'u':
-            break;
-
-        default:
-            if (str <= end)
-                *str = '%';
-            ++str;
-            if (*fmt) {
-                if (str <= end)
-                    *str = *fmt;
-                ++str;
-            } else {
-                --fmt;
-            }
-            continue;
         }
-        if (qualifier == 'L')
-            num = va_arg(args, long long);
-        else if (qualifier == 'l') {
-            num = va_arg(args, unsigned long);
-            if (flags & SIGN)
-                num = (signed long) num;
-        } else if (qualifier == 'Z') {
-            num = va_arg(args, size_t);
-        } else if (qualifier == 'h') {
-            num = (unsigned short) va_arg(args, int);
-            if (flags & SIGN)
-                num = (signed short) num;
-        } else {
-            num = va_arg(args, unsigned int);
-            if (flags & SIGN)
-                num = (signed int) num;
-        }
-
-        str = number(str, end, num, base,
-                     field_width, precision, flags);
-    }
-    if (str <= end)
-        *str = '\0';
-    else if (size > 0)
-        /* don't write out a null byte if the buf size is zero */
-        *end = '\0';
-    /* the trailing null byte doesn't count towards the total
-     * ++str;
-     */
-    return str-buf;
+#undef PCHAR
 }
 
 /**
@@ -552,220 +635,587 @@ int sprintf(char * buf, const char *fmt, ...)
     return i;
 }
 
+/*
+ * Fill in the given table from the scanset at the given format
+ * (just after `[').  Return a pointer to the character past the
+ * closing `]'.  The table has a 1 wherever characters should be
+ * considered part of the scanset.
+ */
+static const u_char *
+__sccl(char *tab, const u_char *fmt)
+{
+        int c, n, v;
+
+        /* first `clear' the whole table */
+        c = *fmt++;             /* first char hat => negated scanset */
+        if (c == '^') {
+                v = 1;          /* default => accept */
+                c = *fmt++;     /* get new first char */
+        } else
+                v = 0;          /* default => reject */
+
+        /* XXX: Will not work if sizeof(tab*) > sizeof(char) */
+        for (n = 0; n < 256; n++)
+                     tab[n] = v;        /* memset(tab, v, 256) */
+
+        if (c == 0)
+                return (fmt - 1);/* format ended before closing ] */
+
+        /*
+         * Now set the entries corresponding to the actual scanset
+         * to the opposite of the above.
+         *
+         * The first character may be ']' (or '-') without being special;
+         * the last character may be '-'.
+         */
+        v = 1 - v;
+        for (;;) {
+                tab[c] = v;             /* take character c */
+doswitch:
+                n = *fmt++;             /* and examine the next */
+                switch (n) {
+
+                case 0:                 /* format ended too soon */
+                        return (fmt - 1);
+
+                case '-':
+                        /*
+                         * A scanset of the form
+                         *      [01+-]
+                         * is defined as `the digit 0, the digit 1,
+                         * the character +, the character -', but
+                         * the effect of a scanset such as
+                         *      [a-zA-Z0-9]
+                         * is implementation defined.  The V7 Unix
+                         * scanf treats `a-z' as `the letters a through
+                         * z', but treats `a-a' as `the letter a, the
+                         * character -, and the letter a'.
+                         *
+                         * For compatibility, the `-' is not considerd
+                         * to define a range if the character following
+                         * it is either a close bracket (required by ANSI)
+                         * or is not numerically greater than the character
+                         * we just stored in the table (c).
+                         */
+                        n = *fmt;
+                        if (n == ']' || n < c) {
+                                c = '-';
+                                break;  /* resume the for(;;) */
+                        }
+                        fmt++;
+                        /* fill in the range */
+                        do {
+                            tab[++c] = v;
+                        } while (c < n);
+                        c = n;
+                        /*
+                         * Alas, the V7 Unix scanf also treats formats
+                         * such as [a-c-e] as `the letters a through e'.
+                         * This too is permitted by the standard....
+                         */
+                        goto doswitch;
+                        break;
+
+                case ']':               /* end of scanset */
+                        return (fmt);
+
+                default:                /* just another character */
+                        c = n;
+                        break;
+                }
+        }
+        /* NOTREACHED */
+}
+
 /**
  * vsscanf - Unformat a buffer into a list of arguments
  * @buf:	input buffer
  * @fmt:	format of buffer
  * @args:	arguments
  */
-int vsscanf(const char * buf, const char * fmt, va_list args)
+#define BUF             32      /* Maximum length of numeric string. */
+
+/*
+ * Flags used during conversion.
+ */
+#define LONG            0x01    /* l: long or double */
+#define SHORT           0x04    /* h: short */
+#define SUPPRESS        0x08    /* suppress assignment */
+#define POINTER         0x10    /* weird %p pointer (`fake hex') */
+#define NOSKIP          0x20    /* do not skip blanks */
+#define QUAD            0x400
+#define SHORTSHORT      0x4000  /** hh: char */
+
+/*
+ * The following are used in numeric conversions only:
+ * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
+ * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
+ */
+#define SIGNOK          0x40    /* +/- is (still) legal */
+#define NDIGITS         0x80    /* no digits detected */
+
+#define DPTOK           0x100   /* (float) decimal point is still legal */
+#define EXPOK           0x200   /* (float) exponent (e+3, etc) still legal */
+
+#define PFXOK           0x100   /* 0x prefix is (still) legal */
+#define NZDIGITS        0x200   /* no zero digits detected */
+
+/*
+ * Conversion types.
+ */
+#define CT_CHAR         0       /* %c conversion */
+#define CT_CCL          1       /* %[...] conversion */
+#define CT_STRING       2       /* %s conversion */
+#define CT_INT          3       /* integer, i.e., strtoq or strtouq */
+typedef uint64_t (*ccfntype)(const char *, char **, int);
+
+int
+vsscanf(const char *inp, char const *fmt0, va_list ap)
 {
-	const char *str = buf;
-	char *next;
-	char digit;
-	int num = 0;
-	int qualifier;
-	int base;
-	int field_width;
-	int is_sign = 0;
+        int inr;
+        const u_char *fmt = (const u_char *)fmt0;
+        int c;                  /* character from format, or conversion */
+        size_t width;           /* field width, or 0 */
+        char *p;                /* points into all kinds of strings */
+        int n;                  /* handy integer */
+        int flags;              /* flags as defined above */
+        char *p0;               /* saves original value of p when necessary */
+        int nassigned;          /* number of fields assigned */
+        int nconversions;       /* number of conversions */
+        int nread;              /* number of characters consumed from fp */
+        int base;               /* base argument to strtoq/strtouq */
+        ccfntype ccfn;          /* conversion function (strtoq/strtouq) */
+        char ccltab[256];       /* character class table for %[...] */
+        char buf[BUF];          /* buffer for numeric conversions */
 
-	while(*fmt && *str) {
-		/* skip any white space in format */
-		/* white space in format matchs any amount of
-		 * white space, including none, in the input.
-		 */
-		if (isspace(*fmt)) {
-			while (isspace(*fmt))
-				++fmt;
-			while (isspace(*str))
-				++str;
-		}
+        /* `basefix' is used to avoid `if' tests in the integer scanner */
+        static short basefix[17] =
+                { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
 
-		/* anything that is not a conversion must match exactly */
-		if (*fmt != '%' && *fmt) {
-			if (*fmt++ != *str++)
-				break;
-			continue;
-		}
+        inr = strlen(inp);
 
-		if (!*fmt)
-			break;
-		++fmt;
-		
-		/* skip this conversion.
-		 * advance both strings to next white space
-		 */
-		if (*fmt == '*') {
-			while (!isspace(*fmt) && *fmt)
-				fmt++;
-			while (!isspace(*str) && *str)
-				str++;
-			continue;
-		}
+        nassigned = 0;
+        nconversions = 0;
+        nread = 0;
+        base = 0;               /* XXX just to keep gcc happy */
+        ccfn = NULL;            /* XXX just to keep gcc happy */
+        for (;;) {
+                c = *fmt++;
+                if (c == 0)
+                        return (nassigned);
+                if (isspace(c)) {
+                        while (inr > 0 && isspace(*inp))
+                                nread++, inr--, inp++;
+                        continue;
+                }
+                if (c != '%')
+                        goto literal;
+                width = 0;
+                flags = 0;
+                /*
+                 * switch on the format.  continue if done;
+                 * break once format type is derived.
+                 */
+again:          c = *fmt++;
+                switch (c) {
+                case '%':
+literal:
+                        if (inr <= 0)
+                                goto input_failure;
+                        if (*inp != c)
+                                goto match_failure;
+                        inr--, inp++;
+                        nread++;
+                        continue;
 
-		/* get field width */
-		field_width = -1;
-		if (isdigit(*fmt))
-			field_width = skip_atoi(&fmt);
+                case '*':
+                        flags |= SUPPRESS;
+                        goto again;
+                case 'l':
+                        if (flags & LONG){
+                                flags &= ~LONG;
+                                flags |= QUAD;
+                        } else {
+                                flags |= LONG;
+                        }
+                        goto again;
+                case 'q':
+                        flags |= QUAD;
+                        goto again;
+                case 'h':
+                        if (flags & SHORT){
+                                flags &= ~SHORT;
+                                flags |= SHORTSHORT;
+                        } else {
+                                flags |= SHORT;
+                        }
+                        goto again;
 
-		/* get conversion qualifier */
-		qualifier = -1;
-		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
-		    *fmt == 'Z' || *fmt == 'z') {
-			qualifier = *fmt++;
-			if (unlikely(qualifier == *fmt)) {
-				if (qualifier == 'h') {
-					qualifier = 'H';
-					fmt++;
-				} else if (qualifier == 'l') {
-					qualifier = 'L';
-					fmt++;
-				}
-			}
-		}
-		base = 10;
-		is_sign = 0;
+                case '0': case '1': case '2': case '3': case '4':
+                case '5': case '6': case '7': case '8': case '9':
+                        width = width * 10 + c - '0';
+                        goto again;
 
-		if (!*fmt || !*str)
-			break;
+                /*
+                 * Conversions.
+                 *
+                 */
+                case 'd':
+                        c = CT_INT;
+                        ccfn = (ccfntype)strtoq;
+                        base = 10;
+                        break;
 
-		switch(*fmt++) {
-		case 'c':
-		{
-			char *s = (char *) va_arg(args,char*);
-			if (field_width == -1)
-				field_width = 1;
-			do {
-				*s++ = *str++;
-			} while (--field_width > 0 && *str);
-			num++;
-		}
-		continue;
-		case 's':
-		{
-			char *s = (char *) va_arg(args, char *);
-			if(field_width == -1)
-				field_width = INT_MAX;
-			/* first, skip leading white space in buffer */
-			while (isspace(*str))
-				str++;
-
-			/* now copy until next white space */
-			while (*str && !isspace(*str) && field_width--) {
-				*s++ = *str++;
-			}
-			*s = '\0';
-			num++;
-		}
-		continue;
-		case 'n':
-			/* return number of characters read so far */
-		{
-			int *i = (int *)va_arg(args,int*);
-			*i = str - buf;
-		}
-		continue;
-		case 'o':
-			base = 8;
-			break;
-		case 'x':
-		case 'X':
-			base = 16;
-			break;
-		case 'i':
+                case 'i':
+                        c = CT_INT;
+                        ccfn = (ccfntype)strtoq;
                         base = 0;
-		case 'd':
-			is_sign = 1;
-		case 'u':
-			break;
-		case '%':
-			/* looking for '%' in str */
-			if (*str++ != '%') 
-				return num;
-			continue;
-		default:
-			/* invalid format; stop here */
-			return num;
-		}
-
-		/* have some sort of integer conversion.
-		 * first, skip white space in buffer.
-		 */
-		while (isspace(*str))
-			str++;
-
-		digit = *str;
-		if (is_sign && digit == '-')
-			digit = *(str + 1);
-
-		if (!digit
-                    || (base == 16 && !isxdigit(digit))
-                    || (base == 10 && !isdigit(digit))
-                    || (base == 8 && (!isdigit(digit) || digit > '7'))
-                    || (base == 0 && !isdigit(digit)))
-				break;
-
-		switch(qualifier) {
-		case 'H':	/* that's 'hh' in format */
-			if (is_sign) {
-				signed char *s = (signed char *) va_arg(args,signed char *);
-				*s = (signed char) simple_strtol(str,&next,base);
-			} else {
-				unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
-				*s = (unsigned char) simple_strtoul(str, &next, base);
-			}
-			break;
-		case 'h':
-			if (is_sign) {
-				short *s = (short *) va_arg(args,short *);
-				*s = (short) simple_strtol(str,&next,base);
-			} else {
-				unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
-				*s = (unsigned short) simple_strtoul(str, &next, base);
-			}
-			break;
-		case 'l':
-			if (is_sign) {
-				long *l = (long *) va_arg(args,long *);
-				*l = simple_strtol(str,&next,base);
-			} else {
-				unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
-				*l = simple_strtoul(str,&next,base);
-			}
-			break;
-		case 'L':
-			if (is_sign) {
-				long long *l = (long long*) va_arg(args,long long *);
-				*l = simple_strtoll(str,&next,base);
-			} else {
-				unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
-				*l = simple_strtoull(str,&next,base);
-			}
-			break;
-		case 'Z':
-		case 'z':
-		{
-			size_t *s = (size_t*) va_arg(args,size_t*);
-			*s = (size_t) simple_strtoul(str,&next,base);
-		}
-		break;
-		default:
-			if (is_sign) {
-				int *i = (int *) va_arg(args, int*);
-				*i = (int) simple_strtol(str,&next,base);
-			} else {
-				unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
-				*i = (unsigned int) simple_strtoul(str,&next,base);
-			}
-			break;
-		}
-		num++;
-
-		if (!next)
-			break;
-		str = next;
-	}
-	return num;
+                        break;
+
+                case 'o':
+                        c = CT_INT;
+                        ccfn = strtouq;
+                        base = 8;
+                        break;
+
+                case 'u':
+                        c = CT_INT;
+                        ccfn = strtouq;
+                        base = 10;
+                        break;
+
+                case 'x':
+                        flags |= PFXOK; /* enable 0x prefixing */
+                        c = CT_INT;
+                        ccfn = strtouq;
+                        base = 16;
+                        break;
+
+                case 's':
+                        c = CT_STRING;
+                        break;
+
+                case '[':
+                        fmt = __sccl(ccltab, fmt);
+                        flags |= NOSKIP;
+                        c = CT_CCL;
+                        break;
+
+                case 'c':
+                        flags |= NOSKIP;
+                        c = CT_CHAR;
+                        break;
+
+                case 'p':       /* pointer format is like hex */
+                        flags |= POINTER | PFXOK;
+                        c = CT_INT;
+                        ccfn = strtouq;
+                        base = 16;
+                        break;
+
+                case 'n':
+                        nconversions++;
+                        if (flags & SUPPRESS)   /* ??? */
+                                continue;
+                        if (flags & SHORTSHORT)
+                                *va_arg(ap, char *) = nread;
+                        else if (flags & SHORT)
+                                *va_arg(ap, short *) = nread;
+                        else if (flags & LONG)
+                                *va_arg(ap, long *) = nread;
+                        else if (flags & QUAD)
+                                *va_arg(ap, int64_t *) = nread;
+                        else
+                                *va_arg(ap, int *) = nread;
+                        continue;
+                }
+
+                /*
+                 * We have a conversion that requires input.
+                 */
+                if (inr <= 0)
+                        goto input_failure;
+
+                /*
+                 * Consume leading white space, except for formats
+                 * that suppress this.
+                 */
+                if ((flags & NOSKIP) == 0) {
+                        while (isspace(*inp)) {
+                                nread++;
+                                if (--inr > 0)
+                                        inp++;
+                                else
+                                        goto input_failure;
+                        }
+                        /*
+                         * Note that there is at least one character in
+                         * the buffer, so conversions that do not set NOSKIP
+                         * can no longer result in an input failure.
+                         */
+                }
+
+                /*
+                 * Do the conversion.
+                 */
+                switch (c) {
+
+                case CT_CHAR:
+                        /* scan arbitrary characters (sets NOSKIP) */
+                        if (width == 0)
+                                width = 1;
+                        if (flags & SUPPRESS) {
+                                size_t sum = 0;
+                                for (;;) {
+                                        if ((n = inr) < width) {
+                                                sum += n;
+                                                width -= n;
+                                                inp += n;
+                                                if (sum == 0)
+                                                        goto input_failure;
+                                                break;
+                                        } else {
+                                                sum += width;
+                                                inr -= width;
+                                                inp += width;
+                                                break;
+                                        }
+                                }
+                                nread += sum;
+                        } else {
+                                memcpy(va_arg(ap, char *), inp, width);
+                                inr -= width;
+                                inp += width;
+                                nread += width;
+                                nassigned++;
+                        }
+                        nconversions++;
+                        break;
+
+                case CT_CCL:
+                        /* scan a (nonempty) character class (sets NOSKIP) */
+                        if (width == 0)
+                                width = (size_t)~0;     /* `infinity' */
+                        /* take only those things in the class */
+                        if (flags & SUPPRESS) {
+                                n = 0;
+                                while (ccltab[(unsigned char)*inp]) {
+                                        n++, inr--, inp++;
+                                        if (--width == 0)
+                                                break;
+                                        if (inr <= 0) {
+                                                if (n == 0)
+                                                        goto input_failure;
+                                                break;
+                                        }
+                                }
+                                if (n == 0)
+                                        goto match_failure;
+                        } else {
+                                p0 = p = va_arg(ap, char *);
+                                while (ccltab[(unsigned char)*inp]) {
+                                        inr--;
+                                        *p++ = *inp++;
+                                        if (--width == 0)
+                                                break;
+                                        if (inr <= 0) {
+                                                if (p == p0)
+                                                        goto input_failure;
+                                                break;
+                                        }
+                                }
+                                n = p - p0;
+                                if (n == 0)
+                                        goto match_failure;
+                                *p = 0;
+                                nassigned++;
+                        }
+                        nread += n;
+                        nconversions++;
+                        break;
+
+                case CT_STRING:
+                        /* like CCL, but zero-length string OK, & no NOSKIP */
+                        if (width == 0)
+                                width = (size_t)~0;
+                        if (flags & SUPPRESS) {
+                                n = 0;
+                                while (!isspace(*inp)) {
+                                        n++, inr--, inp++;
+                                        if (--width == 0)
+                                                break;
+                                        if (inr <= 0)
+                                                break;
+                                }
+                                nread += n;
+                        } else {
+                                p0 = p = va_arg(ap, char *);
+                                while (!isspace(*inp)) {
+                                        inr--;
+                                        *p++ = *inp++;
+                                        if (--width == 0)
+                                                break;
+                                        if (inr <= 0)
+                                                break;
+                                }
+                                *p = 0;
+                                nread += p - p0;
+                                nassigned++;
+                        }
+                        nconversions++;
+                        continue;
+
+                case CT_INT:
+                        /* scan an integer as if by strtoq/strtouq */
+#ifdef hardway
+                        if (width == 0 || width > sizeof(buf) - 1)
+                                width = sizeof(buf) - 1;
+#else
+                        /* size_t is unsigned, hence this optimisation */
+                        if (--width > sizeof(buf) - 2)
+                                width = sizeof(buf) - 2;
+                        width++;
+#endif
+                        flags |= SIGNOK | NDIGITS | NZDIGITS;
+                        for (p = buf; width; width--) {
+                                c = *inp;
+                                /*
+                                 * Switch on the character; `goto ok'
+                                 * if we accept it as a part of number.
+                                 */
+                                switch (c) {
+
+                                /*
+                                 * The digit 0 is always legal, but is
+                                 * special.  For %i conversions, if no
+                                 * digits (zero or nonzero) have been
+                                 * scanned (only signs), we will have
+                                 * base==0.  In that case, we should set
+                                 * it to 8 and enable 0x prefixing.
+                                 * Also, if we have not scanned zero digits
+                                 * before this, do not turn off prefixing
+                                 * (someone else will turn it off if we
+                                 * have scanned any nonzero digits).
+                                 */
+                                case '0':
+                                        if (base == 0) {
+                                                base = 8;
+                                                flags |= PFXOK;
+                                        }
+                                        if (flags & NZDIGITS)
+                                            flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
+                                        else
+                                            flags &= ~(SIGNOK|PFXOK|NDIGITS);
+                                        goto ok;
+
+                                /* 1 through 7 always legal */
+                                case '1': case '2': case '3':
+                                case '4': case '5': case '6': case '7':
+                                        base = basefix[base];
+                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
+                                        goto ok;
+
+                                /* digits 8 and 9 ok iff decimal or hex */
+                                case '8': case '9':
+                                        base = basefix[base];
+                                        if (base <= 8)
+                                                break;  /* not legal here */
+                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
+                                        goto ok;
+
+                                /* letters ok iff hex */
+                                case 'A': case 'B': case 'C':
+                                case 'D': case 'E': case 'F':
+                                case 'a': case 'b': case 'c':
+                                case 'd': case 'e': case 'f':
+                                        /* no need to fix base here */
+                                        if (base <= 10)
+                                                break;  /* not legal here */
+                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
+                                        goto ok;
+
+                                /* sign ok only as first character */
+                                case '+': case '-':
+                                        if (flags & SIGNOK) {
+                                                flags &= ~SIGNOK;
+                                                goto ok;
+                                        }
+                                        break;
+
+                                /* x ok iff flag still set & 2nd char */
+                                case 'x': case 'X':
+                                        if (flags & PFXOK && p == buf + 1) {
+                                                base = 16;      /* if %i */
+                                                flags &= ~PFXOK;
+                                                goto ok;
+                                        }
+                                        break;
+                                }
+
+                                /*
+                                 * If we got here, c is not a legal character
+                                 * for a number.  Stop accumulating digits.
+                                 */
+                                break;
+                ok:
+                                /*
+                                 * c is legal: store it and look at the next.
+                                 */
+                                *p++ = c;
+                                if (--inr > 0)
+                                        inp++;
+                                else 
+                                        break;          /* end of input */
+                        }
+                        /*
+                         * If we had only a sign, it is no good; push
+                         * back the sign.  If the number ends in `x',
+                         * it was [sign] '' 'x', so push back the x
+                         * and treat it as [sign] ''.
+                         */
+                        if (flags & NDIGITS) {
+                                if (p > buf) {
+                                        inp--;
+                                        inr++;
+                                }
+                                goto match_failure;
+                        }
+                        c = ((u_char *)p)[-1];
+                        if (c == 'x' || c == 'X') {
+                                --p;
+                                inp--;
+                                inr++;
+                        }
+                        if ((flags & SUPPRESS) == 0) {
+                                uint64_t res;
+
+                                *p = 0;
+                                res = (*ccfn)(buf, (char **)NULL, base);
+                                if (flags & POINTER)
+                                        *va_arg(ap, void **) =
+                                                (void *)(uintptr_t)res;
+                                else if (flags & SHORTSHORT)
+                                        *va_arg(ap, char *) = res;
+                                else if (flags & SHORT)
+                                        *va_arg(ap, short *) = res;
+                                else if (flags & LONG)
+                                        *va_arg(ap, long *) = res;
+                                else if (flags & QUAD)
+                                        *va_arg(ap, int64_t *) = res;
+                                else
+                                        *va_arg(ap, int *) = res;
+                                nassigned++;
+                        }
+                        nread += p - buf;
+                        nconversions++;
+                        break;
+
+                }
+        }
+input_failure:
+        return (nconversions != 0 ? nassigned : -1);
+match_failure:
+        return (nassigned);
 }
 
 /**
diff --git a/tpmback.c b/tpmback.c
index 00b66e8..22adbd3 100644
--- a/tpmback.c
+++ b/tpmback.c
@@ -52,10 +52,6 @@
 #include <mini-os/wait.h>
 
 
-#ifndef HAVE_LIBC
-#define strtoul simple_strtoul
-#endif
-
 //#define TPMBACK_PRINT_DEBUG
 #ifdef TPMBACK_PRINT_DEBUG
 #define TPMBACK_DEBUG(fmt,...) printk("Tpmback:Debug("__FILE__":%d) " fmt, __LINE__, ##__VA_ARGS__)
-- 
2.6.6


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] mini-os: replace lib/printf.c with a version not under GPL
  2016-07-04  9:16 [PATCH v2] mini-os: replace lib/printf.c with a version not under GPL Juergen Gross
@ 2016-07-12  8:48 ` Samuel Thibault
  2016-07-12  9:19   ` [Minios-devel] " Wei Liu
  0 siblings, 1 reply; 4+ messages in thread
From: Samuel Thibault @ 2016-07-12  8:48 UTC (permalink / raw)
  To: Juergen Gross, wei.liu2; +Cc: minios-devel, xen-devel, andrew.cooper3

Juergen Gross, on Mon 04 Jul 2016 11:16:59 +0200, wrote:
> Instead of a Linux kernel based implementation use one from freeBSD.
> 
> As a result some of the printings will change due to more posix like
> behavior of %p format (omitting leading zeroes, prepending "0x").
> 
> Signed-off-by: Juergen Gross <jgross@suse.com>

Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

> ---
> V2: remove include/lib-gpl.h as requested by Samuel Thibault
> ---
>  blkfront.c        |    4 -
>  include/lib-gpl.h |   59 --
>  include/lib.h     |   27 +-
>  lib/printf.c      | 1744 +++++++++++++++++++++++++++++++++--------------------
>  tpmback.c         |    4 -
>  5 files changed, 1119 insertions(+), 719 deletions(-)
>  delete mode 100644 include/lib-gpl.h
> 
> diff --git a/blkfront.c b/blkfront.c
> index bdb7765..f747216 100644
> --- a/blkfront.c
> +++ b/blkfront.c
> @@ -17,10 +17,6 @@
>  #include <mini-os/lib.h>
>  #include <fcntl.h>
>  
> -#ifndef HAVE_LIBC
> -#define strtoul simple_strtoul
> -#endif
> -
>  /* Note: we generally don't need to disable IRQs since we hardly do anything in
>   * the interrupt handler.  */
>  
> diff --git a/include/lib-gpl.h b/include/lib-gpl.h
> deleted file mode 100644
> index d5602b2..0000000
> --- a/include/lib-gpl.h
> +++ /dev/null
> @@ -1,59 +0,0 @@
> -/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
> - ****************************************************************************
> - * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
> - ****************************************************************************
> - *
> - *        File: lib.h
> - *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
> - *     Changes: 
> - *              
> - *        Date: Aug 2003
> - * 
> - * Environment: Xen Minimal OS
> - * Description: Random useful library functions, from Linux'
> - * include/linux/kernel.h
> - *
> - *  This program is free software; you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation; either version 2 of the License, or
> - *  (at your option) any later version.
> - *
> - *  This program is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - *  GNU General Public License for more details.
> - *
> - *  You should have received a copy of the GNU General Public License
> - *  along with this program; if not, write to the Free Software
> - *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> - */
> -
> -#ifndef _LIB_GPL_H_
> -#define _LIB_GPL_H_
> -
> -#ifndef HAVE_LIBC
> -/* printing */
> -extern unsigned long simple_strtoul(const char *,char **,unsigned int);
> -extern long simple_strtol(const char *,char **,unsigned int);
> -extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
> -extern long long simple_strtoll(const char *,char **,unsigned int);
> -
> -extern int sprintf(char * buf, const char * fmt, ...)
> -	__attribute__ ((format (printf, 2, 3)));
> -extern int vsprintf(char *buf, const char *, va_list)
> -	__attribute__ ((format (printf, 2, 0)));
> -extern int snprintf(char * buf, size_t size, const char * fmt, ...)
> -	__attribute__ ((format (printf, 3, 4)));
> -extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
> -	__attribute__ ((format (printf, 3, 0)));
> -extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
> -	__attribute__ ((format (printf, 3, 4)));
> -extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
> -	__attribute__ ((format (printf, 3, 0)));
> -extern int sscanf(const char *, const char *, ...)
> -	__attribute__ ((format (scanf, 2, 3)));
> -extern int vsscanf(const char *, const char *, va_list)
> -	__attribute__ ((format (scanf, 2, 0)));
> -#endif
> -
> -#endif /* _LIB_GPL_H_ */
> diff --git a/include/lib.h b/include/lib.h
> index 62836c7..39d6a18 100644
> --- a/include/lib.h
> +++ b/include/lib.h
> @@ -66,11 +66,6 @@
>  #ifdef HAVE_LIBC
>  #include <sys/queue.h>
>  #include <stdio.h>
> -#else
> -#include <lib-gpl.h>
> -#endif
> -
> -#ifdef HAVE_LIBC
>  #include <string.h>
>  #else
>  /* string and memory manipulation */
> @@ -107,6 +102,28 @@ char *strrchr(const char *p, int ch);
>  void	*memcpy(void *to, const void *from, size_t len);
>  
>  size_t strnlen(const char *, size_t);
> +
> +unsigned long strtoul(const char *nptr, char **endptr, int base);
> +int64_t strtoq(const char *nptr, char **endptr, int base);
> +uint64_t strtouq(const char *nptr, char **endptr, int base);
> +
> +extern int sprintf(char * buf, const char * fmt, ...)
> +        __attribute__ ((format (printf, 2, 3)));
> +extern int vsprintf(char *buf, const char *, va_list)
> +        __attribute__ ((format (printf, 2, 0)));
> +extern int snprintf(char * buf, size_t size, const char * fmt, ...)
> +        __attribute__ ((format (printf, 3, 4)));
> +extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
> +        __attribute__ ((format (printf, 3, 0)));
> +extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
> +        __attribute__ ((format (printf, 3, 4)));
> +extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
> +        __attribute__ ((format (printf, 3, 0)));
> +extern int sscanf(const char *, const char *, ...)
> +        __attribute__ ((format (scanf, 2, 3)));
> +extern int vsscanf(const char *, const char *, va_list)
> +        __attribute__ ((format (scanf, 2, 0)));
> +
>  #endif
>  
>  #include <mini-os/console.h>
> diff --git a/lib/printf.c b/lib/printf.c
> index 40f92fc..e48ab61 100644
> --- a/lib/printf.c
> +++ b/lib/printf.c
> @@ -1,50 +1,53 @@
>  /*
>   ****************************************************************************
> - * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
> - ****************************************************************************
>   *
>   *        File: printf.c
> - *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
> - *     Changes: Grzegorz Milos (gm281@cam.ac.uk) 
> + *      Author: Juergen Gross <jgross@suse.com>
>   *
> - *        Date: Aug 2003, Aug 2005
> + *        Date: Jun 2016
>   *
>   * Environment: Xen Minimal OS
>   * Description: Library functions for printing
> - *              (Linux port, mainly lib/vsprintf.c)
> + *              (freeBSD port)
>   *
>   ****************************************************************************
>   */
>  
> -/*
> - * Copyright (C) 1991, 1992  Linus Torvalds
> - */
> -
> -/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
> -/*
> - * Wirzenius wrote this portably, Torvalds fucked it up :-)
> - */
> -
> -/*
> - * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
> - * - changed to provide snprintf and vsnprintf functions
> - * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
> - * - scnprintf and vscnprintf
> +/*-
> + * Copyright (c) 1990, 1993
> + *	The Regents of the University of California.  All rights reserved.
>   *
> + * This code is derived from software contributed to Berkeley by
> + * Chris Torek.
>   *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> + * Copyright (c) 2011 The FreeBSD Foundation
> + * All rights reserved.
> + * Portions of this software were developed by David Chisnall
> + * under sponsorship from the FreeBSD Foundation.
>   *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the University nor the names of its contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
>   *
> - * You should have received a copy of the GNU General Public License
> - * along with this program; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
>   */
>  
>  #if !defined HAVE_LIBC
> @@ -57,449 +60,529 @@
>  #include <mini-os/ctype.h>
>  #include <mini-os/posix/limits.h>
>  
> -/**
> - * simple_strtoul - convert a string to an unsigned long
> - * @cp: The start of the string
> - * @endp: A pointer to the end of the parsed string will be placed here
> - * @base: The number base to use
> +#define __DECONST(type, var)    ((type)(uintptr_t)(const void *)(var))
> +/* 64 bits + 0-Byte at end */
> +#define MAXNBUF	65
> +
> +static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
> +/*
> + * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
> + * order; return an optional length and a pointer to the last character
> + * written in the buffer (i.e., the first character of the string).
> + * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
>   */
> -unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
> +static char *
> +ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
>  {
> -    unsigned long result = 0,value;
> -
> -    if (!base) {
> -        base = 10;
> -        if (*cp == '0') {
> -            base = 8;
> -            cp++;
> -            if ((*cp == 'x') && isxdigit(cp[1])) {
> -                cp++;
> -                base = 16;
> -            }
> -        }
> -    }
> -    while (isxdigit(*cp) &&
> -           (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
> -        result = result*base + value;
> -        cp++;
> -    }
> -    if (endp)
> -        *endp = (char *)cp;
> -    return result;
> -}
> -
> -/**
> - * simple_strtol - convert a string to a signed long
> - * @cp: The start of the string
> - * @endp: A pointer to the end of the parsed string will be placed here
> - * @base: The number base to use
> - */
> -long simple_strtol(const char *cp,char **endp,unsigned int base)
> -{
> -    if(*cp=='-')
> -        return -simple_strtoul(cp+1,endp,base);
> -    return simple_strtoul(cp,endp,base);
> +	char *p, c;
> +
> +	p = nbuf;
> +	*p = '\0';
> +	do {
> +		c = hex2ascii_data[num % base];
> +		*++p = upper ? toupper(c) : c;
> +	} while (num /= base);
> +	if (lenp)
> +		*lenp = p - nbuf;
> +	return (p);
>  }
>  
> -/**
> - * simple_strtoull - convert a string to an unsigned long long
> - * @cp: The start of the string
> - * @endp: A pointer to the end of the parsed string will be placed here
> - * @base: The number base to use
> +/*
> + * Convert a string to an unsigned long integer.
> + *
> + * Ignores `locale' stuff.  Assumes that the upper and lower case
> + * alphabets and digits are each contiguous.
>   */
> -unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
> +unsigned long
> +strtoul(const char *nptr, char **endptr, int base)
>  {
> -    unsigned long long result = 0,value;
> -
> -    if (!base) {
> -        base = 10;
> -        if (*cp == '0') {
> -            base = 8;
> -            cp++;
> -            if ((*cp == 'x') && isxdigit(cp[1])) {
> -                cp++;
> +        const char *s = nptr;
> +        unsigned long acc;
> +        unsigned char c;
> +        unsigned long cutoff;
> +        int neg = 0, any, cutlim;
> +
> +        /*
> +         * See strtol for comments as to the logic used.
> +         */
> +        do {
> +                c = *s++;
> +        } while (isspace(c));
> +        if (c == '-') {
> +                neg = 1;
> +                c = *s++;
> +        } else if (c == '+')
> +                c = *s++;
> +        if ((base == 0 || base == 16) &&
> +            c == '0' && (*s == 'x' || *s == 'X')) {
> +                c = s[1];
> +                s += 2;
>                  base = 16;
> -            }
>          }
> -    }
> -    while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
> -                                                               ? toupper(*cp) : *cp)-'A'+10) < base) {
> -        result = result*base + value;
> -        cp++;
> -    }
> -    if (endp)
> -        *endp = (char *)cp;
> -    return result;
> +        if (base == 0)
> +                base = c == '0' ? 8 : 10;
> +        cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
> +        cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
> +        for (acc = 0, any = 0;; c = *s++) {
> +                if (!isascii(c))
> +                        break;
> +                if (isdigit(c))
> +                        c -= '0';
> +                else if (isalpha(c))
> +                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
> +                else
> +                        break;
> +                if (c >= base)
> +                        break;
> +                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
> +                        any = -1;
> +                else {
> +                        any = 1;
> +                        acc *= base;
> +                        acc += c;
> +                }
> +        }
> +        if (any < 0) {
> +                acc = ULONG_MAX;
> +        } else if (neg)
> +                acc = -acc;
> +        if (endptr != 0)
> +                *endptr = __DECONST(char *, any ? s - 1 : nptr);
> +        return (acc);
>  }
>  
> -/**
> - * simple_strtoll - convert a string to a signed long long
> - * @cp: The start of the string
> - * @endp: A pointer to the end of the parsed string will be placed here
> - * @base: The number base to use
> +/*
> + * Convert a string to a quad integer.
> + *
> + * Ignores `locale' stuff.  Assumes that the upper and lower case
> + * alphabets and digits are each contiguous.
>   */
> -long long simple_strtoll(const char *cp,char **endp,unsigned int base)
> -{
> -    if(*cp=='-')
> -        return -simple_strtoull(cp+1,endp,base);
> -    return simple_strtoull(cp,endp,base);
> -}
> -
> -static int skip_atoi(const char **s)
> -{
> -    int i=0;
> -
> -    while (isdigit(**s))
> -        i = i*10 + *((*s)++) - '0';
> -    return i;
> -}
> -
> -#define ZEROPAD 1               /* pad with zero */
> -#define SIGN    2               /* unsigned/signed long */
> -#define PLUS    4               /* show plus */
> -#define SPACE   8               /* space if plus */
> -#define LEFT    16              /* left justified */
> -#define SPECIAL 32              /* 0x */
> -#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
> -
> -static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
> +int64_t
> +strtoq(const char *nptr, char **endptr, int base)
>  {
> -    char c,sign,tmp[66];
> -    const char *digits;
> -    const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
> -    const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
> -    int i;
> -
> -    digits = (type & LARGE) ? large_digits : small_digits;
> -    if (type & LEFT)
> -        type &= ~ZEROPAD;
> -    if (base < 2 || base > 36)
> -        return buf;
> -    c = (type & ZEROPAD) ? '0' : ' ';
> -    sign = 0;
> -    if (type & SIGN) {
> -        if (num < 0) {
> -            sign = '-';
> -            num = -num;
> -            size--;
> -        } else if (type & PLUS) {
> -            sign = '+';
> -            size--;
> -        } else if (type & SPACE) {
> -            sign = ' ';
> -            size--;
> -        }
> -    }
> -    if (type & SPECIAL) {
> -        if (base == 16)
> -            size -= 2;
> -        else if (base == 8)
> -            size--;
> -    }
> -    i = 0;
> -    if (num == 0)
> -        tmp[i++]='0';
> -    else 
> -    {
> -        /* XXX KAF: force unsigned mod and div. */
> -        unsigned long long num2=(unsigned long long)num;
> -        unsigned int base2=(unsigned int)base;
> -        while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }
> -    }
> -    if (i > precision)
> -        precision = i;
> -    size -= precision;
> -    if (!(type&(ZEROPAD+LEFT))) {
> -        while(size-->0) {
> -            if (buf <= end)
> -                *buf = ' ';
> -            ++buf;
> +        const char *s;
> +        uint64_t acc;
> +        unsigned char c;
> +        uint64_t qbase, cutoff;
> +        int neg, any, cutlim;
> +
> +        /*
> +         * Skip white space and pick up leading +/- sign if any.
> +         * If base is 0, allow 0x for hex and 0 for octal, else
> +         * assume decimal; if base is already 16, allow 0x.
> +         */
> +        s = nptr;
> +        do {
> +                c = *s++;
> +        } while (isspace(c));
> +        if (c == '-') {
> +                neg = 1;
> +                c = *s++;
> +        } else {
> +                neg = 0;
> +                if (c == '+')
> +                        c = *s++;
>          }
> -    }
> -    if (sign) {
> -        if (buf <= end)
> -            *buf = sign;
> -        ++buf;
> -    }
> -    if (type & SPECIAL) {
> -        if (base==8) {
> -            if (buf <= end)
> -                *buf = '0';
> -            ++buf;
> -        } else if (base==16) {
> -            if (buf <= end)
> -                *buf = '0';
> -            ++buf;
> -            if (buf <= end)
> -                *buf = digits[33];
> -            ++buf;
> +        if ((base == 0 || base == 16) &&
> +            c == '0' && (*s == 'x' || *s == 'X')) {
> +                c = s[1];
> +                s += 2;
> +                base = 16;
>          }
> -    }
> -    if (!(type & LEFT)) {
> -        while (size-- > 0) {
> -            if (buf <= end)
> -                *buf = c;
> -            ++buf;
> +        if (base == 0)
> +                base = c == '0' ? 8 : 10;
> +
> +        /*
> +         * Compute the cutoff value between legal numbers and illegal
> +         * numbers.  That is the largest legal value, divided by the
> +         * base.  An input number that is greater than this value, if
> +         * followed by a legal input character, is too big.  One that
> +         * is equal to this value may be valid or not; the limit
> +         * between valid and invalid numbers is then based on the last
> +         * digit.  For instance, if the range for quads is
> +         * [-9223372036854775808..9223372036854775807] and the input base
> +         * is 10, cutoff will be set to 922337203685477580 and cutlim to
> +         * either 7 (neg==0) or 8 (neg==1), meaning that if we have
> +         * accumulated a value > 922337203685477580, or equal but the
> +         * next digit is > 7 (or 8), the number is too big, and we will
> +         * return a range error.
> +         *
> +         * Set any if any `digits' consumed; make it negative to indicate
> +         * overflow.
> +         */
> +        qbase = (unsigned)base;
> +        cutoff = neg ? (uint64_t)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX : LLONG_MAX;
> +        cutlim = cutoff % qbase;
> +        cutoff /= qbase;
> +        for (acc = 0, any = 0;; c = *s++) {
> +                if (!isascii(c))
> +                        break;
> +                if (isdigit(c))
> +                        c -= '0';
> +                else if (isalpha(c))
> +                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
> +                else
> +                        break;
> +                if (c >= base)
> +                        break;
> +                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
> +                        any = -1;
> +                else {
> +                        any = 1;
> +                        acc *= qbase;
> +                        acc += c;
> +                }
>          }
> -    }
> -    while (i < precision--) {
> -        if (buf <= end)
> -            *buf = '0';
> -        ++buf;
> -    }
> -    while (i-- > 0) {
> -        if (buf <= end)
> -            *buf = tmp[i];
> -        ++buf;
> -    }
> -    while (size-- > 0) {
> -        if (buf <= end)
> -            *buf = ' ';
> -        ++buf;
> -    }
> -    return buf;
> +        if (any < 0) {
> +                acc = neg ? LLONG_MIN : LLONG_MAX;
> +        } else if (neg)
> +                acc = -acc;
> +        if (endptr != 0)
> +                *endptr = __DECONST(char *, any ? s - 1 : nptr);
> +        return (acc);
>  }
>  
> -/**
> -* vsnprintf - Format a string and place it in a buffer
> -* @buf: The buffer to place the result into
> -* @size: The size of the buffer, including the trailing null space
> -* @fmt: The format string to use
> -* @args: Arguments for the format string
> -*
> -* Call this function if you are already dealing with a va_list.
> -* You probably want snprintf instead.
> +/*
> + * Convert a string to an unsigned quad integer.
> + *
> + * Ignores `locale' stuff.  Assumes that the upper and lower case
> + * alphabets and digits are each contiguous.
>   */
> -int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
> +uint64_t
> +strtouq(const char *nptr, char **endptr, int base)
>  {
> -    int len;
> -    unsigned long long num;
> -    int i, base;
> -    char *str, *end, c;
> -    const char *s;
> -
> -    int flags;          /* flags to number() */
> -
> -    int field_width;    /* width of output field */
> -    int precision;              /* min. # of digits for integers; max
> -                                   number of chars for from string */
> -    int qualifier;              /* 'h', 'l', or 'L' for integer fields */
> -                                /* 'z' support added 23/7/1999 S.H.    */
> -                                /* 'z' changed to 'Z' --davidm 1/25/99 */
> -
> -    str = buf;
> -    end = buf + size - 1;
> -
> -    if (end < buf - 1) {
> -        end = ((void *) -1);
> -        size = end - buf + 1;
> -    }
> -
> -    for (; *fmt ; ++fmt) {
> -        if (*fmt != '%') {
> -            if (str <= end)
> -                *str = *fmt;
> -            ++str;
> -            continue;
> -        }
> -
> -        /* process flags */
> -        flags = 0;
> -    repeat:
> -        ++fmt;          /* this also skips first '%' */
> -        switch (*fmt) {
> -        case '-': flags |= LEFT; goto repeat;
> -        case '+': flags |= PLUS; goto repeat;
> -        case ' ': flags |= SPACE; goto repeat;
> -        case '#': flags |= SPECIAL; goto repeat;
> -        case '0': flags |= ZEROPAD; goto repeat;
> -        }
> -
> -        /* get field width */
> -        field_width = -1;
> -        if (isdigit(*fmt))
> -            field_width = skip_atoi(&fmt);
> -        else if (*fmt == '*') {
> -            ++fmt;
> -            /* it's the next argument */
> -            field_width = va_arg(args, int);
> -            if (field_width < 0) {
> -                field_width = -field_width;
> -                flags |= LEFT;
> -            }
> -        }
> -
> -        /* get the precision */
> -        precision = -1;
> -        if (*fmt == '.') {
> -            ++fmt;
> -            if (isdigit(*fmt))
> -                precision = skip_atoi(&fmt);
> -            else if (*fmt == '*') {
> -                ++fmt;
> -                          /* it's the next argument */
> -                precision = va_arg(args, int);
> -            }
> -            if (precision < 0)
> -                precision = 0;
> +        const char *s = nptr;
> +        uint64_t acc;
> +        unsigned char c;
> +        uint64_t qbase, cutoff;
> +        int neg, any, cutlim;
> +
> +        /*
> +         * See strtoq for comments as to the logic used.
> +         */
> +        do {
> +                c = *s++;
> +        } while (isspace(c));
> +        if (c == '-') {
> +                neg = 1;
> +                c = *s++;
> +        } else {
> +                neg = 0;
> +                if (c == '+')
> +                        c = *s++;
>          }
> -
> -        /* get the conversion qualifier */
> -        qualifier = -1;
> -        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z' || *fmt == 'z') {
> -            qualifier = *fmt;
> -            ++fmt;
> -            if (qualifier == 'l' && *fmt == 'l') {
> -                qualifier = 'L';
> -                ++fmt;
> -            } else if (qualifier == 'z') {
> -                qualifier = 'Z';
> -            }
> +        if ((base == 0 || base == 16) &&
> +            c == '0' && (*s == 'x' || *s == 'X')) {
> +                c = s[1];
> +                s += 2;
> +                base = 16;
>          }
> -        if (*fmt == 'q') {
> -            qualifier = 'L';
> -            ++fmt;
> +        if (base == 0)
> +                base = c == '0' ? 8 : 10;
> +        qbase = (unsigned)base;
> +        cutoff = (uint64_t)ULLONG_MAX / qbase;
> +        cutlim = (uint64_t)ULLONG_MAX % qbase;
> +        for (acc = 0, any = 0;; c = *s++) {
> +                if (!isascii(c))
> +                        break;
> +                if (isdigit(c))
> +                        c -= '0';
> +                else if (isalpha(c))
> +                        c -= isupper(c) ? 'A' - 10 : 'a' - 10;
> +                else
> +                        break;
> +                if (c >= base)
> +                        break;
> +                if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
> +                        any = -1;
> +                else {
> +                        any = 1;
> +                        acc *= qbase;
> +                        acc += c;
> +                }
>          }
> +        if (any < 0) {
> +                acc = ULLONG_MAX;
> +        } else if (neg)
> +                acc = -acc;
> +        if (endptr != 0)
> +                *endptr = __DECONST(char *, any ? s - 1 : nptr);
> +        return (acc);
> +}
>  
> -        /* default base */
> -        base = 10;
> -
> -        switch (*fmt) {
> -        case 'c':
> -            if (!(flags & LEFT)) {
> -                while (--field_width > 0) {
> -                    if (str <= end)
> -                        *str = ' ';
> -                    ++str;
> +/*
> + * Scaled down version of printf(3).
> + */
> +int
> +vsnprintf(char *str, size_t size, char const *fmt, va_list ap)
> +{
> +#define PCHAR(c) { if (size >= 2) { *str++ = c; size--; } retval++; }
> +        char nbuf[MAXNBUF];
> +        const char *p, *percent;
> +        int ch, n;
> +        uintmax_t num;
> +        int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
> +        int cflag, hflag, jflag, tflag, zflag;
> +        int dwidth, upper;
> +        char padc;
> +        int stop = 0, retval = 0;
> +
> +        num = 0;
> +
> +        if (fmt == NULL)
> +                fmt = "(fmt null)\n";
> +
> +        for (;;) {
> +                padc = ' ';
> +                width = 0;
> +                while ((ch = (u_char)*fmt++) != '%' || stop) {
> +                        if (ch == '\0') {
> +                                if (size >= 1)
> +                                        *str++ = '\0';
> +                                return (retval);
> +                        }
> +                        PCHAR(ch);
>                  }
> -            }
> -            c = (unsigned char) va_arg(args, int);
> -            if (str <= end)
> -                *str = c;
> -            ++str;
> -            while (--field_width > 0) {
> -                if (str <= end)
> -                    *str = ' ';
> -                ++str;
> -            }
> -            continue;
> -
> -        case 's':
> -            s = va_arg(args, char *);
> -            if (!s)
> -                s = "<NULL>";
> -
> -            len = strnlen(s, precision);
> -
> -            if (!(flags & LEFT)) {
> -                while (len < field_width--) {
> -                    if (str <= end)
> -                        *str = ' ';
> -                    ++str;
> +                percent = fmt - 1;
> +                qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
> +                sign = 0; dot = 0; dwidth = 0; upper = 0;
> +                cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
> +reswitch:       switch (ch = (u_char)*fmt++) {
> +                case '.':
> +                        dot = 1;
> +                        goto reswitch;
> +                case '#':
> +                        sharpflag = 1;
> +                        goto reswitch;
> +                case '+':
> +                        sign = 1;
> +                        goto reswitch;
> +                case '-':
> +                        ladjust = 1;
> +                        goto reswitch;
> +                case '%':
> +                        PCHAR(ch);
> +                        break;
> +                case '*':
> +                        if (!dot) {
> +                                width = va_arg(ap, int);
> +                                if (width < 0) {
> +                                        ladjust = !ladjust;
> +                                        width = -width;
> +                                }
> +                        } else {
> +                                dwidth = va_arg(ap, int);
> +                        }
> +                        goto reswitch;
> +                case '0':
> +                        if (!dot) {
> +                                padc = '0';
> +                                goto reswitch;
> +                        }
> +                case '1': case '2': case '3': case '4':
> +                case '5': case '6': case '7': case '8': case '9':
> +                                for (n = 0;; ++fmt) {
> +                                        n = n * 10 + ch - '0';
> +                                        ch = *fmt;
> +                                        if (ch < '0' || ch > '9')
> +                                                break;
> +                                }
> +                        if (dot)
> +                                dwidth = n;
> +                        else
> +                                width = n;
> +                        goto reswitch;
> +                case 'c':
> +                        PCHAR(va_arg(ap, int));
> +                        break;
> +                case 'd':
> +                case 'i':
> +                        base = 10;
> +                        sign = 1;
> +                        goto handle_sign;
> +                case 'h':
> +                        if (hflag) {
> +                                hflag = 0;
> +                                cflag = 1;
> +                        } else
> +                                hflag = 1;
> +                        goto reswitch;
> +                case 'j':
> +                        jflag = 1;
> +                        goto reswitch;
> +                case 'l':
> +                        if (lflag) {
> +                                lflag = 0;
> +                                qflag = 1;
> +                        } else
> +                                lflag = 1;
> +                        goto reswitch;
> +                case 'n':
> +                        if (jflag)
> +                                *(va_arg(ap, intmax_t *)) = retval;
> +                        else if (qflag)
> +                                *(va_arg(ap, int64_t *)) = retval;
> +                        else if (lflag)
> +                                *(va_arg(ap, long *)) = retval;
> +                        else if (zflag)
> +                                *(va_arg(ap, size_t *)) = retval;
> +                        else if (hflag)
> +                                *(va_arg(ap, short *)) = retval;
> +                        else if (cflag)
> +                                *(va_arg(ap, char *)) = retval;
> +                        else
> +                                *(va_arg(ap, int *)) = retval;
> +                        break;
> +                case 'o':
> +                        base = 8;
> +                        goto handle_nosign;
> +                case 'p':
> +                        base = 16;
> +                        sharpflag = (width == 0);
> +                        sign = 0;
> +                        num = (uintptr_t)va_arg(ap, void *);
> +                        goto number;
> +                case 'q':
> +                        qflag = 1;
> +                        goto reswitch;
> +                case 'r':
> +                        base = 10;
> +                        if (sign)
> +                                goto handle_sign;
> +                        goto handle_nosign;
> +                case 's':
> +                        p = va_arg(ap, char *);
> +                        if (p == NULL)
> +                                p = "(null)";
> +                        if (!dot)
> +                                n = strlen (p);
> +                        else
> +                                for (n = 0; n < dwidth && p[n]; n++)
> +                                        continue;
> +
> +                        width -= n;
> +
> +                        if (!ladjust && width > 0)
> +                                while (width--)
> +                                        PCHAR(padc);
> +                        while (n--)
> +                                PCHAR(*p++);
> +                        if (ladjust && width > 0)
> +                                while (width--)
> +                                        PCHAR(padc);
> +                        break;
> +                case 't':
> +                        tflag = 1;
> +                        goto reswitch;
> +                case 'u':
> +                        base = 10;
> +                        goto handle_nosign;
> +                case 'X':
> +                        upper = 1;
> +                case 'x':
> +                        base = 16;
> +                        goto handle_nosign;
> +                case 'y':
> +                        base = 16;
> +                        sign = 1;
> +                        goto handle_sign;
> +                case 'z':
> +                        zflag = 1;
> +                        goto reswitch;
> +handle_nosign:
> +                        sign = 0;
> +                        if (jflag)
> +                                num = va_arg(ap, uintmax_t);
> +                        else if (qflag)
> +                                num = va_arg(ap, uint64_t);
> +                        else if (tflag)
> +                                num = va_arg(ap, ptrdiff_t);
> +                        else if (lflag)
> +                                num = va_arg(ap, u_long);
> +                        else if (zflag)
> +                                num = va_arg(ap, size_t);
> +                        else if (hflag)
> +                                num = (unsigned short)va_arg(ap, int);
> +                        else if (cflag)
> +                                num = (u_char)va_arg(ap, int);
> +                        else
> +                                num = va_arg(ap, u_int);
> +                        goto number;
> +handle_sign:
> +                        if (jflag)
> +                                num = va_arg(ap, intmax_t);
> +                        else if (qflag)
> +                                num = va_arg(ap, int64_t);
> +                        else if (tflag)
> +                                num = va_arg(ap, ptrdiff_t);
> +                        else if (lflag)
> +                                num = va_arg(ap, long);
> +                        else if (zflag)
> +                                num = va_arg(ap, ssize_t);
> +                        else if (hflag)
> +                                num = (short)va_arg(ap, int);
> +                        else if (cflag)
> +                                num = (char)va_arg(ap, int);
> +                        else
> +                                num = va_arg(ap, int);
> +number:
> +                        if (sign && (intmax_t)num < 0) {
> +                                neg = 1;
> +                                num = -(intmax_t)num;
> +                        }
> +                        p = ksprintn(nbuf, num, base, &n, upper);
> +                        tmp = 0;
> +                        if (sharpflag && num != 0) {
> +                                if (base == 8)
> +                                        tmp++;
> +                                else if (base == 16)
> +                                        tmp += 2;
> +                        }
> +                        if (neg)
> +                                tmp++;
> +
> +                        if (!ladjust && padc == '0')
> +                                dwidth = width - tmp;
> +                        width -= tmp + (dwidth > n ? dwidth : n);
> +                        dwidth -= n;
> +                        if (!ladjust)
> +                                while (width-- > 0)
> +                                        PCHAR(' ');
> +                        if (neg)
> +                                PCHAR('-');
> +                        if (sharpflag && num != 0) {
> +                                if (base == 8) {
> +                                        PCHAR('0');
> +                                } else if (base == 16) {
> +                                        PCHAR('0');
> +                                        PCHAR('x');
> +                                }
> +                        }
> +                        while (dwidth-- > 0)
> +                                PCHAR('0');
> +
> +                        while (*p)
> +                                PCHAR(*p--);
> +
> +                        if (ladjust)
> +                                while (width-- > 0)
> +                                        PCHAR(' ');
> +
> +                        break;
> +                default:
> +                        while (percent < fmt)
> +                                PCHAR(*percent++);
> +                        /*
> +                         * Since we ignore a formatting argument it is no
> +                         * longer safe to obey the remaining formatting
> +                         * arguments as the arguments will no longer match
> +                         * the format specs.
> +                         */
> +                        stop = 1;
> +                        break;
>                  }
> -            }
> -            for (i = 0; i < len; ++i) {
> -                if (str <= end)
> -                    *str = *s;
> -                ++str; ++s;
> -            }
> -            while (len < field_width--) {
> -                if (str <= end)
> -                    *str = ' ';
> -                ++str;
> -            }
> -            continue;
> -
> -        case 'p':
> -            if (field_width == -1) {
> -                field_width = 2*sizeof(void *);
> -                flags |= ZEROPAD;
> -            }
> -            str = number(str, end,
> -                         (unsigned long) va_arg(args, void *),
> -                         16, field_width, precision, flags);
> -            continue;
> -
> -
> -        case 'n':
> -            if (qualifier == 'l') {
> -                long * ip = va_arg(args, long *);
> -                *ip = (str - buf);
> -            } else if (qualifier == 'Z') {
> -                size_t * ip = va_arg(args, size_t *);
> -                *ip = (str - buf);
> -            } else {
> -                int * ip = va_arg(args, int *);
> -                *ip = (str - buf);
> -            }
> -            continue;
> -
> -        case '%':
> -            if (str <= end)
> -                *str = '%';
> -            ++str;
> -            continue;
> -
> -            /* integer number formats - set up the flags and "break" */
> -        case 'o':
> -            base = 8;
> -            break;
> -
> -        case 'X':
> -            flags |= LARGE;
> -        case 'x':
> -            base = 16;
> -            break;
> -
> -        case 'd':
> -        case 'i':
> -            flags |= SIGN;
> -        case 'u':
> -            break;
> -
> -        default:
> -            if (str <= end)
> -                *str = '%';
> -            ++str;
> -            if (*fmt) {
> -                if (str <= end)
> -                    *str = *fmt;
> -                ++str;
> -            } else {
> -                --fmt;
> -            }
> -            continue;
>          }
> -        if (qualifier == 'L')
> -            num = va_arg(args, long long);
> -        else if (qualifier == 'l') {
> -            num = va_arg(args, unsigned long);
> -            if (flags & SIGN)
> -                num = (signed long) num;
> -        } else if (qualifier == 'Z') {
> -            num = va_arg(args, size_t);
> -        } else if (qualifier == 'h') {
> -            num = (unsigned short) va_arg(args, int);
> -            if (flags & SIGN)
> -                num = (signed short) num;
> -        } else {
> -            num = va_arg(args, unsigned int);
> -            if (flags & SIGN)
> -                num = (signed int) num;
> -        }
> -
> -        str = number(str, end, num, base,
> -                     field_width, precision, flags);
> -    }
> -    if (str <= end)
> -        *str = '\0';
> -    else if (size > 0)
> -        /* don't write out a null byte if the buf size is zero */
> -        *end = '\0';
> -    /* the trailing null byte doesn't count towards the total
> -     * ++str;
> -     */
> -    return str-buf;
> +#undef PCHAR
>  }
>  
>  /**
> @@ -552,220 +635,587 @@ int sprintf(char * buf, const char *fmt, ...)
>      return i;
>  }
>  
> +/*
> + * Fill in the given table from the scanset at the given format
> + * (just after `[').  Return a pointer to the character past the
> + * closing `]'.  The table has a 1 wherever characters should be
> + * considered part of the scanset.
> + */
> +static const u_char *
> +__sccl(char *tab, const u_char *fmt)
> +{
> +        int c, n, v;
> +
> +        /* first `clear' the whole table */
> +        c = *fmt++;             /* first char hat => negated scanset */
> +        if (c == '^') {
> +                v = 1;          /* default => accept */
> +                c = *fmt++;     /* get new first char */
> +        } else
> +                v = 0;          /* default => reject */
> +
> +        /* XXX: Will not work if sizeof(tab*) > sizeof(char) */
> +        for (n = 0; n < 256; n++)
> +                     tab[n] = v;        /* memset(tab, v, 256) */
> +
> +        if (c == 0)
> +                return (fmt - 1);/* format ended before closing ] */
> +
> +        /*
> +         * Now set the entries corresponding to the actual scanset
> +         * to the opposite of the above.
> +         *
> +         * The first character may be ']' (or '-') without being special;
> +         * the last character may be '-'.
> +         */
> +        v = 1 - v;
> +        for (;;) {
> +                tab[c] = v;             /* take character c */
> +doswitch:
> +                n = *fmt++;             /* and examine the next */
> +                switch (n) {
> +
> +                case 0:                 /* format ended too soon */
> +                        return (fmt - 1);
> +
> +                case '-':
> +                        /*
> +                         * A scanset of the form
> +                         *      [01+-]
> +                         * is defined as `the digit 0, the digit 1,
> +                         * the character +, the character -', but
> +                         * the effect of a scanset such as
> +                         *      [a-zA-Z0-9]
> +                         * is implementation defined.  The V7 Unix
> +                         * scanf treats `a-z' as `the letters a through
> +                         * z', but treats `a-a' as `the letter a, the
> +                         * character -, and the letter a'.
> +                         *
> +                         * For compatibility, the `-' is not considerd
> +                         * to define a range if the character following
> +                         * it is either a close bracket (required by ANSI)
> +                         * or is not numerically greater than the character
> +                         * we just stored in the table (c).
> +                         */
> +                        n = *fmt;
> +                        if (n == ']' || n < c) {
> +                                c = '-';
> +                                break;  /* resume the for(;;) */
> +                        }
> +                        fmt++;
> +                        /* fill in the range */
> +                        do {
> +                            tab[++c] = v;
> +                        } while (c < n);
> +                        c = n;
> +                        /*
> +                         * Alas, the V7 Unix scanf also treats formats
> +                         * such as [a-c-e] as `the letters a through e'.
> +                         * This too is permitted by the standard....
> +                         */
> +                        goto doswitch;
> +                        break;
> +
> +                case ']':               /* end of scanset */
> +                        return (fmt);
> +
> +                default:                /* just another character */
> +                        c = n;
> +                        break;
> +                }
> +        }
> +        /* NOTREACHED */
> +}
> +
>  /**
>   * vsscanf - Unformat a buffer into a list of arguments
>   * @buf:	input buffer
>   * @fmt:	format of buffer
>   * @args:	arguments
>   */
> -int vsscanf(const char * buf, const char * fmt, va_list args)
> +#define BUF             32      /* Maximum length of numeric string. */
> +
> +/*
> + * Flags used during conversion.
> + */
> +#define LONG            0x01    /* l: long or double */
> +#define SHORT           0x04    /* h: short */
> +#define SUPPRESS        0x08    /* suppress assignment */
> +#define POINTER         0x10    /* weird %p pointer (`fake hex') */
> +#define NOSKIP          0x20    /* do not skip blanks */
> +#define QUAD            0x400
> +#define SHORTSHORT      0x4000  /** hh: char */
> +
> +/*
> + * The following are used in numeric conversions only:
> + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
> + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
> + */
> +#define SIGNOK          0x40    /* +/- is (still) legal */
> +#define NDIGITS         0x80    /* no digits detected */
> +
> +#define DPTOK           0x100   /* (float) decimal point is still legal */
> +#define EXPOK           0x200   /* (float) exponent (e+3, etc) still legal */
> +
> +#define PFXOK           0x100   /* 0x prefix is (still) legal */
> +#define NZDIGITS        0x200   /* no zero digits detected */
> +
> +/*
> + * Conversion types.
> + */
> +#define CT_CHAR         0       /* %c conversion */
> +#define CT_CCL          1       /* %[...] conversion */
> +#define CT_STRING       2       /* %s conversion */
> +#define CT_INT          3       /* integer, i.e., strtoq or strtouq */
> +typedef uint64_t (*ccfntype)(const char *, char **, int);
> +
> +int
> +vsscanf(const char *inp, char const *fmt0, va_list ap)
>  {
> -	const char *str = buf;
> -	char *next;
> -	char digit;
> -	int num = 0;
> -	int qualifier;
> -	int base;
> -	int field_width;
> -	int is_sign = 0;
> +        int inr;
> +        const u_char *fmt = (const u_char *)fmt0;
> +        int c;                  /* character from format, or conversion */
> +        size_t width;           /* field width, or 0 */
> +        char *p;                /* points into all kinds of strings */
> +        int n;                  /* handy integer */
> +        int flags;              /* flags as defined above */
> +        char *p0;               /* saves original value of p when necessary */
> +        int nassigned;          /* number of fields assigned */
> +        int nconversions;       /* number of conversions */
> +        int nread;              /* number of characters consumed from fp */
> +        int base;               /* base argument to strtoq/strtouq */
> +        ccfntype ccfn;          /* conversion function (strtoq/strtouq) */
> +        char ccltab[256];       /* character class table for %[...] */
> +        char buf[BUF];          /* buffer for numeric conversions */
>  
> -	while(*fmt && *str) {
> -		/* skip any white space in format */
> -		/* white space in format matchs any amount of
> -		 * white space, including none, in the input.
> -		 */
> -		if (isspace(*fmt)) {
> -			while (isspace(*fmt))
> -				++fmt;
> -			while (isspace(*str))
> -				++str;
> -		}
> +        /* `basefix' is used to avoid `if' tests in the integer scanner */
> +        static short basefix[17] =
> +                { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
>  
> -		/* anything that is not a conversion must match exactly */
> -		if (*fmt != '%' && *fmt) {
> -			if (*fmt++ != *str++)
> -				break;
> -			continue;
> -		}
> +        inr = strlen(inp);
>  
> -		if (!*fmt)
> -			break;
> -		++fmt;
> -		
> -		/* skip this conversion.
> -		 * advance both strings to next white space
> -		 */
> -		if (*fmt == '*') {
> -			while (!isspace(*fmt) && *fmt)
> -				fmt++;
> -			while (!isspace(*str) && *str)
> -				str++;
> -			continue;
> -		}
> +        nassigned = 0;
> +        nconversions = 0;
> +        nread = 0;
> +        base = 0;               /* XXX just to keep gcc happy */
> +        ccfn = NULL;            /* XXX just to keep gcc happy */
> +        for (;;) {
> +                c = *fmt++;
> +                if (c == 0)
> +                        return (nassigned);
> +                if (isspace(c)) {
> +                        while (inr > 0 && isspace(*inp))
> +                                nread++, inr--, inp++;
> +                        continue;
> +                }
> +                if (c != '%')
> +                        goto literal;
> +                width = 0;
> +                flags = 0;
> +                /*
> +                 * switch on the format.  continue if done;
> +                 * break once format type is derived.
> +                 */
> +again:          c = *fmt++;
> +                switch (c) {
> +                case '%':
> +literal:
> +                        if (inr <= 0)
> +                                goto input_failure;
> +                        if (*inp != c)
> +                                goto match_failure;
> +                        inr--, inp++;
> +                        nread++;
> +                        continue;
>  
> -		/* get field width */
> -		field_width = -1;
> -		if (isdigit(*fmt))
> -			field_width = skip_atoi(&fmt);
> +                case '*':
> +                        flags |= SUPPRESS;
> +                        goto again;
> +                case 'l':
> +                        if (flags & LONG){
> +                                flags &= ~LONG;
> +                                flags |= QUAD;
> +                        } else {
> +                                flags |= LONG;
> +                        }
> +                        goto again;
> +                case 'q':
> +                        flags |= QUAD;
> +                        goto again;
> +                case 'h':
> +                        if (flags & SHORT){
> +                                flags &= ~SHORT;
> +                                flags |= SHORTSHORT;
> +                        } else {
> +                                flags |= SHORT;
> +                        }
> +                        goto again;
>  
> -		/* get conversion qualifier */
> -		qualifier = -1;
> -		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
> -		    *fmt == 'Z' || *fmt == 'z') {
> -			qualifier = *fmt++;
> -			if (unlikely(qualifier == *fmt)) {
> -				if (qualifier == 'h') {
> -					qualifier = 'H';
> -					fmt++;
> -				} else if (qualifier == 'l') {
> -					qualifier = 'L';
> -					fmt++;
> -				}
> -			}
> -		}
> -		base = 10;
> -		is_sign = 0;
> +                case '0': case '1': case '2': case '3': case '4':
> +                case '5': case '6': case '7': case '8': case '9':
> +                        width = width * 10 + c - '0';
> +                        goto again;
>  
> -		if (!*fmt || !*str)
> -			break;
> +                /*
> +                 * Conversions.
> +                 *
> +                 */
> +                case 'd':
> +                        c = CT_INT;
> +                        ccfn = (ccfntype)strtoq;
> +                        base = 10;
> +                        break;
>  
> -		switch(*fmt++) {
> -		case 'c':
> -		{
> -			char *s = (char *) va_arg(args,char*);
> -			if (field_width == -1)
> -				field_width = 1;
> -			do {
> -				*s++ = *str++;
> -			} while (--field_width > 0 && *str);
> -			num++;
> -		}
> -		continue;
> -		case 's':
> -		{
> -			char *s = (char *) va_arg(args, char *);
> -			if(field_width == -1)
> -				field_width = INT_MAX;
> -			/* first, skip leading white space in buffer */
> -			while (isspace(*str))
> -				str++;
> -
> -			/* now copy until next white space */
> -			while (*str && !isspace(*str) && field_width--) {
> -				*s++ = *str++;
> -			}
> -			*s = '\0';
> -			num++;
> -		}
> -		continue;
> -		case 'n':
> -			/* return number of characters read so far */
> -		{
> -			int *i = (int *)va_arg(args,int*);
> -			*i = str - buf;
> -		}
> -		continue;
> -		case 'o':
> -			base = 8;
> -			break;
> -		case 'x':
> -		case 'X':
> -			base = 16;
> -			break;
> -		case 'i':
> +                case 'i':
> +                        c = CT_INT;
> +                        ccfn = (ccfntype)strtoq;
>                          base = 0;
> -		case 'd':
> -			is_sign = 1;
> -		case 'u':
> -			break;
> -		case '%':
> -			/* looking for '%' in str */
> -			if (*str++ != '%') 
> -				return num;
> -			continue;
> -		default:
> -			/* invalid format; stop here */
> -			return num;
> -		}
> -
> -		/* have some sort of integer conversion.
> -		 * first, skip white space in buffer.
> -		 */
> -		while (isspace(*str))
> -			str++;
> -
> -		digit = *str;
> -		if (is_sign && digit == '-')
> -			digit = *(str + 1);
> -
> -		if (!digit
> -                    || (base == 16 && !isxdigit(digit))
> -                    || (base == 10 && !isdigit(digit))
> -                    || (base == 8 && (!isdigit(digit) || digit > '7'))
> -                    || (base == 0 && !isdigit(digit)))
> -				break;
> -
> -		switch(qualifier) {
> -		case 'H':	/* that's 'hh' in format */
> -			if (is_sign) {
> -				signed char *s = (signed char *) va_arg(args,signed char *);
> -				*s = (signed char) simple_strtol(str,&next,base);
> -			} else {
> -				unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
> -				*s = (unsigned char) simple_strtoul(str, &next, base);
> -			}
> -			break;
> -		case 'h':
> -			if (is_sign) {
> -				short *s = (short *) va_arg(args,short *);
> -				*s = (short) simple_strtol(str,&next,base);
> -			} else {
> -				unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
> -				*s = (unsigned short) simple_strtoul(str, &next, base);
> -			}
> -			break;
> -		case 'l':
> -			if (is_sign) {
> -				long *l = (long *) va_arg(args,long *);
> -				*l = simple_strtol(str,&next,base);
> -			} else {
> -				unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
> -				*l = simple_strtoul(str,&next,base);
> -			}
> -			break;
> -		case 'L':
> -			if (is_sign) {
> -				long long *l = (long long*) va_arg(args,long long *);
> -				*l = simple_strtoll(str,&next,base);
> -			} else {
> -				unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
> -				*l = simple_strtoull(str,&next,base);
> -			}
> -			break;
> -		case 'Z':
> -		case 'z':
> -		{
> -			size_t *s = (size_t*) va_arg(args,size_t*);
> -			*s = (size_t) simple_strtoul(str,&next,base);
> -		}
> -		break;
> -		default:
> -			if (is_sign) {
> -				int *i = (int *) va_arg(args, int*);
> -				*i = (int) simple_strtol(str,&next,base);
> -			} else {
> -				unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
> -				*i = (unsigned int) simple_strtoul(str,&next,base);
> -			}
> -			break;
> -		}
> -		num++;
> -
> -		if (!next)
> -			break;
> -		str = next;
> -	}
> -	return num;
> +                        break;
> +
> +                case 'o':
> +                        c = CT_INT;
> +                        ccfn = strtouq;
> +                        base = 8;
> +                        break;
> +
> +                case 'u':
> +                        c = CT_INT;
> +                        ccfn = strtouq;
> +                        base = 10;
> +                        break;
> +
> +                case 'x':
> +                        flags |= PFXOK; /* enable 0x prefixing */
> +                        c = CT_INT;
> +                        ccfn = strtouq;
> +                        base = 16;
> +                        break;
> +
> +                case 's':
> +                        c = CT_STRING;
> +                        break;
> +
> +                case '[':
> +                        fmt = __sccl(ccltab, fmt);
> +                        flags |= NOSKIP;
> +                        c = CT_CCL;
> +                        break;
> +
> +                case 'c':
> +                        flags |= NOSKIP;
> +                        c = CT_CHAR;
> +                        break;
> +
> +                case 'p':       /* pointer format is like hex */
> +                        flags |= POINTER | PFXOK;
> +                        c = CT_INT;
> +                        ccfn = strtouq;
> +                        base = 16;
> +                        break;
> +
> +                case 'n':
> +                        nconversions++;
> +                        if (flags & SUPPRESS)   /* ??? */
> +                                continue;
> +                        if (flags & SHORTSHORT)
> +                                *va_arg(ap, char *) = nread;
> +                        else if (flags & SHORT)
> +                                *va_arg(ap, short *) = nread;
> +                        else if (flags & LONG)
> +                                *va_arg(ap, long *) = nread;
> +                        else if (flags & QUAD)
> +                                *va_arg(ap, int64_t *) = nread;
> +                        else
> +                                *va_arg(ap, int *) = nread;
> +                        continue;
> +                }
> +
> +                /*
> +                 * We have a conversion that requires input.
> +                 */
> +                if (inr <= 0)
> +                        goto input_failure;
> +
> +                /*
> +                 * Consume leading white space, except for formats
> +                 * that suppress this.
> +                 */
> +                if ((flags & NOSKIP) == 0) {
> +                        while (isspace(*inp)) {
> +                                nread++;
> +                                if (--inr > 0)
> +                                        inp++;
> +                                else
> +                                        goto input_failure;
> +                        }
> +                        /*
> +                         * Note that there is at least one character in
> +                         * the buffer, so conversions that do not set NOSKIP
> +                         * can no longer result in an input failure.
> +                         */
> +                }
> +
> +                /*
> +                 * Do the conversion.
> +                 */
> +                switch (c) {
> +
> +                case CT_CHAR:
> +                        /* scan arbitrary characters (sets NOSKIP) */
> +                        if (width == 0)
> +                                width = 1;
> +                        if (flags & SUPPRESS) {
> +                                size_t sum = 0;
> +                                for (;;) {
> +                                        if ((n = inr) < width) {
> +                                                sum += n;
> +                                                width -= n;
> +                                                inp += n;
> +                                                if (sum == 0)
> +                                                        goto input_failure;
> +                                                break;
> +                                        } else {
> +                                                sum += width;
> +                                                inr -= width;
> +                                                inp += width;
> +                                                break;
> +                                        }
> +                                }
> +                                nread += sum;
> +                        } else {
> +                                memcpy(va_arg(ap, char *), inp, width);
> +                                inr -= width;
> +                                inp += width;
> +                                nread += width;
> +                                nassigned++;
> +                        }
> +                        nconversions++;
> +                        break;
> +
> +                case CT_CCL:
> +                        /* scan a (nonempty) character class (sets NOSKIP) */
> +                        if (width == 0)
> +                                width = (size_t)~0;     /* `infinity' */
> +                        /* take only those things in the class */
> +                        if (flags & SUPPRESS) {
> +                                n = 0;
> +                                while (ccltab[(unsigned char)*inp]) {
> +                                        n++, inr--, inp++;
> +                                        if (--width == 0)
> +                                                break;
> +                                        if (inr <= 0) {
> +                                                if (n == 0)
> +                                                        goto input_failure;
> +                                                break;
> +                                        }
> +                                }
> +                                if (n == 0)
> +                                        goto match_failure;
> +                        } else {
> +                                p0 = p = va_arg(ap, char *);
> +                                while (ccltab[(unsigned char)*inp]) {
> +                                        inr--;
> +                                        *p++ = *inp++;
> +                                        if (--width == 0)
> +                                                break;
> +                                        if (inr <= 0) {
> +                                                if (p == p0)
> +                                                        goto input_failure;
> +                                                break;
> +                                        }
> +                                }
> +                                n = p - p0;
> +                                if (n == 0)
> +                                        goto match_failure;
> +                                *p = 0;
> +                                nassigned++;
> +                        }
> +                        nread += n;
> +                        nconversions++;
> +                        break;
> +
> +                case CT_STRING:
> +                        /* like CCL, but zero-length string OK, & no NOSKIP */
> +                        if (width == 0)
> +                                width = (size_t)~0;
> +                        if (flags & SUPPRESS) {
> +                                n = 0;
> +                                while (!isspace(*inp)) {
> +                                        n++, inr--, inp++;
> +                                        if (--width == 0)
> +                                                break;
> +                                        if (inr <= 0)
> +                                                break;
> +                                }
> +                                nread += n;
> +                        } else {
> +                                p0 = p = va_arg(ap, char *);
> +                                while (!isspace(*inp)) {
> +                                        inr--;
> +                                        *p++ = *inp++;
> +                                        if (--width == 0)
> +                                                break;
> +                                        if (inr <= 0)
> +                                                break;
> +                                }
> +                                *p = 0;
> +                                nread += p - p0;
> +                                nassigned++;
> +                        }
> +                        nconversions++;
> +                        continue;
> +
> +                case CT_INT:
> +                        /* scan an integer as if by strtoq/strtouq */
> +#ifdef hardway
> +                        if (width == 0 || width > sizeof(buf) - 1)
> +                                width = sizeof(buf) - 1;
> +#else
> +                        /* size_t is unsigned, hence this optimisation */
> +                        if (--width > sizeof(buf) - 2)
> +                                width = sizeof(buf) - 2;
> +                        width++;
> +#endif
> +                        flags |= SIGNOK | NDIGITS | NZDIGITS;
> +                        for (p = buf; width; width--) {
> +                                c = *inp;
> +                                /*
> +                                 * Switch on the character; `goto ok'
> +                                 * if we accept it as a part of number.
> +                                 */
> +                                switch (c) {
> +
> +                                /*
> +                                 * The digit 0 is always legal, but is
> +                                 * special.  For %i conversions, if no
> +                                 * digits (zero or nonzero) have been
> +                                 * scanned (only signs), we will have
> +                                 * base==0.  In that case, we should set
> +                                 * it to 8 and enable 0x prefixing.
> +                                 * Also, if we have not scanned zero digits
> +                                 * before this, do not turn off prefixing
> +                                 * (someone else will turn it off if we
> +                                 * have scanned any nonzero digits).
> +                                 */
> +                                case '0':
> +                                        if (base == 0) {
> +                                                base = 8;
> +                                                flags |= PFXOK;
> +                                        }
> +                                        if (flags & NZDIGITS)
> +                                            flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
> +                                        else
> +                                            flags &= ~(SIGNOK|PFXOK|NDIGITS);
> +                                        goto ok;
> +
> +                                /* 1 through 7 always legal */
> +                                case '1': case '2': case '3':
> +                                case '4': case '5': case '6': case '7':
> +                                        base = basefix[base];
> +                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
> +                                        goto ok;
> +
> +                                /* digits 8 and 9 ok iff decimal or hex */
> +                                case '8': case '9':
> +                                        base = basefix[base];
> +                                        if (base <= 8)
> +                                                break;  /* not legal here */
> +                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
> +                                        goto ok;
> +
> +                                /* letters ok iff hex */
> +                                case 'A': case 'B': case 'C':
> +                                case 'D': case 'E': case 'F':
> +                                case 'a': case 'b': case 'c':
> +                                case 'd': case 'e': case 'f':
> +                                        /* no need to fix base here */
> +                                        if (base <= 10)
> +                                                break;  /* not legal here */
> +                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
> +                                        goto ok;
> +
> +                                /* sign ok only as first character */
> +                                case '+': case '-':
> +                                        if (flags & SIGNOK) {
> +                                                flags &= ~SIGNOK;
> +                                                goto ok;
> +                                        }
> +                                        break;
> +
> +                                /* x ok iff flag still set & 2nd char */
> +                                case 'x': case 'X':
> +                                        if (flags & PFXOK && p == buf + 1) {
> +                                                base = 16;      /* if %i */
> +                                                flags &= ~PFXOK;
> +                                                goto ok;
> +                                        }
> +                                        break;
> +                                }
> +
> +                                /*
> +                                 * If we got here, c is not a legal character
> +                                 * for a number.  Stop accumulating digits.
> +                                 */
> +                                break;
> +                ok:
> +                                /*
> +                                 * c is legal: store it and look at the next.
> +                                 */
> +                                *p++ = c;
> +                                if (--inr > 0)
> +                                        inp++;
> +                                else 
> +                                        break;          /* end of input */
> +                        }
> +                        /*
> +                         * If we had only a sign, it is no good; push
> +                         * back the sign.  If the number ends in `x',
> +                         * it was [sign] '' 'x', so push back the x
> +                         * and treat it as [sign] ''.
> +                         */
> +                        if (flags & NDIGITS) {
> +                                if (p > buf) {
> +                                        inp--;
> +                                        inr++;
> +                                }
> +                                goto match_failure;
> +                        }
> +                        c = ((u_char *)p)[-1];
> +                        if (c == 'x' || c == 'X') {
> +                                --p;
> +                                inp--;
> +                                inr++;
> +                        }
> +                        if ((flags & SUPPRESS) == 0) {
> +                                uint64_t res;
> +
> +                                *p = 0;
> +                                res = (*ccfn)(buf, (char **)NULL, base);
> +                                if (flags & POINTER)
> +                                        *va_arg(ap, void **) =
> +                                                (void *)(uintptr_t)res;
> +                                else if (flags & SHORTSHORT)
> +                                        *va_arg(ap, char *) = res;
> +                                else if (flags & SHORT)
> +                                        *va_arg(ap, short *) = res;
> +                                else if (flags & LONG)
> +                                        *va_arg(ap, long *) = res;
> +                                else if (flags & QUAD)
> +                                        *va_arg(ap, int64_t *) = res;
> +                                else
> +                                        *va_arg(ap, int *) = res;
> +                                nassigned++;
> +                        }
> +                        nread += p - buf;
> +                        nconversions++;
> +                        break;
> +
> +                }
> +        }
> +input_failure:
> +        return (nconversions != 0 ? nassigned : -1);
> +match_failure:
> +        return (nassigned);
>  }
>  
>  /**
> diff --git a/tpmback.c b/tpmback.c
> index 00b66e8..22adbd3 100644
> --- a/tpmback.c
> +++ b/tpmback.c
> @@ -52,10 +52,6 @@
>  #include <mini-os/wait.h>
>  
>  
> -#ifndef HAVE_LIBC
> -#define strtoul simple_strtoul
> -#endif
> -
>  //#define TPMBACK_PRINT_DEBUG
>  #ifdef TPMBACK_PRINT_DEBUG
>  #define TPMBACK_DEBUG(fmt,...) printk("Tpmback:Debug("__FILE__":%d) " fmt, __LINE__, ##__VA_ARGS__)
> -- 
> 2.6.6
> 

-- 
Samuel
As usual, this being a 1.3.x release, I haven't even compiled this
kernel yet.  So if it works, you should be doubly impressed.
(Linus Torvalds, announcing kernel 1.3.3 on the linux-kernel mailing list.)

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Minios-devel] [PATCH v2] mini-os: replace lib/printf.c with a version not under GPL
  2016-07-12  8:48 ` Samuel Thibault
@ 2016-07-12  9:19   ` Wei Liu
  2016-07-12  9:44     ` Wei Liu
  0 siblings, 1 reply; 4+ messages in thread
From: Wei Liu @ 2016-07-12  9:19 UTC (permalink / raw)
  To: Samuel Thibault, Juergen Gross, wei.liu2, minios-devel,
	xen-devel, andrew.cooper3

On Tue, Jul 12, 2016 at 10:48:50AM +0200, Samuel Thibault wrote:
> Juergen Gross, on Mon 04 Jul 2016 11:16:59 +0200, wrote:
> > Instead of a Linux kernel based implementation use one from freeBSD.
> > 
> > As a result some of the printings will change due to more posix like
> > behavior of %p format (omitting leading zeroes, prepending "0x").
> > 
> > Signed-off-by: Juergen Gross <jgross@suse.com>
> 
> Acked-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

Queued.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Minios-devel] [PATCH v2] mini-os: replace lib/printf.c with a version not under GPL
  2016-07-12  9:19   ` [Minios-devel] " Wei Liu
@ 2016-07-12  9:44     ` Wei Liu
  0 siblings, 0 replies; 4+ messages in thread
From: Wei Liu @ 2016-07-12  9:44 UTC (permalink / raw)
  To: Samuel Thibault, Juergen Gross, wei.liu2, minios-devel,
	xen-devel, andrew.cooper3

On Tue, Jul 12, 2016 at 10:19:41AM +0100, Wei Liu wrote:
> On Tue, Jul 12, 2016 at 10:48:50AM +0200, Samuel Thibault wrote:
> > Juergen Gross, on Mon 04 Jul 2016 11:16:59 +0200, wrote:
> > > Instead of a Linux kernel based implementation use one from freeBSD.

Roger has asked me on IRC to s/freeBSD/FreeBSD/. I will do that when I
push this patch.

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-07-12  9:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-04  9:16 [PATCH v2] mini-os: replace lib/printf.c with a version not under GPL Juergen Gross
2016-07-12  8:48 ` Samuel Thibault
2016-07-12  9:19   ` [Minios-devel] " Wei Liu
2016-07-12  9:44     ` Wei Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).