Detect and provide conversion routines for C specialized integer types ([u]int{8,16,32,64}_t)

This commit is contained in:
Juan Jose Garcia Ripoll 2009-03-01 15:41:36 +01:00
parent 40f2552ffb
commit e16ff91913
12 changed files with 2952 additions and 3237 deletions

View file

@ -88,6 +88,12 @@ ECL 9.1.0:
- New, more efficient bytecodes for parsing the function lambda list, instead
of using a common function.
- ECL provides macros that define specialized integer types (ecl_uint8_t,
ecl_int32_t, ... up to ecl_int64_t). These macros can be used to check for
support of these specialized types in arrays and in compilers. There are
also companion functions or macros, ecl_make_[u]int*_t and ecl_to_[u]int*_t
that respectively convert to and from Lisp integers.
;;; Local Variables: ***
;;; mode:text ***
;;; fill-column:79 ***

91
src/aclocal.m4 vendored
View file

@ -13,7 +13,8 @@ AC_DEFUN([AC_C_LONG_LONG],
ac_cv_c_long_long=no)
fi])
if test $ac_cv_c_long_long = yes; then
AC_DEFINE(HAVE_LONG_LONG, 1, [compiler understands long long])
AC_DEFINE(ecl_long_long_t, long long, [compiler understands long long])
AC_DEFINE(ecl_ulong_long_t, unsigned long long, [compiler understands long long])
fi
])
@ -373,7 +374,91 @@ int main() {
}]])],[ECL_FILE_CNT=3],[])
fi
])
dnl
dnl --------------------------------------------------------------
dnl Check the existence of different integer types and that they
dnl have the right size;
dnl
AC_DEFUN(ECL_INTEGER_TYPES,[
AC_SUBST(ECL_HAVE_INT16_T)
ECL_UINT16_T=""
ECL_UINT32_T=""
ECL_UINT64_T=""
ECL_INT16_T=""
ECL_INT32_T=""
ECL_INT64_T=""
if test -z "${ECL_UINT16_T}"; then
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdint.h>]], [[
{
uint16_t i = 0x8000UL;
if (i == 0)
return 0;
if ((i << 1))
return 0;
if ((i - 1) != 0x7FFFUL)
return 0;
return 1;
}]])],[ECL_UINT16_T=uint16_t;ECL_INT16_T=int16_t],[])
fi
if test -z "${ECL_UINT32_T}"; then
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdint.h>]], [[
{
uint32_t i = 0x80000000UL;
if (i == 0)
return 0;
if ((i << 1))
return 0;
if ((i - 1) != 0x7FFFFFFFUL)
return 0;
return 1;
}]])],[ECL_UINT32_T=uint32_t;ECL_INT32_T=int32_t],[])
fi
if test -z "${ECL_UINT64_T}"; then
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdint.h>]], [[
{
uint64_t i = 1;
i <<= 63; if (i == 0) return 0;
i <<= 1; if (i) return 0;
return 1;
}]])],[ECL_UINT64_T=uint64_t;ECL_INT64_T=int64_t],[])
fi
if test "${ECL_UINT16_T}${CL_FIXNUM_BITS}" = "16"; then
ECL_UINT16_T="cl_index"
ECL_INT16_T="cl_fixnum"
fi
if test "${ECL_UINT32_T}${CL_FIXNUM_BITS}" = "32"; then
ECL_UINT32_T="cl_index"
ECL_INT32_T="cl_fixnum"
fi
if test "${ECL_UINT64_T}${CL_FIXNUM_BITS}" = "64"; then
ECL_UINT64_T="cl_index"
ECL_INT64_T="cl_fixnum"
fi
AC_MSG_CHECKING(uint16_t type)
if test -n "${ECL_UINT16_T}"; then
AC_DEFINE_UNQUOTED([ecl_uint16_t],[$ECL_UINT16_T])
AC_DEFINE_UNQUOTED([ecl_int16_t],[$ECL_INT16_T])
AC_MSG_RESULT(${ECL_UINT16_T})
else
AC_MSG_RESULT(none)
fi
AC_MSG_CHECKING(uint32_t type)
if test -n "${ECL_UINT32_T}"; then
AC_DEFINE_UNQUOTED([ecl_uint32_t],[$ECL_UINT32_T])
AC_DEFINE_UNQUOTED([ecl_int32_t],[$ECL_INT32_T])
AC_MSG_RESULT(${ECL_UINT32_T})
else
AC_MSG_RESULT(none)
fi
AC_MSG_CHECKING(uint64_t type)
if test -n "${ECL_UINT64_T}"; then
AC_DEFINE_UNQUOTED([ecl_uint64_t],[$ECL_UINT64_T])
AC_DEFINE_UNQUOTED([ecl_int64_t],[$ECL_INT64_T])
AC_MSG_RESULT(${ECL_UINT64_T})
else
AC_MSG_RESULT(none)
fi
])
dnl
dnl --------------------------------------------------------------
dnl Check the direction to which the stack grows (for garbage
@ -573,7 +658,7 @@ case "${host_cpu}" in
EXTRA_OBJS="${EXTRA_OBJS} apply_x86.o"
AC_DEFINE(ECL_ASM_APPLY)
fi
AC_DEFINE(ECL_USE_VARARG_AS_POINTER)
AC_DEFINE(ECL_USE_VARARG_AS_POINTER)
dynamic_ffi=yes
;;
x86_64 )

