delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1996/05/29/15:13:41

Date: Wed, 29 May 1996 23:10:52 +0400 (MSD)
From: "Alexander V. Lukyanov" <lav AT video DOT yars DOT free DOT net>
Message-Id: <199605291910.XAA06321@video.yars.free.net>
To: djgpp-workers AT delorie DOT com
Subject: long long for libc

Here are the patches and new files for long long support in libc.

--- include/limits.h.orig	Sat May 18 19:33:05 1996
+++ include/limits.h	Fri May 24 14:45:52 1996
@@ -60,6 +60,15 @@
 
 #ifndef _POSIX_SOURCE
 
+/* constants used in Solaris */
+#define LLONG_MIN       (-9223372036854775807LL-1LL)
+#define LLONG_MAX       9223372036854775807LL
+#define ULLONG_MAX      18446744073709551615ULL
+/* gnuc ones */
+#define LONG_LONG_MIN	LLONG_MIN
+#define LONG_LONG_MAX	LLONG_MAX
+#define ULONG_LONG_MAX	ULLONG_MAX
+
 #endif /* !_POSIX_SOURCE */
 #endif /* !__STRICT_ANSI__ */
 #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */
--- include/stdlib.h.orig	Sat May 18 18:57:16 1996
+++ include/stdlib.h	Fri May 24 15:01:00 1996
@@ -70,15 +70,25 @@
 
 #ifndef _POSIX_SOURCE
 
+typedef struct {
+  long long quot;
+  long long rem;
+} lldiv_t;
+
 void *		alloca(size_t _size);
 long double	_atold(const char *_s);
+long long	atoll(const char *_s);
 void		cfree(void *_ptr);
 char *		getpass(const char *_prompt);
 int		getlongpass(const char *_prompt, char *_buffer, int _max_len);
 char *		itoa(int value, char *buffer, int radix);
+long long	llabs(long long _i);
+lldiv_t		lldiv(long long _numer, long long _denom);
 int		putenv(const char *_val);
 int		setenv(const char *_var, const char *_val, int _replace);
 long double	_strtold(const char *_s, char **_endptr);
+long long	strtoll(const char *_s, char **_endptr, int _base);
+unsigned long long strtoull(const char *_s, char **_endptr, int _base);
 void		swab(const void *from, void *to, int nbytes);
 
 #ifndef alloca
--- src/libc/ansi/stdio/doprnt.c.orig	Sat May 18 16:38:40 1996
+++ src/libc/ansi/stdio/doprnt.c	Wed May 29 22:48:15 1996
@@ -28,10 +28,11 @@
 
 #define	PUTC(ch)	(void) putc(ch, fp)
 
-#define ARG(basetype) \
-	_ulong = flags&LONGINT ? va_arg(argp, long basetype) : \
-	    flags&SHORTINT ? (short basetype)va_arg(argp, int) : \
-	    va_arg(argp, int)
+#define ARG(basetype) _ulonglong = \
+		flags&LONGDBL ? va_arg(argp, long long basetype) : \
+		flags&LONGINT ? va_arg(argp, long basetype) : \
+		flags&SHORTINT ? (short basetype)va_arg(argp, int) : \
+		va_arg(argp, int)
 
 static int nan = 0;
 
@@ -79,7 +80,7 @@
   char *t;			/* buffer pointer */
   long double _ldouble;		/* double and long double precision arguments
 				   %L.[eEfgG] */
-  unsigned long _ulong;		/* integer arguments %[diouxX] */
+  unsigned long long _ulonglong; /* integer arguments %[diouxX] */
   int base;			/* base for [diouxX] conversion */
   int dprec;			/* decimal precision in [diouxX] */
   int fieldsz;			/* field size expanded by sign, etc */
@@ -187,7 +188,10 @@
       flags |= SHORTINT;
       goto rflag;
     case 'l':
-      flags |= LONGINT;
+      if (flags&LONGINT)
+	flags |= LONGDBL; /* for 'll' - long long */
+      else
+	flags |= LONGINT;
       goto rflag;
     case 'c':
       *(t = buf) = va_arg(argp, int);
@@ -200,9 +204,9 @@
     case 'd':
     case 'i':
       ARG(int);
-      if ((long)_ulong < 0)
+      if ((long long)_ulonglong < 0)
       {
-	_ulong = -_ulong;
+        _ulonglong = -_ulonglong;
 	sign = '-';
       }
       base = 10;
