/contrib/bind9/lib/lwres/strtoul.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 135 lines · 67 code · 9 blank · 59 comment · 37 complexity · 2b23495a9d2c21f835de9e1115d08530 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004, 2005, 2007, 2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /*
  18. * Copyright (c) 1990, 1993
  19. * The Regents of the University of California. All rights reserved.
  20. *
  21. * Redistribution and use in source and binary forms, with or without
  22. * modification, are permitted provided that the following conditions
  23. * are met:
  24. * 1. Redistributions of source code must retain the above copyright
  25. * notice, this list of conditions and the following disclaimer.
  26. * 2. Redistributions in binary form must reproduce the above copyright
  27. * notice, this list of conditions and the following disclaimer in the
  28. * documentation and/or other materials provided with the distribution.
  29. * 3. All advertising materials mentioning features or use of this software
  30. * must display the following acknowledgement:
  31. * This product includes software developed by the University of
  32. * California, Berkeley and its contributors.
  33. * 4. Neither the name of the University nor the names of its contributors
  34. * may be used to endorse or promote products derived from this software
  35. * without specific prior written permission.
  36. *
  37. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  38. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  39. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  40. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  41. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  42. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  43. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  44. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  45. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  46. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. */
  49. /*! \file */
  50. #if defined(LIBC_SCCS) && !defined(lint)
  51. static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
  52. #endif /* LIBC_SCCS and not lint */
  53. /* $Id$ */
  54. #include <config.h>
  55. #include <limits.h>
  56. #include <ctype.h>
  57. #include <errno.h>
  58. #include <lwres/stdlib.h>
  59. #define DE_CONST(konst, var) \
  60. do { \
  61. union { const void *k; void *v; } _u; \
  62. _u.k = konst; \
  63. var = _u.v; \
  64. } while (0)
  65. /*!
  66. * Convert a string to an unsigned long integer.
  67. *
  68. * Ignores `locale' stuff. Assumes that the upper and lower case
  69. * alphabets and digits are each contiguous.
  70. */
  71. unsigned long
  72. lwres_strtoul(const char *nptr, char **endptr, int base) {
  73. const char *s = nptr;
  74. unsigned long acc;
  75. unsigned char c;
  76. unsigned long cutoff;
  77. int neg = 0, any, cutlim;
  78. /*
  79. * See strtol for comments as to the logic used.
  80. */
  81. do {
  82. c = *s++;
  83. } while (isspace(c));
  84. if (c == '-') {
  85. neg = 1;
  86. c = *s++;
  87. } else if (c == '+')
  88. c = *s++;
  89. if ((base == 0 || base == 16) &&
  90. c == '0' && (*s == 'x' || *s == 'X')) {
  91. c = s[1];
  92. s += 2;
  93. base = 16;
  94. }
  95. if (base == 0)
  96. base = c == '0' ? 8 : 10;
  97. cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
  98. cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
  99. for (acc = 0, any = 0;; c = *s++) {
  100. if (!isascii(c))
  101. break;
  102. if (isdigit(c))
  103. c -= '0';
  104. else if (isalpha(c))
  105. c -= isupper(c) ? 'A' - 10 : 'a' - 10;
  106. else
  107. break;
  108. if (c >= base)
  109. break;
  110. if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
  111. any = -1;
  112. else {
  113. any = 1;
  114. acc *= base;
  115. acc += c;
  116. }
  117. }
  118. if (any < 0) {
  119. acc = ULONG_MAX;
  120. errno = ERANGE;
  121. } else if (neg)
  122. acc = -acc;
  123. if (endptr != 0)
  124. DE_CONST(any ? s - 1 : nptr, *endptr);
  125. return (acc);
  126. }