Back to index

glibc  2.9
Defines | Functions | Variables
strtol_l.c File Reference
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <xlocale.h>
#include <bits/wordsize.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define __set_errno(Val)   errno = (Val)
#define UNSIGNED   0
#define INT   LONG int
#define strtol_l   strtol_l
#define __strtol_l   __strtol_l2(strtol_l)
#define __strtol_l2(name)   __strtol_l3(name)
#define __strtol_l3(name)   __##name
#define LONG   long
#define ULONG_MAX   ((unsigned long int) ~(unsigned long int) 0)
#define LONG_MAX   ((long int) (ULONG_MAX >> 1))
#define STRTOL_LONG_MIN   LONG_MIN
#define STRTOL_LONG_MAX   LONG_MAX
#define STRTOL_ULONG_MAX   ULONG_MAX
#define _NL_CURRENT(category, item)   (current->values[_NL_ITEM_INDEX (item)].string)
#define _NL_CURRENT_WORD(category, item)   ((uint32_t) current->values[_NL_ITEM_INDEX (item)].word)
#define IN_CTYPE_DOMAIN(c)   1
#define L_(Ch)   Ch
#define UCHAR_TYPE   unsigned char
#define STRING_TYPE   char
#define ISSPACE(Ch)   __isspace_l ((Ch), loc)
#define ISALPHA(Ch)   __isalpha_l ((Ch), loc)
#define TOUPPER(Ch)   __toupper_l ((Ch), loc)
#define INTERNAL(X)   INTERNAL1(X)
#define INTERNAL1(X)   __##X##_internal
#define WEAKNAME(X)   WEAKNAME1(X)
#define DEF(TYPE, NAME)
#define F(X)   ULONG_MAX / X
#define F(X)   ULONG_MAX % X
#define jmax_tab   __strtol_ul_max_tab
#define cutoff_tab   __strtol_ul_max_tab
#define cutlim_tab   __strtol_ul_rem_tab
#define PARAMS(Args)   ()

Functions

 DEF (unsigned long, __strtol_ul_max_tab)
 DEF (unsigned char, __strtol_ul_rem_tab)
INT INTERNAL() __strtol_l (STRING_TYPE *nptr, STRING_TYPE **endptr, int base, int group, __locale_t loc) const
INT __strtol_l PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base))
INT __strtol_l (STRING_TYPE *nptr, STRING_TYPE **endptr, int base, __locale_t loc) const

Variables

const unsigned long
__strtol_ul_max_tab[] 
attribute_hidden

Define Documentation

#define __set_errno (   Val)    errno = (Val)

Definition at line 35 of file strtol_l.c.

Definition at line 93 of file strtol_l.c.

#define __strtol_l2 (   name)    __strtol_l3(name)

Definition at line 94 of file strtol_l.c.

#define __strtol_l3 (   name)    __##name

Definition at line 95 of file strtol_l.c.

#define _NL_CURRENT (   category,
  item 
)    (current->values[_NL_ITEM_INDEX (item)].string)

Definition at line 125 of file strtol_l.c.

#define _NL_CURRENT_WORD (   category,
  item 
)    ((uint32_t) current->values[_NL_ITEM_INDEX (item)].word)

Definition at line 128 of file strtol_l.c.

#define cutlim_tab   __strtol_ul_rem_tab

Definition at line 214 of file strtol_l.c.

#define cutoff_tab   __strtol_ul_max_tab

Definition at line 213 of file strtol_l.c.

#define DEF (   TYPE,
  NAME 
)
Value:
const TYPE NAME[] attribute_hidden =                                     \
  {                                                               \
    F(2), F(3), F(4), F(5), F(6), F(7), F(8), F(9), F(10),               \
    F(11), F(12), F(13), F(14), F(15), F(16), F(17), F(18), F(19), F(20),  \
    F(21), F(22), F(23), F(24), F(25), F(26), F(27), F(28), F(29), F(30),  \
    F(31), F(32), F(33), F(34), F(35), F(36)                             \
  }

Definition at line 178 of file strtol_l.c.

#define F (   X)    ULONG_MAX / X

Definition at line 191 of file strtol_l.c.

#define F (   X)    ULONG_MAX % X

Definition at line 191 of file strtol_l.c.

#define IN_CTYPE_DOMAIN (   c)    1

Definition at line 146 of file strtol_l.c.

#define INT   LONG int

Definition at line 57 of file strtol_l.c.

#define INTERNAL (   X)    INTERNAL1(X)

Definition at line 158 of file strtol_l.c.

#define INTERNAL1 (   X)    __##X##_internal

Definition at line 159 of file strtol_l.c.

#define ISALPHA (   Ch)    __isalpha_l ((Ch), loc)

Definition at line 154 of file strtol_l.c.

#define ISSPACE (   Ch)    __isspace_l ((Ch), loc)

Definition at line 153 of file strtol_l.c.

#define jmax_tab   __strtol_ul_max_tab

