scm_wta_* procedures replace SCM_WTA_* macros
[bpt/guile.git] / libguile / __scm.h
index d486b69..c437d60 100644 (file)
@@ -3,21 +3,23 @@
 #ifndef SCM___SCM_H
 #define SCM___SCM_H
 
-/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003, 2006, 2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2006,
+ *   2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
  */
 
 \f
  * additional information to the developers.
  */
 
+/* Return true (non-zero) if GCC version MAJ.MIN or later is being used
+ * (macro taken from glibc.)  */
+#if defined __GNUC__ && defined __GNUC_MINOR__
+# define SCM_GNUC_PREREQ(maj, min) \
+       ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+# define SCM_GNUC_PREREQ(maj, min) 0
+#endif
+
 /* The macro SCM_NORETURN indicates that a function will never return.
  * Examples:
  *   1) int foo (char arg) SCM_NORETURN;
@@ -88,7 +99,7 @@
 /* The SCM_EXPECT macros provide branch prediction hints to the compiler.  To
  * use only in places where the result of the expression under "normal"
  * circumstances is known.  */
-#if defined(__GNUC__) && (__GNUC__ >= 3)
+#if SCM_GNUC_PREREQ (3, 0)
 # define SCM_EXPECT    __builtin_expect
 #else
 # define SCM_EXPECT(_expr, _value) (_expr)
 #define SCM_UNLIKELY(_expr)  SCM_EXPECT ((_expr), 0)
 
 /* The SCM_INTERNAL macro makes it possible to explicitly declare a function
- * as having "internal" linkage.  */
-#if (defined __GNUC__) && \
-  ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ == 3))
-# define SCM_INTERNAL  extern __attribute__ ((__visibility__ ("internal")))
+ * as having "internal" linkage.  However our current tack on this problem is
+ * to use GCC 4's -fvisibility=hidden, making functions internal by default,
+ * and then SCM_API marks them for export. */
+#define SCM_INTERNAL  extern
+
+/* The SCM_DEPRECATED macro is used in declarations of deprecated functions
+ * or variables.  Defining `SCM_BUILDING_DEPRECATED_CODE' allows deprecated
+ * functions to be implemented in terms of deprecated functions, and allows
+ * deprecated functions to be referred to by `scm_c_define_gsubr ()'.  */
+#if !defined (SCM_BUILDING_DEPRECATED_CODE) && SCM_GNUC_PREREQ (3, 0)
+# define SCM_DEPRECATED  SCM_API __attribute__ ((__deprecated__))
 #else
-# define SCM_INTERNAL  extern
+# define SCM_DEPRECATED  SCM_API
 #endif
 
+/* The SCM_ALIGNED macro, when defined, can be used to instruct the compiler
+ * to honor the given alignment constraint.  */
+#if defined __GNUC__
+# define SCM_ALIGNED(x)  __attribute__ ((aligned (x)))
+#elif defined __INTEL_COMPILER
+# define SCM_ALIGNED(x)  __declspec (align (x))
+#else
+/* Don't know how to align things.  */
+# undef SCM_ALIGNED
+#endif
 
-\f
-/* {Supported Options}
- *
- * These may be defined or undefined.
- */
-
-/* #define GUILE_DEBUG_FREELIST */
-
-/* All the number support there is.
- */
-#define BIGNUMS
-
-/* GC should relinquish empty cons-pair arenas. */
-/* cmm:FIXME look at this after done mangling the GC */
-/* #define GC_FREE_SEGMENTS */
-
-/* Provide a scheme-accessible count-down timer that
- * generates a pseudo-interrupt.
- */
-#define TICKS
-
-
-/* Use engineering notation when converting numbers strings?
- */
-#undef ENGNOT
-
-\f
-/* {Unsupported Options}
- *
- * These must be defined as given here.
- */
-
-
-#define CCLO
-
-/* Guile Scheme supports the #f/() distinction; Guile Lisp won't.  We
-   have horrible plans for their unification.  */
-#undef SICP
-
-\f
-
-/* Random options (not yet supported or in final form). */
-
-#define STACK_CHECKING
-#undef NO_CEVAL_STACK_CHECKING
+/* The SCM_MALLOC macro can be used in function declarations to tell the
+ * compiler that a function may be treated as if any non-NULL pointer it returns
+ * cannot alias any other pointer valid when the function returns.  */
+#if SCM_GNUC_PREREQ (3, 0)
+# define SCM_MALLOC  __attribute__ ((__malloc__))
+#else
+# define SCM_MALLOC
+#endif
 
 \f
 
 /* SCM_API is a macro prepended to all function and data definitions
-   which should be exported or imported in the resulting dynamic link
-   library (DLL) in the Win32 port. */
-
-#if defined (SCM_IMPORT)
-# define SCM_API __declspec (dllimport) extern
-#elif defined (SCM_EXPORT) || defined (DLL_EXPORT)
-# define SCM_API __declspec (dllexport) extern
+   which should be exported from libguile. */
+
+#if defined BUILDING_LIBGUILE && defined HAVE_VISIBILITY
+# define SCM_API extern __attribute__((__visibility__("default")))
+#elif defined BUILDING_LIBGUILE && defined _MSC_VER
+# define SCM_API __declspec(dllexport) extern
+#elif defined _MSC_VER
+# define SCM_API __declspec(dllimport) extern
 #else
 # define SCM_API extern
 #endif
 #define SCM_DEBUG 0
 #endif
 