@@ -258,7 +262,9 @@
       t = *buf ? buf : buf + 1;
       goto pforw;
     case 'n':
-      if (flags & LONGINT)
+      if (flags & LONGDBL)
+        *va_arg(argp, long long *) = cnt;
+      else if (flags & LONGINT)
 	*va_arg(argp, long *) = cnt;
       else if (flags & SHORTINT)
 	*va_arg(argp, short *) = cnt;
@@ -281,7 +287,7 @@
        *	-- ANSI X3J11
        */
       /* NOSTRICT */
-      _ulong = (unsigned long)va_arg(argp, void *);
+      _ulonglong = (unsigned long)va_arg(argp, void *);
       base = 16;
       goto nosign;
     case 's':
@@ -323,18 +329,20 @@
       ARG(unsigned);
       base = 16;
       /* leading 0x/X only if non-zero */
-      if (flags & ALT && _ulong != 0)
+      if (flags & ALT && _ulonglong != 0)
 	flags |= HEXPREFIX;
 
+    nosign:
       /* unsigned conversions */
-    nosign:			sign = '\0';
+      sign = '\0';
+    number:
       /*
        * ``... diouXx conversions ... if a precision is
        * specified, the 0 flag will be ignored.''
        *	-- ANSI X3J11
        */
-    number:			if ((dprec = prec) >= 0)
-      flags &= ~ZEROPAD;
+      if ((dprec = prec) >= 0)
+	flags &= ~ZEROPAD;
 
       /*
        * ``The result of converting a zero value with an
@@ -342,16 +350,31 @@
        *	-- ANSI X3J11
        */
       t = buf + BUF;
-      if (_ulong != 0 || prec != 0)
+
+      if (_ulonglong != 0 || prec != 0)
       {
-	do {
-	  *--t = digs[_ulong % base];
-	  _ulong /= base;
-	} while (_ulong);
-	digs = "0123456789abcdef";
-	if (flags & ALT && base == 8 && *t != '0')
-	  *--t = '0';		/* octal leading 0 */
+        /* conversion is done separately since operations
+	  with long long are much slower */
+#define CONVERT(type) \
+	{ \
+	  register type _n = (type)_ulonglong; \
+	  do { \
+	    *--t = digs[_n % base]; \
+	    _n /= base; \
+	  } while (_n); \
+	}
+	if (flags&LONGDBL)
+	  CONVERT(unsigned long long) /* no ; */
+        else if(flags&SHORTINT)
+          CONVERT(unsigned short) /* no ; */
+	else
+	  CONVERT(unsigned long) /* no ; */
+#undef CONVERT
+        if (flags & ALT && base == 8 && *t != '0')
+          *--t = '0';		/* octal leading 0 */
       }
+
+      digs = "0123456789abcdef";
       size = buf + BUF - t;
 
     pforw:
--- src/libc/ansi/stdio/doscan.c.orig	Sat May 18 17:51:13 1996
+++ src/libc/ansi/stdio/doscan.c	Sat May 18 18:40:01 1996
@@ -73,10 +73,18 @@
     }
     if (len == 0)
       len = 30000;
-    if (ch=='l') {
+    
+    if (ch=='l') 
+    {
       size = LONG;
       ch = *fmt++;
-    } else if (ch=='h') {
+      if (ch=='l')
+      {
+        size = LONGDOUBLE; /* for long long 'll' format */
+        ch = *fmt++;
+      }
+    }
+    else if (ch=='h') {
       size = SHORT;
       ch = *fmt++;
     } else if (ch=='L') {
@@ -89,7 +97,10 @@
 	 gcc gives warning: ANSI C forbids braced
 	 groups within expressions */
       ch += 'a' - 'A';
-      size = LONG;
+      if (size==LONG)
+        size = LONGDOUBLE;
+      else
+        size = LONG;
     }
     if (ch == '\0')
       return(-1);
@@ -103,7 +114,7 @@
       else if (size==SHORT)
         **(short**)ptr = nchars;
       else if (size==LONGDOUBLE)
-        **(long**)ptr = nchars;
+        **(long long**)ptr = nchars;
       else
         **(int**)ptr = nchars;
       break;
@@ -159,7 +170,7 @@
   char numbuf[64];
   register c, base;
   int expseen, scale, negflg, c1, ndigit;
-  long lcval;
+  long long lcval;
   int cpos;
 
   if (type=='c' || type=='s' || type=='[')
@@ -276,8 +287,11 @@
     break;
 
   case (INT<<4) | LONG:
-  case (INT<<4) | LONGDOUBLE:
     **(long **)ptr = lcval;
+    break;
+
+  case (INT<<4) | LONGDOUBLE:
+    **(long long **)ptr = lcval;
     break;
   }
   return(1);
