Back to index

tetex-bin  3.0
Defines | Functions | Variables
strtol.c File Reference
#include <ctype.h>
#include <errno.h>

Go to the source code of this file.

Defines

#define NULL   0
#define UNSIGNED   0
#define INT   LONG int
#define LONG   long
#define INTERNAL(x)   __x_internal

Functions

INT INTERNAL() strtol (char *nptr, char **endptr, int base, int group) const
INT strtol (char *nptr, char **endptr, int base) const

Variables

int errno

Define Documentation

#define INT   LONG int

Definition at line 57 of file strtol.c.

#define INTERNAL (   x)    __x_internal

Definition at line 92 of file strtol.c.

#define LONG   long

Definition at line 85 of file strtol.c.

#define NULL   0

Definition at line 45 of file strtol.c.

#define UNSIGNED   0

Definition at line 56 of file strtol.c.


Function Documentation

INT INTERNAL() strtol ( char *  nptr,
char **  endptr,
int  base,
int  group 
) const

Definition at line 109 of file strtol.c.

{
  int negative;
  register unsigned LONG int cutoff;
  register unsigned int cutlim;
  register unsigned LONG int i;
  register const char *s;
  register unsigned char c;
  const char *save, *end;
  int overflow;

#ifdef USE_NUMBER_GROUPING
  /* The thousands character of the current locale.  */
  wchar_t thousands;
  /* The numeric grouping specification of the current locale,
     in the format described in <locale.h>.  */
  const char *grouping;

  if (group)
    {
      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
      if (*grouping <= 0 || *grouping == CHAR_MAX)
       grouping = NULL;
      else
       {
         /* Figure out the thousands separator character.  */
         if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
                    strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
           thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
         if (thousands == L'\0')
           grouping = NULL;
       }
    }
  else
    grouping = NULL;
#endif

  if (base < 0 || base == 1 || base > 36)
    base = 10;

  s = nptr;

  /* Skip white space.  */
  while (isspace (*s))
    ++s;
  if (*s == '\0')
    goto noconv;

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

  if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
    s += 2;

  /* If BASE is zero, figure it out ourselves.  */
  if (base == 0)
    if (*s == '0')
      {
       if (toupper (s[1]) == 'X')
         {
           s += 2;
           base = 16;
         }
       else
         base = 8;
      }
    else
      base = 10;

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

#ifdef USE_NUMBER_GROUPING
  if (group)
    {
      /* Find the end of the digit string and check its grouping.  */
      end = s;
      for (c = *end; c != '\0'; c = *++end)
       if (c != thousands && !isdigit (c) &&
           (!isalpha (c) || toupper (c) - 'A' + 10 >= base))
         break;
      if (*s == thousands)
       end = s;
      else
       end = correctly_grouped_prefix (s, end, thousands, grouping);
    }
  else
#endif
    end = NULL;

  cutoff = ULONG_MAX / (unsigned LONG int) base;
  cutlim = ULONG_MAX % (unsigned LONG int) base;

  overflow = 0;
  i = 0;
  for (c = *s; c != '\0'; c = *++s)
    {
      if (s == end)
       break;
      if (isdigit (c))
       c -= '0';
      else if (isalpha (c))
       c = toupper (c) - 'A' + 10;
      else
       break;
      if (c >= base)
       break;
      /* Check for overflow.  */
      if (i > cutoff || (i == cutoff && c > cutlim))
       overflow = 1;
      else
       {
         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 = (char *) s;

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

  if (overflow)
    {
      errno = ERANGE;
#if UNSIGNED
      return ULONG_MAX;
#else
      return negative ? LONG_MIN : LONG_MAX;
#endif
    }

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

noconv:
  /* There was no number to convert.  */
  if (endptr != NULL)
    *endptr = (char *) nptr;
  return 0L;
}

Here is the call graph for this function:

Here is the caller graph for this function:

INT strtol ( char *  nptr,
char **  endptr,
int  base 
) const

Definition at line 285 of file strtol.c.

{
  return INTERNAL (strtol) (nptr, endptr, base, 0);
}

Here is the call graph for this function:


Variable Documentation