-/* For debugging purposes: define this is to ensure nobody is using
- * the mark bits outside of the marking phase.  This is meant for
- * debugging purposes only.
- */
-#ifndef SCM_DEBUG_MARKING_API
-#define SCM_DEBUG_MARKING_API 0
-#endif
-
 /* If SCM_DEBUG_CELL_ACCESSES is set to 1, cell accesses will perform
  * exhaustive parameter checking:  It will be verified that cell parameters
  * actually point to a valid heap cell.  Note:  If this option is enabled,
 #define SCM_DEBUG_CELL_ACCESSES SCM_DEBUG
 #endif
 
-/* If SCM_DEBUG_INTERRUPTS is set to 1, with every deferring and allowing of
- * interrupts a consistency check will be performed.
- */
-#ifndef SCM_DEBUG_INTERRUPTS
-#define SCM_DEBUG_INTERRUPTS SCM_DEBUG
-#endif
-
 /* If SCM_DEBUG_PAIR_ACCESSES is set to 1, accesses to cons cells will be
  * exhaustively checked.  Note:  If this option is enabled, guile will run
  * slower than normally.
 #define SCM_DEBUG_REST_ARGUMENT SCM_DEBUG
 #endif
 
-/* The macro SCM_DEBUG_TYPING_STRICTNESS indicates what level of type checking
- * shall be performed with respect to the use of the SCM datatype.  The macro
- * may be defined to one of the values 0, 1 and 2.
- *
- * A value of 0 means that there will be no compile time type checking, since
- * the SCM datatype will be declared as an integral type.  This setting should
- * only be used on systems, where casting from integral types to pointers may
- * lead to loss of bit information.
- *
- * A value of 1 means that there will an intermediate level of compile time
- * type checking, since the SCM datatype will be declared as a pointer to an
- * undefined struct.  This setting is the default, since it does not cost
- * anything in terms of performance or code size.
- *
- * A value of 2 provides a maximum level of compile time type checking since
- * the SCM datatype will be declared as a struct.  This setting should be used
- * for _compile time_ type checking only, since the compiled result is likely
- * to be quite inefficient.  The right way to make use of this option is to do
- * a 'make clean; make CFLAGS=-DSCM_DEBUG_TYPING_STRICTNESS=2', fix your
- * errors, and then do 'make clean; make'.
- */
-#ifndef SCM_DEBUG_TYPING_STRICTNESS
-#define SCM_DEBUG_TYPING_STRICTNESS 1
-#endif
-
-/* If SCM_DEBUG_DEBUGGING_SUPPORT is set to 1, guile will provide a set of
- * special functions that support debugging with a debugger like gdb or
- * debugging of guile internals on the scheme level.  The behaviour of guile
- * is not changed by this macro, only the set of functions that are available
- * will differ.  All functions that are introduced this way have the prefix
- * 'scm_dbg_' on the C level and the prefix 'dbg-' on the scheme level.  This
- * allows to easily determine the set of support functions, given that your
- * debugger or repl provide automatic name completion.  Note that these
- * functions are intended to be used during interactive debugging sessions
- * only.  They are not considered part of guile's official API.  They may
- * change or disappear without notice or deprecation phase.
- */
-#ifndef SCM_DEBUG_DEBUGGING_SUPPORT
-#define SCM_DEBUG_DEBUGGING_SUPPORT SCM_DEBUG
-#endif
-
 \f
 
 /* {Feature Options}
 # define SCM_LONG_BIT (SCM_CHAR_BIT * sizeof (long) / sizeof (char))
 #endif
 
-#ifdef UCHAR_MAX
-# define SCM_CHAR_CODE_LIMIT (UCHAR_MAX + 1L)
-#else
-# define SCM_CHAR_CODE_LIMIT 256L
-#endif
-
 #define SCM_I_UTYPE_MAX(type)      ((type)-1)
 #define SCM_I_TYPE_MAX(type,umax)  ((type)((umax)/2))
 #define SCM_I_TYPE_MIN(type,umax)  (-((type)((umax)/2))-1)
 #define SCM_T_INT32_MIN   SCM_I_TYPE_MIN(scm_t_int32,SCM_T_UINT32_MAX)
 #define SCM_T_INT32_MAX   SCM_I_TYPE_MAX(scm_t_int32,SCM_T_UINT32_MAX)
 
-#if SCM_HAVE_T_INT64
 #define SCM_T_UINT64_MAX  SCM_I_UTYPE_MAX(scm_t_uint64)
 #define SCM_T_INT64_MIN   SCM_I_TYPE_MIN(scm_t_int64,SCM_T_UINT64_MAX)
 #define SCM_T_INT64_MAX   SCM_I_TYPE_MAX(scm_t_int64,SCM_T_UINT64_MAX)
-#endif
-
-#if SCM_SIZEOF_LONG_LONG
-#define SCM_I_ULLONG_MAX  SCM_I_UTYPE_MAX(unsigned long long)
-#define SCM_I_LLONG_MIN   SCM_I_TYPE_MIN(long long,SCM_I_ULLONG_MAX)
-#define SCM_I_LLONG_MAX   SCM_I_TYPE_MAX(long long,SCM_I_ULLONG_MAX)
-#endif
 
 #define SCM_T_UINTMAX_MAX SCM_I_UTYPE_MAX(scm_t_uintmax)
 #define SCM_T_INTMAX_MIN  SCM_I_TYPE_MIN(scm_t_intmax,SCM_T_UINTMAX_MAX)
 #define SCM_T_INTMAX_MAX  SCM_I_TYPE_MAX(scm_t_intmax,SCM_T_UINTMAX_MAX)
 
-#define SCM_I_SIZE_MAX    SCM_I_UTYPE_MAX(size_t)
-#define SCM_I_SSIZE_MIN   SCM_I_TYPE_MIN(ssize_t,SCM_I_SIZE_MAX)
-#define SCM_I_SSIZE_MAX   SCM_I_TYPE_MAX(ssize_t,SCM_I_SIZE_MAX)
+#define SCM_T_UINTPTR_MAX SCM_I_UTYPE_MAX(scm_t_uintptr)
+#define SCM_T_INTPTR_MIN  SCM_I_TYPE_MIN(scm_t_intptr,SCM_T_UINTPTR_MAX)
+#define SCM_T_INTPTR_MAX  SCM_I_TYPE_MAX(scm_t_intptr,SCM_T_UINTPTR_MAX)
 
 \f
 
 #include "libguile/tags.h"
 
+
+/* The type of subrs, i.e., Scheme procedures implemented in C.  Empty
+   function declarators are used internally for pointers to functions of
+   any arity.  However, these are equivalent to `(void)' in C++, are
+   obsolescent as of C99, and trigger `strict-prototypes' GCC warnings
+   (bug #23681).  */
+
+#ifdef BUILDING_LIBGUILE
+typedef SCM (* scm_t_subr) ();
+#else
+typedef void *scm_t_subr;
+#endif
+
 \f
