Mercurial > hg > xemacs-beta
diff src/lisp-union.h @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 3d6bfa290dbd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lisp-union.h Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,218 @@ +/* Fundamental definitions for XEmacs Lisp interpreter -- union objects. + Copyright (C) 1985, 1986, 1987, 1992, 1993, 1994 + Free Software Foundation, Inc. + +This file is part of XEmacs. + +XEmacs is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +XEmacs 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 General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: FSF 19.30. Split out from lisp.h. */ + +#if (!!defined (WORDS_BIGENDIAN) != !!defined (LOWTAGS)) + +/* Big-endian lowtags, little-endian hightags */ +typedef +union Lisp_Object + { + struct + { + unsigned EMACS_INT type_mark: GCTYPEBITS + 1; + signed EMACS_INT val: VALBITS; + } s; + struct + { +#ifdef __GNUC__ /* Non-ANSI extension */ + enum Lisp_Type type: GCTYPEBITS; +#else + unsigned EMACS_INT type: GCTYPEBITS; +#endif /* __GNUC__ */ + /* The markbit is not really part of the value of a Lisp_Object, + and is always zero except during garbage collection. */ + unsigned EMACS_INT markbit: 1; + unsigned EMACS_INT val: VALBITS; + } gu; + EMACS_INT i; + /* GCC bites yet again. I fart in the general direction of + the GCC authors. + + This was formerly declared 'void *v' etc. but that causes + GCC to accept any (yes, any) pointer as the argument of + a function declared to accept a Lisp_Object. */ + struct __nosuchstruct__ *v; + CONST struct __nosuchstruct__ *cv; /* C wanks */ + } +Lisp_Object; + +#else /* If WORDS_BIGENDIAN, or little-endian hightags */ + +/* Big-endian hightags, little-endian lowtags */ +typedef +union Lisp_Object + { + struct + { + signed EMACS_INT val: VALBITS; + unsigned EMACS_INT mark_type: GCTYPEBITS + 1; + } s; + struct + { + unsigned EMACS_INT val: VALBITS; +#ifdef __GNUC__ /* Non-ANSI extension */ + enum Lisp_Type type: GCTYPEBITS; +#else + unsigned EMACS_INT type: GCTYPEBITS; +#endif /* __GNUC__ */ + /* The markbit is not really part of the value of a Lisp_Object, + and is always zero except during garbage collection. */ + unsigned EMACS_INT markbit: 1; + } gu; + EMACS_INT i; + struct __nosuchstruct__ *v; + CONST struct __nosuchstruct__ *cv; /* C sucks */ + } +Lisp_Object; + +#endif /* BIG/LITTLE_ENDIAN vs HIGH/LOWTAGS */ + + +#ifndef XMAKE_LISP +#if (__GNUC__ > 1) +/* Use GCC's struct initializers feature */ +#define XMAKE_LISP(vartype,ptr) \ + ((union Lisp_Object) { gu: { markbit: 0, \ + type: (vartype), \ + val: ((unsigned EMACS_INT) ptr) } }) +#endif /* __GNUC__ */ +#endif /* !XMAKE_LISP */ + + +#ifdef XMAKE_LISP +#define Qzero (XMAKE_LISP (Lisp_Int, 0)) +#define make_int(a) (XMAKE_LISP (Lisp_Int, (a))) +#else +extern Lisp_Object Qzero; +#endif + + +#define EQ(x,y) ((x).v == (y).v) +#define GC_EQ(x,y) ((x).gu.val == (y).gu.val && (x).gu.type == (y).gu.type) + +#define XTYPE(a) ((enum Lisp_Type) (a).gu.type) +#define XSETTYPE(a,b) ((a).gu.type = (b)) +#define XGCTYPE(a) XTYPE (a) + +/* This was commented out a long time ago. I uncommented it, but it + makes the Alpha crash, and that's the only system that would use + this, so it stays commented out. */ +#if 0 /* EXPLICIT_SIGN_EXTEND */ +/* Make sure we sign-extend; compilers have been known to fail to do so. */ +#define XREALINT(a) (((a).i << ((LONGBITS) - (VALBITS))) >> ((LONGBITS) - (VALBITS))) +#else +#define XREALINT(a) ((a).s.val) +#endif /* EXPLICIT_SIGN_EXTEND */ + +#if 0 +/* XFASTINT is error-prone and saves a few instructions at best, + so there's really no point to it. Just use XINT() or make_int() + instead. --ben */ +/* The + 0 is to prevent XFASTINT being used on the LHS of an assignment */ +#define XFASTINT(a) ((a).gu.val + 0) +#endif /* 0 */ + +#define XUINT(a) ((a).gu.val) +#ifdef HAVE_SHM +/* In this representation, data is found in two widely separated segments. */ +extern int pure_size; +# define XPNTR(a) \ + ((void *)(((a).gu.val) | ((a).gu.val > pure_size ? DATA_SEG_BITS : PURE_SEG_BITS))) +#else /* not HAVE_SHM */ +# ifdef DATA_SEG_BITS +/* This case is used for the rt-pc and hp-pa. + In the diffs I was given, it checked for ptr = 0 + and did not adjust it in that case. + But I don't think that zero should ever be found + in a Lisp object whose data type says it points to something. + */ +# define XPNTR(a) ((void *)(((a).gu.val) | DATA_SEG_BITS)) +# else /* not DATA_SEG_BITS */ +# define XPNTR(a) ((void *) ((a).gu.val)) +# endif /* not DATA_SEG_BITS */ +#endif /* not HAVE_SHM */ +#define XSETINT(a, b) do { ((a) = make_int (b)); } while (0) +#define XSETUINT(a, b) XSETINT (a, b) +#define XSETPNTR(a, b) XSETINT (a, b) + +#define XSETCHAR(a, b) do { ((a) = make_char (b)); } while (0) + +/* XSETOBJ was formerly named XSET. The name change was made to catch + C code that attempts to use this macro. You should always use the + individual settor macros (XSETCONS, XSETBUFFER, etc.) instead. */ + +#ifdef XMAKE_LISP +#define XSETOBJ(var,vartype,ptr) \ + do { ((var) = XMAKE_LISP (vartype, ptr)); } while (0) +#else +/* This is haired up to avoid evaluating var twice... + This is necessary only in the "union" version. + The "int" version has never done double evaluation. + */ +/* XEmacs change: put the assignment to val first; otherwise you + can trip up the error_check_*() stuff */ +#define XSETOBJ(var, vartype, ptr) \ + do { \ + Lisp_Object *tmp_xset_var = &(var); \ + (*tmp_xset_var).s.val = ((EMACS_INT) (ptr)); \ + (*tmp_xset_var).gu.markbit = 0; \ + (*tmp_xset_var).gu.type = (vartype); \ + } while (0) +#endif /* undefined XMAKE_LISP */ + +/* During garbage collection, XGCTYPE must be used for extracting types + so that the mark bit is ignored. XMARKBIT access the markbit. + Markbits are used only in particular slots of particular structure types. + Other markbits are always zero. + Outside of garbage collection, all mark bits are always zero. */ + + +#define XMARKBIT(a) ((a).gu.markbit) +#define XSETMARKBIT(a,b) do { (XMARKBIT (a) = (b)); } while (0) +#define XMARK(a) do { XMARKBIT (a) = 1; } while (0) +/* no 'do {} while' because this is used in a mondo macro in lrecord.h */ +#define XUNMARK(a) (XMARKBIT (a) = 0) + +/* Use this for turning a (void *) into a Lisp_Object, as when the + Lisp_Object is passed into a toolkit callback function */ +#define VOID_TO_LISP(larg,varg) \ + do { ((larg).v = (struct __nosuchstruct__ *) (varg)); } while (0) +#define CVOID_TO_LISP(larg,varg) \ + do { ((larg).cv = (CONST struct __nosuchstruct__ *) (varg)); } while (0) + +/* Use this for turning a Lisp_Object into a (void *), as when the + Lisp_Object is passed into a toolkit callback function */ +#define LISP_TO_VOID(larg) ((void *) ((larg).v)) +#define LISP_TO_CVOID(larg) ((CONST void *) ((larg).cv)) + +/* Convert a Lisp_Object into something that can't be used as an + lvalue. Useful for type-checking. */ +#if (__GNUC__ > 1) +#define NON_LVALUE(larg) ({ (larg); }) +#else +/* Well, you can't really do it without using a function call, and + there's no real point in that; no-union-type is the rule, and that + will catch errors. */ +#define NON_LVALUE(larg) (larg) +#endif +