X-Git-Url: http://git.chise.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flrecord.h;h=0dc5e052dbd5ddb6a1ec83aa4fd33fd156dc7737;hb=ea21eb75bbf90355514d65686bd53bea579f8e23;hp=dae210b1813ddfbd70d83d13b50c7faa6de33d70;hpb=2e3e3f9ee27fec50f45c282d71eaddf7c673bc56;p=chise%2Fxemacs-chise.git diff --git a/src/lrecord.h b/src/lrecord.h index dae210b..0dc5e05 100644 --- a/src/lrecord.h +++ b/src/lrecord.h @@ -50,7 +50,7 @@ Boston, MA 02111-1307, USA. */ a `next' pointer, and are allocated using alloc_lcrecord(). Creating a new lcrecord type is fairly easy; just follow the - lead of some existing type (e.g. hashtables). Note that you + lead of some existing type (e.g. hash tables). Note that you do not need to supply all the methods (see below); reasonable defaults are provided for many of them. Alternatively, if you're just looking for a way of encapsulating data (which possibly @@ -59,85 +59,55 @@ Boston, MA 02111-1307, USA. */ struct lrecord_header { - /* It would be better to put the mark-bit together with the - following datatype identification field in an 8- or 16-bit - integer rather than playing funny games with changing - header->implementation and "wasting" 32 bits on the below - pointer. The type-id would then be a 7 or 15 bit index into a - table of lrecord-implementations rather than a direct pointer. - There would be 24 (or 16) bits left over for datatype-specific - per-instance flags. - - The below is the simplest thing to do for the present, - and doesn't incur that much overhead as most Emacs records - are of such a size that the overhead isn't too bad. - (The marker datatype is the worst case.) - - It also has the very very very slight advantage that type-checking - involves one memory read (of the "implementation" slot) and a - comparison against a link-time constant address rather than a - read and a comparison against a variable value. (Variable since - it is a very good idea to assign the indices into the hypothetical - type-code table dynamically rather that pre-defining them.) - I think I remember that Elk Lisp does something like this. - Gee, I wonder if some cretin has patented it? */ - - /* - * If USE_INDEXED_LRECORD_IMPLEMENTATION is defined, we are - * implementing the scheme described in the 'It would be better - * ...' paragraph above. - */ -#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION /* index into lrecord_implementations_table[] */ - unsigned type:8; - /* 1 if the object is marked during GC, 0 otherwise. */ - unsigned mark:1; - /* 1 if the object resides in pure (read-only) space */ - unsigned pure:1; -#else - CONST struct lrecord_implementation *implementation; -#endif + unsigned type :8; + /* 1 if the object is marked during GC. */ + unsigned mark :1; + /* 1 if the object resides in read-only space */ + unsigned c_readonly : 1; + /* 1 if the object is readonly from lisp */ + unsigned lisp_readonly : 1; }; struct lrecord_implementation; int lrecord_type_index (CONST struct lrecord_implementation *implementation); -#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION -# define set_lheader_implementation(header,imp) do \ -{ \ - (header)->type = lrecord_type_index (imp); \ - (header)->mark = 0; \ - (header)->pure = 0; \ +#define set_lheader_implementation(header,imp) do { \ + struct lrecord_header* SLI_header = (header); \ + SLI_header->type = lrecord_type_index (imp); \ + SLI_header->mark = 0; \ + SLI_header->c_readonly = 0; \ + SLI_header->lisp_readonly = 0; \ } while (0) -#else -# define set_lheader_implementation(header,imp) \ - ((void) ((header)->implementation = (imp))) -#endif struct lcrecord_header { struct lrecord_header lheader; - /* The "next" field is normally used to chain all lrecords together + + /* The `next' field is normally used to chain all lrecords together so that the GC can find (and free) all of them. - "alloc_lcrecord" threads records together. + `alloc_lcrecord' threads records together. + + The `next' field may be used for other purposes as long as some + other mechanism is provided for letting the GC do its work. - The "next" field may be used for other purposes as long as some - other mechanism is provided for letting the GC do its work. (For - example, the event and marker datatypes allocate members out of - memory chunks, and are able to find all unmarked members by - sweeping through the elements of the list of chunks) */ + For example, the event and marker object types allocate members + out of memory chunks, and are able to find all unmarked members + by sweeping through the elements of the list of chunks. */ struct lcrecord_header *next; - /* This is just for debugging/printing convenience. - Having this slot doesn't hurt us much spacewise, since an lcrecord - already has the above slots together with malloc overhead. */ + + /* The `uid' field is just for debugging/printing convenience. + Having this slot doesn't hurt us much spacewise, since an + lcrecord already has the above slots plus malloc overhead. */ unsigned int uid :31; - /* A flag that indicates whether this lcrecord is on a "free list". - Free lists are used to minimize the number of calls to malloc() - when we're repeatedly allocating and freeing a number of the - same sort of lcrecord. Lcrecords on a free list always get - marked in a different fashion, so we can use this flag as a - sanity check to make sure that free lists only have freed lcrecords - and there are no freed lcrecords elsewhere. */ + + /* The `free' field is a flag that indicates whether this lcrecord + is on a "free list". Free lists are used to minimize the number + of calls to malloc() when we're repeatedly allocating and freeing + a number of the same sort of lcrecord. Lcrecords on a free list + always get marked in a different fashion, so we can use this flag + as a sanity check to make sure that free lists only have freed + lcrecords and there are no freed lcrecords elsewhere. */ unsigned int free :1; }; @@ -148,13 +118,8 @@ struct free_lcrecord_header Lisp_Object chain; }; -/* This as the value of lheader->implementation->finalizer - * means that this record is already marked */ -void this_marks_a_marked_record (void *, int); - /* see alloc.c for an explanation */ -Lisp_Object this_one_is_unmarkable (Lisp_Object obj, - void (*markobj) (Lisp_Object)); +Lisp_Object this_one_is_unmarkable (Lisp_Object obj); struct lrecord_implementation { @@ -168,7 +133,7 @@ struct lrecord_implementation recursion, so the object returned should preferably be the one with the deepest level of Lisp_Object pointers. This function can be NULL, meaning no GC marking is necessary. */ - Lisp_Object (*marker) (Lisp_Object, void (*mark_object) (Lisp_Object)); + Lisp_Object (*marker) (Lisp_Object); /* This can be NULL if the object is an lcrecord; the default_object_printer() in print.c will be used. */ void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); @@ -188,6 +153,10 @@ struct lrecord_implementation `equal', they *must* hash to the same value or the hashing won't work). */ unsigned long (*hash) (Lisp_Object, int); + + /* External data layout description */ + const struct lrecord_description *description; + Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); int (*remprop) (Lisp_Object obj, Lisp_Object prop); @@ -208,48 +177,155 @@ struct lrecord_implementation int basic_p; }; -#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION extern CONST struct lrecord_implementation *lrecord_implementations_table[]; -# define XRECORD_LHEADER_IMPLEMENTATION(obj) \ +#define XRECORD_LHEADER_IMPLEMENTATION(obj) \ (lrecord_implementations_table[XRECORD_LHEADER (obj)->type]) -# define LHEADER_IMPLEMENTATION(lh) (lrecord_implementations_table[(lh)->type]) -#else -# define XRECORD_LHEADER_IMPLEMENTATION(obj) \ - (XRECORD_LHEADER (obj)->implementation) -# define LHEADER_IMPLEMENTATION(lh) ((lh)->implementation) -#endif +#define LHEADER_IMPLEMENTATION(lh) (lrecord_implementations_table[(lh)->type]) extern int gc_in_progress; -#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION -# define MARKED_RECORD_P(obj) (gc_in_progress && XRECORD_LHEADER (obj)->mark) -#else -# define MARKED_RECORD_P(obj) (gc_in_progress && \ - XRECORD_LHEADER (obj)->implementation->finalizer == \ - this_marks_a_marked_record) -#endif +#define MARKED_RECORD_P(obj) (gc_in_progress && XRECORD_LHEADER (obj)->mark) +#define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark) +#define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 1)) +#define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0)) -#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION +#define UNMARKABLE_RECORD_HEADER_P(lheader) \ + (LHEADER_IMPLEMENTATION (lheader)->marker == this_one_is_unmarkable) + +#define C_READONLY_RECORD_HEADER_P(lheader) ((lheader)->c_readonly) +#define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly) +#define SET_C_READONLY_RECORD_HEADER(lheader) \ + ((void) ((lheader)->c_readonly = (lheader)->lisp_readonly = 1)) +#define SET_LISP_READONLY_RECORD_HEADER(lheader) \ + ((void) ((lheader)->lisp_readonly = 1)) + +/* External description stuff + + A lrecord external description is an array of values. The first + value of each line is a type, the second the offset in the lrecord + structure. Following values are parameters, their presence, type + and number is type-dependant. + + The description ends with a "XD_END" or "XD_SPECIFIER_END" record. + + Some example descriptions : + static const struct lrecord_description cons_description[] = { + { XD_LISP_OBJECT, offsetof(struct Lisp_Cons, car), 2 }, + { XD_END } + }; + + Which means "two lisp objects starting at the 'car' element" + + static const struct lrecord_description string_description[] = { + { XD_BYTECOUNT, offsetof(Lisp_String, size) }, + { XD_OPAQUE_DATA_PTR, offsetof(Lisp_String, data), XD_INDIRECT(0, 1) }, + { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, + { XD_END } + }; + "A pointer to string data at 'data', the size of the pointed array being the value + of the size variable plus 1, and one lisp object at 'plist'" + + The existing types : + XD_LISP_OBJECT + Lisp objects. The third element is the count. This is also the type to use + for pointers to other lrecords. + + XD_LO_RESET_NIL + Lisp objects which will be reset to Qnil when dumping. Useful for cleaning + up caches. + + XD_LO_LINK + Link in a linked list of objects of the same type. + + XD_OPAQUE_PTR + Pointer to undumpable data. Must be NULL when dumping. + + XD_STRUCT_PTR + Pointer to described struct. Parameters are number of structures and + struct_description. + + XD_OPAQUE_DATA_PTR + Pointer to dumpable opaque data. Parameter is the size of the data. + Pointed data must be relocatable without changes. + + XD_C_STRING + Pointer to a C string. + + XD_DOC_STRING + Pointer to a doc string (C string if positive, opaque value if negative) + + XD_INT_RESET + An integer which will be reset to a given value in the dump file. + + + XD_SIZE_T + size_t value. Used for counts. + + XD_INT + int value. Used for counts. + + XD_LONG + long value. Used for counts. + + XD_BYTECOUNT + bytecount value. Used for counts. + + XD_END + Special type indicating the end of the array. + + XD_SPECIFIER_END + Special type indicating the end of the array for a specifier. Extra + description is going to be fetched from the specifier methods. + + + Special macros: + XD_INDIRECT(line, delta) + Usable where a "count" or "size" is requested. Gives the value of + the element which is at line number 'line' in the description (count + starts at zero) and adds delta to it. +*/ + +enum lrecord_description_type { + XD_LISP_OBJECT, + XD_LO_RESET_NIL, + XD_LO_LINK, + XD_OPAQUE_PTR, + XD_STRUCT_PTR, + XD_OPAQUE_DATA_PTR, + XD_C_STRING, + XD_DOC_STRING, + XD_INT_RESET, + XD_SIZE_T, + XD_INT, + XD_LONG, + XD_BYTECOUNT, + XD_END, + XD_SPECIFIER_END +}; -# define MARKED_RECORD_HEADER_P(lheader) (lheader)->mark -# define MARK_RECORD_HEADER(lheader) (lheader)->mark = 1 -# define UNMARK_RECORD_HEADER(lheader) (lheader)->mark = 0 +struct lrecord_description { + enum lrecord_description_type type; + int offset; + EMACS_INT data1; + const struct struct_description *data2; +}; -#else /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */ +struct struct_description { + size_t size; + const struct lrecord_description *description; +}; -# define MARKED_RECORD_HEADER_P(lheader) \ - (((lheader)->implementation->finalizer) == this_marks_a_marked_record) -# define MARK_RECORD_HEADER(lheader) \ - do { (((lheader)->implementation)++); } while (0) -# define UNMARK_RECORD_HEADER(lheader) \ - do { (((lheader)->implementation)--); } while (0) +#define XD_INDIRECT(val, delta) (-1-((val)|(delta<<8))) -#endif /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */ +#define XD_IS_INDIRECT(code) (code<0) +#define XD_INDIRECT_VAL(code) ((-1-code) & 255) +#define XD_INDIRECT_DELTA(code) (((-1-code)>>8) & 255) -#define UNMARKABLE_RECORD_HEADER_P(lheader) \ - ((LHEADER_IMPLEMENTATION (lheader)->marker) \ - == this_one_is_unmarkable) +#define XD_DYNARR_DESC(base_type, sub_desc) \ + { XD_STRUCT_PTR, offsetof(base_type, base), XD_INDIRECT(1, 0), sub_desc }, \ + { XD_INT, offsetof(base_type, cur) }, \ + { XD_INT_RESET, offsetof(base_type, max), XD_INDIRECT(1, 0) } /* Declaring the following structures as const puts them in the text (read-only) segment, which makes debugging inconvenient @@ -272,44 +348,38 @@ extern int gc_in_progress; # define DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype) #endif -#define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,structtype) \ -DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,0,0,0,0,structtype) +#define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ +DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) -#define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,getprop,putprop,remprop,props,structtype) \ -MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,getprop,putprop,remprop,props,sizeof(structtype),0,1,structtype) +#define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,structtype) \ +MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizeof(structtype),0,1,structtype) -#define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,structtype) \ -DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,0,0,0,0,structtype) +#define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ +DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) -#define DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,getprop,putprop,remprop,props,structtype) \ -MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,getprop,putprop,remprop,props,sizeof (structtype),0,0,structtype) +#define DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,structtype) \ +MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizeof (structtype),0,0,structtype) -#define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,sizer,structtype) \ -DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,0,0,0,0,sizer,structtype) +#define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ +DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype) -#define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,getprop,putprop,remprop,props,sizer,structtype) \ -MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,getprop,putprop,remprop,props,0,sizer,0,structtype) \ +#define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizer,structtype) \ +MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,0,sizer,0,structtype) \ -#define MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,getprop,putprop,remprop,props,size,sizer,basic_p,structtype) \ +#define MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,size,sizer,basic_p,structtype) \ DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype) \ static int lrecord_##c_name##_lrecord_type_index; \ -CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name[2] = \ - { { name, marker, printer, nuker, equal, hash, \ - getprop, putprop, remprop, props, size, sizer, \ - &(lrecord_##c_name##_lrecord_type_index), basic_p }, \ - { 0, 0, 0, this_marks_a_marked_record, 0, 0, 0, 0, 0, 0, 0, 0, 0, basic_p } } +CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name = \ + { name, marker, printer, nuker, equal, hash, desc, \ + getprop, putprop, remprop, props, size, sizer, \ + &(lrecord_##c_name##_lrecord_type_index), basic_p } \ -#define LRECORDP(a) (XTYPE ((a)) == Lisp_Type_Record) +#define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) -#ifdef USE_INDEXED_LRECORD_IMPLEMENTATION -# define RECORD_TYPEP(x, ty) \ +#define RECORD_TYPEP(x, ty) \ (LRECORDP (x) && \ lrecord_implementations_table[XRECORD_LHEADER (x)->type] == (ty)) -#else -# define RECORD_TYPEP(x, ty) \ - (LRECORDP (x) && XRECORD_LHEADER (x)->implementation == (ty)) -#endif /* NOTE: the DECLARE_LRECORD() must come before the associated DEFINE_LRECORD_*() or you will get compile errors. @@ -324,26 +394,23 @@ CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name[2] = \ # define DECLARE_LRECORD(c_name, structtype) \ extern CONST_IF_NOT_DEBUG struct lrecord_implementation \ - lrecord_##c_name[]; \ -INLINE structtype *error_check_##c_name (Lisp_Object _obj); \ + lrecord_##c_name; \ +INLINE structtype *error_check_##c_name (Lisp_Object obj); \ INLINE structtype * \ -error_check_##c_name (Lisp_Object _obj) \ +error_check_##c_name (Lisp_Object obj) \ { \ - XUNMARK (_obj); \ - assert (RECORD_TYPEP (_obj, lrecord_##c_name) || \ - MARKED_RECORD_P (_obj)); \ - return (structtype *) XPNTR (_obj); \ + assert (RECORD_TYPEP (obj, &lrecord_##c_name)); \ + return (structtype *) XPNTR (obj); \ } \ extern Lisp_Object Q##c_name##p # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ -INLINE structtype *error_check_##c_name (Lisp_Object _obj); \ +INLINE structtype *error_check_##c_name (Lisp_Object obj); \ INLINE structtype * \ -error_check_##c_name (Lisp_Object _obj) \ +error_check_##c_name (Lisp_Object obj) \ { \ - XUNMARK (_obj); \ - assert (XGCTYPE (_obj) == type_enum); \ - return (structtype *) XPNTR (_obj); \ + assert (XTYPE (obj) == type_enum); \ + return (structtype *) XPNTR (obj); \ } \ extern Lisp_Object Q##c_name##p @@ -353,8 +420,7 @@ extern Lisp_Object Q##c_name##p # define XSETRECORD(var, p, c_name) do \ { \ XSETOBJ (var, Lisp_Type_Record, p); \ - assert (RECORD_TYPEP (var, lrecord_##c_name) || \ - MARKED_RECORD_P (var)); \ + assert (RECORD_TYPEP (var, &lrecord_##c_name)); \ } while (0) #else /* not ERROR_CHECK_TYPECHECK */ @@ -362,7 +428,7 @@ extern Lisp_Object Q##c_name##p # define DECLARE_LRECORD(c_name, structtype) \ extern Lisp_Object Q##c_name##p; \ extern CONST_IF_NOT_DEBUG struct lrecord_implementation \ - lrecord_##c_name[] + lrecord_##c_name # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ extern Lisp_Object Q##c_name##p # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x)) @@ -372,8 +438,7 @@ extern Lisp_Object Q##c_name##p #endif /* not ERROR_CHECK_TYPECHECK */ -#define RECORDP(x, c_name) RECORD_TYPEP (x, lrecord_##c_name) -#define GC_RECORDP(x, c_name) gc_record_type_p (x, lrecord_##c_name) +#define RECORDP(x, c_name) RECORD_TYPEP (x, &lrecord_##c_name) /* Note: we now have two different kinds of type-checking macros. The "old" kind has now been renamed CONCHECK_foo. The reason for @@ -399,7 +464,7 @@ extern Lisp_Object Q##c_name##p way out and disabled returning from a signal entirely. */ #define CONCHECK_RECORD(x, c_name) do { \ - if (!RECORD_TYPEP (x, lrecord_##c_name)) \ + if (!RECORD_TYPEP (x, &lrecord_##c_name)) \ x = wrong_type_argument (Q##c_name##p, x); \ } while (0) #define CONCHECK_NONRECORD(x, lisp_enum, predicate) do {\ @@ -407,7 +472,7 @@ extern Lisp_Object Q##c_name##p x = wrong_type_argument (predicate, x); \ } while (0) #define CHECK_RECORD(x, c_name) do { \ - if (!RECORD_TYPEP (x, lrecord_##c_name)) \ + if (!RECORD_TYPEP (x, &lrecord_##c_name)) \ dead_wrong_type_argument (Q##c_name##p, x); \ } while (0) #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \ @@ -420,19 +485,16 @@ void *alloc_lcrecord (size_t size, CONST struct lrecord_implementation *); #define alloc_lcrecord_type(type, lrecord_implementation) \ ((type *) alloc_lcrecord (sizeof (type), lrecord_implementation)) -int gc_record_type_p (Lisp_Object frob, - CONST struct lrecord_implementation *type); - /* Copy the data from one lcrecord structure into another, but don't overwrite the header information. */ #define copy_lcrecord(dst, src) \ - memcpy ((char *) dst + sizeof (struct lcrecord_header), \ - (char *) src + sizeof (struct lcrecord_header), \ - sizeof (*dst) - sizeof (struct lcrecord_header)) + memcpy ((char *) (dst) + sizeof (struct lcrecord_header), \ + (char *) (src) + sizeof (struct lcrecord_header), \ + sizeof (*(dst)) - sizeof (struct lcrecord_header)) #define zero_lcrecord(lcr) \ - memset ((char *) lcr + sizeof (struct lcrecord_header), 0, \ - sizeof (*lcr) - sizeof (struct lcrecord_header)) + memset ((char *) (lcr) + sizeof (struct lcrecord_header), 0, \ + sizeof (*(lcr)) - sizeof (struct lcrecord_header)) #endif /* _XEMACS_LRECORD_H_ */