Mercurial > hg > xemacs-beta
annotate src/lrecord.h @ 5117:3742ea8250b5 ben-lisp-object ben-lisp-object-final-ws-year-2005
Checking in final CVS version of workspace 'ben-lisp-object'
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Sat, 26 Dec 2009 00:20:27 -0600 |
parents | d30cd499e445 |
children | e0db3c197671 |
rev | line source |
---|---|
428 | 1 /* The "lrecord" structure (header of a compound lisp object). |
2 Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. | |
3017 | 3 Copyright (C) 1996, 2001, 2002, 2004, 2005 Ben Wing. |
428 | 4 |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Not in FSF. */ | |
23 | |
2367 | 24 /* This file has been Mule-ized, Ben Wing, 10-13-04. */ |
25 | |
440 | 26 #ifndef INCLUDED_lrecord_h_ |
27 #define INCLUDED_lrecord_h_ | |
428 | 28 |
2720 | 29 #ifdef MC_ALLOC |
30 /* The "lrecord" type of Lisp object is used for all object types | |
31 other than a few simple ones (like char and int). This allows many | |
32 types to be implemented but only a few bits required in a Lisp | |
33 object for type information. (The tradeoff is that each object has | |
34 its type marked in it, thereby increasing its size.) All lrecords | |
35 begin with a `struct lrecord_header', which identifies the lisp | |
36 object type, by providing an index into a table of `struct | |
37 lrecord_implementation', which describes the behavior of the lisp | |
38 object. It also contains some other data bits. | |
39 | |
40 Creating a new lrecord type is fairly easy; just follow the | |
41 lead of some existing type (e.g. hash tables). Note that you | |
42 do not need to supply all the methods (see below); reasonable | |
43 defaults are provided for many of them. Alternatively, if you're | |
44 just looking for a way of encapsulating data (which possibly | |
45 could contain Lisp_Objects in it), you may well be able to use | |
46 the opaque type. | |
47 */ | |
48 #else /* not MC_ALLOC */ | |
428 | 49 /* The "lrecord" type of Lisp object is used for all object types |
50 other than a few simple ones. This allows many types to be | |
442 | 51 implemented but only a few bits required in a Lisp object for type |
52 information. (The tradeoff is that each object has its type marked | |
53 in it, thereby increasing its size.) All lrecords begin with a | |
54 `struct lrecord_header', which identifies the lisp object type, by | |
55 providing an index into a table of `struct lrecord_implementation', | |
56 which describes the behavior of the lisp object. It also contains | |
57 some other data bits. | |
428 | 58 |
59 Lrecords are of two types: straight lrecords, and lcrecords. | |
60 Straight lrecords are used for those types of objects that have | |
61 their own allocation routines (typically allocated out of 2K chunks | |
62 of memory called `frob blocks'). These objects have a `struct | |
63 lrecord_header' at the top, containing only the bits needed to find | |
64 the lrecord_implementation for the object. There are special | |
1204 | 65 routines in alloc.c to create an object of each such type. |
428 | 66 |
442 | 67 Lcrecords are used for less common sorts of objects that don't do |
68 their own allocation. Each such object is malloc()ed individually, | |
69 and the objects are chained together through a `next' pointer. | |
3024 | 70 Lcrecords have a `struct old_lcrecord_header' at the top, which |
442 | 71 contains a `struct lrecord_header' and a `next' pointer, and are |
3024 | 72 allocated using old_alloc_lcrecord_type() or its variants. |
428 | 73 |
74 Creating a new lcrecord type is fairly easy; just follow the | |
75 lead of some existing type (e.g. hash tables). Note that you | |
76 do not need to supply all the methods (see below); reasonable | |
77 defaults are provided for many of them. Alternatively, if you're | |
78 just looking for a way of encapsulating data (which possibly | |
79 could contain Lisp_Objects in it), you may well be able to use | |
1204 | 80 the opaque type. --ben |
81 */ | |
2720 | 82 #endif /* not MC_ALLOC */ |
428 | 83 |
3024 | 84 #ifdef MC_ALLOC |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
85 #define ALLOC_LISP_OBJECT(type) alloc_lrecord (&lrecord_##type) |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
86 #define ALLOC_SIZED_LISP_OBJECT(size, type) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
87 alloc_sized_lrecord (size, &lrecord_##type) |
3024 | 88 #define ALLOC_LCRECORD_TYPE alloc_lrecord_type |
89 #define COPY_SIZED_LCRECORD copy_sized_lrecord | |
90 #define COPY_LCRECORD copy_lrecord | |
91 #define LISPOBJ_STORAGE_SIZE(ptr, size, stats) \ | |
92 mc_alloced_storage_size (size, stats) | |
93 #define ZERO_LCRECORD zero_lrecord | |
94 #define LCRECORD_HEADER lrecord_header | |
95 #define FREE_LCRECORD free_lrecord | |
96 #else | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
97 #define ALLOC_LISP_OBJECT(type) alloc_lcrecord (&lrecord_##type) |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
98 #define ALLOC_SIZED_LISP_OBJECT(size, type) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
99 old_alloc_sized_lcrecord (size, &lrecord_##type) |
3024 | 100 #define ALLOC_LCRECORD_TYPE old_alloc_lcrecord_type |
101 #define COPY_SIZED_LCRECORD old_copy_sized_lcrecord | |
102 #define COPY_LCRECORD old_copy_lcrecord | |
103 #define LISPOBJ_STORAGE_SIZE malloced_storage_size | |
104 #define ZERO_LCRECORD old_zero_lcrecord | |
105 #define LCRECORD_HEADER old_lcrecord_header | |
106 #define FREE_LCRECORD old_free_lcrecord | |
107 #endif | |
108 | |
1743 | 109 BEGIN_C_DECLS |
1650 | 110 |
428 | 111 struct lrecord_header |
112 { | |
1204 | 113 /* Index into lrecord_implementations_table[]. Objects that have been |
114 explicitly freed using e.g. free_cons() have lrecord_type_free in this | |
115 field. */ | |
442 | 116 unsigned int type :8; |
117 | |
2720 | 118 #ifdef MC_ALLOC |
119 /* 1 if the object is readonly from lisp */ | |
120 unsigned int lisp_readonly :1; | |
121 | |
122 /* The `free' field is a flag that indicates whether this lrecord | |
123 is currently free or not. This is used for error checking and | |
124 debugging. */ | |
125 unsigned int free :1; | |
126 | |
3063 | 127 /* The `uid' field is just for debugging/printing convenience. Having |
128 this slot doesn't hurt us spacewise, since the bits are unused | |
129 anyway. (The bits are used for strings, though.) */ | |
2720 | 130 unsigned int uid :22; |
131 | |
132 #else /* not MC_ALLOC */ | |
442 | 133 /* If `mark' is 0 after the GC mark phase, the object will be freed |
134 during the GC sweep phase. There are 2 ways that `mark' can be 1: | |
135 - by being referenced from other objects during the GC mark phase | |
136 - because it is permanently on, for c_readonly objects */ | |
137 unsigned int mark :1; | |
138 | |
139 /* 1 if the object resides in logically read-only space, and does not | |
140 reference other non-c_readonly objects. | |
141 Invariant: if (c_readonly == 1), then (mark == 1 && lisp_readonly == 1) */ | |
142 unsigned int c_readonly :1; | |
143 | |
428 | 144 /* 1 if the object is readonly from lisp */ |
442 | 145 unsigned int lisp_readonly :1; |
771 | 146 |
3063 | 147 /* The `uid' field is just for debugging/printing convenience. Having |
148 this slot doesn't hurt us spacewise, since the bits are unused | |
149 anyway. (The bits are used for strings, though.) */ | |
150 unsigned int uid :21; | |
934 | 151 |
2720 | 152 #endif /* not MC_ALLOC */ |
428 | 153 }; |
154 | |
155 struct lrecord_implementation; | |
442 | 156 int lrecord_type_index (const struct lrecord_implementation *implementation); |
3063 | 157 extern int lrecord_uid_counter; |
428 | 158 |
2720 | 159 #ifdef MC_ALLOC |
160 #define set_lheader_implementation(header,imp) do { \ | |
161 struct lrecord_header* SLI_header = (header); \ | |
162 SLI_header->type = (imp)->lrecord_type_index; \ | |
163 SLI_header->lisp_readonly = 0; \ | |
164 SLI_header->free = 0; \ | |
3063 | 165 SLI_header->uid = lrecord_uid_counter++; \ |
2720 | 166 } while (0) |
167 #else /* not MC_ALLOC */ | |
430 | 168 #define set_lheader_implementation(header,imp) do { \ |
428 | 169 struct lrecord_header* SLI_header = (header); \ |
442 | 170 SLI_header->type = (imp)->lrecord_type_index; \ |
430 | 171 SLI_header->mark = 0; \ |
172 SLI_header->c_readonly = 0; \ | |
173 SLI_header->lisp_readonly = 0; \ | |
3063 | 174 SLI_header->uid = lrecord_uid_counter++; \ |
428 | 175 } while (0) |
2720 | 176 #endif /* not MC_ALLOC */ |
428 | 177 |
2720 | 178 #ifndef MC_ALLOC |
3024 | 179 struct old_lcrecord_header |
428 | 180 { |
181 struct lrecord_header lheader; | |
182 | |
442 | 183 /* The `next' field is normally used to chain all lcrecords together |
428 | 184 so that the GC can find (and free) all of them. |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
185 `old_alloc_sized_lcrecord' threads lcrecords together. |
428 | 186 |
187 The `next' field may be used for other purposes as long as some | |
188 other mechanism is provided for letting the GC do its work. | |
189 | |
190 For example, the event and marker object types allocate members | |
191 out of memory chunks, and are able to find all unmarked members | |
192 by sweeping through the elements of the list of chunks. */ | |
3024 | 193 struct old_lcrecord_header *next; |
428 | 194 |
195 /* The `uid' field is just for debugging/printing convenience. | |
196 Having this slot doesn't hurt us much spacewise, since an | |
197 lcrecord already has the above slots plus malloc overhead. */ | |
198 unsigned int uid :31; | |
199 | |
200 /* The `free' field is a flag that indicates whether this lcrecord | |
201 is on a "free list". Free lists are used to minimize the number | |
202 of calls to malloc() when we're repeatedly allocating and freeing | |
203 a number of the same sort of lcrecord. Lcrecords on a free list | |
204 always get marked in a different fashion, so we can use this flag | |
205 as a sanity check to make sure that free lists only have freed | |
206 lcrecords and there are no freed lcrecords elsewhere. */ | |
207 unsigned int free :1; | |
208 }; | |
209 | |
210 /* Used for lcrecords in an lcrecord-list. */ | |
211 struct free_lcrecord_header | |
212 { | |
3024 | 213 struct old_lcrecord_header lcheader; |
428 | 214 Lisp_Object chain; |
215 }; | |
2720 | 216 #endif /* not MC_ALLOC */ |
428 | 217 |
442 | 218 enum lrecord_type |
219 { | |
220 /* Symbol value magic types come first to make SYMBOL_VALUE_MAGIC_P fast. | |
221 #### This should be replaced by a symbol_value_magic_p flag | |
222 in the Lisp_Symbol lrecord_header. */ | |
2720 | 223 lrecord_type_symbol_value_forward, /* 0 */ |
224 lrecord_type_symbol_value_varalias, /* 1 */ | |
225 lrecord_type_symbol_value_lisp_magic, /* 2 */ | |
226 lrecord_type_symbol_value_buffer_local, /* 3 */ | |
442 | 227 lrecord_type_max_symbol_value_magic = lrecord_type_symbol_value_buffer_local, |
2720 | 228 lrecord_type_symbol, /* 4 */ |
229 lrecord_type_subr, /* 5 */ | |
230 lrecord_type_cons, /* 6 */ | |
231 lrecord_type_vector, /* 7 */ | |
232 lrecord_type_string, /* 8 */ | |
233 #ifndef MC_ALLOC | |
442 | 234 lrecord_type_lcrecord_list, |
2720 | 235 #endif /* not MC_ALLOC */ |
236 lrecord_type_compiled_function, /* 9 */ | |
237 lrecord_type_weak_list, /* 10 */ | |
238 lrecord_type_bit_vector, /* 11 */ | |
239 lrecord_type_float, /* 12 */ | |
240 lrecord_type_hash_table, /* 13 */ | |
241 lrecord_type_lstream, /* 14 */ | |
242 lrecord_type_process, /* 15 */ | |
243 lrecord_type_charset, /* 16 */ | |
244 lrecord_type_coding_system, /* 17 */ | |
245 lrecord_type_char_table, /* 18 */ | |
246 lrecord_type_char_table_entry, /* 19 */ | |
247 lrecord_type_range_table, /* 20 */ | |
248 lrecord_type_opaque, /* 21 */ | |
249 lrecord_type_opaque_ptr, /* 22 */ | |
250 lrecord_type_buffer, /* 23 */ | |
251 lrecord_type_extent, /* 24 */ | |
252 lrecord_type_extent_info, /* 25 */ | |
253 lrecord_type_extent_auxiliary, /* 26 */ | |
254 lrecord_type_marker, /* 27 */ | |
255 lrecord_type_event, /* 28 */ | |
256 #ifdef EVENT_DATA_AS_OBJECTS /* not defined */ | |
934 | 257 lrecord_type_key_data, |
258 lrecord_type_button_data, | |
259 lrecord_type_motion_data, | |
260 lrecord_type_process_data, | |
261 lrecord_type_timeout_data, | |
262 lrecord_type_eval_data, | |
263 lrecord_type_misc_user_data, | |
264 lrecord_type_magic_eval_data, | |
265 lrecord_type_magic_data, | |
1204 | 266 #endif /* EVENT_DATA_AS_OBJECTS */ |
2720 | 267 lrecord_type_keymap, /* 29 */ |
268 lrecord_type_command_builder, /* 30 */ | |
269 lrecord_type_timeout, /* 31 */ | |
270 lrecord_type_specifier, /* 32 */ | |
271 lrecord_type_console, /* 33 */ | |
272 lrecord_type_device, /* 34 */ | |
273 lrecord_type_frame, /* 35 */ | |
274 lrecord_type_window, /* 36 */ | |
275 lrecord_type_window_mirror, /* 37 */ | |
276 lrecord_type_window_configuration, /* 38 */ | |
277 lrecord_type_gui_item, /* 39 */ | |
278 lrecord_type_popup_data, /* 40 */ | |
279 lrecord_type_toolbar_button, /* 41 */ | |
280 lrecord_type_scrollbar_instance, /* 42 */ | |
281 lrecord_type_color_instance, /* 43 */ | |
282 lrecord_type_font_instance, /* 44 */ | |
283 lrecord_type_image_instance, /* 45 */ | |
284 lrecord_type_glyph, /* 46 */ | |
285 lrecord_type_face, /* 47 */ | |
286 lrecord_type_database, /* 48 */ | |
287 lrecord_type_tooltalk_message, /* 49 */ | |
288 lrecord_type_tooltalk_pattern, /* 50 */ | |
289 lrecord_type_ldap, /* 51 */ | |
290 lrecord_type_pgconn, /* 52 */ | |
291 lrecord_type_pgresult, /* 53 */ | |
292 lrecord_type_devmode, /* 54 */ | |
293 lrecord_type_mswindows_dialog_id, /* 55 */ | |
294 lrecord_type_case_table, /* 56 */ | |
295 lrecord_type_emacs_ffi, /* 57 */ | |
296 lrecord_type_emacs_gtk_object, /* 58 */ | |
297 lrecord_type_emacs_gtk_boxed, /* 59 */ | |
298 lrecord_type_weak_box, /* 60 */ | |
299 lrecord_type_ephemeron, /* 61 */ | |
300 lrecord_type_bignum, /* 62 */ | |
301 lrecord_type_ratio, /* 63 */ | |
302 lrecord_type_bigfloat, /* 64 */ | |
303 #ifndef MC_ALLOC | |
454 | 304 lrecord_type_free, /* only used for "free" lrecords */ |
305 lrecord_type_undefined, /* only used for debugging */ | |
2720 | 306 #endif /* not MC_ALLOC */ |
307 lrecord_type_last_built_in_type /* 65 */ /* must be last */ | |
442 | 308 }; |
309 | |
1632 | 310 extern MODULE_API int lrecord_type_count; |
428 | 311 |
312 struct lrecord_implementation | |
313 { | |
2367 | 314 const Ascbyte *name; |
442 | 315 |
934 | 316 /* information for the dumper: is the object dumpable and should it |
317 be dumped. */ | |
318 unsigned int dumpable :1; | |
319 | |
442 | 320 /* `marker' is called at GC time, to make sure that all Lisp_Objects |
428 | 321 pointed to by this object get properly marked. It should call |
322 the mark_object function on all Lisp_Objects in the object. If | |
323 the return value is non-nil, it should be a Lisp_Object to be | |
324 marked (don't call the mark_object function explicitly on it, | |
325 because the GC routines will do this). Doing it this way reduces | |
326 recursion, so the object returned should preferably be the one | |
327 with the deepest level of Lisp_Object pointers. This function | |
1204 | 328 can be NULL, meaning no GC marking is necessary. |
329 | |
330 NOTE NOTE NOTE: This is not used by KKCC (which uses the data | |
331 description below instead), unless the data description is missing. | |
332 Yes, this currently means there is logic duplication. Eventually the | |
333 mark methods will be removed. */ | |
428 | 334 Lisp_Object (*marker) (Lisp_Object); |
442 | 335 |
336 /* `printer' converts the object to a printed representation. | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
337 This can be NULL; in this case internal_object_printer() will be |
442 | 338 used instead. */ |
428 | 339 void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); |
442 | 340 |
341 /* `finalizer' is called at GC time when the object is about to | |
428 | 342 be freed, and at dump time (FOR_DISKSAVE will be non-zero in this |
343 case). It should perform any necessary cleanup (e.g. freeing | |
442 | 344 malloc()ed memory). This can be NULL, meaning no special |
428 | 345 finalization is necessary. |
346 | |
442 | 347 WARNING: remember that `finalizer' is called at dump time even |
428 | 348 though the object is not being freed. */ |
349 void (*finalizer) (void *header, int for_disksave); | |
442 | 350 |
428 | 351 /* This can be NULL, meaning compare objects with EQ(). */ |
352 int (*equal) (Lisp_Object obj1, Lisp_Object obj2, int depth); | |
442 | 353 |
354 /* `hash' generates hash values for use with hash tables that have | |
355 `equal' as their test function. This can be NULL, meaning use | |
356 the Lisp_Object itself as the hash. But, you must still satisfy | |
357 the constraint that if two objects are `equal', then they *must* | |
358 hash to the same value in order for hash tables to work properly. | |
359 This means that `hash' can be NULL only if the `equal' method is | |
360 also NULL. */ | |
2515 | 361 Hashcode (*hash) (Lisp_Object, int); |
428 | 362 |
1204 | 363 /* Data layout description for your object. See long comment below. */ |
364 const struct memory_description *description; | |
428 | 365 |
442 | 366 /* These functions allow any object type to have builtin property |
367 lists that can be manipulated from the lisp level with | |
368 `get', `put', `remprop', and `object-plist'. */ | |
428 | 369 Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop); |
370 int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val); | |
371 int (*remprop) (Lisp_Object obj, Lisp_Object prop); | |
372 Lisp_Object (*plist) (Lisp_Object obj); | |
373 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
374 /* Only one of `static_size' and `size_in_bytes_method' is non-0. If |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
375 `static_size' is 0, this type is not instantiable by |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
376 ALLOC_LISP_OBJECT(). If both are 0 (this should never happen), this |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
377 object cannot be instantiated; you will get an abort() if you try.*/ |
665 | 378 Bytecount static_size; |
379 Bytecount (*size_in_bytes_method) (const void *header); | |
442 | 380 |
381 /* The (constant) index into lrecord_implementations_table */ | |
382 enum lrecord_type lrecord_type_index; | |
383 | |
2720 | 384 #ifndef MC_ALLOC |
428 | 385 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. |
3024 | 386 one that does not have an old_lcrecord_header at the front and which |
1204 | 387 is (usually) allocated in frob blocks. */ |
442 | 388 unsigned int basic_p :1; |
2720 | 389 #endif /* not MC_ALLOC */ |
428 | 390 }; |
391 | |
617 | 392 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. |
442 | 393 Additional ones may be defined by a module (none yet). We leave some |
394 room in `lrecord_implementations_table' for such new lisp object types. */ | |
395 #define MODULE_DEFINABLE_TYPE_COUNT 32 | |
396 | |
1632 | 397 extern MODULE_API const struct lrecord_implementation * |
398 lrecord_implementations_table[lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT]; | |
428 | 399 |
400 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \ | |
442 | 401 LHEADER_IMPLEMENTATION (XRECORD_LHEADER (obj)) |
402 #define LHEADER_IMPLEMENTATION(lh) lrecord_implementations_table[(lh)->type] | |
428 | 403 |
404 extern int gc_in_progress; | |
405 | |
2720 | 406 #ifdef MC_ALLOC |
407 #include "mc-alloc.h" | |
408 | |
2994 | 409 #ifdef ALLOC_TYPE_STATS |
2720 | 410 void init_lrecord_stats (void); |
2775 | 411 void inc_lrecord_string_data_stats (Bytecount size); |
412 void dec_lrecord_string_data_stats (Bytecount size); | |
2720 | 413 void inc_lrecord_stats (Bytecount size, const struct lrecord_header *h); |
414 void dec_lrecord_stats (Bytecount size_including_overhead, | |
415 const struct lrecord_header *h); | |
2994 | 416 #endif /* ALLOC_TYPE_STATS */ |
2720 | 417 |
418 /* Tell mc-alloc how to call a finalizer. */ | |
419 #define MC_ALLOC_CALL_FINALIZER(ptr) \ | |
420 { \ | |
421 Lisp_Object MCACF_obj = wrap_pointer_1 (ptr); \ | |
422 struct lrecord_header *MCACF_lheader = XRECORD_LHEADER (MCACF_obj); \ | |
423 if (XRECORD_LHEADER (MCACF_obj) && LRECORDP (MCACF_obj) \ | |
424 && !LRECORD_FREE_P (MCACF_lheader) ) \ | |
425 { \ | |
426 const struct lrecord_implementation *MCACF_implementation \ | |
427 = LHEADER_IMPLEMENTATION (MCACF_lheader); \ | |
428 if (MCACF_implementation && MCACF_implementation->finalizer) \ | |
429 MCACF_implementation->finalizer (ptr, 0); \ | |
430 } \ | |
431 } while (0) | |
432 | |
433 /* Tell mc-alloc how to call a finalizer for disksave. */ | |
434 #define MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE(ptr) \ | |
435 { \ | |
436 Lisp_Object MCACF_obj = wrap_pointer_1 (ptr); \ | |
437 struct lrecord_header *MCACF_lheader = XRECORD_LHEADER (MCACF_obj); \ | |
438 if (XRECORD_LHEADER (MCACF_obj) && LRECORDP (MCACF_obj) \ | |
439 && !LRECORD_FREE_P (MCACF_lheader) ) \ | |
440 { \ | |
441 const struct lrecord_implementation *MCACF_implementation \ | |
442 = LHEADER_IMPLEMENTATION (MCACF_lheader); \ | |
443 if (MCACF_implementation && MCACF_implementation->finalizer) \ | |
444 MCACF_implementation->finalizer (ptr, 1); \ | |
445 } \ | |
446 } while (0) | |
447 | |
448 #define LRECORD_FREE_P(ptr) \ | |
449 (((struct lrecord_header *) ptr)->free) | |
450 | |
451 #define MARK_LRECORD_AS_FREE(ptr) \ | |
452 ((void) (((struct lrecord_header *) ptr)->free = 1)) | |
453 | |
454 #define MARK_LRECORD_AS_NOT_FREE(ptr) \ | |
455 ((void) (((struct lrecord_header *) ptr)->free = 0)) | |
456 | |
457 #define MARKED_RECORD_P(obj) MARKED_P (obj) | |
458 #define MARKED_RECORD_HEADER_P(lheader) MARKED_P (lheader) | |
459 #define MARK_RECORD_HEADER(lheader) MARK (lheader) | |
460 #define UNMARK_RECORD_HEADER(lheader) UNMARK (lheader) | |
461 | |
462 #define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly) | |
463 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ | |
464 ((void) ((lheader)->lisp_readonly = 1)) | |
465 #define MARK_LRECORD_AS_LISP_READONLY(ptr) \ | |
466 ((void) (((struct lrecord_header *) ptr)->lisp_readonly = 1)) | |
467 | |
468 #else /* not MC_ALLOC */ | |
469 | |
470 #define LRECORD_FREE_P(ptr) \ | |
471 (((struct lrecord_header *) ptr)->type == lrecord_type_free) | |
472 | |
473 #define MARK_LRECORD_AS_FREE(ptr) \ | |
474 ((void) (((struct lrecord_header *) ptr)->type = lrecord_type_free)) | |
475 | |
442 | 476 #define MARKED_RECORD_P(obj) (XRECORD_LHEADER (obj)->mark) |
428 | 477 #define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark) |
478 #define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 1)) | |
479 #define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0)) | |
480 | |
481 #define C_READONLY_RECORD_HEADER_P(lheader) ((lheader)->c_readonly) | |
482 #define LISP_READONLY_RECORD_HEADER_P(lheader) ((lheader)->lisp_readonly) | |
442 | 483 #define SET_C_READONLY_RECORD_HEADER(lheader) do { \ |
484 struct lrecord_header *SCRRH_lheader = (lheader); \ | |
485 SCRRH_lheader->c_readonly = 1; \ | |
486 SCRRH_lheader->lisp_readonly = 1; \ | |
487 SCRRH_lheader->mark = 1; \ | |
488 } while (0) | |
428 | 489 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \ |
490 ((void) ((lheader)->lisp_readonly = 1)) | |
2720 | 491 #endif /* not MC_ALLOC */ |
1676 | 492 |
493 #ifdef USE_KKCC | |
494 #define RECORD_DESCRIPTION(lheader) lrecord_memory_descriptions[(lheader)->type] | |
495 #else /* not USE_KKCC */ | |
442 | 496 #define RECORD_MARKER(lheader) lrecord_markers[(lheader)->type] |
1676 | 497 #endif /* not USE_KKCC */ |
428 | 498 |
934 | 499 #define RECORD_DUMPABLE(lheader) (lrecord_implementations_table[(lheader)->type])->dumpable |
1204 | 500 |
501 /* Data description stuff | |
934 | 502 |
1204 | 503 Data layout descriptions describe blocks of memory (in particular, Lisp |
504 objects and other objects on the heap, and global objects with pointers | |
505 to such heap objects), including their size and a list of the elements | |
506 that need relocating, marking or other special handling. They are | |
507 currently used in two places: by pdump [the new, portable dumper] and | |
508 KKCC [the new garbage collector]. The two subsystems use the | |
509 descriptions in different ways, and as a result some of the descriptions | |
510 are appropriate only for one or the other, when it is known that only | |
511 that subsystem will use the description. (This is particularly the case | |
512 with objects that can't be dumped, because pdump needs more info than | |
513 KKCC.) However, properly written descriptions are appropriate for both, | |
514 and you should strive to write your descriptions that way, since the | |
515 dumpable status of an object may change and new uses for the | |
516 descriptions may be created. (An example that comes to mind is a | |
517 facility for determining the memory usage of XEmacs data structures -- | |
518 like `buffer-memory-usage', `window-memory-usage', etc. but more | |
519 general.) | |
520 | |
521 More specifically: | |
428 | 522 |
1204 | 523 Pdump (the portable dumper) needs to write out all objects in heap |
524 space, and later on (in another invocation of XEmacs) load them back | |
525 into the heap, relocating all pointers to the heap objects in the global | |
526 data space. ("Heap" means anything malloc()ed, including all Lisp | |
527 objects, and "global data" means anything declared globally or | |
528 `static'.) Pdump, then, needs to be told about the location of all | |
529 global pointers to heap objects, all the description of all such | |
530 objects, including their size and any pointers to other heap (aka | |
531 "relocatable") objects. (Pdump assumes that the heap may occur in | |
532 different places in different invocations -- therefore, it is not enough | |
533 simply to write out the entire heap and later reload it at the same | |
534 location -- but that global data is always in the same place, and hence | |
535 pointers to it do not need to be relocated. This assumption holds true | |
536 in general for modern operating systems, but would be broken, for | |
537 example, in a system without virtual memory, or when dealing with shared | |
538 libraries. Also, unlike unexec, pdump does not usually write out or | |
539 restore objects in the global data space, and thus they need to be | |
540 initialized every time XEmacs is loaded. This is the purpose of the | |
541 reinit_*() functions throughout XEmacs. [It's possible, however, to make | |
542 pdump restore global data. This must be done, of course, for heap | |
543 pointers, but is also done for other values that are not easy to | |
544 recompute -- in particular, values established by the Lisp code loaded | |
545 at dump time.]) Note that the data type `Lisp_Object' is basically just | |
546 a relocatable pointer disguised as a long, and in general pdump treats | |
547 the Lisp_Object values and pointers to Lisp objects (e.g. Lisp_Object | |
548 vs. `struct frame *') identically. (NOTE: This equivalence depends | |
549 crucially on the current "minimal tagbits" implementation of Lisp_Object | |
550 pointers.) | |
428 | 551 |
1204 | 552 Descriptions are used by pdump in three places: (a) descriptions of Lisp |
553 objects, referenced in the DEFINE_*LRECORD_*IMPLEMENTATION*() call; (b) | |
554 descriptions of global objects to be dumped, registered by | |
555 dump_add_root_block(); (c) descriptions of global pointers to | |
2367 | 556 non-Lisp_Object heap objects, registered by dump_add_root_block_ptr(). |
1204 | 557 The descriptions need to tell pdump which elements of your structure are |
558 Lisp_Objects or structure pointers, plus the descriptions in turn of the | |
559 non-Lisp_Object structures pointed to. If these structures are you own | |
560 private ones, you will have to write these recursive descriptions | |
561 yourself; otherwise, you are reusing a structure already in existence | |
562 elsewhere and there is probably already a description for it. | |
563 | |
564 Pdump does not care about Lisp objects that cannot be dumped (the | |
565 dumpable flag to DEFINE_*LRECORD_*IMPLEMENTATION*() is 0). | |
566 | |
567 KKCC also uses data layout descriptions, but differently. It cares | |
568 about all objects, dumpable or not, but specifically only wants to know | |
569 about Lisp_Objects in your object and in structures pointed to. Thus, | |
570 it doesn't care about things like pointers to structures ot other blocks | |
571 of memory with no Lisp Objects in them, which pdump would care a lot | |
572 about. | |
573 | |
574 Technically, then, you could write your description differently | |
575 depending on whether your object is dumpable -- the full pdump | |
576 description if so, the abbreviated KKCC description if not. In fact, | |
577 some descriptions are written this way. This is dangerous, though, | |
578 because another use might come along for the data descriptions, that | |
579 doesn't care about the dumper flag and makes use of some of the stuff | |
580 normally omitted from the "abbreviated" description -- see above. | |
581 | |
582 A memory_description is an array of values. (This is actually | |
771 | 583 misnamed, in that it does not just describe lrecords, but any |
584 blocks of memory.) The first value of each line is a type, the | |
585 second the offset in the lrecord structure. The third and | |
586 following elements are parameters; their presence, type and number | |
587 is type-dependent. | |
588 | |
1204 | 589 The description ends with an "XD_END" record. |
771 | 590 |
591 The top-level description of an lrecord or lcrecord does not need | |
592 to describe every element, just the ones that need to be relocated, | |
593 since the size of the lrecord is known. (The same goes for nested | |
594 structures, whenever the structure size is given, rather than being | |
595 defaulted by specifying 0 for the size.) | |
596 | |
1204 | 597 A sized_memory_description is a memory_description plus the size of the |
598 block of memory. The size field in a sized_memory_description can be | |
599 given as zero, i.e. unspecified, meaning that the last element in the | |
600 structure is described in the description and the size of the block can | |
601 therefore be computed from it. (This is useful for stretchy arrays.) | |
602 | |
603 memory_descriptions are used to describe lrecords (the size of the | |
604 lrecord is elsewhere in its description, attached to its methods, so it | |
605 does not need to be given here) and global objects, where the size is an | |
606 argument to the call to dump_add_root_block(). | |
607 sized_memory_descriptions are used for pointers and arrays in | |
2367 | 608 memory_descriptions and for calls to dump_add_root_block_ptr(). (#### |
1204 | 609 It is not obvious why this is so in the latter case. Probably, calls to |
2367 | 610 dump_add_root_block_ptr() should use plain memory_descriptions and have |
1204 | 611 the size be an argument to the call.) |
612 | |
613 NOTE: Anywhere that a sized_memory_description occurs inside of a plain | |
614 memory_description, a "description map" can be substituted. Rather than | |
615 being an actual description, this describes how to find the description | |
616 by looking inside of the object being described. This is a convenient | |
617 way to describe Lisp objects with subtypes and corresponding | |
618 type-specific data. | |
428 | 619 |
620 Some example descriptions : | |
440 | 621 |
814 | 622 struct Lisp_String |
623 { | |
624 struct lrecord_header lheader; | |
625 Bytecount size; | |
867 | 626 Ibyte *data; |
814 | 627 Lisp_Object plist; |
628 }; | |
629 | |
1204 | 630 static const struct memory_description cons_description[] = { |
440 | 631 { XD_LISP_OBJECT, offsetof (Lisp_Cons, car) }, |
632 { XD_LISP_OBJECT, offsetof (Lisp_Cons, cdr) }, | |
428 | 633 { XD_END } |
634 }; | |
635 | |
440 | 636 Which means "two lisp objects starting at the 'car' and 'cdr' elements" |
428 | 637 |
1204 | 638 static const struct memory_description string_description[] = { |
814 | 639 { XD_BYTECOUNT, offsetof (Lisp_String, size) }, |
1204 | 640 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT (0, 1) }, |
814 | 641 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, |
642 { XD_END } | |
643 }; | |
644 | |
645 "A pointer to string data at 'data', the size of the pointed array being | |
646 the value of the size variable plus 1, and one lisp object at 'plist'" | |
647 | |
648 If your object has a pointer to an array of Lisp_Objects in it, something | |
649 like this: | |
650 | |
651 struct Lisp_Foo | |
652 { | |
653 ...; | |
654 int count; | |
655 Lisp_Object *objects; | |
656 ...; | |
657 } | |
658 | |
2367 | 659 You'd use XD_BLOCK_PTR, something like: |
814 | 660 |
1204 | 661 static const struct memory_description foo_description[] = { |
662 ... | |
663 { XD_INT, offsetof (Lisp_Foo, count) }, | |
2367 | 664 { XD_BLOCK_PTR, offsetof (Lisp_Foo, objects), |
2551 | 665 XD_INDIRECT (0, 0), { &lisp_object_description } }, |
1204 | 666 ... |
667 }; | |
668 | |
669 lisp_object_description is declared in alloc.c, like this: | |
670 | |
671 static const struct memory_description lisp_object_description_1[] = { | |
814 | 672 { XD_LISP_OBJECT, 0 }, |
673 { XD_END } | |
674 }; | |
675 | |
1204 | 676 const struct sized_memory_description lisp_object_description = { |
814 | 677 sizeof (Lisp_Object), |
1204 | 678 lisp_object_description_1 |
814 | 679 }; |
680 | |
2367 | 681 Another example of XD_BLOCK_PTR: |
428 | 682 |
1204 | 683 typedef struct htentry |
814 | 684 { |
685 Lisp_Object key; | |
686 Lisp_Object value; | |
1204 | 687 } htentry; |
814 | 688 |
689 struct Lisp_Hash_Table | |
690 { | |
3017 | 691 struct LCRECORD_HEADER header; |
814 | 692 Elemcount size; |
693 Elemcount count; | |
694 Elemcount rehash_count; | |
695 double rehash_size; | |
696 double rehash_threshold; | |
697 Elemcount golden_ratio; | |
698 hash_table_hash_function_t hash_function; | |
699 hash_table_test_function_t test_function; | |
1204 | 700 htentry *hentries; |
814 | 701 enum hash_table_weakness weakness; |
702 Lisp_Object next_weak; // Used to chain together all of the weak | |
703 // hash tables. Don't mark through this. | |
704 }; | |
705 | |
1204 | 706 static const struct memory_description htentry_description_1[] = { |
707 { XD_LISP_OBJECT, offsetof (htentry, key) }, | |
708 { XD_LISP_OBJECT, offsetof (htentry, value) }, | |
814 | 709 { XD_END } |
710 }; | |
711 | |
1204 | 712 static const struct sized_memory_description htentry_description = { |
713 sizeof (htentry), | |
714 htentry_description_1 | |
814 | 715 }; |
716 | |
1204 | 717 const struct memory_description hash_table_description[] = { |
814 | 718 { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) }, |
2367 | 719 { XD_BLOCK_PTR, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (0, 1), |
2551 | 720 { &htentry_description } }, |
814 | 721 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, |
722 { XD_END } | |
723 }; | |
724 | |
725 Note that we don't need to declare all the elements in the structure, just | |
726 the ones that need to be relocated (Lisp_Objects and structures) or that | |
727 need to be referenced as counts for relocated objects. | |
728 | |
1204 | 729 A description map looks like this: |
730 | |
731 static const struct sized_memory_description specifier_extra_description_map [] = { | |
732 { offsetof (Lisp_Specifier, methods) }, | |
733 { offsetof (struct specifier_methods, extra_description) }, | |
734 { -1 } | |
735 }; | |
736 | |
737 const struct memory_description specifier_description[] = { | |
738 ... | |
2367 | 739 { XD_BLOCK_ARRAY, offset (Lisp_Specifier, data), 1, |
2551 | 740 { specifier_extra_description_map } }, |
1204 | 741 ... |
742 { XD_END } | |
743 }; | |
744 | |
745 This would be appropriate for an object that looks like this: | |
746 | |
747 struct specifier_methods | |
748 { | |
749 ... | |
750 const struct sized_memory_description *extra_description; | |
751 ... | |
752 }; | |
753 | |
754 struct Lisp_Specifier | |
755 { | |
3017 | 756 struct LCRECORD_HEADER header; |
1204 | 757 struct specifier_methods *methods; |
758 | |
759 ... | |
760 // type-specific extra data attached to a specifier | |
761 max_align_t data[1]; | |
762 }; | |
763 | |
764 The description map means "retrieve a pointer into the object at offset | |
765 `offsetof (Lisp_Specifier, methods)' , then in turn retrieve a pointer | |
766 into that object at offset `offsetof (struct specifier_methods, | |
767 extra_description)', and that is the sized_memory_description to use." | |
768 There can be any number of indirections, which can be either into | |
769 straight pointers or Lisp_Objects. The way that description maps are | |
770 distinguished from normal sized_memory_descriptions is that in the | |
771 former, the memory_description pointer is NULL. | |
772 | |
773 --ben | |
774 | |
814 | 775 |
776 The existing types : | |
777 | |
778 | |
428 | 779 XD_LISP_OBJECT |
1204 | 780 |
781 A Lisp object. This is also the type to use for pointers to other lrecords | |
782 (e.g. struct frame *). | |
428 | 783 |
440 | 784 XD_LISP_OBJECT_ARRAY |
1204 | 785 |
771 | 786 An array of Lisp objects or (equivalently) pointers to lrecords. |
787 The parameter (i.e. third element) is the count. This would be declared | |
788 as Lisp_Object foo[666]. For something declared as Lisp_Object *foo, | |
2367 | 789 use XD_BLOCK_PTR, whose description parameter is a sized_memory_description |
771 | 790 consisting of only XD_LISP_OBJECT and XD_END. |
440 | 791 |
428 | 792 XD_LO_LINK |
1204 | 793 |
771 | 794 Weak link in a linked list of objects of the same type. This is a |
795 link that does NOT generate a GC reference. Thus the pdumper will | |
796 not automatically add the referenced object to the table of all | |
797 objects to be dumped, and when storing and loading the dumped data | |
798 will automatically prune unreferenced objects in the chain and link | |
799 each referenced object to the next referenced object, even if it's | |
800 many links away. We also need to special handling of a similar | |
801 nature for the root of the chain, which will be a staticpro()ed | |
802 object. | |
432 | 803 |
428 | 804 XD_OPAQUE_PTR |
1204 | 805 |
428 | 806 Pointer to undumpable data. Must be NULL when dumping. |
807 | |
2551 | 808 XD_OPAQUE_PTR_CONVERTIBLE |
809 | |
810 Pointer to data which is not directly dumpable but can be converted | |
811 to a dumpable, opaque external representation. The parameter is | |
812 a pointer to an opaque_convert_functions struct. | |
813 | |
814 XD_OPAQUE_DATA_CONVERTIBLE | |
815 | |
816 Data which is not directly dumpable but can be converted to a | |
817 dumpable, opaque external representation. The parameter is a | |
818 pointer to an opaque_convert_functions struct. | |
819 | |
2367 | 820 XD_BLOCK_PTR |
1204 | 821 |
771 | 822 Pointer to block of described memory. (This is misnamed: It is NOT |
823 necessarily a pointer to a struct foo.) Parameters are number of | |
1204 | 824 contiguous blocks and sized_memory_description. |
771 | 825 |
2367 | 826 XD_BLOCK_ARRAY |
1204 | 827 |
771 | 828 Array of blocks of described memory. Parameters are number of |
2367 | 829 structures and sized_memory_description. This differs from XD_BLOCK_PTR |
771 | 830 in that the parameter is declared as struct foo[666] instead of |
831 struct *foo. In other words, the block of memory holding the | |
832 structures is within the containing structure, rather than being | |
833 elsewhere, with a pointer in the containing structure. | |
428 | 834 |
1204 | 835 NOTE NOTE NOTE: Be sure that you understand the difference between |
2367 | 836 XD_BLOCK_PTR and XD_BLOCK_ARRAY: |
1204 | 837 - struct foo bar[666], i.e. 666 inline struct foos |
2367 | 838 --> XD_BLOCK_ARRAY, argument 666, pointing to a description of |
1204 | 839 struct foo |
840 - struct foo *bar, i.e. pointer to a block of 666 struct foos | |
2367 | 841 --> XD_BLOCK_PTR, argument 666, pointing to a description of |
1204 | 842 struct foo |
843 - struct foo *bar[666], i.e. 666 pointers to separate blocks of struct foos | |
2367 | 844 --> XD_BLOCK_ARRAY, argument 666, pointing to a description of |
1204 | 845 a single pointer to struct foo; the description is a single |
2367 | 846 XD_BLOCK_PTR, argument 1, which in turn points to a description |
1204 | 847 of struct foo. |
848 | |
2367 | 849 NOTE also that an XD_BLOCK_PTR of 666 foos is equivalent to an |
850 XD_BLOCK_PTR of 1 bar, where the description of `bar' is an | |
851 XD_BLOCK_ARRAY of 666 foos. | |
852 | |
428 | 853 XD_OPAQUE_DATA_PTR |
1204 | 854 |
428 | 855 Pointer to dumpable opaque data. Parameter is the size of the data. |
856 Pointed data must be relocatable without changes. | |
857 | |
771 | 858 XD_UNION |
1204 | 859 |
860 Union of two or more different types of data. Parameters are a constant | |
861 which determines which type the data is (this is usually an XD_INDIRECT, | |
862 referring to one of the fields in the structure), and a "sizing lobby" (a | |
863 sized_memory_description, which points to a memory_description and | |
864 indicates its size). The size field in the sizing lobby describes the | |
865 size of the union field in the object, and the memory_description in it | |
866 is referred to as a "union map" and has a special interpretation: The | |
867 offset field is replaced by a constant, which is compared to the first | |
868 parameter of the XD_UNION descriptor to determine if this description | |
869 applies to the union data, and XD_INDIRECT references refer to the | |
870 containing object and description. Note that the description applies | |
2367 | 871 "inline" to the union data, like XD_BLOCK_ARRAY and not XD_BLOCK_PTR. |
1204 | 872 If the union data is a pointer to different types of structures, each |
2367 | 873 element in the memory_description should be an XD_BLOCK_PTR. See |
1204 | 874 unicode.c, redisplay.c and objects.c for examples of XD_UNION. |
875 | |
876 XD_UNION_DYNAMIC_SIZE | |
877 | |
878 Same as XD_UNION except that this is used for objects where the size of | |
879 the object containing the union varies depending on the particular value | |
880 of the union constant. That is, an object with plain XD_UNION typically | |
881 has the union declared as `union foo' or as `void *', where an object | |
882 with XD_UNION_DYNAMIC_SIZE typically has the union as the last element, | |
2367 | 883 and declared as something like Rawbyte foo[1]. With plain XD_UNION, the |
1204 | 884 object is (usually) of fixed size and always contains enough space for |
885 the data associated with all possible union constants, and thus the union | |
886 constant can potentially change during the lifetime of the object. With | |
887 XD_UNION_DYNAMIC_SIZE, however, the union constant is fixed at the time | |
888 of creation of the object, and the size of the object is computed | |
889 dynamically at creation time based on the size of the data associated | |
890 with the union constant. Currently, the only difference between XD_UNION | |
891 and XD_UNION_DYNAMIC_SIZE is how the size of the union data is | |
892 calculated, when (a) the structure containing the union has no size | |
893 given; (b) the union occurs as the last element in the structure; and (c) | |
894 the union has no size given (in the first-level sized_memory_description | |
895 pointed to). In this circumstance, the size of XD_UNION comes from the | |
896 max size of the data associated with all possible union constants, | |
897 whereas the size of XD_UNION_DYNAMIC_SIZE comes from the size of the data | |
898 associated with the currently specified (and unchangeable) union | |
899 constant. | |
771 | 900 |
2367 | 901 XD_ASCII_STRING |
1204 | 902 |
2367 | 903 Pointer to a C string, purely ASCII. |
428 | 904 |
905 XD_DOC_STRING | |
1204 | 906 |
2367 | 907 Pointer to a doc string (C string in pure ASCII if positive, |
908 opaque value if negative) | |
428 | 909 |
910 XD_INT_RESET | |
1204 | 911 |
428 | 912 An integer which will be reset to a given value in the dump file. |
913 | |
1204 | 914 XD_ELEMCOUNT |
771 | 915 |
665 | 916 Elemcount value. Used for counts. |
647 | 917 |
665 | 918 XD_BYTECOUNT |
1204 | 919 |
665 | 920 Bytecount value. Used for counts. |
647 | 921 |
665 | 922 XD_HASHCODE |
1204 | 923 |
665 | 924 Hashcode value. Used for the results of hashing functions. |
428 | 925 |
926 XD_INT | |
1204 | 927 |
428 | 928 int value. Used for counts. |
929 | |
930 XD_LONG | |
1204 | 931 |
428 | 932 long value. Used for counts. |
933 | |
771 | 934 XD_BYTECOUNT |
1204 | 935 |
771 | 936 bytecount value. Used for counts. |
937 | |
428 | 938 XD_END |
1204 | 939 |
428 | 940 Special type indicating the end of the array. |
941 | |
942 | |
943 Special macros: | |
1204 | 944 |
945 XD_INDIRECT (line, delta) | |
946 Usable where a count, size, offset or union constant is requested. Gives | |
947 the value of the element which is at line number 'line' in the | |
948 description (count starts at zero) and adds delta to it, which must | |
949 (currently) be positive. | |
428 | 950 */ |
951 | |
1204 | 952 enum memory_description_type |
647 | 953 { |
440 | 954 XD_LISP_OBJECT_ARRAY, |
428 | 955 XD_LISP_OBJECT, |
956 XD_LO_LINK, | |
957 XD_OPAQUE_PTR, | |
2551 | 958 XD_OPAQUE_PTR_CONVERTIBLE, |
959 XD_OPAQUE_DATA_CONVERTIBLE, | |
960 XD_OPAQUE_DATA_PTR, | |
2367 | 961 XD_BLOCK_PTR, |
962 XD_BLOCK_ARRAY, | |
771 | 963 XD_UNION, |
1204 | 964 XD_UNION_DYNAMIC_SIZE, |
2367 | 965 XD_ASCII_STRING, |
428 | 966 XD_DOC_STRING, |
967 XD_INT_RESET, | |
665 | 968 XD_BYTECOUNT, |
969 XD_ELEMCOUNT, | |
970 XD_HASHCODE, | |
428 | 971 XD_INT, |
972 XD_LONG, | |
1204 | 973 XD_END |
428 | 974 }; |
975 | |
1204 | 976 enum data_description_entry_flags |
647 | 977 { |
1204 | 978 /* If set, KKCC does not process this entry. |
979 | |
980 (1) One obvious use is with things that pdump saves but which do not get | |
981 marked normally -- for example the next and prev fields in a marker. The | |
982 marker chain is weak, with its entries removed when they are finalized. | |
983 | |
984 (2) This can be set on structures not containing any Lisp objects, or (more | |
985 usefully) on structures that contain Lisp objects but where the objects | |
986 always occur in another structure as well. For example, the extent lists | |
987 kept by a buffer keep the extents in two lists, one sorted by the start | |
988 of the extent and the other by the end. There's no point in marking | |
989 both, since each contains the same objects as the other; but when dumping | |
990 (if we were to dump such a structure), when computing memory size, etc., | |
991 it's crucial to tag both sides. | |
992 */ | |
993 XD_FLAG_NO_KKCC = 1, | |
994 /* If set, pdump does not process this entry. */ | |
995 XD_FLAG_NO_PDUMP = 2, | |
996 /* Indicates that this is a "default" entry in a union map. */ | |
997 XD_FLAG_UNION_DEFAULT_ENTRY = 4, | |
2720 | 998 #ifndef MC_ALLOC |
1204 | 999 /* Indicates that this is a free Lisp object we're marking. |
1000 Only relevant for ERROR_CHECK_GC. This occurs when we're marking | |
1001 lcrecord-lists, where the objects have had their type changed to | |
1002 lrecord_type_free and also have had their free bit set, but we mark | |
1003 them as normal. */ | |
1429 | 1004 XD_FLAG_FREE_LISP_OBJECT = 8 |
2720 | 1005 #endif /* not MC_ALLOC */ |
1204 | 1006 #if 0 |
1429 | 1007 , |
1204 | 1008 /* Suggestions for other possible flags: */ |
1009 | |
1010 /* Eliminate XD_UNION_DYNAMIC_SIZE and replace it with a flag, like this. */ | |
1011 XD_FLAG_UNION_DYNAMIC_SIZE = 16, | |
1012 /* Require that everyone who uses a description map has to flag it, so | |
1013 that it's easy to tell, when looking through the code, where the | |
1014 description maps are and who's using them. This might also become | |
1015 necessary if for some reason the format of the description map is | |
1016 expanded and we need to stick a pointer in the second slot (although | |
1017 we could still ensure that the second slot in the first entry was NULL | |
1018 or <0). */ | |
1429 | 1019 XD_FLAG_DESCRIPTION_MAP = 32 |
1204 | 1020 #endif |
428 | 1021 }; |
1022 | |
2551 | 1023 union memory_contents_description |
1024 { | |
1025 /* The first element is used by static initializers only. We always read | |
1026 from one of the other two pointers. */ | |
1027 const void *write_only; | |
1028 const struct sized_memory_description *descr; | |
1029 const struct opaque_convert_functions *funcs; | |
1030 }; | |
1031 | |
1204 | 1032 struct memory_description |
1033 { | |
1034 enum memory_description_type type; | |
1035 Bytecount offset; | |
1036 EMACS_INT data1; | |
2551 | 1037 union memory_contents_description data2; |
1204 | 1038 /* Indicates which subsystems process this entry, plus (potentially) other |
1039 flags that apply to this entry. */ | |
1040 int flags; | |
1041 }; | |
428 | 1042 |
1204 | 1043 struct sized_memory_description |
1044 { | |
1045 Bytecount size; | |
1046 const struct memory_description *description; | |
1047 }; | |
1048 | |
2551 | 1049 |
1050 struct opaque_convert_functions | |
1051 { | |
1052 /* Used by XD_OPAQUE_PTR_CONVERTIBLE and | |
1053 XD_OPAQUE_DATA_CONVERTIBLE */ | |
1054 | |
1055 /* Converter to external representation, for those objects from | |
1056 external libraries that can't be directly dumped as opaque data | |
1057 because they contain pointers. This is called at dump time to | |
1058 convert to an opaque, pointer-less representation. | |
1059 | |
1060 This function must put a pointer to the opaque result in *data | |
1061 and its size in *size. */ | |
1062 void (*convert)(const void *object, void **data, Bytecount *size); | |
1063 | |
1064 /* Post-conversion cleanup. Optional (null if not provided). | |
1065 | |
1066 When provided it will be called post-dumping to free any storage | |
1067 allocated for the conversion results. */ | |
1068 void (*convert_free)(const void *object, void *data, Bytecount size); | |
1069 | |
1070 /* De-conversion. | |
1071 | |
1072 At reload time, rebuilds the object from the converted form. | |
1073 "object" is 0 for the PTR case, return is ignored in the DATA | |
1074 case. */ | |
1075 void *(*deconvert)(void *object, void *data, Bytecount size); | |
1076 | |
1077 }; | |
1078 | |
1204 | 1079 extern const struct sized_memory_description lisp_object_description; |
1080 | |
1081 #define XD_INDIRECT(val, delta) (-1 - (Bytecount) ((val) | ((delta) << 8))) | |
428 | 1082 |
1204 | 1083 #define XD_IS_INDIRECT(code) ((code) < 0) |
1084 #define XD_INDIRECT_VAL(code) ((-1 - (code)) & 255) | |
1085 #define XD_INDIRECT_DELTA(code) ((-1 - (code)) >> 8) | |
1086 | |
1087 #define XD_DYNARR_DESC(base_type, sub_desc) \ | |
2551 | 1088 { XD_BLOCK_PTR, offsetof (base_type, base), XD_INDIRECT(1, 0), {sub_desc} },\ |
1204 | 1089 { XD_INT, offsetof (base_type, cur) }, \ |
1090 { XD_INT_RESET, offsetof (base_type, max), XD_INDIRECT(1, 0) } \ | |
1091 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1092 /* DEFINE_LISP_OBJECT is for objects with constant size. |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1093 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1094 DEFINE_SIZABLE_LISP_OBJECT is for objects whose size varies. |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1095 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1096 DEFINE_FROB_BLOCK_LISP_OBJECT is for objects that are allocated in |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1097 large blocks ("frob blocks"), which are parceled up individually. Such |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1098 objects need special handling in alloc.c. This does not apply to |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1099 MC_ALLOC, because it does this automatically. |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1100 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1101 DEFINE_*_WITH_PROPS is for objects which support the unified property |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1102 interface using `get', `put', `remprop' and `object-plist'. |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1103 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1104 DEFINE_EXTERNAL_* is for objects defined in an external module. |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1105 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1106 MAKE_LISP_OBJECT is what underlies all of these; it defines |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1107 |
428 | 1108 */ |
1109 | |
800 | 1110 #if defined (ERROR_CHECK_TYPES) |
1111 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) | |
428 | 1112 #else |
800 | 1113 # define DECLARE_ERROR_CHECK_TYPES(c_name, structtype) |
428 | 1114 #endif |
1115 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1116 #error MUST STILL SUPPORT THIS::: |
934 | 1117 |
1118 #define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ | |
1119 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) | |
1120 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1121 #error and variations |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1122 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1123 #define DEFINE_INTERNAL_LISP_OBJECT(name,c_name,dumpable,structtype,desc,marker) ... |
934 | 1124 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1125 #define DEFINE_FROB_BLOCK_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1126 DEFINE_FROB_BLOCK_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1127 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1128 #define DEFINE_FROB_BLOCK_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1129 MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof(structtype),0,1,structtype) |
934 | 1130 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1131 #define DEFINE_INTERNAL_LISP_OBJECT(name,c_name,structtype,desc,dumpable,marker) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1132 DEFINE_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,) |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1133 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1134 #define DEFINE_LISP_OBJECT(name,c_name,structtype,desc,dumpable,marker,printer,equal,hash,nuker) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1135 DEFINE_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,) |
934 | 1136 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1137 #define DEFINE_LISP_OBJECT_WITH_PROPS(name,c_name,structtype,dumpable,desc,marker,printer,equal,hash,nuker,getprop,putprop,remprop,plist) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1138 MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype) |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1139 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1140 #define DEFINE_SIZABLE_LISP_OBJECT(name,c_name,structtype,sizer,desc,dumpable,marker,printer,equal,hash,nuker) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1141 DEFINE_SIZABLE_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype) |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1142 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1143 #define DEFINE_SIZABLE_LISP_OBJECT_WITH_PROPS(name,c_name,structtype,sizer,desc,dumpable,marker,printer,equal,hash,nuker,getprop,putprop,remprop,plist) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1144 MAKE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) |
934 | 1145 |
2720 | 1146 #ifdef MC_ALLOC |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1147 #define MAKE_LISP_OBJECT(name,c_name,structtype,sizer,desc,dumpable,marker,printer,equal,hash,nuker,getprop,putprop,remprop,plist,frob_block) \ |
2720 | 1148 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
1149 const struct lrecord_implementation lrecord_##c_name = \ | |
1150 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | |
1151 getprop, putprop, remprop, plist, size, sizer, \ | |
1152 lrecord_type_##c_name } | |
1153 #else /* not MC_ALLOC */ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1154 #define MAKE_LISP_OBJECT(name,c_name,structtype,sizer,desc,dumpable,marker,printer,equal,hash,nuker,getprop,putprop,remprop,plist,frob_block) \ |
1204 | 1155 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
934 | 1156 const struct lrecord_implementation lrecord_##c_name = \ |
1157 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | |
1158 getprop, putprop, remprop, plist, size, sizer, \ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1159 lrecord_type_##c_name, frob_block } |
2720 | 1160 #endif /* not MC_ALLOC */ |
934 | 1161 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1162 #define DEFINE_EXTERNAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,structtype) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1163 DEFINE_EXTERNAL_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype) |
934 | 1164 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1165 #define DEFINE_EXTERNAL_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,structtype) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1166 MAKE_EXTERNAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizeof (structtype),0,0,structtype) |
934 | 1167 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1168 #define DEFINE_EXTERNAL_SIZABLE_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,sizer,structtype) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1169 DEFINE_EXTERNAL_SIZABLE_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype) |
934 | 1170 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1171 #define DEFINE_EXTERNAL_SIZABLE_LISP_OBJECT_WITH_PROPS(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,sizer,structtype) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1172 MAKE_EXTERNAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,0,sizer,0,structtype) |
934 | 1173 |
2720 | 1174 #ifdef MC_ALLOC |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1175 #define MAKE_EXTERNAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ |
2720 | 1176 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
1177 int lrecord_type_##c_name; \ | |
1178 struct lrecord_implementation lrecord_##c_name = \ | |
1179 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | |
1180 getprop, putprop, remprop, plist, size, sizer, \ | |
1181 lrecord_type_last_built_in_type } | |
1182 #else /* not MC_ALLOC */ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1183 #define MAKE_EXTERNAL_LISP_OBJECT(name,c_name,dumpable,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,plist,size,sizer,basic_p,structtype) \ |
1204 | 1184 DECLARE_ERROR_CHECK_TYPES(c_name, structtype) \ |
934 | 1185 int lrecord_type_##c_name; \ |
1186 struct lrecord_implementation lrecord_##c_name = \ | |
1187 { name, dumpable, marker, printer, nuker, equal, hash, desc, \ | |
1188 getprop, putprop, remprop, plist, size, sizer, \ | |
1189 lrecord_type_last_built_in_type, basic_p } | |
2720 | 1190 #endif /* not MC_ALLOC */ |
934 | 1191 |
1676 | 1192 #ifdef USE_KKCC |
1193 extern MODULE_API const struct memory_description *lrecord_memory_descriptions[]; | |
1194 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1195 #define INIT_LISP_OBJECT(type) do { \ |
1676 | 1196 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ |
1197 lrecord_memory_descriptions[lrecord_type_##type] = \ | |
1198 lrecord_implementations_table[lrecord_type_##type]->description; \ | |
1199 } while (0) | |
1200 #else /* not USE_KKCC */ | |
1632 | 1201 extern MODULE_API Lisp_Object (*lrecord_markers[]) (Lisp_Object); |
442 | 1202 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1203 #define INIT_LISP_OBJECT(type) do { \ |
442 | 1204 lrecord_implementations_table[lrecord_type_##type] = &lrecord_##type; \ |
1205 lrecord_markers[lrecord_type_##type] = \ | |
1206 lrecord_implementations_table[lrecord_type_##type]->marker; \ | |
1207 } while (0) | |
1676 | 1208 #endif /* not USE_KKCC */ |
428 | 1209 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1210 #define INIT_EXTERNAL_LISP_OBJECT(type) do { \ |
444 | 1211 lrecord_type_##type = lrecord_type_count++; \ |
1212 lrecord_##type.lrecord_type_index = lrecord_type_##type; \ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1213 INIT_LISP_OBJECT(type); \ |
444 | 1214 } while (0) |
1215 | |
996 | 1216 #ifdef HAVE_SHLIB |
1217 /* Allow undefining types in order to support module unloading. */ | |
1218 | |
1676 | 1219 #ifdef USE_KKCC |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1220 #define UNDEF_LISP_OBJECT(type) do { \ |
1676 | 1221 lrecord_implementations_table[lrecord_type_##type] = NULL; \ |
1222 lrecord_memory_descriptions[lrecord_type_##type] = NULL; \ | |
1223 } while (0) | |
1224 #else /* not USE_KKCC */ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1225 #define UNDEF_LISP_OBJECT(type) do { \ |
996 | 1226 lrecord_implementations_table[lrecord_type_##type] = NULL; \ |
1227 lrecord_markers[lrecord_type_##type] = NULL; \ | |
1228 } while (0) | |
1676 | 1229 #endif /* not USE_KKCC */ |
996 | 1230 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1231 #define UNDEF_EXTERNAL_LISP_OBJECT(type) do { \ |
996 | 1232 if (lrecord_##type.lrecord_type_index == lrecord_type_count - 1) { \ |
1233 /* This is the most recently defined type. Clean up nicely. */ \ | |
1234 lrecord_type_##type = lrecord_type_count--; \ | |
1235 } /* Else we can't help leaving a hole with this implementation. */ \ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1236 UNDEF_LISP_OBJECT(type); \ |
996 | 1237 } while (0) |
1238 | |
1239 #endif /* HAVE_SHLIB */ | |
1240 | |
428 | 1241 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) |
1242 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) | |
1243 | |
1244 #define RECORD_TYPEP(x, ty) \ | |
647 | 1245 (LRECORDP (x) && (XRECORD_LHEADER (x)->type == (unsigned int) (ty))) |
442 | 1246 |
1247 /* Steps to create a new object: | |
1248 | |
1249 1. Declare the struct for your object in a header file somewhere. | |
1250 Remember that it must begin with | |
1251 | |
3017 | 1252 struct LCRECORD_HEADER header; |
442 | 1253 |
793 | 1254 2. Put the "standard junk" (DECLARE_RECORD()/XFOO/etc.) below the |
617 | 1255 struct definition -- see below. |
442 | 1256 |
1257 3. Add this header file to inline.c. | |
1258 | |
1259 4. Create the methods for your object. Note that technically you don't | |
1260 need any, but you will almost always want at least a mark method. | |
1261 | |
1204 | 1262 4. Create the data layout description for your object. See |
1263 toolbar_button_description below; the comment above in `struct lrecord', | |
1264 describing the purpose of the descriptions; and comments elsewhere in | |
1265 this file describing the exact syntax of the description structures. | |
1266 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1267 6. Define your object with DEFINE_LISP_OBJECT() or some |
442 | 1268 variant. |
1269 | |
1204 | 1270 7. Include the header file in the .c file where you defined the object. |
442 | 1271 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1272 8. Put a call to INIT_LISP_OBJECT() for the object in the |
442 | 1273 .c file's syms_of_foo() function. |
1274 | |
1204 | 1275 9. Add a type enum for the object to enum lrecord_type, earlier in this |
442 | 1276 file. |
1277 | |
1204 | 1278 --ben |
1279 | |
442 | 1280 An example: |
428 | 1281 |
442 | 1282 ------------------------------ in toolbar.h ----------------------------- |
1283 | |
1284 struct toolbar_button | |
1285 { | |
3017 | 1286 struct LCRECORD_HEADER header; |
442 | 1287 |
1288 Lisp_Object next; | |
1289 Lisp_Object frame; | |
1290 | |
1291 Lisp_Object up_glyph; | |
1292 Lisp_Object down_glyph; | |
1293 Lisp_Object disabled_glyph; | |
1294 | |
1295 Lisp_Object cap_up_glyph; | |
1296 Lisp_Object cap_down_glyph; | |
1297 Lisp_Object cap_disabled_glyph; | |
1298 | |
1299 Lisp_Object callback; | |
1300 Lisp_Object enabled_p; | |
1301 Lisp_Object help_string; | |
1302 | |
1303 char enabled; | |
1304 char down; | |
1305 char pushright; | |
1306 char blank; | |
1307 | |
1308 int x, y; | |
1309 int width, height; | |
1310 int dirty; | |
1311 int vertical; | |
1312 int border_width; | |
1313 }; | |
428 | 1314 |
617 | 1315 [[ the standard junk: ]] |
1316 | |
442 | 1317 DECLARE_LRECORD (toolbar_button, struct toolbar_button); |
1318 #define XTOOLBAR_BUTTON(x) XRECORD (x, toolbar_button, struct toolbar_button) | |
617 | 1319 #define wrap_toolbar_button(p) wrap_record (p, toolbar_button) |
442 | 1320 #define TOOLBAR_BUTTONP(x) RECORDP (x, toolbar_button) |
1321 #define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button) | |
1322 #define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button) | |
1323 | |
1324 ------------------------------ in toolbar.c ----------------------------- | |
1325 | |
1326 #include "toolbar.h" | |
1327 | |
1328 ... | |
1329 | |
1204 | 1330 static const struct memory_description toolbar_button_description [] = { |
1331 { XD_LISP_OBJECT, offsetof (struct toolbar_button, next) }, | |
1332 { XD_LISP_OBJECT, offsetof (struct toolbar_button, frame) }, | |
1333 { XD_LISP_OBJECT, offsetof (struct toolbar_button, up_glyph) }, | |
1334 { XD_LISP_OBJECT, offsetof (struct toolbar_button, down_glyph) }, | |
1335 { XD_LISP_OBJECT, offsetof (struct toolbar_button, disabled_glyph) }, | |
1336 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_up_glyph) }, | |
1337 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_down_glyph) }, | |
1338 { XD_LISP_OBJECT, offsetof (struct toolbar_button, cap_disabled_glyph) }, | |
1339 { XD_LISP_OBJECT, offsetof (struct toolbar_button, callback) }, | |
1340 { XD_LISP_OBJECT, offsetof (struct toolbar_button, enabled_p) }, | |
1341 { XD_LISP_OBJECT, offsetof (struct toolbar_button, help_string) }, | |
1342 { XD_END } | |
1343 }; | |
1344 | |
442 | 1345 static Lisp_Object |
1346 mark_toolbar_button (Lisp_Object obj) | |
1204 | 1347 \{ |
442 | 1348 struct toolbar_button *data = XTOOLBAR_BUTTON (obj); |
1349 mark_object (data->next); | |
1350 mark_object (data->frame); | |
1351 mark_object (data->up_glyph); | |
1352 mark_object (data->down_glyph); | |
1353 mark_object (data->disabled_glyph); | |
1354 mark_object (data->cap_up_glyph); | |
1355 mark_object (data->cap_down_glyph); | |
1356 mark_object (data->cap_disabled_glyph); | |
1357 mark_object (data->callback); | |
1358 mark_object (data->enabled_p); | |
1359 return data->help_string; | |
1360 } | |
1361 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1362 DEFINE_NONDUMPABLE_LISP_OBJECT ("toolbar-button", toolbar_button, |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1363 mark_toolbar_button, |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1364 external_object_printer, 0, 0, 0, |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1365 toolbar_button_description, |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1366 struct toolbar_button); |
442 | 1367 |
1368 ... | |
1369 | |
1370 void | |
1371 syms_of_toolbar (void) | |
1372 { | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1373 INIT_LISP_OBJECT (toolbar_button); |
442 | 1374 |
1375 ...; | |
1376 } | |
1377 | |
1378 ------------------------------ in inline.c ----------------------------- | |
1379 | |
1380 #ifdef HAVE_TOOLBARS | |
1381 #include "toolbar.h" | |
1382 #endif | |
1383 | |
1384 ------------------------------ in lrecord.h ----------------------------- | |
1385 | |
1386 enum lrecord_type | |
1387 { | |
1388 ... | |
1389 lrecord_type_toolbar_button, | |
1390 ... | |
1391 }; | |
1392 | |
1204 | 1393 |
1394 --ben | |
1395 | |
442 | 1396 */ |
1397 | |
1398 /* | |
1399 | |
1400 Note: Object types defined in external dynamically-loaded modules (not | |
1401 part of the XEmacs main source code) should use DECLARE_EXTERNAL_LRECORD | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1402 and DEFINE_EXTERNAL_LISP_OBJECT rather than DECLARE_LRECORD |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1403 and DEFINE_LISP_OBJECT. The EXTERNAL versions declare and |
3029 | 1404 allocate an enumerator for the type being defined. |
442 | 1405 |
1406 */ | |
1407 | |
428 | 1408 |
800 | 1409 #ifdef ERROR_CHECK_TYPES |
428 | 1410 |
788 | 1411 # define DECLARE_LRECORD(c_name, structtype) \ |
1412 extern const struct lrecord_implementation lrecord_##c_name; \ | |
826 | 1413 DECLARE_INLINE_HEADER ( \ |
1414 structtype * \ | |
2367 | 1415 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
826 | 1416 ) \ |
788 | 1417 { \ |
1418 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1419 return (structtype *) XPNTR (obj); \ | |
1420 } \ | |
428 | 1421 extern Lisp_Object Q##c_name##p |
1422 | |
1632 | 1423 # define DECLARE_MODULE_API_LRECORD(c_name, structtype) \ |
1424 extern MODULE_API const struct lrecord_implementation lrecord_##c_name; \ | |
1425 DECLARE_INLINE_HEADER ( \ | |
1426 structtype * \ | |
2367 | 1427 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
1632 | 1428 ) \ |
1429 { \ | |
1430 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1431 return (structtype *) XPNTR (obj); \ | |
1432 } \ | |
1433 extern MODULE_API Lisp_Object Q##c_name##p | |
1434 | |
788 | 1435 # define DECLARE_EXTERNAL_LRECORD(c_name, structtype) \ |
1436 extern int lrecord_type_##c_name; \ | |
1437 extern struct lrecord_implementation lrecord_##c_name; \ | |
826 | 1438 DECLARE_INLINE_HEADER ( \ |
1439 structtype * \ | |
2367 | 1440 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
826 | 1441 ) \ |
788 | 1442 { \ |
1443 assert_at_line (RECORD_TYPEP (obj, lrecord_type_##c_name), file, line); \ | |
1444 return (structtype *) XPNTR (obj); \ | |
1445 } \ | |
444 | 1446 extern Lisp_Object Q##c_name##p |
442 | 1447 |
788 | 1448 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ |
826 | 1449 DECLARE_INLINE_HEADER ( \ |
1450 structtype * \ | |
2367 | 1451 error_check_##c_name (Lisp_Object obj, const Ascbyte *file, int line) \ |
826 | 1452 ) \ |
788 | 1453 { \ |
1454 assert_at_line (XTYPE (obj) == type_enum, file, line); \ | |
1455 return (structtype *) XPNTR (obj); \ | |
1456 } \ | |
428 | 1457 extern Lisp_Object Q##c_name##p |
1458 | |
788 | 1459 # define XRECORD(x, c_name, structtype) \ |
1460 error_check_##c_name (x, __FILE__, __LINE__) | |
1461 # define XNONRECORD(x, c_name, type_enum, structtype) \ | |
1462 error_check_##c_name (x, __FILE__, __LINE__) | |
428 | 1463 |
826 | 1464 DECLARE_INLINE_HEADER ( |
1465 Lisp_Object | |
2367 | 1466 wrap_record_1 (const void *ptr, enum lrecord_type ty, const Ascbyte *file, |
800 | 1467 int line) |
826 | 1468 ) |
617 | 1469 { |
793 | 1470 Lisp_Object obj = wrap_pointer_1 (ptr); |
1471 | |
788 | 1472 assert_at_line (RECORD_TYPEP (obj, ty), file, line); |
617 | 1473 return obj; |
1474 } | |
1475 | |
788 | 1476 #define wrap_record(ptr, ty) \ |
1477 wrap_record_1 (ptr, lrecord_type_##ty, __FILE__, __LINE__) | |
617 | 1478 |
800 | 1479 #else /* not ERROR_CHECK_TYPES */ |
428 | 1480 |
1481 # define DECLARE_LRECORD(c_name, structtype) \ | |
1482 extern Lisp_Object Q##c_name##p; \ | |
442 | 1483 extern const struct lrecord_implementation lrecord_##c_name |
1638 | 1484 # define DECLARE_MODULE_API_LRECORD(c_name, structtype) \ |
1485 extern MODULE_API Lisp_Object Q##c_name##p; \ | |
1486 extern MODULE_API const struct lrecord_implementation lrecord_##c_name | |
442 | 1487 # define DECLARE_EXTERNAL_LRECORD(c_name, structtype) \ |
1488 extern Lisp_Object Q##c_name##p; \ | |
647 | 1489 extern int lrecord_type_##c_name; \ |
444 | 1490 extern struct lrecord_implementation lrecord_##c_name |
428 | 1491 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ |
1492 extern Lisp_Object Q##c_name##p | |
1493 # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x)) | |
1494 # define XNONRECORD(x, c_name, type_enum, structtype) \ | |
1495 ((structtype *) XPNTR (x)) | |
617 | 1496 /* wrap_pointer_1 is so named as a suggestion not to use it unless you |
1497 know what you're doing. */ | |
1498 #define wrap_record(ptr, ty) wrap_pointer_1 (ptr) | |
428 | 1499 |
800 | 1500 #endif /* not ERROR_CHECK_TYPES */ |
428 | 1501 |
442 | 1502 #define RECORDP(x, c_name) RECORD_TYPEP (x, lrecord_type_##c_name) |
428 | 1503 |
1504 /* Note: we now have two different kinds of type-checking macros. | |
1505 The "old" kind has now been renamed CONCHECK_foo. The reason for | |
1506 this is that the CONCHECK_foo macros signal a continuable error, | |
1507 allowing the user (through debug-on-error) to substitute a different | |
1508 value and return from the signal, which causes the lvalue argument | |
1509 to get changed. Quite a lot of code would crash if that happened, | |
1510 because it did things like | |
1511 | |
1512 foo = XCAR (list); | |
1513 CHECK_STRING (foo); | |
1514 | |
1515 and later on did XSTRING (XCAR (list)), assuming that the type | |
1516 is correct (when it might be wrong, if the user substituted a | |
1517 correct value in the debugger). | |
1518 | |
1519 To get around this, I made all the CHECK_foo macros signal a | |
1520 non-continuable error. Places where a continuable error is OK | |
1521 (generally only when called directly on the argument of a Lisp | |
1522 primitive) should be changed to use CONCHECK(). | |
1523 | |
1524 FSF Emacs does not have this problem because RMS took the cheesy | |
1525 way out and disabled returning from a signal entirely. */ | |
1526 | |
1527 #define CONCHECK_RECORD(x, c_name) do { \ | |
442 | 1528 if (!RECORD_TYPEP (x, lrecord_type_##c_name)) \ |
428 | 1529 x = wrong_type_argument (Q##c_name##p, x); \ |
1530 } while (0) | |
1531 #define CONCHECK_NONRECORD(x, lisp_enum, predicate) do {\ | |
1532 if (XTYPE (x) != lisp_enum) \ | |
1533 x = wrong_type_argument (predicate, x); \ | |
1534 } while (0) | |
1535 #define CHECK_RECORD(x, c_name) do { \ | |
442 | 1536 if (!RECORD_TYPEP (x, lrecord_type_##c_name)) \ |
428 | 1537 dead_wrong_type_argument (Q##c_name##p, x); \ |
1538 } while (0) | |
1539 #define CHECK_NONRECORD(x, lisp_enum, predicate) do { \ | |
1540 if (XTYPE (x) != lisp_enum) \ | |
1541 dead_wrong_type_argument (predicate, x); \ | |
1542 } while (0) | |
1543 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1544 /* How to allocate a Lisp object: |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1545 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1546 - For most objects, simply call ALLOC_LISP_OBJECT (type), where TYPE is |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1547 the name of the type (e.g. toolbar_button). Such objects can be freed |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1548 manually using FREE_LCRECORD. |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1549 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1550 - For objects whose size can vary (and hence which have a |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1551 size_in_bytes_method rather than a static_size), call |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1552 ALLOC_SIZED_LISP_OBJECT (size, type), where TYPE is the |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1553 name of the type. NOTE: You cannot call FREE_LCRECORD() on such |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1554 on object! (At least when not MC_ALLOC) |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1555 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1556 - Basic lrecords (of which there are a limited number, which exist only |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1557 when not MC_ALLOC, and which have special handling in alloc.c) need |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1558 special handling; if you don't understand this, just ignore it. |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1559 |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1560 - Some lrecords, which are used totally internally, use the |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1561 noseeum-* functions for the reason of debugging. |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1562 */ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1563 |
2720 | 1564 #ifndef MC_ALLOC |
1204 | 1565 /*-------------------------- lcrecord-list -----------------------------*/ |
1566 | |
1567 struct lcrecord_list | |
1568 { | |
3024 | 1569 struct LCRECORD_HEADER header; |
1204 | 1570 Lisp_Object free; |
1571 Elemcount size; | |
1572 const struct lrecord_implementation *implementation; | |
1573 }; | |
1574 | |
1575 DECLARE_LRECORD (lcrecord_list, struct lcrecord_list); | |
1576 #define XLCRECORD_LIST(x) XRECORD (x, lcrecord_list, struct lcrecord_list) | |
1577 #define wrap_lcrecord_list(p) wrap_record (p, lcrecord_list) | |
1578 #define LCRECORD_LISTP(x) RECORDP (x, lcrecord_list) | |
1579 /* #define CHECK_LCRECORD_LIST(x) CHECK_RECORD (x, lcrecord_list) | |
1580 Lcrecord lists should never escape to the Lisp level, so | |
1581 functions should not be doing this. */ | |
1582 | |
826 | 1583 /* Various ways of allocating lcrecords. All bytes (except lcrecord |
1204 | 1584 header) are zeroed in returned structure. |
1585 | |
1586 See above for a discussion of the difference between plain lrecords and | |
1587 lrecords. lcrecords themselves are divided into three types: (1) | |
1588 auto-managed, (2) hand-managed, and (3) unmanaged. "Managed" refers to | |
1589 using a special object called an lcrecord-list to keep track of freed | |
3024 | 1590 lcrecords, which can freed with FREE_LCRECORD() or the like and later be |
1204 | 1591 recycled when a new lcrecord is required, rather than requiring new |
1592 malloc(). Thus, allocation of lcrecords can be very | |
1593 cheap. (Technically, the lcrecord-list manager could divide up large | |
1594 chunks of memory and allocate out of that, mimicking what happens with | |
1595 lrecords. At that point, however, we'd want to rethink the whole | |
1596 division between lrecords and lcrecords.) | |
1597 | |
1598 NOTE: There is a fundamental limitation of lcrecord-lists, which is that | |
1599 they only handle blocks of a particular, fixed size. Thus, objects that | |
1600 can be of varying sizes need to do various tricks. These considerations | |
1601 in particular dictate the various types of management: | |
1602 | |
1603 -- "Auto-managed" means that you just go ahead and allocate the lcrecord | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1604 whenever you want, using ALLOC_LISP_OBJECT(), and the appropriate |
1204 | 1605 lcrecord-list manager is automatically created. To free, you just call |
3024 | 1606 "FREE_LCRECORD()" and the appropriate lcrecord-list manager is |
1204 | 1607 automatically located and called. The limitation here of course is that |
1608 all your objects are of the same size. (#### Eventually we should have a | |
1609 more sophisticated system that tracks the sizes seen and creates one | |
1610 lcrecord list per size, indexed in a hash table. Usually there are only | |
1611 a limited number of sizes, so this works well.) | |
826 | 1612 |
1204 | 1613 -- "Hand-managed" exists because we haven't yet written the more |
1614 sophisticated scheme for auto-handling different-sized lcrecords, as | |
1615 described in the end of the last paragraph. In this model, you go ahead | |
1616 and create the lcrecord-list objects yourself for the sizes you will | |
1617 need, using make_lcrecord_list(). Then, create lcrecords using | |
1618 alloc_managed_lcrecord(), passing in the lcrecord-list you created, and | |
1619 free them with free_managed_lcrecord(). | |
1620 | |
1621 -- "Unmanaged" means you simply allocate lcrecords, period. No | |
1622 lcrecord-lists, no way to free them. This may be suitable when the | |
1623 lcrecords are variable-sized and (a) you're too lazy to write the code | |
1624 to hand-manage them, or (b) the objects you create are always or almost | |
1625 always Lisp-visible, and thus there's no point in freeing them (and it | |
1626 wouldn't be safe to do so). You just create them with | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1627 ALLOC_SIZED_LISP_OBJECT(), and that's it. |
1204 | 1628 |
1629 --ben | |
1630 | |
1631 Here is an in-depth look at the steps required to create a allocate an | |
1632 lcrecord using the hand-managed style. Since this is the most | |
1633 complicated, you will learn a lot about the other styles as well. In | |
1634 addition, there is useful general information about what freeing an | |
1635 lcrecord really entails, and what are the precautions: | |
1636 | |
1637 1) Create an lcrecord-list object using make_lcrecord_list(). This is | |
1638 often done at initialization. Remember to staticpro_nodump() this | |
1639 object! The arguments to make_lcrecord_list() are the same as would be | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1640 passed to ALLOC_SIZED_LISP_OBJECT(). |
428 | 1641 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1642 2) Instead of calling ALLOC_SIZED_LISP_OBJECT(), call |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1643 alloc_managed_lcrecord() and pass the lcrecord-list earlier created. |
1204 | 1644 |
1645 3) When done with the lcrecord, call free_managed_lcrecord(). The | |
1646 standard freeing caveats apply: ** make sure there are no pointers to | |
1647 the object anywhere! ** | |
1648 | |
1649 4) Calling free_managed_lcrecord() is just like kissing the | |
1650 lcrecord goodbye as if it were garbage-collected. This means: | |
1651 -- the contents of the freed lcrecord are undefined, and the | |
1652 contents of something produced by alloc_managed_lcrecord() | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1653 are undefined, just like for ALLOC_SIZED_LISP_OBJECT(). |
1204 | 1654 -- the mark method for the lcrecord's type will *NEVER* be called |
1655 on freed lcrecords. | |
1656 -- the finalize method for the lcrecord's type will be called | |
1657 at the time that free_managed_lcrecord() is called. | |
1658 */ | |
1659 | |
1660 /* UNMANAGED MODEL: */ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1661 Lisp_Object old_alloc_lcrecord (const struct lrecord_implementation *); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1662 Lisp_Object old_alloc_sized_lcrecord (Bytecount size, |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1663 const struct lrecord_implementation *); |
1204 | 1664 |
1665 /* HAND-MANAGED MODEL: */ | |
1666 Lisp_Object make_lcrecord_list (Elemcount size, | |
1667 const struct lrecord_implementation | |
1668 *implementation); | |
1669 Lisp_Object alloc_managed_lcrecord (Lisp_Object lcrecord_list); | |
1670 void free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord); | |
1671 | |
1672 /* AUTO-MANAGED MODEL: */ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1673 MODULE_API Lisp_Object |
1632 | 1674 alloc_automanaged_lcrecord (Bytecount size, |
1675 const struct lrecord_implementation *); | |
3017 | 1676 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1677 #define old_alloc_lcrecord_type(type, imp) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1678 ((type *) XPNTR (alloc_automanaged_lcrecord (sizeof (type), imp))) |
2720 | 1679 |
3024 | 1680 void old_free_lcrecord (Lisp_Object rec); |
771 | 1681 |
428 | 1682 |
1683 /* Copy the data from one lcrecord structure into another, but don't | |
1684 overwrite the header information. */ | |
1685 | |
3024 | 1686 #define old_copy_sized_lcrecord(dst, src, size) \ |
1687 memcpy ((Rawbyte *) (dst) + sizeof (struct old_lcrecord_header), \ | |
1688 (Rawbyte *) (src) + sizeof (struct old_lcrecord_header), \ | |
1689 (size) - sizeof (struct old_lcrecord_header)) | |
771 | 1690 |
3024 | 1691 #define old_copy_lcrecord(dst, src) \ |
1692 old_copy_sized_lcrecord (dst, src, sizeof (*(dst))) | |
428 | 1693 |
3024 | 1694 #define old_zero_sized_lcrecord(lcr, size) \ |
1695 memset ((Rawbyte *) (lcr) + sizeof (struct old_lcrecord_header), 0, \ | |
1696 (size) - sizeof (struct old_lcrecord_header)) | |
771 | 1697 |
3024 | 1698 #define old_zero_lcrecord(lcr) old_zero_sized_lcrecord (lcr, sizeof (*(lcr))) |
1204 | 1699 |
2720 | 1700 #else /* MC_ALLOC */ |
1701 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1702 Lisp_Object alloc_sized_lrecord (Bytecount size, |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1703 const struct lrecord_implementation *imp); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1704 Lisp_Object noseeum_alloc_sized_lrecord (Bytecount size, |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1705 const struct lrecord_implementation *); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1706 Lisp_Object alloc_lrecord (const struct lrecord_implementation *imp); |
2720 | 1707 |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1708 #define alloc_lrecord_type(type, imp) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1709 ((type *) XPNTR (alloc_sized_lrecord (sizeof (type), imp))) |
2720 | 1710 |
1711 void *noseeum_alloc_lrecord (Bytecount size, | |
1712 const struct lrecord_implementation *); | |
1713 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1714 #define noseeum_alloc_lrecord_type(type, imp) \ |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3063
diff
changeset
|
1715 ((type *) XPNTR (noseeum_alloc_sized_lrecord (sizeof (type), imp))) |
2720 | 1716 |
1717 void free_lrecord (Lisp_Object rec); | |
1718 | |
1719 | |
1720 /* Copy the data from one lrecord structure into another, but don't | |
1721 overwrite the header information. */ | |
1722 | |
1723 #define copy_sized_lrecord(dst, src, size) \ | |
1724 memcpy ((char *) (dst) + sizeof (struct lrecord_header), \ | |
1725 (char *) (src) + sizeof (struct lrecord_header), \ | |
1726 (size) - sizeof (struct lrecord_header)) | |
1727 | |
1728 #define copy_lrecord(dst, src) copy_sized_lrecord (dst, src, sizeof (*(dst))) | |
1729 | |
3017 | 1730 #endif /* MC_ALLOC */ |
1731 | |
2720 | 1732 #define zero_sized_lrecord(lcr, size) \ |
1733 memset ((char *) (lcr) + sizeof (struct lrecord_header), 0, \ | |
1734 (size) - sizeof (struct lrecord_header)) | |
1735 | |
1736 #define zero_lrecord(lcr) zero_sized_lrecord (lcr, sizeof (*(lcr))) | |
1737 | |
1204 | 1738 DECLARE_INLINE_HEADER ( |
1739 Bytecount | |
1740 detagged_lisp_object_size (const struct lrecord_header *h) | |
1741 ) | |
1742 { | |
1743 const struct lrecord_implementation *imp = LHEADER_IMPLEMENTATION (h); | |
1744 | |
1745 return (imp->size_in_bytes_method ? | |
1746 imp->size_in_bytes_method (h) : | |
1747 imp->static_size); | |
1748 } | |
1749 | |
1750 DECLARE_INLINE_HEADER ( | |
1751 Bytecount | |
1752 lisp_object_size (Lisp_Object o) | |
1753 ) | |
1754 { | |
1755 return detagged_lisp_object_size (XRECORD_LHEADER (o)); | |
1756 } | |
1757 | |
1758 | |
1759 /************************************************************************/ | |
1760 /* Dumping */ | |
1761 /************************************************************************/ | |
1762 | |
2367 | 1763 /* dump_add_root_block_ptr (&var, &desc) dumps the structure pointed to by |
1204 | 1764 `var'. This is for a single relocatable pointer located in the data |
2367 | 1765 segment (i.e. the block pointed to is in the heap). |
1766 | |
1767 If the structure pointed to is not a `struct' but an array, you should | |
1768 set the size field of the sized_memory_description to 0, and use | |
1769 XD_BLOCK_ARRAY in the inner memory_description. | |
1770 | |
1771 NOTE that a "root struct pointer" could also be described using | |
1772 dump_add_root_block(), with SIZE == sizeof (void *), and a description | |
1773 containing a single XD_BLOCK_PTR entry, offset 0, size 1, with a | |
1774 structure description the same as the value passed to | |
1775 dump_add_root_block_ptr(). That would require an extra level of | |
1776 description, though, as compared to using dump_add_root_block_ptr(), | |
1777 and thus this function is generally more convenient. | |
1778 */ | |
1204 | 1779 #ifdef PDUMP |
2367 | 1780 void dump_add_root_block_ptr (void *, const struct sized_memory_description *); |
1204 | 1781 #else |
2367 | 1782 #define dump_add_root_block_ptr(varaddr, descaddr) DO_NOTHING |
1204 | 1783 #endif |
1784 | |
1785 /* dump_add_opaque (&var, size) dumps the opaque static structure `var'. | |
1786 This is for a static block of memory (in the data segment, not the | |
1787 heap), with no relocatable pointers in it. */ | |
1788 #ifdef PDUMP | |
1789 #define dump_add_opaque(varaddr,size) dump_add_root_block (varaddr, size, NULL) | |
1790 #else | |
1791 #define dump_add_opaque(varaddr,size) DO_NOTHING | |
1792 #endif | |
1793 | |
1794 /* dump_add_root_block (ptr, size, desc) dumps the static structure | |
1795 located at `var' of size SIZE and described by DESC. This is for a | |
1796 static block of memory (in the data segment, not the heap), with | |
1797 relocatable pointers in it. */ | |
1798 #ifdef PDUMP | |
1799 void dump_add_root_block (const void *ptraddress, Bytecount size, | |
1800 const struct memory_description *desc); | |
1801 #else | |
2367 | 1802 #define dump_add_root_block(ptraddress, size, desc) DO_NOTHING |
1204 | 1803 #endif |
1804 | |
1805 /* Call dump_add_opaque_int (&int_var) to dump `int_var', of type `int'. */ | |
1806 #ifdef PDUMP | |
1807 #define dump_add_opaque_int(int_varaddr) do { \ | |
1808 int *dao_ = (int_varaddr); /* type check */ \ | |
1809 dump_add_opaque (dao_, sizeof (*dao_)); \ | |
1810 } while (0) | |
1811 #else | |
1812 #define dump_add_opaque_int(int_varaddr) DO_NOTHING | |
1813 #endif | |
1814 | |
1815 /* Call dump_add_opaque_fixnum (&fixnum_var) to dump `fixnum_var', of type | |
1816 `Fixnum'. */ | |
1817 #ifdef PDUMP | |
1818 #define dump_add_opaque_fixnum(fixnum_varaddr) do { \ | |
1819 Fixnum *dao_ = (fixnum_varaddr); /* type check */ \ | |
1820 dump_add_opaque (dao_, sizeof (*dao_)); \ | |
1821 } while (0) | |
1822 #else | |
1823 #define dump_add_opaque_fixnum(fixnum_varaddr) DO_NOTHING | |
1824 #endif | |
1825 | |
1826 /* Call dump_add_root_lisp_object (&var) to ensure that var is properly | |
1827 updated after pdump. */ | |
1828 #ifdef PDUMP | |
1829 void dump_add_root_lisp_object (Lisp_Object *); | |
1830 #else | |
1831 #define dump_add_root_lisp_object(varaddr) DO_NOTHING | |
1832 #endif | |
1833 | |
1834 /* Call dump_add_weak_lisp_object (&var) to ensure that var is properly | |
1835 updated after pdump. var must point to a linked list of objects out of | |
1836 which some may not be dumped */ | |
1837 #ifdef PDUMP | |
1838 void dump_add_weak_object_chain (Lisp_Object *); | |
1839 #else | |
1840 #define dump_add_weak_object_chain(varaddr) DO_NOTHING | |
1841 #endif | |
1842 | |
1843 /* Nonzero means Emacs has already been initialized. | |
1844 Used during startup to detect startup of dumped Emacs. */ | |
1632 | 1845 extern MODULE_API int initialized; |
1204 | 1846 |
1847 #ifdef PDUMP | |
1688 | 1848 #include "dumper.h" |
2720 | 1849 #ifdef MC_ALLOC |
1850 #define DUMPEDP(adr) 0 | |
1851 #else /* not MC_ALLOC */ | |
2367 | 1852 #define DUMPEDP(adr) ((((Rawbyte *) (adr)) < pdump_end) && \ |
1853 (((Rawbyte *) (adr)) >= pdump_start)) | |
2720 | 1854 #endif /* not MC_ALLOC */ |
1204 | 1855 #else |
1856 #define DUMPEDP(adr) 0 | |
1857 #endif | |
1858 | |
1330 | 1859 #define OBJECT_DUMPED_P(obj) DUMPEDP (XPNTR (obj)) |
1860 | |
1204 | 1861 /***********************************************************************/ |
1862 /* data descriptions */ | |
1863 /***********************************************************************/ | |
1864 | |
1865 | |
1866 #if defined (USE_KKCC) || defined (PDUMP) | |
1867 | |
1868 extern int in_pdump; | |
1869 | |
1870 EMACS_INT lispdesc_indirect_count_1 (EMACS_INT code, | |
1871 const struct memory_description *idesc, | |
1872 const void *idata); | |
1873 const struct sized_memory_description *lispdesc_indirect_description_1 | |
1874 (const void *obj, const struct sized_memory_description *sdesc); | |
2367 | 1875 Bytecount lispdesc_block_size_1 (const void *obj, Bytecount size, |
1876 const struct memory_description *desc); | |
1877 | |
1878 DECLARE_INLINE_HEADER ( | |
1879 Bytecount lispdesc_block_size (const void *obj, | |
1880 const struct sized_memory_description *sdesc)) | |
1881 { | |
1882 return lispdesc_block_size_1 (obj, sdesc->size, sdesc->description); | |
1883 } | |
1204 | 1884 |
1885 DECLARE_INLINE_HEADER ( | |
1886 EMACS_INT | |
1887 lispdesc_indirect_count (EMACS_INT code, | |
1888 const struct memory_description *idesc, | |
1889 const void *idata) | |
1890 ) | |
1891 { | |
1892 if (XD_IS_INDIRECT (code)) | |
1893 code = lispdesc_indirect_count_1 (code, idesc, idata); | |
1894 return code; | |
1895 } | |
1896 | |
1897 DECLARE_INLINE_HEADER ( | |
1898 const struct sized_memory_description * | |
1899 lispdesc_indirect_description (const void *obj, | |
1900 const struct sized_memory_description *sdesc) | |
1901 ) | |
1902 { | |
1903 if (sdesc->description) | |
1904 return sdesc; | |
1905 else | |
1906 return lispdesc_indirect_description_1 (obj, sdesc); | |
1907 } | |
1908 | |
1909 | |
1910 /* Do standard XD_UNION processing. DESC1 is an entry in DESC, which | |
1911 describes the entire data structure. Returns NULL (do nothing, nothing | |
1912 matched), or a new value for DESC1. In the latter case, assign to DESC1 | |
1913 in your function and goto union_switcheroo. */ | |
1914 | |
1915 DECLARE_INLINE_HEADER ( | |
1916 const struct memory_description * | |
1917 lispdesc_process_xd_union (const struct memory_description *desc1, | |
1918 const struct memory_description *desc, | |
1919 const void *data) | |
1920 ) | |
1921 { | |
1922 int count = 0; | |
1923 EMACS_INT variant = lispdesc_indirect_count (desc1->data1, desc, | |
1924 data); | |
1925 desc1 = | |
2551 | 1926 lispdesc_indirect_description (data, desc1->data2.descr)->description; |
1204 | 1927 |
1928 for (count = 0; desc1[count].type != XD_END; count++) | |
1929 { | |
1930 if ((desc1[count].flags & XD_FLAG_UNION_DEFAULT_ENTRY) || | |
1931 desc1[count].offset == variant) | |
1932 { | |
1933 return &desc1[count]; | |
1934 } | |
1935 } | |
1936 | |
1937 return NULL; | |
1938 } | |
1939 | |
1940 #endif /* defined (USE_KKCC) || defined (PDUMP) */ | |
428 | 1941 |
1743 | 1942 END_C_DECLS |
1650 | 1943 |
440 | 1944 #endif /* INCLUDED_lrecord_h_ */ |