--- src/libc/ansi/stdio/printf.txh.orig	Mon May 20 15:26:00 1996
+++ src/libc/ansi/stdio/printf.txh	Mon May 20 15:33:39 1996
@@ -67,7 +67,7 @@
 
 An optional conversion qualifier, which may be @code{h} to specify
 @code{short}, @code{l} to specify long ints, or @code{L} to specify
-long doubles.
+long doubles. Long long type can be specified by @code{L} or @code{ll}.
 
 @item
 
--- src/libc/ansi/stdio/scanf.txh.orig	Mon Jul 10 05:39:48 1995
+++ src/libc/ansi/stdio/scanf.txh	Mon May 20 15:29:12 1996
@@ -36,7 +36,7 @@
 
 An optional conversion qualifier, which may be @code{h} to specify
 @code{short}, @code{l} to specify long ints, or @code{L} to specify
-long doubles.
+long doubles. Long long type can be specified by @code{L} or @code{ll}.
 
 @item
 
@@ -117,7 +117,8 @@
 
 @subheading Return Value
 
-The number of items successfully scanned.
+The number of items successfully matched and assigned. If input ends
+before first item is assigned, EOF is returned.
 
 @subheading Example
 
End of diffs

#!/bin/sh
# This is a shell archive (produced by GNU shar 4.0).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1996-05-29 22:05 MSK by <lav AT video>.
# Source directory was `/home/lav/ftp/djgpp'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    149 -rw-r--r-- src/libc/ansi/stdlib/llabs.c
#    410 -rw-r--r-- src/libc/ansi/stdlib/lldiv.c
#    256 -rw-r--r-- src/libc/ansi/stdlib/llabs.txh
#    737 -rw-r--r-- src/libc/ansi/stdlib/lldiv.txh
#    911 -rw-r--r-- src/libc/ansi/stdlib/strtoll.txh
#    496 -rw-r--r-- src/libc/ansi/stdlib/strtoull.txh
#   1589 -rw-r--r-- src/libc/ansi/stdlib/strtoll.c
#   1630 -rw-r--r-- src/libc/ansi/stdlib/strtoull.c
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo 'WARNING: not restoring timestamps'
fi
rm -f 1231235999 $$.touch
#
# ============= src/libc/ansi/stdlib/llabs.c ==============
if test ! -d 'src'; then
  echo 'x - creating directory src'
  mkdir 'src'
fi
if test ! -d 'src/libc'; then
  echo 'x - creating directory src/libc'
  mkdir 'src/libc'
fi
if test ! -d 'src/libc/ansi'; then
  echo 'x - creating directory src/libc/ansi'
  mkdir 'src/libc/ansi'
fi
if test ! -d 'src/libc/ansi/stdlib'; then
  echo 'x - creating directory src/libc/ansi/stdlib'
  mkdir 'src/libc/ansi/stdlib'
fi
if test -f 'src/libc/ansi/stdlib/llabs.c' && test X"$1" != X"-c"; then
  echo 'x - skipping src/libc/ansi/stdlib/llabs.c (File already exists)'
else
  echo 'x - extracting src/libc/ansi/stdlib/llabs.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/libc/ansi/stdlib/llabs.c' &&
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <stdlib.h>
X
long long
llabs(long long j)
{
X  return j<0 ? -j : j;
}
SHAR_EOF
  $shar_touch -am 0518195096 'src/libc/ansi/stdlib/llabs.c' &&
  chmod 0644 'src/libc/ansi/stdlib/llabs.c' ||
  echo 'restore of src/libc/ansi/stdlib/llabs.c failed'
  shar_count="`wc -c < 'src/libc/ansi/stdlib/llabs.c'`"
  test 149 -eq "$shar_count" ||
    echo "src/libc/ansi/stdlib/llabs.c: original size 149, current size $shar_count"
fi
# ============= src/libc/ansi/stdlib/lldiv.c ==============
if test -f 'src/libc/ansi/stdlib/lldiv.c' && test X"$1" != X"-c"; then
  echo 'x - skipping src/libc/ansi/stdlib/lldiv.c (File already exists)'