Definition at line 208 of file strtol_l.c.

#define L_ (   Ch)    Ch

Definition at line 150 of file strtol_l.c.

#define LONG   long

Definition at line 106 of file strtol_l.c.

#define LONG_MAX   ((long int) (ULONG_MAX >> 1))

Definition at line 112 of file strtol_l.c.

#define PARAMS (   Args)    ()

Definition at line 543 of file strtol_l.c.

#define STRING_TYPE   char

Definition at line 152 of file strtol_l.c.

#define strtol_l   strtol_l

Definition at line 88 of file strtol_l.c.

#define STRTOL_LONG_MAX   LONG_MAX

Definition at line 115 of file strtol_l.c.

#define STRTOL_LONG_MIN   LONG_MIN

Definition at line 114 of file strtol_l.c.

Definition at line 116 of file strtol_l.c.

#define TOUPPER (   Ch)    __toupper_l ((Ch), loc)

Definition at line 155 of file strtol_l.c.

#define UCHAR_TYPE   unsigned char

Definition at line 151 of file strtol_l.c.

#define ULONG_MAX   ((unsigned long int) ~(unsigned long int) 0)

Definition at line 109 of file strtol_l.c.

#define UNSIGNED   0

Definition at line 56 of file strtol_l.c.

#define WEAKNAME (   X)    WEAKNAME1(X)

Definition at line 160 of file strtol_l.c.


Function Documentation

INT INTERNAL() __strtol_l ( STRING_TYPE nptr,
STRING_TYPE **  endptr,
int  base,
int  group,
__locale_t  loc 
) const

Definition at line 226 of file strtol_l.c.

