strtol.c revision 151497
1104862Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001 2104862Sru Free Software Foundation, Inc. 375584Sru Written by James Clark (jjc@jclark.com) 475584Sru 575584SruThis file is part of groff. 675584Sru 775584Srugroff is free software; you can redistribute it and/or modify it under 875584Sruthe terms of the GNU General Public License as published by the Free 975584SruSoftware Foundation; either version 2, or (at your option) any later 1075584Sruversion. 1175584Sru 1275584Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY 1375584SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 1475584SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1575584Srufor more details. 1675584Sru 1775584SruYou should have received a copy of the GNU General Public License along 1875584Sruwith groff; see the file COPYING. If not, write to the Free Software 19151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 2075584Sru 21104862Sru#ifdef HAVE_CONFIG_H 22104862Sru#include <config.h> 23104862Sru#endif 24104862Sru 2575584Sru#include <string.h> 2675584Sru#include <ctype.h> 2775584Sru#include <errno.h> 2875584Sru 2975584Sru#ifdef HAVE_LIMITS_H 3075584Sru#include <limits.h> 3175584Sru#endif 3275584Sru 3375584Sru#ifndef LONG_MAX 3475584Sru#define LONG_MAX 2147483647 3575584Sru#endif 3675584Sru 3775584Sru#ifndef LONG_MIN 3875584Sru#define LONG_MIN (-LONG_MAX-1) 3975584Sru#endif 4075584Sru 4175584Sru#ifdef isascii 4275584Sru#define ISASCII(c) isascii(c) 4375584Sru#else 4475584Sru#define ISASCII(c) (1) 4575584Sru#endif 4675584Sru 4775584Srulong strtol(str, ptr, base) 4875584Sru char *str, **ptr; 4975584Sru int base; 5075584Sru{ 5175584Sru char *start = str; 5275584Sru int neg = 0; 5375584Sru long val; 5475584Sru char *p; 5575584Sru static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 5675584Sru 5775584Sru while (ISASCII((unsigned char)*str) && isspace((unsigned char)*str)) 5875584Sru str++; 5975584Sru 6075584Sru if (*str == '-') { 6175584Sru neg = 1; 6275584Sru str++; 6375584Sru } 6475584Sru if (base == 0) { 6575584Sru if (*str == '0') { 6675584Sru if (str[1] == 'x' || str[1] == 'X') { 6775584Sru str += 2; 6875584Sru base = 16; 6975584Sru } 7075584Sru else 7175584Sru base = 8; 7275584Sru } 7375584Sru else 7475584Sru base = 10; 7575584Sru } 7675584Sru if (base < 2 || base > 36) 7775584Sru base = 10; 7875584Sru else if (base == 16 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) 7975584Sru str += 2; 8075584Sru 8175584Sru p = strchr(digits, (ISASCII((unsigned char)*str) 8275584Sru && isupper((unsigned char)*str) 8375584Sru ? tolower((unsigned char)*str) 8475584Sru : *str)); 8575584Sru if (p == 0 || (val = (p - digits)) >= base) { 8675584Sru if (base == 16 && str > start && (str[-1] == 'x' || str[-1] == 'X')) { 8775584Sru if (ptr) 8875584Sru *ptr = str - 1; 8975584Sru } 9075584Sru else { 9175584Sru if (ptr) 9275584Sru *ptr = start; 9375584Sru errno = ERANGE; 9475584Sru } 9575584Sru return 0; 9675584Sru } 9775584Sru if (neg) 9875584Sru val = -val; 9975584Sru 10075584Sru while (*++str != '\0') { 10175584Sru int n; 10275584Sru 10375584Sru p = strchr(digits, (ISASCII((unsigned char)*str) 10475584Sru && isupper((unsigned char)*str) 10575584Sru ? tolower((unsigned char)*str) : *str)); 10675584Sru if (p == 0) 10775584Sru break; 10875584Sru n = p - digits; 10975584Sru if (n >= base) 11075584Sru break; 11175584Sru if (neg) { 11275584Sru if (-(unsigned long)val > (-(unsigned long)LONG_MIN - n)/base) { 11375584Sru val = LONG_MIN; 11475584Sru errno = ERANGE; 11575584Sru } 11675584Sru else 11775584Sru val = val*base - n; 11875584Sru } 11975584Sru else { 12075584Sru if (val > (LONG_MAX - n)/base) { 12175584Sru val = LONG_MAX; 12275584Sru errno = ERANGE; 12375584Sru } 12475584Sru else 12575584Sru val = val*base + n; 12675584Sru } 12775584Sru } 12875584Sru 12975584Sru if (ptr) 13075584Sru *ptr = str; 13175584Sru 13275584Sru return val; 13375584Sru} 134