PageRenderTime 26ms CodeModel.GetById 14ms app.highlight 9ms RepoModel.GetById 2ms app.codeStats 0ms

/contrib/cvs/lib/strtoul.c

https://bitbucket.org/freebsd/freebsd-head/
C | 100 lines | 82 code | 10 blank | 8 comment | 37 complexity | 22f302311850eef58afe67796d99cb40 MD5 | raw file
  1/*
  2 * strtol : convert a string to long.
  3 *
  4 * Andy Wilson, 2-Oct-89.
  5 */
  6
  7#include <errno.h>
  8#include <ctype.h>
  9#include <stdio.h>
 10
 11#ifdef HAVE_CONFIG_H
 12#include "config.h"
 13#endif
 14
 15#ifndef ULONG_MAX
 16#define	ULONG_MAX	((unsigned long)(~0L))		/* 0xFFFFFFFF */
 17#endif
 18
 19extern int errno;
 20
 21unsigned long
 22strtoul(s, ptr, base)
 23     const char *s; char **ptr; int base;
 24{
 25  unsigned long total = 0;
 26  unsigned digit;
 27  const char *start=s;
 28  int did_conversion=0;
 29  int overflow = 0;
 30  int negate = 0;
 31  unsigned long maxdiv, maxrem;
 32
 33  if (s==NULL)
 34    {
 35      errno = ERANGE;
 36      if (!ptr)
 37	*ptr = (char *)start;
 38      return 0L;
 39    }
 40
 41  while (isspace(*s))
 42    s++;
 43  if (*s == '+')
 44    s++;
 45  else if (*s == '-')
 46    s++, negate = 1;
 47  if (base==0 || base==16) /*  the 'base==16' is for handling 0x */
 48    {
 49      int tmp;
 50
 51      /*
 52       * try to infer base from the string
 53       */
 54      if (*s != '0')
 55        tmp = 10;	/* doesn't start with 0 - assume decimal */
 56      else if (s[1] == 'X' || s[1] == 'x')
 57	tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */
 58      else
 59	tmp = 8;	/* starts with 0 - hence octal */
 60      if (base==0)
 61	base = (int)tmp;
 62    }
 63
 64  maxdiv = ULONG_MAX / base;
 65  maxrem = ULONG_MAX % base;
 66
 67  while ((digit = *s) != '\0')
 68    {
 69      if (digit >= '0' && digit < ('0'+base))
 70	digit -= '0';
 71      else
 72	if (base > 10)
 73	  {
 74	    if (digit >= 'a' && digit < ('a'+(base-10)))
 75	      digit = digit - 'a' + 10;
 76	    else if (digit >= 'A' && digit < ('A'+(base-10)))
 77	      digit = digit - 'A' + 10;
 78	    else
 79	      break;
 80	  }
 81	else
 82	  break;
 83      did_conversion = 1;
 84      if (total > maxdiv
 85	  || (total == maxdiv && digit > maxrem))
 86	overflow = 1;
 87      total = (total * base) + digit;
 88      s++;
 89    }
 90  if (overflow)
 91    {
 92      errno = ERANGE;
 93      if (ptr != NULL)
 94	*ptr = (char *)s;
 95      return (ULONG_MAX);
 96    }
 97  if (ptr != NULL)
 98    *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start);
 99  return negate ? -total : total;
100}