home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21fs.zip / octave / kpathsea / strtol.c < prev    next >
C/C++ Source or Header  |  2000-01-15  |  7KB  |  300 lines

  1. /* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
  2.  
  3. This file is part of the GNU C Library.
  4.  
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public License as
  7. published by the Free Software Foundation; either version 2 of the
  8. License, or (at your option) any later version.
  9.  
  10. The GNU C Library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. Library General Public License for more details.
  14.  
  15. You should have received a copy of the GNU Library General Public
  16. License along with the GNU C Library; see the file COPYING.LIB.  If
  17. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  18. Cambridge, MA 02139, USA.  */
  19.  
  20. /* Modified by Klaus Gebhardt, 1999 */
  21.  
  22.  
  23. #include <config.h>
  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 strtol strtoul
  61. # define INT unsigned LONG int
  62. #endif
  63.  
  64. /* If QUAD is defined, we are defining `strtoq' or `strtouq',
  65.    operating on `long long int's.  */
  66. #ifdef QUAD
  67. # if UNSIGNED
  68. #  define strtoul strtouq
  69. # else
  70. #  define strtol strtoq
  71. # endif
  72. # define LONG long long
  73. # undef LONG_MIN
  74. # define LONG_MIN LONG_LONG_MIN
  75. # undef LONG_MAX
  76. # define LONG_MAX LONG_LONG_MAX
  77. # undef ULONG_MAX
  78. # define ULONG_MAX ULONG_LONG_MAX
  79. # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
  80.    /* Work around gcc bug with using this constant.  */
  81.    static const unsigned long long int maxquad = ULONG_LONG_MAX;
  82. #  undef ULONG_MAX
  83. #  define ULONG_MAX maxquad
  84. # endif
  85. #else
  86. # define LONG long
  87. #endif
  88.  
  89. #ifdef __STDC__
  90. # define INTERNAL(x) INTERNAL1(x)
  91. # define INTERNAL1(x) __##x##_internal
  92. #else
  93. # define INTERNAL(x) __/**/x/**/_internal
  94. #endif
  95.  
  96. #ifdef USE_NUMBER_GROUPING
  97. /* This file defines a function to check for correct grouping.  */
  98. # include "grouping.h"
  99. #endif
  100.  
  101.  
  102. /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
  103.    If BASE is 0 the base is determined by the presence of a leading
  104.    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
  105.    If BASE is < 2 or > 36, it is reset to 10.
  106.    If ENDPTR is not NULL, a pointer to the character after the last
  107.    one converted is stored in *ENDPTR.  */
  108.  
  109. INT
  110. INTERNAL (strtol) (nptr, endptr, base, group)
  111.      const char *nptr;
  112.      char **endptr;
  113.      int base;
  114.      int group;
  115. {
  116.   int negative;
  117.   register unsigned LONG int cutoff;
  118.   register unsigned int cutlim;
  119.   register unsigned LONG int i;
  120.   register const char *s;
  121.   register unsigned char c;
  122.   const char *save, *end;
  123.   int overflow;
  124.  
  125. #ifdef USE_NUMBER_GROUPING
  126.   /* The thousands character of the current locale.  */
  127.   wchar_t thousands;
  128.   /* The numeric grouping specification of the current locale,
  129.      in the format described in <locale.h>.  */
  130.   const char *grouping;
  131.  
  132.   if (group)
  133.     {
  134.       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
  135.       if (*grouping <= 0 || *grouping == CHAR_MAX)
  136.     grouping = NULL;
  137.       else
  138.     {
  139.       /* Figure out the thousands separator character.  */
  140.       if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
  141.               strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
  142.         thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
  143.       if (thousands == L'\0')
  144.         grouping = NULL;
  145.     }
  146.     }
  147.   else
  148.     grouping = NULL;
  149. #endif
  150.  
  151.   if (base < 0 || base == 1 || base > 36)
  152.     base = 10;
  153.  
  154.   s = nptr;
  155.  
  156.   /* Skip white space.  */
  157. #ifdef EMX09D
  158.   while (isspace ((int) *s))
  159. #else
  160.   while (isspace (*s))
  161. #endif
  162.     ++s;
  163.   if (*s == '\0')
  164.     goto noconv;
  165.  
  166.   /* Check for a sign.  */
  167.   if (*s == '-')
  168.     {
  169.       negative = 1;
  170.       ++s;
  171.     }
  172.   else if (*s == '+')
  173.     {
  174.       negative = 0;
  175.       ++s;
  176.     }
  177.   else
  178.     negative = 0;
  179.  
  180.   if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
  181.     s += 2;
  182.  
  183.   /* If BASE is zero, figure it out ourselves.  */
  184.   /* Braces added ... Klaus Gebhardt, 19.04.1999 */
  185.   if (base == 0)
  186.     {
  187.       if (*s == '0')
  188.     {
  189.       if (toupper (s[1]) == 'X')
  190.         {
  191.           s += 2;
  192.           base = 16;
  193.         }
  194.       else
  195.         base = 8;
  196.     }
  197.       else
  198.     base = 10;
  199.     }
  200.  
  201.   /* Save the pointer so we can check later if anything happened.  */
  202.   save = s;
  203.  
  204. #ifdef USE_NUMBER_GROUPING
  205.   if (group)
  206.     {
  207.       /* Find the end of the digit string and check its grouping.  */
  208.       end = s;
  209.       for (c = *end; c != '\0'; c = *++end)
  210.     if (c != thousands && !isdigit (c) &&
  211.         (!isalpha (c) || toupper (c) - 'A' + 10 >= base))
  212.       break;
  213.       if (*s == thousands)
  214.     end = s;
  215.       else
  216.     end = correctly_grouped_prefix (s, end, thousands, grouping);
  217.     }
  218.   else
  219. #endif
  220.     end = NULL;
  221.  
  222.   cutoff = ULONG_MAX / (unsigned LONG int) base;
  223.   cutlim = ULONG_MAX % (unsigned LONG int) base;
  224.  
  225.   overflow = 0;
  226.   i = 0;
  227.   for (c = *s; c != '\0'; c = *++s)
  228.     {
  229.       if (s == end)
  230.     break;
  231.       if (isdigit (c))
  232.     c -= '0';
  233.       else if (isalpha (c))
  234.     c = toupper (c) - 'A' + 10;
  235.       else
  236.     break;
  237.       if (c >= base)
  238.     break;
  239.       /* Check for overflow.  */
  240.       if (i > cutoff || (i == cutoff && c > cutlim))
  241.     overflow = 1;
  242.       else
  243.     {
  244.       i *= (unsigned LONG int) base;
  245.       i += c;
  246.     }
  247.     }
  248.  
  249.   /* Check if anything actually happened.  */
  250.   if (s == save)
  251.     goto noconv;
  252.  
  253.   /* Store in ENDPTR the address of one character
  254.      past the last character we converted.  */
  255.   if (endptr != NULL)
  256.     *endptr = (char *) s;
  257.  
  258. #if !UNSIGNED
  259.   /* Check for a value that is within the range of
  260.      `unsigned LONG int', but outside the range of `LONG int'.  */
  261.   if (i > (negative ?
  262.        -(unsigned LONG int) LONG_MIN : (unsigned LONG int) LONG_MAX))
  263.     overflow = 1;
  264. #endif
  265.  
  266.   if (overflow)
  267.     {
  268.       errno = ERANGE;
  269. #if UNSIGNED
  270.       return ULONG_MAX;
  271. #else
  272.       return negative ? LONG_MIN : LONG_MAX;
  273. #endif
  274.     }
  275.  
  276.   /* Return the result of the appropriate sign.  */
  277.   return (negative ? -i : i);
  278.  
  279. noconv:
  280.   /* There was no number to convert.  */
  281.   if (endptr != NULL)
  282.     *endptr = (char *) nptr;
  283.   return 0L;
  284. }
  285.  
  286. /* External user entry point.  */
  287.  
  288. #ifdef weak_symbol
  289. weak_symbol (strtol)
  290. #endif
  291.  
  292. INT
  293. strtol (nptr, endptr, base)
  294.      const char *nptr;
  295.      char **endptr;
  296.      int base;
  297. {
  298.   return INTERNAL (strtol) (nptr, endptr, base, 0);
  299. }
  300.