View file

@ -87,6 +87,80 @@ static char stdin_buf[BUFSIZ];
static char stdout_buf[BUFSIZ];
#endif
static const char *feature_names[] = {
"ECL", "COMMON", ECL_ARCHITECTURE, "FFI", "PREFIXED-API",
"IEEE-FLOATING-POINT",
#ifdef WITH_GMP
"COMMON-LISP",
"ANSI-CL",
#endif /* WITH_GMP */
#if defined(GBC_BOEHM)
"BOEHM-GC",
#endif
#ifdef ECL_THREADS
"THREADS",
#endif
#ifdef CLOS
"CLOS",
#endif
#ifdef ENABLE_DLOPEN
"DLOPEN",
#endif
#ifdef ECL_OLD_LOOP
"OLD-LOOP",
#endif
"ECL-PDE",
#ifdef unix
"UNIX",
#endif
#ifdef BSD
"BSD",
#endif
#ifdef SYSV
"SYSTEM-V",
#endif
#ifdef MSDOS
"MS-DOS",
#endif
#ifdef mingw32
"MINGW32",
#endif
#ifdef _MSC_VER
"MSVC",
#endif
#ifdef ECL_CMU_FORMAT
"CMU-FORMAT",
#endif
#ifdef ECL_CLOS_STREAMS
"CLOS-STREAMS",
#endif
#ifdef ECL_DYNAMIC_FFI
"DFFI",
#endif
#ifdef ECL_UNICODE
"UNICODE",
#endif
#ifdef ECL_LONG_FLOAT
"LONG-FLOAT",
#endif
#ifdef ECL_SHORT_FLOAT
"SHORT-FLOAT",
#endif
#ifdef ECL_RELATIVE_PACKAGE_NAMES
"RELATIVE-PACKAGE-NAMES",
#endif
#ifdef ecl_uint16_t
"UINT16-T",
#endif
#ifdef ecl_uint32_t
"UINT32-T",
#endif
#ifdef ecl_uint64_t
"UINT64-T",
#endif
0
};
cl_fixnum
ecl_get_option(int option)
{
@ -556,78 +630,9 @@ cl_boot(int argc, char **argv)
cl_list(8, @'&optional', @'&rest', @'&key', @'&allow-other-keys',
@'&aux', @'&whole', @'&environment', @'&body'));
features = cl_list(5,
ecl_make_keyword("ECL"),
ecl_make_keyword("COMMON"),
ecl_make_keyword(ECL_ARCHITECTURE),
ecl_make_keyword("FFI"),
ecl_make_keyword("PREFIXED-API"));
#define ADD_FEATURE(name) features = CONS(ecl_make_keyword(name),features)
#ifdef WITH_GMP
ADD_FEATURE("COMMON-LISP");
ADD_FEATURE("ANSI-CL");
#endif /* WITH_GMP */
#if defined(GBC_BOEHM)
ADD_FEATURE("BOEHM-GC");
#endif
#ifdef ECL_THREADS
ADD_FEATURE("THREADS");
#endif
#ifdef CLOS
ADD_FEATURE("CLOS");
#endif
#ifdef ENABLE_DLOPEN
ADD_FEATURE("DLOPEN");
#endif
#ifdef ECL_OLD_LOOP
ADD_FEATURE("OLD-LOOP");
#endif
ADD_FEATURE("ECL-PDE");
#ifdef unix
ADD_FEATURE("UNIX");
#endif
#ifdef BSD
ADD_FEATURE("BSD");
#endif
#ifdef SYSV
ADD_FEATURE("SYSTEM-V");
#endif
#ifdef MSDOS
ADD_FEATURE("MS-DOS");
#endif
#ifdef mingw32
ADD_FEATURE("MINGW32");
#endif
#ifdef _MSC_VER
ADD_FEATURE("MSVC");
#endif
#ifdef ECL_CMU_FORMAT
ADD_FEATURE("CMU-FORMAT");
#endif
#ifdef ECL_CLOS_STREAMS
ADD_FEATURE("CLOS-STREAMS");
#endif
#ifdef ECL_DYNAMIC_FFI
ADD_FEATURE("DFFI");
#endif
#ifdef ECL_UNICODE
ADD_FEATURE("UNICODE");
#endif
#ifdef ECL_LONG_FLOAT
ADD_FEATURE("LONG-FLOAT");
#endif
#ifdef ECL_SHORT_FLOAT
ADD_FEATURE("SHORT-FLOAT");
#endif
#ifdef ECL_RELATIVE_PACKAGE_NAMES
ADD_FEATURE("RELATIVE-PACKAGE-NAMES");
ECL_SET(@'SI::*RELATIVE-PACKAGE-NAMES*', Ct);
#endif
/* This is assumed in all systems */
ADD_FEATURE("IEEE-FLOATING-POINT");
for (i = 0, features = Cnil; feature_names[i]; i++) {
features = CONS(ecl_make_keyword(feature_names[i]),features);
}
ECL_SET(@'*features*', features);

