[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |