Mercurial > hg > xemacs-beta
comparison src/lrecord.h @ 424:11054d720c21 r21-2-20
Import from CVS: tag r21-2-20
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:26:11 +0200 |
parents | 41dbb7a9d5f2 |
children |
comparison
equal
deleted
inserted
replaced
423:28d9c139be4c | 424:11054d720c21 |
---|---|
117 struct lcrecord_header lcheader; | 117 struct lcrecord_header lcheader; |
118 Lisp_Object chain; | 118 Lisp_Object chain; |
119 }; | 119 }; |
120 | 120 |
121 /* see alloc.c for an explanation */ | 121 /* see alloc.c for an explanation */ |
122 Lisp_Object this_one_is_unmarkable (Lisp_Object obj, | 122 Lisp_Object this_one_is_unmarkable (Lisp_Object obj); |
123 void (*markobj) (Lisp_Object)); | |
124 | 123 |
125 struct lrecord_implementation | 124 struct lrecord_implementation |
126 { | 125 { |
127 CONST char *name; | 126 CONST char *name; |
128 /* This function is called at GC time, to make sure that all Lisp_Objects | 127 /* This function is called at GC time, to make sure that all Lisp_Objects |
132 marked (don't call the mark_object function explicitly on it, | 131 marked (don't call the mark_object function explicitly on it, |
133 because the GC routines will do this). Doing it this way reduces | 132 because the GC routines will do this). Doing it this way reduces |
134 recursion, so the object returned should preferably be the one | 133 recursion, so the object returned should preferably be the one |
135 with the deepest level of Lisp_Object pointers. This function | 134 with the deepest level of Lisp_Object pointers. This function |
136 can be NULL, meaning no GC marking is necessary. */ | 135 can be NULL, meaning no GC marking is necessary. */ |
137 Lisp_Object (*marker) (Lisp_Object, void (*mark_object) (Lisp_Object)); | 136 Lisp_Object (*marker) (Lisp_Object); |
138 /* This can be NULL if the object is an lcrecord; the | 137 /* This can be NULL if the object is an lcrecord; the |
139 default_object_printer() in print.c will be used. */ | 138 default_object_printer() in print.c will be used. */ |
140 void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); | 139 void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); |
141 /* This function is called at GC time when the object is about to | 140 /* This function is called at GC time when the object is about to |
142 be freed, and at dump time (FOR_DISKSAVE will be non-zero in this | 141 be freed, and at dump time (FOR_DISKSAVE will be non-zero in this |
206 A lrecord external description is an array of values. The first | 205 A lrecord external description is an array of values. The first |
207 value of each line is a type, the second the offset in the lrecord | 206 value of each line is a type, the second the offset in the lrecord |
208 structure. Following values are parameters, their presence, type | 207 structure. Following values are parameters, their presence, type |
209 and number is type-dependant. | 208 and number is type-dependant. |
210 | 209 |
211 The description ends with a "XD_END" record. | 210 The description ends with a "XD_END" or "XD_SPECIFIER_END" record. |
212 | 211 |
213 Some example descriptions : | 212 Some example descriptions : |
214 static const struct lrecord_description cons_description[] = { | 213 static const struct lrecord_description cons_description[] = { |
215 { XD_LISP_OBJECT, offsetof(struct Lisp_Cons, car), 2 }, | 214 { XD_LISP_OBJECT, offsetof(struct Lisp_Cons, car), 2 }, |
216 { XD_END } | 215 { XD_END } |
217 }; | 216 }; |
218 | 217 |
219 Which means "two lisp objects starting at the 'car' element" | 218 Which means "two lisp objects starting at the 'car' element" |
220 | 219 |
221 static const struct lrecord_description string_description[] = { | 220 static const struct lrecord_description string_description[] = { |
222 { XD_STRING_DATA, offsetof(Lisp_String, data) }, | 221 { XD_BYTECOUNT, offsetof(Lisp_String, size) }, |
223 { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, | 222 { XD_OPAQUE_DATA_PTR, offsetof(Lisp_String, data), XD_INDIRECT(0, 1) }, |
223 { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, | |
224 { XD_END } | 224 { XD_END } |
225 }; | 225 }; |
226 "A string data pointer at 'data', one lisp object at 'plist'" | 226 "A pointer to string data at 'data', the size of the pointed array being the value |
227 of the size variable plus 1, and one lisp object at 'plist'" | |
227 | 228 |
228 The existing types : | 229 The existing types : |
229 XD_LISP_OBJECT | 230 XD_LISP_OBJECT |
230 Lisp objects. The third element is the count. This is also the type to use | 231 Lisp objects. The third element is the count. This is also the type to use |
231 for pointers to other lrecords. | 232 for pointers to other lrecords. |
232 | 233 |
233 XD_STRING_DATA | 234 XD_LO_RESET_NIL |
234 Pointer to string data. | 235 Lisp objects which will be reset to Qnil when dumping. Useful for cleaning |
235 | 236 up caches. |
237 | |
238 XD_LO_LINK | |
239 Link in a linked list of objects of the same type. | |
240 | |
236 XD_OPAQUE_PTR | 241 XD_OPAQUE_PTR |
237 Pointer to undumpable data. Must be NULL when dumping. | 242 Pointer to undumpable data. Must be NULL when dumping. |
238 | 243 |
239 XD_STRUCT_PTR | 244 XD_STRUCT_PTR |
240 Pointer to described struct. Parameters are number of structures and | 245 Pointer to described struct. Parameters are number of structures and |
242 | 247 |
243 XD_OPAQUE_DATA_PTR | 248 XD_OPAQUE_DATA_PTR |
244 Pointer to dumpable opaque data. Parameter is the size of the data. | 249 Pointer to dumpable opaque data. Parameter is the size of the data. |
245 Pointed data must be relocatable without changes. | 250 Pointed data must be relocatable without changes. |
246 | 251 |
252 XD_C_STRING | |
253 Pointer to a C string. | |
254 | |
255 XD_DOC_STRING | |
256 Pointer to a doc string (C string if positive, opaque value if negative) | |
257 | |
258 XD_INT_RESET | |
259 An integer which will be reset to a given value in the dump file. | |
260 | |
261 | |
247 XD_SIZE_T | 262 XD_SIZE_T |
248 size_t value. Used for counts. | 263 size_t value. Used for counts. |
249 | 264 |
250 XD_INT | 265 XD_INT |
251 int value. Used for counts. | 266 int value. Used for counts. |
252 | 267 |
253 XD_LONG | 268 XD_LONG |
254 long value. Used for counts. | 269 long value. Used for counts. |
255 | 270 |
271 XD_BYTECOUNT | |
272 bytecount value. Used for counts. | |
273 | |
256 XD_END | 274 XD_END |
257 Special type indicating the end of the array. | 275 Special type indicating the end of the array. |
258 | 276 |
277 XD_SPECIFIER_END | |
278 Special type indicating the end of the array for a specifier. Extra | |
279 description is going to be fetched from the specifier methods. | |
280 | |
259 | 281 |
260 Special macros: | 282 Special macros: |
261 XD_INDIRECT(line) | 283 XD_INDIRECT(line, delta) |
262 Usable where a "count" or "size" is requested. Gives the value of the element | 284 Usable where a "count" or "size" is requested. Gives the value of |
263 which is at line number 'line' in the description (count starts at zero). | 285 the element which is at line number 'line' in the description (count |
264 | 286 starts at zero) and adds delta to it. |
265 XD_PARENT_INDIRECT(line) | |
266 Same as XD_INDIRECT but the element number refers to the parent structure. | |
267 Usable only in struct descriptions. | |
268 */ | 287 */ |
269 | 288 |
270 enum lrecord_description_type { | 289 enum lrecord_description_type { |
271 XD_LISP_OBJECT, | 290 XD_LISP_OBJECT, |
272 XD_STRING_DATA, | 291 XD_LO_RESET_NIL, |
292 XD_LO_LINK, | |
273 XD_OPAQUE_PTR, | 293 XD_OPAQUE_PTR, |
274 XD_STRUCT_PTR, | 294 XD_STRUCT_PTR, |
275 XD_OPAQUE_DATA_PTR, | 295 XD_OPAQUE_DATA_PTR, |
296 XD_C_STRING, | |
297 XD_DOC_STRING, | |
298 XD_INT_RESET, | |
276 XD_SIZE_T, | 299 XD_SIZE_T, |
277 XD_INT, | 300 XD_INT, |
278 XD_LONG, | 301 XD_LONG, |
279 XD_END | 302 XD_BYTECOUNT, |
303 XD_END, | |
304 XD_SPECIFIER_END | |
280 }; | 305 }; |
281 | 306 |
282 struct lrecord_description { | 307 struct lrecord_description { |
283 enum lrecord_description_type type; | 308 enum lrecord_description_type type; |
284 int offset; | 309 int offset; |
289 struct struct_description { | 314 struct struct_description { |
290 size_t size; | 315 size_t size; |
291 const struct lrecord_description *description; | 316 const struct lrecord_description *description; |
292 }; | 317 }; |
293 | 318 |
294 #define XD_INDIRECT(count) (-1-(count)) | 319 #define XD_INDIRECT(val, delta) (-1-((val)|(delta<<8))) |
295 #define XD_PARENT_INDIRECT(count) (-1000-(count)) | 320 |
321 #define XD_IS_INDIRECT(code) (code<0) | |
322 #define XD_INDIRECT_VAL(code) ((-1-code) & 255) | |
323 #define XD_INDIRECT_DELTA(code) (((-1-code)>>8) & 255) | |
296 | 324 |
297 #define XD_DYNARR_DESC(base_type, sub_desc) \ | 325 #define XD_DYNARR_DESC(base_type, sub_desc) \ |
298 { XD_STRUCT_PTR, offsetof(base_type, base), XD_INDIRECT(1), sub_desc }, \ | 326 { XD_STRUCT_PTR, offsetof(base_type, base), XD_INDIRECT(1, 0), sub_desc }, \ |
299 { XD_INT, offsetof(base_type, max) } | 327 { XD_INT, offsetof(base_type, cur) }, \ |
328 { XD_INT_RESET, offsetof(base_type, max), XD_INDIRECT(1, 0) } | |
300 | 329 |
301 /* Declaring the following structures as const puts them in the | 330 /* Declaring the following structures as const puts them in the |
302 text (read-only) segment, which makes debugging inconvenient | 331 text (read-only) segment, which makes debugging inconvenient |
303 because this segment is not mapped when processing a core- | 332 because this segment is not mapped when processing a core- |
304 dump file */ | 333 dump file */ |
343 CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name = \ | 372 CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name = \ |
344 { name, marker, printer, nuker, equal, hash, desc, \ | 373 { name, marker, printer, nuker, equal, hash, desc, \ |
345 getprop, putprop, remprop, props, size, sizer, \ | 374 getprop, putprop, remprop, props, size, sizer, \ |
346 &(lrecord_##c_name##_lrecord_type_index), basic_p } \ | 375 &(lrecord_##c_name##_lrecord_type_index), basic_p } \ |
347 | 376 |
348 #define LRECORDP(a) (XTYPE ((a)) == Lisp_Type_Record) | 377 #define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) |
349 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) | 378 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) |
350 | 379 |
351 #define RECORD_TYPEP(x, ty) \ | 380 #define RECORD_TYPEP(x, ty) \ |
352 (LRECORDP (x) && \ | 381 (LRECORDP (x) && \ |
353 lrecord_implementations_table[XRECORD_LHEADER (x)->type] == (ty)) | 382 lrecord_implementations_table[XRECORD_LHEADER (x)->type] == (ty)) |
368 lrecord_##c_name; \ | 397 lrecord_##c_name; \ |
369 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ | 398 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ |
370 INLINE structtype * \ | 399 INLINE structtype * \ |
371 error_check_##c_name (Lisp_Object obj) \ | 400 error_check_##c_name (Lisp_Object obj) \ |
372 { \ | 401 { \ |
373 assert (RECORD_TYPEP (obj, &lrecord_##c_name) || \ | 402 assert (RECORD_TYPEP (obj, &lrecord_##c_name)); \ |
374 MARKED_RECORD_P (obj)); \ | |
375 return (structtype *) XPNTR (obj); \ | 403 return (structtype *) XPNTR (obj); \ |
376 } \ | 404 } \ |
377 extern Lisp_Object Q##c_name##p | 405 extern Lisp_Object Q##c_name##p |
378 | 406 |
379 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ | 407 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ |
380 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ | 408 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ |
381 INLINE structtype * \ | 409 INLINE structtype * \ |
382 error_check_##c_name (Lisp_Object obj) \ | 410 error_check_##c_name (Lisp_Object obj) \ |
383 { \ | 411 { \ |
384 assert (XGCTYPE (obj) == type_enum); \ | 412 assert (XTYPE (obj) == type_enum); \ |
385 return (structtype *) XPNTR (obj); \ | 413 return (structtype *) XPNTR (obj); \ |
386 } \ | 414 } \ |
387 extern Lisp_Object Q##c_name##p | 415 extern Lisp_Object Q##c_name##p |
388 | 416 |
389 # define XRECORD(x, c_name, structtype) error_check_##c_name (x) | 417 # define XRECORD(x, c_name, structtype) error_check_##c_name (x) |
390 # define XNONRECORD(x, c_name, type_enum, structtype) error_check_##c_name (x) | 418 # define XNONRECORD(x, c_name, type_enum, structtype) error_check_##c_name (x) |
391 | 419 |
392 # define XSETRECORD(var, p, c_name) do \ | 420 # define XSETRECORD(var, p, c_name) do \ |
393 { \ | 421 { \ |
394 XSETOBJ (var, Lisp_Type_Record, p); \ | 422 XSETOBJ (var, Lisp_Type_Record, p); \ |
395 assert (RECORD_TYPEP (var, &lrecord_##c_name) || \ | 423 assert (RECORD_TYPEP (var, &lrecord_##c_name)); \ |
396 MARKED_RECORD_P (var)); \ | |
397 } while (0) | 424 } while (0) |
398 | 425 |
399 #else /* not ERROR_CHECK_TYPECHECK */ | 426 #else /* not ERROR_CHECK_TYPECHECK */ |
400 | 427 |
401 # define DECLARE_LRECORD(c_name, structtype) \ | 428 # define DECLARE_LRECORD(c_name, structtype) \ |
410 # define XSETRECORD(var, p, c_name) XSETOBJ (var, Lisp_Type_Record, p) | 437 # define XSETRECORD(var, p, c_name) XSETOBJ (var, Lisp_Type_Record, p) |
411 | 438 |
412 #endif /* not ERROR_CHECK_TYPECHECK */ | 439 #endif /* not ERROR_CHECK_TYPECHECK */ |
413 | 440 |
414 #define RECORDP(x, c_name) RECORD_TYPEP (x, &lrecord_##c_name) | 441 #define RECORDP(x, c_name) RECORD_TYPEP (x, &lrecord_##c_name) |
415 #define GC_RECORDP(x, c_name) gc_record_type_p (x, &lrecord_##c_name) | |
416 | 442 |
417 /* Note: we now have two different kinds of type-checking macros. | 443 /* Note: we now have two different kinds of type-checking macros. |
418 The "old" kind has now been renamed CONCHECK_foo. The reason for | 444 The "old" kind has now been renamed CONCHECK_foo. The reason for |
419 this is that the CONCHECK_foo macros signal a continuable error, | 445 this is that the CONCHECK_foo macros signal a continuable error, |
420 allowing the user (through debug-on-error) to substitute a different | 446 allowing the user (through debug-on-error) to substitute a different |
457 void *alloc_lcrecord (size_t size, CONST struct lrecord_implementation *); | 483 void *alloc_lcrecord (size_t size, CONST struct lrecord_implementation *); |
458 | 484 |
459 #define alloc_lcrecord_type(type, lrecord_implementation) \ | 485 #define alloc_lcrecord_type(type, lrecord_implementation) \ |
460 ((type *) alloc_lcrecord (sizeof (type), lrecord_implementation)) | 486 ((type *) alloc_lcrecord (sizeof (type), lrecord_implementation)) |
461 | 487 |
462 int gc_record_type_p (Lisp_Object frob, | |
463 CONST struct lrecord_implementation *type); | |
464 | |
465 /* Copy the data from one lcrecord structure into another, but don't | 488 /* Copy the data from one lcrecord structure into another, but don't |
466 overwrite the header information. */ | 489 overwrite the header information. */ |
467 | 490 |
468 #define copy_lcrecord(dst, src) \ | 491 #define copy_lcrecord(dst, src) \ |
469 memcpy ((char *) dst + sizeof (struct lcrecord_header), \ | 492 memcpy ((char *) dst + sizeof (struct lcrecord_header), \ |