View file

@ -113,6 +113,176 @@ ecl_make_unsigned_integer(cl_index l)
return MAKE_FIXNUM(l);
}
ecl_uint8_t
ecl_to_uint8_t(cl_object x) {
do {
if (FIXNUMP(x)) {
cl_fixnum y = fix(x);
if (y >= 0 && y < 256) {
return (uint8_t)y;
}
}
x = ecl_type_error(@'coerce', "variable", x,
cl_list(3,@'integer',MAKE_FIXNUM(-128),
MAKE_FIXNUM(127)));
} while(1);
}
ecl_int8_t
ecl_to_int8_t(cl_object x) {
do {
if (FIXNUMP(x)) {
cl_fixnum y = fix(x);
if (y >= -128 && y <= 127) {
return (int8_t)y;
}
}
x = ecl_type_error(@'coerce', "variable", x,
cl_list(3,@'integer',MAKE_FIXNUM(-128),
MAKE_FIXNUM(127)));
} while(1);
}
#if FIXNUM_BITS < 32
# error "Unsupported platform with cl_fixnum < ecl_uint32_t"
#endif
#ifdef ecl_uint16_t
ecl_uint16_t
ecl_to_uint16_t(cl_object x) {
do {
if (FIXNUMP(x)) {
cl_fixnum y = fix(x);
if (y >= 0 && y < 0xFFFFL) {
return (ecl_uint16_t)y;
}
}
x = ecl_type_error(@'coerce', "variable", x,
cl_list(3,@'integer',MAKE_FIXNUM(0),
MAKE_FIXNUM(0xFFFFL)));
} while(1);
}
ecl_int16_t
ecl_to_int16_t(cl_object x) {
do {
if (FIXNUMP(x)) {
cl_fixnum y = fix(x);
if (y >= -0x8000 && y <= 0x7FFF) {
return (ecl_int16_t)y;
}
}
x = ecl_type_error(@'coerce', "variable", x,
cl_list(3,@'integer',MAKE_FIXNUM(-0x8000),
MAKE_FIXNUM(0x7FFF)));
} while(1);
}
#endif /* ecl_uint16_t */
#if defined(ecl_uint32_t) && (FIXNUM_BITS != 32)
ecl_uint32_t
ecl_to_uint32_t(cl_object x) {
do {
if (FIXNUMP(x)) {
cl_fixnum y = fix(x);
if (y >= 0 && y < 0xFFFFFFFFUL) {
return (ecl_uint32_t)y;
}
}
x = ecl_type_error(@'coerce', "variable", x,
cl_list(3,@'integer',MAKE_FIXNUM(0),
ecl_make_unsigned_integer(0xFFFFFFFFUL)));
} while(1);
}
ecl_int32_t
ecl_to_int32_t(cl_object x) {
do {
if (FIXNUMP(x)) {
cl_fixnum y = fix(x);
if (y >= -0x80000000 && y <= 0x7FFFFFFFL) {
return (ecl_int16_t)y;
}
}
x = ecl_type_error(@'coerce', "variable", x,
cl_list(3,@'integer',
ecl_make_integer(-0x80000000L),
ecl_make_integer(0x7FFFFFFFL)));
} while(1);
}
#endif /* ecl_uint32_t */
#if defined(ecl_uint64_t) && (FIXNUM_BITS < 64)
ecl_uint64_t
ecl_to_uint64_t(cl_object x) {
do {
# if !defined(WITH_GMP) || FIXNUM_BITS != 32
# error "Cannot handle ecl_uint64_t without GMP or 32/64 bits integer"
# endif
if (!ecl_minusp(x)) {
if (FIXNUMP(x)) {
return (ecl_uint64_t)fix(x);
} else {
ecl_uint64_t output;
mpz_t copy;
mpz_div_2exp(copy, x->big.big_num, 32);
if (mpz_fits_ulong_p(copy)) {
output = (ecl_uint64_t)mpz_get_ui(copy);
output = (output << 32) | mpz_get_ui(x->big.big_num);
mpz_clear(copy);
return output;
}
mpz_clear(copy);
}
}
x = ecl_type_error(@'coerce', "variable", x,
cl_list(3,@'integer',MAKE_FIXNUM(0),
ecl_one_minus(ecl_ash(MAKE_FIXNUM(1), 64))));
} while(1);
}
ecl_int64_t
ecl_to_int64_t(cl_object x) {
# if !defined(WITH_GMP) || FIXNUM_BITS != 32
# error "Cannot handle ecl_uint64_t without GMP or 32 bits fixnums"
# endif
do {
if (FIXNUMP(x)) {
return (ecl_uint64_t)fix(x);
} else {
ecl_int64_t output;
mpz_t copy;
mpz_div_2exp(copy, x->big.big_num, 64);
if (mpz_fits_ulong_p(copy)) {
output = (ecl_int64_t)mpz_get_si(copy);
output = (output << 32) | mpz_get_ui(x->big.big_num);
mpz_clear(copy);
return output;
}
mpz_clear(copy);
}
x = ecl_type_error(@'coerce', "variable", x,
cl_list(3,@'integer',
ecl_negate(ecl_ash(MAKE_FIXNUM(1), 63)),
ecl_one_minus(ecl_ash(MAKE_FIXNUM(1), 63))));
} while(1);
}
cl_object
ecl_make_uint64_t(ecl_uint64_t i)
{
cl_object aux = ecl_make_uint32_t(i >> 32);
return cl_logior(2, ecl_ash(aux, 32), ecl_make_uint32_t((ecl_uint32_t)i));
}
cl_object
ecl_make_int64_t(ecl_int64_t i)
{
cl_object aux = ecl_make_int32_t(i >> 32);
return cl_logior(2, ecl_ash(aux, 32), ecl_make_uint32_t((ecl_uint32_t)i));
}
#endif /* ecl_uint64_t */
cl_object
ecl_make_ratio(cl_object num, cl_object den)
{

View file

@ -9,6 +9,11 @@
#else
# define ECL_NAME(x) NULL
#endif
#ifdef ECL_RELATIVE_PACKAGE_NAMES
# define RELATIVE_PACKAGES_P Ct
#else
# define RELATIVE_PACKAGES_P Cnil
#endif
#ifdef DPP
#define CLOS_ "CLOS::"
#define EXT_ "EXT::"
@ -1617,7 +1622,7 @@ cl_symbols[] = {
{SYS_ "SET-FINALIZER", SI_ORDINARY, si_set_finalizer, 2, OBJNULL},
#ifdef ECL_RELATIVE_PACKAGE_NAMES
{SYS_ "*RELATIVE-PACKAGE-NAMES*", SI_SPECIAL, NULL, -1, Cnil},
{SYS_ "*RELATIVE-PACKAGE-NAMES*", SI_SPECIAL, NULL, -1, RELATIVE_PACKAGES_P},
{KEY_ "RELATIVE-PACKAGE-NAMES", KEYWORD, NULL, -1, OBJNULL},
{SYS_ "FIND-RELATIVE-PACKAGE", SI_ORDINARY, si_find_relative_package, -1, OBJNULL},
{SYS_ "PACKAGE-PARENT", SI_ORDINARY, NULL, -1, OBJNULL},

View file

@ -9,6 +9,11 @@
#else
# define ECL_NAME(x) NULL
#endif
#ifdef ECL_RELATIVE_PACKAGE_NAMES
# define RELATIVE_PACKAGES_P Ct
#else
# define RELATIVE_PACKAGES_P Cnil
#endif
#ifdef DPP
#define CLOS_ "CLOS::"
#define EXT_ "EXT::"

5678
src/configure vendored

File diff suppressed because it is too large Load diff

View file

@ -397,6 +397,9 @@ dnl ----------------------------------------------------------------------
dnl SONAME is only active when SONAME_LDFLAGS and SONAME are non nil
dnl
AC_MSG_CHECKING(for soname flags)
PACKAGE_MAJOR=`echo ${PACKAGE_VERSION} | sed -e 's,\(.*\)\..*\..*,\1,g'`
PACKAGE_MINOR=`echo ${PACKAGE_VERSION} | sed -e 's,.*\.\(.*\)\..*,\1,g'`
PACKAGE_LEAST=`echo ${PACKAGE_VERSION} | sed -e 's,.*\..*\.\(.*\),\1,g'`
if test "${enable_soname}" != yes; then
SONAME=''
SONAME1=''
@ -406,9 +409,6 @@ if test "${enable_soname}" != yes; then
SONAME_LDFLAGS=''
AC_MSG_RESULT([none])
else
PACKAGE_MAJOR=`echo ${PACKAGE_VERSION} | sed -e 's,\(.*\)\..*\..*,\1,g'`
PACKAGE_MINOR=`echo ${PACKAGE_VERSION} | sed -e 's,.*\.\(.*\)\..*,\1,g'`
PACKAGE_LEAST=`echo ${PACKAGE_VERSION} | sed -e 's,.*\..*\.\(.*\),\1,g'`
i="${PACKAGE_MAJOR}.${PACKAGE_MINOR}.${PACKAGE_LEAST}"
SONAME3=`echo $SONAME | sed "s,.SOVERSION,.$i,g"`
i="${PACKAGE_MAJOR}.${PACKAGE_MINOR}"
@ -425,6 +425,10 @@ AC_SUBST(SONAME1)
AC_SUBST(SONAME)
AC_SUBST(SONAME_LDFLAGS)
dnl Related to that, the package version number
ECL_VERSION_NUMBER=$(($PACKAGE_MAJOR * 10000 + $PACKAGE_MINOR * 100 + $PACKAGE_LEAST))
AC_SUBST(ECL_VERSION_NUMBER)
dnl ----------------------------------------------------------------------
dnl Deactivate floating point exceptions if asked to
if test "${with_fpe}" != yes; then
@ -484,6 +488,7 @@ dnl fi
dnl ----------------------------------------------------------------------
dnl Check the appropiate type for cl_fixnum/cl_index
ECL_FIXNUM_TYPE
ECL_INTEGER_TYPES
ECL_LINEFEED_MODE
ECL_FIND_SETJMP

View file

@ -85,6 +85,16 @@
/* Use mprotect for fast interrupt dispatch */
#undef ECL_USE_MPROTECT
/* Integer types */
#undef ecl_uint16_t
#undef ecl_int16_t
#undef ecl_uint32_t
#undef ecl_int32_t
#undef ecl_uint64_t
#undef ecl_int64_t
#undef ecl_long_long_t
#undef ecl_ulong_long_t
/*
* C TYPES AND SYSTEM LIMITS
*/
@ -264,8 +274,6 @@ typedef unsigned @CL_FIXNUM_TYPE@ cl_hashkey;
#undef HAVE_SIGPROCMASK
/* isatty() checks whether a file is connected to a */
#undef HAVE_ISATTY
/* compiler understands long long */
#undef HAVE_LONG_LONG
/* can manipulate floating point environment */
#undef HAVE_FENV_H
/* can activate individual traps in floating point environment */

View file

@ -27,12 +27,15 @@
#include <stdio.h> /* FILE */
#if !defined(_MSC_VER) && !defined(__sun)
#include <stdint.h> /* int8_t and friends */
#define ecl_int8_t int8_t
#define ecl_uint8_t uint8_t
#else
typedef char int8_t;
typedef short int16_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef int int32_t;
#define ecl_uint8_t unsigned char
#define ecl_int8_t char
#define ecl_uint16_t unsigned short
#define ecl_int16_t short
#define ecl_uint32_t unsigned int
#define ecl_int32_t int
#endif
/* Microsoft VC++ does not have va_copy() */
#if defined(_MSC_VER) || !defined(va_copy)

View file

@ -939,6 +939,47 @@ extern ECL_API cl_fixnum ecl_fixnum_in_range(cl_object fun, const char *what, cl
cl_fixnum min, cl_fixnum max);
extern ECL_API cl_object ecl_make_integer(cl_fixnum i);
extern ECL_API cl_object ecl_make_unsigned_integer(cl_index i);
extern ECL_API ecl_uint8_t ecl_to_uint8_t(cl_object o);
extern ECL_API ecl_int8_t ecl_to_int8_t(cl_object o);
#define ecl_make_uint8_t(i) MAKE_FIXNUM(i)
#define ecl_make_int8_t(i) MAKE_FIXNUM(i)
#if FIXNUM_BITS < 32
# error "Unsupported platforms with FIXNUM_BITS < 32"
#endif
#ifdef ecl_uint16_t
extern ECL_API ecl_uint16_t ecl_to_uint16_t(cl_object o);
extern ECL_API ecl_int16_t ecl_to_int16_t(cl_object o);
# define ecl_make_uint16_t(i) MAKE_FIXNUM(i)
# define ecl_make_int16_t(i) MAKE_FIXNUM(i)
#endif /* ecl_uint16_t */
#ifdef ecl_uint32_t
# if FIXNUM_BITS == 32
# define ecl_to_uint32_t fixnnint
# define ecl_to_int32_t fixnint
# define ecl_make_uint32_t ecl_make_unsigned_integer
# define ecl_make_int32_t ecl_make_integer
# else
# define ecl_make_uint32_t(i) MAKE_FIXNUM(i)
# define ecl_make_int32_t(i) MAKE_FIXNUM(i)
extern ECL_API ecl_uint32_t ecl_to_uint32_t(cl_object o);
extern ECL_API ecl_int32_t ecl_to_int32_t(cl_object o);
# endif
#endif /* ecl_uint32_t */
#ifdef ecl_uint64_t
# if FIXNUM_BITS == 64
# define ecl_to_uint64_t fixnnint
# define ecl_to_int64_t fixint
# define ecl_make_uint64_t ecl_make_unsigned_integer
# define ecl_make_int64_t ecl_make_integer
# else
extern ECL_API cl_object ecl_make_uint64_t(ecl_uint64_t i);
extern ECL_API cl_object ecl_make_int64_t(ecl_int64_t i);
# endif
#endif /* ecl_uint64_t */
extern ECL_API cl_object ecl_make_ratio(cl_object num, cl_object den);
extern ECL_API cl_object ecl_make_singlefloat(float f);
extern ECL_API cl_object ecl_make_doublefloat(double f);

View file

@ -187,11 +187,11 @@ struct ecl_bignum {
#else /* WITH_GMP */
# ifdef HAVE_LONG_LONG
# ifdef ecl_long_long_t
typedef long long int big_num_t;
# else /* HAVE_LONG_LONG */
# else
typedef long int big_num_t; /* would it work? */
# endif /* HAVE_LONG_LONG */
# endif /* ecl_long_long_t */
struct ecl_bignum {
HEADER;