comparison src/lrecord.h @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
24 #ifndef INCLUDED_lrecord_h_ 24 #ifndef INCLUDED_lrecord_h_
25 #define INCLUDED_lrecord_h_ 25 #define INCLUDED_lrecord_h_
26 26
27 /* The "lrecord" type of Lisp object is used for all object types 27 /* The "lrecord" type of Lisp object is used for all object types
28 other than a few simple ones. This allows many types to be 28 other than a few simple ones. This allows many types to be
29 implemented but only a few bits required in a Lisp object for 29 implemented but only a few bits required in a Lisp object for type
30 type information. (The tradeoff is that each object has its 30 information. (The tradeoff is that each object has its type marked
31 type marked in it, thereby increasing its size.) The first 31 in it, thereby increasing its size.) All lrecords begin with a
32 four bytes of all lrecords is either a pointer to a struct 32 `struct lrecord_header', which identifies the lisp object type, by
33 lrecord_implementation, which contains methods describing how 33 providing an index into a table of `struct lrecord_implementation',
34 to process this object, or an index into an array of pointers 34 which describes the behavior of the lisp object. It also contains
35 to struct lrecord_implementations plus some other data bits. 35 some other data bits.
36 36
37 Lrecords are of two types: straight lrecords, and lcrecords. 37 Lrecords are of two types: straight lrecords, and lcrecords.
38 Straight lrecords are used for those types of objects that have 38 Straight lrecords are used for those types of objects that have
39 their own allocation routines (typically allocated out of 2K chunks 39 their own allocation routines (typically allocated out of 2K chunks
40 of memory called `frob blocks'). These objects have a `struct 40 of memory called `frob blocks'). These objects have a `struct
41 lrecord_header' at the top, containing only the bits needed to find 41 lrecord_header' at the top, containing only the bits needed to find
42 the lrecord_implementation for the object. There are special 42 the lrecord_implementation for the object. There are special
43 routines in alloc.c to deal with each such object type. 43 routines in alloc.c to deal with each such object type.
44 44
45 Lcrecords are used for less common sorts of objects that don't 45 Lcrecords are used for less common sorts of objects that don't do
46 do their own allocation. Each such object is malloc()ed 46 their own allocation. Each such object is malloc()ed individually,
47 individually, and the objects are chained together through 47 and the objects are chained together through a `next' pointer.
48 a `next' pointer. Lcrecords have a `struct lcrecord_header' 48 Lcrecords have a `struct lcrecord_header' at the top, which
49 at the top, which contains a `struct lrecord_header' and 49 contains a `struct lrecord_header' and a `next' pointer, and are
50 a `next' pointer, and are allocated using alloc_lcrecord(). 50 allocated using alloc_lcrecord().
51 51
52 Creating a new lcrecord type is fairly easy; just follow the 52 Creating a new lcrecord type is fairly easy; just follow the
53 lead of some existing type (e.g. hash tables). Note that you 53 lead of some existing type (e.g. hash tables). Note that you
54 do not need to supply all the methods (see below); reasonable 54 do not need to supply all the methods (see below); reasonable
55 defaults are provided for many of them. Alternatively, if you're 55 defaults are provided for many of them. Alternatively, if you're
58 the opaque type. */ 58 the opaque type. */
59 59
60 struct lrecord_header 60 struct lrecord_header
61 { 61 {
62 /* index into lrecord_implementations_table[] */ 62 /* index into lrecord_implementations_table[] */
63 unsigned type :8; 63 unsigned int type :8;
64 /* 1 if the object is marked during GC. */ 64
65 unsigned mark :1; 65 /* If `mark' is 0 after the GC mark phase, the object will be freed
66 /* 1 if the object resides in read-only space */ 66 during the GC sweep phase. There are 2 ways that `mark' can be 1:
67 unsigned c_readonly : 1; 67 - by being referenced from other objects during the GC mark phase
68 - because it is permanently on, for c_readonly objects */
69 unsigned int mark :1;
70
71 /* 1 if the object resides in logically read-only space, and does not
72 reference other non-c_readonly objects.
73 Invariant: if (c_readonly == 1), then (mark == 1 && lisp_readonly == 1) */
74 unsigned int c_readonly :1;
75
68 /* 1 if the object is readonly from lisp */ 76 /* 1 if the object is readonly from lisp */
69 unsigned lisp_readonly : 1; 77 unsigned int lisp_readonly :1;
70 }; 78 };
71 79
72 struct lrecord_implementation; 80 struct lrecord_implementation;
73 int lrecord_type_index (CONST struct lrecord_implementation *implementation); 81 int lrecord_type_index (const struct lrecord_implementation *implementation);
74 82
75 #define set_lheader_implementation(header,imp) do { \ 83 #define set_lheader_implementation(header,imp) do { \
76 struct lrecord_header* SLI_header = (header); \ 84 struct lrecord_header* SLI_header = (header); \
77 SLI_header->type = lrecord_type_index (imp); \ 85 SLI_header->type = (imp)->lrecord_type_index; \
78 SLI_header->mark = 0; \ 86 SLI_header->mark = 0; \
79 SLI_header->c_readonly = 0; \ 87 SLI_header->c_readonly = 0; \
80 SLI_header->lisp_readonly = 0; \ 88 SLI_header->lisp_readonly = 0; \
81 } while (0) 89 } while (0)
82 90
83 struct lcrecord_header 91 struct lcrecord_header
84 { 92 {
85 struct lrecord_header lheader; 93 struct lrecord_header lheader;
86 94
87 /* The `next' field is normally used to chain all lrecords together 95 /* The `next' field is normally used to chain all lcrecords together
88 so that the GC can find (and free) all of them. 96 so that the GC can find (and free) all of them.
89 `alloc_lcrecord' threads records together. 97 `alloc_lcrecord' threads lcrecords together.
90 98
91 The `next' field may be used for other purposes as long as some 99 The `next' field may be used for other purposes as long as some
92 other mechanism is provided for letting the GC do its work. 100 other mechanism is provided for letting the GC do its work.
93 101
94 For example, the event and marker object types allocate members 102 For example, the event and marker object types allocate members
116 { 124 {
117 struct lcrecord_header lcheader; 125 struct lcrecord_header lcheader;
118 Lisp_Object chain; 126 Lisp_Object chain;
119 }; 127 };
120 128
121 /* see alloc.c for an explanation */ 129 enum lrecord_type
122 Lisp_Object this_one_is_unmarkable (Lisp_Object obj); 130 {
131 /* Symbol value magic types come first to make SYMBOL_VALUE_MAGIC_P fast.
132 #### This should be replaced by a symbol_value_magic_p flag
133 in the Lisp_Symbol lrecord_header. */
134 lrecord_type_symbol_value_forward,
135 lrecord_type_symbol_value_varalias,
136 lrecord_type_symbol_value_lisp_magic,
137 lrecord_type_symbol_value_buffer_local,
138 lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local,
139
140 lrecord_type_symbol,
141 lrecord_type_subr,
142 lrecord_type_cons,
143 lrecord_type_vector,
144 lrecord_type_string,
145 lrecord_type_lcrecord_list,
146 lrecord_type_compiled_function,
147 lrecord_type_weak_list,
148 lrecord_type_bit_vector,
149 lrecord_type_float,
150 lrecord_type_hash_table,
151 lrecord_type_lstream,
152 lrecord_type_process,
153 lrecord_type_charset,
154 lrecord_type_coding_system,
155 lrecord_type_char_table,
156 lrecord_type_char_table_entry,
157 lrecord_type_range_table,
158 lrecord_type_opaque,
159 lrecord_type_opaque_ptr,
160 lrecord_type_buffer,
161 lrecord_type_extent,
162 lrecord_type_extent_info,
163 lrecord_type_extent_auxiliary,
164 lrecord_type_marker,
165 lrecord_type_event,
166 lrecord_type_keymap,
167 lrecord_type_command_builder,
168 lrecord_type_timeout,
169 lrecord_type_specifier,
170 lrecord_type_console,
171 lrecord_type_device,
172 lrecord_type_frame,
173 lrecord_type_window,
174 lrecord_type_window_configuration,
175 lrecord_type_gui_item,
176 lrecord_type_popup_data,
177 lrecord_type_toolbar_button,
178 lrecord_type_color_instance,
179 lrecord_type_font_instance,
180 lrecord_type_image_instance,
181 lrecord_type_glyph,
182 lrecord_type_face,
183 lrecord_type_database,
184 lrecord_type_tooltalk_message,
185 lrecord_type_tooltalk_pattern,
186 lrecord_type_ldap,
187 lrecord_type_pgconn,
188 lrecord_type_pgresult,
189 lrecord_type_devmode,
190 lrecord_type_mswindows_dialog_id,
191 lrecord_type_last_built_in_type /* must be last */
192 };
193
194 extern unsigned int lrecord_type_count;
123 195
124 struct lrecord_implementation 196 struct lrecord_implementation
125 { 197 {
126 CONST char *name; 198 const char *name;
127 /* This function is called at GC time, to make sure that all Lisp_Objects 199
200 /* `marker' is called at GC time, to make sure that all Lisp_Objects
128 pointed to by this object get properly marked. It should call 201 pointed to by this object get properly marked. It should call
129 the mark_object function on all Lisp_Objects in the object. If 202 the mark_object function on all Lisp_Objects in the object. If
130 the return value is non-nil, it should be a Lisp_Object to be 203 the return value is non-nil, it should be a Lisp_Object to be
131 marked (don't call the mark_object function explicitly on it, 204 marked (don't call the mark_object function explicitly on it,
132 because the GC routines will do this). Doing it this way reduces 205 because the GC routines will do this). Doing it this way reduces
133 recursion, so the object returned should preferably be the one 206 recursion, so the object returned should preferably be the one
134 with the deepest level of Lisp_Object pointers. This function 207 with the deepest level of Lisp_Object pointers. This function
135 can be NULL, meaning no GC marking is necessary. */ 208 can be NULL, meaning no GC marking is necessary. */
136 Lisp_Object (*marker) (Lisp_Object); 209 Lisp_Object (*marker) (Lisp_Object);
137 /* This can be NULL if the object is an lcrecord; the 210
138 default_object_printer() in print.c will be used. */ 211 /* `printer' converts the object to a printed representation.
212 This can be NULL; in this case default_object_printer() will be
213 used instead. */
139 void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); 214 void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag);
140 /* This function is called at GC time when the object is about to 215
216 /* `finalizer' is called at GC time when the object is about to
141 be freed, and at dump time (FOR_DISKSAVE will be non-zero in this 217 be freed, and at dump time (FOR_DISKSAVE will be non-zero in this
142 case). It should perform any necessary cleanup (e.g. freeing 218 case). It should perform any necessary cleanup (e.g. freeing
143 malloc()ed memory. This can be NULL, meaning no special 219 malloc()ed memory). This can be NULL, meaning no special
144 finalization is necessary. 220 finalization is necessary.
145 221
146 WARNING: remember that the finalizer is called at dump time even 222 WARNING: remember that `finalizer' is called at dump time even
147 though the object is not being freed. */ 223 though the object is not being freed. */
148 void (*finalizer) (void *header, int for_disksave); 224 void (*finalizer) (void *header, int for_disksave);
225
149 /* This can be NULL, meaning compare objects with EQ(). */ 226 /* This can be NULL, meaning compare objects with EQ(). */
150 int (*equal) (Lisp_Object obj1, Lisp_Object obj2, int depth); 227 int (*equal) (Lisp_Object obj1, Lisp_Object obj2, int depth);
151 /* This can be NULL, meaning use the Lisp_Object itself as the hash; 228
152 but *only* if the `equal' function is EQ (if two objects are 229 /* `hash' generates hash values for use with hash tables that have
153 `equal', they *must* hash to the same value or the hashing won't 230 `equal' as their test function. This can be NULL, meaning use
154 work). */ 231 the Lisp_Object itself as the hash. But, you must still satisfy
232 the constraint that if two objects are `equal', then they *must*
233 hash to the same value in order for hash tables to work properly.
234 This means that `hash' can be NULL only if the `equal' method is
235 also NULL. */
155 unsigned long (*hash) (Lisp_Object, int); 236 unsigned long (*hash) (Lisp_Object, int);
156 237
157 /* External data layout description */ 238 /* External data layout description */
158 const struct lrecord_description *description; 239 const struct lrecord_description *description;
159 240
241 /* These functions allow any object type to have builtin property
242 lists that can be manipulated from the lisp level with
243 `get', `put', `remprop', and `object-plist'. */
160 Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); 244 Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop);
161 int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); 245 int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val);
162 int (*remprop) (Lisp_Object obj, Lisp_Object prop); 246 int (*remprop) (Lisp_Object obj, Lisp_Object prop);
163 Lisp_Object (*plist) (Lisp_Object obj); 247 Lisp_Object (*plist) (Lisp_Object obj);
164 248
165 /* Only one of these is non-0. If both are 0, it means that this type 249 /* Only one of `static_size' and `size_in_bytes_method' is non-0.
166 is not instantiable by alloc_lcrecord(). */ 250 If both are 0, this type is not instantiable by alloc_lcrecord(). */
167 size_t static_size; 251 size_t static_size;
168 size_t (*size_in_bytes_method) (CONST void *header); 252 size_t (*size_in_bytes_method) (const void *header);
169 /* A unique subtag-code (dynamically) assigned to this datatype. */ 253
170 /* (This is a pointer so the rest of this structure can be read-only.) */ 254 /* The (constant) index into lrecord_implementations_table */
171 int *lrecord_type_index; 255 enum lrecord_type lrecord_type_index;
256
172 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. 257 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e.
173 one that does not have an lcrecord_header at the front and which 258 one that does not have an lcrecord_header at the front and which
174 is (usually) allocated in frob blocks. We only use this flag for 259 is (usually) allocated in frob blocks. We only use this flag for
175 some consistency checking, and that only when error-checking is 260 some consistency checking, and that only when error-checking is
176 enabled. */ 261 enabled. */
177 int basic_p; 262 unsigned int basic_p :1;
178 }; 263 };
179 264
180 extern CONST struct lrecord_implementation *lrecord_implementations_table[]; 265 /* All the built-in lisp object types are enumerated in `enum record_type'.
266 Additional ones may be defined by a module (none yet). We leave some
267 room in `lrecord_implementations_table' for such new lisp object types. */
268 #define MODULE_DEFINABLE_TYPE_COUNT 32
269
270 extern const struct lrecord_implementation *lrecord_implementations_table[(unsigned int)lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT];
181 271
182 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \ 272 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \
183 (lrecord_implementations_table[XRECORD_LHEADER (obj)->type]) 273 LHEADER_IMPLEMENTATION (XRECORD_LHEADER (obj))
184 #define LHEADER_IMPLEMENTATION(lh) (lrecord_implementations_table[(lh)->type]) 274 #define LHEADER_IMPLEMENTATION(lh) lrecord_implementations_table[(lh)->type]
185 275
186 extern int gc_in_progress; 276 extern int gc_in_progress;
187 277
188 #define MARKED_RECORD_P(obj) (gc_in_progress && XRECORD_LHEADER (obj)->mark) 278 #define MARKED_RECORD_P(obj) (XRECORD_LHEADER (obj)->mark)
189 #define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark) 279 #define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark)
190 #define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 1)) 280 #define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 1))
191 #define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0)) 281 #define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0))
192 282
193 #define UNMARKABLE_RECORD_HEADER_P(lheader) \
194 (LHEADER_IMPLEMENTATION (lheader)->marker == this_one_is_unmarkable)
195
196 #define C_READONLY_RECORD_HEADER_P(lheader) ((lheader)->c_readonly) 283 #define C_READONLY_RECORD_HEADER_P(lheader) ((lheader)->c_readonly)
197 #define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly) 284 #define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly)
198 #define SET_C_READONLY_RECORD_HEADER(lheader) \ 285 #define SET_C_READONLY_RECORD_HEADER(lheader) do { \
199 ((void) ((lheader)->c_readonly = (lheader)->lisp_readonly = 1)) 286 struct lrecord_header *SCRRH_lheader = (lheader); \
287 SCRRH_lheader->c_readonly = 1; \
288 SCRRH_lheader->lisp_readonly = 1; \
289 SCRRH_lheader->mark = 1; \
290 } while (0)
200 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ 291 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \
201 ((void) ((lheader)->lisp_readonly = 1)) 292 ((void) ((lheader)->lisp_readonly = 1))
293 #define RECORD_MARKER(lheader) lrecord_markers[(lheader)->type]
202 294
203 /* External description stuff 295 /* External description stuff
204 296
205 A lrecord external description is an array of values. The first 297 A lrecord external description is an array of values. The first
206 value of each line is a type, the second the offset in the lrecord 298 value of each line is a type, the second the offset in the lrecord
207 structure. Following values are parameters, their presence, type 299 structure. Following values are parameters, their presence, type
208 and number is type-dependant. 300 and number is type-dependent.
209 301
210 The description ends with a "XD_END" or "XD_SPECIFIER_END" record. 302 The description ends with a "XD_END" or "XD_SPECIFIER_END" record.
211 303
212 Some example descriptions : 304 Some example descriptions :
213 305
234 326
235 XD_LISP_OBJECT_ARRAY 327 XD_LISP_OBJECT_ARRAY
236 An array of Lisp objects or pointers to lrecords. 328 An array of Lisp objects or pointers to lrecords.
237 The third element is the count. 329 The third element is the count.
238 330
239 XD_LO_RESET_NIL 331 XD_LO_RESET_NIL
240 Lisp objects which will be reset to Qnil when dumping. Useful for cleaning 332 Lisp objects which will be reset to Qnil when dumping. Useful for cleaning
241 up caches. 333 up caches.
242 334
243 XD_LO_LINK 335 XD_LO_LINK
244 Link in a linked list of objects of the same type. 336 Link in a linked list of objects of the same type.
331 #define XD_DYNARR_DESC(base_type, sub_desc) \ 423 #define XD_DYNARR_DESC(base_type, sub_desc) \
332 { XD_STRUCT_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), sub_desc }, \ 424 { XD_STRUCT_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), sub_desc }, \
333 { XD_INT, offsetof (base_type, cur) }, \ 425 { XD_INT, offsetof (base_type, cur) }, \
334 { XD_INT_RESET, offsetof (base_type, max), XD_INDIRECT(1, 0) } 426 { XD_INT_RESET, offsetof (base_type, max), XD_INDIRECT(1, 0) }
335 427
336 /* Declaring the following structures as const puts them in the
337 text (read-only) segment, which makes debugging inconvenient
338 because this segment is not mapped when processing a core-
339 dump file */
340
341 #ifdef DEBUG_XEMACS
342 #define CONST_IF_NOT_DEBUG
343 #else
344 #define CONST_IF_NOT_DEBUG CONST
345 #endif
346
347 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size. 428 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size.
348 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies. 429 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies.
349 */ 430 */
350 431
351 #if defined (ERROR_CHECK_TYPECHECK) 432 #if defined (ERROR_CHECK_TYPECHECK)
355 #endif 436 #endif
356 437
357 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ 438 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \
358 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) 439 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
359 440
360 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,structtype) \ 441 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \
361 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizeof(structtype),0,1,structtype) 442 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof(structtype),0,1,structtype)
362 443
363 #define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \ 444 #define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \
364 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) 445 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
365 446
366 #define DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,structtype) \ 447 #define DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \
367 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizeof (structtype),0,0,structtype) 448 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype)
368 449
369 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ 450 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \
370 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype) 451 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype)
371 452
372 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizer,structtype) \ 453 #define DEFINE_BASIC_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \
373 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,0,sizer,0,structtype) \ 454 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,0,sizer,1,structtype)
374 455
375 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,size,sizer,basic_p,structtype) \ 456 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \
457 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) \
458
459 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \
376 DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype) \ 460 DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype) \
377 static int lrecord_##c_name##_lrecord_type_index; \ 461 const struct lrecord_implementation lrecord_##c_name = \
378 CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name = \
379 { name, marker, printer, nuker, equal, hash, desc, \ 462 { name, marker, printer, nuker, equal, hash, desc, \
380 getprop, putprop, remprop, props, size, sizer, \ 463 getprop, putprop, remprop, plist, size, sizer, \
381 &(lrecord_##c_name##_lrecord_type_index), basic_p } \ 464 lrecord_type_##c_name, basic_p }
465
466 #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \
467 DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
468
469 #define DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \
470 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype)
471
472 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \
473 DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype)
474
475 #define DEFINE_EXTERNAL_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \
476 MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype)
477
478 #define MAKE_EXTERNAL_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \
479 DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype) \
480 unsigned int lrecord_type_##c_name = lrecord_type_count++; \
481 const struct lrecord_implementation lrecord_##c_name = \
482 { name, marker, printer, nuker, equal, hash, desc, \
483 getprop, putprop, remprop, plist, size, sizer, \
484 (enum lrecord_type)lrecord_type_##c_name, basic_p }
485
486
487 extern Lisp_Object (*lrecord_markers[]) (Lisp_Object);
488
489 #define INIT_LRECORD_IMPLEMENTATION(type) do { \
490 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \
491 lrecord_markers[lrecord_type_##type] = \
492 lrecord_implementations_table[lrecord_type_##type]->marker; \
493 } while (0)
382 494
383 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) 495 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record)
384 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) 496 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a))
385 497
386 #define RECORD_TYPEP(x, ty) \ 498 #define RECORD_TYPEP(x, ty) \
387 (LRECORDP (x) && \ 499 (LRECORDP (x) && (((unsigned int)(XRECORD_LHEADER (x)->type)) == ((unsigned int)(ty))))
388 lrecord_implementations_table[XRECORD_LHEADER (x)->type] == (ty)) 500
389 501 /* Steps to create a new object:
390 /* NOTE: the DECLARE_LRECORD() must come before the associated 502
391 DEFINE_LRECORD_*() or you will get compile errors. 503 1. Declare the struct for your object in a header file somewhere.
392 504 Remember that it must begin with
393 Furthermore, you always need to put the DECLARE_LRECORD() in a header 505
394 file, and make sure the header file is included in inline.c, even 506 struct lcrecord_header header;
395 if the type is private to a particular file. Otherwise, you will 507
396 get undefined references for the error_check_foo() inline function 508 2. Put a DECLARE_LRECORD() for the object below the struct definition,
397 under GCC. */ 509 along with the standard XFOO/XSETFOO junk.
510
511 3. Add this header file to inline.c.
512
513 4. Create the methods for your object. Note that technically you don't
514 need any, but you will almost always want at least a mark method.
515
516 5. Define your object with DEFINE_LRECORD_IMPLEMENTATION() or some
517 variant.
518
519 6. Include the header file in the .c file where you defined the object.
520
521 7. Put a call to INIT_LRECORD_IMPLEMENTATION() for the object in the
522 .c file's syms_of_foo() function.
523
524 8. Add a type enum for the object to enum lrecord_type, earlier in this
525 file.
526
527 An example:
528
529 ------------------------------ in toolbar.h -----------------------------
530
531 struct toolbar_button
532 {
533 struct lcrecord_header header;
534
535 Lisp_Object next;
536 Lisp_Object frame;
537
538 Lisp_Object up_glyph;
539 Lisp_Object down_glyph;
540 Lisp_Object disabled_glyph;
541
542 Lisp_Object cap_up_glyph;
543 Lisp_Object cap_down_glyph;
544 Lisp_Object cap_disabled_glyph;
545
546 Lisp_Object callback;
547 Lisp_Object enabled_p;
548 Lisp_Object help_string;
549
550 char enabled;
551 char down;
552 char pushright;
553 char blank;
554
555 int x, y;
556 int width, height;
557 int dirty;
558 int vertical;
559 int border_width;
560 };
561
562 DECLARE_LRECORD (toolbar_button, struct toolbar_button);
563 #define XTOOLBAR_BUTTON(x) XRECORD (x, toolbar_button, struct toolbar_button)
564 #define XSETTOOLBAR_BUTTON(x, p) XSETRECORD (x, p, toolbar_button)
565 #define TOOLBAR_BUTTONP(x) RECORDP (x, toolbar_button)
566 #define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button)
567 #define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button)
568
569 ------------------------------ in toolbar.c -----------------------------
570
571 #include "toolbar.h"
572
573 ...
574
575 static Lisp_Object
576 mark_toolbar_button (Lisp_Object obj)
577 {
578 struct toolbar_button *data = XTOOLBAR_BUTTON (obj);
579 mark_object (data->next);
580 mark_object (data->frame);
581 mark_object (data->up_glyph);
582 mark_object (data->down_glyph);
583 mark_object (data->disabled_glyph);
584 mark_object (data->cap_up_glyph);
585 mark_object (data->cap_down_glyph);
586 mark_object (data->cap_disabled_glyph);
587 mark_object (data->callback);
588 mark_object (data->enabled_p);
589 return data->help_string;
590 }
591
592 DEFINE_LRECORD_IMPLEMENTATION ("toolbar-button", toolbar_button,
593 mark_toolbar_button, 0, 0, 0, 0, 0,
594 struct toolbar_button);
595
596 ...
597
598 void
599 syms_of_toolbar (void)
600 {
601 INIT_LRECORD_IMPLEMENTATION (toolbar_button);
602
603 ...;
604 }
605
606 ------------------------------ in inline.c -----------------------------
607
608 #ifdef HAVE_TOOLBARS
609 #include "toolbar.h"
610 #endif
611
612 ------------------------------ in lrecord.h -----------------------------
613
614 enum lrecord_type
615 {
616 ...
617 lrecord_type_toolbar_button,
618 ...
619 };
620
621 */
622
623 /*
624
625 Note: Object types defined in external dynamically-loaded modules (not
626 part of the XEmacs main source code) should use DECLARE_EXTERNAL_LRECORD
627 and DEFINE_EXTERNAL_LRECORD_IMPLEMENTATION rather than DECLARE_LRECORD
628 and DEFINE_LRECORD_IMPLEMENTATION.
629
630 */
631
398 632
399 #ifdef ERROR_CHECK_TYPECHECK 633 #ifdef ERROR_CHECK_TYPECHECK
400 634
401 # define DECLARE_LRECORD(c_name, structtype) \ 635 # define DECLARE_LRECORD(c_name, structtype) \
402 extern CONST_IF_NOT_DEBUG struct lrecord_implementation \ 636 extern const struct lrecord_implementation lrecord_##c_name; \
403 lrecord_##c_name; \ 637 INLINE_HEADER structtype * \
404 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ 638 error_check_##c_name (Lisp_Object obj); \
405 INLINE structtype * \ 639 INLINE_HEADER structtype * \
406 error_check_##c_name (Lisp_Object obj) \ 640 error_check_##c_name (Lisp_Object obj) \
407 { \ 641 { \
408 assert (RECORD_TYPEP (obj, &lrecord_##c_name)); \ 642 assert (RECORD_TYPEP (obj, lrecord_type_##c_name)); \
409 return (structtype *) XPNTR (obj); \ 643 return (structtype *) XPNTR (obj); \
410 } \ 644 } \
411 extern Lisp_Object Q##c_name##p 645 extern Lisp_Object Q##c_name##p
412 646
647 # define DECLARE_EXTERNAL_LRECORD(c_name, structtype) \
648 extern unsigned int lrecord_type_##c_name; \
649 DECLARE_LRECORD(c_name, structtype)
650
413 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ 651 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \
414 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ 652 INLINE_HEADER structtype * \
415 INLINE structtype * \ 653 error_check_##c_name (Lisp_Object obj); \
654 INLINE_HEADER structtype * \
416 error_check_##c_name (Lisp_Object obj) \ 655 error_check_##c_name (Lisp_Object obj) \
417 { \ 656 { \
418 assert (XTYPE (obj) == type_enum); \ 657 assert (XTYPE (obj) == type_enum); \
419 return (structtype *) XPNTR (obj); \ 658 return (structtype *) XPNTR (obj); \
420 } \ 659 } \
423 # define XRECORD(x, c_name, structtype) error_check_##c_name (x) 662 # define XRECORD(x, c_name, structtype) error_check_##c_name (x)
424 # define XNONRECORD(x, c_name, type_enum, structtype) error_check_##c_name (x) 663 # define XNONRECORD(x, c_name, type_enum, structtype) error_check_##c_name (x)
425 664
426 # define XSETRECORD(var, p, c_name) do \ 665 # define XSETRECORD(var, p, c_name) do \
427 { \ 666 { \
428 XSETOBJ (var, Lisp_Type_Record, p); \ 667 XSETOBJ (var, p); \
429 assert (RECORD_TYPEP (var, &lrecord_##c_name)); \ 668 assert (RECORD_TYPEP (var, lrecord_type_##c_name)); \
430 } while (0) 669 } while (0)
431 670
432 #else /* not ERROR_CHECK_TYPECHECK */ 671 #else /* not ERROR_CHECK_TYPECHECK */
433 672
434 # define DECLARE_LRECORD(c_name, structtype) \ 673 # define DECLARE_LRECORD(c_name, structtype) \
435 extern Lisp_Object Q##c_name##p; \ 674 extern Lisp_Object Q##c_name##p; \
436 extern CONST_IF_NOT_DEBUG struct lrecord_implementation \ 675 extern const struct lrecord_implementation lrecord_##c_name
437 lrecord_##c_name 676 # define DECLARE_EXTERNAL_LRECORD(c_name, structtype) \
677 extern Lisp_Object Q##c_name##p; \
678 extern unsigned int lrecord_type_##c_name; \
679 extern const struct lrecord_implementation lrecord_##c_name
438 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ 680 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \
439 extern Lisp_Object Q##c_name##p 681 extern Lisp_Object Q##c_name##p
440 # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x)) 682 # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x))
441 # define XNONRECORD(x, c_name, type_enum, structtype) \ 683 # define XNONRECORD(x, c_name, type_enum, structtype) \
442 ((structtype *) XPNTR (x)) 684 ((structtype *) XPNTR (x))
443 # define XSETRECORD(var, p, c_name) XSETOBJ (var, Lisp_Type_Record, p) 685 # define XSETRECORD(var, p, c_name) XSETOBJ (var, p)
444 686
445 #endif /* not ERROR_CHECK_TYPECHECK */ 687 #endif /* not ERROR_CHECK_TYPECHECK */
446 688
447 #define RECORDP(x, c_name) RECORD_TYPEP (x, &lrecord_##c_name) 689 #define RECORDP(x, c_name) RECORD_TYPEP (x, lrecord_type_##c_name)
448 690
449 /* Note: we now have two different kinds of type-checking macros. 691 /* Note: we now have two different kinds of type-checking macros.
450 The "old" kind has now been renamed CONCHECK_foo. The reason for 692 The "old" kind has now been renamed CONCHECK_foo. The reason for
451 this is that the CONCHECK_foo macros signal a continuable error, 693 this is that the CONCHECK_foo macros signal a continuable error,
452 allowing the user (through debug-on-error) to substitute a different 694 allowing the user (through debug-on-error) to substitute a different
468 710
469 FSF Emacs does not have this problem because RMS took the cheesy 711 FSF Emacs does not have this problem because RMS took the cheesy
470 way out and disabled returning from a signal entirely. */ 712 way out and disabled returning from a signal entirely. */
471 713
472 #define CONCHECK_RECORD(x, c_name) do { \ 714 #define CONCHECK_RECORD(x, c_name) do { \
473 if (!RECORD_TYPEP (x, &lrecord_##c_name)) \ 715 if (!RECORD_TYPEP (x, lrecord_type_##c_name)) \
474 x = wrong_type_argument (Q##c_name##p, x); \ 716 x = wrong_type_argument (Q##c_name##p, x); \
475 } while (0) 717 } while (0)
476 #define CONCHECK_NONRECORD(x, lisp_enum, predicate) do {\ 718 #define CONCHECK_NONRECORD(x, lisp_enum, predicate) do {\
477 if (XTYPE (x) != lisp_enum) \ 719 if (XTYPE (x) != lisp_enum) \
478 x = wrong_type_argument (predicate, x); \ 720 x = wrong_type_argument (predicate, x); \
479 } while (0) 721 } while (0)
480 #define CHECK_RECORD(x, c_name) do { \ 722 #define CHECK_RECORD(x, c_name) do { \
481 if (!RECORD_TYPEP (x, &lrecord_##c_name)) \ 723 if (!RECORD_TYPEP (x, lrecord_type_##c_name)) \
482 dead_wrong_type_argument (Q##c_name##p, x); \ 724 dead_wrong_type_argument (Q##c_name##p, x); \
483 } while (0) 725 } while (0)
484 #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \ 726 #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \
485 if (XTYPE (x) != lisp_enum) \ 727 if (XTYPE (x) != lisp_enum) \
486 dead_wrong_type_argument (predicate, x); \ 728 dead_wrong_type_argument (predicate, x); \
487 } while (0) 729 } while (0)
488 730
489 void *alloc_lcrecord (size_t size, CONST struct lrecord_implementation *); 731 void *alloc_lcrecord (size_t size, const struct lrecord_implementation *);
490 732
491 #define alloc_lcrecord_type(type, lrecord_implementation) \ 733 #define alloc_lcrecord_type(type, lrecord_implementation) \
492 ((type *) alloc_lcrecord (sizeof (type), lrecord_implementation)) 734 ((type *) alloc_lcrecord (sizeof (type), lrecord_implementation))
493 735
494 /* Copy the data from one lcrecord structure into another, but don't 736 /* Copy the data from one lcrecord structure into another, but don't