-#ifdef vms
-# ifndef CHEAP_CONTINUATIONS
-   typedef int jmp_buf[17];
-   extern int setjump(jmp_buf env);
-   extern int longjump(jmp_buf env, int ret);
-#  define setjmp setjump
-#  define longjmp longjump
-# else
-#  include <setjmp.h>
-# endif
-#else                          /* ndef vms */
-# ifdef _CRAY1
-    typedef int jmp_buf[112];
-    extern int setjump(jmp_buf env);
-    extern int longjump(jmp_buf env, int ret);
-#  define setjmp setjump
-#  define longjmp longjump
-# else                         /* ndef _CRAY1 */
-#  if defined (__ia64__)
-/* For IA64, emulate the setjmp API using getcontext. */
-#   include <signal.h>
-#   include <ucontext.h>
-    typedef struct {
-      ucontext_t ctx;
-      int fresh;
-    } jmp_buf;
-#   define setjmp(JB)                                  \
-      ( (JB).fresh = 1,                                        \
-        getcontext (&((JB).ctx)),                      \
-        ((JB).fresh ? ((JB).fresh = 0, 0) : 1) )
-#   define longjmp(JB,VAL) scm_ia64_longjmp (&(JB), VAL)
-    void scm_ia64_longjmp (jmp_buf *, int);
-#  else                        /* ndef __ia64__ */
-#   include <setjmp.h>
-#  endif                       /* ndef __ia64__ */
-# endif                                /* ndef _CRAY1 */
-#endif                         /* ndef vms */
-
-/* James Clark came up with this neat one instruction fix for
- * continuations on the SPARC.  It flushes the register windows so
- * that all the state of the process is contained in the stack.
+
+/* scm_i_jmp_buf
+ *
+ * The corresponding SCM_I_SETJMP and SCM_I_LONGJMP are defined in the
+ * _scm.h private header.
  */
 
