File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lrzsz / lib / strtol.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Thu Oct 24 15:49:50 2019 UTC (4 years, 8 months ago) by misho
Branches: lrzsz, MAIN
CVS tags: v0_12_20p5, HEAD
lrzsz ver 0.12.20

    1: /* Copyright (C) 1991, 92, 94, 95, 96 Free Software Foundation, Inc.
    2: 
    3: NOTE: The canonical source of this file is maintained with the GNU C Library.
    4: Bugs can be reported to bug-glibc@prep.ai.mit.edu.
    5: 
    6: This program is free software; you can redistribute it and/or modify it
    7: under the terms of the GNU General Public License as published by the
    8: Free Software Foundation; either version 2, or (at your option) any
    9: later version.
   10: 
   11: This program is distributed in the hope that it will be useful,
   12: but WITHOUT ANY WARRANTY; without even the implied warranty of
   13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14: GNU General Public License for more details.
   15: 
   16: You should have received a copy of the GNU General Public License
   17: along with this program; if not, write to the Free Software
   18: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
   19: USA.  */
   20: 
   21: #ifdef HAVE_CONFIG_H
   22: # include <config.h>
   23: #endif
   24: 
   25: #ifdef _LIBC
   26: # define USE_NUMBER_GROUPING
   27: # define STDC_HEADERS
   28: # define HAVE_LIMITS_H
   29: #endif
   30: 
   31: #include <ctype.h>
   32: #include <errno.h>
   33: #ifndef errno
   34: extern int errno;
   35: #endif
   36: 
   37: #ifdef HAVE_LIMITS_H
   38: # include <limits.h>
   39: #endif
   40: 
   41: #ifdef STDC_HEADERS
   42: # include <stddef.h>
   43: # include <stdlib.h>
   44: #else
   45: # ifndef NULL
   46: #  define NULL 0
   47: # endif
   48: #endif
   49: 
   50: #ifdef USE_NUMBER_GROUPING
   51: # include "../locale/localeinfo.h"
   52: #endif
   53: 
   54: /* Nonzero if we are defining `strtoul' or `strtouq', operating on
   55:    unsigned integers.  */
   56: #ifndef UNSIGNED
   57: # define UNSIGNED 0
   58: # define INT LONG int
   59: #else
   60: # define INT unsigned LONG int
   61: #endif
   62: 
   63: /* Determine the name.  */
   64: #if UNSIGNED
   65: # ifdef USE_WIDE_CHAR
   66: #  ifdef QUAD
   67: #   define strtol wcstouq
   68: #  else
   69: #   define strtol wcstoul
   70: #  endif
   71: # else
   72: #  ifdef QUAD
   73: #   define strtol strtouq
   74: #  else
   75: #   define strtol strtoul
   76: #  endif
   77: # endif
   78: #else
   79: # ifdef USE_WIDE_CHAR
   80: #  ifdef QUAD
   81: #   define strtol wcstoq
   82: #  else
   83: #   define strtol wcstol
   84: #  endif
   85: # else
   86: #  ifdef QUAD
   87: #   define strtol strtoq
   88: #  endif
   89: # endif
   90: #endif
   91: 
   92: /* If QUAD is defined, we are defining `strtoq' or `strtouq',
   93:    operating on `long long int's.  */
   94: #ifdef QUAD
   95: # define LONG long long
   96: # undef LONG_MIN
   97: # define LONG_MIN LONG_LONG_MIN
   98: # undef LONG_MAX
   99: # define LONG_MAX LONG_LONG_MAX
  100: # undef ULONG_MAX
  101: # define ULONG_MAX ULONG_LONG_MAX
  102: # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
  103:    /* Work around gcc bug with using this constant.  */
  104:    static const unsigned long long int maxquad = ULONG_LONG_MAX;
  105: #  undef ULONG_MAX
  106: #  define ULONG_MAX maxquad
  107: # endif
  108: #else
  109: # define LONG long
  110: 
  111: #ifndef ULONG_MAX
  112: # define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
  113: #endif
  114: #ifndef LONG_MAX
  115: # define LONG_MAX ((long int) (ULONG_MAX >> 1))
  116: #endif
  117: #endif
  118: 
  119: #ifdef USE_WIDE_CHAR
  120: # include <wchar.h>
  121: # include <wctype.h>
  122: # define L_(ch) L##ch
  123: # define UCHAR_TYPE wint_t
  124: # define STRING_TYPE wchar_t
  125: # define ISSPACE(ch) iswspace (ch)
  126: # define ISALPHA(ch) iswalpha (ch)
  127: # define TOUPPER(ch) towupper (ch)
  128: #else
  129: # define L_(ch) ch
  130: # define UCHAR_TYPE unsigned char
  131: # define STRING_TYPE char
  132: # define ISSPACE(ch) isspace (ch)
  133: # define ISALPHA(ch) isalpha (ch)
  134: # define TOUPPER(ch) toupper (ch)
  135: #endif
  136: 
  137: #ifdef __STDC__
  138: # define INTERNAL(x) INTERNAL1(x)
  139: # define INTERNAL1(x) __##x##_internal
  140: # define WEAKNAME(x) WEAKNAME1(x)
  141: # define WEAKNAME1(x) __##x
  142: #else
  143: # define INTERNAL(x) __/**/x/**/_internal
  144: # define WEAKNAME(x) __/**/x
  145: #endif
  146: 
  147: #ifdef USE_NUMBER_GROUPING
  148: /* This file defines a function to check for correct grouping.  */
  149: # include "grouping.h"
  150: #endif
  151: 
  152: 
  153: /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
  154:    If BASE is 0 the base is determined by the presence of a leading
  155:    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
  156:    If BASE is < 2 or > 36, it is reset to 10.
  157:    If ENDPTR is not NULL, a pointer to the character after the last
  158:    one converted is stored in *ENDPTR.  */
  159: 
  160: INT
  161: INTERNAL (strtol) (nptr, endptr, base, group)
  162:      const STRING_TYPE *nptr;
  163:      STRING_TYPE **endptr;
  164:      int base;
  165:      int group;
  166: {
  167:   int negative;
  168:   register unsigned LONG int cutoff;
  169:   register unsigned int cutlim;
  170:   register unsigned LONG int i;
  171:   register const STRING_TYPE *s;
  172:   register UCHAR_TYPE c;
  173:   const STRING_TYPE *save, *end;
  174:   int overflow;
  175: 
  176: #ifdef USE_NUMBER_GROUPING
  177:   /* The thousands character of the current locale.  */
  178:   wchar_t thousands;
  179:   /* The numeric grouping specification of the current locale,
  180:      in the format described in <locale.h>.  */
  181:   const char *grouping;
  182: 
  183:   if (group)
  184:     {
  185:       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
  186:       if (*grouping <= 0 || *grouping == CHAR_MAX)
  187: 	grouping = NULL;
  188:       else
  189: 	{
  190: 	  /* Figure out the thousands separator character.  */
  191: 	  if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
  192: 		      strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
  193: 	    thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
  194: 	  if (thousands == L'\0')
  195: 	    grouping = NULL;
  196: 	}
  197:     }
  198:   else
  199:     grouping = NULL;
  200: #endif
  201: 
  202:   if (base < 0 || base == 1 || base > 36)
  203:     base = 10;
  204: 
  205:   save = s = nptr;
  206: 
  207:   /* Skip white space.  */
  208:   while (ISSPACE (*s))
  209:     ++s;
  210:   if (*s == L_('\0'))
  211:     goto noconv;
  212: 
  213:   /* Check for a sign.  */
  214:   if (*s == L_('-'))
  215:     {
  216:       negative = 1;
  217:       ++s;
  218:     }
  219:   else if (*s == L_('+'))
  220:     {
  221:       negative = 0;
  222:       ++s;
  223:     }
  224:   else
  225:     negative = 0;
  226: 
  227:   if (base == 16 && s[0] == L_('0') && TOUPPER (s[1]) == L_('X'))
  228:     s += 2;
  229: 
  230:   /* If BASE is zero, figure it out ourselves.  */
  231:   if (base == 0)
  232:     if (*s == L_('0'))
  233:       {
  234: 	if (TOUPPER (s[1]) == L_('X'))
  235: 	  {
  236: 	    s += 2;
  237: 	    base = 16;
  238: 	  }
  239: 	else
  240: 	  base = 8;
  241:       }
  242:     else
  243:       base = 10;
  244: 
  245:   /* Save the pointer so we can check later if anything happened.  */
  246:   save = s;
  247: 
  248: #ifdef USE_NUMBER_GROUPING
  249:   if (group)
  250:     {
  251:       /* Find the end of the digit string and check its grouping.  */
  252:       end = s;
  253:       for (c = *end; c != L_('\0'); c = *++end)
  254: 	if (c != thousands && (c < L_('0') || c > L_('9'))
  255: 	    && (!ISALPHA (c) || TOUPPER (c) - L_('A') + 10 >= base))
  256: 	  break;
  257:       if (*s == thousands)
  258: 	end = s;
  259:       else
  260: 	end = correctly_grouped_prefix (s, end, thousands, grouping);
  261:     }
  262:   else
  263: #endif
  264:     end = NULL;
  265: 
  266:   cutoff = ULONG_MAX / (unsigned LONG int) base;
  267:   cutlim = ULONG_MAX % (unsigned LONG int) base;
  268: 
  269:   overflow = 0;
  270:   i = 0;
  271:   for (c = *s; c != L_('\0'); c = *++s)
  272:     {
  273:       if (s == end)
  274: 	break;
  275:       if (c >= L_('0') && c <= L_('9'))
  276: 	c -= L_('0');
  277:       else if (ISALPHA (c))
  278: 	c = TOUPPER (c) - L_('A') + 10;
  279:       else
  280: 	break;
  281:       if (c >= base)
  282: 	break;
  283:       /* Check for overflow.  */
  284:       if (i > cutoff || (i == cutoff && c > cutlim))
  285: 	overflow = 1;
  286:       else
  287: 	{
  288: 	  i *= (unsigned LONG int) base;
  289: 	  i += c;
  290: 	}
  291:     }
  292: 
  293:   /* Check if anything actually happened.  */
  294:   if (s == save)
  295:     goto noconv;
  296: 
  297:   /* Store in ENDPTR the address of one character
  298:      past the last character we converted.  */
  299:   if (endptr != NULL)
  300:     *endptr = (STRING_TYPE *) s;
  301: 
  302: #if !UNSIGNED
  303:   /* Check for a value that is within the range of
  304:      `unsigned LONG int', but outside the range of `LONG int'.  */
  305:   if (overflow == 0
  306:       && i > (negative
  307: 	      ? -((unsigned LONG int) (LONG_MIN + 1)) + 1
  308: 	      : (unsigned LONG int) LONG_MAX))
  309:     overflow = 1;
  310: #endif
  311: 
  312:   if (overflow)
  313:     {
  314:       errno = ERANGE;
  315: #if UNSIGNED
  316:       return ULONG_MAX;
  317: #else
  318:       return negative ? LONG_MIN : LONG_MAX;
  319: #endif
  320:     }
  321: 
  322:   /* Return the result of the appropriate sign.  */
  323:   return (negative ? -i : i);
  324: 
  325: noconv:
  326:   /* We must handle a special case here: the base is 0 or 16 and the
  327:      first two characters and '0' and 'x', but the rest are no
  328:      hexadecimal digits.  This is no error case.  We return 0 and
  329:      ENDPTR points to the `x`.  */
  330:   if (endptr != NULL)
  331:     if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
  332: 	&& save[-2] == L_('0'))
  333:       *endptr = (STRING_TYPE *) &save[-1];
  334:     else
  335:       /*  There was no number to convert.  */
  336:       *endptr = (STRING_TYPE *) nptr;
  337: 
  338:   return 0L;
  339: }
  340: 
  341: /* External user entry point.  */
  342: 
  343: #undef __P
  344: #if defined (__STDC__) && __STDC__
  345: #define __P(args) args
  346: #else
  347: #define __P(args) ()
  348: #endif
  349: 
  350: /* Prototype.  */
  351: INT strtol __P ((const STRING_TYPE *nptr, STRING_TYPE **endptr,
  352: 			    int base));
  353: 
  354: 
  355: INT
  356: strtol (nptr, endptr, base)
  357:      const STRING_TYPE *nptr;
  358:      STRING_TYPE **endptr;
  359:      int base;
  360: {
  361:   return INTERNAL (strtol) (nptr, endptr, base, 0);
  362: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>