Contents in latest XEmacs 21.2 at 1999-06-24-19.
[chise/xemacs-chise.git.1] / src / lrecord.h
1 /* The "lrecord" structure (header of a compound lisp object).
2    Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
3    Copyright (C) 1996 Ben Wing.
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
24 #ifndef _XEMACS_LRECORD_H_
25 #define _XEMACS_LRECORD_H_
26
27 /* The "lrecord" type of Lisp object is used for all object types
28    other than a few simple ones.  This allows many types to be
29    implemented but only a few bits required in a Lisp object for
30    type information. (The tradeoff is that each object has its
31    type marked in it, thereby increasing its size.) The first
32    four bytes of all lrecords is either a pointer to a struct
33    lrecord_implementation, which contains methods describing how
34    to process this object, or an index into an array of pointers
35    to struct lrecord_implementations plus some other data bits.
36
37    Lrecords are of two types: straight lrecords, and lcrecords.
38    Straight lrecords are used for those types of objects that have
39    their own allocation routines (typically allocated out of 2K chunks
40    of memory called `frob blocks').  These objects have a `struct
41    lrecord_header' at the top, containing only the bits needed to find
42    the lrecord_implementation for the object.  There are special
43    routines in alloc.c to deal with each such object type.
44
45    Lcrecords are used for less common sorts of objects that don't
46    do their own allocation.  Each such object is malloc()ed
47    individually, and the objects are chained together through
48    a `next' pointer.  Lcrecords have a `struct lcrecord_header'
49    at the top, which contains a `struct lrecord_header' and
50    a `next' pointer, and are allocated using alloc_lcrecord().
51
52    Creating a new lcrecord type is fairly easy; just follow the
53    lead of some existing type (e.g. hash tables).  Note that you
54    do not need to supply all the methods (see below); reasonable
55    defaults are provided for many of them.  Alternatively, if you're
56    just looking for a way of encapsulating data (which possibly
57    could contain Lisp_Objects in it), you may well be able to use
58    the opaque type. */
59
60 struct lrecord_header
61 {
62   /* index into lrecord_implementations_table[] */
63   unsigned type :8;
64   /* 1 if the object is marked during GC. */
65   unsigned mark :1;
66   /* 1 if the object resides in read-only space */
67   unsigned c_readonly : 1;
68   /* 1 if the object is readonly from lisp */
69   unsigned lisp_readonly : 1;
70 };
71
72 struct lrecord_implementation;
73 int lrecord_type_index (CONST struct lrecord_implementation *implementation);
74
75 # define set_lheader_implementation(header,imp) do {    \
76   struct lrecord_header* SLI_header = (header);         \
77   (SLI_header)->type = lrecord_type_index (imp);        \
78   (SLI_header)->mark = 0;                               \
79   (SLI_header)->c_readonly = 0;                         \
80   (SLI_header)->lisp_readonly = 0;                      \
81 } while (0)
82
83 struct lcrecord_header
84 {
85   struct lrecord_header lheader;
86
87   /* The `next' field is normally used to chain all lrecords together
88      so that the GC can find (and free) all of them.
89      `alloc_lcrecord' threads records together.
90
91      The `next' field may be used for other purposes as long as some
92      other mechanism is provided for letting the GC do its work.
93
94      For example, the event and marker object types allocate members
95      out of memory chunks, and are able to find all unmarked members
96      by sweeping through the elements of the list of chunks.  */
97   struct lcrecord_header *next;
98
99   /* The `uid' field is just for debugging/printing convenience.
100      Having this slot doesn't hurt us much spacewise, since an
101      lcrecord already has the above slots plus malloc overhead. */
102   unsigned int uid :31;
103
104   /* The `free' field is a flag that indicates whether this lcrecord
105      is on a "free list".  Free lists are used to minimize the number
106      of calls to malloc() when we're repeatedly allocating and freeing
107      a number of the same sort of lcrecord.  Lcrecords on a free list
108      always get marked in a different fashion, so we can use this flag
109      as a sanity check to make sure that free lists only have freed
110      lcrecords and there are no freed lcrecords elsewhere. */
111   unsigned int free :1;
112 };
113
114 /* Used for lcrecords in an lcrecord-list. */
115 struct free_lcrecord_header
116 {
117   struct lcrecord_header lcheader;
118   Lisp_Object chain;
119 };
120
121 /* see alloc.c for an explanation */
122 Lisp_Object this_one_is_unmarkable (Lisp_Object obj,
123                                     void (*markobj) (Lisp_Object));
124
125 struct lrecord_implementation
126 {
127   CONST char *name;
128   /* This function is called at GC time, to make sure that all Lisp_Objects
129      pointed to by this object get properly marked.  It should call
130      the mark_object function on all Lisp_Objects in the object.  If
131      the return value is non-nil, it should be a Lisp_Object to be
132      marked (don't call the mark_object function explicitly on it,
133      because the GC routines will do this).  Doing it this way reduces
134      recursion, so the object returned should preferably be the one
135      with the deepest level of Lisp_Object pointers.  This function
136      can be NULL, meaning no GC marking is necessary. */
137   Lisp_Object (*marker) (Lisp_Object, void (*mark_object) (Lisp_Object));
138   /* This can be NULL if the object is an lcrecord; the
139      default_object_printer() in print.c will be used. */
140   void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag);
141   /* 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
143      case).  It should perform any necessary cleanup (e.g. freeing
144      malloc()ed memory.  This can be NULL, meaning no special
145      finalization is necessary.
146
147      WARNING: remember that the finalizer is called at dump time even
148      though the object is not being freed. */
149   void (*finalizer) (void *header, int for_disksave);
150   /* This can be NULL, meaning compare objects with EQ(). */
151   int (*equal) (Lisp_Object obj1, Lisp_Object obj2, int depth);
152   /* This can be NULL, meaning use the Lisp_Object itself as the hash;
153      but *only* if the `equal' function is EQ (if two objects are
154      `equal', they *must* hash to the same value or the hashing won't
155      work). */
156   unsigned long (*hash) (Lisp_Object, int);
157
158   /* External data layout description */
159   const struct lrecord_description *description;
160
161   Lisp_Object (*getprop) (Lisp_Object obj, Lisp_Object prop);
162   int (*putprop) (Lisp_Object obj, Lisp_Object prop, Lisp_Object val);
163   int (*remprop) (Lisp_Object obj, Lisp_Object prop);
164   Lisp_Object (*plist) (Lisp_Object obj);
165
166   /* Only one of these is non-0.  If both are 0, it means that this type
167      is not instantiable by alloc_lcrecord(). */
168   size_t static_size;
169   size_t (*size_in_bytes_method) (CONST void *header);
170   /* A unique subtag-code (dynamically) assigned to this datatype. */
171   /* (This is a pointer so the rest of this structure can be read-only.) */
172   int *lrecord_type_index;
173   /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e.
174      one that does not have an lcrecord_header at the front and which
175      is (usually) allocated in frob blocks.  We only use this flag for
176      some consistency checking, and that only when error-checking is
177      enabled. */
178   int basic_p;
179 };
180
181 extern CONST struct lrecord_implementation *lrecord_implementations_table[];
182
183 #define XRECORD_LHEADER_IMPLEMENTATION(obj) \
184    (lrecord_implementations_table[XRECORD_LHEADER (obj)->type])
185 #define LHEADER_IMPLEMENTATION(lh) (lrecord_implementations_table[(lh)->type])
186
187 extern int gc_in_progress;
188
189 #define MARKED_RECORD_P(obj) (gc_in_progress && XRECORD_LHEADER (obj)->mark)
190 #define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark)
191 #define MARK_RECORD_HEADER(lheader)   ((void) ((lheader)->mark = 1))
192 #define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0))
193
194 #define UNMARKABLE_RECORD_HEADER_P(lheader) \
195   (LHEADER_IMPLEMENTATION (lheader)->marker == this_one_is_unmarkable)
196
197 #define C_READONLY_RECORD_HEADER_P(lheader)  ((lheader)->c_readonly)
198 #define LISP_READONLY_RECORD_HEADER_P(lheader)  ((lheader)->lisp_readonly)
199 #define SET_C_READONLY_RECORD_HEADER(lheader) \
200   ((void) ((lheader)->c_readonly = (lheader)->lisp_readonly = 1))
201 #define SET_LISP_READONLY_RECORD_HEADER(lheader) \
202   ((void) ((lheader)->lisp_readonly = 1))
203
204 /* External description stuff
205
206    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
208    structure.  Following values  are parameters, their  presence, type
209    and number is type-dependant.
210
211    The description ends with a "XD_END" record.
212
213    Some example descriptions :
214    static const struct lrecord_description cons_description[] = {
215      { XD_LISP_OBJECT, offsetof(struct Lisp_Cons, car), 2 },
216      { XD_END }
217    };
218
219    Which means "two lisp objects starting at the 'car' element"
220
221   static const struct lrecord_description string_description[] = {
222     { XD_STRING_DATA, offsetof(Lisp_String, data) },
223     { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 },
224     { XD_END }
225   };
226   "A string data pointer at 'data', one lisp object at 'plist'"
227
228   The existing types :
229     XD_LISP_OBJECT
230   Lisp objects.  The third element is the count.  This is also the type to use
231   for pointers to other lrecords.
232
233     XD_STRING_DATA
234   Pointer to string data.
235
236     XD_OPAQUE_PTR
237   Pointer to undumpable data.  Must be NULL when dumping.
238
239     XD_STRUCT_PTR
240   Pointer to described struct.  Parameters are number of structures and
241   struct_description.
242
243     XD_OPAQUE_DATA_PTR
244   Pointer to dumpable opaque data.  Parameter is the size of the data.
245   Pointed data must be relocatable without changes.
246
247     XD_SIZE_T
248   size_t value.  Used for counts.
249
250     XD_INT
251   int value.  Used for counts.
252
253     XD_LONG
254   long value.  Used for counts.
255
256     XD_END
257   Special type indicating the end of the array.
258
259
260   Special macros:
261     XD_INDIRECT(line)
262   Usable where a "count" or "size" is requested.  Gives the value of the element
263   which is at line number 'line' in the description (count starts at zero).
264
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 */
269
270 enum lrecord_description_type {
271   XD_LISP_OBJECT,
272   XD_STRING_DATA,
273   XD_OPAQUE_PTR,
274   XD_STRUCT_PTR,
275   XD_OPAQUE_DATA_PTR,
276   XD_SIZE_T,
277   XD_INT,
278   XD_LONG,
279   XD_END
280 };
281
282 struct lrecord_description {
283   enum lrecord_description_type type;
284   int offset;
285   EMACS_INT data1;
286   const struct struct_description *data2;
287 };
288
289 struct struct_description {
290   size_t size;
291   const struct lrecord_description *description;
292 };
293
294 #define XD_INDIRECT(count) (-1-(count))
295 #define XD_PARENT_INDIRECT(count) (-1000-(count))
296
297 #define XD_DYNARR_DESC(base_type, sub_desc) \
298   { XD_STRUCT_PTR, offsetof(base_type, base), XD_INDIRECT(1), sub_desc }, \
299   { XD_INT,        offsetof(base_type, max) }
300
301 /* Declaring the following structures as const puts them in the
302    text (read-only) segment, which makes debugging inconvenient
303    because this segment is not mapped when processing a core-
304    dump file */
305
306 #ifdef DEBUG_XEMACS
307 #define CONST_IF_NOT_DEBUG
308 #else
309 #define CONST_IF_NOT_DEBUG CONST
310 #endif
311
312 /* DEFINE_LRECORD_IMPLEMENTATION is for objects with constant size.
313    DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION is for objects whose size varies.
314  */
315
316 #if defined (ERROR_CHECK_TYPECHECK)
317 # define DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype)
318 #else
319 # define DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype)
320 #endif
321
322 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \
323 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
324
325 #define DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,structtype) \
326 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizeof(structtype),0,1,structtype)
327
328 #define DEFINE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,structtype) \
329 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,structtype)
330
331 #define DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,structtype) \
332 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizeof (structtype),0,0,structtype)
333
334 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,sizer,structtype) \
335 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,0,0,0,0,sizer,structtype)
336
337 #define DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION_WITH_PROPS(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,sizer,structtype) \
338 MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,0,sizer,0,structtype) \
339
340 #define MAKE_LRECORD_IMPLEMENTATION(name,c_name,marker,printer,nuker,equal,hash,desc,getprop,putprop,remprop,props,size,sizer,basic_p,structtype) \
341 DECLARE_ERROR_CHECK_TYPECHECK(c_name, structtype)                       \
342 static int lrecord_##c_name##_lrecord_type_index;                       \
343 CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name =     \
344   { name, marker, printer, nuker, equal, hash, desc,                    \
345     getprop, putprop, remprop, props, size, sizer,                      \
346     &(lrecord_##c_name##_lrecord_type_index), basic_p }                 \
347
348 #define LRECORDP(a) (XTYPE ((a)) == Lisp_Type_Record)
349 #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a))
350
351 #define RECORD_TYPEP(x, ty) \
352   (LRECORDP (x) && \
353    lrecord_implementations_table[XRECORD_LHEADER (x)->type] == (ty))
354
355 /* NOTE: the DECLARE_LRECORD() must come before the associated
356    DEFINE_LRECORD_*() or you will get compile errors.
357
358    Furthermore, you always need to put the DECLARE_LRECORD() in a header
359    file, and make sure the header file is included in inline.c, even
360    if the type is private to a particular file.  Otherwise, you will
361    get undefined references for the error_check_foo() inline function
362    under GCC. */
363
364 #ifdef ERROR_CHECK_TYPECHECK
365
366 # define DECLARE_LRECORD(c_name, structtype)                    \
367 extern CONST_IF_NOT_DEBUG struct lrecord_implementation         \
368   lrecord_##c_name;                                             \
369 INLINE structtype *error_check_##c_name (Lisp_Object obj);      \
370 INLINE structtype *                                             \
371 error_check_##c_name (Lisp_Object obj)                          \
372 {                                                               \
373   assert (RECORD_TYPEP (obj, &lrecord_##c_name) ||              \
374           MARKED_RECORD_P (obj));                               \
375   return (structtype *) XPNTR (obj);                            \
376 }                                                               \
377 extern Lisp_Object Q##c_name##p
378
379 # define DECLARE_NONRECORD(c_name, type_enum, structtype)       \
380 INLINE structtype *error_check_##c_name (Lisp_Object obj);      \
381 INLINE structtype *                                             \
382 error_check_##c_name (Lisp_Object obj)                          \
383 {                                                               \
384   assert (XGCTYPE (obj) == type_enum);                          \
385   return (structtype *) XPNTR (obj);                            \
386 }                                                               \
387 extern Lisp_Object Q##c_name##p
388
389 # 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)
391
392 # define XSETRECORD(var, p, c_name) do                          \
393 {                                                               \
394   XSETOBJ (var, Lisp_Type_Record, p);                           \
395   assert (RECORD_TYPEP (var, &lrecord_##c_name) ||              \
396           MARKED_RECORD_P (var));                               \
397 } while (0)
398
399 #else /* not ERROR_CHECK_TYPECHECK */
400
401 # define DECLARE_LRECORD(c_name, structtype)                    \
402 extern Lisp_Object Q##c_name##p;                                \
403 extern CONST_IF_NOT_DEBUG struct lrecord_implementation         \
404   lrecord_##c_name
405 # define DECLARE_NONRECORD(c_name, type_enum, structtype)       \
406 extern Lisp_Object Q##c_name##p
407 # define XRECORD(x, c_name, structtype) ((structtype *) XPNTR (x))
408 # define XNONRECORD(x, c_name, type_enum, structtype)           \
409   ((structtype *) XPNTR (x))
410 # define XSETRECORD(var, p, c_name) XSETOBJ (var, Lisp_Type_Record, p)
411
412 #endif /* not ERROR_CHECK_TYPECHECK */
413
414 #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
417 /* Note: we now have two different kinds of type-checking macros.
418    The "old" kind has now been renamed CONCHECK_foo.  The reason for
419    this is that the CONCHECK_foo macros signal a continuable error,
420    allowing the user (through debug-on-error) to substitute a different
421    value and return from the signal, which causes the lvalue argument
422    to get changed.  Quite a lot of code would crash if that happened,
423    because it did things like
424
425    foo = XCAR (list);
426    CHECK_STRING (foo);
427
428    and later on did XSTRING (XCAR (list)), assuming that the type
429    is correct (when it might be wrong, if the user substituted a
430    correct value in the debugger).
431
432    To get around this, I made all the CHECK_foo macros signal a
433    non-continuable error.  Places where a continuable error is OK
434    (generally only when called directly on the argument of a Lisp
435    primitive) should be changed to use CONCHECK().
436
437    FSF Emacs does not have this problem because RMS took the cheesy
438    way out and disabled returning from a signal entirely. */
439
440 #define CONCHECK_RECORD(x, c_name) do {                 \
441  if (!RECORD_TYPEP (x, &lrecord_##c_name))              \
442    x = wrong_type_argument (Q##c_name##p, x);           \
443 }  while (0)
444 #define CONCHECK_NONRECORD(x, lisp_enum, predicate) do {\
445  if (XTYPE (x) != lisp_enum)                            \
446    x = wrong_type_argument (predicate, x);              \
447  } while (0)
448 #define CHECK_RECORD(x, c_name) do {                    \
449  if (!RECORD_TYPEP (x, &lrecord_##c_name))              \
450    dead_wrong_type_argument (Q##c_name##p, x);          \
451  } while (0)
452 #define CHECK_NONRECORD(x, lisp_enum, predicate) do {   \
453  if (XTYPE (x) != lisp_enum)                            \
454    dead_wrong_type_argument (predicate, x);             \
455  } while (0)
456
457 void *alloc_lcrecord (size_t size, CONST struct lrecord_implementation *);
458
459 #define alloc_lcrecord_type(type, lrecord_implementation) \
460   ((type *) alloc_lcrecord (sizeof (type), lrecord_implementation))
461
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
466    overwrite the header information. */
467
468 #define copy_lcrecord(dst, src)                                 \
469   memcpy ((char *) dst + sizeof (struct lcrecord_header),       \
470           (char *) src + sizeof (struct lcrecord_header),       \
471           sizeof (*dst) - sizeof (struct lcrecord_header))
472
473 #define zero_lcrecord(lcr)                                      \
474    memset ((char *) lcr + sizeof (struct lcrecord_header), 0,   \
475            sizeof (*lcr) - sizeof (struct lcrecord_header))
476
477 #endif /* _XEMACS_LRECORD_H_ */