Mercurial > hg > xemacs-beta
diff src/lisp.h @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lisp.h Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,1841 @@ +/* Fundamental definitions for XEmacs Lisp interpreter. + Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc. + Copyright (C) 1993-1996 Richard Mlynarik. + Copyright (C) 1995, 1996 Ben Wing. + +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. */ + +#ifndef _XEMACS_LISP_H_ +#define _XEMACS_LISP_H_ + +/************************************************************************/ +/* general definitions */ +/************************************************************************/ + +/* We include the following generally useful header files so that you + don't have to worry about prototypes when using the standard C + library functions and macros. These files shouldn't be excessively + large so they shouldn't cause that much of a slowdown. */ + +#include <stdlib.h> +#include <string.h> /* primarily for memcpy, etc. */ +#include <stdio.h> /* NULL, etc. */ +#include <ctype.h> +#include <stdarg.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifndef INCLUDED_FCNTL +# define INCLUDED_FCNTL +# include <fcntl.h> +#endif /* INCLUDED_FCNTL */ + +#ifdef __lucid +# include <sysent.h> +#endif + +#include "blocktype.h" /* A generally useful include */ +#include "dynarr.h" /* A generally useful include */ +#include "symsinit.h" /* compiler warning suppression */ + +/* Also define min() and max(). (Some compilers put them in strange + places that won't be referenced by the above include files, such + as 'macros.h' under Solaris.) */ + +#ifndef min +#define min(a,b) ((a) <= (b) ? (a) : (b)) +#endif +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif + +/* Emacs needs to use its own definitions of certain system calls on + some systems (like SunOS 4.1 and USG systems, where the read system + call is interruptible but Emacs expects it not to be; and under + MULE, where all filenames need to be converted to external format). + To do this, we #define read to be sys_read, which is defined in + sysdep.c. We first #undef read, in case some system file defines + read as a macro. sysdep.c doesn't encapsulate read, so the call to + read inside of sys_read will do the right thing. + + DONT_ENCAPSULATE is used in files such as sysdep.c that want to + call the actual system calls rather than the encapsulated versions. + Those files can call sys_read to get the (possibly) encapsulated + versions. + + IMPORTANT: the redefinition of the system call must occur *after* the + inclusion of any header files that declare or define the system call; + otherwise lots of unfriendly things can happen. This goes for all + encapsulated system calls. + + We encapsulate the most common system calls here; we assume their + declarations are in one of the standard header files included above. + Other encapsulations are declared in the appropriate sys*.h file. */ + +#if defined (ENCAPSULATE_READ) && !defined (DONT_ENCAPSULATE) +# undef read +# define read sys_read +#endif +#if !defined (ENCAPSULATE_READ) && defined (DONT_ENCAPSULATE) +# define sys_read read +#endif + +#if defined (ENCAPSULATE_WRITE) && !defined (DONT_ENCAPSULATE) +# undef write +# define write sys_write +#endif +#if !defined (ENCAPSULATE_WRITE) && defined (DONT_ENCAPSULATE) +# define sys_write write +#endif + +#if defined (ENCAPSULATE_OPEN) && !defined (DONT_ENCAPSULATE) +# undef open +# define open sys_open +#endif +#if !defined (ENCAPSULATE_OPEN) && defined (DONT_ENCAPSULATE) +# define sys_open open +#endif + +#if defined (ENCAPSULATE_CLOSE) && !defined (DONT_ENCAPSULATE) +# undef close +# define close sys_close +#endif +#if !defined (ENCAPSULATE_CLOSE) && defined (DONT_ENCAPSULATE) +# define sys_close close +#endif + +/* Now the stdio versions ... */ + +#if defined (ENCAPSULATE_FREAD) && !defined (DONT_ENCAPSULATE) +# undef fread +# define fread sys_fread +#endif +#if !defined (ENCAPSULATE_FREAD) && defined (DONT_ENCAPSULATE) +# define sys_fread fread +#endif + +#if defined (ENCAPSULATE_FWRITE) && !defined (DONT_ENCAPSULATE) +# undef fwrite +# define fwrite sys_fwrite +#endif +#if !defined (ENCAPSULATE_FWRITE) && defined (DONT_ENCAPSULATE) +# define sys_fwrite fwrite +#endif + +#if defined (ENCAPSULATE_FOPEN) && !defined (DONT_ENCAPSULATE) +# undef fopen +# define fopen sys_fopen +#endif +#if !defined (ENCAPSULATE_FOPEN) && defined (DONT_ENCAPSULATE) +# define sys_fopen fopen +#endif + +#if defined (ENCAPSULATE_FCLOSE) && !defined (DONT_ENCAPSULATE) +# undef fclose +# define fclose sys_fclose +#endif +#if !defined (ENCAPSULATE_FCLOSE) && defined (DONT_ENCAPSULATE) +# define sys_fclose fclose +#endif + +/* generally useful */ +#define countof(x) (sizeof(x)/sizeof(x[0])) +#define slot_offset(type, slot_name) \ + ((unsigned) (((char *) (&(((type *)0)->slot_name))) - ((char *)0))) +#define malloc_type(type) ((type *) xmalloc (sizeof (type))) +#define malloc_type_and_zero(type) ((type *) xmalloc_and_zero (sizeof (type))) + +/* also generally useful if you want to avoid arbitrary size limits + but don't need a full dynamic array. Assumes that BASEVAR points + to a malloced array of TYPE objects (or possibly a NULL pointer, + if SIZEVAR is 0), with the total size stored in SIZEVAR. This + macro will realloc BASEVAR as necessary so that it can hold at + least NEEDED_SIZE objects. The reallocing is done by doubling, + which ensures constant amortized time per element. */ +#define DO_REALLOC(basevar, sizevar, needed_size, type) do \ +{ \ + /* Avoid side-effectualness. */ \ + /* Dammit! Macros suffer from dynamic scope! */ \ + /* We demand inline functions! */ \ + int do_realloc_needed_size = (needed_size); \ + int newsize = 0; \ + while ((sizevar) < (do_realloc_needed_size)) { \ + newsize = 2*(sizevar); \ + if (newsize < 32) \ + newsize = 32; \ + (sizevar) = newsize; \ + } \ + if (newsize) \ + (basevar) = (type *) xrealloc (basevar, (newsize)*sizeof(type)); \ +} while (0) + +#ifdef ERROR_CHECK_MALLOC +#define xfree(lvalue) do \ +{ \ + void **ptr = (void **) &(lvalue); \ + xfree_1 (*ptr); \ + *ptr = (void *) 0xDEADBEEF; \ +} while (0) +#else +#define xfree_1 xfree +#endif + +/* We assume an ANSI C compiler and libraries and memcpy, memset, memcmp */ +/* (This definition is here because system header file macros may want + * to call bzero (eg FD_ZERO) */ +#ifndef bzero +# define bzero(m, l) memset ((m), 0, (l)) +#endif + +#ifndef PRINTF_ARGS +# if defined (__GNUC__) && (__GNUC__ >= 2) +# define PRINTF_ARGS(string_index,first_to_check) \ + __attribute__ ((format (printf, string_index, first_to_check))) +# else +# define PRINTF_ARGS(string_index,first_to_check) +# endif /* GNUC */ +#endif + +#ifndef DOESNT_RETURN +# if defined __GNUC__ +# if ((__GNUC__ > 2) || (__GNUC__ == 2) && (__GNUC_MINOR__ >= 5)) +# define DOESNT_RETURN void volatile +# define DECLARE_DOESNT_RETURN(decl) \ + extern void volatile decl __attribute__ ((noreturn)) +# define DECLARE_DOESNT_RETURN_GCC__ATTRIBUTE__SYNTAX_SUCKS(decl,str,idx) \ + /* Should be able to state multiple independent __attribute__s, but \ + the losing syntax doesn't work that way, and screws losing cpp */ \ + extern void volatile decl \ + __attribute__ ((noreturn, format (printf, str, idx))) +# else +# define DOESNT_RETURN void volatile +# define DECLARE_DOESNT_RETURN(decl) extern void volatile decl +# define DECLARE_DOESNT_RETURN_GCC__ATTRIBUTE__SYNTAX_SUCKS(decl,str,idx) \ + extern void volatile decl PRINTF_ARGS(str,idx) +# endif /* GNUC 2.5 */ +# else +# define DOESNT_RETURN void +# define DECLARE_DOESNT_RETURN(decl) extern void decl +# define DECLARE_DOESNT_RETURN_GCC__ATTRIBUTE__SYNTAX_SUCKS(decl,str,idx) \ + extern void decl PRINTF_ARGS(str,idx) +# endif /* GNUC */ +#endif + +#ifndef ALIGNOF +# if defined (__GNUC__) && (__GNUC__ >= 2) +# define ALIGNOF(x) __alignof (x) +# else +# define ALIGNOF(x) sizeof (x) +# endif +#endif + +#define ALIGN_SIZE(len, unit) \ + ((((len) + (unit) - 1) / (unit)) * (unit)) + +/* #### Yuck, this is kind of evil */ +#define ALIGN_PTR(ptr, unit) \ + ((void *) ALIGN_SIZE ((long) (ptr), unit)) + +#ifdef QUANTIFY +#include "quantify.h" +#define QUANTIFY_START_RECORDING \ + do { quantify_start_recording_data (); } while (0) +#define QUANTIFY_STOP_RECORDING \ + do { quantify_stop_recording_data (); } while (0) +#else /* !QUANTIFY */ +#define QUANTIFY_START_RECORDING +#define QUANTIFY_STOP_RECORDING +#endif /* !QUANTIFY */ + + +#ifndef DO_NOTHING +#define DO_NOTHING do {} while (0) +#endif + +/* We define assert iff USE_ASSERTIONS or DEBUG_XEMACS is defined. + Otherwise we it to NULL. Quantify has shown that the time the + assert checks take is measurable so let's not include them in + production binaries. */ + +#ifdef USE_ASSERTIONS +/* Highly dubious kludge */ +/* (thanks, Jamie, I feel better now -- ben) */ +DECLARE_DOESNT_RETURN (assert_failed (CONST char *, int, CONST char *)); +# define abort() (assert_failed (__FILE__, __LINE__, "abort()")) +# define assert(x) ((x) ? (void) 0 : assert_failed (__FILE__, __LINE__, #x)) +#else +# ifdef DEBUG_XEMACS +# define assert(x) ((x) ? (void) 0 : (void) abort ()) +# else +# define assert(x) +# endif +#endif + +#ifdef DEBUG_XEMACS +#define REGISTER +#else +#define REGISTER register +#endif + +#ifndef INT_MAX +#define INT_MAX ((int) ((1U << (INTBITS - 1)) - 1)) +#endif + +#if defined (__GNUC__) && (__GNUC__ >= 2) +/* Entomological studies have revealed that the following junk is + necessary under GCC. GCC has a compiler bug where incorrect + code will be generated if you use a global temporary variable + in a macro and the macro occurs twice in the same expression. + As it happens, we can avoid this problem using a GCC language + extension. Thus we play weird games with syntax to avoid having + to provide two definitions for lots of macros. + + The approximate way this works is as follows: + + 1. Use these macros whenever you want to avoid evaluating an + argument more than once in a macro. (It's almost always a + good idea to make your macros safe like this.) + 2. Choose a name for the temporary variable you will store + the parameter in. It should begin with `MT' and + be distinguishing, since it will (or may) be a global + variable. + 3. In the same header file as the macro, put in a + MAC_DECLARE_EXTERN for the temporary variable. This + resolves to an external variable declaration for some + compilers. + 4. Put a MAC_DEFINE for the variable in a C file somewhere. + This resolves to a variable definition for some compilers. + 5. Write your macro with no semicolons or commas in it. + Remember to use parentheses to surround macro arguments, + but you do not need to surround each separate statement + or the temporary variable with parentheses. + 6. Write your macro like this: + +#define foo(bar,baz) \ +MAC_BEGIN \ + MAC_DECLARE (struct frobozz *, MTfoobar, bar) \ + SOME_EXPRESSION \ + MAC_SEP \ + SOME OTHER EXPRESSION \ +MAC_END + + 7. You only need to use MAC_SEP if you have more than one + expression in the macro, not counting any MAC_DECLARE + statements. + + DONT_DECLARE_MAC_VARS is used in signal.c, for asynchronous signals. + All functions that may be called from within an asynchronous signal + handler must declare local variables (with MAC_DECLARE_LOCAL) for + the (normally global) variables used in these sorts of macros. + Otherwise, a signal could occur in the middle of processing one + of these macros and the signal handler could use the same macro, + resulting in the global variable getting overwritten and yielding + nasty evil crashes that are very difficult to track down. +*/ +# define MAC_BEGIN ({ +# define MAC_DECLARE(type, var, value) type var = (value); +# define MAC_SEP ; +# define MAC_END ; }) +# define MAC_DECLARE_EXTERN(type, var) +# define MAC_DECLARE_LOCAL(type, var) +# define MAC_DEFINE(type, var) +#else +# define MAC_BEGIN ( +# define MAC_DECLARE(type, var, value) var = (value), +# define MAC_SEP , +# define MAC_END ) +# ifdef DONT_DECLARE_MAC_VARS +# define MAC_DECLARE_EXTERN(type, var) +# else +# define MAC_DECLARE_EXTERN(type, var) extern type var; +# endif +# define MAC_DECLARE_LOCAL(type, var) type var; +# define MAC_DEFINE(type, var) type var; +#endif + +/* For Lo, the Lord didst appear and look upon the face of the code, + and the Lord was unhappy with the strange syntax that had come + into vogue with the cryptic name of "C". And so the Lord didst + decree, that from now on all programmers shall use Pascal syntax, + a syntax truly and in sooth ordained in heaven. Amen. */ + + +/************************************************************************/ +/* typedefs */ +/************************************************************************/ + +/* We put typedefs here so that prototype declarations don't choke. + Note that we don't actually declare the structures here (except + maybe for simple structures like Dynarrs); that keeps them private + to the routines that actually use them. */ + +/* The data representing the text in a buffer is logically a set + of Bufbytes, declared as follows. */ + +typedef unsigned char Bufbyte; + +/* The data representing a string in "external" format (simple + binary format) is logically a set of Extbytes, declared as follows. */ + +typedef unsigned char Extbyte; + +/* To the user, a buffer is made up of characters, declared as follows. + In the non-Mule world, characters and Bufbytes are equivalent. + In the Mule world, a characters requires (typically) 1 to 4 + Bufbytes for its representation in a buffer. */ + +typedef int Emchar; + +/* Different ways of referring to a position in a buffer. We use + the typedefs in preference to 'int' to make it clearer what + sort of position is being used. See extents.c for a description + of the different positions. We put them here instead of in + buffer.h (where they rightfully belong) to avoid syntax errors + in function prototypes. */ + +typedef int Bufpos; +typedef int Bytind; +typedef int Memind; + +/* Counts of bytes or chars */ + +typedef int Bytecount; +typedef int Charcount; + +/* Length in bytes of a string in external format */ +typedef int Extcount; + +typedef struct lstream Lstream; + +typedef unsigned int face_index; +typedef struct face_cachel_dynarr_type +{ + Dynarr_declare (struct face_cachel); +} face_cachel_dynarr; + +typedef unsigned int glyph_index; +typedef struct glyph_cachel_dynarr_type +{ + Dynarr_declare (struct glyph_cachel); +} glyph_cachel_dynarr; + +struct buffer; /* "buffer.h" */ +struct console; /* "console.h" */ +struct device; /* "device.h" */ +struct extent_fragment; +struct extent; +struct frame; /* "frame.h" */ +struct window; /* "window.h" */ +struct Lisp_Event; /* "events.h" */ +struct Lisp_Face; +struct Lisp_Process; /* "process.c" */ +struct stat; /* <sys/stat.h> */ +struct Lisp_Color_Instance; +struct Lisp_Font_Instance; +struct Lisp_Image_Instance; +struct display_line; +struct redisplay_info; +struct window_mirror; +struct scrollbar_instance; +struct font_metric_info; +struct face_cachel; +struct console_type_entry; + +typedef struct bufbyte_dynarr_type +{ + Dynarr_declare (Bufbyte); +} bufbyte_dynarr; + +typedef struct extbyte_dynarr_type +{ + Dynarr_declare (Extbyte); +} extbyte_dynarr; + +typedef struct emchar_dynarr_type +{ + Dynarr_declare (Emchar); +} emchar_dynarr; + +typedef struct unsigned_char_dynarr_type +{ + Dynarr_declare (unsigned char); +} unsigned_char_dynarr; + +typedef struct int_dynarr_type +{ + Dynarr_declare (int); +} int_dynarr; + +typedef struct bufpos_dynarr_type +{ + Dynarr_declare (Bufpos); +} bufpos_dynarr; + +typedef struct bytind_dynarr_type +{ + Dynarr_declare (Bytind); +} bytind_dynarr; + +typedef struct charcount_dynarr_type +{ + Dynarr_declare (Charcount); +} charcount_dynarr; + +typedef struct bytecount_dynarr_type +{ + Dynarr_declare (Bytecount); +} bytecount_dynarr; + +typedef struct console_type_entry_dynarr_type +{ + Dynarr_declare (struct console_type_entry); +} console_type_entry_dynarr; + +/* Need to declare this here. */ +enum external_data_format +{ + /* Binary format. This is the simplest format and is what we + use in the absence of a more appropriate format. This converts + according to the `binary' coding system: + + a) On input, bytes 0 - 255 are converted into characters 0 - 255. + b) On output, characters 0 - 255 are converted into bytes 0 - 255 + and other characters are converted into `X'. + */ + FORMAT_BINARY, + + /* Format used for filenames. In the original Mule, this is + user-definable with the `pathname-coding-system' variable. + For the moment, we just use the `binary' coding system. */ + FORMAT_FILENAME, + + /* Format used for output to the terminal. This should be controlled + by the `display-coding-system' variable. Under kterm, this will + be some ISO2022 system. On some DOS machines, this is Shift-JIS. */ + FORMAT_DISPLAY, + + /* Format used for input from the terminal. This should be controlled + by the `keyboard-coding-system' variable. */ + FORMAT_KEYBOARD, + + /* Format used for the external Unix environment -- argv[], stuff + from getenv(), stuff from the /etc/passwd file, etc. + + Perhaps should be the same as FORMAT_FILENAME. */ + FORMAT_OS, + + /* Compound-text format. This is the standard X format used for + data stored in properties, selections, and the like. This is + an 8-bit no-lock-shift ISO2022 coding system. */ + FORMAT_CTEXT +}; + +enum run_hooks_condition +{ + RUN_HOOKS_TO_COMPLETION, + RUN_HOOKS_UNTIL_SUCCESS, + RUN_HOOKS_UNTIL_FAILURE +}; + +#ifdef HAVE_TOOLBARS +enum toolbar_pos +{ + TOP_TOOLBAR, + BOTTOM_TOOLBAR, + LEFT_TOOLBAR, + RIGHT_TOOLBAR +}; +#endif + +#ifndef ERROR_CHECK_TYPECHECK + +typedef enum error_behavior +{ + ERROR_ME, + ERROR_ME_NOT, + ERROR_ME_WARN +} Error_behavior; + +#define ERRB_EQ(a, b) ((a) == (b)) + +#else + +/* By defining it like this, we provide strict type-checking + for code that lazily uses ints. */ + +typedef struct _error_behavior_struct_ +{ + int really_unlikely_name_to_have_accidentally_in_a_non_errb_structure; +} Error_behavior; + +extern Error_behavior ERROR_ME; +extern Error_behavior ERROR_ME_NOT; +extern Error_behavior ERROR_ME_WARN; + +#define ERRB_EQ(a, b) \ + ((a).really_unlikely_name_to_have_accidentally_in_a_non_errb_structure == \ + (b).really_unlikely_name_to_have_accidentally_in_a_non_errb_structure) + +#endif + +enum munge_me_out_the_door +{ + MUNGE_ME_FUNCTION_KEY, + MUNGE_ME_KEY_TRANSLATION +}; + + +/************************************************************************/ +/* Definition of Lisp_Object data type */ +/************************************************************************/ + +/* There's not any particular reason not to use lrecords for these; some + objects get slightly larger, but we get 3 bit tags instead of 4. + */ +#define LRECORD_SYMBOL + + +/* Define the fundamental Lisp data structures */ + +/* This is the set of Lisp data types */ + +enum Lisp_Type +{ + /* Integer. XINT(obj) is the integer value. */ + Lisp_Int /* 0 DTP-FIXNUM */ + + /* XRECORD_LHEADER (object) points to a struct lrecord_header + lheader->implementation determines the type (and GC behaviour) + of the object. */ + ,Lisp_Record /* 1 DTP-OTHER-POINTER */ + + /* Cons. XCONS (object) points to a struct Lisp_Cons. */ + ,Lisp_Cons /* 2 DTP-LIST */ + + /* LRECORD_STRING is NYI */ + /* String. XSTRING (object) points to a struct Lisp_String. + The length of the string, and its contents, are stored therein. */ + ,Lisp_String /* 3 DTP-STRING */ + +#ifndef LRECORD_VECTOR + /* Vector of Lisp objects. XVECTOR(object) points to a struct Lisp_Vector. + The length of the vector, and its contents, are stored therein. */ + ,Lisp_Vector /* 4 DTP-SIMPLE-ARRAY */ +#endif + +#ifndef LRECORD_SYMBOL + /* Symbol. XSYMBOL (object) points to a struct Lisp_Symbol. */ + ,Lisp_Symbol +#endif /* !LRECORD_SYMBOL */ + }; + +/* unsafe! */ +#define POINTER_TYPE_P(type) ((type) != Lisp_Int) + +/* This should be the underlying type intowhich a Lisp_Object must fit. + In a strict ANSI world, this must be `int', since ANSI says you can't + use bitfields on any type other than `int'. However, on a machine + where `int' and `long' are not the same size, this should be the + longer of the two. (This also must be something into which a pointer + to an arbitrary object will fit, modulo any DATA_SEG_BITS cruft.) + */ +#if (LONGBITS > INTBITS) +# define EMACS_INT long +# define EMACS_UINT unsigned long +#else +# define EMACS_INT int +# define EMACS_UINT unsigned int +#endif + +/* Cast pointers to this type to compare them. Some machines want int. */ +#ifndef PNTR_COMPARISON_TYPE +# define PNTR_COMPARISON_TYPE unsigned int +#endif + +/* Overridden by m/next.h */ +#ifndef ASSERT_VALID_POINTER +# define ASSERT_VALID_POINTER(pnt) (assert ((((EMACS_UINT) pnt) & 3) == 0)) +#endif + +/* These values are overridden by the m- file on some machines. */ +#ifndef GCTYPEBITS +# define GCTYPEBITS 3L +#endif + +#ifndef VALBITS +# define VALBITS ((LONGBITS)-((GCTYPEBITS)+1L)) +#endif + +#ifdef NO_UNION_TYPE +# include "lisp-disunion.h" +#else /* !NO_UNION_TYPE */ +# include "lisp-union.h" +#endif /* !NO_UNION_TYPE */ + +/* WARNING WARNING WARNING. You must ensure on your own that proper + GC protection is provided for the elements in this array. */ +typedef struct lisp_dynarr_type +{ + Dynarr_declare (Lisp_Object); +} lisp_dynarr; + +/* Close your eyes now lest you vomit or spontaneously combust ... */ + +#define HACKEQ_UNSAFE(obj1, obj2) \ + (EQ (obj1, obj2) || (!POINTER_TYPE_P (XGCTYPE (obj1)) \ + && !POINTER_TYPE_P (XGCTYPE (obj2)) \ + && XREALINT (obj1) == XREALINT (obj2))) + +INLINE int HACKEQ (Lisp_Object obj1, Lisp_Object obj2); +INLINE int +HACKEQ (Lisp_Object obj1, Lisp_Object obj2) +{ + return HACKEQ_UNSAFE (obj1, obj2); +} + +/* OK, you can open them again */ + +/************************************************************************/ +/* Definitions of basic Lisp objects */ +/************************************************************************/ + +#include "lrecord.h" + +/********** unbound ***********/ + +/* Qunbound is a special Lisp_Object (actually of type + symbol-value-forward), that can never be visible to + the Lisp caller and thus can be used in the C code + to mean "no such value". */ + +#define UNBOUNDP(val) EQ (val, Qunbound) +#define GC_UNBOUNDP(val) GC_EQ (val, Qunbound) + +/*********** cons ***********/ + +/* In a cons, the markbit of the car is the gc mark bit */ + +struct Lisp_Cons +{ + Lisp_Object car, cdr; +}; + +#if 0 /* FSFmacs */ +/* Like a cons, but records info on where the text lives that it was read from */ +/* This is not really in use now */ + +struct Lisp_Buffer_Cons +{ + Lisp_Object car, cdr; + struct buffer *buffer; + int bufpos; +}; +#endif + +DECLARE_NONRECORD (cons, Lisp_Cons, struct Lisp_Cons); +#define XCONS(a) XNONRECORD (a, cons, Lisp_Cons, struct Lisp_Cons) +#define XSETCONS(c, p) XSETOBJ (c, Lisp_Cons, p) +#define CONSP(x) (XTYPE (x) == Lisp_Cons) +#define GC_CONSP(x) (XGCTYPE (x) == Lisp_Cons) +#define CHECK_CONS(x) CHECK_NONRECORD (x, Lisp_Cons, Qconsp) +#define CONCHECK_CONS(x) CONCHECK_NONRECORD (x, Lisp_Cons, Qconsp) + +/* Define these because they're used in a few places, inside and + out of alloc.c */ +#define CONS_MARKED_P(c) XMARKBIT (c->car) +#define MARK_CONS(c) XMARK (c->car) + +#define NILP(x) EQ (x, Qnil) +#define GC_NILP(x) GC_EQ (x, Qnil) +#define CHECK_LIST(x) \ + do { if ((!CONSP (x)) && !NILP (x)) dead_wrong_type_argument (Qlistp, x); } while (0) +#define CONCHECK_LIST(x) \ + do { if ((!CONSP (x)) && !NILP (x)) x = wrong_type_argument (Qlistp, x); } while (0) +#define XCAR(a) (XCONS (a)->car) +#define XCDR(a) (XCONS (a)->cdr) + +/* For a list that's known to be in valid list format -- + will abort() if the list is not in valid format */ +#define LIST_LOOP(consvar, list) \ + for (consvar = list; !NILP (consvar); consvar = XCDR (consvar)) + +/* For a list that's known to be in valid list format, where we may + be deleting the current element out of the list -- + will abort() if the list is not in valid format */ +#define LIST_LOOP_DELETING(consvar, nextconsvar, list) \ + for (consvar = list; \ + !NILP (consvar) ? (nextconsvar = XCDR (consvar), 1) : 0; \ + consvar = nextconsvar) + +/* For a list that may not be in valid list format -- + will signal an error if the list is not in valid format */ +#define EXTERNAL_LIST_LOOP(consvar, listp) \ + for (consvar = listp; !NILP (consvar); consvar = XCDR (consvar)) \ + if (!CONSP (consvar)) \ + signal_simple_error ("Invalid list format", listp); \ + else + +/* For a property list (alternating keywords/values) that may not be + in valid list format -- will signal an error if the list is not in + valid format. CONSVAR is used to keep track of the iterations + without modifying LISTP. + + We have to be tricky to still keep the same C format.*/ +#define EXTERNAL_PROPERTY_LIST_LOOP(consvar, keyword, value, listp) \ + for (consvar = listp; \ + (CONSP (consvar) && CONSP (XCDR (consvar)) ? \ + (keyword = XCAR (consvar), value = XCAR (XCDR (consvar))) : \ + (keyword = Qunbound, value = Qunbound)), \ + !NILP (consvar); \ + consvar = XCDR (XCDR (consvar))) \ + if (UNBOUNDP (keyword)) \ + signal_simple_error ("Invalid property list format", listp); \ + else + +/*********** string ***********/ + +/* In a string or vector, the sign bit of the `size' is the gc mark bit */ + +/* (The size and data fields have underscores prepended to catch old + code that attempts to reference the fields directly) */ +struct Lisp_String +{ +#ifdef LRECORD_STRING + struct lrecord_header lheader; +#endif + long _size; + Bufbyte *_data; + Lisp_Object plist; +}; + +#ifdef LRECORD_STRING + +DECLARE_LRECORD (string, struct Lisp_String); +#define XSTRING(x) XRECORD (x, string, struct Lisp_String) +#define XSETSTRING(x, p) XSETRECORD (x, p, string) +#define STRINGP(x) RECORDP (x, string) +#define GC_STRINGP(x) GC_RECORDP (x, string) +#define CHECK_STRING(x) CHECK_RECORD (x, string) +#define CONCHECK_STRING(x) CONCHECK_RECORD (x, string) + +#else + +DECLARE_NONRECORD (string, Lisp_String, struct Lisp_String); +#define XSTRING(x) XNONRECORD (x, string, Lisp_String, struct Lisp_String) +#define XSETSTRING(x, p) XSETOBJ (x, Lisp_String, p) +#define STRINGP(x) (XTYPE (x) == Lisp_String) +#define GC_STRINGP(x) (XGCTYPE (x) == Lisp_String) +#define CHECK_STRING(x) CHECK_NONRECORD (x, Lisp_String, Qstringp) +#define CONCHECK_STRING(x) CONCHECK_NONRECORD (x, Lisp_String, Qstringp) + +#endif + + +# define bytecount_to_charcount(ptr, len) (len) +# define charcount_to_bytecount(ptr, len) (len) + +#define string_length(s) ((s)->_size) +#define string_data(s) ((s)->_data + 0) +#define string_byte(s, i) ((s)->_data[i] + 0) +#define string_byte_addr(s, i) (&((s)->_data[i])) +#define set_string_length(s, len) do { (s)->_size = (len); } while (0) +#define set_string_data(s, ptr) do { (s)->_data = (ptr); } while (0) +#define set_string_byte(s, i, c) do { (s)->_data[i] = (c); } while (0) + +void resize_string (struct Lisp_String *s, Bytecount pos, Bytecount delta); + +# define string_char_length(s) string_length (s) +# define string_char(s, i) ((Emchar) string_byte (s, i)) +# define string_char_addr(s, i) string_byte_addr (s, i) +# define set_string_char(s, i, c) set_string_byte (s, i, c) + + +/*********** vector ***********/ + +struct Lisp_Vector +{ +#ifdef LRECORD_VECTOR + struct lrecord_header lheader; +#endif + long size; + /* next is now chained through v->contents[size], terminated by Qzero. + * This means that pure vectors don't need a "next" */ + /* struct Lisp_Vector *next; */ + Lisp_Object contents[1]; +}; + +#ifdef LRECORD_VECTOR + +DECLARE_LRECORD (vector, struct Lisp_Vector); +#define XVECTOR(x) XRECORD (x, vector, struct Lisp_Vector) +#define XSETVECTOR(x, p) XSETRECORD (x, p, vector) +#define VECTORP(x) RECORDP (x, vector) +#define GC_VECTORP(x) GC_RECORDP (x, vector) +#define CHECK_VECTOR(x) CHECK_RECORD (x, vector) +#define CONCHECK_VECTOR(x) CONCHECK_RECORD (x, vector) + +#else + +DECLARE_NONRECORD (vector, Lisp_Vector, struct Lisp_Vector); +#define XVECTOR(x) XNONRECORD (x, vector, Lisp_Vector, struct Lisp_Vector) +#define XSETVECTOR(x, p) XSETOBJ (x, Lisp_Vector, p) +#define VECTORP(x) (XTYPE (x) == Lisp_Vector) +#define GC_VECTORP(x) (XGCTYPE (x) == Lisp_Vector) +#define CHECK_VECTOR(x) CHECK_NONRECORD (x, Lisp_Vector, Qvectorp) +#define CONCHECK_VECTOR(x) CONCHECK_NONRECORD (x, Lisp_Vector, Qvectorp) + +#endif + +#define vector_length(v) ((v)->size) +#define vector_data(v) ((v)->contents) +#define vector_next(v) ((v)->contents[(v)->size]) + +/*********** bit vector ***********/ + +#if (LONGBITS < 16) +What the hell?! +#elif (LONGBITS < 32) +# define LONGBITS_LOG2 4 +# define LONGBITS_POWER_OF_2 16 +#elif (LONGBITS < 64) +# define LONGBITS_LOG2 5 +# define LONGBITS_POWER_OF_2 32 +#elif (LONGBITS < 128) +# define LONGBITS_LOG2 6 +# define LONGBITS_POWER_OF_2 64 +#else +#error You really have 128-bit integers?! +#endif + +struct Lisp_Bit_Vector +{ + struct lrecord_header lheader; + Lisp_Object next; + long size; + unsigned int bits[1]; +}; + +DECLARE_LRECORD (bit_vector, struct Lisp_Bit_Vector); +#define XBIT_VECTOR(x) XRECORD (x, bit_vector, struct Lisp_Bit_Vector) +#define XSETBIT_VECTOR(x, p) XSETRECORD (x, p, bit_vector) +#define BIT_VECTORP(x) RECORDP (x, bit_vector) +#define GC_BIT_VECTORP(x) GC_RECORDP (x, bit_vector) +#define CHECK_BIT_VECTOR(x) CHECK_RECORD (x, bit_vector) +#define CONCHECK_BIT_VECTOR(x) CONCHECK_RECORD (x, bit_vector) + +#define BITP(x) (INTP (x) && (XINT (x) == 0 || XINT (x) == 1)) +#define GC_BITP(x) (GC_INTP (x) && (XINT (x) == 0 || XINT (x) == 1)) + +#define CHECK_BIT(x) \ + do { if (!BITP (x)) dead_wrong_type_argument (Qbitp, x); } while (0) +#define CONCHECK_BIT(x) \ + do { if (!BITP (x)) x = wrong_type_argument (Qbitp, x); } while (0) + +#define bit_vector_length(v) ((v)->size) +#define bit_vector_next(v) ((v)->next) + +INLINE int bit_vector_bit (struct Lisp_Bit_Vector *v, int i); +INLINE int +bit_vector_bit (struct Lisp_Bit_Vector *v, int i) +{ + unsigned int ui = (unsigned int) i; + + return (((v)->bits[ui >> LONGBITS_LOG2] >> (ui & (LONGBITS_POWER_OF_2 - 1))) + & 1); +} + +INLINE void set_bit_vector_bit (struct Lisp_Bit_Vector *v, int i, int value); +INLINE void +set_bit_vector_bit (struct Lisp_Bit_Vector *v, int i, int value) +{ + unsigned int ui = (unsigned int) i; + if (value) + (v)->bits[ui >> LONGBITS_LOG2] |= (1 << (ui & (LONGBITS_POWER_OF_2 - 1))); + else + (v)->bits[ui >> LONGBITS_LOG2] &= ~(1 << (ui & (LONGBITS_POWER_OF_2 - 1))); +} + +/* Number of longs required to hold LEN bits */ +#define BIT_VECTOR_LONG_STORAGE(len) \ + ((len + LONGBITS_POWER_OF_2 - 1) >> LONGBITS_LOG2) + + +/*********** symbol ***********/ + +/* In a symbol, the markbit of the plist is used as the gc mark bit */ + +struct Lisp_Symbol +{ +#ifdef LRECORD_SYMBOL + struct lrecord_header lheader; +#endif + /* next symbol in this obarray bucket */ + struct Lisp_Symbol *next; + struct Lisp_String *name; + Lisp_Object value; + Lisp_Object function; + Lisp_Object plist; +}; + +#define SYMBOL_IS_KEYWORD(sym) (string_byte (XSYMBOL(sym)->name, 0) == ':') +#define KEYWORDP(obj) (SYMBOLP (obj) && SYMBOL_IS_KEYWORD (obj)) + +#ifdef LRECORD_SYMBOL + +DECLARE_LRECORD (symbol, struct Lisp_Symbol); +#define XSYMBOL(x) XRECORD (x, symbol, struct Lisp_Symbol) +#define XSETSYMBOL(x, p) XSETRECORD (x, p, symbol) +#define SYMBOLP(x) RECORDP (x, symbol) +#define GC_SYMBOLP(x) GC_RECORDP (x, symbol) +#define CHECK_SYMBOL(x) CHECK_RECORD (x, symbol) +#define CONCHECK_SYMBOL(x) CONCHECK_RECORD (x, symbol) + +#else + +DECLARE_NONRECORD (symbol, Lisp_Symbol, struct Lisp_Symbol); +#define XSYMBOL(x) XNONRECORD (x, symbol, Lisp_Symbol, struct Lisp_Symbol) +#define XSETSYMBOL(s, p) XSETOBJ ((s), Lisp_Symbol, (p)) +#define SYMBOLP(x) (XTYPE (x) == Lisp_Symbol) +#define GC_SYMBOLP(x) (XGCTYPE (x) == Lisp_Symbol) +#define CHECK_SYMBOL(x) CHECK_NONRECORD (x, Lisp_Symbol, Qsymbolp) +#define CONCHECK_SYMBOL(x) CONCHECK_NONRECORD (x, Lisp_Symbol, Qsymbolp) + +#endif + +#define symbol_next(s) ((s)->next) +#define symbol_name(s) ((s)->name) +#define symbol_value(s) ((s)->value) +#define symbol_function(s) ((s)->function) +#define symbol_plist(s) ((s)->plist) + +/*********** subr ***********/ + +struct Lisp_Subr +{ + struct lrecord_header lheader; + short min_args, max_args; + CONST char *prompt; + CONST char *doc; + CONST char *name; + Lisp_Object (*subr_fn) (); +}; + +DECLARE_LRECORD (subr, struct Lisp_Subr); +#define XSUBR(x) XRECORD (x, subr, struct Lisp_Subr) +#define XSETSUBR(x, p) XSETRECORD (x, p, subr) +#define SUBRP(x) RECORDP (x, subr) +#define GC_SUBRP(x) GC_RECORDP (x, subr) +#define CHECK_SUBR(x) CHECK_RECORD (x, subr) +#define CONCHECK_SUBR(x) CONCHECK_RECORD (x, subr) + +#define subr_function(subr) (subr)->subr_fn +#define subr_name(subr) (subr)->name + +/*********** marker ***********/ + +struct Lisp_Marker +{ + struct lrecord_header lheader; + struct Lisp_Marker *next, *prev; + struct buffer *buffer; + Memind memind; + char insertion_type; +}; + +DECLARE_LRECORD (marker, struct Lisp_Marker); +#define XMARKER(x) XRECORD (x, marker, struct Lisp_Marker) +#define XSETMARKER(x, p) XSETRECORD (x, p, marker) +#define MARKERP(x) RECORDP (x, marker) +#define GC_MARKERP(x) GC_RECORDP (x, marker) +#define CHECK_MARKER(x) CHECK_RECORD (x, marker) +#define CONCHECK_MARKER(x) CONCHECK_RECORD (x, marker) + +/* The second check was looking for GCed markers still in use */ +/* if (INTP (XMARKER (x)->lheader.next.v)) abort (); */ + +#define marker_next(m) ((m)->next) +#define marker_prev(m) ((m)->prev) + +/*********** char ***********/ + +#define CHARP(x) (INTP (x)) +#define GC_CHARP(x) (GC_INTP (x)) + +#ifdef ERROR_CHECK_TYPECHECK + +INLINE Emchar XCHAR (Lisp_Object obj); +INLINE Emchar +XCHAR (Lisp_Object obj) +{ + return XREALINT (obj); +} + +#else + +#define XCHAR(x) (XINT (x)) + +#endif + +#define CHECK_CHAR(x) (CHECK_INT (x)) +#define CONCHECK_CHAR(x) (CONCHECK_INT (x)) + + +/*********** float ***********/ + +#ifdef LISP_FLOAT_TYPE + +struct Lisp_Float +{ + struct lrecord_header lheader; + union { double d; struct Lisp_Float *next; } data; +}; + +DECLARE_LRECORD (float, struct Lisp_Float); +#define XFLOAT(x) XRECORD (x, float, struct Lisp_Float) +#define XSETFLOAT(x, p) XSETRECORD (x, p, float) +#define FLOATP(x) RECORDP (x, float) +#define GC_FLOATP(x) GC_RECORDP (x, float) +#define CHECK_FLOAT(x) CHECK_RECORD (x, float) +#define CONCHECK_FLOAT(x) CONCHECK_RECORD (x, float) + +#define float_next(f) ((f)->data.next) +#define float_data(f) ((f)->data.d) + +#ifndef DBL_DIG +# define DBL_DIG 16 +#endif + +#define XFLOATINT(n) extract_float (n) + +#define CHECK_INT_OR_FLOAT(x) \ + do { if ( !INTP (x) && !FLOATP (x)) \ + dead_wrong_type_argument (Qnumberp, (x)); } while (0) +#define CONCHECK_INT_OR_FLOAT(x) \ + do { if ( !INTP (x) && !FLOATP (x)) \ + x = wrong_type_argument (Qnumberp, (x)); } while (0) + +/* These are always continuable because they change their arguments + even when no error is signalled. */ + +#define CHECK_INT_OR_FLOAT_COERCE_MARKER(x) \ + do { if (INTP (x) || FLOATP (x)) \ + ; \ + else if (MARKERP (x)) \ + x = make_int (marker_position (x)); \ + else \ + x = wrong_type_argument (Qnumber_or_marker_p, x); } while (0) + +#define CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER(x) \ + do { if (INTP (x) || FLOATP (x)) \ + ; \ + else if (CHARP (x)) \ + x = make_int (XCHAR (x)); \ + else if (MARKERP (x)) \ + x = make_int (marker_position (x)); \ + else \ + x = wrong_type_argument (Qnumber_char_or_marker_p, x); \ + } while (0) + +# define INT_OR_FLOATP(x) (INTP (x) || FLOATP (x)) +# define GC_INT_OR_FLOATP(x) (GC_INTP (x) || GC_FLOATP (x)) + +#else /* not LISP_FLOAT_TYPE */ + +#define XFLOAT(x) --- error! No float support. --- +#define XSETFLOAT(x, p) --- error! No float support. --- +#define FLOATP(x) 0 +#define GC_FLOATP(x) 0 +#define CHECK_FLOAT(x) --- error! No float support. --- +#define CONCHECK_FLOAT(x) --- error! No float support. --- + +#define XFLOATINT(n) XINT(n) +#define CHECK_INT_OR_FLOAT CHECK_INT +#define CONCHECK_INT_OR_FLOAT CONCHECK_INT +#define CHECK_INT_OR_FLOAT_COERCE_MARKER CHECK_INT_COERCE_MARKER +#define CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER \ + CHECK_INT_COERCE_CHAR_OR_MARKER +#define INT_OR_FLOATP(x) (INTP (x)) +# define GC_INT_OR_FLOATP(x) (GC_INTP (x)) + +#endif /* not LISP_FLOAT_TYPE */ + +#define INTP(x) (XTYPE (x) == Lisp_Int) +#define GC_INTP(x) (XGCTYPE (x) == Lisp_Int) + +#define ZEROP(x) EQ (x, Qzero) +#define GC_ZEROP(x) GC_EQ (x, Qzero) + +#ifdef ERROR_CHECK_TYPECHECK + +INLINE EMACS_INT XINT (Lisp_Object obj); +INLINE EMACS_INT +XINT (Lisp_Object obj) +{ + assert (INTP (obj)); + return XREALINT (obj); +} + +#else + +#define XINT(obj) XREALINT (obj) + +#endif + +#define CHECK_INT(x) CHECK_NONRECORD (x, Lisp_Int, Qintegerp) +#define CONCHECK_INT(x) CONCHECK_NONRECORD (x, Lisp_Int, Qintegerp) + +#define NATNUMP(x) (INTP (x) && XINT (x) >= 0) +#define GC_NATNUMP(x) (GC_INTP (x) && XINT (x) >= 0) + +#define CHECK_NATNUM(x) \ + do { if (!NATNUMP (x)) dead_wrong_type_argument (Qnatnump, x); } while (0) +#define CONCHECK_NATNUM(x) \ + do { if (!NATNUMP (x)) x = wrong_type_argument (Qnatnump, x); } while (0) + +/* next three always continuable because they coerce their arguments. */ +#define CHECK_INT_COERCE_CHAR(x) \ + do { if (INTP (x)) \ + ; \ + else if (CHARP (x)) \ + x = make_int (XCHAR (x)); \ + else \ + x = wrong_type_argument (Qinteger_or_char_p, x); } while (0) + +#define CHECK_INT_COERCE_MARKER(x) \ + do { if (INTP (x)) \ + ; \ + else if (MARKERP (x)) \ + x = make_int (marker_position (x)); \ + else \ + x = wrong_type_argument (Qinteger_or_marker_p, x); } while (0) + +#define CHECK_INT_COERCE_CHAR_OR_MARKER(x) \ + do { if (INTP (x)) \ + ; \ + else if (CHARP (x)) \ + x = make_int (XCHAR (x)); \ + else if (MARKERP (x)) \ + x = make_int (marker_position (x)); \ + else \ + x = wrong_type_argument (Qinteger_char_or_marker_p, x); \ + } while (0) + +/*********** pure space ***********/ + +#define CHECK_IMPURE(obj) \ + do { if (purified (obj)) pure_write_error (); } while (0) + +/*********** structures ***********/ + +struct structure_keyword_entry +{ + Lisp_Object keyword; + int (*validate) (Lisp_Object keyword, Lisp_Object value, + Error_behavior errb); +}; + +typedef struct structure_keyword_entry_dynarr_type +{ + Dynarr_declare (struct structure_keyword_entry); +} Structure_keyword_entry_dynarr; + +struct structure_type +{ + Lisp_Object type; + Structure_keyword_entry_dynarr *keywords; + int (*validate) (Lisp_Object data, Error_behavior errb); + Lisp_Object (*instantiate) (Lisp_Object data); +}; + +typedef struct structure_type_dynarr_type +{ + Dynarr_declare (struct structure_type); +} Structure_type_dynarr; + +struct structure_type *define_structure_type (Lisp_Object type, + int (*validate) + (Lisp_Object data, + Error_behavior errb), + Lisp_Object (*instantiate) + (Lisp_Object data)); +void define_structure_type_keyword (struct structure_type *st, + Lisp_Object keyword, + int (*validate) (Lisp_Object keyword, + Lisp_Object value, + Error_behavior errb)); + +/*********** weak lists ***********/ + +enum weak_list_type +{ + /* element disappears if it's unmarked. */ + WEAK_LIST_SIMPLE, + /* element disappears if it's a cons and either its car or + cdr is unmarked. */ + WEAK_LIST_ASSOC, + /* element disappears if it's a cons and its car is unmarked. */ + WEAK_LIST_KEY_ASSOC, + /* element disappears if it's a cons and its cdr is unmarked. */ + WEAK_LIST_VALUE_ASSOC +}; + +struct weak_list +{ + struct lcrecord_header header; + Lisp_Object list; /* don't mark through this! */ + enum weak_list_type type; + Lisp_Object next_weak; /* don't mark through this! */ +}; + +DECLARE_LRECORD (weak_list, struct weak_list); +#define XWEAK_LIST(x) XRECORD (x, weak_list, struct weak_list) +#define XSETWEAK_LIST(x, p) XSETRECORD (x, p, weak_list) +#define WEAK_LISTP(x) RECORDP (x, weak_list) +#define GC_WEAK_LISTP(x) GC_RECORDP (x, weak_list) +#define CHECK_WEAK_LIST(x) CHECK_RECORD (x, weak_list) +#define CONCHECK_WEAK_LIST(x) CONCHECK_RECORD (x, weak_list) + +#define weak_list_list(w) ((w)->list) +#define XWEAK_LIST_LIST(w) (XWEAK_LIST (w)->list) + +Lisp_Object make_weak_list (enum weak_list_type type); +/* The following two are only called by the garbage collector */ +int finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), + void (*markobj) (Lisp_Object)); +void prune_weak_lists (int (*obj_marked_p) (Lisp_Object)); + +/*********** lcrecord lists ***********/ + +struct lcrecord_list +{ + struct lcrecord_header header; + Lisp_Object free; + int size; + CONST struct lrecord_implementation *implementation; +}; + +DECLARE_LRECORD (lcrecord_list, struct lcrecord_list); +#define XLCRECORD_LIST(x) XRECORD (x, lcrecord_list, struct lcrecord_list) +#define XSETLCRECORD_LIST(x, p) XSETRECORD (x, p, lcrecord_list) +#define LCRECORD_LISTP(x) RECORDP (x, lcrecord_list) +#define GC_LCRECORD_LISTP(x) GC_RECORDP (x, lcrecord_list) +/* #define CHECK_LCRECORD_LIST(x) CHECK_RECORD (x, lcrecord_list) + Lcrecord lists should never escape to the Lisp level, so + functions should not be doing this. */ + +Lisp_Object make_lcrecord_list (int size, + CONST struct lrecord_implementation + *implementation); +Lisp_Object allocate_managed_lcrecord (Lisp_Object lcrecord_list); +void free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord); + + +/************************************************************************/ +/* Definitions of primitive Lisp functions and variables */ +/************************************************************************/ + +/* Define a built-in function for calling from Lisp. + `lname' should be the name to give the function in Lisp, + as a null-terminated C string. + `fnname' should be the name of the function in C. + By convention, it starts with F. + `sname' should be the name for the C constant structure + that records information on this function for internal use. + By convention, it should be the same as `fnname' but with S instead of F. + It's too bad that C macros can't compute this from `fnname'. + `minargs' should be a number, the minimum number of arguments allowed. + `maxargs' should be a number, the maximum number of arguments allowed, + or else MANY or UNEVALLED. + MANY means pass a vector of evaluated arguments, + in the form of an integer number-of-arguments + followed by the address of a vector of Lisp_Objects + which contains the argument values. + UNEVALLED means pass the list of unevaluated arguments + `prompt' says how to read arguments for an interactive call. + See the doc string for `interactive'. + A null string means call interactively with no arguments. + `doc' is documentation for the user. +*/ + +#define SUBR_MAX_ARGS 8 +#define MANY -2 +#define UNEVALLED -1 + +/* Can't be const, because then subr->doc is read-only and + * FSnarf_documentation chokes */ +#define DEFUN(lname, fnname, sname, minargs, maxargs, prompt) \ + Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; /* See below */ \ + static struct Lisp_Subr sname \ + = { { lrecord_subr }, minargs, maxargs, prompt, 0, lname, fnname }; \ + Lisp_Object fnname + +/* Scary ANSI C preprocessor hackery by Felix Lee <flee@guardian.cse.psu.edu> + to get DEFUN to declare a prototype that matches maxargs, so that the + compiler can complain if the "real" arglist doesn't match. Clever hack + or repulsive kludge? You be the judge. + */ + +/* WARNING: If you add defines below for higher values of maxargs, + make sure to also fix the clauses in primitive_funcall(). */ + +#define DEFUN_ARGS_MANY (int, Lisp_Object *) +#define DEFUN_ARGS_UNEVALLED (Lisp_Object) +#define DEFUN_ARGS_0 (void) +#define DEFUN_ARGS_1 (Lisp_Object) +#define DEFUN_ARGS_2 (Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_3 (Lisp_Object, Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_4 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object) +#define DEFUN_ARGS_6 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_7 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_8 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_9 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object) +#define DEFUN_ARGS_10 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_11 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object, Lisp_Object) +#define DEFUN_ARGS_12 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \ + Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) + +#include "symeval.h" + +/* Depth of special binding/unwind-protect stack. Use as arg to unbind_to */ +int specpdl_depth (void); + + +/************************************************************************/ +/* Checking for QUIT */ +/************************************************************************/ + +/* Asynchronous events set something_happened, and then are processed + within the QUIT macro. At this point, we are guaranteed to not be in + any sensitive code. */ + +extern volatile int something_happened; +int check_what_happened (void); + +extern volatile int quit_check_signal_happened; +extern volatile int quit_check_signal_tick_count; +int check_quit (void); + +void signal_quit (void); + +/* Nonzero if ought to quit now. */ +#define QUITP ((quit_check_signal_happened ? check_quit () : 0), \ + (!NILP (Vquit_flag) && (NILP (Vinhibit_quit) \ + || EQ (Vquit_flag, Qcritical)))) + +/* QUIT used to call QUITP, but there are some places where QUITP + is called directly, and check_what_happened() should only be called + when Emacs is actually ready to quit because it could do things + like switch threads. */ +#define INTERNAL_QUITP \ + ((something_happened ? check_what_happened () : 0), \ + (!NILP (Vquit_flag) && \ + (NILP (Vinhibit_quit) || EQ (Vquit_flag, Qcritical)))) + +#define INTERNAL_REALLY_QUITP \ + (check_what_happened (), \ + (!NILP (Vquit_flag) && \ + (NILP (Vinhibit_quit) || EQ (Vquit_flag, Qcritical)))) + +/* Check quit-flag and quit if it is non-nil. Also do any other things + that might have gotten queued until it was safe. */ +#define QUIT \ + do { if (INTERNAL_QUITP) signal_quit (); } while (0) + +#define REALLY_QUIT \ + do { if (INTERNAL_REALLY_QUITP) signal_quit (); } while (0) + + +/************************************************************************/ +/* hashing */ +/************************************************************************/ + +/* #### for a 64-bit machine, we should substitute a prime just over + 2^32 */ +#define GOOD_HASH_VALUE 65599 /* prime number just over 2^16; + Dragon book, p. 435 */ +#define HASH2(a, b) ((a) * GOOD_HASH_VALUE + (b)) +#define HASH3(a, b, c) (HASH2 (a, b) * GOOD_HASH_VALUE + (c)) +#define HASH4(a, b, c, d) (HASH3 (a, b, c) * GOOD_HASH_VALUE + (d)) +#define HASH5(a, b, c, d, e) (HASH4 (a, b, c, d) * GOOD_HASH_VALUE + (e)) +#define HASH6(a, b, c, d, e, f) (HASH5 (a, b, c, d, e) * GOOD_HASH_VALUE + (f)) +#define HASH7(a, b, c, d, e, f, g) \ + (HASH6 (a, b, c, d, e, f) * GOOD_HASH_VALUE + (g)) +#define HASH8(a, b, c, d, e, f, g, h) \ + (HASH7 (a, b, c, d, e, f, g) * GOOD_HASH_VALUE + (h)) +#define HASH9(a, b, c, d, e, f, g, h, i) \ + (HASH8 (a, b, c, d, e, f, g, h) * GOOD_HASH_VALUE + (i)) + +/* Enough already! */ + +#define LISP_HASH(obj) ((unsigned long) LISP_TO_VOID (obj)) +unsigned long string_hash (CONST void *xv); +unsigned long memory_hash (CONST void *xv, int size); +unsigned long internal_hash (Lisp_Object obj, int depth); +unsigned long internal_array_hash (Lisp_Object *arr, int size, int depth); + + +/************************************************************************/ +/* String translation */ +/************************************************************************/ + +#ifdef I18N3 +#ifdef HAVE_LIBINTL_H +#include <libintl.h> +#else +char *dgettext (CONST char *, CONST char *); +char *gettext (CONST char *); +char *textdomain (CONST char *); +char *bindtextdomain (CONST char *, CONST char *); +#endif /* HAVE_LIBINTL_H */ + +#define GETTEXT(x) gettext(x) +#define LISP_GETTEXT(x) Fgettext (x) +#else /* !I18N3 */ +#define GETTEXT(x) (x) +#define LISP_GETTEXT(x) (x) +#endif /* !I18N3 */ + +/* DEFER_GETTEXT is used to identify strings which are translated when + they are referenced instead of when they are defined. + These include Qerror_messages and initialized arrays of strings. +*/ +#define DEFER_GETTEXT(x) (x) + + +/************************************************************************/ +/* Garbage collection / GC-protection */ +/************************************************************************/ + +/* number of bytes of structure consed since last GC */ + +extern EMACS_INT consing_since_gc; + +/* threshold for doing another gc */ + +extern EMACS_INT gc_cons_threshold; + +/* Structure for recording stack slots that need marking */ + +/* This is a chain of structures, each of which points at a Lisp_Object + variable whose value should be marked in garbage collection. + Normally every link of the chain is an automatic variable of a function, + and its `val' points to some argument or local variable of the function. + On exit to the function, the chain is set back to the value it had on + entry. This way, no link remains in the chain when the stack frame + containing the link disappears. + + Every function that can call Feval must protect in this fashion all + Lisp_Object variables whose contents will be used again. */ + +extern struct gcpro *gcprolist; + +struct gcpro +{ + struct gcpro *next; + Lisp_Object *var; /* Address of first protected variable */ + int nvars; /* Number of consecutive protected variables */ +}; + +/* Normally, you declare variables gcpro1, gcpro2, ... and use the + GCPROn() macros. However, if you need to have nested gcpro's, + declare ngcpro1, ngcpro2, ... and use NGCPROn(). If you need + to nest another level, use nngcpro1, nngcpro2, ... and use + NNGCPROn(). If you need to nest yet another level, create + the appropriate macros. */ + +#ifdef DEBUG_GCPRO + +void debug_gcpro1 (), debug_gcpro2 (), debug_gcpro3 (), debug_gcpro4 (); +void debug_gcpro_5 (), debug_ungcpro (); + +#define GCPRO1(v) \ + debug_gcpro1 (__FILE__, __LINE__,&gcpro1,&v) +#define GCPRO2(v1,v2) \ + debug_gcpro2 (__FILE__, __LINE__,&gcpro1,&gcpro2,&v1,&v2) +#define GCPRO3(v1,v2,v3) \ + debug_gcpro3 (__FILE__, __LINE__,&gcpro1,&gcpro2,&gcpro3,&v1,&v2,&v3) +#define GCPRO4(v1,v2,v3,v4) \ + debug_gcpro4 (__FILE__, __LINE__,&gcpro1,&gcpro2,&gcpro3,&gcpro4,\ + &v1,&v2,&v3,&v4) +#define GCPRO5(v1,v2,v3,v4,v5) \ + debug_gcpro5 (__FILE__, __LINE__,&gcpro1,&gcpro2,&gcpro3,&gcpro4,&gcpro5,\ + &v1,&v2,&v3,&v4,&v5) +#define UNGCPRO \ + debug_ungcpro(__FILE__, __LINE__,&gcpro1) + +#define NGCPRO1(v) \ + debug_gcpro1 (__FILE__, __LINE__,&ngcpro1,&v) +#define NGCPRO2(v1,v2) \ + debug_gcpro2 (__FILE__, __LINE__,&ngcpro1,&ngcpro2,&v1,&v2) +#define NGCPRO3(v1,v2,v3) \ + debug_gcpro3 (__FILE__, __LINE__,&ngcpro1,&ngcpro2,&ngcpro3,&v1,&v2,&v3) +#define NGCPRO4(v1,v2,v3,v4) \ + debug_gcpro4 (__FILE__, __LINE__,&ngcpro1,&ngcpro2,&ngcpro3,&ngcpro4,\ + &v1,&v2,&v3,&v4) +#define NGCPRO5(v1,v2,v3,v4,v5) \ + debug_gcpro5 (__FILE__, __LINE__,&ngcpro1,&ngcpro2,&ngcpro3,&ngcpro4,\ + &ngcpro5,&v1,&v2,&v3,&v4,&v5) +#define NUNGCPRO \ + debug_ungcpro(__FILE__, __LINE__,&ngcpro1) + +#define NNGCPRO1(v) \ + debug_gcpro1 (__FILE__, __LINE__,&nngcpro1,&v) +#define NNGCPRO2(v1,v2) \ + debug_gcpro2 (__FILE__, __LINE__,&nngcpro1,&nngcpro2,&v1,&v2) +#define NNGCPRO3(v1,v2,v3) \ + debug_gcpro3 (__FILE__, __LINE__,&nngcpro1,&nngcpro2,&nngcpro3,&v1,&v2,&v3) +#define NNGCPRO4(v1,v2,v3,v4) \ + debug_gcpro4 (__FILE__, __LINE__,&nngcpro1,&nngcpro2,&nngcpro3,&nngcpro4,\ + &v1,&v2,&v3,&v4) +#define NNGCPRO5(v1,v2,v3,v4,v5) \ + debug_gcpro5 (__FILE__, __LINE__,&nngcpro1,&nngcpro2,&nngcpro3,&nngcpro4,\ + &nngcpro5,&v1,&v2,&v3,&v4,&v5) +#define NUNNGCPRO \ + debug_ungcpro(__FILE__, __LINE__,&nngcpro1) + +#else /* ! DEBUG_GCPRO */ + +#define GCPRO1(varname) \ + {gcpro1.next = gcprolist; gcpro1.var = &varname; gcpro1.nvars = 1; \ + gcprolist = &gcpro1; } + +#define GCPRO2(varname1, varname2) \ + {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ + gcprolist = &gcpro2; } + +#define GCPRO3(varname1, varname2, varname3) \ + {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ + gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ + gcprolist = &gcpro3; } + +#define GCPRO4(varname1, varname2, varname3, varname4) \ + {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ + gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ + gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ + gcprolist = &gcpro4; } + +#define GCPRO5(varname1, varname2, varname3, varname4, varname5) \ + {gcpro1.next = gcprolist; gcpro1.var = &varname1; gcpro1.nvars = 1; \ + gcpro2.next = &gcpro1; gcpro2.var = &varname2; gcpro2.nvars = 1; \ + gcpro3.next = &gcpro2; gcpro3.var = &varname3; gcpro3.nvars = 1; \ + gcpro4.next = &gcpro3; gcpro4.var = &varname4; gcpro4.nvars = 1; \ + gcpro5.next = &gcpro4; gcpro5.var = &varname5; gcpro5.nvars = 1; \ + gcprolist = &gcpro5; } + +#define UNGCPRO (gcprolist = gcpro1.next) + +#define NGCPRO1(varname) \ + {ngcpro1.next = gcprolist; ngcpro1.var = &varname; ngcpro1.nvars = 1; \ + gcprolist = &ngcpro1; } + +#define NGCPRO2(varname1, varname2) \ + {ngcpro1.next = gcprolist; ngcpro1.var = &varname1; ngcpro1.nvars = 1; \ + ngcpro2.next = &ngcpro1; ngcpro2.var = &varname2; ngcpro2.nvars = 1; \ + gcprolist = &ngcpro2; } + +#define NGCPRO3(varname1, varname2, varname3) \ + {ngcpro1.next = gcprolist; ngcpro1.var = &varname1; ngcpro1.nvars = 1; \ + ngcpro2.next = &ngcpro1; ngcpro2.var = &varname2; ngcpro2.nvars = 1; \ + ngcpro3.next = &ngcpro2; ngcpro3.var = &varname3; ngcpro3.nvars = 1; \ + gcprolist = &ngcpro3; } + +#define NGCPRO4(varname1, varname2, varname3, varname4) \ + {ngcpro1.next = gcprolist; ngcpro1.var = &varname1; ngcpro1.nvars = 1; \ + ngcpro2.next = &ngcpro1; ngcpro2.var = &varname2; ngcpro2.nvars = 1; \ + ngcpro3.next = &ngcpro2; ngcpro3.var = &varname3; ngcpro3.nvars = 1; \ + ngcpro4.next = &ngcpro3; ngcpro4.var = &varname4; ngcpro4.nvars = 1; \ + gcprolist = &ngcpro4; } + +#define NGCPRO5(varname1, varname2, varname3, varname4, varname5) \ + {ngcpro1.next = gcprolist; ngcpro1.var = &varname1; ngcpro1.nvars = 1; \ + ngcpro2.next = &ngcpro1; ngcpro2.var = &varname2; ngcpro2.nvars = 1; \ + ngcpro3.next = &ngcpro2; ngcpro3.var = &varname3; ngcpro3.nvars = 1; \ + ngcpro4.next = &ngcpro3; ngcpro4.var = &varname4; ngcpro4.nvars = 1; \ + ngcpro5.next = &ngcpro4; ngcpro5.var = &varname5; ngcpro5.nvars = 1; \ + gcprolist = &ngcpro5; } + +#define NUNGCPRO (gcprolist = ngcpro1.next) + +#define NNGCPRO1(varname) \ + {nngcpro1.next = gcprolist; nngcpro1.var = &varname; nngcpro1.nvars = 1; \ + gcprolist = &nngcpro1; } + +#define NNGCPRO2(varname1, varname2) \ + {nngcpro1.next = gcprolist; nngcpro1.var = &varname1; nngcpro1.nvars = 1; \ + nngcpro2.next = &nngcpro1; nngcpro2.var = &varname2; nngcpro2.nvars = 1; \ + gcprolist = &nngcpro2; } + +#define NNGCPRO3(varname1, varname2, varname3) \ + {nngcpro1.next = gcprolist; nngcpro1.var = &varname1; nngcpro1.nvars = 1; \ + nngcpro2.next = &nngcpro1; nngcpro2.var = &varname2; nngcpro2.nvars = 1; \ + nngcpro3.next = &nngcpro2; nngcpro3.var = &varname3; nngcpro3.nvars = 1; \ + gcprolist = &nngcpro3; } + +#define NNGCPRO4(varname1, varname2, varname3, varname4) \ + {nngcpro1.next = gcprolist; nngcpro1.var = &varname1; nngcpro1.nvars = 1; \ + nngcpro2.next = &nngcpro1; nngcpro2.var = &varname2; nngcpro2.nvars = 1; \ + nngcpro3.next = &nngcpro2; nngcpro3.var = &varname3; nngcpro3.nvars = 1; \ + nngcpro4.next = &nngcpro3; nngcpro4.var = &varname4; nngcpro4.nvars = 1; \ + gcprolist = &nngcpro4; } + +#define NNGCPRO5(varname1, varname2, varname3, varname4, varname5) \ + {nngcpro1.next = gcprolist; nngcpro1.var = &varname1; nngcpro1.nvars = 1; \ + nngcpro2.next = &nngcpro1; nngcpro2.var = &varname2; nngcpro2.nvars = 1; \ + nngcpro3.next = &nngcpro2; nngcpro3.var = &varname3; nngcpro3.nvars = 1; \ + nngcpro4.next = &nngcpro3; nngcpro4.var = &varname4; nngcpro4.nvars = 1; \ + nngcpro5.next = &nngcpro4; nngcpro5.var = &varname5; nngcpro5.nvars = 1; \ + gcprolist = &nngcpro5; } + +#define NNUNGCPRO (gcprolist = nngcpro1.next) + +#endif /* ! DEBUG_GCPRO */ + +/* Another try to fix SunPro C compiler warnings */ +/* "end-of-loop code not reached" */ +#ifdef __SUNPRO_C +#define RETURN__ if (1) return +#else +#define RETURN__ return +#endif + +/* Another try to fix SunPro C compiler warnings */ +/* "end-of-loop code not reached" */ +/* "statement not reached */ +#ifdef __SUNPRO_C +#define RETURN__ if (1) return +#define RETURN_NOT_REACHED(value) +#else +#define RETURN__ return +#define RETURN_NOT_REACHED(value) return value; +#endif + +/* Evaluate expr, UNGCPRO, and then return the value of expr. */ +#define RETURN_UNGCPRO(expr) do \ +{ \ + Lisp_Object ret_ungc_val = (expr); \ + UNGCPRO; \ + RETURN__ ret_ungc_val; \ +} while (0) + +/* Evaluate expr, NUNGCPRO, UNGCPRO, and then return the value of expr. */ +#define RETURN_NUNGCPRO(expr) do \ +{ \ + Lisp_Object ret_ungc_val = (expr); \ + NUNGCPRO; \ + UNGCPRO; \ + RETURN__ ret_ungc_val; \ +} while (0) + +/* Evaluate expr, NNUNGCPRO, NUNGCPRO, UNGCPRO, and then return the + value of expr. */ +#define RETURN_NNUNGCPRO(expr) do \ +{ \ + Lisp_Object ret_ungc_val = (expr); \ + NNUNGCPRO; \ + NUNGCPRO; \ + UNGCPRO; \ + RETURN__ ret_ungc_val; \ +} while (0) + +/* Evaluate expr, return it if it's not Qunbound. */ +#define RETURN_IF_NOT_UNBOUND(expr) do \ +{ \ + Lisp_Object ret_nunb_val = (expr); \ + if (!UNBOUNDP (ret_nunb_val)) \ + RETURN__ ret_nunb_val; \ +} while (0) + +/* Call staticpro (&var) to protect static variable `var'. */ +void staticpro (Lisp_Object *); + +/* Nonzero means Emacs has already been initialized. + Used during startup to detect startup of dumped Emacs. */ +extern int initialized; + +#ifdef MEMORY_USAGE_STATS + +/* This structure is used to keep statistics on the amount of memory + in use. + + WAS_REQUESTED stores the actual amount of memory that was requested + of the allocation function. The *_OVERHEAD fields store the + additional amount of memory that was grabbed by the functions to + facilitate allocation, reallocation, etc. MALLOC_OVERHEAD is for + memory allocated with malloc(); DYNARR_OVERHEAD is for dynamic + arrays; GAP_OVERHEAD is for gap arrays. Note that for (e.g.) + dynamic arrays, there is both MALLOC_OVERHEAD and DYNARR_OVERHEAD + memory: The dynamic array allocates memory above and beyond what + was asked of it, and when it in turns allocates memory using + malloc(), malloc() allocates memory beyond what it was asked + to allocate. + + Functions that accept a structure of this sort do not initialize + the fields to 0, and add any existing values to whatever was there + before; this way, you can get a cumulative effect. */ + +struct overhead_stats +{ + int was_requested; + int malloc_overhead; + int dynarr_overhead; + int gap_overhead; +}; + +#endif /* MEMORY_USAGE_STATS */ + +/* Some systems (e.g., NT) use a different path separator than Unix, + in addition to a device separator. Default the path separator + to '/', and don't test for a device separator in IS_ANY_SEP. */ + +#ifndef DIRECTORY_SEP +#define DIRECTORY_SEP '/' +#endif +#ifndef IS_DIRECTORY_SEP +#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP) +#endif +#ifndef IS_DEVICE_SEP +#ifndef DEVICE_SEP +#define IS_DEVICE_SEP(_c_) 0 +#else +#define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP) +#endif +#endif +#ifndef IS_ANY_SEP +#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_)) +#endif + +#include "emacsfns.h" + +#endif /* _XEMACS_LISP_H_ */