Logo Search packages:      
Sourcecode: mingw-w64 version File versions  Download package

strtoimax.c
/**
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is part of the w64 mingw-runtime package.
 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
 */
/*
    This source code was extracted from the Q8 package created and
    placed in the PUBLIC DOMAIN by Doug Gwyn <gwyn@arl.mil>
    last edit:    1999/11/05  gwyn@arl.mil

      Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E).

      This particular implementation requires the matching <inttypes.h>.
      It also assumes that character codes for A..Z and a..z are in
      contiguous ascending order; this is true for ASCII but not EBCDIC.
*/
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <inttypes.h>

/* Helper macros */

/* convert digit character to number, in any base */
#define ToNumber(c)     (isdigit(c) ? (c) - '0' : \
                   isupper(c) ? (c) - 'A' + 10 : \
                   islower(c) ? (c) - 'a' + 10 : \
                   -1         /* "invalid" flag */ \
                  )
/* validate converted digit character for specific base */
#define valid(n, b)     ((n) >= 0 && (n) < (b))

intmax_t
strtoimax(nptr, endptr, base)
      register const char * __restrict__  nptr;
      char ** __restrict__                endptr;
      register int                        base;
      {
      register uintmax_t      accum;      /* accumulates converted value */
      register int            n;    /* numeral from digit character */
      int               minus;      /* set iff minus sign seen */
      int               toobig;     /* set iff value overflows */

      if ( endptr != NULL )
            *endptr = (char *)nptr; /* in case no conversion's performed */

      if ( base < 0 || base == 1 || base > 36 )
            {
            errno = EDOM;
            return 0;         /* unspecified behavior */
            }

      /* skip initial, possibly empty sequence of white-space characters */

      while ( isspace(*nptr) )
            ++nptr;

      /* process subject sequence: */

      /* optional sign */
      if ( (minus = *nptr == '-') || *nptr == '+' )
            ++nptr;

      if ( base == 0 ) {
            if ( *nptr == '0' ) {
                  if ( nptr[1] == 'X' || nptr[1] == 'x' )
                        base = 16;
                  else
                        base = 8;
            }
            else
                        base = 10;
      }
      /* optional "0x" or "0X" for base 16 */

      if ( base == 16 && *nptr == '0' && (nptr[1] == 'X' || nptr[1] == 'x') )
            nptr += 2;        /* skip past this prefix */

      /* check whether there is at least one valid digit */

      n = ToNumber(*nptr);
      ++nptr;

      if ( !valid(n, base) )
            return 0;         /* subject seq. not of expected form */

      accum = n;

      for ( toobig = 0; n = ToNumber(*nptr), valid(n, base); ++nptr )
            if ( accum > (uintmax_t)(INTMAX_MAX / base + 2) ) /* major wrap-around */
                  toobig = 1; /* but keep scanning */
            else
                  accum = base * accum + n;

      if ( endptr != NULL )
            *endptr = (char *)nptr; /* points to first not-valid-digit */

      if ( minus )
            {
            if ( accum > (uintmax_t)INTMAX_MAX + 1 )
                  toobig = 1;
            }
      else
      if ( accum > (uintmax_t)INTMAX_MAX )
            toobig = 1;

      if ( toobig )
            {
            errno = ERANGE;
            return minus ? INTMAX_MIN : INTMAX_MAX;
            }
      else
            return (intmax_t)(minus ? -accum : accum);
      }

long long __attribute__ ((alias ("strtoimax")))
strtoll (const char* __restrict__ nptr, char ** __restrict__ endptr, int base);

Generated by  Doxygen 1.6.0   Back to index