-#if defined (sparc) || defined (__sparc__) || defined (__sparc)
-# define SCM_FLUSH_REGISTER_WINDOWS asm("ta 3")
+#if defined (vms)
+typedef int scm_i_jmp_buf[17];
+
+#elif defined (_CRAY1)
+typedef int scm_i_jmp_buf[112];
+
+#elif defined (__ia64__)
+# include <signal.h>
+# include <ucontext.h>
+typedef struct {
+  ucontext_t ctx;
+  int fresh;
+} scm_i_jmp_buf;
+
 #else
-# define SCM_FLUSH_REGISTER_WINDOWS /* empty */
+# include <setjmp.h>
+typedef jmp_buf scm_i_jmp_buf;
 #endif
 
+
+\f
+
 /* If stack is not longword aligned then
  */
 
@@ -475,119 +390,14 @@ typedef long SCM_STACKITEM;
 #define SCM_STACK_PTR(ptr) ((SCM_STACKITEM *) (void *) (ptr))
 \f
 
-#define SCM_ASYNC_TICK /*fixme* should change names */ \
-do { \
-  if (SCM_I_CURRENT_THREAD->pending_asyncs) \
-    scm_async_click (); \
-} while (0)
-
-
-/* Anthony Green writes:
-   When the compiler sees...
-          DEFER_INTS;
-          [critical code here]
-          ALLOW_INTS;
-   ...it doesn't actually promise to keep the critical code within the
-   boundries of the DEFER/ALLOW_INTS instructions. It may very well
-   schedule it outside of the magic defined in those macros.
-
-   However, GCC's volatile asm feature forms a barrier over which code is
-   never moved. So if you add...
-          asm ("");
-   ...to each of the DEFER_INTS and ALLOW_INTS macros, the critical
-   code will always remain in place.  asm's without inputs or outputs
-   are implicitly volatile. */
-#ifdef __GNUC__
-#define SCM_FENCE asm /* volatile */ ("")
-#elif defined (__INTEL_COMPILER) && defined (__ia64)
-#define SCM_FENCE __memory_barrier()
+#ifdef BUILDING_LIBGUILE
+#define SCM_TICK SCM_ASYNC_TICK
 #else
-#define SCM_FENCE
+#define SCM_TICK scm_async_tick ()
 #endif
 
-#define SCM_TICK \
-do { \
-  SCM_ASYNC_TICK; \
-  SCM_THREAD_SWITCHING_CODE; \
-} while (0)
-
 \f
 
