X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..2a1bd2d3eef5c7a7bb14f4bb9fdbca9a96ee4752:/iokit/Kernel/IOStringFuncs.c diff --git a/iokit/Kernel/IOStringFuncs.c b/iokit/Kernel/IOStringFuncs.c index 8fe5ddec5..48f8239c3 100644 --- a/iokit/Kernel/IOStringFuncs.c +++ b/iokit/Kernel/IOStringFuncs.c @@ -1,25 +1,33 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1998-2016 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ -/* Copyright (c) 1995 NeXT Computer, Inc. All rights reserved. + +/* + * Copyright (c) 1995 NeXT Computer, Inc. All rights reserved. * * strol.c - The functions strtol() & strtoul() are exported as public API * via the header file ~driverkit/generalFuncs.h @@ -32,7 +40,7 @@ * Commented out references to errno. */ -/*- +/* * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * @@ -66,38 +74,46 @@ */ /* -#include -#include -#include -*/ -#include + #include + #include + #include + */ +#include #include + +long strtol(const char *nptr, char **endptr, int base); +unsigned long strtoul(const char *nptr, char **endptr, int base); +quad_t strtoq(const char *nptr, char **endptr, int base); +u_quad_t strtouq(const char *nptr, char **endptr, int base); +char *strncat(char *s1, const char *s2, unsigned long n); + + typedef int BOOL; static inline BOOL isupper(char c) { - return (c >= 'A' && c <= 'Z'); + return c >= 'A' && c <= 'Z'; } static inline BOOL isalpha(char c) { - return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } static inline BOOL isspace(char c) { - return (c == ' ' || c == '\t' || c == '\n' || c == '\12'); + return c == ' ' || c == '\t' || c == '\n' || c == '\12'; } static inline BOOL isdigit(char c) { - return (c >= '0' && c <= '9'); + return c >= '0' && c <= '9'; } /* @@ -107,16 +123,13 @@ isdigit(char c) * alphabets and digits are each contiguous. */ long -strtol(nptr, endptr, base) - const char *nptr; - char **endptr; - register int base; +strtol(const char *nptr, char **endptr, int base) { - register const char *s = nptr; - register unsigned long acc; - register int c; - register unsigned long cutoff; - register int neg = 0, any, cutlim; + const char *s = nptr; + unsigned long acc; + char c; + unsigned long cutoff; + int neg = 0, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. @@ -129,8 +142,9 @@ strtol(nptr, endptr, base) if (c == '-') { neg = 1; c = *s++; - } else if (c == '+') + } else if (c == '+') { c = *s++; + } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; @@ -142,8 +156,9 @@ strtol(nptr, endptr, base) s += 2; base = 2; } - if (base == 0) + if (base == 0) { base = c == '0' ? 8 : 10; + } /* * Compute the cutoff value between legal numbers and illegal @@ -163,20 +178,22 @@ strtol(nptr, endptr, base) * overflow. */ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; - cutlim = cutoff % (unsigned long)base; + cutlim = ((int)(cutoff % (unsigned long)base)); cutoff /= (unsigned long)base; for (acc = 0, any = 0;; c = *s++) { - if (isdigit(c)) + if (isdigit(c)) { c -= '0'; - else if (isalpha(c)) + } else if (isalpha(c)) { c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else + } else { break; - if (c >= base) + } + if (c >= base) { break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) ) + } + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { any = -1; - else { + } else { any = 1; acc *= base; acc += c; @@ -185,24 +202,27 @@ strtol(nptr, endptr, base) if (any < 0) { acc = neg ? LONG_MIN : LONG_MAX; // errno = ERANGE; - } else if (neg) + } else if (neg) { acc = -acc; - if (endptr != 0) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); + } + if (endptr != 0) { + if (any) { + *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); + } else { + *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); + } + } + return acc; } unsigned long -strtoul(nptr, endptr, base) - const char *nptr; - char **endptr; - register int base; +strtoul(const char *nptr, char **endptr, int base) { - register const char *s = nptr; - register unsigned long acc; - register int c; - register unsigned long cutoff; - register int neg = 0, any, cutlim; + const char *s = nptr; + unsigned long acc; + char c; + unsigned long cutoff; + int neg = 0, any, cutlim; /* * See strtol for comments as to the logic used. @@ -213,8 +233,9 @@ strtoul(nptr, endptr, base) if (c == '-') { neg = 1; c = *s++; - } else if (c == '+') + } else if (c == '+') { c = *s++; + } if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; @@ -226,22 +247,25 @@ strtoul(nptr, endptr, base) s += 2; base = 2; } - if (base == 0) + if (base == 0) { base = c == '0' ? 8 : 10; + } cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; - cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + cutlim = ((int)((unsigned long)ULONG_MAX % (unsigned long)base)); for (acc = 0, any = 0;; c = *s++) { - if (isdigit(c)) + if (isdigit(c)) { c -= '0'; - else if (isalpha(c)) + } else if (isalpha(c)) { c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else + } else { break; - if (c >= base) + } + if (c >= base) { break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim) ) + } + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { any = -1; - else { + } else { any = 1; acc *= base; acc += c; @@ -250,26 +274,204 @@ strtoul(nptr, endptr, base) if (any < 0) { acc = ULONG_MAX; // errno = ERANGE; - } else if (neg) + } else if (neg) { acc = -acc; - if (endptr != 0) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); + } + if (endptr != 0) { + if (any) { + *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); + } else { + *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); + } + } + + return acc; } /* + * Convert a string to a quad integer. * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. */ +quad_t +strtoq(const char *nptr, char **endptr, int base) +{ + const char *s; + u_quad_t acc; + char c; + u_quad_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 ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + 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 ? -(u_quad_t)QUAD_MIN : QUAD_MAX; + cutlim = ((int)(cutoff % qbase)); + cutoff /= qbase; + for (acc = 0, any = 0;; c = *s++) { + 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 = neg ? QUAD_MIN : QUAD_MAX; +// errno = ERANGE; + } else if (neg) { + acc = -acc; + } + if (endptr != 0) { + if (any) { + *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); + } else { + *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); + } + } -char *strchr(const char *str, int ch) + return acc; +} + + +/* + * Convert a string to an unsigned quad integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +u_quad_t +strtouq(const char *nptr, + char **endptr, + int base) { - do { - if (*str == ch) - return((char *)str); - } while (*str++); - return ((char *) 0); + const char *s = nptr; + u_quad_t acc; + char c; + u_quad_t qbase, cutoff; + int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') { + c = *s++; + } + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) { + base = c == '0' ? 8 : 10; + } + qbase = (unsigned)base; + cutoff = (u_quad_t)UQUAD_MAX / qbase; + cutlim = ((int)((u_quad_t)UQUAD_MAX % qbase)); + for (acc = 0, any = 0;; c = *s++) { + 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 = UQUAD_MAX; +// errno = ERANGE; + } else if (neg) { + acc = -acc; + } + if (endptr != 0) { + if (any) { + *endptr = __CAST_AWAY_QUALIFIER(s - 1, const, char *); + } else { + *endptr = __CAST_AWAY_QUALIFIER(nptr, const, char *); + } + } + + return acc; } + /* * */ @@ -277,17 +479,20 @@ char *strchr(const char *str, int ch) char * strncat(char *s1, const char *s2, unsigned long n) { - char *os1; - int i = n; + if (n != 0) { + char *d = s1; + const char *s = s2; - os1 = s1; - while (*s1++) - ; - --s1; - while ((*s1++ = *s2++)) - if (--i < 0) { - *--s1 = '\0'; - break; + while (*d != 0) { + d++; } - return(os1); + do { + if ((*d = *s++) == '\0') { + break; + } + d++; + } while (--n != 0); + *d = '\0'; + } + return s1; }