struct lrecord_header
{
/* index into lrecord_implementations_table[] */
- unsigned char type;
- struct {
- /* 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;
- } flags;
+ 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);
-# define set_lheader_implementation(header,imp) do { \
+#define set_lheader_implementation(header,imp) do { \
struct lrecord_header* SLI_header = (header); \
- (SLI_header)->type = lrecord_type_index (imp); \
- (SLI_header)->flags.mark = 0; \
- (SLI_header)->flags.c_readonly = 0; \
- (SLI_header)->flags.lisp_readonly = 0; \
+ SLI_header->type = lrecord_type_index (imp); \
+ SLI_header->mark = 0; \
+ SLI_header->c_readonly = 0; \
+ SLI_header->lisp_readonly = 0; \
} while (0)
struct lcrecord_header
};
/* 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
{
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);
`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);
extern int gc_in_progress;
-#define MARKED_RECORD_P(obj) (gc_in_progress && XRECORD_LHEADER (obj)->flags.mark)
-#define MARKED_RECORD_HEADER_P(lheader) ((lheader)->flags.mark)
-#define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->flags.mark = 1))
-#define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->flags.mark = 0))
+#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))
#define UNMARKABLE_RECORD_HEADER_P(lheader) \
(LHEADER_IMPLEMENTATION (lheader)->marker == this_one_is_unmarkable)
-#define C_READONLY_RECORD_HEADER_P(lheader) ((lheader)->flags.c_readonly)
-#define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->flags.lisp_readonly)
+#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)->flags.c_readonly = (lheader)->flags.lisp_readonly = 1))
+ ((void) ((lheader)->c_readonly = (lheader)->lisp_readonly = 1))
#define SET_LISP_READONLY_RECORD_HEADER(lheader) \
- ((void) ((lheader)->flags.lisp_readonly = 1))
+ ((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
+};
+
+struct lrecord_description {
+ enum lrecord_description_type type;
+ int offset;
+ EMACS_INT data1;
+ const struct struct_description *data2;
+};
+
+struct struct_description {
+ size_t size;
+ const struct lrecord_description *description;
+};
+
+#define XD_INDIRECT(val, delta) (-1-((val)|(delta<<8)))
+
+#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 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
# 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 = \
- { name, marker, printer, nuker, equal, hash, \
+ { 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))
#define RECORD_TYPEP(x, ty) \
INLINE structtype * \
error_check_##c_name (Lisp_Object obj) \
{ \
- assert (RECORD_TYPEP (obj, &lrecord_##c_name) || \
- MARKED_RECORD_P (obj)); \
+ assert (RECORD_TYPEP (obj, &lrecord_##c_name)); \
return (structtype *) XPNTR (obj); \
} \
extern Lisp_Object Q##c_name##p
INLINE structtype * \
error_check_##c_name (Lisp_Object obj) \
{ \
- assert (XGCTYPE (obj) == type_enum); \
+ assert (XTYPE (obj) == type_enum); \
return (structtype *) XPNTR (obj); \
} \
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 */
#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)
/* Note: we now have two different kinds of type-checking macros.
The "old" kind has now been renamed CONCHECK_foo. The reason for
#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_ */