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