Commit eb77aba9 authored by Kevin Bracey's avatar Kevin Bracey
Browse files

Added atoll, strtoll, strtoull, strtoimax, strtoumax, imaxabs and imaxdiv...

Added atoll, strtoll, strtoull, strtoimax, strtoumax, imaxabs and imaxdiv functions to the standard C library.

Version 5.45. Tagged as 'RISC_OSLib-5_45'
parent aa313346
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "5.44"
Module_Version SETA 544
Module_MajorVersion SETS "5.45"
Module_Version SETA 545
Module_MinorVersion SETS ""
Module_Date SETS "16 Jan 2003"
Module_ApplicationDate SETS "16-Jan-03"
Module_Date SETS "17 Jan 2003"
Module_ApplicationDate SETS "17-Jan-03"
Module_ComponentName SETS "RISC_OSLib"
Module_ComponentPath SETS "RiscOS/Sources/Lib/RISC_OSLib"
Module_FullVersion SETS "5.44"
Module_HelpVersion SETS "5.44 (16 Jan 2003)"
Module_FullVersion SETS "5.45"
Module_HelpVersion SETS "5.45 (17 Jan 2003)"
END
/* (5.44)
/* (5.45)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.68.
*
*/
#define Module_MajorVersion_CMHG 5.44
#define Module_MajorVersion_CMHG 5.45
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 16 Jan 2003
#define Module_Date_CMHG 17 Jan 2003
#define Module_MajorVersion "5.44"
#define Module_Version 544
#define Module_MajorVersion "5.45"
#define Module_Version 545
#define Module_MinorVersion ""
#define Module_Date "16 Jan 2003"
#define Module_Date "17 Jan 2003"
#define Module_ApplicationDate "16-Jan-03"
#define Module_ApplicationDate "17-Jan-03"
#define Module_ComponentName "RISC_OSLib"
#define Module_ComponentPath "RiscOS/Sources/Lib/RISC_OSLib"
#define Module_FullVersion "5.44"
#define Module_HelpVersion "5.44 (16 Jan 2003)"
#define Module_LibraryVersionInfo "5:44"
#define Module_FullVersion "5.45"
#define Module_HelpVersion "5.45 (17 Jan 2003)"
#define Module_LibraryVersionInfo "5:45"
......@@ -33,6 +33,7 @@
#include "kernel.h"
#include <stdio.h> /* we define scanf for this */
#include <stdlib.h> /* and strtol/strtoul etc for this */
#include <inttypes.h> /* and strtoimax/strtoumax for this */
#include <math.h>
#include <errno.h>
#include <string.h>
......@@ -927,6 +928,41 @@ static unsigned long int _strtoul(const char *nsptr, char **endptr, int base)
}
}
static unsigned long long int _strtoull(const char *nsptr, char **endptr, int base)
{
const unsigned char *nptr = (const unsigned char *)nsptr; /* see scanf */
int c, ok = 0, overflowed = 0;
while ((c = *nptr++)!=0 && isspace(c));
if (c=='0')
{ ok = 1;
c = *nptr++;
if (c=='x' || c=='X')
{ if (base==0 || base==16)
{ ok = 0;
base = 16;
c = *nptr++;
}
}
else if (base==0) base = 8;
}
if (base==0) base = 10;
{ unsigned long long dhigh = 0, dlow = 0;
int digit;
while ((digit = ch_val(c,base)) >= 0)
{ ok = 1;
dlow = base * dlow + digit;
dhigh = base * dhigh + (dlow >> 32);
dlow &= 0xffffffff;
if (dhigh >= 0x100000000) overflowed = 1;
c = *nptr++;
}
if (endptr) *endptr = ok ? (char *)nptr-1 : (char *)nsptr;
/* extra result */
return overflowed ? (errno = ERANGE, ULLONG_MAX)
: (dhigh << 32) | dlow;
}
}
long int strtol(const char *nsptr, char **endptr, int base)
{
/* The specification in the ANSI information bulletin upsets me here: */
......@@ -969,10 +1005,6 @@ default: nptr--;
}
unsigned long int strtoul(const char *nsptr, char **endptr, int base)
/*
* I don't think the way negation is treated in this is right, but its closer
* than before
*/
{
const unsigned char *nptr = (const unsigned char *)nsptr; /* see scanf */
int flag = 0, c;
......@@ -990,16 +1022,95 @@ default: nptr--;
{ char *endp;
unsigned long ud = _strtoul((char *)nptr, &endp, base);
if (endptr) *endptr = endp==(char *)nptr ? (char *)nsptr : endp;
/* ??? The following lines depend on the fact that unsigned->int casts and */
/* ??? unary '-' cannot cause arithmetic traps. Recode to avoid this? */
if (errno == ERANGE) return ud;
errno = errno_saved;
if (flag & NUMNEG)
return (ud <= LONG_MAX) ? -(unsigned long)ud : (errno = ERANGE, ULONG_MAX);
else return +(unsigned long)ud;
return -ud;
else
return +ud;
}
}
long long int strtoll(const char * restrict nsptr,
char ** restrict endptr, int base)
{
/* This code is NOT shared with the %i conversion in scanf for several */
/* reasons: (a) here I deal with overflow in a silly way as noted above, */
/* (b) in scanf I have to deal with field width limitations, which does */
/* not fit in neatly here (c) this functions scans an array of char, */
/* while scanf reads from a stream - fudging these together seems too */
/* much work, (d) here I have the option of specifying the radix, while */
/* in scanf there seems to be no provision for that. Ah well! */
const unsigned char *nptr = (const unsigned char *)nsptr; /* see scanf */
int flag = 0, c;
while ((c = *nptr++)!=0 && isspace(c));
switch (c)
{
case '-': flag |= NUMNEG;
/* drop through */
case '+': break;
default: nptr--;
break;
}
{ char *endp;
unsigned long long ud = _strtoull((char *)nptr, &endp, base);
if (endptr) *endptr = endp==(char *)nptr ? (char *)nsptr : endp;
/* The following lines depend on the fact that unsigned->int casts and */
/* unary '-' cannot cause arithmetic traps. Recode to avoid this? */
if (flag & NUMNEG)
return (-(long long)ud <= 0) ? -(long long)ud : (errno = ERANGE, LLONG_MIN);
else
return (+(long long)ud >= 0) ? +(long long)ud : (errno = ERANGE, LLONG_MAX);
}
}
unsigned long long int strtoull(const char * restrict nsptr,
char ** restrict endptr, int base)
{
const unsigned char *nptr = (const unsigned char *)nsptr; /* see scanf */
int flag = 0, c;
int errno_saved = errno;
while ((c = *nptr++)!=0 && isspace(c));
switch (c)
{
case '-': flag |= NUMNEG;
/* drop through */
case '+': break;
default: nptr--;
break;
}
errno = 0;
{ char *endp;
unsigned long long ud = _strtoull((char *)nptr, &endp, base);
if (endptr) *endptr = endp==(char *)nptr ? (char *)nsptr : endp;
if (errno == ERANGE) return ud;
errno = errno_saved;
if (flag & NUMNEG)
return -ud;
else
return +ud;
}
}
#if INTMAX_MAX != LLONG_MAX || INTMAX_MIN != LLONG_MIN
#error New strtoimax needed
#endif
intmax_t strtoimax(const char * restrict nsptr,
char ** restrict endptr, int base)
{
return strtoll(nsptr, endptr, base);
}
#if UINTMAX_MAX != ULLONG_MAX
#error New strtoumax needed
#endif
uintmax_t strtoumax(const char * restrict nsptr,
char ** restrict endptr, int base)
{
return strtoull(nsptr, endptr, base);
}
double atof(const char *nptr)
{
......@@ -1025,4 +1136,12 @@ long int atol(const char *nptr)
return res;
}
long long int atoll(const char *nptr)
{
int save_errno = errno;
long long int res = strtoll(nptr, (char **)NULL, 10);
errno = save_errno;
return res;
}
/* end of scanf.c */
......@@ -17,12 +17,12 @@
/* inttypes.h: ISO 'C' (9899:1999) library header, section 7.8 */
/* Copyright (C) Acorn Computers Ltd. 2002 */
/* version 1.02 */
/* version 1.03 */
#ifndef __inttypes_h
#define __inttypes_h
#include "stdint.h"
#include <stdint.h>
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
......@@ -151,63 +151,90 @@
#define PRId64 "lld"
#define PRIdLEAST64 "lld"
#define PRIdFAST64 "lld"
#define PRIdMAX "lld"
#define PRIdMAX "jd"
#define PRIi64 "lli"
#define PRIiLEAST64 "lli"
#define PRIiFAST64 "lli"
#define PRIiMAX "lli"
#define PRIiMAX "ji"
#define PRIo64 "llo"
#define PRIoLEAST64 "llo"
#define PRIoFAST64 "llo"
#define PRIoMAX "llo"
#define PRIoMAX "jo"
#define PRIu64 "llu"
#define PRIuLEAST64 "llu"
#define PRIuFAST64 "llu"
#define PRIuMAX "llu"
#define PRIuMAX "ju"
#define PRIx64 "llx"
#define PRIxLEAST64 "llx"
#define PRIxFAST64 "llx"
#define PRIxMAX "llx"
#define PRIxMAX "jx"
#define PRIX64 "llX"
#define PRIXLEAST64 "llX"
#define PRIXFAST64 "llX"
#define PRIXMAX "llX"
#define PRIXMAX "jX"
#define SCNd64 "lld"
#define SCNdLEAST64 "lld"
#define SCNdFAST64 "lld"
#define SCNdMAX "lld"
#define SCNdMAX "jd"
#define SCNi64 "lli"
#define SCNiLEAST64 "lli"
#define SCNiFAST64 "lli"
#define SCNiMAX "lli"
#define SCNiMAX "ji"
#define SCNo64 "llo"
#define SCNoLEAST64 "llo"
#define SCNoFAST64 "llo"
#define SCNoMAX "llo"
#define SCNoMAX "jo"
#define SCNu64 "llu"
#define SCNuLEAST64 "llu"
#define SCNuFAST64 "llu"
#define SCNuMAX "llu"
#define SCNuMAX "ju"
#define SCNx64 "llx"
#define SCNxLEAST64 "llx"
#define SCNxFAST64 "llx"
#define SCNxMAX "llx"
#define SCNxMAX "jx"
#endif
#endif
#if 0
/* Not actually in the C library yet */
#ifdef __stdint_ll
typedef struct imaxdiv_t { intmax_t quot, rem; } imaxdiv_t;
/* type of the value returned by the imaxdiv function. */
extern intmax_t imaxabs(intmax_t /*j*/);
/*
* computes the absolute value of an integer j. If the result cannot be
* represented, the behaviour is undefined.
* Returns: the absolute value.
*/
extern imaxdiv_t imaxdiv(intmax_t /*numer*/, intmax_t /*denom*/);
/*
* computes numer / denom and numer % denom in a single operation.
* Returns: a structure of type imaxdiv_t, comprising both the quotient and
* the remainder.
*/
extern intmax_t strtoimax(const char * restrict /*nptr*/,
char ** restrict /*endptr*/, int /*base*/);
char ** restrict /*endptr*/, int /*base*/);
/*
* equivalent to the strtoll function, except that the initial portion of the
* string is converted to intmax_t representation.
* Returns: the converted value if any. If no conversion could be performed,
* zero is returned. If the correct value is outside the range of
* representable values, INTMAX_MAX or INTMAX_MIN is returned
* (according to the sign of the value), and the value of the
* macro ERANGE is stored in errno.
*/
extern uintmax_t strtoumax(const char * restrict /*nptr*/,
char ** restrict /*endptr*/, int /*base*/);
#endif /* 0 */
char ** restrict /*endptr*/, int /*base*/);
/*
* equivalent to the strtoull function, except that the initial portion of
* the string is converted to uintmax_t representation.
* Returns: the converted value if any. If no conversion could be performed,
* zero is returned. If the correct value is outside the range of
* representable values, UINTMAX_MAX is returned, and the value of
* the macro ERANGE is stored in errno.
*/
#endif
#endif
......
......@@ -18,7 +18,7 @@
/* stdlib.h: ISO 'C' (9899:1999) library header, section 7.20 */
/* Copyright (C) Codemist Ltd. */
/* Copyright (C) Acorn Computers Ltd., 1990, 1992 */
/* version 2.00 */
/* version 2.01 */
/*
* stdlib.h declares four types, several general purpose functions,
......@@ -109,6 +109,16 @@ extern long int atol(const char * /*nptr*/);
* representation.
* Returns: the converted value.
*/
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ >= 199901
extern long long int atoll(const char * /*nptr*/);
/*
* converts the initial part of the string pointed to by nptr to long long
* int representation.
* Returns: the converted value.
*/
#endif
#endif
extern double strtod(const char * /*nptr*/, char ** /*endptr*/);
/*
......@@ -141,7 +151,7 @@ extern long int strtol(const char * /*nptr*/, char **/*endptr*/, int /*base*/);
* terminating null character of the input string. Then it attempts to
* convert the subject sequence to an integer, and returns the result.
* If the value of base is 0, the expected form of the subject sequence is
* that of an integer constant (described in ANSI Draft, section 3.1.3.2),
* that of an integer constant (described in ISO Standard, section 6.4.4.1),
* optionally preceeded by a '+' or '-' sign, but not including an integer
* suffix. If the value of base is between 2 and 36, the expected form of
* the subject sequence is a sequence of letters and digits representing an
......@@ -171,8 +181,8 @@ extern unsigned long int strtoul(const char * /*nptr*/,
* including the terminating null character of the input string. Then it
* attempts to convert the subject sequence to an unsigned integer, and
* returns the result. If the value of base is zero, the expected form of
* the subject sequence is that of an integer constant (described in ANSI
* Draft, section 3.1.3.2), optionally preceeded by a '+' or '-' sign, but
* the subject sequence is that of an integer constant (described in ISO
* Standard, section 6.4.4.1), optionally preceeded by a '+' or '-' sign, but
* not including an integer suffix. If the value of base is between 2 and
* 36, the expected form of the subject sequence is a sequence of letters
* and digits representing an integer with the radix specified by base,
......@@ -188,13 +198,77 @@ extern unsigned long int strtoul(const char * /*nptr*/,
* representable values, ULONG_MAX is returned, and the value of the
* macro ERANGE is stored in errno.
*/
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ >= 199901
extern long long int strtoll(const char * restrict /*nptr*/,
char ** restrict /*endptr*/, int /*base*/);
/*
* converts the initial part of the string pointed to by nptr to long long
* int representation. First it decomposes the input string into three parts:
* an initial, possibly empty, sequence of white-space characters (as
* specified by the isspace function), a subject sequence resembling an
* integer represented in some radix determined by the value of base, and a
* final string of one or more unrecognised characters, including the
* terminating null character of the input string. Then it attempts to
* convert the subject sequence to an integer, and returns the result.
* If the value of base is 0, the expected form of the subject sequence is
* that of an integer constant (described in ISO Standard, section 6.4.4.1),
* optionally preceeded by a '+' or '-' sign, but not including an integer
* suffix. If the value of base is between 2 and 36, the expected form of
* the subject sequence is a sequence of letters and digits representing an
* integer with the radix specified by base, optionally preceeded by a plus
* or minus sign, but not including an integer suffix. The letters from a
* (or A) through z (or Z) are ascribed the values 10 to 35; only letters
* whose ascribed values are less than that of the base are permitted. If
* the value of base is 16, the characters 0x or 0X may optionally precede
* the sequence of letters and digits following the sign if present.
* A pointer to the final string is stored in the object
* pointed to by endptr, provided that endptr is not a null pointer.
* Returns: the converted value if any. If no conversion could be performed,
* zero is returned. If the correct value is outside the range of
* representable values, LLONG_MAX or LLONG_MIN is returned
* (according to the sign of the value), and the value of the
* macro ERANGE is stored in errno.
*/
extern unsigned long long int strtoull(const char * restrict /*nptr*/,
char ** restrict /*endptr*/,
int /*base*/);
/*
* converts the initial part of the string pointed to by nptr to unsigned
* long long int representation. First it decomposes the input string into
* three parts: an initial, possibly empty, sequence of white-space
* characters (as determined by the isspace function), a subject sequence
* resembling an unsigned integer represented in some radix determined by the
* value of base, and a final string of one or more unrecognised characters,
* including the terminating null character of the input string. Then it
* attempts to convert the subject sequence to an unsigned integer, and
* returns the result. If the value of base is zero, the expected form of
* the subject sequence is that of an integer constant (described in ISO
* Standard, section 6.4.4.1), optionally preceeded by a '+' or '-' sign, but
* not including an integer suffix. If the value of base is between 2 and
* 36, the expected form of the subject sequence is a sequence of letters
* and digits representing an integer with the radix specified by base,
* optionally preceeded by a '+' or '-' sign, but not including an integer
* suffix. The letters from a (or A) through z (or Z) stand for the values
* 10 to 35; only letters whose ascribed values are less than that of the
* base are permitted. If the value of base is 16, the characters 0x or 0X
* may optionally precede the sequence of letters and digits following the
* sign, if present. A pointer to the final string is stored in the object
* pointed to by endptr, provided that endptr is not a null pointer.
* Returns: the converted value if any. If no conversion could be performed,
* zero is returned. If the correct value is outside the range of
* representable values, ULLONG_MAX is returned, and the value of
* the macro ERANGE is stored in errno.
*/
#endif
#endif
extern int rand(void);
/*
* Computes a sequence of pseudo-random integers in the range 0 to RAND_MAX.
* Uses an additive generator (Mitchell & Moore) of the form:
* Xn = (X[n-24] + X[n-55]) MOD 2^31
* This is described in section 3.2.2 of Knuth, vol 2. It's period is
* This is described in section 3.2.2 of Knuth, vol 2. Its period is
* in excess of 2^55 and its randomness properties, though unproven, are
* conjectured to be good. Empirical testing since 1958 has shown no flaws.
* Returns: a pseudo-random integer.
......@@ -346,7 +420,7 @@ extern int system(const char * /*string*/);
* value is the return code from the executed command).
*/
extern void *bsearch(const void *key, const void * /*base*/,
extern void *bsearch(const void * /*key*/, const void * /*base*/,
size_t /*nmemb*/, size_t /*size*/,
int (* /*compar*/)(const void *, const void *));
/*
......@@ -398,11 +472,11 @@ extern long int labs(long int /*j*/);
extern ldiv_t ldiv(long int /*numer*/, long int /*denom*/);
/*
* computes numer / denom and numer % denom in a single operation.
* Returns: a structure of type div_t, comprising both the quotient and the
* Returns: a structure of type ldiv_t, comprising both the quotient and the
* remainder.
*/
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ > 199901
#if __STDC_VERSION__ >= 199901
extern long long int llabs(long long int /*j*/);
/*
* computes the absolute value of an integer j. If the result cannot be
......@@ -412,7 +486,7 @@ extern long long int llabs(long long int /*j*/);
extern lldiv_t lldiv(long long int /*numer*/, long long int /*denom*/);
/*
* computes numer / denom and numer % denom in a single operation.
* Returns: a structure of type div_t, comprising both the quotient and the
* Returns: a structure of type lldiv_t, comprising both the quotient and the
* remainder.
*/
#endif
......
......@@ -166,7 +166,9 @@ $Label
EXPORT div
EXPORT ldiv
EXPORT lldiv
EXPORT imaxdiv
EXPORT llabs
EXPORT imaxabs
EXPORT fmin
EXPORT fminf
......@@ -350,8 +352,8 @@ ldiv
STMIA ip, {a1,a2}
Return ,LinkNotStacked
imaxdiv NOP ; addresses have to be distinct :(
lldiv ; a1 -> result, a2 = num.l, a3=num.h, a4=den.l, den.h on stack
imaxdiv
FunctionEntry "a1"
MOV a1, a2
MOV a2, a3
......@@ -362,6 +364,7 @@ imaxdiv
STMIA ip, {a1-a4}
Return ,LinkNotStacked
imaxabs NOP ; addresses have to be distinct :(
llabs
TEQ a2, #0
Return ,LinkNotStacked,PL
......
......@@ -77,5 +77,12 @@
Entry llabs, , , unveneered
Entry lldiv, , , unveneered
Entry atoll, imported, , unveneered
Entry strtoll, imported, , unveneered
Entry strtoull, imported, , unveneered
Entry imaxabs, , , unveneered
Entry imaxdiv, , , unveneered
Entry strtoimax, imported, , unveneered
Entry strtoumax, imported, , unveneered
END
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment