Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

strtol.c

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1990 The Regents of the University of California.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. All advertising materials mentioning features or use of this software
00014  *    must display the following acknowledgement:
00015  *      This product includes software developed by the University of
00016  *      California, Berkeley and its contributors.
00017  * 4. Neither the name of the University nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *  
00033  * CHANGELOG: this file has been modified by Sergio Perez Alcañiz <serpeal@disca.upv.es> 
00034  *            Departamento de Informática de Sistemas y Computadores          
00035  *            Universidad Politécnica de Valencia                             
00036  *            Valencia (Spain)    
00037  *            Date: March 2003                                          
00038  *            
00039  */
00040 
00041 #include  <ctype.h>
00042 #include  <errno.h>
00043 #include  <limits.h>
00044 
00045 /*
00046  * Convert a string to a long integer.
00047  *
00048  * Ignores `locale' stuff.  Assumes that the upper and lower case
00049  * alphabets and digits are each contiguous.
00050  */
00051 /*  */
00052 /* strtol */
00053 long strtol(const char *nptr, char **endptr,register int base)
00054 {
00055         register const char *s;
00056         register long acc, cutoff;
00057         register int c;
00058         register int neg, any, cutlim;
00059 
00060         /*
00061          * Skip white space and pick up leading +/- sign if any.
00062          * If base is 0, allow 0x for hex and 0 for octal, else
00063          * assume decimal; if base is already 16, allow 0x.
00064          */
00065         s = nptr;
00066         do {
00067                 c = (unsigned char) *s++;
00068         } while (isspace(c));
00069         if (c == '-') {
00070                 neg = 1;
00071                 c = *s++;
00072         } else {
00073                 neg = 0;
00074                 if (c == '+')
00075                         c = *s++;
00076         }
00077         if ((base == 0 || base == 16) &&
00078             c == '0' && (*s == 'x' || *s == 'X')) {
00079                 c = s[1];
00080                 s += 2;
00081                 base = 16;
00082         }
00083         if (base == 0)
00084                 base = c == '0' ? 8 : 10;
00085 
00086         /*
00087          * Compute the cutoff value between legal numbers and illegal
00088          * numbers.  That is the largest legal value, divided by the
00089          * base.  An input number that is greater than this value, if
00090          * followed by a legal input character, is too big.  One that
00091          * is equal to this value may be valid or not; the limit
00092          * between valid and invalid numbers is then based on the last
00093          * digit.  For instance, if the range for longs is
00094          * [-2147483648..2147483647] and the input base is 10,
00095          * cutoff will be set to 214748364 and cutlim to either
00096          * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
00097          * a value > 214748364, or equal but the next digit is > 7 (or 8),
00098          * the number is too big, and we will return a range error.
00099          *
00100          * Set any if any `digits' consumed; make it negative to indicate
00101          * overflow.
00102          */
00103         cutoff = neg ? LONG_MIN : LONG_MAX;
00104         cutlim = cutoff % base;
00105         cutoff /= base;
00106         if (neg) {
00107                 if (cutlim > 0) {
00108                         cutlim -= base;
00109                         cutoff += 1;
00110                 }
00111                 cutlim = -cutlim;
00112         }
00113         for (acc = 0, any = 0;; c = (unsigned char) *s++) {
00114                 if (isdigit(c))
00115                         c -= '0';
00116                 else if (isalpha(c))
00117                         c -= isupper(c) ? 'A' - 10 : 'a' - 10;
00118                 else
00119                         break;
00120                 if (c >= base)
00121                         break;
00122                 if (any < 0)
00123                         continue;
00124                 if (neg) {
00125                         if ((acc < cutoff || acc == cutoff) && c > cutlim) {
00126                                 any = -1;
00127                                 acc = LONG_MIN;
00128                                 errno = ERANGE;
00129                         } else {
00130                                 any = 1;
00131                                 acc *= base;
00132                                 acc -= c;
00133                         }
00134                 } else {
00135                         if ((acc > cutoff || acc == cutoff) && c > cutlim) {
00136                                 any = -1;
00137                                 acc = LONG_MAX;
00138                                 errno = ERANGE;
00139                         } else {
00140                                 any = 1;
00141                                 acc *= base;
00142                                 acc += c;
00143                         }
00144                 }
00145         }
00146         if (endptr != 0)
00147                 *endptr = (char *) (any ? s - 1 : nptr);
00148         return (acc);
00149 }

Generated on Wed Jan 14 12:58:57 2004 for RTL-lwIP-0.4 by doxygen 1.3.4