else
  echo 'x - extracting src/libc/ansi/stdlib/lldiv.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/libc/ansi/stdlib/lldiv.c' &&
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <stdlib.h>
X
lldiv_t
lldiv(long long num, long long denom)
{
X  lldiv_t r;
X
X  if (num > 0 && denom < 0)
X  {
X    num = -num;
X    denom = -denom;
X  }
X  r.quot = num / denom;
X  r.rem = num % denom;
X  if (num < 0 && denom > 0)
X  {
X    if (r.rem > 0)
X    {
X      r.quot++;
X      r.rem -= denom;
X    }
X  }
X  return r;
}
SHAR_EOF
  $shar_touch -am 0518195396 'src/libc/ansi/stdlib/lldiv.c' &&
  chmod 0644 'src/libc/ansi/stdlib/lldiv.c' ||
  echo 'restore of src/libc/ansi/stdlib/lldiv.c failed'
  shar_count="`wc -c < 'src/libc/ansi/stdlib/lldiv.c'`"
  test 410 -eq "$shar_count" ||
    echo "src/libc/ansi/stdlib/lldiv.c: original size 410, current size $shar_count"
fi
# ============= src/libc/ansi/stdlib/llabs.txh ==============
if test -f 'src/libc/ansi/stdlib/llabs.txh' && test X"$1" != X"-c"; then
  echo 'x - skipping src/libc/ansi/stdlib/llabs.txh (File already exists)'
else
  echo 'x - extracting src/libc/ansi/stdlib/llabs.txh (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/libc/ansi/stdlib/llabs.txh' &&
@node llabs, misc
@subheading Syntax
X
@example
#include <stdlib.h>
X
long long llabs(long long x);
@end example
X
@subheading Description
X
This function takes the absolute value of @var{x}.  @xref{abs}.
X
@subheading Return Value
X
|@var{x}|
X
SHAR_EOF
  $shar_touch -am 0520151096 'src/libc/ansi/stdlib/llabs.txh' &&
  chmod 0644 'src/libc/ansi/stdlib/llabs.txh' ||
  echo 'restore of src/libc/ansi/stdlib/llabs.txh failed'
  shar_count="`wc -c < 'src/libc/ansi/stdlib/llabs.txh'`"
  test 256 -eq "$shar_count" ||
    echo "src/libc/ansi/stdlib/llabs.txh: original size 256, current size $shar_count"
fi
# ============= src/libc/ansi/stdlib/lldiv.txh ==============
if test -f 'src/libc/ansi/stdlib/lldiv.txh' && test X"$1" != X"-c"; then
  echo 'x - skipping src/libc/ansi/stdlib/lldiv.txh (File already exists)'
else
  echo 'x - extracting src/libc/ansi/stdlib/lldiv.txh (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/libc/ansi/stdlib/lldiv.txh' &&
@node lldiv, math
@subheading Syntax
X
@example
#include <stdlib.h>
X
lldiv_t lldiv(long long numerator, long long denomonator);
@end example
X
@subheading Description
X
Returns the quotient and remainder of the division @var{numberator}
divided by @var{denomonator}.  The return type is as follows:
X
@example
typedef struct @{
X  long long quot;
X  long long rem;
@} lldiv_t;
@end example
X
@subheading Return Value
X
The results of the division are returned.
X
@subheading Example
X
@example
lldiv_t l = lldiv(42, 3);
printf("42 = %lld x 3 + %lld\n", l.quot, l.rem);
X
lldiv(+40, +3) = @{ +13, +1 @}
lldiv(+40, -3) = @{ -13, -1 @}
lldiv(-40, +3) = @{ -13, -1 @}
lldiv(-40, -3) = @{ +13, -1 @}
X
@end example
X
SHAR_EOF
  $shar_touch -am 0520151396 'src/libc/ansi/stdlib/lldiv.txh' &&
  chmod 0644 'src/libc/ansi/stdlib/lldiv.txh' ||
  echo 'restore of src/libc/ansi/stdlib/lldiv.txh failed'
  shar_count="`wc -c < 'src/libc/ansi/stdlib/lldiv.txh'`"
  test 737 -eq "$shar_count" ||
    echo "src/libc/ansi/stdlib/lldiv.txh: original size 737, current size $shar_count"
fi
# ============= src/libc/ansi/stdlib/strtoll.txh ==============
if test -f 'src/libc/ansi/stdlib/strtoll.txh' && test X"$1" != X"-c"; then
  echo 'x - skipping src/libc/ansi/stdlib/strtoll.txh (File already exists)'
