Main Page | Alphabetical List | Class List | File List | Class Members | File Members

strtol.h

Go to the documentation of this file.
00001 #ifndef __STRTOL_H__
00002 #define __STRTOL_H__
00003 
00004 #include <nlibc.h>
00005 
00045 #include <assert.h>
00046 #include <ctype.h>
00047 #include <errno.h>
00048 #include <limits.h>
00049 
00050 //---------------------------------------------------------------------------------------------
00110 #ifndef __HAS_MAIN
00111 extern long strtol(const char *nptr, char **endptr, int base);
00112 #else
00113 #if !defined(__cflow_processed) || defined(_uses_strtol_strtol_h)
00114 long strtol(const char *nptr, char **endptr, int base)
00115 {
00116         const char *s;
00117         long acc, cutoff;
00118         int c;
00119         int neg, any_consumed, cutlim;
00120         int len;
00121 
00122         assert(nptr != NULL);
00123         /* endptr may be NULL */
00124 
00125         /*
00126          * expand compacted string to char array for easy 
00127          * handling
00128          */
00129         len = strlen( nptr );
00130         s = stringexpand( nptr, len );
00131 
00132         /*
00133          * Skip white space and pick up leading +/- sign if any.
00134          * If base is 0, allow 0x for hex and 0 for octal, else
00135          * assume decimal; if base is already 16, allow 0x.
00136          */
00137         do {
00138                 c = (unsigned char) *s++;
00139         } while (isspace(c));
00140         if (c == '-') {
00141                 neg = 1;
00142                 c = *s++;
00143         } else {
00144                 neg = 0;
00145                 if (c == '+')
00146                         c = *s++;
00147         }
00148         if ((base == 0 || base == 16) &&
00149             c == '0' && (*s == 'x' || *s == 'X')) {
00150                 c = s[1];
00151                 s += 2;
00152                 base = 16;
00153         }
00154         if (base == 0)
00155                 base = c == '0' ? 8 : 10;
00156 
00157         /*
00158          * Compute the cutoff value between legal numbers and illegal
00159          * numbers.  That is the largest legal value, divided by the
00160          * base.  An input number that is greater than this value, if
00161          * followed by a legal input character, is too big.  One that
00162          * is equal to this value may be valid or not; the limit
00163          * between valid and invalid numbers is then based on the last
00164          * digit.  For instance, if the range for longs is
00165          * [-2147483648..2147483647] and the input base is 10,
00166          * cutoff will be set to 214748364 and cutlim to either
00167          * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
00168          * a value > 214748364, or equal but the next digit is > 7 (or 8),
00169          * the number is too big, and we will return a range error.
00170          *
00171          * Set any_consumed if any `digits' consumed; make it negative to indicate
00172          * overflow.
00173          */
00174         cutoff = neg ? LONG_MIN : LONG_MAX;
00175         cutlim = (int)(cutoff % base);
00176         cutoff /= base;
00177         if (neg) {
00178                 if (cutlim > 0) {
00179                         cutlim -= base;
00180                         cutoff += 1;
00181                 }
00182                 cutlim = -cutlim;
00183         }
00184         for (acc = 0, any_consumed = 0;; c = (unsigned char) *s++) {
00185                 if (isdigit(c))
00186                         c -= '0';
00187                 else if (isalpha(c))
00188                         c -= isupper(c) ? 'A' - 10 : 'a' - 10;
00189                 else
00190                         break;
00191                 if (c >= base)
00192                         break;
00193                 if (any_consumed < 0)
00194                         continue;
00195                 if (neg) {
00196                         if (acc < cutoff || (acc == cutoff && c > cutlim)) {
00197                                 any_consumed = -1;
00198                                 acc = LONG_MIN;
00199                                 errno = ERANGE;
00200                         } else {
00201                                 any_consumed = 1;
00202                                 acc *= base;
00203                                 acc -= c;
00204                         }
00205                 } else {
00206                         if (acc > cutoff || (acc == cutoff && c > cutlim)) {
00207                                 any_consumed = -1;
00208                                 acc = LONG_MAX;
00209                                 errno = ERANGE;
00210                         } else {
00211                                 any_consumed = 1;
00212                                 acc *= base;
00213                                 acc += c;
00214                         }
00215                 }
00216         }
00217         if (endptr != 0)
00218                 /* LINTED interface specification */
00219                 *endptr = (char *)(any_consumed ? s - 1 : nptr);
00220         return (acc);
00221 }
00222 #endif // _uses_strtol_strtol_h
00223 #endif // Has Main
00224 
00225 #define strtoll(nptr, endptr, base)  strtol(nptr, endptr, base)
00226 
00227 #endif // __STRTOL_H__

Generated on Fri Jul 14 10:51:32 2006 for nlibc by doxygen 1.3.5