{
  int negative;
  register unsigned LONG int cutoff;
  register unsigned int cutlim;
  register unsigned LONG int i;
  register const STRING_TYPE *s;
  register UCHAR_TYPE c;
  const STRING_TYPE *save, *end;
  int overflow;
#ifndef USE_WIDE_CHAR
  size_t cnt;
#endif

#ifdef USE_NUMBER_GROUPING
  struct locale_data *current = loc->__locales[LC_NUMERIC];
  /* The thousands character of the current locale.  */
# ifdef USE_WIDE_CHAR
  wchar_t thousands = L'\0';
# else
  const char *thousands = NULL;
  size_t thousands_len = 0;
# endif
  /* The numeric grouping specification of the current locale,
     in the format described in <locale.h>.  */
  const char *grouping;

  if (__builtin_expect (group, 0))
    {
      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
      if (*grouping <= 0 || *grouping == CHAR_MAX)
       grouping = NULL;
      else
       {
         /* Figure out the thousands separator character.  */
# ifdef USE_WIDE_CHAR
#  ifdef _LIBC
         thousands = _NL_CURRENT_WORD (LC_NUMERIC,
                                   _NL_NUMERIC_THOUSANDS_SEP_WC);
#  endif
         if (thousands == L'\0')
           grouping = NULL;
# else
#  ifdef _LIBC
         thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
#  endif
         if (*thousands == '\0')
           {
             thousands = NULL;
             grouping = NULL;
           }
# endif
       }
    }
  else
    grouping = NULL;
#endif

  if (base < 0 || base == 1 || base > 36)
    {
      __set_errno (EINVAL);
      return 0;
    }

  save = s = nptr;

  /* Skip white space.  */
  while (ISSPACE (*s))
    ++s;
  if (__builtin_expect (*s == L_('\0'), 0))
    goto noconv;

  /* Check for a sign.  */
  negative = 0;
  if (*s == L_('-'))
    {
      negative = 1;
      ++s;
    }
  else if (*s == L_('+'))
    ++s;

  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
  if (*s == L_('0'))
    {
      if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
       {
         s += 2;
         base = 16;
       }
      else if (base == 0)
       base = 8;
    }
  else if (base == 0)
    base = 10;

  /* Save the pointer so we can check later if anything happened.  */
  save = s;

#ifdef USE_NUMBER_GROUPING
  if (base != 10)
    grouping = NULL;

  if (__builtin_expect (grouping != NULL, 0))
    {
# ifndef USE_WIDE_CHAR
      thousands_len = strlen (thousands);
# endif

      /* Find the end of the digit string and check its grouping.  */
      end = s;
      if (
# ifdef USE_WIDE_CHAR
         *s != thousands
# else
         ({ for (cnt = 0; cnt < thousands_len; ++cnt)
              if (thousands[cnt] != end[cnt])
               break;
            cnt < thousands_len; })
# endif
         )
       {
         for (c = *end; c != L_('\0'); c = *++end)
           if (((STRING_TYPE) c < L_('0') || (STRING_TYPE) c > L_('9'))
# ifdef USE_WIDE_CHAR
              && (wchar_t) c != thousands
# else
              && ({ for (cnt = 0; cnt < thousands_len; ++cnt)
                    if (thousands[cnt] != end[cnt])
                     break;
                    cnt < thousands_len; })
# endif
              && (!ISALPHA (c)
                  || (int) (TOUPPER (c) - L_('A') + 10) >= base))
             break;

# ifdef USE_WIDE_CHAR
         end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
# else
         end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
# endif
       }
    }
  else
#endif
    end = NULL;

  /* Avoid runtime division; lookup cutoff and limit.  */
  cutoff = cutoff_tab[base - 2];
  cutlim = cutlim_tab[base - 2];

  overflow = 0;
  i = 0;
  c = *s;
  if (sizeof (long int) != sizeof (LONG int))
    {
      unsigned long int j = 0;
      unsigned long int jmax = jmax_tab[base - 2];

      for (;c != L_('\0'); c = *++s)
       {
         if (s == end)
           break;
         if (c >= L_('0') && c <= L_('9'))
           c -= L_('0');
#ifdef USE_NUMBER_GROUPING
# ifdef USE_WIDE_CHAR
         else if (grouping && (wchar_t) c == thousands)
           continue;
# else
         else if (thousands_len)
           {
             for (cnt = 0; cnt < thousands_len; ++cnt)
              if (thousands[cnt] != s[cnt])
                break;
             if (cnt == thousands_len)
              {
                s += thousands_len - 1;
                continue;
              }
             if (ISALPHA (c))
              c = TOUPPER (c) - L_('A') + 10;
             else
              break;
           }
# endif
#endif
         else if (ISALPHA (c))
           c = TOUPPER (c) - L_('A') + 10;
         else
           break;
         if ((int) c >= base)
           break;
         /* Note that we never can have an overflow.  */
         else if (j >= jmax)
           {
             /* We have an overflow.  Now use the long representation.  */
             i = (unsigned LONG int) j;
             goto use_long;
           }
         else
           j = j * (unsigned long int) base + c;
       }

      i = (unsigned LONG int) j;
    }
  else
    for (;c != L_('\0'); c = *++s)
      {
       if (s == end)
         break;
       if (c >= L_('0') && c <= L_('9'))
         c -= L_('0');
#ifdef USE_NUMBER_GROUPING
# ifdef USE_WIDE_CHAR
       else if (grouping && (wchar_t) c == thousands)
         continue;
# else
       else if (thousands_len)
         {
           for (cnt = 0; cnt < thousands_len; ++cnt)
             if (thousands[cnt] != s[cnt])
              break;
           if (cnt == thousands_len)
             {
              s += thousands_len - 1;
              continue;
             }
           if (ISALPHA (c))
             c = TOUPPER (c) - L_('A') + 10;
           else
             break;
         }
# endif
#endif
       else if (ISALPHA (c))
         c = TOUPPER (c) - L_('A') + 10;
       else
         break;
       if ((int) c >= base)
         break;
       /* Check for overflow.  */
       if (i > cutoff || (i == cutoff && c > cutlim))
         overflow = 1;
       else
         {
         use_long:
           i *= (unsigned LONG int) base;
           i += c;
         }
      }

  /* Check if anything actually happened.  */
  if (s == save)
    goto noconv;

  /* Store in ENDPTR the address of one character
     past the last character we converted.  */
  if (endptr != NULL)
    *endptr = (STRING_TYPE *) s;

#if !UNSIGNED
  /* Check for a value that is within the range of
     `unsigned LONG int', but outside the range of `LONG int'.  */
  if (overflow == 0
      && i > (negative
             ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
             : (unsigned LONG int) STRTOL_LONG_MAX))
    overflow = 1;
#endif

  if (__builtin_expect (overflow, 0))
    {
      __set_errno (ERANGE);
#if UNSIGNED
      return STRTOL_ULONG_MAX;
#else
      return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
#endif
    }

  /* Return the result of the appropriate sign.  */
  return negative ? -i : i;

noconv:
  /* We must handle a special case here: the base is 0 or 16 and the
     first two characters are '0' and 'x', but the rest are no
     hexadecimal digits.  This is no error case.  We return 0 and
     ENDPTR points to the `x`.  */
  if (endptr != NULL)
    {
      if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
         && save[-2] == L_('0'))
       *endptr = (STRING_TYPE *) &save[-1];
      else
       /*  There was no number to convert.  */
       *endptr = (STRING_TYPE *) nptr;
    }

  return 0L;
}

Here is the call graph for this function:

INT __strtol_l ( STRING_TYPE nptr,
STRING_TYPE **  endptr,
int  base,
__locale_t  loc 
) const

Definition at line 556 of file strtol_l.c.

{
  return INTERNAL (__strtol_l) (nptr, endptr, base, 0, loc);
}
DEF ( unsigned  long,
__strtol_ul_max_tab   
)
DEF ( unsigned  char,
__strtol_ul_rem_tab   
)

Variable Documentation

const unsigned char __strtol_ul_rem_tab [] attribute_hidden

Definition at line 172 of file strtol_l.c.