strtoul.c revision 116189
1212793Sdim/*- 2212793Sdim * Copyright (c) 1990, 1993 3212793Sdim * The Regents of the University of California. All rights reserved. 4212793Sdim * 5212793Sdim * This code is derived from software contributed to Berkeley by 6212793Sdim * Chris Torek. 7212793Sdim * 8212793Sdim * Redistribution and use in source and binary forms, with or without 9212793Sdim * modification, are permitted provided that the following conditions 10226633Sdim * are met: 11249423Sdim * 1. Redistributions of source code must retain the above copyright 12249423Sdim * notice, this list of conditions and the following disclaimer. 13249423Sdim * 2. Redistributions in binary form must reproduce the above copyright 14249423Sdim * notice, this list of conditions and the following disclaimer in the 15218893Sdim * documentation and/or other materials provided with the distribution. 16226633Sdim * 3. All advertising materials mentioning features or use of this software 17249423Sdim * must display the following acknowledgement: 18226633Sdim * This product includes software developed by the University of 19226633Sdim * California, Berkeley and its contributors. 20226633Sdim * 4. Neither the name of the University nor the names of its contributors 21218893Sdim * may be used to endorse or promote products derived from this software 22218893Sdim * without specific prior written permission. 23212793Sdim * 24218893Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25239462Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26234353Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27234353Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28249423Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29212793Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30212793Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31218893Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32218893Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33218893Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34218893Sdim * SUCH DAMAGE. 35218893Sdim * 36224145Sdim * From: @(#)strtoul.c 8.1 (Berkeley) 6/4/93 37218893Sdim */ 38218893Sdim 39218893Sdim#include <sys/cdefs.h> 40239462Sdim__FBSDID("$FreeBSD: head/sys/libkern/strtoul.c 116189 2003-06-11 05:37:42Z obrien $"); 41224145Sdim 42218893Sdim#include <sys/param.h> 43218893Sdim#include <sys/systm.h> 44218893Sdim#include <sys/ctype.h> 45224145Sdim#include <sys/limits.h> 46218893Sdim 47218893Sdim/* 48224145Sdim * Convert a string to an unsigned long integer. 49218893Sdim * 50218893Sdim * Ignores `locale' stuff. Assumes that the upper and lower case 51218893Sdim * alphabets and digits are each contiguous. 52224145Sdim */ 53218893Sdimunsigned long 54218893Sdimstrtoul(nptr, endptr, base) 55218893Sdim const char *nptr; 56224145Sdim char **endptr; 57218893Sdim int base; 58218893Sdim{ 59218893Sdim const char *s = nptr; 60218893Sdim unsigned long acc; 61218893Sdim unsigned char c; 62218893Sdim unsigned long cutoff; 63218893Sdim int neg = 0, any, cutlim; 64218893Sdim 65218893Sdim /* 66218893Sdim * See strtol for comments as to the logic used. 67218893Sdim */ 68218893Sdim do { 69218893Sdim c = *s++; 70218893Sdim } while (isspace(c)); 71218893Sdim if (c == '-') { 72218893Sdim neg = 1; 73218893Sdim c = *s++; 74218893Sdim } else if (c == '+') 75218893Sdim c = *s++; 76218893Sdim if ((base == 0 || base == 16) && 77218893Sdim c == '0' && (*s == 'x' || *s == 'X')) { 78218893Sdim c = s[1]; 79218893Sdim s += 2; 80218893Sdim base = 16; 81218893Sdim } 82218893Sdim if (base == 0) 83218893Sdim base = c == '0' ? 8 : 10; 84218893Sdim cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 85218893Sdim cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 86218893Sdim for (acc = 0, any = 0;; c = *s++) { 87218893Sdim if (!isascii(c)) 88218893Sdim break; 89218893Sdim if (isdigit(c)) 90218893Sdim c -= '0'; 91218893Sdim else if (isalpha(c)) 92218893Sdim c -= isupper(c) ? 'A' - 10 : 'a' - 10; 93218893Sdim else 94218893Sdim break; 95218893Sdim if (c >= base) 96218893Sdim break; 97218893Sdim if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 98218893Sdim any = -1; 99218893Sdim else { 100218893Sdim any = 1; 101218893Sdim acc *= base; 102218893Sdim acc += c; 103218893Sdim } 104249423Sdim } 105249423Sdim if (any < 0) { 106218893Sdim acc = ULONG_MAX; 107218893Sdim } else if (neg) 108218893Sdim acc = -acc; 109218893Sdim if (endptr != 0) 110239462Sdim *((const char **)endptr) = any ? s - 1 : nptr; 111218893Sdim return (acc); 112218893Sdim} 113218893Sdim