else
  echo 'x - extracting src/libc/ansi/stdlib/strtoll.txh (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/libc/ansi/stdlib/strtoll.txh' &&
@node strtoll, string
@subheading Syntax
X
@example
#include <stdlib.h>
X
long long strtoll(const char *s, char **endp, int base);
@end example
X
@subheading Description
X
This function converts as much of @var{s} as looks like an appropriate
number into the value of that number, and sets @var{*endp} to point to
the first unused character. 
X
The @var{base} argument indicates what base the digits (or letters)
should be treated as.  If @var{base} is zero, the base is determined by
looking for @code{0x}, @code{0X}, or @code{0} as the first part of the
string, and sets the base used to 16, 16, or 8 if it finds one.  The
default base is 10 if none of those prefixes are found.
X
@subheading Return Value
X
The value.
X
@subheading Example
X
@example
printf("Enter a number: "); fflush(stdout);
gets(buf);
char *bp;
printf("The value is %lld\n", strtoll(buf, &bp, 0));
@end example
X
SHAR_EOF
  $shar_touch -am 0520151496 'src/libc/ansi/stdlib/strtoll.txh' &&
  chmod 0644 'src/libc/ansi/stdlib/strtoll.txh' ||
  echo 'restore of src/libc/ansi/stdlib/strtoll.txh failed'
  shar_count="`wc -c < 'src/libc/ansi/stdlib/strtoll.txh'`"
  test 911 -eq "$shar_count" ||
    echo "src/libc/ansi/stdlib/strtoll.txh: original size 911, current size $shar_count"
fi
# ============= src/libc/ansi/stdlib/strtoull.txh ==============
if test -f 'src/libc/ansi/stdlib/strtoull.txh' && test X"$1" != X"-c"; then
  echo 'x - skipping src/libc/ansi/stdlib/strtoull.txh (File already exists)'
else
  echo 'x - extracting src/libc/ansi/stdlib/strtoull.txh (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/libc/ansi/stdlib/strtoull.txh' &&
@node strtoull, string
@subheading Syntax
X
@example
#include <stdlib.h>
X
unsigned long long strtoull(const char *s, char **endp, int base);
@end example
X
@subheading Description
X
This is just like @code{strtoll} (@pxref{strtoll}) except that the result
is unsigned. 
X
@subheading Return Value
X
The value.
X
@subheading Example
X
@example
printf("Enter a number: "); fflush(stdout);
gets(buf);
char *bp;
printf("The value is %llu\n", strtoull(buf, &bp, 0));
@end example
X
SHAR_EOF
  $shar_touch -am 0520151696 'src/libc/ansi/stdlib/strtoull.txh' &&
  chmod 0644 'src/libc/ansi/stdlib/strtoull.txh' ||
  echo 'restore of src/libc/ansi/stdlib/strtoull.txh failed'
  shar_count="`wc -c < 'src/libc/ansi/stdlib/strtoull.txh'`"
  test 496 -eq "$shar_count" ||
    echo "src/libc/ansi/stdlib/strtoull.txh: original size 496, current size $shar_count"
fi
# ============= src/libc/ansi/stdlib/strtoll.c ==============
if test -f 'src/libc/ansi/stdlib/strtoll.c' && test X"$1" != X"-c"; then
  echo 'x - skipping src/libc/ansi/stdlib/strtoll.c (File already exists)'
