No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / groff / src / libs / libgroff / strtol.c
blobd2284ac86cf48936c993641fbeac37773c361155
1 /* $NetBSD$ */
3 /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
4 Free Software Foundation, Inc.
5 Written by James Clark (jjc@jclark.com)
7 This file is part of groff.
9 groff is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
14 groff is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License along
20 with groff; see the file COPYING. If not, write to the Free Software
21 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <string.h>
28 #include <ctype.h>
29 #include <errno.h>
31 #ifdef HAVE_LIMITS_H
32 #include <limits.h>
33 #endif
35 #ifndef LONG_MAX
36 #define LONG_MAX 2147483647
37 #endif
39 #ifndef LONG_MIN
40 #define LONG_MIN (-LONG_MAX-1)
41 #endif
43 #ifdef isascii
44 #define ISASCII(c) isascii(c)
45 #else
46 #define ISASCII(c) (1)
47 #endif
49 long strtol(str, ptr, base)
50 char *str, **ptr;
51 int base;
53 char *start = str;
54 int neg = 0;
55 long val;
56 char *p;
57 static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
59 while (ISASCII((unsigned char)*str) && isspace((unsigned char)*str))
60 str++;
62 if (*str == '-') {
63 neg = 1;
64 str++;
66 if (base == 0) {
67 if (*str == '0') {
68 if (str[1] == 'x' || str[1] == 'X') {
69 str += 2;
70 base = 16;
72 else
73 base = 8;
75 else
76 base = 10;
78 if (base < 2 || base > 36)
79 base = 10;
80 else if (base == 16 && *str == '0' && (str[1] == 'x' || str[1] == 'X'))
81 str += 2;
83 p = strchr(digits, (ISASCII((unsigned char)*str)
84 && isupper((unsigned char)*str)
85 ? tolower((unsigned char)*str)
86 : *str));
87 if (p == 0 || (val = (p - digits)) >= base) {
88 if (base == 16 && str > start && (str[-1] == 'x' || str[-1] == 'X')) {
89 if (ptr)
90 *ptr = str - 1;
92 else {
93 if (ptr)
94 *ptr = start;
95 errno = ERANGE;
97 return 0;
99 if (neg)
100 val = -val;
102 while (*++str != '\0') {
103 int n;
105 p = strchr(digits, (ISASCII((unsigned char)*str)
106 && isupper((unsigned char)*str)
107 ? tolower((unsigned char)*str) : *str));
108 if (p == 0)
109 break;
110 n = p - digits;
111 if (n >= base)
112 break;
113 if (neg) {
114 if (-(unsigned long)val > (-(unsigned long)LONG_MIN - n)/base) {
115 val = LONG_MIN;
116 errno = ERANGE;
118 else
119 val = val*base - n;
121 else {
122 if (val > (LONG_MAX - n)/base) {
123 val = LONG_MAX;
124 errno = ERANGE;
126 else
127 val = val*base + n;
131 if (ptr)
132 *ptr = str;
134 return val;