TIOCGPGRP copies an int out of the kernel
[unix-history] / usr / src / lib / libc / stdlib / strtoul.c
CommitLineData
8c50609b
KB
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8#if defined(LIBC_SCCS) && !defined(lint)
f0a345ab 9static char sccsid[] = "@(#)strtoul.c 5.3 (Berkeley) %G%";
8c50609b
KB
10#endif /* LIBC_SCCS and not lint */
11
12#include <limits.h>
13#include <ctype.h>
14#include <errno.h>
dd967b02 15#include <stdlib.h>
8c50609b
KB
16
17/*
18 * Convert a string to an unsigned long integer.
19 *
20 * Ignores `locale' stuff. Assumes that the upper and lower case
21 * alphabets and digits are each contiguous.
22 */
23unsigned long
24strtoul(nptr, endptr, base)
f0a345ab
DS
25 const char *nptr;
26 char **endptr;
8c50609b
KB
27 register int base;
28{
f0a345ab 29 register const char *s = nptr;
8c50609b
KB
30 register unsigned long acc;
31 register int c;
32 register unsigned long cutoff;
33 register int neg = 0, any, cutlim;
34
35 /*
36 * See strtol for comments as to the logic used.
37 */
38 do {
39 c = *s++;
40 } while (isspace(c));
41 if (c == '-') {
42 neg = 1;
43 c = *s++;
44 } else if (c == '+')
45 c = *s++;
46 if ((base == 0 || base == 16) &&
47 c == '0' && (*s == 'x' || *s == 'X')) {
48 c = s[1];
49 s += 2;
50 base = 16;
51 }
52 if (base == 0)
53 base = c == '0' ? 8 : 10;
54 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
55 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
56 for (acc = 0, any = 0;; c = *s++) {
57 if (isdigit(c))
58 c -= '0';
59 else if (isalpha(c))
60 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
61 else
62 break;
63 if (c >= base)
64 break;
65 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
66 any = -1;
67 else {
68 any = 1;
69 acc *= base;
70 acc += c;
71 }
72 }
73 if (any < 0) {
74 acc = ULONG_MAX;
75 errno = ERANGE;
76 } else if (neg)
77 acc = -acc;
78 if (endptr != 0)
f0a345ab 79 *endptr = any ? s - 1 : (char *)nptr;
8c50609b
KB
80 return (acc);
81}