else
  echo 'x - extracting src/libc/ansi/stdlib/strtoll.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/libc/ansi/stdlib/strtoll.c' &&
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <libc/unconst.h>
X
long long
strtoll(const char *nptr, char **endptr, int base)
{
X  const char *s = nptr;
X  unsigned long long acc;
X  int c;
X  unsigned long long cutoff;
X  int neg = 0, any, cutlim;
X
X  /*
X   * See strtol for comments as to the logic used.
X   */
X  do {
X    c = *s++;
X  } while (isspace(c));
X  if (c == '-')
X  {
X    neg = 1;
X    c = *s++;
X  }
X  else if (c == '+')
X    c = *s++;
X  if ((base == 0 || base == 16) &&
X      c == '0' && (*s == 'x' || *s == 'X'))
X  {
X    c = s[1];
X    s += 2;
X    base = 16;
X  }
X  if (base == 0)
X    base = c == '0' ? 8 : 10;
X
/* to prevent overflow, we take max-1 and add 1 after division */
X  cutoff = neg ? -(LLONG_MIN+1) : LLONG_MAX-1;
X  cutlim = cutoff % base;
X  cutoff /= base;
X  if (++cutlim == base)
X  {
X    cutlim = 0;
X    cutoff++;
X  }
X  for (acc = 0, any = 0;; c = *s++)
X  {
X    if (isdigit(c))
X      c -= '0';
X    else if (isalpha(c))
X      c -= isupper(c) ? 'A' - 10 : 'a' - 10;
X    else
X      break;
X    if (c >= base)
X      break;
X    if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
X      any = -1;
X    else
X    {
X      any = 1;
X      acc *= base;
X      acc += c;
X    }
X  }
X  if (any < 0)
X  {
X    acc = neg ? LLONG_MIN : LLONG_MAX;
X    errno = ERANGE;
X  }
X  else if (neg)
X    acc = -acc;
X  if (endptr != 0)
X    *endptr = any ? unconst(s, char *) - 1 : unconst(nptr, char *);
X  return acc;
}
SHAR_EOF
  $shar_touch -am 0524144996 'src/libc/ansi/stdlib/strtoll.c' &&
  chmod 0644 'src/libc/ansi/stdlib/strtoll.c' ||
  echo 'restore of src/libc/ansi/stdlib/strtoll.c failed'
  shar_count="`wc -c < 'src/libc/ansi/stdlib/strtoll.c'`"
  test 1589 -eq "$shar_count" ||
    echo "src/libc/ansi/stdlib/strtoll.c: original size 1589, current size $shar_count"
fi
# ============= src/libc/ansi/stdlib/strtoull.c ==============
if test -f 'src/libc/ansi/stdlib/strtoull.c' && test X"$1" != X"-c"; then
  echo 'x - skipping src/libc/ansi/stdlib/strtoull.c (File already exists)'
else
  echo 'x - extracting src/libc/ansi/stdlib/strtoull.c (text)'
  sed 's/^X//' << 'SHAR_EOF' > 'src/libc/ansi/stdlib/strtoull.c' &&
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <libc/unconst.h>
X
/*
X * Convert a string to an unsigned long long integer.
X *
X * Ignores `locale' stuff.  Assumes that the upper and lower case
X * alphabets and digits are each contiguous.
X */
unsigned long long
strtoull(const char *nptr, char **endptr, int base)
{
X  const char *s = nptr;
X  unsigned long long acc;
X  int c;
X  unsigned long long cutoff;
X  int neg = 0, any, cutlim;
X
X  /*
X   * See strtol for comments as to the logic used.
X   */
X  do {
X    c = *s++;
X  } while (isspace(c));
X  if (c == '-')
X  {
X    neg = 1;
X    c = *s++;
X  }
X  else if (c == '+')
X    c = *s++;
X  if ((base == 0 || base == 16) &&
X      c == '0' && (*s == 'x' || *s == 'X'))
X  {
X    c = s[1];
X    s += 2;
X    base = 16;
X  }
X  if (base == 0)
X    base = c == '0' ? 8 : 10;
X  cutoff = (unsigned long long)ULLONG_MAX / base;
X  cutlim = (unsigned long long)ULLONG_MAX % base;
X  for (acc = 0, any = 0;; c = *s++)
X  {
X    if (isdigit(c))
X      c -= '0';
X    else if (isalpha(c))
X      c -= isupper(c) ? 'A' - 10 : 'a' - 10;
X    else
X      break;
X    if (c >= base)
X      break;
X    if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
X      any = -1;
X    else {
X      any = 1;
X      acc *= base;
X      acc += c;
X    }
X  }
X  if (any < 0)
X  {
X    acc = ULLONG_MAX;
X    errno = ERANGE;
X  }
X  else if (neg)
X    acc = -acc;
X  if (endptr != 0)
X    *endptr = any ? unconst(s, char *) - 1 : unconst(nptr, char *);
X  return acc;
}
SHAR_EOF
  $shar_touch -am 0524150396 'src/libc/ansi/stdlib/strtoull.c' &&
  chmod 0644 'src/libc/ansi/stdlib/strtoull.c' ||
  echo 'restore of src/libc/ansi/stdlib/strtoull.c failed'
  shar_count="`wc -c < 'src/libc/ansi/stdlib/strtoull.c'`"
  test 1630 -eq "$shar_count" ||
    echo "src/libc/ansi/stdlib/strtoull.c: original size 1630, current size $shar_count"
fi
exit 0

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019