1/* $NetBSD: _strtoul.h,v 1.7 2013/05/17 12:55:56 joerg Exp $ */ 2 3/*- 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * Original version ID: 32 * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp 33 */ 34 35#include <bmk-core/null.h> 36#include <bmk-core/platform.h> 37#include <bmk-core/string.h> 38 39/* 40 * Technically this module is meant to be used as an includable template, 41 * but for now we only need strtoul, so just hardcode it. 42 */ 43 44#define _FUNCNAME bmk_strtoul 45#define __UINT unsigned long 46#define __UINT_MAX (2UL*__LONG_MAX__+1UL) 47 48#define __UNCONST(x) ((void *)(unsigned long)(x)) 49 50/* 51 * function template for strtoul, strtoull and strtoumax. 52 * 53 * parameters: 54 * _FUNCNAME : function name 55 * __UINT : return type 56 * __UINT_MAX : upper limit of the return type 57 */ 58__UINT 59_FUNCNAME(const char *nptr, char **endptr, int base) 60{ 61 const char *s; 62 __UINT acc, cutoff; 63 unsigned char c; 64 int i, neg, any, cutlim; 65 66 /* check base value */ 67 if (base && (base < 2 || base > 36)) { 68 bmk_platform_halt("invalid base to strtoul"); 69 } 70 71 /* 72 * Skip white space and pick up leading +/- sign if any. 73 * If base is 0, allow 0x for hex and 0 for octal, else 74 * assume decimal; if base is already 16, allow 0x. 75 */ 76 s = nptr; 77 do { 78 c = *s++; 79 } while (c == ' '|| (c >= '\t' && c <= '\r')); 80 if (c == '-') { 81 neg = 1; 82 c = *s++; 83 } else { 84 neg = 0; 85 if (c == '+') 86 c = *s++; 87 } 88 if ((base == 0 || base == 16) && 89 c == '0' && (*s == 'x' || *s == 'X')) { 90 c = s[1]; 91 s += 2; 92 base = 16; 93 } 94 if (base == 0) 95 base = (c == '0' ? 8 : 10); 96 97 /* 98 * See strtol for comments as to the logic used. 99 */ 100 cutoff = ((__UINT)__UINT_MAX / (__UINT)base); 101 cutlim = (int)((__UINT)__UINT_MAX % (__UINT)base); 102 for (acc = 0, any = 0;; c = *s++) { 103 if (c >= '0' && c <= '9') 104 i = c - '0'; 105 else if (c >= 'a' && c <= 'z') 106 i = (c - 'a') + 10; 107 else if (c >= 'A' && c <= 'Z') 108 i = (c - 'A') + 10; 109 else 110 break; 111 if (i >= base) 112 break; 113 if (any < 0) 114 continue; 115 if (acc > cutoff || (acc == cutoff && i > cutlim)) { 116 acc = __UINT_MAX; 117 any = 0; 118 break; 119 } else { 120 any = 1; 121 acc *= (__UINT)base; 122 acc += i; 123 } 124 } 125 if (neg && any > 0) 126 acc = -acc; 127 if (endptr != NULL) 128 /* LINTED interface specification */ 129 *endptr = __UNCONST(any ? s - 1 : nptr); 130 return(acc); 131} 132