[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2] mini-os: replace lib/printf.c with a version not under GPL



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@xxxxxxxx>

Acked-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>

> ---
> 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@xxxxxxxxxxxxx)
> - *     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@xxxxxxxxxxxxx)
> - *     Changes: Grzegorz Milos (gm281@xxxxxxxxx) 
> + *      Author: Juergen Gross <jgross@xxxxxxxx>
>   *
> - *        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@xxxxxxxxxxxxxx>
> - * - changed to provide snprintf and vsnprintf functions
> - * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@xxxxxxx>
> - * - 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@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.