Date: Wed, 29 May 1996 23:10:52 +0400 (MSD) From: "Alexander V. Lukyanov" 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 . # 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 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 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 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 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 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 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 #include #include #include #include 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 #include #include #include #include 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