-/** SCM_ASSERT
- **
- **/
-
-
-#ifdef SCM_RECKLESS
-#define SCM_ASSERT(_cond, _arg, _pos, _subr)
-#define SCM_ASSERT_TYPE(_cond, _arg, _pos, _subr, _msg)
-#define SCM_ASRTGO(_cond, _label)
-#else
-#define SCM_ASSERT(_cond, _arg, _pos, _subr)                   \
-        do { if (SCM_UNLIKELY (!(_cond)))                      \
-          scm_wrong_type_arg (_subr, _pos, _arg); } while (0)
-#define SCM_ASSERT_TYPE(_cond, _arg, _pos, _subr, _msg)                        \
-        do { if (SCM_UNLIKELY (!(_cond)))                              \
-          scm_wrong_type_arg_msg(_subr, _pos, _arg, _msg);  } while (0)
-#define SCM_ASRTGO(_cond, _label)              \
-        do {  if (SCM_UNLIKELY (!(_cond)))     \
-          goto _label; } while (0)
-#endif
-
-/*
- * SCM_WTA_DISPATCH
- */
-
-/* Dirk:FIXME:: In all of the SCM_WTA_DISPATCH_* macros it is assumed that
- * 'gf' is zero if uninitialized.  It would be cleaner if some valid SCM value
- * like SCM_BOOL_F or SCM_UNDEFINED was chosen.
- */
-
-SCM_API SCM scm_call_generic_0 (SCM gf);
-
-#define SCM_WTA_DISPATCH_0(gf, subr)                           \
-  return (SCM_UNPACK (gf)                                      \
-         ? scm_call_generic_0 ((gf))                           \
-         : (scm_error_num_args_subr ((subr)), SCM_UNSPECIFIED))
-#define SCM_GASSERT0(cond, gf, subr)           \
-  if (SCM_UNLIKELY(!(cond)))           \
-    SCM_WTA_DISPATCH_0((gf), (subr))
-
-SCM_API SCM scm_call_generic_1 (SCM gf, SCM a1);
-
-#define SCM_WTA_DISPATCH_1(gf, a1, pos, subr)                  \
-  return (SCM_UNPACK (gf)                                      \
-         ? scm_call_generic_1 ((gf), (a1))                     \
-         : (scm_wrong_type_arg ((subr), (pos), (a1)), SCM_UNSPECIFIED))
-#define SCM_GASSERT1(cond, gf, a1, pos, subr)          \
-  if (SCM_UNLIKELY (!(cond)))                  \
-    SCM_WTA_DISPATCH_1((gf), (a1), (pos), (subr))
-
-SCM_API SCM scm_call_generic_2 (SCM gf, SCM a1, SCM a2);
-
-#define SCM_WTA_DISPATCH_2(gf, a1, a2, pos, subr)                      \
-  return (SCM_UNPACK (gf)                                              \
-         ? scm_call_generic_2 ((gf), (a1), (a2))                       \
-         : (scm_wrong_type_arg ((subr), (pos),                         \
-                                (pos) == SCM_ARG1 ? (a1) : (a2)),      \
-            SCM_UNSPECIFIED))
-#define SCM_GASSERT2(cond, gf, a1, a2, pos, subr)      \
-  if (SCM_UNLIKELY (!(cond)))                  \
-    SCM_WTA_DISPATCH_2((gf), (a1), (a2), (pos), (subr))
-
-SCM_API SCM scm_apply_generic (SCM gf, SCM args);
-
-#define SCM_WTA_DISPATCH_n(gf, args, pos, subr)                                  \
-  return (SCM_UNPACK (gf)                                                \
-         ? scm_apply_generic ((gf), (args))                              \
-         : (scm_wrong_type_arg ((subr), (pos),                           \
-                                scm_list_ref ((args),                    \
-                                              scm_from_int ((pos) - 1))), \
-            SCM_UNSPECIFIED))
-#define SCM_GASSERTn(cond, gf, args, pos, subr)                \
-  if (SCM_UNLIKELY (!(cond)))                  \
-    SCM_WTA_DISPATCH_n((gf), (args), (pos), (subr))
-
 #ifndef SCM_MAGIC_SNARFER
 /* Let these macros pass through if
    we are snarfing;  thus we can tell the
@@ -642,6 +452,14 @@ SCM_API SCM scm_apply_generic (SCM gf, SCM args);
 #define SCM_C_INLINE_KEYWORD
 #endif
 
+/* Handling thread-local storage (TLS).  */
+
+#ifdef SCM_HAVE_THREAD_STORAGE_CLASS
+# define SCM_THREAD_LOCAL __thread
+#else
+# define SCM_THREAD_LOCAL
+#endif
+
 #endif  /* SCM___SCM_H */
 
 /*