home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gettext-0.10.24-src.tgz / tar.out / fsf / gettext / lib / strtol.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  8KB  |  353 lines

  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. # include <string.h>
  45. #else
  46. # ifndef NULL
  47. #  define NULL 0
  48. # endif
  49. #endif
  50.  
  51. #ifdef USE_NUMBER_GROUPING
  52. # include "../locale/localeinfo.h"
  53. #endif
  54.  
  55. /* Nonzero if we are defining `strtoul' or `strtouq', operating on
  56.    unsigned integers.  */
  57. #ifndef UNSIGNED
  58. # define UNSIGNED 0
  59. # define INT LONG int
  60. #else
  61. # define INT unsigned LONG int
  62. #endif
  63.  
  64. /* Determine the name.  */
  65. #if UNSIGNED
  66. # ifdef USE_WIDE_CHAR
  67. #  ifdef QUAD
  68. #   define strtol wcstouq
  69. #  else
  70. #   define strtol wcstoul
  71. #  endif
  72. # else
  73. #  ifdef QUAD
  74. #   define strtol strtouq
  75. #  else
  76. #   define strtol strtoul
  77. #  endif
  78. # endif
  79. #else
  80. # ifdef USE_WIDE_CHAR
  81. #  ifdef QUAD
  82. #   define strtol wcstoq
  83. #  else
  84. #   define strtol wcstol
  85. #  endif
  86. # else
  87. #  ifdef QUAD
  88. #   define strtol strtoq
  89. #  endif
  90. # endif
  91. #endif
  92.  
  93. /* If QUAD is defined, we are defining `strtoq' or `strtouq',
  94.    operating on `long long int's.  */
  95. #ifdef QUAD
  96. # define LONG long long
  97. # undef LONG_MIN
  98. # define LONG_MIN LONG_LONG_MIN
  99. # undef LONG_MAX
  100. # define LONG_MAX LONG_LONG_MAX
  101. # undef ULONG_MAX
  102. # define ULONG_MAX ULONG_LONG_MAX
  103. # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
  104.    /* Work around gcc bug with using this constant.  */
  105.    static const unsigned long long int maxquad = ULONG_LONG_MAX;
  106. #  undef ULONG_MAX
  107. #  define ULONG_MAX maxquad
  108. # endif
  109. #else
  110. # define LONG long
  111.  
  112. #ifndef ULONG_MAX
  113. # define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
  114. #endif
  115. #ifndef LONG_MAX
  116. # define LONG_MAX ((long int) (ULONG_MAX >> 1))
  117. #endif
  118. #endif
  119.  
  120. #ifdef USE_WIDE_CHAR
  121. # include <wchar.h>
  122. # include <wctype.h>
  123. # define L_(ch) L##ch
  124. # define UCHAR_TYPE wint_t
  125. # define STRING_TYPE wchar_t
  126. # define ISSPACE(ch) iswspace (ch)
  127. # define ISALPHA(ch) iswalpha (ch)
  128. # define TOUPPER(ch) towupper (ch)
  129. #else
  130. # define L_(ch) ch
  131. # define UCHAR_TYPE unsigned char
  132. # define STRING_TYPE char
  133. # define ISSPACE(ch) isspace (ch)
  134. # define ISALPHA(ch) isalpha (ch)
  135. # define TOUPPER(ch) toupper (ch)
  136. #endif
  137.  
  138. #ifdef __STDC__
  139. # define INTERNAL(x) INTERNAL1(x)
  140. # define INTERNAL1(x) __##x##_internal
  141. # define WEAKNAME(x) WEAKNAME1(x)
  142. #else
  143. # define INTERNAL(x) __/**/x/**/_internal
  144. #endif
  145.  
  146. #ifdef USE_NUMBER_GROUPING
  147. /* This file defines a function to check for correct grouping.  */
  148. # include "grouping.h"
  149. #endif
  150.  
  151.  
  152. /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
  153.    If BASE is 0 the base is determined by the presence of a leading
  154.    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
  155.    If BASE is < 2 or > 36, it is reset to 10.
  156.    If ENDPTR is not NULL, a pointer to the character after the last
  157.    one converted is stored in *ENDPTR.  */
  158.  
  159. INT
  160. INTERNAL (strtol) (nptr, endptr, base, group)
  161.      const STRING_TYPE *nptr;
  162.      STRING_TYPE **endptr;
  163.      int base;
  164.      int group;
  165. {
  166.   int negative;
  167.   register unsigned LONG int cutoff;
  168.   register unsigned int cutlim;
  169.   register unsigned LONG int i;
  170.   register const STRING_TYPE *s;
  171.   register UCHAR_TYPE c;
  172.   const STRING_TYPE *save, *end;
  173.   int overflow;
  174.  
  175. #ifdef USE_NUMBER_GROUPING
  176.   /* The thousands character of the current locale.  */
  177.   wchar_t thousands;
  178.   /* The numeric grouping specification of the current locale,
  179.      in the format described in <locale.h>.  */
  180.   const char *grouping;
  181.  
  182.   if (group)
  183.     {
  184.       grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
  185.       if (*grouping <= 0 || *grouping == CHAR_MAX)
  186.     grouping = NULL;
  187.       else
  188.     {
  189.       /* Figure out the thousands separator character.  */
  190.       if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
  191.               strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
  192.         thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
  193.       if (thousands == L'\0')
  194.         grouping = NULL;
  195.     }
  196.     }
  197.   else
  198.     grouping = NULL;
  199. #endif
  200.  
  201.   if (base < 0 || base == 1 || base > 36)
  202.     base = 10;
  203.  
  204.   save = s = nptr;
  205.  
  206.   /* Skip white space.  */
  207.   while (ISSPACE (*s))
  208.     ++s;
  209.   if (*s == L_('\0'))
  210.     goto noconv;
  211.  
  212.   /* Check for a sign.  */
  213.   if (*s == L_('-'))
  214.     {
  215.       negative = 1;
  216.       ++s;
  217.     }
  218.   else if (*s == L_('+'))
  219.     {
  220.       negative = 0;
  221.       ++s;
  222.     }
  223.   else
  224.     negative = 0;
  225.  
  226.   if (base == 16 && s[0] == L_('0') && TOUPPER (s[1]) == L_('X'))
  227.     s += 2;
  228.  
  229.   /* If BASE is zero, figure it out ourselves.  */
  230.   if (base == 0)
  231.     if (*s == L_('0'))
  232.       {
  233.     if (TOUPPER (s[1]) == L_('X'))
  234.       {
  235.         s += 2;
  236.         base = 16;
  237.       }
  238.     else
  239.       base = 8;
  240.       }
  241.     else
  242.       base = 10;
  243.  
  244.   /* Save the pointer so we can check later if anything happened.  */
  245.   save = s;
  246.  
  247. #ifdef USE_NUMBER_GROUPING
  248.   if (group)
  249.     {
  250.       /* Find the end of the digit string and check its grouping.  */
  251.       end = s;
  252.       for (c = *end; c != L_('\0'); c = *++end)
  253.     if ((wchar_t) c != thousands
  254.         && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
  255.         && (!ISALPHA (c) || (int) (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 ((int) 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 are '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. INT
  343. #ifdef weak_function
  344. weak_function
  345. #endif
  346. strtol (nptr, endptr, base)
  347.      const STRING_TYPE *nptr;
  348.      STRING_TYPE **endptr;
  349.      int base;
  350. {
  351.   return INTERNAL (strtol) (nptr, endptr, base, 0);
  352. }
  353.