source: trunk/minix/lib/ansi/strtol.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 2.3 KB
Line 
1/*
2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
4 */
5/* $Header: /cvsup/minix/src/lib/ansi/strtol.c,v 1.1.1.1 2005/04/21 14:56:06 beng Exp $ */
6
7#include <ctype.h>
8#include <errno.h>
9#include <limits.h>
10#include <stdlib.h>
11
12static unsigned long
13string2long(register const char *nptr, char **endptr,
14 int base, int is_signed);
15
16long int
17strtol(register const char *nptr, char **endptr, int base)
18{
19 return (signed long)string2long(nptr, endptr, base, 1);
20}
21
22unsigned long int
23strtoul(register const char *nptr, char **endptr, int base)
24{
25 return (unsigned long)string2long(nptr, endptr, base, 0);
26}
27
28#define between(a, c, z) ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))
29
30static unsigned long
31string2long(register const char *nptr, char ** const endptr,
32 int base, int is_signed)
33{
34 register unsigned int v;
35 register unsigned long val = 0;
36 register int c;
37 int ovfl = 0, sign = 1;
38 const char *startnptr = nptr, *nrstart;
39
40 if (endptr) *endptr = (char *)nptr;
41 while (isspace(*nptr)) nptr++;
42 c = *nptr;
43
44 if (c == '-' || c == '+') {
45 if (c == '-') sign = -1;
46 nptr++;
47 }
48 nrstart = nptr; /* start of the number */
49
50 /* When base is 0, the syntax determines the actual base */
51 if (base == 0)
52 if (*nptr == '0')
53 if (*++nptr == 'x' || *nptr == 'X') {
54 base = 16;
55 nptr++;
56 }
57 else base = 8;
58 else base = 10;
59 else if (base==16 && *nptr=='0' && (*++nptr =='x' || *nptr =='X'))
60 nptr++;
61
62 for (;;) {
63 c = *nptr;
64 if (between('0', c, '9')) {
65 v = c - '0';
66 } else
67 if (between('a', c, 'z')) {
68 v = c - 'a' + 0xa;
69 } else
70 if (between('A', c, 'Z')) {
71 v = c - 'A' + 0xA;
72 } else {
73 break;
74 }
75 if (v >= base) break;
76 if (val > (ULONG_MAX - v) / base) ovfl++;
77 val = (val * base) + v;
78 nptr++;
79 }
80 if (endptr) {
81 if (nrstart == nptr) *endptr = (char *)startnptr;
82 else *endptr = (char *)nptr;
83 }
84
85 if (!ovfl) {
86 /* Overflow is only possible when converting a signed long. */
87 if (is_signed
88 && ( (sign < 0 && val > -(unsigned long)LONG_MIN)
89 || (sign > 0 && val > LONG_MAX)))
90 ovfl++;
91 }
92
93 if (ovfl) {
94 errno = ERANGE;
95 if (is_signed)
96 if (sign < 0) return LONG_MIN;
97 else return LONG_MAX;
98 else return ULONG_MAX;
99 }
100 return (long) sign * val;
101}
Note: See TracBrowser for help on using the repository browser.