8613124564c8aca464db7f04be6be4c7e229c54e
[sxemacs] / src / alloc.c
1 /* Storage allocation and gc for SXEmacs Lisp interpreter.
2    Copyright (C) 1985-1998 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4    Copyright (C) 1995, 1996 Ben Wing.
5
6 This file is part of SXEmacs
7
8 SXEmacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 SXEmacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
20
21
22 /* Synched up with: FSF 19.28, Mule 2.0.  Substantially different from
23    FSF. */
24
25 /* Authorship:
26
27    FSF: Original version; a long time ago.
28    Mly: Significantly rewritten to use new 3-bit tags and
29         nicely abstracted object definitions, for 19.8.
30    JWZ: Improved code to keep track of purespace usage and
31         issue nice purespace and GC stats.
32    Ben Wing: Cleaned up frob-block lrecord code, added error-checking
33         and various changes for Mule, for 19.12.
34         Added bit vectors for 19.13.
35         Added lcrecord lists for 19.14.
36    slb: Lots of work on the purification and dump time code.
37         Synched Doug Lea malloc support from Emacs 20.2.
38    og:  Killed the purespace.  Portable dumper (moved to dumper.c)
39 */
40
41 #include <config.h>
42 #include "lisp.h"
43
44 #include "backtrace.h"
45 #include "buffer.h"
46 #include "bytecode.h"
47 #include "chartab.h"
48 #include "ui/device.h"
49 #include "elhash.h"
50 #define INCLUDE_EVENTS_H_PRIVATE_SPHERE
51 #include "events/events.h"
52 #include "extents.h"
53 #include "ui/frame.h"
54 #include "ui/glyphs.h"
55 #include "opaque.h"
56 #include "ui/redisplay.h"
57 #include "specifier.h"
58 #include "sysfile.h"
59 #include "sysdep.h"
60 #include "ui/window.h"
61 #include "ui/console-stream.h"
62
63 #ifdef DOUG_LEA_MALLOC
64 #include <malloc.h>
65 #endif
66
67 #ifdef PDUMP
68 #include "dumper.h"
69 #endif
70
71 #define SXE_DEBUG_GC_GMP(args...)       SXE_DEBUG_GC("[gmp]: " args)
72
73 /* bdwgc */
74 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
75 # undef GC_DEBUG
76 # define GC_DEBUG       1
77 # if defined HAVE_GC_GC_H
78 #  include "gc/gc.h"
79 # elif defined HAVE_GC_H
80 #  include "gc.h"
81 # elif 1
82 /* declare the 3 funs we need */
83 extern void *GC_malloc(size_t);
84 extern void *GC_malloc_atomic(size_t);
85 extern void *GC_malloc_uncollectable(size_t);
86 extern void *GC_malloc_stubborn(size_t);
87 extern void *GC_realloc(void*, size_t);
88 extern char *GC_strdup(const char*);
89 extern void GC_free(void*);
90 # else
91 #  error "I'm very concerned about your BDWGC support"
92 # endif
93 #endif
94
95 /* category subsystem */
96 #include "category.h"
97 #include "dynacat.h"
98 #include "seq.h"
99 #include "dict.h"
100
101 EXFUN(Fgarbage_collect, 0);
102
103 #if 0
104 /* this is _way_ too slow to be part of the standard debug options */
105 #if defined(DEBUG_SXEMACS) && defined(MULE)
106 #define VERIFY_STRING_CHARS_INTEGRITY
107 #endif
108 #endif
109
110 /* Define this to use malloc/free with no freelist for all datatypes,
111    the hope being that some debugging tools may help detect
112    freed memory references */
113 #ifdef USE_DEBUG_MALLOC         /* Taking the above comment at face value -slb */
114 #include <dmalloc.h>
115 #define ALLOC_NO_POOLS
116 #endif
117
118 #ifdef DEBUG_SXEMACS
119 static Fixnum debug_allocation;
120 static Fixnum debug_allocation_backtrace_length;
121 #endif
122
123 #if defined EF_USE_ASYNEQ && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
124 #include "semaphore.h"
125 sxe_mutex_t cons_mutex;
126 #endif  /* EF_USE_ASYNEQ && !BDWGC */
127 #ifdef EF_USE_ASYNEQ
128 #include "events/event-queue.h"
129 #include "events/workers.h"
130 dllist_t workers = NULL;
131 #endif
132
133 /* Number of bytes of consing done since the last gc */
134 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
135 #define INCREMENT_CONS_COUNTER_1(size)
136
137 #else  /* !BDWGC */
138
139 EMACS_INT consing_since_gc;
140 #define INCREMENT_CONS_COUNTER_1(size) (consing_since_gc += (size))
141 #endif  /* BDWGC */
142
143 #ifdef DEBUG_SXEMACS
144 static inline void
145 debug_allocation_backtrace(void)
146 {
147         if (debug_allocation_backtrace_length > 0) {
148                 debug_short_backtrace (debug_allocation_backtrace_length);
149         }
150         return;
151 }
152
153 #define INCREMENT_CONS_COUNTER(foosize, type)                           \
154         do {                                                            \
155                 if (debug_allocation) {                                 \
156                         stderr_out("allocating %s (size %ld)\n",        \
157                                    type, (long)foosize);                \
158                         debug_allocation_backtrace ();                  \
159                 }                                                       \
160                 INCREMENT_CONS_COUNTER_1(foosize);                      \
161         } while (0)
162 #define NOSEEUM_INCREMENT_CONS_COUNTER(foosize, type)                   \
163         do {                                                            \
164                 if (debug_allocation > 1) {                             \
165                         stderr_out("allocating noseeum %s (size %ld)\n", \
166                                    type, (long)foosize);                \
167                         debug_allocation_backtrace ();                  \
168                 }                                                       \
169                 INCREMENT_CONS_COUNTER_1(foosize);                      \
170         } while (0)
171 #else
172 #define INCREMENT_CONS_COUNTER(size, type) INCREMENT_CONS_COUNTER_1 (size)
173 #define NOSEEUM_INCREMENT_CONS_COUNTER(size, type)      \
174         INCREMENT_CONS_COUNTER_1 (size)
175 #endif
176
177 static inline void
178 DECREMENT_CONS_COUNTER(size_t size)
179         __attribute__((always_inline));
180
181 static inline void
182 DECREMENT_CONS_COUNTER(size_t size)
183 {
184         consing_since_gc -= (size);
185         if (consing_since_gc < 0) {
186                 consing_since_gc = 0;
187         }
188 }
189
190 /* Number of bytes of consing since gc before another gc should be done. */
191 EMACS_INT gc_cons_threshold;
192
193 /* Nonzero during gc */
194 int gc_in_progress;
195
196 /* Number of times GC has happened at this level or below.
197  * Level 0 is most volatile, contrary to usual convention.
198  *  (Of course, there's only one level at present) */
199 EMACS_INT gc_generation_number[1];
200
201 /* This is just for use by the printer, to allow things to print uniquely */
202 static int lrecord_uid_counter;
203
204 /* Nonzero when calling certain hooks or doing other things where
205    a GC would be bad */
206 int gc_currently_forbidden;
207
208 /* Hooks. */
209 Lisp_Object Vpre_gc_hook, Qpre_gc_hook;
210 Lisp_Object Vpost_gc_hook, Qpost_gc_hook;
211
212 /* "Garbage collecting" */
213 Lisp_Object Vgc_message;
214 Lisp_Object Vgc_pointer_glyph;
215 static char gc_default_message[] = "Garbage collecting";
216 Lisp_Object Qgarbage_collecting;
217
218 /* Non-zero means we're in the process of doing the dump */
219 int purify_flag;
220
221 #ifdef ERROR_CHECK_TYPECHECK
222
223 Error_behavior ERROR_ME, ERROR_ME_NOT, ERROR_ME_WARN;
224
225 #endif
226
227 int c_readonly(Lisp_Object obj)
228 {
229         return POINTER_TYPE_P(XTYPE(obj)) && C_READONLY(obj);
230 }
231
232 int lisp_readonly(Lisp_Object obj)
233 {
234         return POINTER_TYPE_P(XTYPE(obj)) && LISP_READONLY(obj);
235 }
236 \f
237 /* Maximum amount of C stack to save when a GC happens.  */
238
239 #ifndef MAX_SAVE_STACK
240 #define MAX_SAVE_STACK 0        /* 16000 */
241 #endif
242
243 /* Non-zero means ignore malloc warnings.  Set during initialization.  */
244 int ignore_malloc_warnings;
245 \f
246 static void *breathing_space;
247
248 void release_breathing_space(void)
249 {
250         if (breathing_space) {
251                 void *tmp = breathing_space;
252                 breathing_space = 0;
253                 free(tmp);
254         }
255 }
256
257 /* malloc calls this if it finds we are near exhausting storage */
258 void malloc_warning(const char *str)
259 {
260         if (ignore_malloc_warnings)
261                 return;
262
263         warn_when_safe
264             (Qmemory, Qcritical,
265              "%s\n"
266              "Killing some buffers may delay running out of memory.\n"
267              "However, certainly by the time you receive the 95%% warning,\n"
268              "you should clean up, kill this Emacs, and start a new one.", str);
269 }
270
271 /* Called if malloc returns zero */
272 DOESNT_RETURN memory_full(void)
273 {
274         /* Force a GC next time eval is called.
275            It's better to loop garbage-collecting (we might reclaim enough
276            to win) than to loop beeping and barfing "Memory exhausted"
277          */
278 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
279         /* that's all we can do */
280         GC_gcollect();
281 #else  /* !BDWGC */
282         consing_since_gc = gc_cons_threshold + 1;
283         release_breathing_space();
284 #endif  /* BDWGC */
285
286         /* Flush some histories which might conceivably contain garbalogical
287            inhibitors.  */
288         if (!NILP(Fboundp(Qvalues))) {
289                 Fset(Qvalues, Qnil);
290         }
291         Vcommand_history = Qnil;
292
293         error("Memory exhausted");
294 }
295
296 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
297 /* like malloc and realloc but check for no memory left, and block input. */
298
299 #undef xmalloc
300 void *xmalloc(size_t size)
301 {
302 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
303         /* yes i know this is contradicting because of the outer conditional
304          * but this here and the definition in lisp.h are meant to be
305          * interchangeable */
306         void *val = zmalloc(size);
307 #else  /* !HAVE_BDWGC */
308         void *val = ymalloc(size);
309 #endif  /* HAVE_BDWGC */
310
311         if (!val && (size != 0))
312                 memory_full();
313         return val;
314 }
315
316 #undef xmalloc_atomic
317 void *xmalloc_atomic(size_t size)
318 {
319 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
320         void *val = zmalloc_atomic(size);
321 #else  /* !HAVE_BDWGC */
322         void *val = ymalloc_atomic(size);
323 #endif  /* HAVE_BDWGC */
324
325         if (!val && (size != 0))
326                 memory_full();
327         return val;
328 }
329
330 #undef xcalloc
331 static void *xcalloc(size_t nelem, size_t elsize)
332 {
333 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
334         void *val = zcalloc(nelem, elsize);
335 #else  /* !BDWGC */
336         void *val = ycalloc(nelem, elsize);
337 #endif  /* BDWGC */
338
339         if (!val && (nelem != 0))
340                 memory_full();
341         return val;
342 }
343
344 void *xmalloc_and_zero(size_t size)
345 {
346 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
347         return zmalloc_and_zero(size);
348 #else  /* !BDWGC */
349         return xcalloc(size, 1);
350 #endif  /* BDWGC */
351 }
352
353 #undef xrealloc
354 void *xrealloc(void *block, size_t size)
355 {
356 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
357         void *val = zrealloc(block, size);
358 #else  /* !HAVE_BDWGC */
359         /* We must call malloc explicitly when BLOCK is 0, since some
360            reallocs don't do this.  */
361         void *val = block ? yrealloc(block, size) : ymalloc(size);
362 #endif  /* HAVE_BDWGC */
363
364         if (!val && (size != 0))
365                 memory_full();
366         return val;
367 }
368 #endif  /* !BDWGC */
369
370 #ifdef ERROR_CHECK_GC
371
372 #if SIZEOF_INT == 4
373 typedef unsigned int four_byte_t;
374 #elif SIZEOF_LONG == 4
375 typedef unsigned long four_byte_t;
376 #elif SIZEOF_SHORT == 4
377 typedef unsigned short four_byte_t;
378 #else
379 What kind of strange - ass system are we running on ?
380 #endif
381 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
382 static void deadbeef_memory(void *ptr, size_t size)
383 {
384         four_byte_t *ptr4 = (four_byte_t *) ptr;
385         size_t beefs = size >> 2;
386
387         /* In practice, size will always be a multiple of four.  */
388         while (beefs--)
389                 (*ptr4++) = 0xDEADBEEF;
390 }
391 #endif  /* !BDWGC */
392
393 #else  /* !ERROR_CHECK_GC */
394
395 #define deadbeef_memory(ptr, size)
396
397 #endif  /* !ERROR_CHECK_GC */
398
399 #undef xstrdup
400 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
401 char *xstrdup(const char *str)
402 {
403 #ifdef ERROR_CHECK_MALLOC
404 #if SIZEOF_VOID_P == 4
405         /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an
406            error until much later on for many system mallocs, such as
407            the one that comes with Solaris 2.3.  FMH!! */
408         assert(str != (void *)0xDEADBEEF);
409 #elif SIZEOF_VOID_P == 8
410         assert(str != (void*)0xCAFEBABEDEADBEEF);
411 #endif
412 #endif                          /* ERROR_CHECK_MALLOC */
413         if ( str ) {
414                 int len = strlen(str)+1;        /* for stupid terminating 0 */
415                 
416                 void *val = xmalloc(len);
417                 if (val == 0)
418                         return 0;
419                 return (char*)memcpy(val, str, len);
420         }
421         return 0;
422 }
423 #endif  /* !BDWGC */
424
425 #if !defined HAVE_STRDUP 
426 /* will be a problem I think */
427 char *strdup(const char *s)
428 {
429         return xstrdup(s);
430 }
431 #endif  /* !HAVE_STRDUP */
432
433 \f
434 static inline void*
435 allocate_lisp_storage(size_t size)
436 {
437         return xmalloc(size);
438 }
439
440 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
441 static void
442 lcrec_register_finaliser(struct lcrecord_header *b)
443 {
444         GC_finalization_proc *foo = NULL;
445         void **bar = NULL;
446         auto void lcrec_finaliser();
447
448         auto void lcrec_finaliser(void *obj, void *SXE_UNUSED(data))
449         {
450                 const struct lrecord_implementation *lrimp =
451                         XRECORD_LHEADER_IMPLEMENTATION(obj);
452                 if (LIKELY(lrimp->finalizer != NULL)) {
453                         SXE_DEBUG_GC("running the finaliser on %p :type %d\n",
454                                      obj, 0);
455                         lrimp->finalizer(obj, 0);
456                 }
457                 /* cleanse */
458                 memset(obj, 0, sizeof(struct lcrecord_header));
459                 return;
460         }
461
462         SXE_DEBUG_GC("lcrec-fina %p\n", b);
463         GC_REGISTER_FINALIZER(b, lcrec_finaliser, NULL, foo, bar);
464         return;
465 }
466 #else  /* !BDWGC */
467 static inline void
468 lcrec_register_finaliser(struct lcrecord_header *SXE_UNUSED(b))
469 {
470         return;
471 }
472 #endif  /* HAVE_BDWGC */
473
474 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
475 /* lcrecords are chained together through their "next" field.
476    After doing the mark phase, GC will walk this linked list
477    and free any lcrecord which hasn't been marked. */
478 static struct lcrecord_header *all_lcrecords;
479 #endif  /* !BDWGC */
480
481 #define USE_MLY_UIDS
482 #if defined USE_MLY_UIDS
483 #define lcheader_set_uid(_x)    (_x)->uid = lrecord_uid_counter++
484 #elif defined USE_JWZ_UIDS
485 #define lcheader_set_uid(_x)    (_x)->uid = (long int)&(_x)
486 #endif
487
488 void *alloc_lcrecord(size_t size,
489                      const struct lrecord_implementation *implementation)
490 {
491         struct lcrecord_header *lcheader;
492
493         type_checking_assert
494             ((implementation->static_size == 0 ?
495               implementation->size_in_bytes_method != NULL :
496               implementation->static_size == size)
497              && (!implementation->basic_p)
498              &&
499              (!(implementation->hash == NULL
500                 && implementation->equal != NULL)));
501
502         lock_allocator();
503         lcheader = (struct lcrecord_header *)allocate_lisp_storage(size);
504         lcrec_register_finaliser(lcheader);
505         set_lheader_implementation(&lcheader->lheader, implementation);
506
507         lcheader_set_uid(lcheader);
508         lcheader->free = 0;
509 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
510         lcheader->next = all_lcrecords;
511         all_lcrecords = lcheader;
512         INCREMENT_CONS_COUNTER(size, implementation->name);
513 #endif  /* !BDWGC */
514         unlock_allocator();
515         return lcheader;
516 }
517
518 static void disksave_object_finalization_1(void)
519 {
520 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
521         struct lcrecord_header *header;
522
523         for (header = all_lcrecords; header; header = header->next) {
524                 if (LHEADER_IMPLEMENTATION(&header->lheader)->finalizer &&
525                     !header->free)
526                         LHEADER_IMPLEMENTATION(&header->lheader)->
527                             finalizer(header, 1);
528         }
529 #endif  /* !BDWGC */
530 }
531 \f
532 /************************************************************************/
533 /*                        Debugger support                              */
534 /************************************************************************/
535 /* Give gdb/dbx enough information to decode Lisp Objects.  We make
536    sure certain symbols are always defined, so gdb doesn't complain
537    about expressions in src/.gdbinit.  See src/.gdbinit or src/.dbxrc
538    to see how this is used.  */
539
540 EMACS_UINT dbg_valmask = ((1UL << VALBITS) - 1) << GCBITS;
541 EMACS_UINT dbg_typemask = (1UL << GCTYPEBITS) - 1;
542
543 unsigned char dbg_valbits = VALBITS;
544 unsigned char dbg_gctypebits = GCTYPEBITS;
545
546 /* On some systems, the above definitions will be optimized away by
547    the compiler or linker unless they are referenced in some function. */
548 long dbg_inhibit_dbg_symbol_deletion(void);
549 long dbg_inhibit_dbg_symbol_deletion(void)
550 {
551         return (dbg_valmask + dbg_typemask + dbg_valbits + dbg_gctypebits);
552 }
553
554 /* Macros turned into functions for ease of debugging.
555    Debuggers don't know about macros! */
556 int dbg_eq(Lisp_Object obj1, Lisp_Object obj2);
557 int dbg_eq(Lisp_Object obj1, Lisp_Object obj2)
558 {
559         return EQ(obj1, obj2);
560 }
561 \f
562 /************************************************************************/
563 /*                        Fixed-size type macros                        */
564 /************************************************************************/
565
566 /* For fixed-size types that are commonly used, we malloc() large blocks
567    of memory at a time and subdivide them into chunks of the correct
568    size for an object of that type.  This is more efficient than
569    malloc()ing each object separately because we save on malloc() time
570    and overhead due to the fewer number of malloc()ed blocks, and
571    also because we don't need any extra pointers within each object
572    to keep them threaded together for GC purposes.  For less common
573    (and frequently large-size) types, we use lcrecords, which are
574    malloc()ed individually and chained together through a pointer
575    in the lcrecord header.  lcrecords do not need to be fixed-size
576    (i.e. two objects of the same type need not have the same size;
577    however, the size of a particular object cannot vary dynamically).
578    It is also much easier to create a new lcrecord type because no
579    additional code needs to be added to alloc.c.  Finally, lcrecords
580    may be more efficient when there are only a small number of them.
581
582    The types that are stored in these large blocks (or "frob blocks")
583    are cons, float, compiled-function, symbol, marker, extent, event,
584    and string.
585
586    Note that strings are special in that they are actually stored in
587    two parts: a structure containing information about the string, and
588    the actual data associated with the string.  The former structure
589    (a struct Lisp_String) is a fixed-size structure and is managed the
590    same way as all the other such types.  This structure contains a
591    pointer to the actual string data, which is stored in structures of
592    type struct string_chars_block.  Each string_chars_block consists
593    of a pointer to a struct Lisp_String, followed by the data for that
594    string, followed by another pointer to a Lisp_String, followed by
595    the data for that string, etc.  At GC time, the data in these
596    blocks is compacted by searching sequentially through all the
597    blocks and compressing out any holes created by unmarked strings.
598    Strings that are more than a certain size (bigger than the size of
599    a string_chars_block, although something like half as big might
600    make more sense) are malloc()ed separately and not stored in
601    string_chars_blocks.  Furthermore, no one string stretches across
602    two string_chars_blocks.
603
604    Vectors are each malloc()ed separately, similar to lcrecords.
605
606    In the following discussion, we use conses, but it applies equally
607    well to the other fixed-size types.
608
609    We store cons cells inside of cons_blocks, allocating a new
610    cons_block with malloc() whenever necessary.  Cons cells reclaimed
611    by GC are put on a free list to be reallocated before allocating
612    any new cons cells from the latest cons_block.  Each cons_block is
613    just under 2^n - MALLOC_OVERHEAD bytes long, since malloc (at least
614    the versions in malloc.c and gmalloc.c) really allocates in units
615    of powers of two and uses 4 bytes for its own overhead.
616
617    What GC actually does is to search through all the cons_blocks,
618    from the most recently allocated to the oldest, and put all
619    cons cells that are not marked (whether or not they're already
620    free) on a cons_free_list.  The cons_free_list is a stack, and
621    so the cons cells in the oldest-allocated cons_block end up
622    at the head of the stack and are the first to be reallocated.
623    If any cons_block is entirely free, it is freed with free()
624    and its cons cells removed from the cons_free_list.  Because
625    the cons_free_list ends up basically in memory order, we have
626    a high locality of reference (assuming a reasonable turnover
627    of allocating and freeing) and have a reasonable probability
628    of entirely freeing up cons_blocks that have been more recently
629    allocated.  This stage is called the "sweep stage" of GC, and
630    is executed after the "mark stage", which involves starting
631    from all places that are known to point to in-use Lisp objects
632    (e.g. the obarray, where are all symbols are stored; the
633    current catches and condition-cases; the backtrace list of
634    currently executing functions; the gcpro list; etc.) and
635    recursively marking all objects that are accessible.
636
637    At the beginning of the sweep stage, the conses in the cons blocks
638    are in one of three states: in use and marked, in use but not
639    marked, and not in use (already freed).  Any conses that are marked
640    have been marked in the mark stage just executed, because as part
641    of the sweep stage we unmark any marked objects.  The way we tell
642    whether or not a cons cell is in use is through the LRECORD_FREE_P
643    macro.  This uses a special lrecord type `lrecord_type_free',
644    which is never associated with any valid object.
645
646    Conses on the free_cons_list are threaded through a pointer stored
647    in the conses themselves.  Because the cons is still in a
648    cons_block and needs to remain marked as not in use for the next
649    time that GC happens, we need room to store both the "free"
650    indicator and the chaining pointer.  So this pointer is stored
651    after the lrecord header (actually where C places a pointer after
652    the lrecord header; they are not necessarily contiguous).  This
653    implies that all fixed-size types must be big enough to contain at
654    least one pointer.  This is true for all current fixed-size types,
655    with the possible exception of Lisp_Floats, for which we define the
656    meat of the struct using a union of a pointer and a double to
657    ensure adequate space for the free list chain pointer.
658
659    Some types of objects need additional "finalization" done
660    when an object is converted from in use to not in use;
661    this is the purpose of the ADDITIONAL_FREE_type macro.
662    For example, markers need to be removed from the chain
663    of markers that is kept in each buffer.  This is because
664    markers in a buffer automatically disappear if the marker
665    is no longer referenced anywhere (the same does not
666    apply to extents, however).
667
668    WARNING: Things are in an extremely bizarre state when
669    the ADDITIONAL_FREE_type macros are called, so beware!
670
671    When ERROR_CHECK_GC is defined, we do things differently so as to
672    maximize our chances of catching places where there is insufficient
673    GCPROing.  The thing we want to avoid is having an object that
674    we're using but didn't GCPRO get freed by GC and then reallocated
675    while we're in the process of using it -- this will result in
676    something seemingly unrelated getting trashed, and is extremely
677    difficult to track down.  If the object gets freed but not
678    reallocated, we can usually catch this because we set most of the
679    bytes of a freed object to 0xDEADBEEF. (The lisp object type is set
680    to the invalid type `lrecord_type_free', however, and a pointer
681    used to chain freed objects together is stored after the lrecord
682    header; we play some tricks with this pointer to make it more
683    bogus, so crashes are more likely to occur right away.)
684
685    We want freed objects to stay free as long as possible,
686    so instead of doing what we do above, we maintain the
687    free objects in a first-in first-out queue.  We also
688    don't recompute the free list each GC, unlike above;
689    this ensures that the queue ordering is preserved.
690    [This means that we are likely to have worse locality
691    of reference, and that we can never free a frob block
692    once it's allocated. (Even if we know that all cells
693    in it are free, there's no easy way to remove all those
694    cells from the free list because the objects on the
695    free list are unlikely to be in memory order.)]
696    Furthermore, we never take objects off the free list
697    unless there's a large number (usually 1000, but
698    varies depending on type) of them already on the list.
699    This way, we ensure that an object that gets freed will
700    remain free for the next 1000 (or whatever) times that
701    an object of that type is allocated.  */
702
703 #ifndef MALLOC_OVERHEAD
704 #ifdef GNU_MALLOC
705 #define MALLOC_OVERHEAD 0
706 #elif defined (rcheck)
707 #define MALLOC_OVERHEAD 20
708 #else
709 #define MALLOC_OVERHEAD 8
710 #endif
711 #endif  /* MALLOC_OVERHEAD */
712
713 #if !defined(HAVE_MMAP) || defined(DOUG_LEA_MALLOC)
714 /* If we released our reserve (due to running out of memory),
715    and we have a fair amount free once again,
716    try to set aside another reserve in case we run out once more.
717
718    This is called when a relocatable block is freed in ralloc.c.  */
719 void refill_memory_reserve(void);
720 void refill_memory_reserve(void)
721 {
722         if (breathing_space == 0)
723                 breathing_space = (char *)malloc(4096 - MALLOC_OVERHEAD);
724 }
725 #endif  /* !HAVE_MMAP || DOUG_LEA_MALLOC */
726
727 #ifdef ALLOC_NO_POOLS
728 # define TYPE_ALLOC_SIZE(type, structtype) 1
729 #else
730 # define TYPE_ALLOC_SIZE(type, structtype)                      \
731     ((2048 - MALLOC_OVERHEAD - sizeof (struct type##_block *))  \
732      / sizeof (structtype))
733 #endif                          /* ALLOC_NO_POOLS */
734
735 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
736 #define DECLARE_FIXED_TYPE_ALLOC(type, structtype)      \
737         static inline void                              \
738         init_##type##_alloc(void)                       \
739         {                                               \
740                 return;                                 \
741         }
742 #else  /* !BDWGC */
743 #define DECLARE_FIXED_TYPE_ALLOC(type, structtype)              \
744                                                                 \
745 struct type##_block                                             \
746 {                                                               \
747         struct type##_block *prev;                              \
748         structtype block[TYPE_ALLOC_SIZE (type, structtype)];   \
749 };                                                              \
750                                                                 \
751 static struct type##_block *current_##type##_block;             \
752 static int current_##type##_block_index;                        \
753                                                                 \
754 static Lisp_Free *type##_free_list;                             \
755 static Lisp_Free *type##_free_list_tail;                        \
756                                                                 \
757 static void                                                     \
758 init_##type##_alloc (void)                                      \
759 {                                                               \
760         current_##type##_block = 0;                             \
761         current_##type##_block_index =                          \
762                 countof (current_##type##_block->block);        \
763         type##_free_list = 0;                                   \
764         type##_free_list_tail = 0;                              \
765 }                                                               \
766                                                                 \
767 static int gc_count_num_##type##_in_use;                        \
768 static int gc_count_num_##type##_freelist
769 #endif  /* HAVE_BDWGC */
770
771 /* no need for a case distinction, shouldn't be called in bdwgc mode */
772 #define ALLOCATE_FIXED_TYPE_FROM_BLOCK(type, result)                    \
773         do {                                                            \
774                 if (current_##type##_block_index                        \
775                     == countof (current_##type##_block->block)) {       \
776                         struct type##_block *AFTFB_new =                \
777                                 (struct type##_block *)                 \
778                                 allocate_lisp_storage(                  \
779                                         sizeof (struct type##_block));  \
780                         AFTFB_new->prev = current_##type##_block;       \
781                         current_##type##_block = AFTFB_new;             \
782                         current_##type##_block_index = 0;               \
783                 }                                                       \
784                 (result) = &(current_##type##_block                     \
785                              ->block[current_##type##_block_index++]);  \
786         } while (0)
787
788 /* Allocate an instance of a type that is stored in blocks.
789    TYPE is the "name" of the type, STRUCTTYPE is the corresponding
790    structure type. */
791
792 #ifdef ERROR_CHECK_GC
793
794 /* Note: if you get crashes in this function, suspect incorrect calls
795    to free_cons() and friends.  This happened once because the cons
796    cell was not GC-protected and was getting collected before
797    free_cons() was called. */
798
799 /* no need for a case distinction, shouldn't be called in bdwgc mode */
800 #define ALLOCATE_FIXED_TYPE_1(type, structtype, result)                 \
801         do {                                                            \
802                 lock_allocator();                                       \
803                 if (gc_count_num_##type##_freelist >                    \
804                     MINIMUM_ALLOWED_FIXED_TYPE_CELLS_##type) {          \
805                         result = (structtype *) type##_free_list;       \
806                         /* Before actually using the chain pointer,     \
807                            we complement all its bits;                  \
808                            see FREE_FIXED_TYPE(). */                    \
809                         type##_free_list = (Lisp_Free *)                \
810                                 (~ (EMACS_UINT)                         \
811                                  (type##_free_list->chain));            \
812                         gc_count_num_##type##_freelist--;               \
813                 } else {                                                \
814                         ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result);  \
815                 }                                                       \
816                 MARK_LRECORD_AS_NOT_FREE (result);                      \
817                 unlock_allocator();                                     \
818         } while (0)
819
820 #else  /* !ERROR_CHECK_GC */
821
822 /* no need for a case distinction, shouldn't be called in bdwgc mode */
823 #define ALLOCATE_FIXED_TYPE_1(type, structtype, result)                 \
824         do {                                                            \
825                 if (type##_free_list) {                                 \
826                         result = (structtype *) type##_free_list;       \
827                         type##_free_list = type##_free_list->chain;     \
828                 } else {                                                \
829                         ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result);  \
830                 }                                                       \
831                 MARK_LRECORD_AS_NOT_FREE (result);                      \
832         } while (0)
833 #endif  /* !ERROR_CHECK_GC */
834
835 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
836
837 #define ALLOCATE_FIXED_TYPE(type, structtype, result)                   \
838         do {                                                            \
839                 result = xnew(structtype);                              \
840                 assert(result != NULL);                                 \
841                 INCREMENT_CONS_COUNTER(sizeof(structtype), #type);      \
842         } while (0)
843 #define ALLOCATE_ATOMIC_FIXED_TYPE(type, structtype, result)            \
844         do {                                                            \
845                 result = xnew_atomic(structtype);                       \
846                 assert(result != NULL);                                 \
847                 INCREMENT_CONS_COUNTER(sizeof(structtype), #type);      \
848         } while (0)
849
850 #else  /* !BDWGC */
851
852 #define ALLOCATE_FIXED_TYPE(type, structtype, result)                   \
853         do {                                                            \
854                 ALLOCATE_FIXED_TYPE_1 (type, structtype, result);       \
855                 INCREMENT_CONS_COUNTER (sizeof (structtype), #type);    \
856         } while (0)
857 #define ALLOCATE_ATOMIC_FIXED_TYPE      ALLOCATE_FIXED_TYPE
858
859 #endif  /* BDWGC */
860
861 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
862 #define NOSEEUM_ALLOCATE_FIXED_TYPE(type, structtype, result)           \
863         (result) = xnew(structtype)
864 #else  /* !BDWGC */
865 #define NOSEEUM_ALLOCATE_FIXED_TYPE(type, structtype, result)           \
866         do {                                                            \
867                 ALLOCATE_FIXED_TYPE_1 (type, structtype, result);       \
868                 NOSEEUM_INCREMENT_CONS_COUNTER(sizeof (structtype), #type); \
869         } while (0)
870 #endif  /* BDWGC */
871
872 /* Lisp_Free is the type to represent a free list member inside a frob
873    block of any lisp object type.  */
874 typedef struct Lisp_Free {
875         struct lrecord_header lheader;
876         struct Lisp_Free *chain;
877 } Lisp_Free;
878
879 #define LRECORD_FREE_P(ptr) \
880 ((ptr)->lheader.type == lrecord_type_free)
881
882 #define MARK_LRECORD_AS_FREE(ptr) \
883 ((void) ((ptr)->lheader.type = lrecord_type_free))
884
885 #ifdef ERROR_CHECK_GC
886 #define MARK_LRECORD_AS_NOT_FREE(ptr) \
887 ((void) ((ptr)->lheader.type = lrecord_type_undefined))
888 #else
889 #define MARK_LRECORD_AS_NOT_FREE(ptr) DO_NOTHING
890 #endif
891
892 #ifdef ERROR_CHECK_GC
893
894 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr)              \
895         do {                                                            \
896                 if (type##_free_list_tail) {                            \
897                         /* When we store the chain pointer, we          \
898                            complement all its bits; this should         \
899                            significantly increase its bogosity in case  \
900                            someone tries to use the value, and          \
901                            should make us crash faster if someone       \
902                            overwrites the pointer because when it gets  \
903                            un-complemented in ALLOCATED_FIXED_TYPE(),   \
904                            the resulting pointer will be extremely      \
905                            bogus. */                                    \
906                         type##_free_list_tail->chain =                  \
907                                 (Lisp_Free *) ~ (EMACS_UINT) (ptr);     \
908                 } else {                                                \
909                         type##_free_list = (Lisp_Free *) (ptr);         \
910                 }                                                       \
911                 type##_free_list_tail = (Lisp_Free *) (ptr);            \
912         } while (0)
913
914 #else  /* !ERROR_CHECK_GC */
915
916 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr)              \
917         do {                                                            \
918                 ((Lisp_Free *) (ptr))->chain = type##_free_list;        \
919                 type##_free_list = (Lisp_Free *) (ptr);                 \
920         } while (0)                                                     \
921
922 #endif                          /* !ERROR_CHECK_GC */
923
924 /* TYPE and STRUCTTYPE are the same as in ALLOCATE_FIXED_TYPE(). */
925
926 #define FREE_FIXED_TYPE(type, structtype, ptr)                          \
927         do {                                                            \
928                 structtype *FFT_ptr = (ptr);                            \
929                 ADDITIONAL_FREE_##type (FFT_ptr);                       \
930                 deadbeef_memory (FFT_ptr, sizeof (structtype));         \
931                 PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, FFT_ptr); \
932                 MARK_LRECORD_AS_FREE (FFT_ptr);                         \
933         } while (0)
934
935 /* Like FREE_FIXED_TYPE() but used when we are explicitly
936    freeing a structure through free_cons(), free_marker(), etc.
937    rather than through the normal process of sweeping.
938    We attempt to undo the changes made to the allocation counters
939    as a result of this structure being allocated.  This is not
940    completely necessary but helps keep things saner: e.g. this way,
941    repeatedly allocating and freeing a cons will not result in
942    the consing-since-gc counter advancing, which would cause a GC
943    and somewhat defeat the purpose of explicitly freeing. */
944
945 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
946 #define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr)
947 #else  /* !HAVE_BDWGC */
948 #define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr)   \
949         do {                                                    \
950                 FREE_FIXED_TYPE (type, structtype, ptr);        \
951                 DECREMENT_CONS_COUNTER (sizeof (structtype));   \
952                 gc_count_num_##type##_freelist++;               \
953         } while (0)
954 #endif  /* HAVE_BDWGC */
955 \f
956 /************************************************************************/
957 /*                         Cons allocation                              */
958 /************************************************************************/
959
960 DECLARE_FIXED_TYPE_ALLOC(cons, Lisp_Cons);
961 /* conses are used and freed so often that we set this really high */
962 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */
963 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000
964
965 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
966 static void
967 cons_register_finaliser(Lisp_Cons *s)
968 {
969         GC_finalization_proc *foo = NULL;
970         void **bar = NULL;
971         auto void cons_finaliser();
972
973         auto void cons_finaliser(void *obj, void *SXE_UNUSED(data))
974         {
975                 /* cleanse */
976                 memset(obj, 0, sizeof(Lisp_Cons));
977                 return;
978         }
979
980         SXE_DEBUG_GC("cons-fina %p\n", s);
981         GC_REGISTER_FINALIZER(s, cons_finaliser, NULL, foo, bar);
982         return;
983 }
984 #else  /* !BDWGC */
985 static inline void
986 cons_register_finaliser(Lisp_Cons *SXE_UNUSED(b))
987 {
988         return;
989 }
990 #endif  /* HAVE_BDWGC */
991
992 static Lisp_Object mark_cons(Lisp_Object obj)
993 {
994         if (NILP(XCDR(obj)))
995                 return XCAR(obj);
996
997         mark_object(XCAR(obj));
998         return XCDR(obj);
999 }
1000
1001 static int cons_equal(Lisp_Object ob1, Lisp_Object ob2, int depth)
1002 {
1003         depth++;
1004         while (internal_equal(XCAR(ob1), XCAR(ob2), depth)) {
1005                 ob1 = XCDR(ob1);
1006                 ob2 = XCDR(ob2);
1007                 if (!CONSP(ob1) || !CONSP(ob2))
1008                         return internal_equal(ob1, ob2, depth);
1009         }
1010         return 0;
1011 }
1012
1013 /* the seq approach for conses */
1014 static size_t
1015 cons_length(const seq_t cons)
1016 {
1017         size_t len;
1018         GET_EXTERNAL_LIST_LENGTH((Lisp_Object)cons, len);
1019         return len;
1020 }
1021
1022 static void
1023 cons_iter_init(seq_t cons, seq_iter_t si)
1024 {
1025         si->data = si->seq = cons;
1026         return;
1027 }
1028
1029 static void
1030 cons_iter_next(seq_iter_t si, void **elt)
1031 {
1032         if (si->data != NULL && CONSP(si->data)) {
1033                 *elt = (void*)((Lisp_Cons*)si->data)->car;
1034                 si->data = (void*)((Lisp_Cons*)si->data)->cdr;
1035         } else {
1036                 *elt = NULL;
1037         }
1038         return;
1039 }
1040
1041 static void
1042 cons_iter_fini(seq_iter_t si)
1043 {
1044         si->data = si->seq = NULL;
1045         return;
1046 }
1047
1048 static void
1049 cons_iter_reset(seq_iter_t si)
1050 {
1051         si->data = si->seq;
1052         return;
1053 }
1054
1055 static size_t
1056 cons_explode(void *restrict tgt[], size_t ntgt, const seq_t s)
1057 {
1058         volatile size_t i = 0;
1059         volatile Lisp_Object c = (Lisp_Object)s;
1060
1061         while (CONSP(c) && i < ntgt) {
1062                 tgt[i++] = (void*)XCAR(c);
1063                 c = XCDR(c);
1064         }
1065         return i;
1066 }
1067
1068 static struct seq_impl_s __scons = {
1069         .length_f = cons_length,
1070         .iter_init_f = cons_iter_init,
1071         .iter_next_f = cons_iter_next,
1072         .iter_fini_f = cons_iter_fini,
1073         .iter_reset_f = cons_iter_reset,
1074         .explode_f = cons_explode,
1075 };
1076
1077 static const struct lrecord_description cons_description[] = {
1078         {XD_LISP_OBJECT, offsetof(Lisp_Cons, car)},
1079         {XD_LISP_OBJECT, offsetof(Lisp_Cons, cdr)},
1080         {XD_END}
1081 };
1082
1083 DEFINE_BASIC_LRECORD_IMPLEMENTATION("cons", cons,
1084                                     mark_cons, print_cons, 0, cons_equal,
1085                                     /*
1086                                      * No `hash' method needed.
1087                                      * internal_hash knows how to
1088                                      * handle conses.
1089                                      */
1090                                     0, cons_description, Lisp_Cons);
1091
1092 DEFUN("cons", Fcons, 2, 2, 0,   /*
1093 Create a new cons, give it CAR and CDR as components, and return it.
1094
1095 A cons cell is a Lisp object (an area in memory) made up of two pointers
1096 called the CAR and the CDR.  Each of these pointers can point to any other
1097 Lisp object.  The common Lisp data type, the list, is a specially-structured
1098 series of cons cells.
1099
1100 The pointers are accessed from Lisp with `car' and `cdr', and mutated with
1101 `setcar' and `setcdr' respectively.  For historical reasons, the aliases
1102 `rplaca' and `rplacd' (for `setcar' and `setcdr') are supported.
1103 */
1104       (car, cdr))
1105 {
1106         /* This cannot GC. */
1107         Lisp_Object val;
1108         Lisp_Cons *c;
1109
1110         ALLOCATE_FIXED_TYPE(cons, Lisp_Cons, c);
1111         set_lheader_implementation(&c->lheader, &lrecord_cons);
1112         cons_register_finaliser(c);
1113         XSETCONS(val, c);
1114         c->car = car;
1115         c->cdr = cdr;
1116         /* propagate the cat system, go with the standard impl of a seq first */
1117         c->lheader.morphisms = 0;
1118         return val;
1119 }
1120
1121 /* This is identical to Fcons() but it used for conses that we're
1122    going to free later, and is useful when trying to track down
1123    "real" consing. */
1124 Lisp_Object noseeum_cons(Lisp_Object car, Lisp_Object cdr)
1125 {
1126         Lisp_Object val;
1127         Lisp_Cons *c;
1128
1129         NOSEEUM_ALLOCATE_FIXED_TYPE(cons, Lisp_Cons, c);
1130         set_lheader_implementation(&c->lheader, &lrecord_cons);
1131         XSETCONS(val, c);
1132         XCAR(val) = car;
1133         XCDR(val) = cdr;
1134         /* propagate the cat system, go with the standard impl of a seq first */
1135         c->lheader.morphisms = 0;
1136         return val;
1137 }
1138
1139 DEFUN("list", Flist, 0, MANY, 0,        /*
1140 Return a newly created list with specified arguments as elements.
1141 Any number of arguments, even zero arguments, are allowed.
1142 */
1143       (int nargs, Lisp_Object * args))
1144 {
1145         Lisp_Object val = Qnil;
1146         Lisp_Object *argp = args + nargs;
1147
1148         while (argp > args)
1149                 val = Fcons(*--argp, val);
1150         return val;
1151 }
1152
1153 Lisp_Object list1(Lisp_Object obj0)
1154 {
1155         /* This cannot GC. */
1156         return Fcons(obj0, Qnil);
1157 }
1158
1159 Lisp_Object list2(Lisp_Object obj0, Lisp_Object obj1)
1160 {
1161         /* This cannot GC. */
1162         return Fcons(obj0, Fcons(obj1, Qnil));
1163 }
1164
1165 Lisp_Object list3(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2)
1166 {
1167         /* This cannot GC. */
1168         return Fcons(obj0, Fcons(obj1, Fcons(obj2, Qnil)));
1169 }
1170
1171 Lisp_Object cons3(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2)
1172 {
1173         /* This cannot GC. */
1174         return Fcons(obj0, Fcons(obj1, obj2));
1175 }
1176
1177 Lisp_Object acons(Lisp_Object key, Lisp_Object value, Lisp_Object alist)
1178 {
1179         return Fcons(Fcons(key, value), alist);
1180 }
1181
1182 Lisp_Object
1183 list4(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2, Lisp_Object obj3)
1184 {
1185         /* This cannot GC. */
1186         return Fcons(obj0, Fcons(obj1, Fcons(obj2, Fcons(obj3, Qnil))));
1187 }
1188
1189 Lisp_Object
1190 list5(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2, Lisp_Object obj3,
1191       Lisp_Object obj4)
1192 {
1193         /* This cannot GC. */
1194         return Fcons(obj0,
1195                      Fcons(obj1, Fcons(obj2, Fcons(obj3, Fcons(obj4, Qnil)))));
1196 }
1197
1198 Lisp_Object
1199 list6(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2, Lisp_Object obj3,
1200       Lisp_Object obj4, Lisp_Object obj5)
1201 {
1202         /* This cannot GC. */
1203         return Fcons(obj0,
1204                      Fcons(obj1,
1205                            Fcons(obj2,
1206                                  Fcons(obj3, Fcons(obj4, Fcons(obj5, Qnil))))));
1207 }
1208
1209 DEFUN("make-list", Fmake_list, 2, 2, 0, /*
1210 Return a new list of length LENGTH, with each element being OBJECT.
1211 */
1212       (length, object))
1213 {
1214         CHECK_NATNUM(length);
1215
1216         {
1217                 Lisp_Object val = Qnil;
1218                 size_t size = XINT(length);
1219
1220                 while (size--)
1221                         val = Fcons(object, val);
1222                 return val;
1223         }
1224 }
1225 \f
1226 /************************************************************************/
1227 /*                        Float allocation                              */
1228 /************************************************************************/
1229
1230 #ifdef HAVE_FPFLOAT
1231 #include <math.h>
1232
1233 DECLARE_FIXED_TYPE_ALLOC(float, Lisp_Float);
1234 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_float 1000
1235
1236 Lisp_Object make_float(fpfloat float_value)
1237 {
1238         Lisp_Object val;
1239         Lisp_Float *f;
1240
1241         if (ENT_FLOAT_PINF_P(float_value))
1242                 return make_indef(POS_INFINITY);
1243         else if (ENT_FLOAT_NINF_P(float_value))
1244                 return make_indef(NEG_INFINITY);
1245         else if (ENT_FLOAT_NAN_P(float_value))
1246                 return make_indef(NOT_A_NUMBER);
1247
1248         ALLOCATE_FIXED_TYPE(float, Lisp_Float, f);
1249
1250         /* Avoid dump-time `uninitialized memory read' purify warnings. */
1251         if (sizeof(struct lrecord_header) +
1252             sizeof(fpfloat) != sizeof(*f))
1253                 xzero(*f);
1254
1255         set_lheader_implementation(&f->lheader, &lrecord_float);
1256         float_data(f) = float_value;
1257         XSETFLOAT(val, f);
1258         return val;
1259 }
1260
1261 #endif  /* HAVE_FPFLOAT */
1262 \f
1263 /************************************************************************/
1264 /*                      Enhanced number allocation                      */
1265 /************************************************************************/
1266
1267 /*** Bignum ***/
1268 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
1269 DECLARE_FIXED_TYPE_ALLOC(bigz, Lisp_Bigz);
1270 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_bigz 250
1271
1272 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
1273 static void
1274 bigz_register_finaliser(Lisp_Bigz *b)
1275 {
1276         GC_finalization_proc *foo = NULL;
1277         void **bar = NULL;
1278         auto void bigz_finaliser();
1279
1280         auto void bigz_finaliser(void *obj, void *SXE_UNUSED(data))
1281         {
1282                 bigz_fini(bigz_data((Lisp_Bigz*)obj));
1283                 /* cleanse */
1284                 memset(obj, 0, sizeof(Lisp_Bigz));
1285                 return;
1286         }
1287
1288         GC_REGISTER_FINALIZER(b, bigz_finaliser, NULL, foo, bar);
1289         return;
1290 }
1291 #else  /* !BDWGC */
1292 static inline void
1293 bigz_register_finaliser(Lisp_Bigz *SXE_UNUSED(b))
1294 {
1295         return;
1296 }
1297 #endif  /* HAVE_BDWGC */
1298
1299 /* WARNING: This function returns a bignum even if its argument fits into a
1300    fixnum.  See Fcanonicalize_number(). */
1301 Lisp_Object
1302 make_bigz (long bigz_value)
1303 {
1304         Lisp_Bigz *b;
1305         
1306         ALLOCATE_FIXED_TYPE(bigz, Lisp_Bigz, b);
1307         bigz_register_finaliser(b);
1308
1309         set_lheader_implementation(&b->lheader, &lrecord_bigz);
1310         bigz_init(bigz_data(b));
1311         bigz_set_long(bigz_data(b), bigz_value);
1312         return wrap_bigz(b);
1313 }
1314
1315 /* WARNING: This function returns a bigz even if its argument fits into a
1316    fixnum.  See Fcanonicalize_number(). */
1317 Lisp_Object
1318 make_bigz_bz (bigz bz)
1319 {
1320         Lisp_Bigz *b;
1321
1322         ALLOCATE_FIXED_TYPE(bigz, Lisp_Bigz, b);
1323         bigz_register_finaliser(b);
1324
1325         set_lheader_implementation(&b->lheader, &lrecord_bigz);
1326         bigz_init(bigz_data(b));
1327         bigz_set(bigz_data(b), bz);
1328         return wrap_bigz(b);
1329 }
1330 #endif /* HAVE_MPZ */
1331
1332 /*** Ratio ***/
1333 #if defined HAVE_MPQ && defined WITH_GMP
1334 DECLARE_FIXED_TYPE_ALLOC(bigq, Lisp_Bigq);
1335 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_bigq 250
1336
1337 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
1338 static void
1339 bigq_register_finaliser(Lisp_Bigq *b)
1340 {
1341         GC_finalization_proc *foo = NULL;
1342         void **bar = NULL;
1343         auto void bigq_finaliser();
1344
1345         auto void bigq_finaliser(void *obj, void *SXE_UNUSED(data))
1346         {
1347                 bigq_fini(bigq_data((Lisp_Bigq*)obj));
1348                 /* cleanse */
1349                 memset(obj, 0, sizeof(Lisp_Bigq));
1350                 return;
1351         }
1352
1353         GC_REGISTER_FINALIZER(b, bigq_finaliser, NULL, foo, bar);
1354         return;
1355 }
1356 #else  /* !BDWGC */
1357 static inline void
1358 bigq_register_finaliser(Lisp_Bigq *SXE_UNUSED(b))
1359 {
1360         return;
1361 }
1362 #endif  /* HAVE_BDWGC */
1363
1364 Lisp_Object
1365 make_bigq(long numerator, unsigned long denominator)
1366 {
1367         Lisp_Bigq *r;
1368
1369         ALLOCATE_FIXED_TYPE(bigq, Lisp_Bigq, r);
1370         bigq_register_finaliser(r);
1371
1372         set_lheader_implementation(&r->lheader, &lrecord_bigq);
1373         bigq_init(bigq_data(r));
1374         bigq_set_long_ulong(bigq_data(r), numerator, denominator);
1375         bigq_canonicalize(bigq_data(r));
1376         return wrap_bigq(r);
1377 }
1378
1379 Lisp_Object
1380 make_bigq_bz(bigz numerator, bigz denominator)
1381 {
1382         Lisp_Bigq *r;
1383
1384         ALLOCATE_FIXED_TYPE(bigq, Lisp_Bigq, r);
1385         bigq_register_finaliser(r);
1386
1387         set_lheader_implementation(&r->lheader, &lrecord_bigq);
1388         bigq_init(bigq_data(r));
1389         bigq_set_bigz_bigz(bigq_data(r), numerator, denominator);
1390         bigq_canonicalize(bigq_data(r));
1391         return wrap_bigq(r);
1392 }
1393
1394 Lisp_Object
1395 make_bigq_bq(bigq rat)
1396 {
1397         Lisp_Bigq *r;
1398
1399         ALLOCATE_FIXED_TYPE(bigq, Lisp_Bigq, r);
1400         bigq_register_finaliser(r);
1401
1402         set_lheader_implementation(&r->lheader, &lrecord_bigq);
1403         bigq_init(bigq_data(r));
1404         bigq_set(bigq_data(r), rat);
1405         return wrap_bigq(r);
1406 }
1407 #endif  /* HAVE_MPQ */
1408
1409 /*** Bigfloat ***/
1410 #if defined HAVE_MPF && defined WITH_GMP
1411 DECLARE_FIXED_TYPE_ALLOC(bigf, Lisp_Bigf);
1412 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_bigf 250
1413
1414 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
1415 static void
1416 bigf_register_finaliser(Lisp_Bigf *b)
1417 {
1418         GC_finalization_proc *foo = NULL;
1419         void **bar = NULL;
1420         auto void bigf_finaliser();
1421
1422         auto void bigf_finaliser(void *obj, void *SXE_UNUSED(data))
1423         {
1424                 bigf_fini(bigf_data((Lisp_Bigf*)obj));
1425                 /* cleanse */
1426                 memset(obj, 0, sizeof(Lisp_Bigf));
1427                 return;
1428         }
1429
1430         GC_REGISTER_FINALIZER(b, bigf_finaliser, NULL, foo, bar);
1431         return;
1432 }
1433 #else  /* !BDWGC */
1434 static inline void
1435 bigf_register_finaliser(Lisp_Bigf *SXE_UNUSED(b))
1436 {
1437         return;
1438 }
1439 #endif  /* HAVE_BDWGC */
1440
1441 /* This function creates a bigfloat with the default precision if the
1442    PRECISION argument is zero. */
1443 Lisp_Object
1444 make_bigf(fpfloat float_value, unsigned long precision)
1445 {
1446         Lisp_Bigf *f;
1447
1448         ALLOCATE_FIXED_TYPE(bigf, Lisp_Bigf, f);
1449         bigf_register_finaliser(f);
1450
1451         set_lheader_implementation(&f->lheader, &lrecord_bigf);
1452         if (precision == 0UL)
1453                 bigf_init(bigf_data(f));
1454         else
1455                 bigf_init_prec(bigf_data(f), precision);
1456         bigf_set_fpfloat(bigf_data(f), float_value);
1457         return wrap_bigf(f);
1458 }
1459
1460 /* This function creates a bigfloat with the precision of its argument */
1461 Lisp_Object
1462 make_bigf_bf(bigf float_value)
1463 {
1464         Lisp_Bigf *f;
1465
1466         ALLOCATE_FIXED_TYPE(bigf, Lisp_Bigf, f);
1467         bigf_register_finaliser(f);
1468
1469         set_lheader_implementation(&f->lheader, &lrecord_bigf);
1470         bigf_init_prec(bigf_data(f), bigf_get_prec(float_value));
1471         bigf_set(bigf_data(f), float_value);
1472         return wrap_bigf(f);
1473 }
1474 #endif /* HAVE_MPF */
1475
1476 /*** Bigfloat with correct rounding ***/
1477 #if defined HAVE_MPFR && defined WITH_MPFR
1478 DECLARE_FIXED_TYPE_ALLOC(bigfr, Lisp_Bigfr);
1479 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_bigfr 250
1480
1481 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
1482 static void
1483 bigfr_register_finaliser(Lisp_Bigfr *b)
1484 {
1485         GC_finalization_proc *foo = NULL;
1486         void **bar = NULL;
1487         auto void bigfr_finaliser();
1488
1489         auto void bigfr_finaliser(void *obj, void *SXE_UNUSED(data))
1490         {
1491                 bigfr_fini(bigfr_data((Lisp_Bigfr*)obj));
1492                 /* cleanse */
1493                 memset(obj, 0, sizeof(Lisp_Bigfr));
1494                 return;
1495         }
1496
1497         GC_REGISTER_FINALIZER(b, bigfr_finaliser, NULL, foo, bar);
1498         return;
1499 }
1500 #else  /* !BDWGC */
1501 static inline void
1502 bigfr_register_finaliser(Lisp_Bigfr *SXE_UNUSED(b))
1503 {
1504         return;
1505 }
1506 #endif  /* HAVE_BDWGC */
1507
1508 /* This function creates a bigfloat with the default precision if the
1509    PRECISION argument is zero. */
1510 Lisp_Object
1511 make_bigfr(fpfloat float_value, unsigned long precision)
1512 {
1513         Lisp_Bigfr *f;
1514
1515         ALLOCATE_FIXED_TYPE(bigfr, Lisp_Bigfr, f);
1516         set_lheader_implementation(&f->lheader, &lrecord_bigfr);
1517         bigfr_register_finaliser(f);
1518
1519         if (precision == 0UL) {
1520                 bigfr_init(bigfr_data(f));
1521         } else {
1522                 bigfr_init_prec(bigfr_data(f), precision);
1523         }
1524         bigfr_set_fpfloat(bigfr_data(f), float_value);
1525         return wrap_bigfr(f);
1526 }
1527
1528 /* This function creates a bigfloat with the precision of its argument */
1529 Lisp_Object
1530 make_bigfr_bf(bigf float_value)
1531 {
1532         Lisp_Bigfr *f;
1533
1534         ALLOCATE_FIXED_TYPE(bigfr, Lisp_Bigfr, f);
1535         set_lheader_implementation(&f->lheader, &lrecord_bigfr);
1536         bigfr_register_finaliser(f);
1537
1538         bigfr_init_prec(bigfr_data(f), bigf_get_prec(float_value));
1539         bigfr_set_bigf(bigfr_data(f), float_value);
1540         return wrap_bigfr(f);
1541 }
1542
1543 /* This function creates a bigfloat with the precision of its argument */
1544 Lisp_Object
1545 make_bigfr_bfr(bigfr bfr_value)
1546 {
1547         Lisp_Bigfr *f;
1548
1549         if (bigfr_nan_p(bfr_value) || bigfr_inf_p(bfr_value)) {
1550                 return make_indef_bfr(bfr_value);
1551         }
1552
1553         ALLOCATE_FIXED_TYPE(bigfr, Lisp_Bigfr, f);
1554         set_lheader_implementation(&f->lheader, &lrecord_bigfr);
1555         bigfr_register_finaliser(f);
1556
1557         bigfr_init_prec(bigfr_data(f), bigfr_get_prec(bfr_value));
1558         bigfr_set(bigfr_data(f), bfr_value);
1559         return wrap_bigfr(f);
1560 }
1561 #endif /* HAVE_MPFR */
1562
1563 /*** Big gaussian numbers ***/
1564 #if defined HAVE_PSEUG && defined HAVE_MPZ && defined WITH_PSEUG
1565 DECLARE_FIXED_TYPE_ALLOC(bigg, Lisp_Bigg);
1566 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_bigg 250
1567
1568 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
1569 static void
1570 bigg_register_finaliser(Lisp_Bigg *b)
1571 {
1572         GC_finalization_proc *foo = NULL;
1573         void **bar = NULL;
1574         auto void bigg_finaliser();
1575
1576         auto void bigg_finaliser(void *obj, void *SXE_UNUSED(data))
1577         {
1578                 bigg_fini(bigg_data((Lisp_Bigg*)obj));
1579                 /* cleanse */
1580                 memset(obj, 0, sizeof(Lisp_Bigg));
1581                 return;
1582         }
1583
1584         GC_REGISTER_FINALIZER(b, bigg_finaliser, NULL, foo, bar);
1585         return;
1586 }
1587 #else  /* !BDWGC */
1588 static inline void
1589 bigg_register_finaliser(Lisp_Bigg *SXE_UNUSED(b))
1590 {
1591         return;
1592 }
1593 #endif  /* HAVE_BDWGC */
1594
1595 /* This function creates a gaussian number. */
1596 Lisp_Object
1597 make_bigg(long intg, long imag)
1598 {
1599         Lisp_Bigg *g;
1600
1601         ALLOCATE_FIXED_TYPE(bigg, Lisp_Bigg, g);
1602         set_lheader_implementation(&g->lheader, &lrecord_bigg);
1603         bigg_register_finaliser(g);
1604
1605         bigg_init(bigg_data(g));
1606         bigg_set_long_long(bigg_data(g), intg, imag);
1607         return wrap_bigg(g);
1608 }
1609
1610 /* This function creates a complex with the precision of its argument */
1611 Lisp_Object
1612 make_bigg_bz(bigz intg, bigz imag)
1613 {
1614         Lisp_Bigg *g;
1615
1616         ALLOCATE_FIXED_TYPE(bigg, Lisp_Bigg, g);
1617         set_lheader_implementation(&g->lheader, &lrecord_bigg);
1618         bigg_register_finaliser(g);
1619
1620         bigg_init(bigg_data(g));
1621         bigg_set_bigz_bigz(bigg_data(g), intg, imag);
1622         return wrap_bigg(g);
1623 }
1624
1625 /* This function creates a complex with the precision of its argument */
1626 Lisp_Object
1627 make_bigg_bg(bigg gaussian_value)
1628 {
1629         Lisp_Bigg *g;
1630
1631         ALLOCATE_FIXED_TYPE(bigg, Lisp_Bigg, g);
1632         set_lheader_implementation(&g->lheader, &lrecord_bigg);
1633         bigg_register_finaliser(g);
1634
1635         bigg_init(bigg_data(g));
1636         bigg_set(bigg_data(g), gaussian_value);
1637         return wrap_bigg(g);
1638 }
1639 #endif /* HAVE_PSEUG */
1640
1641 /*** Big complex numbers with correct rounding ***/
1642 #if defined HAVE_MPC && defined WITH_MPC || \
1643         defined HAVE_PSEUC && defined WITH_PSEUC
1644 DECLARE_FIXED_TYPE_ALLOC(bigc, Lisp_Bigc);
1645 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_bigc 250
1646
1647 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
1648 static void
1649 bigc_register_finaliser(Lisp_Bigc *b)
1650 {
1651         GC_finalization_proc *foo = NULL;
1652         void **bar = NULL;
1653         auto void bigc_finaliser();
1654
1655         auto void bigc_finaliser(void *obj, void *SXE_UNUSED(data))
1656         {
1657                 bigc_fini(bigc_data((Lisp_Bigc*)obj));
1658                 /* cleanse */
1659                 memset(obj, 0, sizeof(Lisp_Bigc));
1660                 return;
1661         }
1662
1663         GC_REGISTER_FINALIZER(b, bigc_finaliser, NULL, foo, bar);
1664         return;
1665 }
1666 #else  /* !BDWGC */
1667 static inline void
1668 bigc_register_finaliser(Lisp_Bigc *SXE_UNUSED(b))
1669 {
1670         return;
1671 }
1672 #endif  /* HAVE_BDWGC */
1673
1674 /* This function creates a bigfloat with the default precision if the
1675    PRECISION argument is zero. */
1676 Lisp_Object
1677 make_bigc(fpfloat re_value, fpfloat im_value, unsigned long precision)
1678 {
1679         Lisp_Bigc *c;
1680
1681         ALLOCATE_FIXED_TYPE(bigc, Lisp_Bigc, c);
1682         set_lheader_implementation(&c->lheader, &lrecord_bigc);
1683         bigc_register_finaliser(c);
1684
1685         if (precision == 0UL) {
1686                 bigc_init(bigc_data(c));
1687         } else {
1688                 bigc_init_prec(bigc_data(c), precision);
1689         }
1690         bigc_set_fpfloat_fpfloat(bigc_data(c), re_value, im_value);
1691         return wrap_bigc(c);
1692 }
1693
1694 /* This function creates a complex with the precision of its argument */
1695 Lisp_Object
1696 make_bigc_bfr(bigfr re_value, bigfr im_value, unsigned long precision)
1697 {
1698         Lisp_Bigc *c;
1699
1700         ALLOCATE_FIXED_TYPE(bigc, Lisp_Bigc, c);
1701         set_lheader_implementation(&c->lheader, &lrecord_bigc);
1702         bigc_register_finaliser(c);
1703
1704         if (precision == 0UL) {
1705                 bigc_init(bigc_data(c));
1706         } else {
1707                 bigc_init_prec(bigc_data(c), precision);
1708         }
1709         bigc_set_bigfr_bigfr(bigc_data(c), re_value, im_value);
1710         return wrap_bigc(c);
1711 }
1712
1713 /* This function creates a complex with the precision of its argument */
1714 Lisp_Object
1715 make_bigc_bc(bigc complex_value)
1716 {
1717         Lisp_Bigc *c;
1718
1719         ALLOCATE_FIXED_TYPE(bigc, Lisp_Bigc, c);
1720         set_lheader_implementation(&c->lheader, &lrecord_bigc);
1721         bigc_register_finaliser(c);
1722
1723         bigc_init_prec(bigc_data(c), bigc_get_prec(complex_value));
1724         bigc_set(bigc_data(c), complex_value);
1725         return wrap_bigc(c);
1726 }
1727 #endif /* HAVE_MPC */
1728
1729 /*** Quaternions ***/
1730 #if defined HAVE_QUATERN && defined HAVE_MPZ && defined WITH_QUATERN
1731 DECLARE_FIXED_TYPE_ALLOC(quatern, Lisp_Quatern);
1732 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_quatern 250
1733
1734 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
1735 static void
1736 quatern_register_finaliser(Lisp_Quatern *b)
1737 {
1738         GC_finalization_proc *foo = NULL;
1739         void **bar = NULL;
1740         auto void quatern_finaliser();
1741
1742         auto void quatern_finaliser(void *obj, void *SXE_UNUSED(data))
1743         {
1744                 quatern_fini(quatern_data((Lisp_Quatern*)obj));
1745                 /* cleanse */
1746                 memset(obj, 0, sizeof(Lisp_Quatern));
1747                 return;
1748         }
1749
1750         GC_REGISTER_FINALIZER(b, quatern_finaliser, NULL, foo, bar);
1751         return;
1752 }
1753 #else  /* !BDWGC */
1754 static inline void
1755 quatern_register_finaliser(Lisp_Quatern *SXE_UNUSED(b))
1756 {
1757         return;
1758 }
1759 #endif  /* HAVE_BDWGC */
1760
1761 /* This function creates a quaternion. */
1762 Lisp_Object
1763 make_quatern(EMACS_INT z, EMACS_INT i, EMACS_INT j, EMACS_INT k)
1764 {
1765         Lisp_Quatern *g;
1766
1767         ALLOCATE_FIXED_TYPE(quatern, Lisp_Quatern, g);
1768         set_lheader_implementation(&g->lheader, &lrecord_quatern);
1769         quatern_register_finaliser(g);
1770
1771         quatern_init(quatern_data(g));
1772         quatern_set_long_long_long_long(quatern_data(g), z, i, j, k);
1773         return wrap_quatern(g);
1774 }
1775
1776 Lisp_Object
1777 make_quatern_bz(bigz z, bigz i, bigz j, bigz k)
1778 {
1779         Lisp_Quatern *g;
1780
1781         ALLOCATE_FIXED_TYPE(quatern, Lisp_Quatern, g);
1782         set_lheader_implementation(&g->lheader, &lrecord_quatern);
1783         quatern_register_finaliser(g);
1784
1785         quatern_init(quatern_data(g));
1786         quatern_set_bigz_bigz_bigz_bigz(quatern_data(g), z, i, j, k);
1787         return wrap_quatern(g);
1788 }
1789
1790 Lisp_Object
1791 make_quatern_qu(quatern quaternion)
1792 {
1793         Lisp_Quatern *g;
1794
1795         ALLOCATE_FIXED_TYPE(quatern, Lisp_Quatern, g);
1796         set_lheader_implementation(&g->lheader, &lrecord_quatern);
1797         quatern_register_finaliser(g);
1798
1799         quatern_init(quatern_data(g));
1800         quatern_set(quatern_data(g), quaternion);
1801         return wrap_quatern(g);
1802 }
1803 #endif /* HAVE_QUATERN */
1804
1805 Lisp_Object
1806 make_indef_internal(indef sym)
1807 {
1808         Lisp_Indef *i;
1809
1810         i = allocate_lisp_storage(sizeof(Lisp_Indef));
1811         set_lheader_implementation(&i->lheader, &lrecord_indef);
1812         indef_data(i) = sym;
1813         return wrap_indef(i);
1814 }
1815
1816 Lisp_Object
1817 make_indef(indef sym)
1818 {
1819         switch (sym) {
1820         case NEG_INFINITY:
1821                 return Vninfinity;
1822         case POS_INFINITY:
1823                 return Vpinfinity;
1824         case COMPLEX_INFINITY:
1825                 return Vcomplex_infinity;
1826         case NOT_A_NUMBER:
1827         default:
1828                 /* list some more here */
1829         case END_OF_COMPARABLE_INFINITIES:
1830         case END_OF_INFINITIES:
1831         case NUMBER_INDEFS:
1832                 return Vnot_a_number;
1833         }
1834 }
1835
1836 #if defined HAVE_MPFR && defined WITH_MPFR
1837 Lisp_Object
1838 make_indef_bfr(bigfr bfr_value)
1839 {
1840         if (bigfr_nan_p(bfr_value)) {
1841                 return make_indef(NOT_A_NUMBER);
1842         } else if (bigfr_inf_p(bfr_value)) {
1843                 if (bigfr_sign(bfr_value) > 0)
1844                         return make_indef(POS_INFINITY);
1845                 else
1846                         return make_indef(NEG_INFINITY);
1847         } else {
1848                 return make_indef(NOT_A_NUMBER);
1849         }
1850 }
1851 #endif
1852
1853 DECLARE_FIXED_TYPE_ALLOC(dynacat, struct dynacat_s);
1854 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_dynacat 1000
1855
1856 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
1857 static void
1858 dynacat_register_finaliser(dynacat_t b)
1859 {
1860         GC_finalization_proc *foo = NULL;
1861         void **bar = NULL;
1862         auto void dynacat_finaliser();
1863
1864         auto void dynacat_finaliser(void *obj, void *SXE_UNUSED(data))
1865         {
1866                 SXE_DEBUG_GC("calling dynacat finaliser on %p\n", obj);
1867                 dynacat_fini(obj);
1868                 /* cleanse */
1869                 memset(obj, 0, sizeof(struct dynacat_s));
1870                 return;
1871         }
1872
1873         SXE_DEBUG_GC("dynacat-fina %p\n", b);
1874         GC_REGISTER_FINALIZER(b, dynacat_finaliser, NULL, foo, bar);
1875         return;
1876 }
1877 #else  /* !BDWGC */
1878 static inline void
1879 dynacat_register_finaliser(dynacat_t SXE_UNUSED(b))
1880 {
1881         return;
1882 }
1883 #endif  /* HAVE_BDWGC */
1884
1885 Lisp_Object
1886 make_dynacat(void *ptr)
1887 {
1888         dynacat_t emp;
1889
1890         ALLOCATE_FIXED_TYPE(dynacat, struct dynacat_s, emp);
1891         dynacat_register_finaliser(emp);
1892         set_lheader_implementation(&emp->lheader, &lrecord_dynacat);
1893
1894         emp->prfun = NULL;
1895         emp->intprfun = NULL;
1896         emp->finfun = NULL;
1897         emp->mrkfun = NULL;
1898         emp->ptr = ptr;
1899         emp->type = Qnil;
1900         emp->plist = Qnil;
1901
1902         return wrap_object(emp);
1903 }
1904
1905 \f
1906 /************************************************************************/
1907 /*                         Vector allocation                            */
1908 /************************************************************************/
1909
1910 static Lisp_Object mark_vector(Lisp_Object obj)
1911 {
1912         Lisp_Vector *ptr = XVECTOR(obj);
1913         int len = vector_length(ptr);
1914         int i;
1915
1916         for (i = 0; i < len - 1; i++)
1917                 mark_object(ptr->contents[i]);
1918         return (len > 0) ? ptr->contents[len - 1] : Qnil;
1919 }
1920
1921 static size_t size_vector(const void *lheader)
1922 {
1923         return FLEXIBLE_ARRAY_STRUCT_SIZEOF(
1924                 Lisp_Vector, Lisp_Object, contents,
1925                 ((const Lisp_Vector*)lheader)->size);
1926 }
1927
1928 static int vector_equal(Lisp_Object obj1, Lisp_Object obj2, int depth)
1929 {
1930         int len = XVECTOR_LENGTH(obj1);
1931         if (len != XVECTOR_LENGTH(obj2))
1932                 return 0;
1933
1934         {
1935                 Lisp_Object *ptr1 = XVECTOR_DATA(obj1);
1936                 Lisp_Object *ptr2 = XVECTOR_DATA(obj2);
1937                 while (len--)
1938                         if (!internal_equal(*ptr1++, *ptr2++, depth + 1))
1939                                 return 0;
1940         }
1941         return 1;
1942 }
1943
1944 static hcode_t vector_hash(Lisp_Object obj, int depth)
1945 {
1946         return HASH2(XVECTOR_LENGTH(obj),
1947                      internal_array_hash(XVECTOR_DATA(obj),
1948                                          XVECTOR_LENGTH(obj), depth + 1));
1949 }
1950
1951 /* the seq approach for conses */
1952 static size_t
1953 vec_length(const seq_t v)
1954 {
1955         return XVECTOR_LENGTH((Lisp_Object)(long int)v);
1956 }
1957
1958 static void
1959 vec_iter_init(seq_t v, seq_iter_t si)
1960 {
1961         si->seq = v;
1962         si->data = (void*)0;
1963         return;
1964 }
1965
1966 static void
1967 vec_iter_next(seq_iter_t si, void **elt)
1968 {
1969         if (si->seq != NULL &&
1970             (long int)si->data < ((Lisp_Vector*)si->seq)->size) {
1971                 *elt = (void*)vector_data((Lisp_Vector*)si->seq)
1972                         [(long int)si->data];
1973                 si->data = (void*)((long int)si->data + 1L);
1974         } else {
1975                 *elt = NULL;
1976         }
1977         return;
1978 }
1979
1980 static void
1981 vec_iter_fini(seq_iter_t si)
1982 {
1983         si->data = si->seq = NULL;
1984         return;
1985 }
1986
1987 static void
1988 vec_iter_reset(seq_iter_t si)
1989 {
1990         si->data = (void*)0;
1991         return;
1992 }
1993
1994 static size_t
1995 vec_explode(void *restrict tgt[], size_t ntgt, const seq_t s)
1996 {
1997         size_t len = vector_length((const Lisp_Vector*)s);
1998         volatile size_t i = 0;
1999
2000         while (i < len && i < ntgt) {
2001                 tgt[i] = (void*)vector_data((const Lisp_Vector*)s)[i];
2002                 i++;
2003         }
2004         return i;
2005 }
2006
2007 static struct seq_impl_s __svec = {
2008         .length_f = vec_length,
2009         .iter_init_f = vec_iter_init,
2010         .iter_next_f = vec_iter_next,
2011         .iter_fini_f = vec_iter_fini,
2012         .iter_reset_f = vec_iter_reset,
2013         .explode_f = vec_explode,
2014 };
2015
2016 static const struct lrecord_description vector_description[] = {
2017         {XD_LONG, offsetof(Lisp_Vector, size)},
2018         {XD_LISP_OBJECT_ARRAY, offsetof(Lisp_Vector, contents),
2019          XD_INDIRECT(0, 0)},
2020         {XD_END}
2021 };
2022
2023 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector,
2024                                        mark_vector, print_vector, 0,
2025                                        vector_equal,
2026                                        vector_hash,
2027                                        vector_description,
2028                                        size_vector, Lisp_Vector);
2029
2030 /* #### should allocate `small' vectors from a frob-block */
2031 static Lisp_Vector *make_vector_internal(size_t sizei)
2032 {
2033         /* no vector_next */
2034         size_t sizem = FLEXIBLE_ARRAY_STRUCT_SIZEOF(Lisp_Vector, Lisp_Object,
2035                                                     contents, sizei);
2036         Lisp_Vector *p = (Lisp_Vector *) alloc_lcrecord(sizem, &lrecord_vector);
2037
2038         p->size = sizei;
2039         p->header.lheader.morphisms = (1<<cat_mk_lc);
2040         return p;
2041 }
2042
2043 Lisp_Object make_vector(size_t length, Lisp_Object object)
2044 {
2045         Lisp_Vector *vecp = make_vector_internal(length);
2046         Lisp_Object *p = vector_data(vecp);
2047
2048         while (length--)
2049                 *p++ = object;
2050
2051         {
2052                 Lisp_Object vector;
2053                 XSETVECTOR(vector, vecp);
2054                 return vector;
2055         }
2056 }
2057
2058 DEFUN("make-vector", Fmake_vector, 2, 2, 0,     /*
2059 Return a new vector of length LENGTH, with each element being OBJECT.
2060 See also the function `vector'.
2061 */
2062       (length, object))
2063 {
2064         CONCHECK_NATNUM(length);
2065         return make_vector(XINT(length), object);
2066 }
2067
2068 DEFUN("vector", Fvector, 0, MANY, 0,    /*
2069 Return a newly created vector with specified arguments as elements.
2070 Any number of arguments, even zero arguments, are allowed.
2071 */
2072       (int nargs, Lisp_Object * args))
2073 {
2074         Lisp_Vector *vecp = make_vector_internal(nargs);
2075         Lisp_Object *p = vector_data(vecp);
2076
2077         while (nargs--)
2078                 *p++ = *args++;
2079
2080         {
2081                 Lisp_Object vector;
2082                 XSETVECTOR(vector, vecp);
2083                 return vector;
2084         }
2085 }
2086
2087 Lisp_Object vector1(Lisp_Object obj0)
2088 {
2089         return Fvector(1, &obj0);
2090 }
2091
2092 Lisp_Object vector2(Lisp_Object obj0, Lisp_Object obj1)
2093 {
2094         Lisp_Object args[2];
2095         args[0] = obj0;
2096         args[1] = obj1;
2097         return Fvector(2, args);
2098 }
2099
2100 Lisp_Object vector3(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2)
2101 {
2102         Lisp_Object args[3];
2103         args[0] = obj0;
2104         args[1] = obj1;
2105         args[2] = obj2;
2106         return Fvector(3, args);
2107 }
2108
2109 #if 0                           /* currently unused */
2110
2111 Lisp_Object
2112 vector4(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2, Lisp_Object obj3)
2113 {
2114         Lisp_Object args[4];
2115         args[0] = obj0;
2116         args[1] = obj1;
2117         args[2] = obj2;
2118         args[3] = obj3;
2119         return Fvector(4, args);
2120 }
2121
2122 Lisp_Object
2123 vector5(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2,
2124         Lisp_Object obj3, Lisp_Object obj4)
2125 {
2126         Lisp_Object args[5];
2127         args[0] = obj0;
2128         args[1] = obj1;
2129         args[2] = obj2;
2130         args[3] = obj3;
2131         args[4] = obj4;
2132         return Fvector(5, args);
2133 }
2134
2135 Lisp_Object
2136 vector6(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2,
2137         Lisp_Object obj3, Lisp_Object obj4, Lisp_Object obj5)
2138 {
2139         Lisp_Object args[6];
2140         args[0] = obj0;
2141         args[1] = obj1;
2142         args[2] = obj2;
2143         args[3] = obj3;
2144         args[4] = obj4;
2145         args[5] = obj5;
2146         return Fvector(6, args);
2147 }
2148
2149 Lisp_Object
2150 vector7(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2,
2151         Lisp_Object obj3, Lisp_Object obj4, Lisp_Object obj5, Lisp_Object obj6)
2152 {
2153         Lisp_Object args[7];
2154         args[0] = obj0;
2155         args[1] = obj1;
2156         args[2] = obj2;
2157         args[3] = obj3;
2158         args[4] = obj4;
2159         args[5] = obj5;
2160         args[6] = obj6;
2161         return Fvector(7, args);
2162 }
2163
2164 Lisp_Object
2165 vector8(Lisp_Object obj0, Lisp_Object obj1, Lisp_Object obj2,
2166         Lisp_Object obj3, Lisp_Object obj4, Lisp_Object obj5,
2167         Lisp_Object obj6, Lisp_Object obj7)
2168 {
2169         Lisp_Object args[8];
2170         args[0] = obj0;
2171         args[1] = obj1;
2172         args[2] = obj2;
2173         args[3] = obj3;
2174         args[4] = obj4;
2175         args[5] = obj5;
2176         args[6] = obj6;
2177         args[7] = obj7;
2178         return Fvector(8, args);
2179 }
2180 #endif                          /* unused */
2181
2182 /************************************************************************/
2183 /*                       Bit Vector allocation                          */
2184 /************************************************************************/
2185
2186 static Lisp_Object all_bit_vectors;
2187
2188 /* #### should allocate `small' bit vectors from a frob-block */
2189 static Lisp_Bit_Vector *make_bit_vector_internal(size_t sizei)
2190 {
2191         size_t num_longs = BIT_VECTOR_LONG_STORAGE(sizei);
2192         size_t sizem =
2193             FLEXIBLE_ARRAY_STRUCT_SIZEOF(Lisp_Bit_Vector, unsigned long,
2194                                          bits, num_longs);
2195         Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage(sizem);
2196         set_lheader_implementation(&p->lheader, &lrecord_bit_vector);
2197
2198         INCREMENT_CONS_COUNTER(sizem, "bit-vector");
2199
2200         bit_vector_length(p) = sizei;
2201         bit_vector_next(p) = all_bit_vectors;
2202         /* make sure the extra bits in the last long are 0; the calling
2203            functions might not set them. */
2204         p->bits[num_longs - 1] = 0;
2205         XSETBIT_VECTOR(all_bit_vectors, p);
2206
2207         /* propagate seq implementation */
2208         p->lheader.morphisms = 0;
2209         return p;
2210 }
2211
2212 Lisp_Object make_bit_vector(size_t length, Lisp_Object bit)
2213 {
2214         Lisp_Bit_Vector *p = make_bit_vector_internal(length);
2215         size_t num_longs = BIT_VECTOR_LONG_STORAGE(length);
2216
2217         CHECK_BIT(bit);
2218
2219         if (ZEROP(bit))
2220                 memset(p->bits, 0, num_longs * sizeof(long));
2221         else {
2222                 size_t bits_in_last = length & (LONGBITS_POWER_OF_2 - 1);
2223                 memset(p->bits, ~0, num_longs * sizeof(long));
2224                 /* But we have to make sure that the unused bits in the
2225                    last long are 0, so that equal/hash is easy. */
2226                 if (bits_in_last)
2227                         p->bits[num_longs - 1] &= (1 << bits_in_last) - 1;
2228         }
2229
2230         {
2231                 Lisp_Object bit_vector;
2232                 XSETBIT_VECTOR(bit_vector, p);
2233                 return bit_vector;
2234         }
2235 }
2236
2237 Lisp_Object
2238 make_bit_vector_from_byte_vector(unsigned char *bytevec, size_t length)
2239 {
2240         size_t i;
2241         Lisp_Bit_Vector *p = make_bit_vector_internal(length);
2242
2243         for (i = 0; i < length; i++)
2244                 set_bit_vector_bit(p, i, bytevec[i]);
2245
2246         {
2247                 Lisp_Object bit_vector;
2248                 XSETBIT_VECTOR(bit_vector, p);
2249                 return bit_vector;
2250         }
2251 }
2252
2253 DEFUN("make-bit-vector", Fmake_bit_vector, 2, 2, 0,     /*
2254 Return a new bit vector of length LENGTH. with each bit set to BIT.
2255 BIT must be one of the integers 0 or 1.  See also the function `bit-vector'.
2256 */
2257       (length, bit))
2258 {
2259         CONCHECK_NATNUM(length);
2260
2261         return make_bit_vector(XINT(length), bit);
2262 }
2263
2264 DEFUN("bit-vector", Fbit_vector, 0, MANY, 0,    /*
2265 Return a newly created bit vector with specified arguments as elements.
2266 Any number of arguments, even zero arguments, are allowed.
2267 Each argument must be one of the integers 0 or 1.
2268 */
2269       (int nargs, Lisp_Object * args))
2270 {
2271         int i;
2272         Lisp_Bit_Vector *p = make_bit_vector_internal(nargs);
2273
2274         for (i = 0; i < nargs; i++) {
2275                 CHECK_BIT(args[i]);
2276                 set_bit_vector_bit(p, i, !ZEROP(args[i]));
2277         }
2278
2279         {
2280                 Lisp_Object bit_vector;
2281                 XSETBIT_VECTOR(bit_vector, p);
2282                 return bit_vector;
2283         }
2284 }
2285
2286 /* the seq approach for conses */
2287 static size_t
2288 bvc_length(const seq_t bv)
2289 {
2290         return bit_vector_length(XBIT_VECTOR((Lisp_Object)(long int)bv));
2291 }
2292
2293 static void
2294 bvc_iter_init(seq_t bv, seq_iter_t si)
2295 {
2296         si->seq = bv;
2297         si->data = (void*)0;
2298         return;
2299 }
2300
2301 static void
2302 bvc_iter_next(seq_iter_t si, void **elt)
2303 {
2304         if (si->seq != NULL &&
2305             (long int)si->data < bit_vector_length((Lisp_Bit_Vector*)si->seq)) {
2306                 *elt = (void*)make_int(
2307                         bit_vector_bit(
2308                                 (Lisp_Bit_Vector*)si->seq, (size_t)si->data));
2309                 si->data = (void*)((long int)si->data + 1L);
2310         } else {
2311                 *elt = NULL;
2312         }
2313         return;
2314 }
2315
2316 static void
2317 bvc_iter_fini(seq_iter_t si)
2318 {
2319         si->data = si->seq = NULL;
2320         return;
2321 }
2322
2323 static void
2324 bvc_iter_reset(seq_iter_t si)
2325 {
2326         si->data = (void*)0;
2327         return;
2328 }
2329
2330 static size_t
2331 bvc_explode(void *restrict tgt[], size_t ntgt, const seq_t s)
2332 {
2333         size_t len = bit_vector_length((const Lisp_Bit_Vector*)s);
2334         volatile size_t i = 0;
2335
2336         while (i < len && i < ntgt) {
2337                 tgt[i] = (void*)make_int(
2338                         bit_vector_bit((const Lisp_Bit_Vector*)s, i));
2339                 i++;
2340         }
2341         return i;
2342 }
2343
2344 static struct seq_impl_s __sbvc = {
2345         .length_f = bvc_length,
2346         .iter_init_f = bvc_iter_init,
2347         .iter_next_f = bvc_iter_next,
2348         .iter_fini_f = bvc_iter_fini,
2349         .iter_reset_f = bvc_iter_reset,
2350         .explode_f = bvc_explode,
2351 };
2352 \f
2353 /************************************************************************/
2354 /*                   Compiled-function allocation                       */
2355 /************************************************************************/
2356
2357 DECLARE_FIXED_TYPE_ALLOC(compiled_function, Lisp_Compiled_Function);
2358 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_compiled_function 1000
2359
2360 static Lisp_Object make_compiled_function(void)
2361 {
2362         Lisp_Compiled_Function *f;
2363         Lisp_Object fun;
2364
2365         ALLOCATE_FIXED_TYPE(compiled_function, Lisp_Compiled_Function, f);
2366         set_lheader_implementation(&f->lheader, &lrecord_compiled_function);
2367
2368         f->stack_depth = 0;
2369         f->specpdl_depth = 0;
2370         f->flags.documentationp = 0;
2371         f->flags.interactivep = 0;
2372         f->flags.domainp = 0;   /* I18N3 */
2373         f->instructions = Qzero;
2374         f->constants = Qzero;
2375         f->arglist = Qnil;
2376         f->doc_and_interactive = Qnil;
2377 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
2378         f->annotated = Qnil;
2379 #endif
2380         XSETCOMPILED_FUNCTION(fun, f);
2381         return fun;
2382 }
2383
2384 DEFUN("make-byte-code", Fmake_byte_code, 4, MANY, 0,    /*
2385 Return a new compiled-function object.
2386 Usage: (arglist instructions constants stack-depth
2387 &optional doc-string interactive)
2388 Note that, unlike all other emacs-lisp functions, calling this with five
2389 arguments is NOT the same as calling it with six arguments, the last of
2390 which is nil.  If the INTERACTIVE arg is specified as nil, then that means
2391 that this function was defined with `(interactive)'.  If the arg is not
2392 specified, then that means the function is not interactive.
2393 This is terrible behavior which is retained for compatibility with old
2394 `.elc' files which expect these semantics.
2395 */
2396       (int nargs, Lisp_Object * args))
2397 {
2398 /* In a non-insane world this function would have this arglist...
2399    (arglist instructions constants stack_depth &optional doc_string interactive)
2400  */
2401         Lisp_Object fun = make_compiled_function();
2402         Lisp_Compiled_Function *f = XCOMPILED_FUNCTION(fun);
2403
2404         Lisp_Object arglist = args[0];
2405         Lisp_Object instructions = args[1];
2406         Lisp_Object constants = args[2];
2407         Lisp_Object stack_depth = args[3];
2408         Lisp_Object doc_string = (nargs > 4) ? args[4] : Qnil;
2409         Lisp_Object interactive = (nargs > 5) ? args[5] : Qunbound;
2410
2411         if (nargs < 4 || nargs > 6)
2412                 return Fsignal(Qwrong_number_of_arguments,
2413                                list2(intern("make-byte-code"),
2414                                      make_int(nargs)));
2415
2416         /* Check for valid formal parameter list now, to allow us to use
2417            SPECBIND_FAST_UNSAFE() later in funcall_compiled_function(). */
2418         {
2419                 EXTERNAL_LIST_LOOP_3(symbol, arglist, tail) {
2420                         CHECK_SYMBOL(symbol);
2421                         if (EQ(symbol, Qt) ||
2422                             EQ(symbol, Qnil) || SYMBOL_IS_KEYWORD(symbol))
2423                                 signal_simple_error_2
2424                                     ("Invalid constant symbol in formal parameter list",
2425                                      symbol, arglist);
2426                 }
2427         }
2428         f->arglist = arglist;
2429
2430         /* `instructions' is a string or a cons (string . int) for a
2431            lazy-loaded function. */
2432         if (CONSP(instructions)) {
2433                 CHECK_STRING(XCAR(instructions));
2434                 CHECK_INT(XCDR(instructions));
2435         } else {
2436                 CHECK_STRING(instructions);
2437         }
2438         f->instructions = instructions;
2439
2440         if (!NILP(constants))
2441                 CHECK_VECTOR(constants);
2442         f->constants = constants;
2443
2444         CHECK_NATNUM(stack_depth);
2445         f->stack_depth = (unsigned short)XINT(stack_depth);
2446
2447 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
2448         if (!NILP(Vcurrent_compiled_function_annotation))
2449                 f->annotated = Fcopy(Vcurrent_compiled_function_annotation);
2450         else if (!NILP(Vload_file_name_internal_the_purecopy))
2451                 f->annotated = Vload_file_name_internal_the_purecopy;
2452         else if (!NILP(Vload_file_name_internal)) {
2453                 struct gcpro gcpro1;
2454                 GCPRO1(fun);    /* don't let fun get reaped */
2455                 Vload_file_name_internal_the_purecopy =
2456                     Ffile_name_nondirectory(Vload_file_name_internal);
2457                 f->annotated = Vload_file_name_internal_the_purecopy;
2458                 UNGCPRO;
2459         }
2460 #endif                          /* COMPILED_FUNCTION_ANNOTATION_HACK */
2461
2462         /* doc_string may be nil, string, int, or a cons (string . int).
2463            interactive may be list or string (or unbound). */
2464         f->doc_and_interactive = Qunbound;
2465 #ifdef I18N3
2466         if ((f->flags.domainp = !NILP(Vfile_domain)) != 0)
2467                 f->doc_and_interactive = Vfile_domain;
2468 #endif
2469         if ((f->flags.interactivep = !UNBOUNDP(interactive)) != 0) {
2470                 f->doc_and_interactive
2471                     = (UNBOUNDP(f->doc_and_interactive) ? interactive :
2472                        Fcons(interactive, f->doc_and_interactive));
2473         }
2474         if ((f->flags.documentationp = !NILP(doc_string)) != 0) {
2475                 f->doc_and_interactive
2476                     = (UNBOUNDP(f->doc_and_interactive) ? doc_string :
2477                        Fcons(doc_string, f->doc_and_interactive));
2478         }
2479         if (UNBOUNDP(f->doc_and_interactive))
2480                 f->doc_and_interactive = Qnil;
2481
2482         return fun;
2483 }
2484 \f
2485 /************************************************************************/
2486 /*                          Symbol allocation                           */
2487 /************************************************************************/
2488
2489 DECLARE_FIXED_TYPE_ALLOC(symbol, Lisp_Symbol);
2490 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_symbol 1000
2491
2492 DEFUN("make-symbol", Fmake_symbol, 1, 1, 0,     /*
2493 Return a newly allocated uninterned symbol whose name is NAME.
2494 Its value and function definition are void, and its property list is nil.
2495 */
2496       (name))
2497 {
2498         Lisp_Object val;
2499         Lisp_Symbol *p;
2500
2501         CHECK_STRING(name);
2502
2503         ALLOCATE_FIXED_TYPE(symbol, Lisp_Symbol, p);
2504         set_lheader_implementation(&p->lheader, &lrecord_symbol);
2505         p->name = XSTRING(name);
2506         p->plist = Qnil;
2507         p->value = Qunbound;
2508         p->function = Qunbound;
2509         symbol_next(p) = 0;
2510         XSETSYMBOL(val, p);
2511         return val;
2512 }
2513 \f
2514 /************************************************************************/
2515 /*                         Extent allocation                            */
2516 /************************************************************************/
2517
2518 DECLARE_FIXED_TYPE_ALLOC(extent, struct extent);
2519 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_extent 1000
2520
2521 struct extent *allocate_extent(void)
2522 {
2523         struct extent *e;
2524
2525         ALLOCATE_FIXED_TYPE(extent, struct extent, e);
2526         set_lheader_implementation(&e->lheader, &lrecord_extent);
2527         extent_object(e) = Qnil;
2528         set_extent_start(e, -1);
2529         set_extent_end(e, -1);
2530         e->plist = Qnil;
2531
2532         xzero(e->flags);
2533
2534         extent_face(e) = Qnil;
2535         e->flags.end_open = 1;  /* default is for endpoints to behave like markers */
2536         e->flags.detachable = 1;
2537
2538         return e;
2539 }
2540 \f
2541 /************************************************************************/
2542 /*                         Event allocation                             */
2543 /************************************************************************/
2544
2545 DECLARE_FIXED_TYPE_ALLOC(event, Lisp_Event);
2546 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_event 1000
2547
2548 Lisp_Object allocate_event(void)
2549 {
2550         Lisp_Object val;
2551         Lisp_Event *e;
2552
2553         ALLOCATE_FIXED_TYPE(event, Lisp_Event, e);
2554         set_lheader_implementation(&e->lheader, &lrecord_event);
2555
2556         XSETEVENT(val, e);
2557         return val;
2558 }
2559 \f
2560 /************************************************************************/
2561 /*                       Marker allocation                              */
2562 /************************************************************************/
2563
2564 DECLARE_FIXED_TYPE_ALLOC(marker, Lisp_Marker);
2565 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_marker 1000
2566
2567 DEFUN("make-marker", Fmake_marker, 0, 0, 0,     /*
2568 Return a new marker which does not point at any place.
2569 */
2570       ())
2571 {
2572         Lisp_Object val;
2573         Lisp_Marker *p;
2574
2575         ALLOCATE_FIXED_TYPE(marker, Lisp_Marker, p);
2576         set_lheader_implementation(&p->lheader, &lrecord_marker);
2577         p->buffer = 0;
2578         p->memind = 0;
2579         marker_next(p) = 0;
2580         marker_prev(p) = 0;
2581         p->insertion_type = 0;
2582         XSETMARKER(val, p);
2583         return val;
2584 }
2585
2586 Lisp_Object noseeum_make_marker(void)
2587 {
2588         Lisp_Object val;
2589         Lisp_Marker *p;
2590
2591         NOSEEUM_ALLOCATE_FIXED_TYPE(marker, Lisp_Marker, p);
2592         set_lheader_implementation(&p->lheader, &lrecord_marker);
2593         p->buffer = 0;
2594         p->memind = 0;
2595         marker_next(p) = 0;
2596         marker_prev(p) = 0;
2597         p->insertion_type = 0;
2598         XSETMARKER(val, p);
2599         return val;
2600 }
2601 \f
2602 /************************************************************************/
2603 /*                        String allocation                             */
2604 /************************************************************************/
2605
2606 /* The data for "short" strings generally resides inside of structs of type
2607    string_chars_block. The Lisp_String structure is allocated just like any
2608    other Lisp object (except for vectors), and these are freelisted when
2609    they get garbage collected. The data for short strings get compacted,
2610    but the data for large strings do not.
2611
2612    Previously Lisp_String structures were relocated, but this caused a lot
2613    of bus-errors because the C code didn't include enough GCPRO's for
2614    strings (since EVERY REFERENCE to a short string needed to be GCPRO'd so
2615    that the reference would get relocated).
2616
2617    This new method makes things somewhat bigger, but it is MUCH safer.  */
2618
2619 DECLARE_FIXED_TYPE_ALLOC(string, Lisp_String);
2620 /* strings are used and freed quite often */
2621 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 10000 */
2622 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000
2623
2624 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && 0
2625 static void
2626 string_register_finaliser(Lisp_String *s)
2627 {
2628         GC_finalization_proc *foo = NULL;
2629         void **bar = NULL;
2630         auto void string_finaliser();
2631
2632         auto void string_finaliser(void *obj, void *SXE_UNUSED(data))
2633         {
2634                 if (!(((Lisp_String*)obj)->lheader.c_readonly)) {
2635                         yfree(((Lisp_String*)obj)->data);
2636                 }
2637                 /* cleanse */
2638                 memset(obj, 0, sizeof(Lisp_String));
2639                 return;
2640         }
2641
2642         SXE_DEBUG_GC("string-fina %p\n", s);
2643         GC_REGISTER_FINALIZER(s, string_finaliser, NULL, foo, bar);
2644         return;
2645 }
2646 #else  /* !BDWGC */
2647 static inline void
2648 string_register_finaliser(Lisp_String *SXE_UNUSED(b))
2649 {
2650         return;
2651 }
2652 #endif  /* HAVE_BDWGC */
2653
2654 static Lisp_Object mark_string(Lisp_Object obj)
2655 {
2656         Lisp_String *ptr = XSTRING(obj);
2657
2658         if (CONSP(ptr->plist) && EXTENT_INFOP(XCAR(ptr->plist)))
2659                 flush_cached_extent_info(XCAR(ptr->plist));
2660 #ifdef EF_USE_COMPRE
2661         mark_object(ptr->compre);
2662 #endif
2663         return ptr->plist;
2664 }
2665
2666 static int string_equal(Lisp_Object obj1, Lisp_Object obj2, int depth)
2667 {
2668         Bytecount len;
2669         return (((len = XSTRING_LENGTH(obj1)) == XSTRING_LENGTH(obj2)) &&
2670                 !memcmp(XSTRING_DATA(obj1), XSTRING_DATA(obj2), len));
2671 }
2672
2673 static const struct lrecord_description string_description[] = {
2674         {XD_BYTECOUNT, offsetof(Lisp_String, size)},
2675         {XD_OPAQUE_DATA_PTR, offsetof(Lisp_String, data), XD_INDIRECT(0, 1)},
2676 #ifdef EF_USE_COMPRE
2677         {XD_LISP_OBJECT, offsetof(Lisp_String, compre)},
2678 #endif
2679         {XD_LISP_OBJECT, offsetof(Lisp_String, plist)},
2680         {XD_END}
2681 };
2682
2683 /* the seq implementation */
2684 static size_t
2685 str_length(const seq_t str)
2686 {
2687         return string_char_length((const Lisp_String*)str);
2688 }
2689
2690 static void
2691 str_iter_init(seq_t str, seq_iter_t si)
2692 {
2693         si->seq = str;
2694         si->data = (void*)0;
2695         return;
2696 }
2697
2698 static void
2699 str_iter_next(seq_iter_t si, void **elt)
2700 {
2701         if (si->seq != NULL &&
2702             (long int)si->data < string_char_length((Lisp_String*)si->seq)) {
2703                 *elt = (void*)make_char(
2704                         string_char((Lisp_String*)si->seq, (long int)si->data));
2705                 si->data = (void*)((long int)si->data + 1);
2706         } else {
2707                 *elt = NULL;
2708         }
2709         return;
2710 }
2711
2712 static void
2713 str_iter_fini(seq_iter_t si)
2714 {
2715         si->data = si->seq = NULL;
2716         return;
2717 }
2718
2719 static void
2720 str_iter_reset(seq_iter_t si)
2721 {
2722         si->data = (void*)0;
2723         return;
2724 }
2725
2726 static size_t
2727 str_explode(void *restrict tgt[], size_t ntgt, const seq_t s)
2728 {
2729         size_t len = string_char_length((const Lisp_String*)s);
2730         volatile size_t i = 0;
2731
2732         while (i < len && i < ntgt) {
2733                 tgt[i] = (void*)make_char(string_char((Lisp_String*)s, i));
2734                 i++;
2735         }
2736         return i;
2737 }
2738
2739 static struct seq_impl_s __sstr = {
2740         .length_f = str_length,
2741         .iter_init_f = str_iter_init,
2742         .iter_next_f = str_iter_next,
2743         .iter_fini_f = str_iter_fini,
2744         .iter_reset_f = str_iter_reset,
2745         .explode_f = str_explode,
2746 };
2747
2748
2749 /* We store the string's extent info as the first element of the string's
2750    property list; and the string's MODIFF as the first or second element
2751    of the string's property list (depending on whether the extent info
2752    is present), but only if the string has been modified.  This is ugly
2753    but it reduces the memory allocated for the string in the vast
2754    majority of cases, where the string is never modified and has no
2755    extent info.
2756
2757    #### This means you can't use an int as a key in a string's plist. */
2758
2759 static Lisp_Object *string_plist_ptr(Lisp_Object string)
2760 {
2761         Lisp_Object *ptr = &XSTRING(string)->plist;
2762
2763         if (CONSP(*ptr) && EXTENT_INFOP(XCAR(*ptr)))
2764                 ptr = &XCDR(*ptr);
2765         if (CONSP(*ptr) && INTP(XCAR(*ptr)))
2766                 ptr = &XCDR(*ptr);
2767         return ptr;
2768 }
2769
2770 static Lisp_Object string_getprop(Lisp_Object string, Lisp_Object property)
2771 {
2772         return external_plist_get(string_plist_ptr(string), property, 0,
2773                                   ERROR_ME);
2774 }
2775
2776 static int
2777 string_putprop(Lisp_Object string, Lisp_Object property, Lisp_Object value)
2778 {
2779         external_plist_put(string_plist_ptr(string), property, value, 0,
2780                            ERROR_ME);
2781         return 1;
2782 }
2783
2784 static int string_remprop(Lisp_Object string, Lisp_Object property)
2785 {
2786         return external_remprop(string_plist_ptr(string), property, 0,
2787                                 ERROR_ME);
2788 }
2789
2790 static Lisp_Object string_plist(Lisp_Object string)
2791 {
2792         return *string_plist_ptr(string);
2793 }
2794
2795 /* No `finalize', or `hash' methods.
2796    internal_hash() already knows how to hash strings and finalization
2797    is done with the ADDITIONAL_FREE_string macro, which is the
2798    standard way to do finalization when using
2799    SWEEP_FIXED_TYPE_BLOCK(). */
2800 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS("string", string,
2801                                                mark_string, print_string,
2802                                                0, string_equal, 0,
2803                                                string_description,
2804                                                string_getprop,
2805                                                string_putprop,
2806                                                string_remprop,
2807                                                string_plist, Lisp_String);
2808
2809 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
2810 /* String blocks contain this many useful bytes. */
2811 #define STRING_CHARS_BLOCK_SIZE                                         \
2812         ((Bytecount) (8192 - MALLOC_OVERHEAD -                          \
2813                       ((2 * sizeof (struct string_chars_block *))       \
2814                        + sizeof (EMACS_INT))))
2815 /* Block header for small strings. */
2816 struct string_chars_block {
2817         EMACS_INT pos;
2818         struct string_chars_block *next;
2819         struct string_chars_block *prev;
2820         /* Contents of string_chars_block->string_chars are interleaved
2821            string_chars structures (see below) and the actual string data */
2822         unsigned char string_chars[STRING_CHARS_BLOCK_SIZE];
2823 };
2824
2825 static struct string_chars_block *first_string_chars_block;
2826 static struct string_chars_block *current_string_chars_block;
2827
2828 /* If SIZE is the length of a string, this returns how many bytes
2829  *  the string occupies in string_chars_block->string_chars
2830  *  (including alignment padding).
2831  */
2832 #define STRING_FULLSIZE(size) \
2833         ALIGN_SIZE(((size) + 1 + sizeof(Lisp_String*)), ALIGNOF(Lisp_String*))
2834
2835 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE)
2836 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size)))
2837
2838 #define STRING_CHARS_FREE_P(ptr) ((ptr)->string == NULL)
2839 #define MARK_STRING_CHARS_AS_FREE(ptr) ((void) ((ptr)->string = NULL))
2840
2841 struct string_chars {
2842         Lisp_String *string;
2843         unsigned char chars[1];
2844 };
2845
2846 struct unused_string_chars {
2847         Lisp_String *string;
2848         EMACS_INT fullsize;
2849 };
2850
2851 static void init_string_chars_alloc(void)
2852 {
2853         first_string_chars_block = ynew(struct string_chars_block);
2854         first_string_chars_block->prev = 0;
2855         first_string_chars_block->next = 0;
2856         first_string_chars_block->pos = 0;
2857         current_string_chars_block = first_string_chars_block;
2858 }
2859
2860 static struct string_chars*
2861 allocate_string_chars_struct(Lisp_String *string_it_goes_with,
2862                              EMACS_INT fullsize)
2863 {
2864         struct string_chars *s_chars;
2865
2866         if (fullsize <= (countof(current_string_chars_block->string_chars)
2867                          - current_string_chars_block->pos)) {
2868                 /* This string can fit in the current string chars block */
2869                 s_chars = (struct string_chars *)
2870                         (current_string_chars_block->string_chars
2871                          + current_string_chars_block->pos);
2872                 current_string_chars_block->pos += fullsize;
2873         } else {
2874                 /* Make a new current string chars block */
2875                 struct string_chars_block *new_scb =
2876                         ynew(struct string_chars_block);
2877
2878                 current_string_chars_block->next = new_scb;
2879                 new_scb->prev = current_string_chars_block;
2880                 new_scb->next = 0;
2881                 current_string_chars_block = new_scb;
2882                 new_scb->pos = fullsize;
2883                 s_chars = (struct string_chars *)
2884                         current_string_chars_block->string_chars;
2885         }
2886
2887         s_chars->string = string_it_goes_with;
2888
2889         INCREMENT_CONS_COUNTER(fullsize, "string chars");
2890
2891         return s_chars;
2892 }
2893 #endif  /* !BDWGC */
2894
2895 Lisp_Object make_uninit_string(Bytecount length)
2896 {
2897         Lisp_String *s = NULL;
2898 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
2899         EMACS_INT fullsize = STRING_FULLSIZE(length);
2900 #endif  /* !BDWGC */
2901         Lisp_Object val;
2902
2903 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
2904         assert(length >= 0 && fullsize > 0);
2905 #endif  /* !BDWGC */
2906
2907         /* Allocate the string header */
2908         ALLOCATE_FIXED_TYPE(string, Lisp_String, s);
2909         set_lheader_implementation(&s->lheader, &lrecord_string);
2910         string_register_finaliser(s);
2911
2912         {
2913                 Bufbyte *foo = NULL;
2914 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
2915                 foo = xnew_atomic_array(Bufbyte, length+1);
2916                 assert(foo != NULL);
2917 #else
2918                 if (BIG_STRING_FULLSIZE_P(fullsize)) {
2919                         foo = xnew_atomic_array(Bufbyte, length + 1);
2920                         assert(foo != NULL);
2921                 } else {
2922                         foo = allocate_string_chars_struct(s, fullsize)->chars;
2923                         assert(foo != NULL);
2924                 }
2925 #endif
2926                 set_string_data(s, foo);
2927         }
2928         set_string_length(s, length);
2929         s->plist = Qnil;
2930 #ifdef EF_USE_COMPRE
2931         s->compre = Qnil;
2932 #endif
2933         /* propagate the cat system, go with the standard impl of a seq first */
2934         s->lheader.morphisms = 0;
2935
2936         set_string_byte(s, length, 0);
2937
2938         XSETSTRING(val, s);
2939         return val;
2940 }
2941
2942 #ifdef VERIFY_STRING_CHARS_INTEGRITY
2943 static void verify_string_chars_integrity(void);
2944 #endif
2945
2946 /* Resize the string S so that DELTA bytes can be inserted starting
2947    at POS.  If DELTA < 0, it means deletion starting at POS.  If
2948    POS < 0, resize the string but don't copy any characters.  Use
2949    this if you're planning on completely overwriting the string.
2950 */
2951
2952 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
2953 void resize_string(Lisp_String * s, Bytecount pos, Bytecount delta)
2954 {
2955         Bytecount len;
2956         Bufbyte *foo;
2957
2958         /* trivial cases first */
2959         if (delta == 0) {
2960                 /* simplest case: no size change. */
2961                 return;
2962         }
2963
2964         if (pos >= 0 && delta < 0) {
2965                 /* If DELTA < 0, the functions below will delete the characters
2966                    before POS.  We want to delete characters *after* POS,
2967                    however, so convert this to the appropriate form. */
2968                 pos += -delta;
2969         }
2970
2971         /* Both strings are big.  We can just realloc().
2972            But careful!  If the string is shrinking, we have to
2973            memmove() _before_ realloc(), and if growing, we have to
2974            memmove() _after_ realloc() - otherwise the access is
2975            illegal, and we might crash. */
2976         len = string_length(s) + 1 - pos;
2977
2978         if (delta < 0 && pos >= 0) {
2979                 memmove(string_data(s) + pos + delta,
2980                         string_data(s) + pos, len);
2981         }
2982
2983         /* do the reallocation */
2984         foo = xrealloc(string_data(s), string_length(s) + delta + 1);
2985         set_string_data(s, foo);
2986
2987         if (delta > 0 && pos >= 0) {
2988                 memmove(string_data(s) + pos + delta,
2989                         string_data(s) + pos, len);
2990         }
2991
2992         set_string_length(s, string_length(s) + delta);
2993         /* If pos < 0, the string won't be zero-terminated.
2994            Terminate now just to make sure. */
2995         string_data(s)[string_length(s)] = '\0';
2996
2997         if (pos >= 0) {
2998                 Lisp_Object string;
2999
3000                 XSETSTRING(string, s);
3001                 /* We also have to adjust all of the extent indices after the
3002                    place we did the change.  We say "pos - 1" because
3003                    adjust_extents() is exclusive of the starting position
3004                    passed to it. */
3005                 adjust_extents(string, pos - 1, string_length(s), delta);
3006         }
3007         return;
3008 }
3009 #else  /* !HAVE_BDWGC */
3010 void resize_string(Lisp_String * s, Bytecount pos, Bytecount delta)
3011 {
3012         Bytecount oldfullsize, newfullsize;
3013 #ifdef VERIFY_STRING_CHARS_INTEGRITY
3014         verify_string_chars_integrity();
3015 #endif
3016
3017 #ifdef ERROR_CHECK_BUFPOS
3018         if (pos >= 0) {
3019                 assert(pos <= string_length(s));
3020                 if (delta < 0)
3021                         assert(pos + (-delta) <= string_length(s));
3022         } else {
3023                 if (delta < 0)
3024                         assert((-delta) <= string_length(s));
3025         }
3026 #endif                          /* ERROR_CHECK_BUFPOS */
3027
3028         if (delta == 0)
3029                 /* simplest case: no size change. */
3030                 return;
3031
3032         if (pos >= 0 && delta < 0)
3033                 /* If DELTA < 0, the functions below will delete the characters
3034                    before POS.  We want to delete characters *after* POS, however,
3035                    so convert this to the appropriate form. */
3036                 pos += -delta;
3037
3038         oldfullsize = STRING_FULLSIZE(string_length(s));
3039         newfullsize = STRING_FULLSIZE(string_length(s) + delta);
3040
3041         if (BIG_STRING_FULLSIZE_P(oldfullsize)) {
3042                 if (BIG_STRING_FULLSIZE_P(newfullsize)) {
3043                         /* Both strings are big.  We can just realloc().
3044                            But careful!  If the string is shrinking, we have to
3045                            memmove() _before_ realloc(), and if growing, we have to
3046                            memmove() _after_ realloc() - otherwise the access is
3047                            illegal, and we might crash. */
3048                         Bytecount len = string_length(s) + 1 - pos;
3049                         Bufbyte *foo;
3050
3051                         if (delta < 0 && pos >= 0)
3052                                 memmove(string_data(s) + pos + delta,
3053                                         string_data(s) + pos, len);
3054
3055                         foo = xrealloc(string_data(s),
3056                                        string_length(s) + delta + 1);
3057                         set_string_data(s, foo);
3058                         if (delta > 0 && pos >= 0) {
3059                                 memmove(string_data(s) + pos + delta,
3060                                         string_data(s) + pos, len);
3061                         }
3062                 } else {
3063                         /* String has been demoted from BIG_STRING. */
3064
3065                         Bufbyte *new_data =
3066                                 allocate_string_chars_struct(s, newfullsize)
3067                                 ->chars;
3068                         Bufbyte *old_data = string_data(s);
3069
3070                         if (pos >= 0) {
3071                                 memcpy(new_data, old_data, pos);
3072                                 memcpy(new_data + pos + delta, old_data + pos,
3073                                        string_length(s) + 1 - pos);
3074                         }
3075                         set_string_data(s, new_data);
3076                         xfree(old_data);
3077                 }
3078         } else {                /* old string is small */
3079
3080                 if (oldfullsize == newfullsize) {
3081                         /* special case; size change but the necessary
3082                            allocation size won't change (up or down; code
3083                            somewhere depends on there not being any unused
3084                            allocation space, modulo any alignment
3085                            constraints). */
3086                         if (pos >= 0) {
3087                                 Bufbyte *addroff = pos + string_data(s);
3088
3089                                 memmove(addroff + delta, addroff,
3090                                         /* +1 due to zero-termination. */
3091                                         string_length(s) + 1 - pos);
3092                         }
3093                 } else {
3094                         Bufbyte *old_data = string_data(s);
3095                         Bufbyte *new_data = BIG_STRING_FULLSIZE_P(newfullsize)
3096                                 ? xnew_atomic_array(
3097                                         Bufbyte, string_length(s) + delta + 1)
3098                                 : allocate_string_chars_struct(
3099                                         s, newfullsize)->chars;
3100
3101                         if (pos >= 0) {
3102                                 memcpy(new_data, old_data, pos);
3103                                 memcpy(new_data + pos + delta, old_data + pos,
3104                                        string_length(s) + 1 - pos);
3105                         }
3106                         set_string_data(s, new_data);
3107
3108                         {
3109                                 /* We need to mark this chunk of the
3110                                    string_chars_block as unused so that
3111                                    compact_string_chars() doesn't freak. */
3112                                 struct string_chars *old_s_chars =
3113                                         (struct string_chars *)
3114                                         ((char *)old_data -
3115                                          offsetof(struct string_chars, chars));
3116                                 /* Sanity check to make sure we aren't hosed by
3117                                    strange alignment/padding. */
3118                                 assert(old_s_chars->string == s);
3119                                 MARK_STRING_CHARS_AS_FREE(old_s_chars);
3120                                 ((struct unused_string_chars *)old_s_chars)->
3121                                         fullsize = oldfullsize;
3122                         }
3123                 }
3124         }
3125
3126         set_string_length(s, string_length(s) + delta);
3127         /* If pos < 0, the string won't be zero-terminated.
3128            Terminate now just to make sure. */
3129         string_data(s)[string_length(s)] = '\0';
3130
3131         if (pos >= 0) {
3132                 Lisp_Object string;
3133
3134                 XSETSTRING(string, s);
3135                 /* We also have to adjust all of the extent indices after the
3136                    place we did the change.  We say "pos - 1" because
3137                    adjust_extents() is exclusive of the starting position
3138                    passed to it. */
3139                 adjust_extents(string, pos - 1, string_length(s), delta);
3140         }
3141 #ifdef VERIFY_STRING_CHARS_INTEGRITY
3142         verify_string_chars_integrity();
3143 #endif
3144 }
3145 #endif  /* BDWGC */
3146 #ifdef MULE
3147
3148 void set_string_char(Lisp_String * s, Charcount i, Emchar c)
3149 {
3150         Bufbyte newstr[MAX_EMCHAR_LEN];
3151         Bytecount bytoff = charcount_to_bytecount(string_data(s), i);
3152         Bytecount oldlen = charcount_to_bytecount(string_data(s) + bytoff, 1);
3153         Bytecount newlen = set_charptr_emchar(newstr, c);
3154
3155         if (oldlen != newlen) {
3156                 resize_string(s, bytoff, newlen - oldlen);
3157         }
3158         /* Remember, string_data (s) might have changed so we can't cache it. */
3159         memcpy(string_data(s) + bytoff, newstr, newlen);
3160 }
3161
3162 #endif                          /* MULE */
3163
3164 DEFUN("make-string", Fmake_string, 2, 2, 0,     /*
3165 Return a new string consisting of LENGTH copies of CHARACTER.
3166 LENGTH must be a non-negative integer.
3167 */
3168       (length, character))
3169 {
3170         CHECK_NATNUM(length);
3171         CHECK_CHAR_COERCE_INT(character);
3172         {
3173                 Bufbyte init_str[MAX_EMCHAR_LEN];
3174                 int len = set_charptr_emchar(init_str, XCHAR(character));
3175                 Lisp_Object val = make_uninit_string(len * XINT(length));
3176
3177                 if (len == 1)
3178                         /* Optimize the single-byte case */
3179                         memset(XSTRING_DATA(val), XCHAR(character),
3180                                XSTRING_LENGTH(val));
3181                 else {
3182                         size_t i;
3183                         Bufbyte *ptr = XSTRING_DATA(val);
3184
3185                         for (i = XINT(length); i; i--) {
3186                                 Bufbyte *init_ptr = init_str;
3187                                 switch (len) {
3188                                 case 4:
3189                                         *ptr++ = *init_ptr++;
3190                                 case 3:
3191                                         *ptr++ = *init_ptr++;
3192                                 case 2:
3193                                         *ptr++ = *init_ptr++;
3194                                 case 1:
3195                                         *ptr++ = *init_ptr++;
3196                                 default:
3197                                         break;
3198                                 }
3199                         }
3200                 }
3201                 return val;
3202         }
3203 }
3204
3205 DEFUN("string", Fstring, 0, MANY, 0,    /*
3206 Concatenate all the argument characters and make the result a string.
3207 */
3208       (int nargs, Lisp_Object * args))
3209 {
3210         Bufbyte *storage, *p;
3211         Lisp_Object result;
3212         int speccount = specpdl_depth();
3213         int len = nargs * MAX_EMCHAR_LEN;
3214
3215         XMALLOC_OR_ALLOCA(storage, len, Bufbyte);
3216         p = storage;
3217         for (; nargs; nargs--, args++) {
3218                 Lisp_Object lisp_char = *args;
3219                 CHECK_CHAR_COERCE_INT(lisp_char);
3220                 p += set_charptr_emchar(p, XCHAR(lisp_char));
3221         }
3222         result = make_string(storage, p - storage);
3223         XMALLOC_UNBIND(storage, len, speccount );
3224
3225         return result;
3226 }
3227
3228 /* Take some raw memory, which MUST already be in internal format,
3229    and package it up into a Lisp string. */
3230 Lisp_Object
3231 make_string(const Bufbyte *contents, Bytecount length)
3232 {
3233         Lisp_Object val;
3234
3235         /* Make sure we find out about bad make_string's when they happen */
3236 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE)
3237         /* Just for the assertions */
3238         bytecount_to_charcount(contents, length);
3239 #endif
3240
3241         val = make_uninit_string(length);
3242         memcpy(XSTRING_DATA(val), contents, length);
3243         return val;
3244 }
3245
3246 /* Take some raw memory, encoded in some external data format,
3247    and convert it into a Lisp string. */
3248 Lisp_Object
3249 make_ext_string(const Extbyte *contents, EMACS_INT length,
3250                 Lisp_Object coding_system)
3251 {
3252         Lisp_Object string;
3253         TO_INTERNAL_FORMAT(DATA, (contents, length),
3254                            LISP_STRING, string, coding_system);
3255         return string;
3256 }
3257
3258 /* why arent the next 3 inlines? */
3259 Lisp_Object build_string(const char *str)
3260 {
3261         /* Some strlen's crash and burn if passed null. */
3262         if( str )
3263                 return make_string((const Bufbyte*)str, strlen(str));
3264         else
3265                 abort();
3266         return Qnil;
3267 }
3268
3269 Lisp_Object build_ext_string(const char *str, Lisp_Object coding_system)
3270 {
3271         /* Some strlen's crash and burn if passed null. */
3272         return make_ext_string((const Extbyte*)str, (str ? strlen(str) : 0), coding_system);
3273 }
3274
3275 Lisp_Object build_translated_string(const char *str)
3276 {
3277         return build_string(GETTEXT(str));
3278 }
3279
3280 Lisp_Object make_string_nocopy(Bufbyte *contents, Bytecount length)
3281 {
3282         Lisp_String *s;
3283         Lisp_Object val;
3284
3285         /* Make sure we find out about bad make_string_nocopy's when they
3286            happen */
3287 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE)
3288         /* Just for the assertions */
3289         bytecount_to_charcount(contents, length);
3290 #endif
3291
3292         /* Allocate the string header */
3293         ALLOCATE_FIXED_TYPE(string, Lisp_String, s);
3294         set_lheader_implementation(&s->lheader, &lrecord_string);
3295         SET_C_READONLY_RECORD_HEADER(&s->lheader);
3296         string_register_finaliser(s);
3297
3298         s->plist = Qnil;
3299 #ifdef EF_USE_COMPRE
3300         s->compre = Qnil;
3301 #endif
3302         set_string_data(s, (Bufbyte*)contents);
3303         set_string_length(s, length);
3304
3305         XSETSTRING(val, s);
3306         return val;
3307 }
3308 \f
3309 /************************************************************************/
3310 /*                           lcrecord lists                             */
3311 /************************************************************************/
3312
3313 /* Lcrecord lists are used to manage the allocation of particular
3314    sorts of lcrecords, to avoid calling alloc_lcrecord() (and thus
3315    malloc() and garbage-collection junk) as much as possible.
3316    It is similar to the Blocktype class.
3317
3318    It works like this:
3319
3320    1) Create an lcrecord-list object using make_lcrecord_list().
3321       This is often done at initialization.  Remember to staticpro_nodump
3322       this object!  The arguments to make_lcrecord_list() are the
3323       same as would be passed to alloc_lcrecord().
3324    2) Instead of calling alloc_lcrecord(), call allocate_managed_lcrecord()
3325       and pass the lcrecord-list earlier created.
3326    3) When done with the lcrecord, call free_managed_lcrecord().
3327       The standard freeing caveats apply: ** make sure there are no
3328       pointers to the object anywhere! **
3329    4) Calling free_managed_lcrecord() is just like kissing the
3330       lcrecord goodbye as if it were garbage-collected.  This means:
3331       -- the contents of the freed lcrecord are undefined, and the
3332          contents of something produced by allocate_managed_lcrecord()
3333          are undefined, just like for alloc_lcrecord().
3334       -- the mark method for the lcrecord's type will *NEVER* be called
3335          on freed lcrecords.
3336       -- the finalize method for the lcrecord's type will be called
3337          at the time that free_managed_lcrecord() is called.
3338
3339    lcrecord lists do not work in bdwgc mode. -hrop
3340
3341    */
3342
3343 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
3344 static Lisp_Object
3345 mark_lcrecord_list(Lisp_Object obj)
3346 {
3347         return Qnil;
3348 }
3349
3350 /* just imitate the lcrecord spectactular */
3351 Lisp_Object
3352 make_lcrecord_list(size_t size,
3353                    const struct lrecord_implementation *implementation)
3354 {
3355         struct lcrecord_list *p =
3356                 alloc_lcrecord_type(struct lcrecord_list,
3357                                     &lrecord_lcrecord_list);
3358         Lisp_Object val;
3359
3360         p->implementation = implementation;
3361         p->size = size;
3362         p->free = Qnil;
3363         XSETLCRECORD_LIST(val, p);
3364         return val;
3365 }
3366
3367 Lisp_Object
3368 allocate_managed_lcrecord(Lisp_Object lcrecord_list)
3369 {
3370         struct lcrecord_list *list = XLCRECORD_LIST(lcrecord_list);
3371         void *tmp = alloc_lcrecord(list->size, list->implementation);
3372         Lisp_Object val;
3373
3374         XSETOBJ(val, tmp);
3375         return val;
3376 }
3377
3378 void
3379 free_managed_lcrecord(Lisp_Object SXE_UNUSED(lcrecord_list), Lisp_Object lcrecord)
3380 {
3381         struct free_lcrecord_header *free_header =
3382                 (struct free_lcrecord_header*)XPNTR(lcrecord);
3383         struct lrecord_header *lheader = &free_header->lcheader.lheader;
3384         const struct lrecord_implementation *imp =
3385                 LHEADER_IMPLEMENTATION(lheader);
3386
3387         if (imp->finalizer) {
3388                 imp->finalizer(lheader, 0);
3389         }
3390         return;
3391 }
3392
3393 #else  /* !BDWGC */
3394
3395 static Lisp_Object
3396 mark_lcrecord_list(Lisp_Object obj)
3397 {
3398         struct lcrecord_list *list = XLCRECORD_LIST(obj);
3399         Lisp_Object chain = list->free;
3400
3401         while (!NILP(chain)) {
3402                 struct lrecord_header *lheader = XRECORD_LHEADER(chain);
3403                 struct free_lcrecord_header *free_header =
3404                     (struct free_lcrecord_header *)lheader;
3405
3406                 gc_checking_assert(
3407                         /* There should be no other pointers to the free list. */
3408                         !MARKED_RECORD_HEADER_P(lheader)
3409                         &&
3410                         /* Only lcrecords should be here. */
3411                         !LHEADER_IMPLEMENTATION(lheader)->
3412                         basic_p &&
3413                         /* Only free lcrecords should be here. */
3414                         free_header->lcheader.free &&
3415                         /* The type of the lcrecord must be right. */
3416                         LHEADER_IMPLEMENTATION(lheader) ==
3417                         list->implementation &&
3418                         /* So must the size. */
3419                         (LHEADER_IMPLEMENTATION(lheader)->
3420                          static_size == 0
3421                          || LHEADER_IMPLEMENTATION(lheader)->
3422                          static_size == list->size)
3423                         );
3424
3425                 MARK_RECORD_HEADER(lheader);
3426                 chain = free_header->chain;
3427         }
3428
3429         return Qnil;
3430 }
3431
3432 Lisp_Object
3433 make_lcrecord_list(size_t size,
3434                    const struct lrecord_implementation *implementation)
3435 {
3436         struct lcrecord_list *p =
3437                 alloc_lcrecord_type(struct lcrecord_list,
3438                                     &lrecord_lcrecord_list);
3439         Lisp_Object val;
3440
3441         p->implementation = implementation;
3442         p->size = size;
3443         p->free = Qnil;
3444         XSETLCRECORD_LIST(val, p);
3445         return val;
3446 }
3447
3448 Lisp_Object
3449 allocate_managed_lcrecord(Lisp_Object lcrecord_list)
3450 {
3451         struct lcrecord_list *list = XLCRECORD_LIST(lcrecord_list);
3452         if (!NILP(list->free)) {
3453                 Lisp_Object val = list->free;
3454                 struct free_lcrecord_header *free_header =
3455                     (struct free_lcrecord_header *)XPNTR(val);
3456
3457 #ifdef ERROR_CHECK_GC
3458                 struct lrecord_header *lheader = &free_header->lcheader.lheader;
3459
3460                 /* There should be no other pointers to the free list. */
3461                 assert(!MARKED_RECORD_HEADER_P(lheader));
3462                 /* Only lcrecords should be here. */
3463                 assert(!LHEADER_IMPLEMENTATION(lheader)->basic_p);
3464                 /* Only free lcrecords should be here. */
3465                 assert(free_header->lcheader.free);
3466                 /* The type of the lcrecord must be right. */
3467                 assert(LHEADER_IMPLEMENTATION(lheader) == list->implementation);
3468                 /* So must the size. */
3469                 assert(LHEADER_IMPLEMENTATION(lheader)->static_size == 0 ||
3470                        LHEADER_IMPLEMENTATION(lheader)->static_size ==
3471                        list->size);
3472 #endif                          /* ERROR_CHECK_GC */
3473
3474                 list->free = free_header->chain;
3475                 free_header->lcheader.free = 0;
3476                 return val;
3477         } else {
3478                 void *tmp = alloc_lcrecord(list->size, list->implementation);
3479                 Lisp_Object val;
3480
3481                 XSETOBJ(val, tmp);
3482                 return val;
3483         }
3484 }
3485
3486 void
3487 free_managed_lcrecord(Lisp_Object lcrecord_list, Lisp_Object lcrecord)
3488 {
3489         struct lcrecord_list *list = XLCRECORD_LIST(lcrecord_list);
3490         struct free_lcrecord_header *free_header =
3491                 (struct free_lcrecord_header*)XPNTR(lcrecord);
3492         struct lrecord_header *lheader = &free_header->lcheader.lheader;
3493         const struct lrecord_implementation *implementation
3494             = LHEADER_IMPLEMENTATION(lheader);
3495
3496         /* Make sure the size is correct.  This will catch, for example,
3497            putting a window configuration on the wrong free list. */
3498         gc_checking_assert((implementation->size_in_bytes_method ?
3499                             implementation->size_in_bytes_method(lheader) :
3500                             implementation->static_size)
3501                            == list->size);
3502
3503         if (implementation->finalizer) {
3504                 implementation->finalizer(lheader, 0);
3505         }
3506         free_header->chain = list->free;
3507         free_header->lcheader.free = 1;
3508         list->free = lcrecord;
3509 }
3510 #endif  /* BDWGC */
3511
3512 DEFINE_LRECORD_IMPLEMENTATION("lcrecord-list", lcrecord_list,
3513                               mark_lcrecord_list, internal_object_printer,
3514                               0, 0, 0, 0, struct lcrecord_list);
3515
3516 \f
3517 DEFUN("purecopy", Fpurecopy, 1, 1, 0,   /*
3518 Kept for compatibility, returns its argument.
3519 Old:
3520 Make a copy of OBJECT in pure storage.
3521 Recursively copies contents of vectors and cons cells.
3522 Does not copy symbols.
3523 */
3524       (object))
3525 {
3526         return object;
3527 }
3528 \f
3529 /************************************************************************/
3530 /*                         Garbage Collection                           */
3531 /************************************************************************/
3532
3533 /* All the built-in lisp object types are enumerated in `enum lrecord_type'.
3534    Additional ones may be defined by a module (none yet).  We leave some
3535    room in `lrecord_implementations_table' for such new lisp object types. */
3536 const struct lrecord_implementation
3537     *lrecord_implementations_table[(unsigned int)lrecord_type_last_built_in_type
3538                                    + MODULE_DEFINABLE_TYPE_COUNT];
3539 unsigned int lrecord_type_count = (unsigned int)lrecord_type_last_built_in_type;
3540 /* Object marker functions are in the lrecord_implementation structure.
3541    But copying them to a parallel array is much more cache-friendly.
3542    This hack speeds up (garbage-collect) by about 5%. */
3543 Lisp_Object(*lrecord_markers[countof(lrecord_implementations_table)])
3544     (Lisp_Object);
3545
3546 #ifndef EF_USE_ASYNEQ
3547 struct gcpro *gcprolist;
3548 #endif
3549
3550 /* We want the staticpros relocated, but not the pointers found therein.
3551    Hence we use a trivial description, as for pointerless objects. */
3552 static const struct lrecord_description staticpro_description_1[] = {
3553         {XD_END}
3554 };
3555
3556 static const struct struct_description staticpro_description = {
3557         sizeof(Lisp_Object *),
3558         staticpro_description_1
3559 };
3560
3561 static const struct lrecord_description staticpros_description_1[] = {
3562         XD_DYNARR_DESC(Lisp_Object_ptr_dynarr, &staticpro_description),
3563         {XD_END}
3564 };
3565
3566 static const struct struct_description staticpros_description = {
3567         sizeof(Lisp_Object_ptr_dynarr),
3568         staticpros_description_1
3569 };
3570
3571 Lisp_Object_ptr_dynarr *staticpros;
3572
3573 /* Mark the Lisp_Object at non-heap VARADDRESS as a root object for
3574    garbage collection, and for dumping. */
3575 void staticpro(Lisp_Object * varaddress)
3576 {
3577         lock_allocator();
3578         Dynarr_add(staticpros, varaddress);
3579         dump_add_root_object(varaddress);
3580         unlock_allocator();
3581 }
3582
3583 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
3584 Lisp_Object_ptr_dynarr *staticpros_nodump;
3585
3586 /* Mark the Lisp_Object at non-heap VARADDRESS as a root object for
3587    garbage collection, but not for dumping. */
3588 void staticpro_nodump(Lisp_Object * varaddress)
3589 {
3590         lock_allocator();
3591         Dynarr_add(staticpros_nodump, varaddress);
3592         unlock_allocator();
3593 }
3594 #endif  /* !BDWGC */
3595
3596
3597 #ifdef ERROR_CHECK_GC
3598 #define GC_CHECK_LHEADER_INVARIANTS(lheader)                            \
3599         do {                                                            \
3600                 struct lrecord_header * GCLI_lh = (lheader);            \
3601                 assert (GCLI_lh != 0);                                  \
3602                 assert (GCLI_lh->type < lrecord_type_count);            \
3603                 assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) ||       \
3604                         (MARKED_RECORD_HEADER_P (GCLI_lh) &&            \
3605                          LISP_READONLY_RECORD_HEADER_P (GCLI_lh)));     \
3606         } while (0)
3607 #else
3608 #define GC_CHECK_LHEADER_INVARIANTS(lheader)
3609 #endif
3610 \f
3611 /* Mark reference to a Lisp_Object.  If the object referred to has not been
3612    seen yet, recursively mark all the references contained in it. */
3613
3614 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
3615 void mark_object(Lisp_Object SXE_UNUSED(obj))
3616 {
3617         return;
3618 }
3619
3620 #else  /* !BDWGC */
3621 void mark_object(Lisp_Object obj)
3622 {
3623         if (obj == Qnull_pointer) {
3624                 return;
3625         }
3626
3627 tail_recurse:
3628         /* Checks we used to perform */
3629         /* if (EQ (obj, Qnull_pointer)) return; */
3630         /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */
3631         /* if (PURIFIED (XPNTR (obj))) return; */
3632
3633         if (XTYPE(obj) == Lisp_Type_Record) {
3634                 struct lrecord_header *lheader = XRECORD_LHEADER(obj);
3635
3636                 GC_CHECK_LHEADER_INVARIANTS(lheader);
3637
3638                 gc_checking_assert(LHEADER_IMPLEMENTATION(lheader)->basic_p ||
3639                                    !((struct lcrecord_header *)lheader)->free);
3640
3641                 /* All c_readonly objects have their mark bit set,
3642                    so that we only need to check the mark bit here. */
3643                 if (!MARKED_RECORD_HEADER_P(lheader)) {
3644                         MARK_RECORD_HEADER(lheader);
3645
3646                         if (RECORD_MARKER(lheader)) {
3647                                 obj = RECORD_MARKER(lheader) (obj);
3648                                 if (!NILP(obj))
3649                                         goto tail_recurse;
3650                         }
3651                 }
3652         }
3653 }
3654 #endif  /* BDWGC */
3655
3656 /* mark all of the conses in a list and mark the final cdr; but
3657    DO NOT mark the cars.
3658
3659    Use only for internal lists!  There should never be other pointers
3660    to the cons cells, because if so, the cars will remain unmarked
3661    even when they maybe should be marked. */
3662 void mark_conses_in_list(Lisp_Object obj)
3663 {
3664         Lisp_Object rest;
3665
3666         for (rest = obj; CONSP(rest); rest = XCDR(rest)) {
3667                 if (CONS_MARKED_P(XCONS(rest)))
3668                         return;
3669                 MARK_CONS(XCONS(rest));
3670         }
3671
3672         mark_object(rest);
3673 }
3674 \f
3675 /* Find all structures not marked, and free them. */
3676
3677 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
3678 static int gc_count_num_bit_vector_used, gc_count_bit_vector_total_size;
3679 static int gc_count_bit_vector_storage;
3680 static int gc_count_num_short_string_in_use;
3681 static int gc_count_string_total_size;
3682 static int gc_count_short_string_total_size;
3683 #endif  /* !BDWGC */
3684
3685 /* static int gc_count_total_records_used, gc_count_records_total_size; */
3686 \f
3687 /* stats on lcrecords in use - kinda kludgy */
3688
3689 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
3690 static struct {
3691         int instances_in_use;
3692         int bytes_in_use;
3693         int instances_freed;
3694         int bytes_freed;
3695         int instances_on_free_list;
3696 } lcrecord_stats[countof(lrecord_implementations_table)
3697                  + MODULE_DEFINABLE_TYPE_COUNT];
3698 #endif  /* !BDWGC */
3699
3700 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
3701 static void tick_lcrecord_stats(const struct lrecord_header *h, int free_p)
3702 {
3703         unsigned int type_index = h->type;
3704
3705         if (((const struct lcrecord_header *)h)->free) {
3706                 gc_checking_assert(!free_p);
3707                 lcrecord_stats[type_index].instances_on_free_list++;
3708         } else {
3709                 const struct lrecord_implementation *implementation =
3710                     LHEADER_IMPLEMENTATION(h);
3711
3712                 size_t sz = (implementation->size_in_bytes_method ?
3713                              implementation->size_in_bytes_method(h) :
3714                              implementation->static_size);
3715                 if (free_p) {
3716                         lcrecord_stats[type_index].instances_freed++;
3717                         lcrecord_stats[type_index].bytes_freed += sz;
3718                 } else {
3719                         lcrecord_stats[type_index].instances_in_use++;
3720                         lcrecord_stats[type_index].bytes_in_use += sz;
3721                 }
3722         }
3723 }
3724 #endif  /* !BDWGC */
3725 \f
3726 /* Free all unmarked records */
3727 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
3728 static void 
3729 sweep_lcrecords_1(struct lcrecord_header *volatile*prev, int *used)
3730 {
3731         int num_used = 0;
3732         /* int total_size = 0; */
3733
3734         xzero(lcrecord_stats);  /* Reset all statistics to 0. */
3735
3736         /* First go through and call all the finalize methods.
3737            Then go through and free the objects.  There used to
3738            be only one loop here, with the call to the finalizer
3739            occurring directly before the xfree() below.  That
3740            is marginally faster but much less safe -- if the
3741            finalize method for an object needs to reference any
3742            other objects contained within it (and many do),
3743            we could easily be screwed by having already freed that
3744            other object. */
3745
3746         for (struct lcrecord_header *volatile header = *prev;
3747              header; header = header->next) {
3748                 struct lrecord_header *h = &(header->lheader);
3749
3750                 GC_CHECK_LHEADER_INVARIANTS(h);
3751
3752                 if (!MARKED_RECORD_HEADER_P(h) && !header->free) {
3753                         if (LHEADER_IMPLEMENTATION(h)->finalizer)
3754                                 LHEADER_IMPLEMENTATION(h)->finalizer(h, 0);
3755                 }
3756         }
3757
3758         for (struct lcrecord_header *volatile header = *prev; header;) {
3759                 struct lrecord_header *volatile h = &(header->lheader);
3760                 if (MARKED_RECORD_HEADER_P(h)) {
3761                         if (!C_READONLY_RECORD_HEADER_P(h))
3762                                 UNMARK_RECORD_HEADER(h);
3763                         num_used++;
3764                         /* total_size += n->implementation->size_in_bytes (h); */
3765                         /* #### May modify header->next on a C_READONLY lcrecord */
3766                         prev = &(header->next);
3767                         header = *prev;
3768                         tick_lcrecord_stats(h, 0);
3769                 } else {
3770                         struct lcrecord_header *next = header->next;
3771                         *prev = next;
3772                         tick_lcrecord_stats(h, 1);
3773                         /* used to call finalizer right here. */
3774                         xfree(header);
3775                         header = next;
3776                 }
3777         }
3778         *used = num_used;
3779         /* *total = total_size; */
3780         return;
3781 }
3782
3783 static void
3784 sweep_bit_vectors_1(Lisp_Object * prev, int *used, int *total, int *storage)
3785 {
3786         Lisp_Object bit_vector;
3787         int num_used = 0;
3788         int total_size = 0;
3789         int total_storage = 0;
3790
3791         /* BIT_VECTORP fails because the objects are marked, which changes
3792            their implementation */
3793         for (bit_vector = *prev; !EQ(bit_vector, Qzero);) {
3794                 Lisp_Bit_Vector *v = XBIT_VECTOR(bit_vector);
3795                 int len = v->size;
3796                 if (MARKED_RECORD_P(bit_vector)) {
3797                         if (!C_READONLY_RECORD_HEADER_P(&(v->lheader)))
3798                                 UNMARK_RECORD_HEADER(&(v->lheader));
3799                         total_size += len;
3800                         total_storage +=
3801                             MALLOC_OVERHEAD +
3802                             FLEXIBLE_ARRAY_STRUCT_SIZEOF(Lisp_Bit_Vector,
3803                                                          unsigned long, bits,
3804                                                          BIT_VECTOR_LONG_STORAGE
3805                                                          (len));
3806                         num_used++;
3807                         /* #### May modify next on a C_READONLY bitvector */
3808                         prev = &(bit_vector_next(v));
3809                         bit_vector = *prev;
3810                 } else {
3811                         Lisp_Object next = bit_vector_next(v);
3812                         *prev = next;
3813                         xfree(v);
3814                         bit_vector = next;
3815                 }
3816         }
3817         *used = num_used;
3818         *total = total_size;
3819         *storage = total_storage;
3820 }
3821 #endif  /* !BDWGC */
3822
3823 /* And the Lord said: Thou shalt use the `c-backslash-region' command
3824    to make macros prettier. */
3825
3826 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
3827 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type)
3828
3829 #elif defined ERROR_CHECK_GC
3830
3831 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type)                      \
3832         do {                                                            \
3833                 struct typename##_block *SFTB_current;                  \
3834                 int SFTB_limit;                                         \
3835                 int num_free = 0, num_used = 0;                         \
3836                                                                         \
3837                 for (SFTB_current = current_##typename##_block,         \
3838                              SFTB_limit = current_##typename##_block_index; \
3839                      SFTB_current;                                      \
3840                         ) {                                             \
3841                         int SFTB_iii;                                   \
3842                                                                         \
3843                         for (SFTB_iii = 0;                              \
3844                              SFTB_iii < SFTB_limit;                     \
3845                              SFTB_iii++) {                              \
3846                                 obj_type *SFTB_victim =                 \
3847                                         &(SFTB_current->block[SFTB_iii]); \
3848                                                                         \
3849                                 if (LRECORD_FREE_P (SFTB_victim)) {     \
3850                                         num_free++;                     \
3851                                 } else if (C_READONLY_RECORD_HEADER_P   \
3852                                            (&SFTB_victim->lheader)) {   \
3853                                         num_used++;                     \
3854                                 } else if (!MARKED_RECORD_HEADER_P      \
3855                                            (&SFTB_victim->lheader)) {   \
3856                                         num_free++;                     \
3857                                         FREE_FIXED_TYPE(typename, obj_type, \
3858                                                         SFTB_victim);   \
3859                                 } else {                                \
3860                                         num_used++;                     \
3861                                         UNMARK_##typename(SFTB_victim); \
3862                                 }                                       \
3863                         }                                               \
3864                         SFTB_current = SFTB_current->prev;              \
3865                         SFTB_limit = countof(current_##typename##_block \
3866                                              ->block);                  \
3867                 }                                                       \
3868                                                                         \
3869                 gc_count_num_##typename##_in_use = num_used;            \
3870                 gc_count_num_##typename##_freelist = num_free;          \
3871         } while (0)
3872
3873 #else  /* !ERROR_CHECK_GC, !BDWGC*/
3874
3875 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type)                      \
3876         do {                                                            \
3877                 struct typename##_block *SFTB_current;                  \
3878                 struct typename##_block **SFTB_prev;                    \
3879                 int SFTB_limit;                                         \
3880                 int num_free = 0, num_used = 0;                         \
3881                                                                         \
3882                 typename##_free_list = 0;                               \
3883                                                                         \
3884                 for (SFTB_prev = &current_##typename##_block,           \
3885                              SFTB_current = current_##typename##_block, \
3886                              SFTB_limit = current_##typename##_block_index; \
3887                      SFTB_current;                                      \
3888                         ) {                                                     \
3889                         int SFTB_iii;                                   \
3890                         int SFTB_empty = 1;                             \
3891                         Lisp_Free *SFTB_old_free_list =                 \
3892                                 typename##_free_list;                   \
3893                                                                         \
3894                         for (SFTB_iii = 0; SFTB_iii < SFTB_limit;       \
3895                              SFTB_iii++) {                              \
3896                                 obj_type *SFTB_victim =                 \
3897                                         &(SFTB_current->block[SFTB_iii]); \
3898                                                                         \
3899                                 if (LRECORD_FREE_P (SFTB_victim)) {     \
3900                                         num_free++;                     \
3901                                         PUT_FIXED_TYPE_ON_FREE_LIST     \
3902                                                 (typename, obj_type,    \
3903                                                  SFTB_victim);          \
3904                                 } else if (C_READONLY_RECORD_HEADER_P   \
3905                                            (&SFTB_victim->lheader)) {   \
3906                                         SFTB_empty = 0;                 \
3907                                         num_used++;                     \
3908                                 } else if (! MARKED_RECORD_HEADER_P     \
3909                                            (&SFTB_victim->lheader)) {   \
3910                                         num_free++;                     \
3911                                         FREE_FIXED_TYPE(typename, obj_type, \
3912                                                         SFTB_victim);   \
3913                                 } else {                                \
3914                                         SFTB_empty = 0;                 \
3915                                         num_used++;                     \
3916                                         UNMARK_##typename (SFTB_victim); \
3917                                 }                                       \
3918                         }                                               \
3919                         if (!SFTB_empty) {                              \
3920                                 SFTB_prev = &(SFTB_current->prev);      \
3921                                 SFTB_current = SFTB_current->prev;      \
3922                         } else if (SFTB_current == current_##typename##_block \
3923                                    && !SFTB_current->prev) {            \
3924                                 /* No real point in freeing sole        \
3925                                  * allocation block */                  \
3926                                 break;                                  \
3927                         } else {                                        \
3928                                 struct typename##_block *SFTB_victim_block = \
3929                                         SFTB_current;                   \
3930                                 if (SFTB_victim_block ==                \
3931                                     current_##typename##_block) {       \
3932                                         current_##typename##_block_index \
3933                                                 = countof               \
3934                                                 (current_##typename##_block \
3935                                                  ->block);              \
3936                                 }                                       \
3937                                 SFTB_current = SFTB_current->prev;      \
3938                                 {                                       \
3939                                         *SFTB_prev = SFTB_current;      \
3940                                         xfree(SFTB_victim_block);       \
3941                                         /* Restore free list to what it was \
3942                                            before victim was swept */   \
3943                                         typename##_free_list =          \
3944                                                 SFTB_old_free_list;     \
3945                                         num_free -= SFTB_limit;         \
3946                                 }                                       \
3947                         }                                               \
3948                         SFTB_limit = countof (current_##typename##_block \
3949                                               ->block);                 \
3950                 }                                                       \
3951                                                                         \
3952                 gc_count_num_##typename##_in_use = num_used;            \
3953                 gc_count_num_##typename##_freelist = num_free;          \
3954         } while (0)
3955
3956 #endif  /* !ERROR_CHECK_GC */
3957 \f
3958 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
3959 static void sweep_conses(void)
3960 {
3961 #define UNMARK_cons(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3962 #define ADDITIONAL_FREE_cons(ptr)
3963
3964         SWEEP_FIXED_TYPE_BLOCK(cons, Lisp_Cons);
3965 }
3966 #endif  /* !BDWGC */
3967
3968 /* Explicitly free a cons cell.  */
3969 void free_cons(Lisp_Cons * ptr)
3970 {
3971 #ifdef ERROR_CHECK_GC
3972         /* If the CAR is not an int, then it will be a pointer, which will
3973            always be four-byte aligned.  If this cons cell has already been
3974            placed on the free list, however, its car will probably contain
3975            a chain pointer to the next cons on the list, which has cleverly
3976            had all its 0's and 1's inverted.  This allows for a quick
3977            check to make sure we're not freeing something already freed. */
3978         if (POINTER_TYPE_P(XTYPE(ptr->car)))
3979                 ASSERT_VALID_POINTER(XPNTR(ptr->car));
3980 #endif                          /* ERROR_CHECK_GC */
3981
3982 #ifndef ALLOC_NO_POOLS
3983         FREE_FIXED_TYPE_WHEN_NOT_IN_GC(cons, Lisp_Cons, ptr);
3984 #endif                          /* ALLOC_NO_POOLS */
3985 }
3986
3987 /* explicitly free a list.  You **must make sure** that you have
3988    created all the cons cells that make up this list and that there
3989    are no pointers to any of these cons cells anywhere else.  If there
3990    are, you will lose. */
3991
3992 void free_list(Lisp_Object list)
3993 {
3994         Lisp_Object rest, next;
3995
3996         for (rest = list; !NILP(rest); rest = next) {
3997                 next = XCDR(rest);
3998                 free_cons(XCONS(rest));
3999         }
4000 }
4001
4002 /* explicitly free an alist.  You **must make sure** that you have
4003    created all the cons cells that make up this alist and that there
4004    are no pointers to any of these cons cells anywhere else.  If there
4005    are, you will lose. */
4006
4007 void free_alist(Lisp_Object alist)
4008 {
4009         Lisp_Object rest, next;
4010
4011         for (rest = alist; !NILP(rest); rest = next) {
4012                 next = XCDR(rest);
4013                 free_cons(XCONS(XCAR(rest)));
4014                 free_cons(XCONS(rest));
4015         }
4016 }
4017
4018 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
4019 static void sweep_compiled_functions(void)
4020 {
4021 #define UNMARK_compiled_function(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4022 #define ADDITIONAL_FREE_compiled_function(ptr)
4023
4024         SWEEP_FIXED_TYPE_BLOCK(compiled_function, Lisp_Compiled_Function);
4025 }
4026
4027 #ifdef HAVE_FPFLOAT
4028 static void sweep_floats(void)
4029 {
4030 #define UNMARK_float(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4031 #define ADDITIONAL_FREE_float(ptr)
4032
4033         SWEEP_FIXED_TYPE_BLOCK(float, Lisp_Float);
4034 }
4035 #endif  /* HAVE_FPFLOAT */
4036
4037 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
4038 static void
4039 sweep_bigzs (void)
4040 {
4041 #define UNMARK_bigz(ptr) UNMARK_RECORD_HEADER(&((ptr)->lheader))
4042 #define ADDITIONAL_FREE_bigz(ptr) bigz_fini(ptr->data)
4043
4044         SWEEP_FIXED_TYPE_BLOCK(bigz, Lisp_Bigz);
4045 }
4046 #endif /* HAVE_MPZ */
4047
4048 #if defined HAVE_MPQ && defined WITH_GMP
4049 static void
4050 sweep_bigqs (void)
4051 {
4052 #define UNMARK_bigq(ptr) UNMARK_RECORD_HEADER(&((ptr)->lheader))
4053 #define ADDITIONAL_FREE_bigq(ptr) bigq_fini(ptr->data)
4054         
4055         SWEEP_FIXED_TYPE_BLOCK(bigq, Lisp_Bigq);
4056 }
4057 #endif /* HAVE_MPQ */
4058
4059 #if defined HAVE_MPF && defined WITH_GMP
4060 static void
4061 sweep_bigfs (void)
4062 {
4063 #define UNMARK_bigf(ptr) UNMARK_RECORD_HEADER(&((ptr)->lheader))
4064 #define ADDITIONAL_FREE_bigf(ptr) bigf_fini(ptr->data)
4065         
4066         SWEEP_FIXED_TYPE_BLOCK(bigf, Lisp_Bigf);
4067 }
4068 #endif  /* HAVE_MPF */
4069
4070 #if defined HAVE_MPFR && defined WITH_MPFR
4071 static void
4072 sweep_bigfrs (void)
4073 {
4074 #define UNMARK_bigfr(ptr) UNMARK_RECORD_HEADER(&((ptr)->lheader))
4075 #define ADDITIONAL_FREE_bigfr(ptr) bigfr_fini(ptr->data)
4076         
4077         SWEEP_FIXED_TYPE_BLOCK(bigfr, Lisp_Bigfr);
4078 }
4079 #endif  /* HAVE_MPFR */
4080
4081 #if defined HAVE_PSEUG && defined WITH_PSEUG
4082 static void
4083 sweep_biggs (void)
4084 {
4085 #define UNMARK_bigg(ptr) UNMARK_RECORD_HEADER(&((ptr)->lheader))
4086 #define ADDITIONAL_FREE_bigg(ptr) bigg_fini(ptr->data)
4087         
4088         SWEEP_FIXED_TYPE_BLOCK(bigg, Lisp_Bigg);
4089 }
4090 #endif  /* HAVE_PSEUG */
4091
4092 #if defined HAVE_MPC && defined WITH_MPC ||     \
4093         defined HAVE_PSEUC && defined WITH_PSEUC
4094 static void
4095 sweep_bigcs (void)
4096 {
4097 #define UNMARK_bigc(ptr) UNMARK_RECORD_HEADER(&((ptr)->lheader))
4098 #define ADDITIONAL_FREE_bigc(ptr) bigc_fini(ptr->data)
4099         
4100         SWEEP_FIXED_TYPE_BLOCK(bigc, Lisp_Bigc);
4101 }
4102 #endif  /* HAVE_MPC */
4103
4104 #if defined HAVE_QUATERN && defined HAVE_MPZ && defined WITH_QUATERN
4105 static void
4106 sweep_quaterns (void)
4107 {
4108 #define UNMARK_quatern(ptr) UNMARK_RECORD_HEADER(&((ptr)->lheader))
4109 #define ADDITIONAL_FREE_quatern(ptr) quatern_fini(ptr->data)
4110         
4111         SWEEP_FIXED_TYPE_BLOCK(quatern, Lisp_Quatern);
4112 }
4113 #endif  /* HAVE_QUATERN */
4114
4115 static void
4116 sweep_dynacats(void)
4117 {
4118 #define UNMARK_dynacat(ptr) UNMARK_RECORD_HEADER(&((ptr)->lheader))
4119 #define ADDITIONAL_FREE_dynacat(ptr) dynacat_fini(ptr);
4120
4121         SWEEP_FIXED_TYPE_BLOCK(dynacat, struct dynacat_s);
4122 }
4123
4124 static void sweep_symbols(void)
4125 {
4126 #define UNMARK_symbol(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4127 #define ADDITIONAL_FREE_symbol(ptr)
4128
4129         SWEEP_FIXED_TYPE_BLOCK(symbol, Lisp_Symbol);
4130 }
4131
4132 static void sweep_extents(void)
4133 {
4134 #define UNMARK_extent(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4135 #define ADDITIONAL_FREE_extent(ptr)
4136
4137         SWEEP_FIXED_TYPE_BLOCK(extent, struct extent);
4138 }
4139
4140 static void sweep_events(void)
4141 {
4142 #define UNMARK_event(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4143 #define ADDITIONAL_FREE_event(ptr)
4144
4145         SWEEP_FIXED_TYPE_BLOCK(event, Lisp_Event);
4146 }
4147
4148 static void sweep_markers(void)
4149 {
4150 #define UNMARK_marker(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4151 #define ADDITIONAL_FREE_marker(ptr)                                     \
4152   do { Lisp_Object tem;                                                 \
4153        XSETMARKER (tem, ptr);                                           \
4154        unchain_marker (tem);                                            \
4155      } while (0)
4156
4157         SWEEP_FIXED_TYPE_BLOCK(marker, Lisp_Marker);
4158 }
4159 #endif  /* !BDWGC */
4160
4161 /* Explicitly free a marker.  */
4162 void free_marker(Lisp_Marker * ptr)
4163 {
4164         /* Perhaps this will catch freeing an already-freed marker. */
4165         gc_checking_assert(ptr->lheader.type == lrecord_type_marker);
4166
4167 #ifndef ALLOC_NO_POOLS
4168         FREE_FIXED_TYPE_WHEN_NOT_IN_GC(marker, Lisp_Marker, ptr);
4169 #endif                          /* ALLOC_NO_POOLS */
4170 }
4171 \f
4172 #if defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY)
4173
4174 static void verify_string_chars_integrity(void)
4175 {
4176         struct string_chars_block *sb;
4177
4178         /* Scan each existing string block sequentially, string by string.  */
4179         for (sb = first_string_chars_block; sb; sb = sb->next) {
4180                 int pos = 0;
4181                 /* POS is the index of the next string in the block.  */
4182                 while (pos < sb->pos) {
4183                         struct string_chars *s_chars =
4184                             (struct string_chars *)&(sb->string_chars[pos]);
4185                         Lisp_String *string;
4186                         int size;
4187                         int fullsize;
4188
4189                         /* If the string_chars struct is marked as free (i.e. the
4190                            STRING pointer is NULL) then this is an unused chunk of
4191                            string storage. (See below.) */
4192
4193                         if (STRING_CHARS_FREE_P(s_chars)) {
4194                                 fullsize =
4195                                     ((struct unused_string_chars *)s_chars)->
4196                                     fullsize;
4197                                 pos += fullsize;
4198                                 continue;
4199                         }
4200
4201                         string = s_chars->string;
4202                         /* Must be 32-bit aligned. */
4203                         assert((((int)string) & 3) == 0);
4204
4205                         size = string_length(string);
4206                         fullsize = STRING_FULLSIZE(size);
4207
4208                         assert(!BIG_STRING_FULLSIZE_P(fullsize));
4209                         assert(string_data(string) == s_chars->chars);
4210                         pos += fullsize;
4211                 }
4212                 assert(pos == sb->pos);
4213         }
4214 }
4215
4216 #endif                          /* MULE && ERROR_CHECK_GC */
4217
4218 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
4219 /* Compactify string chars, relocating the reference to each --
4220    free any empty string_chars_block we see. */
4221 static void compact_string_chars(void)
4222 {
4223         struct string_chars_block *to_sb = first_string_chars_block;
4224         int to_pos = 0;
4225         struct string_chars_block *from_sb;
4226
4227         /* Scan each existing string block sequentially, string by string.  */
4228         for (from_sb = first_string_chars_block; from_sb;
4229              from_sb = from_sb->next) {
4230                 int from_pos = 0;
4231                 /* FROM_POS is the index of the next string in the block.  */
4232                 while (from_pos < from_sb->pos) {
4233                         struct string_chars *from_s_chars =
4234                             (struct string_chars *)&(from_sb->
4235                                                      string_chars[from_pos]);
4236                         struct string_chars *to_s_chars;
4237                         Lisp_String *string;
4238                         int size;
4239                         int fullsize;
4240
4241                         /* If the string_chars struct is marked as free (i.e. the
4242                            STRING pointer is NULL) then this is an unused chunk of
4243                            string storage.  This happens under Mule when a string's
4244                            size changes in such a way that its fullsize changes.
4245                            (Strings can change size because a different-length
4246                            character can be substituted for another character.)
4247                            In this case, after the bogus string pointer is the
4248                            "fullsize" of this entry, i.e. how many bytes to skip. */
4249
4250                         if (STRING_CHARS_FREE_P(from_s_chars)) {
4251                                 fullsize =
4252                                     ((struct unused_string_chars *)
4253                                      from_s_chars)->fullsize;
4254                                 from_pos += fullsize;
4255                                 continue;
4256                         }
4257
4258                         string = from_s_chars->string;
4259                         assert(!(LRECORD_FREE_P(string)));
4260
4261                         size = string_length(string);
4262                         fullsize = STRING_FULLSIZE(size);
4263
4264                         gc_checking_assert(!BIG_STRING_FULLSIZE_P(fullsize));
4265
4266                         /* Just skip it if it isn't marked.  */
4267                         if (!MARKED_RECORD_HEADER_P(&(string->lheader))) {
4268                                 from_pos += fullsize;
4269                                 continue;
4270                         }
4271
4272                         /* If it won't fit in what's left of TO_SB, close TO_SB
4273                            out and go on to the next string_chars_block.  We
4274                            know that TO_SB cannot advance past FROM_SB here
4275                            since FROM_SB is large enough to currently contain
4276                            this string. */
4277                         if ((to_pos + fullsize) >
4278                             countof(to_sb->string_chars)) {
4279                                 to_sb->pos = to_pos;
4280                                 to_sb = to_sb->next;
4281                                 to_pos = 0;
4282                         }
4283
4284                         /* Compute new address of this string
4285                            and update TO_POS for the space being used.  */
4286                         to_s_chars =
4287                             (struct string_chars *)&(to_sb->
4288                                                      string_chars[to_pos]);
4289
4290                         /* Copy the string_chars to the new place.  */
4291                         if (from_s_chars != to_s_chars)
4292                                 memmove(to_s_chars, from_s_chars, fullsize);
4293
4294                         /* Relocate FROM_S_CHARS's reference */
4295                         set_string_data(string, &(to_s_chars->chars[0]));
4296
4297                         from_pos += fullsize;
4298                         to_pos += fullsize;
4299                 }
4300         }
4301
4302         /* Set current to the last string chars block still used and
4303            free any that follow. */
4304         for (volatile struct string_chars_block *victim = to_sb->next;
4305              victim;) {
4306                 volatile struct string_chars_block *tofree = victim;
4307                 victim = victim->next;
4308                 xfree(tofree);
4309         }
4310
4311         current_string_chars_block = to_sb;
4312         current_string_chars_block->pos = to_pos;
4313         current_string_chars_block->next = 0;
4314 }
4315
4316 static int debug_string_purity;
4317
4318 static void debug_string_purity_print(Lisp_String * p)
4319 {
4320         Charcount i;
4321         Charcount s = string_char_length(p);
4322         stderr_out("\"");
4323         for (i = 0; i < s; i++) {
4324                 Emchar ch = string_char(p, i);
4325                 if (ch < 32 || ch >= 126)
4326                         stderr_out("\\%03o", ch);
4327                 else if (ch == '\\' || ch == '\"')
4328                         stderr_out("\\%c", ch);
4329                 else
4330                         stderr_out("%c", ch);
4331         }
4332         stderr_out("\"\n");
4333 }
4334 #endif  /* !BDWGC */
4335
4336 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
4337 static void sweep_strings(void)
4338 {
4339         int num_small_used = 0, num_small_bytes = 0, num_bytes = 0;
4340         int debug = debug_string_purity;
4341
4342 #define UNMARK_string(ptr)                              \
4343         do {                                            \
4344                 Lisp_String *p = (ptr);                 \
4345                 size_t size = string_length (p);        \
4346                 UNMARK_RECORD_HEADER (&(p->lheader));   \
4347                 num_bytes += size;                      \
4348                 if (!BIG_STRING_SIZE_P (size)) {        \
4349                         num_small_bytes += size;        \
4350                         num_small_used++;               \
4351                 }                                       \
4352                 if (debug)                              \
4353                         debug_string_purity_print (p);  \
4354         } while (0)
4355 #define ADDITIONAL_FREE_string(ptr)                     \
4356         do {                                            \
4357                 size_t size = string_length (ptr);      \
4358                 if (BIG_STRING_SIZE_P(size)) {          \
4359                         yfree(ptr->data);               \
4360                 }                                       \
4361         } while (0)
4362
4363         SWEEP_FIXED_TYPE_BLOCK(string, Lisp_String);
4364
4365         gc_count_num_short_string_in_use = num_small_used;
4366         gc_count_string_total_size = num_bytes;
4367         gc_count_short_string_total_size = num_small_bytes;
4368 }
4369 #endif  /* !BDWGC */
4370
4371 /* I hate duplicating all this crap! */
4372 int marked_p(Lisp_Object obj)
4373 {
4374         /* Checks we used to perform. */
4375         /* if (EQ (obj, Qnull_pointer)) return 1; */
4376         /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */
4377         /* if (PURIFIED (XPNTR (obj))) return 1; */
4378
4379         if (XTYPE(obj) == Lisp_Type_Record) {
4380                 struct lrecord_header *lheader = XRECORD_LHEADER(obj);
4381
4382                 GC_CHECK_LHEADER_INVARIANTS(lheader);
4383
4384                 return MARKED_RECORD_HEADER_P(lheader);
4385         }
4386         return 1;
4387 }
4388
4389 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
4390 static void gc_sweep(void)
4391 {
4392         /* Free all unmarked records.  Do this at the very beginning,
4393            before anything else, so that the finalize methods can safely
4394            examine items in the objects.  sweep_lcrecords_1() makes
4395            sure to call all the finalize methods *before* freeing anything,
4396            to complete the safety. */
4397         {
4398                 int ignored;
4399                 sweep_lcrecords_1(&all_lcrecords, &ignored);
4400         }
4401
4402         compact_string_chars();
4403
4404         /* Finalize methods below (called through the ADDITIONAL_FREE_foo
4405            macros) must be *extremely* careful to make sure they're not
4406            referencing freed objects.  The only two existing finalize
4407            methods (for strings and markers) pass muster -- the string
4408            finalizer doesn't look at anything but its own specially-
4409            created block, and the marker finalizer only looks at live
4410            buffers (which will never be freed) and at the markers before
4411            and after it in the chain (which, by induction, will never be
4412            freed because if so, they would have already removed themselves
4413            from the chain). */
4414
4415         /* Put all unmarked strings on free list, free'ing the string chars
4416            of large unmarked strings */
4417         sweep_strings();
4418
4419         /* Put all unmarked conses on free list */
4420         sweep_conses();
4421
4422         /* Free all unmarked bit vectors */
4423         sweep_bit_vectors_1(&all_bit_vectors,
4424                             &gc_count_num_bit_vector_used,
4425                             &gc_count_bit_vector_total_size,
4426                             &gc_count_bit_vector_storage);
4427
4428         /* Free all unmarked compiled-function objects */
4429         sweep_compiled_functions();
4430
4431 #ifdef HAVE_FPFLOAT
4432         /* Put all unmarked floats on free list */
4433         sweep_floats();
4434 #endif  /* HAVE_FPFLOAT */
4435
4436 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
4437         /* Put all unmarked bignums on free list */
4438         sweep_bigzs();
4439 #endif  /* HAVE_MPZ */
4440         
4441 #if defined HAVE_MPQ && defined WITH_GMP
4442         /* Put all unmarked ratios on free list */
4443         sweep_bigqs();
4444 #endif  /* HAVE_MPQ */
4445         
4446 #if defined HAVE_MPF && defined WITH_GMP
4447         /* Put all unmarked bigfloats on free list */
4448         sweep_bigfs();
4449 #endif  /* HAVE_MPF */
4450
4451 #if defined HAVE_MPFR && defined WITH_MPFR
4452         /* Put all unmarked bigfloats on free list */
4453         sweep_bigfrs();
4454 #endif  /* HAVE_MPFR */
4455
4456 #if defined HAVE_PSEUG && defined WITH_PSEUG
4457         /* Put all unmarked gaussian numbers on free list */
4458         sweep_biggs();
4459 #endif  /* HAVE_PSEUG */
4460
4461 #if defined HAVE_MPC && defined WITH_MPC ||     \
4462         defined HAVE_PSEUC && defined WITH_PSEUC
4463         /* Put all unmarked complex numbers on free list */
4464         sweep_bigcs();
4465 #endif  /* HAVE_MPC */
4466
4467 #if defined HAVE_QUATERN && defined WITH_QUATERN
4468         /* Put all unmarked quaternions on free list */
4469         sweep_quaterns();
4470 #endif  /* HAVE_QUATERN */
4471
4472         /* Put all unmarked dynacats on free list */
4473         sweep_dynacats();
4474
4475         /* Put all unmarked symbols on free list */
4476         sweep_symbols();
4477
4478         /* Put all unmarked extents on free list */
4479         sweep_extents();
4480
4481         /* Put all unmarked markers on free list.
4482            Dechain each one first from the buffer into which it points. */
4483         sweep_markers();
4484
4485         sweep_events();
4486
4487 #ifdef PDUMP
4488         pdump_objects_unmark();
4489 #endif
4490 }
4491 #endif  /* !BDWGC */
4492 \f
4493 /* Clearing for disksave. */
4494
4495 void disksave_object_finalization(void)
4496 {
4497         /* It's important that certain information from the environment not get
4498            dumped with the executable (pathnames, environment variables, etc.).
4499            To make it easier to tell when this has happened with strings(1) we
4500            clear some known-to-be-garbage blocks of memory, so that leftover
4501            results of old evaluation don't look like potential problems.
4502            But first we set some notable variables to nil and do one more GC,
4503            to turn those strings into garbage.
4504          */
4505
4506         /* Yeah, this list is pretty ad-hoc... */
4507         Vprocess_environment = Qnil;
4508         /* Vexec_directory = Qnil; */
4509         Vdata_directory = Qnil;
4510         Vdoc_directory = Qnil;
4511         Vconfigure_info_directory = Qnil;
4512         Vexec_path = Qnil;
4513         Vload_path = Qnil;
4514         /* Vdump_load_path = Qnil; */
4515         /* Release hash tables for locate_file */
4516         Flocate_file_clear_hashing(Qt);
4517         uncache_home_directory();
4518
4519 #if defined(LOADHIST) && !(defined(LOADHIST_DUMPED) || \
4520                            defined(LOADHIST_BUILTIN))
4521         Vload_history = Qnil;
4522 #endif
4523         Vshell_file_name = Qnil;
4524
4525         garbage_collect_1();
4526
4527         /* Run the disksave finalization methods of all live objects. */
4528         disksave_object_finalization_1();
4529
4530         /* Zero out the uninitialized (really, unused) part of the containers
4531            for the live strings. */
4532         /* dont know what its counterpart in bdwgc mode is, so leave it out */
4533 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
4534         {
4535                 struct string_chars_block *scb;
4536                 for (scb = first_string_chars_block; scb; scb = scb->next) {
4537                         int count = sizeof(scb->string_chars) - scb->pos;
4538
4539                         assert(count >= 0 && count < STRING_CHARS_BLOCK_SIZE);
4540                         if (count != 0) {
4541                                 /* from the block's fill ptr to the end */
4542                                 memset((scb->string_chars + scb->pos), 0,
4543                                        count);
4544                         }
4545                 }
4546         }
4547 #endif
4548
4549         /* There, that ought to be enough... */
4550         return;
4551 }
4552 \f
4553 Lisp_Object restore_gc_inhibit(Lisp_Object val)
4554 {
4555         gc_currently_forbidden = XINT(val);
4556         return val;
4557 }
4558
4559 /* Maybe we want to use this when doing a "panic" gc after memory_full()? */
4560 static int gc_hooks_inhibited;
4561
4562 struct post_gc_action {
4563         void (*fun) (void *);
4564         void *arg;
4565 };
4566
4567 typedef struct post_gc_action post_gc_action;
4568
4569 typedef struct {
4570         Dynarr_declare(post_gc_action);
4571 } post_gc_action_dynarr;
4572
4573 static post_gc_action_dynarr *post_gc_actions;
4574
4575 /* Register an action to be called at the end of GC.
4576    gc_in_progress is 0 when this is called.
4577    This is used when it is discovered that an action needs to be taken,
4578    but it's during GC, so it's not safe. (e.g. in a finalize method.)
4579
4580    As a general rule, do not use Lisp objects here.
4581    And NEVER signal an error.
4582 */
4583
4584 void register_post_gc_action(void (*fun) (void *), void *arg)
4585 {
4586         post_gc_action action;
4587
4588         if (!post_gc_actions)
4589                 post_gc_actions = Dynarr_new(post_gc_action);
4590
4591         action.fun = fun;
4592         action.arg = arg;
4593
4594         Dynarr_add(post_gc_actions, action);
4595 }
4596
4597 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
4598 static void run_post_gc_actions(void)
4599 {
4600         int i;
4601
4602         if (post_gc_actions) {
4603                 for (i = 0; i < Dynarr_length(post_gc_actions); i++) {
4604                         post_gc_action action = Dynarr_at(post_gc_actions, i);
4605                         (action.fun) (action.arg);
4606                 }
4607
4608                 Dynarr_reset(post_gc_actions);
4609         }
4610 }
4611 #endif  /* !BDWGC */
4612 \f
4613 static inline void
4614 mark_gcprolist(struct gcpro *gcpl)
4615 {
4616         struct gcpro *tail;
4617         int i;
4618         for (tail = gcpl; tail; tail = tail->next) {
4619                 for (i = 0; i < tail->nvars; i++) {
4620                         mark_object(tail->var[i]);
4621                 }
4622         }
4623         return;
4624 }
4625
4626 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
4627 #if 0
4628 static int
4629 stop_gc_p(void)
4630 {
4631         return 0;
4632 }
4633 #endif
4634
4635 void garbage_collect_1(void)
4636 {
4637         SXE_DEBUG_GC("GC\n");
4638 #if defined GC_DEBUG_FLAG
4639         GC_dump();
4640 #endif  /* GC_DEBUG_FLAG */
4641 #if 0
4642         GC_collect_a_little();
4643 #elif 0
4644         GC_gcollect();
4645 #elif 0
4646         GC_try_to_collect(stop_gc_p);
4647 #endif
4648         return;
4649 }
4650 #else  /* !BDWGC */
4651
4652 void garbage_collect_1(void)
4653 {
4654 #if MAX_SAVE_STACK > 0
4655         char stack_top_variable;
4656         extern char *stack_bottom;
4657 #endif
4658         struct frame *f;
4659         int speccount;
4660         int cursor_changed;
4661         Lisp_Object pre_gc_cursor;
4662         struct gcpro gcpro1;
4663
4664         if (gc_in_progress
4665             || gc_currently_forbidden || in_display || preparing_for_armageddon)
4666                 return;
4667
4668         /* We used to call selected_frame() here.
4669
4670            The following functions cannot be called inside GC
4671            so we move to after the above tests. */
4672         {
4673                 Lisp_Object frame;
4674                 Lisp_Object device = Fselected_device(Qnil);
4675                 /* Could happen during startup, eg. if always_gc */
4676                 if (NILP(device)) {
4677                         return;
4678                 }
4679                 frame = DEVICE_SELECTED_FRAME(XDEVICE(device));
4680                 if (NILP(frame)) {
4681                         signal_simple_error("No frames exist on device",
4682                                             device);
4683                 }
4684                 f = XFRAME(frame);
4685         }
4686
4687         pre_gc_cursor = Qnil;
4688         cursor_changed = 0;
4689
4690         GCPRO1(pre_gc_cursor);
4691
4692         /* Very important to prevent GC during any of the following
4693            stuff that might run Lisp code; otherwise, we'll likely
4694            have infinite GC recursion. */
4695         speccount = specpdl_depth();
4696         record_unwind_protect(restore_gc_inhibit,
4697                               make_int(gc_currently_forbidden));
4698         gc_currently_forbidden = 1;
4699
4700         if (!gc_hooks_inhibited)
4701                 run_hook_trapping_errors("Error in pre-gc-hook", Qpre_gc_hook);
4702
4703         /* Now show the GC cursor/message. */
4704         if (!noninteractive) {
4705                 if (FRAME_WIN_P(f)) {
4706                         Lisp_Object frame = make_frame(f);
4707                         Lisp_Object cursor =
4708                             glyph_image_instance(Vgc_pointer_glyph,
4709                                                  FRAME_SELECTED_WINDOW(f),
4710                                                  ERROR_ME_NOT, 1);
4711                         pre_gc_cursor = f->pointer;
4712                         if (POINTER_IMAGE_INSTANCEP(cursor)
4713                             /* don't change if we don't know how to change
4714                                back. */
4715                             && POINTER_IMAGE_INSTANCEP(pre_gc_cursor)) {
4716                                 cursor_changed = 1;
4717                                 Fset_frame_pointer(frame, cursor);
4718                         }
4719                 }
4720
4721                 /* Don't print messages to the stream device. */
4722                 if (STRINGP(Vgc_message) &&
4723                     !cursor_changed &&
4724                     !FRAME_STREAM_P(f)) {
4725                         char *msg = GETTEXT((char *) XSTRING_DATA(Vgc_message));
4726                         Lisp_Object args[2], whole_msg;
4727
4728                         args[0] = build_string(
4729                                 msg ? msg : GETTEXT((char*)gc_default_message));
4730                         args[1] = build_string("...");
4731                         whole_msg = Fconcat(2, args);
4732                         echo_area_message(f, (Bufbyte *) 0, whole_msg, 0, -1,
4733                                           Qgarbage_collecting);
4734                 }
4735         }
4736
4737         /***** Now we actually start the garbage collection. */
4738
4739         lock_allocator();
4740         gc_in_progress = 1;
4741         inhibit_non_essential_printing_operations = 1;
4742
4743         gc_generation_number[0]++;
4744
4745 #if MAX_SAVE_STACK > 0
4746
4747         /* Save a copy of the contents of the stack, for debugging.  */
4748         if (!purify_flag) {
4749                 /* Static buffer in which we save a copy of the C stack at each
4750                    GC.  */
4751                 static char *stack_copy;
4752                 static size_t stack_copy_size;
4753
4754                 ptrdiff_t stack_diff = &stack_top_variable - stack_bottom;
4755                 size_t stack_size = (stack_diff > 0 ? stack_diff : -stack_diff);
4756                 if (stack_size < MAX_SAVE_STACK) {
4757                         if (stack_copy_size < stack_size) {
4758                                 stack_copy =
4759                                     (char *)xrealloc(stack_copy, stack_size);
4760                                 stack_copy_size = stack_size;
4761                         }
4762
4763                         memcpy(stack_copy,
4764                                stack_diff >
4765                                0 ? stack_bottom : &stack_top_variable,
4766                                stack_size);
4767                 }
4768         }
4769 #endif                          /* MAX_SAVE_STACK > 0 */
4770
4771         /* Do some totally ad-hoc resource clearing. */
4772         /* #### generalize this? */
4773         clear_event_resource();
4774         cleanup_specifiers();
4775
4776         /* Mark all the special slots that serve as the roots of
4777            accessibility. */
4778
4779         {                       /* staticpro() */
4780                 Lisp_Object **p = Dynarr_begin(staticpros);
4781                 size_t count;
4782                 for (count = Dynarr_length(staticpros); count; count--) {
4783                         mark_object(**p++);
4784                 }
4785         }
4786
4787         {                       /* staticpro_nodump() */
4788                 Lisp_Object **p = Dynarr_begin(staticpros_nodump);
4789                 size_t count;
4790                 for (count = Dynarr_length(staticpros_nodump); count; count--) {
4791                         mark_object(**p++);
4792                 }
4793         }
4794
4795 #if defined(EF_USE_ASYNEQ)
4796         WITH_DLLIST_TRAVERSE(
4797                 workers,
4798                 eq_worker_t eqw = dllist_item;
4799                 struct gcpro *gcpl = eqw->gcprolist;
4800                 mark_gcprolist(gcpl));
4801 #else
4802         /* GCPRO() */
4803         mark_gcprolist(gcprolist);
4804 #endif
4805         {                       /* specbind() */
4806                 struct specbinding *bind;
4807                 for (bind = specpdl; bind != specpdl_ptr; bind++) {
4808                         mark_object(bind->symbol);
4809                         mark_object(bind->old_value);
4810                 }
4811         }
4812
4813         {
4814                 struct catchtag *catch;
4815                 for (catch = catchlist; catch; catch = catch->next) {
4816                         mark_object(catch->tag);
4817                         mark_object(catch->val);
4818                 }
4819         }
4820
4821         {
4822                 struct backtrace *backlist;
4823                 for (backlist = backtrace_list; backlist;
4824                      backlist = backlist->next) {
4825                         int nargs = backlist->nargs;
4826                         int i;
4827
4828                         mark_object(*backlist->function);
4829                         if (nargs <
4830                             0 /* nargs == UNEVALLED || nargs == MANY */ )
4831                                 mark_object(backlist->args[0]);
4832                         else
4833                                 for (i = 0; i < nargs; i++)
4834                                         mark_object(backlist->args[i]);
4835                 }
4836         }
4837
4838         mark_redisplay();
4839         mark_profiling_info();
4840
4841         /* OK, now do the after-mark stuff.  This is for things that are only
4842            marked when something else is marked (e.g. weak hash tables).  There
4843            may be complex dependencies between such objects -- e.g.  a weak hash
4844            table might be unmarked, but after processing a later weak hash
4845            table, the former one might get marked.  So we have to iterate until
4846            nothing more gets marked. */
4847         while (finish_marking_weak_hash_tables() > 0 ||
4848                finish_marking_weak_lists() > 0) ;
4849
4850         /* And prune (this needs to be called after everything else has been
4851            marked and before we do any sweeping). */
4852         /* #### this is somewhat ad-hoc and should probably be an object
4853            method */
4854         prune_weak_hash_tables();
4855         prune_weak_lists();
4856         prune_specifiers();
4857         prune_syntax_tables();
4858
4859         gc_sweep();
4860
4861         consing_since_gc = 0;
4862 #ifndef DEBUG_SXEMACS
4863         /* Allow you to set it really fucking low if you really want ... */
4864         if (gc_cons_threshold < 10000)
4865                 gc_cons_threshold = 10000;
4866 #endif
4867
4868         unlock_allocator();
4869         inhibit_non_essential_printing_operations = 0;
4870         gc_in_progress = 0;
4871
4872         run_post_gc_actions();
4873
4874         /******* End of garbage collection ********/
4875
4876         run_hook_trapping_errors("Error in post-gc-hook", Qpost_gc_hook);
4877
4878         /* Now remove the GC cursor/message */
4879         if (!noninteractive) {
4880                 if (cursor_changed)
4881                         Fset_frame_pointer(make_frame(f), pre_gc_cursor);
4882                 else if (STRINGP(Vgc_message) && !FRAME_STREAM_P(f)) {
4883                         char *msg = GETTEXT((char *)XSTRING_DATA(Vgc_message));
4884
4885                         /* Show "...done" only if the echo area would otherwise
4886                            be empty. */
4887                         if (NILP(clear_echo_area(selected_frame(),
4888                                                  Qgarbage_collecting, 0))) {
4889                                 Lisp_Object args[2], whole_msg;
4890                                 args[0] = build_string(
4891                                         msg ? msg
4892                                         : GETTEXT((char*)gc_default_message));
4893                                 args[1] = build_string("... done");
4894                                 whole_msg = Fconcat(2, args);
4895                                 echo_area_message(selected_frame(),
4896                                                   (Bufbyte *) 0, whole_msg, 0,
4897                                                   -1, Qgarbage_collecting);
4898                         }
4899                 }
4900         }
4901
4902         /* now stop inhibiting GC */
4903         unbind_to(speccount, Qnil);
4904
4905         if (!breathing_space) {
4906                 breathing_space = malloc(4096 - MALLOC_OVERHEAD);
4907         }
4908
4909         UNGCPRO;
4910         return;
4911 }
4912 #endif  /* BDWGC */
4913
4914
4915 /* Debugging aids.  */
4916 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
4917 #define HACK_O_MATIC(args...)
4918 #define gc_plist_hack(name, val, tail)          \
4919         cons3(intern(name), Qzero, tail)
4920
4921 #else  /* !BDWGC */
4922
4923 static Lisp_Object gc_plist_hack(const char *name, int value, Lisp_Object tail)
4924 {
4925         /* C doesn't have local functions (or closures, or GC, or readable
4926            syntax, or portable numeric datatypes, or bit-vectors, or characters,
4927            or arrays, or exceptions, or ...) */
4928         return cons3(intern(name), make_int(value), tail);
4929 }
4930
4931 #define HACK_O_MATIC(type, name, pl)                                    \
4932         do {                                                            \
4933                 int s = 0;                                              \
4934                 struct type##_block *x = current_##type##_block;        \
4935                 while (x) {                                             \
4936                         s += sizeof (*x) + MALLOC_OVERHEAD;             \
4937                         x = x->prev;                                    \
4938                 }                                                       \
4939                 (pl) = gc_plist_hack ((name), s, (pl));                 \
4940         } while (0)
4941 #endif  /* BDWGC */
4942
4943 DEFUN("garbage-collect", Fgarbage_collect, 0, 0, "",    /*
4944 Reclaim storage for Lisp objects no longer needed.
4945 Return info on amount of space in use:
4946 ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)
4947 (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS
4948 PLIST)
4949 where `PLIST' is a list of alternating keyword/value pairs providing
4950 more detailed information.
4951 Garbage collection happens automatically if you cons more than
4952 `gc-cons-threshold' bytes of Lisp data since previous garbage collection.
4953 */
4954       ())
4955 {
4956 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
4957         GC_gcollect();
4958         return Qnil;
4959 #else  /* !BDWGC */
4960         Lisp_Object pl = Qnil;
4961         unsigned int i;
4962         int gc_count_vector_total_size = 0;
4963
4964         garbage_collect_1();
4965
4966         for (i = 0; i < lrecord_type_count; i++) {
4967                 if (lcrecord_stats[i].bytes_in_use != 0
4968                     || lcrecord_stats[i].bytes_freed != 0
4969                     || lcrecord_stats[i].instances_on_free_list != 0) {
4970                         char buf[255];
4971                         const char *name =
4972                             lrecord_implementations_table[i]->name;
4973                         int len = strlen(name);
4974                         int sz;
4975
4976                         /* save this for the FSFmacs-compatible part of the
4977                            summary */
4978                         if (i == lrecord_type_vector)
4979                                 gc_count_vector_total_size =
4980                                     lcrecord_stats[i].bytes_in_use +
4981                                     lcrecord_stats[i].bytes_freed;
4982
4983                         sz = snprintf(buf, sizeof(buf), "%s-storage", name);
4984                         assert(sz >=0  && (size_t)sz < sizeof(buf));
4985                         pl = gc_plist_hack(buf, lcrecord_stats[i].bytes_in_use,
4986                                            pl);
4987                         /* Okay, simple pluralization check for
4988                            `symbol-value-varalias' */
4989                         if (name[len - 1] == 's')
4990                                 sz = snprintf(buf, sizeof(buf), "%ses-freed", name);
4991                         else
4992                                 sz = snprintf(buf, sizeof(buf), "%ss-freed", name);
4993                         assert(sz >=0  && (size_t)sz < sizeof(buf));
4994                         if (lcrecord_stats[i].instances_freed != 0)
4995                                 pl = gc_plist_hack(buf,
4996                                                    lcrecord_stats[i].
4997                                                    instances_freed, pl);
4998                         if (name[len - 1] == 's')
4999                                 sz = snprintf(buf, sizeof(buf), "%ses-on-free-list", name);
5000                         else
5001                                 sz = snprintf(buf, sizeof(buf), "%ss-on-free-list", name);
5002                         assert(sz >=0  && (size_t)sz < sizeof(buf));
5003                         if (lcrecord_stats[i].instances_on_free_list != 0)
5004                                 pl = gc_plist_hack(buf,
5005                                                    lcrecord_stats[i].
5006                                                    instances_on_free_list, pl);
5007                         if (name[len - 1] == 's')
5008                                 sz = snprintf(buf, sizeof(buf), "%ses-used", name);
5009                         else
5010                                 sz = snprintf(buf, sizeof(buf), "%ss-used", name);
5011                         assert(sz >=0  && (size_t)sz < sizeof(buf));
5012                         pl = gc_plist_hack(buf,
5013                                            lcrecord_stats[i].instances_in_use,
5014                                            pl);
5015                 }
5016         }
5017
5018         HACK_O_MATIC(extent, "extent-storage", pl);
5019         pl = gc_plist_hack("extents-free", gc_count_num_extent_freelist, pl);
5020         pl = gc_plist_hack("extents-used", gc_count_num_extent_in_use, pl);
5021         HACK_O_MATIC(event, "event-storage", pl);
5022         pl = gc_plist_hack("events-free", gc_count_num_event_freelist, pl);
5023         pl = gc_plist_hack("events-used", gc_count_num_event_in_use, pl);
5024         HACK_O_MATIC(marker, "marker-storage", pl);
5025         pl = gc_plist_hack("markers-free", gc_count_num_marker_freelist, pl);
5026         pl = gc_plist_hack("markers-used", gc_count_num_marker_in_use, pl);
5027 #ifdef HAVE_FPFLOAT
5028         HACK_O_MATIC(float, "float-storage", pl);
5029         pl = gc_plist_hack("floats-free", gc_count_num_float_freelist, pl);
5030         pl = gc_plist_hack("floats-used", gc_count_num_float_in_use, pl);
5031 #endif  /* HAVE_FPFLOAT */
5032 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP)
5033         HACK_O_MATIC(bigz, "bigz-storage", pl);
5034         pl = gc_plist_hack("bigzs-free", gc_count_num_bigz_freelist, pl);
5035         pl = gc_plist_hack("bigzs-used", gc_count_num_bigz_in_use, pl);
5036 #endif /* HAVE_MPZ */
5037 #if defined HAVE_MPQ && defined WITH_GMP
5038         HACK_O_MATIC(bigq, "bigq-storage", pl);
5039         pl = gc_plist_hack("bigqs-free", gc_count_num_bigq_freelist, pl);
5040         pl = gc_plist_hack("bigqs-used", gc_count_num_bigq_in_use, pl);
5041 #endif /* HAVE_MPQ */
5042 #if defined HAVE_MPF && defined WITH_GMP
5043         HACK_O_MATIC(bigf, "bigf-storage", pl);
5044         pl = gc_plist_hack("bigfs-free", gc_count_num_bigf_freelist, pl);
5045         pl = gc_plist_hack("bigfs-used", gc_count_num_bigf_in_use, pl);
5046 #endif /* HAVE_MPF */
5047 #if defined HAVE_MPFR && defined WITH_MPFR
5048         HACK_O_MATIC(bigfr, "bigfr-storage", pl);
5049         pl = gc_plist_hack("bigfrs-free", gc_count_num_bigfr_freelist, pl);
5050         pl = gc_plist_hack("bigfrs-used", gc_count_num_bigfr_in_use, pl);
5051 #endif /* HAVE_MPFR */
5052 #if defined HAVE_PSEUG && defined WITH_PSEUG
5053         HACK_O_MATIC(bigg, "bigg-storage", pl);
5054         pl = gc_plist_hack("biggs-free", gc_count_num_bigg_freelist, pl);
5055         pl = gc_plist_hack("biggs-used", gc_count_num_bigg_in_use, pl);
5056 #endif /* HAVE_PSEUG */
5057 #if defined HAVE_MPC && defined WITH_MPC ||     \
5058         defined HAVE_PSEUC && defined WITH_PSEUC
5059         HACK_O_MATIC(bigc, "bigc-storage", pl);
5060         pl = gc_plist_hack("bigcs-free", gc_count_num_bigc_freelist, pl);
5061         pl = gc_plist_hack("bigcs-used", gc_count_num_bigc_in_use, pl);
5062 #endif /* HAVE_MPC */
5063 #if defined HAVE_QUATERN && defined WITH_QUATERN
5064         HACK_O_MATIC(quatern, "quatern-storage", pl);
5065         pl = gc_plist_hack("quaterns-free", gc_count_num_quatern_freelist, pl);
5066         pl = gc_plist_hack("quaterns-used", gc_count_num_quatern_in_use, pl);
5067 #endif /* HAVE_QUATERN */
5068
5069         HACK_O_MATIC(dynacat, "dynacat-storage", pl);
5070         pl = gc_plist_hack("dynacats-free", gc_count_num_dynacat_freelist, pl);
5071         pl = gc_plist_hack("dynacats-used", gc_count_num_dynacat_in_use, pl);
5072
5073         HACK_O_MATIC(string, "string-header-storage", pl);
5074         pl = gc_plist_hack("long-strings-total-length",
5075                            gc_count_string_total_size
5076                            - gc_count_short_string_total_size, pl);
5077         HACK_O_MATIC(string_chars, "short-string-storage", pl);
5078         pl = gc_plist_hack("short-strings-total-length",
5079                            gc_count_short_string_total_size, pl);
5080         pl = gc_plist_hack("strings-free", gc_count_num_string_freelist, pl);
5081         pl = gc_plist_hack("long-strings-used",
5082                            gc_count_num_string_in_use
5083                            - gc_count_num_short_string_in_use, pl);
5084         pl = gc_plist_hack("short-strings-used",
5085                            gc_count_num_short_string_in_use, pl);
5086
5087         HACK_O_MATIC(compiled_function, "compiled-function-storage", pl);
5088         pl = gc_plist_hack("compiled-functions-free",
5089                            gc_count_num_compiled_function_freelist, pl);
5090         pl = gc_plist_hack("compiled-functions-used",
5091                            gc_count_num_compiled_function_in_use, pl);
5092
5093         pl = gc_plist_hack("bit-vector-storage", gc_count_bit_vector_storage,
5094                            pl);
5095         pl = gc_plist_hack("bit-vectors-total-length",
5096                            gc_count_bit_vector_total_size, pl);
5097         pl = gc_plist_hack("bit-vectors-used", gc_count_num_bit_vector_used,
5098                            pl);
5099
5100         HACK_O_MATIC(symbol, "symbol-storage", pl);
5101         pl = gc_plist_hack("symbols-free", gc_count_num_symbol_freelist, pl);
5102         pl = gc_plist_hack("symbols-used", gc_count_num_symbol_in_use, pl);
5103
5104         HACK_O_MATIC(cons, "cons-storage", pl);
5105         pl = gc_plist_hack("conses-free", gc_count_num_cons_freelist, pl);
5106         pl = gc_plist_hack("conses-used", gc_count_num_cons_in_use, pl);
5107
5108         /* The things we do for backwards-compatibility */
5109         /* fuck, what are we doing about those in the bdwgc era? -hrop */
5110         return
5111                 list6(Fcons(make_int(gc_count_num_cons_in_use),
5112                             make_int(gc_count_num_cons_freelist)),
5113                       Fcons(make_int(gc_count_num_symbol_in_use),
5114                             make_int(gc_count_num_symbol_freelist)),
5115                       Fcons(make_int(gc_count_num_marker_in_use),
5116                             make_int(gc_count_num_marker_freelist)),
5117                       make_int(gc_count_string_total_size),
5118                       make_int(gc_count_vector_total_size), pl);
5119 #endif  /* BDWGC */
5120 }
5121
5122 #undef HACK_O_MATIC
5123
5124 /* grrrr ... lisp/itimer-autosave.el is using this, WTF? */
5125 DEFUN("consing-since-gc", Fconsing_since_gc, 0, 0, "",  /*
5126 Return the number of bytes consed since the last garbage collection.
5127 \"Consed\" is a misnomer in that this actually counts allocation
5128 of all different kinds of objects, not just conses.
5129
5130 If this value exceeds `gc-cons-threshold', a garbage collection happens.
5131 */
5132       ())
5133 {
5134 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5135         return Qzero;
5136 #else
5137         return make_int(consing_since_gc);
5138 #endif  /* BDWGC */
5139 }
5140
5141 \f
5142 int object_dead_p(Lisp_Object obj)
5143 {
5144         return ((BUFFERP(obj) && !BUFFER_LIVE_P(XBUFFER(obj))) ||
5145                 (FRAMEP(obj) && !FRAME_LIVE_P(XFRAME(obj))) ||
5146                 (WINDOWP(obj) && !WINDOW_LIVE_P(XWINDOW(obj))) ||
5147                 (DEVICEP(obj) && !DEVICE_LIVE_P(XDEVICE(obj))) ||
5148                 (CONSOLEP(obj) && !CONSOLE_LIVE_P(XCONSOLE(obj))) ||
5149                 (EVENTP(obj) && !EVENT_LIVE_P(XEVENT(obj))) ||
5150                 (EXTENTP(obj) && !EXTENT_LIVE_P(XEXTENT(obj))));
5151 }
5152
5153 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
5154
5155 /* Attempt to determine the actual amount of space that is used for
5156    the block allocated starting at PTR, supposedly of size "CLAIMED_SIZE".
5157
5158    It seems that the following holds:
5159
5160    1. When using the old allocator (malloc.c):
5161
5162       -- blocks are always allocated in chunks of powers of two.  For
5163          each block, there is an overhead of 8 bytes if rcheck is not
5164          defined, 20 bytes if it is defined.  In other words, a
5165          one-byte allocation needs 8 bytes of overhead for a total of
5166          9 bytes, and needs to have 16 bytes of memory chunked out for
5167          it.
5168
5169    2. When using the new allocator (gmalloc.c):
5170
5171       -- blocks are always allocated in chunks of powers of two up
5172          to 4096 bytes.  Larger blocks are allocated in chunks of
5173          an integral multiple of 4096 bytes.  The minimum block
5174          size is 2*sizeof (void *), or 16 bytes if SUNOS_LOCALTIME_BUG
5175          is defined.  There is no per-block overhead, but there
5176          is an overhead of 3*sizeof (size_t) for each 4096 bytes
5177          allocated.
5178
5179     3. When using the system malloc, anything goes, but they are
5180        generally slower and more space-efficient than the GNU
5181        allocators.  One possibly reasonable assumption to make
5182        for want of better data is that sizeof (void *), or maybe
5183        2 * sizeof (void *), is required as overhead and that
5184        blocks are allocated in the minimum required size except
5185        that some minimum block size is imposed (e.g. 16 bytes). */
5186
5187 size_t
5188 malloced_storage_size(void *ptr, size_t claimed_size,
5189                       struct overhead_stats * stats)
5190 {
5191         size_t orig_claimed_size = claimed_size;
5192
5193 #ifdef GNU_MALLOC
5194
5195         if (claimed_size < 2 * sizeof(void *))
5196                 claimed_size = 2 * sizeof(void *);
5197 # ifdef SUNOS_LOCALTIME_BUG
5198         if (claimed_size < 16)
5199                 claimed_size = 16;
5200 # endif
5201         if (claimed_size < 4096) {
5202                 int _log_ = 1;
5203
5204                 /* compute the log base two, more or less, then use it to compute
5205                    the block size needed. */
5206                 claimed_size--;
5207                 /* It's big, it's heavy, it's wood! */
5208                 while ((claimed_size /= 2) != 0)
5209                         ++_log_;
5210                 claimed_size = 1;
5211                 /* It's better than bad, it's good! */
5212                 while (_log_ > 0) {
5213                         claimed_size *= 2;
5214                         _log_--;
5215                 }
5216                 /* We have to come up with some average about the amount of
5217                    blocks used. */
5218                 if ((size_t) (rand() & 4095) < claimed_size)
5219                         claimed_size += 3 * sizeof(void *);
5220         } else {
5221                 claimed_size += 4095;
5222                 claimed_size &= ~4095;
5223                 claimed_size += (claimed_size / 4096) * 3 * sizeof(size_t);
5224         }
5225
5226 #elif defined (SYSTEM_MALLOC)
5227
5228         if (claimed_size < 16)
5229                 claimed_size = 16;
5230         claimed_size += 2 * sizeof(void *);
5231
5232 #else                           /* old GNU allocator */
5233
5234 # ifdef rcheck                  /* #### may not be defined here */
5235         claimed_size += 20;
5236 # else
5237         claimed_size += 8;
5238 # endif
5239         {
5240                 int _log_ = 1;
5241
5242                 /* compute the log base two, more or less, then use it to compute
5243                    the block size needed. */
5244                 claimed_size--;
5245                 /* It's big, it's heavy, it's wood! */
5246                 while ((claimed_size /= 2) != 0)
5247                         ++_log_;
5248                 claimed_size = 1;
5249                 /* It's better than bad, it's good! */
5250                 while (_log_ > 0) {
5251                         claimed_size *= 2;
5252                         _log_--;
5253                 }
5254         }
5255
5256 #endif                          /* old GNU allocator */
5257
5258         if (stats) {
5259                 stats->was_requested += orig_claimed_size;
5260                 stats->malloc_overhead += claimed_size - orig_claimed_size;
5261         }
5262         return claimed_size;
5263 }
5264
5265 size_t fixed_type_block_overhead(size_t size)
5266 {
5267         size_t per_block = TYPE_ALLOC_SIZE(cons, unsigned char);
5268         size_t overhead = 0;
5269         size_t storage_size = malloced_storage_size(0, per_block, 0);
5270         while (size >= per_block) {
5271                 size -= per_block;
5272                 overhead += sizeof(void *) + per_block - storage_size;
5273         }
5274         if (rand() % per_block < size)
5275                 overhead += sizeof(void *) + per_block - storage_size;
5276         return overhead;
5277 }
5278
5279 #endif                          /* MEMORY_USAGE_STATS */
5280
5281 #ifdef EF_USE_ASYNEQ
5282 static eq_worker_t
5283 init_main_worker(void)
5284 {
5285         eq_worker_t res = eq_make_worker();
5286         eq_worker_thread(res) = pthread_self();
5287         return res;
5288 }
5289 #endif
5290
5291 #if defined HAVE_MPZ && defined WITH_GMP ||             \
5292         defined HAVE_MPFR && defined WITH_MPFR
5293 static void*
5294 my_malloc(size_t bar)
5295 {
5296         /* we use atomic here since GMP/MPFR do supervise their objects */
5297         void *foo = xmalloc(bar);
5298         SXE_DEBUG_GC_GMP("alloc :is %p :size %lu\n",
5299                          foo, (long unsigned int)bar);
5300         return foo;
5301 }
5302
5303 /* We need the next two functions since GNU MP insists on giving us an extra
5304    parameter. */
5305 static void*
5306 my_realloc (void *ptr, size_t SXE_UNUSED(old_size), size_t new_size)
5307 {
5308         void *foo = xrealloc(ptr, new_size);
5309         SXE_DEBUG_GC_GMP("gmp realloc :was %p  :is %p\n", ptr, foo);
5310         return foo;
5311 }
5312
5313 static void
5314 my_free (void *ptr, size_t size)
5315 {
5316         SXE_DEBUG_GC_GMP("free :was %p :size %lu\n",
5317                          ptr, (long unsigned int)size);
5318         memset(ptr, 0, size);
5319         xfree(ptr);
5320         return;
5321 }
5322 #endif  /* GMP || MPFR */
5323
5324 #if defined HAVE_BDWGC && defined EF_USE_BDWGC && !defined GC_DEBUG_FLAG
5325 static void
5326 my_shy_warn_proc(char *msg, GC_word arg)
5327 {
5328         /* just don't do anything */
5329         return;
5330 }
5331 #endif  /* BDWGC */
5332
5333 \f
5334 /* Initialization */
5335 void init_bdwgc(void);
5336
5337 void
5338 init_bdwgc(void)
5339 {
5340 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
5341 # if defined GC_DEBUG_FLAG
5342         extern long GC_large_alloc_warn_interval;
5343 # endif
5344         GC_time_limit = GC_TIME_UNLIMITED;
5345         GC_use_entire_heap = 0;
5346         GC_find_leak = 0;
5347         GC_dont_gc = 0;
5348         GC_all_interior_pointers = 1;
5349 #if 0
5350         GC_parallel = 1;
5351         GC_dont_expand = 1;
5352         GC_free_space_divisor = 8;
5353 #endif
5354 #if !defined GC_DEBUG_FLAG
5355         GC_set_warn_proc(my_shy_warn_proc);
5356 #else  /* GC_DEBUG_FLAG */
5357         GC_large_alloc_warn_interval = 1L;
5358 #endif  /* GC_DEBUG_FLAG */
5359         GC_INIT();
5360 #endif  /* BDWGC */
5361         return;
5362 }
5363
5364 static inline void
5365 __init_gmp_mem_funs(void)
5366 {
5367 #if defined HAVE_MPZ && defined WITH_GMP ||             \
5368         defined HAVE_MPFR && defined WITH_MPFR
5369         mp_set_memory_functions(my_malloc, my_realloc, my_free);
5370 #endif  /* GMP || MPFR */
5371 }
5372
5373 void reinit_alloc_once_early(void)
5374 {
5375         gc_generation_number[0] = 0;
5376         breathing_space = 0;
5377         XSETINT(all_bit_vectors, 0);    /* Qzero may not be set yet. */
5378         XSETINT(Vgc_message, 0);
5379 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
5380         all_lcrecords = 0;
5381 #endif  /* !BDWGC */
5382         ignore_malloc_warnings = 1;
5383 #ifdef DOUG_LEA_MALLOC
5384         mallopt(M_TRIM_THRESHOLD, 128 * 1024);  /* trim threshold */
5385         mallopt(M_MMAP_THRESHOLD, 64 * 1024);   /* mmap threshold */
5386 #if 1                           /* Moved to emacs.c */
5387         mallopt(M_MMAP_MAX, 0); /* max. number of mmap'ed areas */
5388 #endif
5389 #endif
5390         /* the category subsystem */
5391         morphisms[lrecord_type_cons].seq_impl = &__scons;
5392         morphisms[lrecord_type_vector].seq_impl = &__svec;
5393         morphisms[lrecord_type_string].seq_impl = &__sstr;
5394         morphisms[lrecord_type_bit_vector].seq_impl = &__sbvc;
5395
5396         init_string_alloc();
5397 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
5398         init_string_chars_alloc();
5399 #endif  /* !BDWGC */
5400         init_cons_alloc();
5401         init_symbol_alloc();
5402         init_compiled_function_alloc();
5403
5404         init_float_alloc();
5405
5406         __init_gmp_mem_funs();
5407 #if defined HAVE_MPZ && (defined WITH_GMP || defined WITH_MP) &&        \
5408         !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
5409         init_bigz_alloc();
5410 #endif
5411 #if defined HAVE_MPQ && defined WITH_GMP &&     \
5412         !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
5413         init_bigq_alloc();
5414 #endif
5415 #if defined HAVE_MPF && defined WITH_GMP &&     \
5416         !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
5417         init_bigf_alloc();
5418 #endif
5419 #if defined HAVE_MPFR && defined WITH_MPFR
5420         init_bigfr_alloc();
5421 #endif
5422 #if defined HAVE_PSEUG && defined HAVE_MPZ && defined WITH_PSEUG
5423         init_bigg_alloc();
5424 #endif
5425 #if defined HAVE_MPC && defined WITH_MPC ||     \
5426         defined HAVE_PSEUC && defined WITH_PSEUC
5427         init_bigc_alloc();
5428 #endif
5429 #if defined HAVE_QUATERN && defined HAVE_MPZ && defined WITH_QUATERN
5430         init_quatern_alloc();
5431 #endif
5432         init_dynacat_alloc();
5433
5434         init_marker_alloc();
5435         init_extent_alloc();
5436         init_event_alloc();
5437
5438         ignore_malloc_warnings = 0;
5439
5440         /* we only use the 500k value for now */
5441         gc_cons_threshold = 500000;
5442         lrecord_uid_counter = 259;
5443
5444 #if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
5445         if (staticpros_nodump) {
5446                 Dynarr_free(staticpros_nodump);
5447         }
5448         staticpros_nodump = Dynarr_new2(Lisp_Object_ptr_dynarr, Lisp_Object *);
5449         /* merely a small optimization */
5450         Dynarr_resize(staticpros_nodump, 100);
5451
5452         /* tuning the GCor */
5453         consing_since_gc = 0;
5454         debug_string_purity = 0;
5455 #endif  /* !BDWGC */
5456 #ifdef EF_USE_ASYNEQ
5457         workers = make_noseeum_dllist();
5458         dllist_prepend(workers, init_main_worker());
5459 #else
5460         gcprolist = 0;
5461 #endif
5462
5463 #if defined EF_USE_ASYNEQ && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
5464         SXE_MUTEX_INIT(&cons_mutex);
5465 #endif
5466
5467         gc_currently_forbidden = 0;
5468         gc_hooks_inhibited = 0;
5469
5470 #ifdef ERROR_CHECK_TYPECHECK
5471         ERROR_ME.
5472             really_unlikely_name_to_have_accidentally_in_a_non_errb_structure =
5473             666;
5474         ERROR_ME_NOT.
5475             really_unlikely_name_to_have_accidentally_in_a_non_errb_structure =
5476             42;
5477         ERROR_ME_WARN.
5478             really_unlikely_name_to_have_accidentally_in_a_non_errb_structure =
5479             3333632;
5480 #endif                          /* ERROR_CHECK_TYPECHECK */
5481 }
5482
5483 void init_alloc_once_early(void)
5484 {
5485         reinit_alloc_once_early();
5486
5487         for (int i = 0; i < countof(lrecord_implementations_table); i++) {
5488                 lrecord_implementations_table[i] = 0;
5489         }
5490
5491         INIT_LRECORD_IMPLEMENTATION(cons);
5492         INIT_LRECORD_IMPLEMENTATION(vector);
5493         INIT_LRECORD_IMPLEMENTATION(string);
5494         INIT_LRECORD_IMPLEMENTATION(lcrecord_list);
5495
5496         staticpros = Dynarr_new2(Lisp_Object_ptr_dynarr, Lisp_Object *);
5497         Dynarr_resize(staticpros, 1410);        /* merely a small optimization */
5498         dump_add_root_struct_ptr(&staticpros, &staticpros_description);
5499
5500         /* GMP/MPFR mem funs */
5501         __init_gmp_mem_funs();
5502
5503         return;
5504 }
5505
5506 void reinit_alloc(void)
5507 {
5508 #ifdef EF_USE_ASYNEQ
5509         eq_worker_t main_th;
5510         assert(dllist_size(workers) == 1);
5511         main_th = dllist_car(workers);
5512         eq_worker_gcprolist(main_th) = NULL;
5513 #else
5514         gcprolist = 0;
5515 #endif
5516 }
5517
5518 void syms_of_alloc(void)
5519 {
5520         DEFSYMBOL(Qpre_gc_hook);
5521         DEFSYMBOL(Qpost_gc_hook);
5522         DEFSYMBOL(Qgarbage_collecting);
5523
5524         DEFSUBR(Fcons);
5525         DEFSUBR(Flist);
5526         DEFSUBR(Fvector);
5527         DEFSUBR(Fbit_vector);
5528         DEFSUBR(Fmake_byte_code);
5529         DEFSUBR(Fmake_list);
5530         DEFSUBR(Fmake_vector);
5531         DEFSUBR(Fmake_bit_vector);
5532         DEFSUBR(Fmake_string);
5533         DEFSUBR(Fstring);
5534         DEFSUBR(Fmake_symbol);
5535         DEFSUBR(Fmake_marker);
5536         DEFSUBR(Fpurecopy);
5537         DEFSUBR(Fgarbage_collect);
5538         DEFSUBR(Fconsing_since_gc);
5539 }
5540
5541 void vars_of_alloc(void)
5542 {
5543         DEFVAR_INT("gc-cons-threshold", &gc_cons_threshold      /*
5544 *Number of bytes of consing between garbage collections.
5545 \"Consing\" is a misnomer in that this actually counts allocation
5546 of all different kinds of objects, not just conses.
5547 Garbage collection can happen automatically once this many bytes have been
5548 allocated since the last garbage collection.  All data types count.
5549
5550 Garbage collection happens automatically when `eval' or `funcall' are
5551 called.  (Note that `funcall' is called implicitly as part of evaluation.)
5552 By binding this temporarily to a large number, you can effectively
5553 prevent garbage collection during a part of the program.
5554
5555 See also `consing-since-gc'.
5556                                                                  */ );
5557
5558 #ifdef DEBUG_SXEMACS
5559         DEFVAR_INT("debug-allocation", &debug_allocation        /*
5560 If non-zero, print out information to stderr about all objects allocated.
5561 See also `debug-allocation-backtrace-length'.
5562                                                                  */ );
5563         debug_allocation = 0;
5564
5565         DEFVAR_INT("debug-allocation-backtrace-length", &debug_allocation_backtrace_length      /*
5566 Length (in stack frames) of short backtrace printed out by `debug-allocation'.
5567                                                                                                  */ );
5568         debug_allocation_backtrace_length = 2;
5569 #endif
5570
5571         DEFVAR_BOOL("purify-flag", &purify_flag /*
5572 Non-nil means loading Lisp code in order to dump an executable.
5573 This means that certain objects should be allocated in readonly space.
5574                                                  */ );
5575
5576         DEFVAR_LISP("pre-gc-hook", &Vpre_gc_hook        /*
5577 Function or functions to be run just before each garbage collection.
5578 Interrupts, garbage collection, and errors are inhibited while this hook
5579 runs, so be extremely careful in what you add here.  In particular, avoid
5580 consing, and do not interact with the user.
5581                                                          */ );
5582         Vpre_gc_hook = Qnil;
5583
5584         DEFVAR_LISP("post-gc-hook", &Vpost_gc_hook      /*
5585 Function or functions to be run just after each garbage collection.
5586 Interrupts, garbage collection, and errors are inhibited while this hook
5587 runs, so be extremely careful in what you add here.  In particular, avoid
5588 consing, and do not interact with the user.
5589                                                          */ );
5590         Vpost_gc_hook = Qnil;
5591
5592         DEFVAR_LISP("gc-message", &Vgc_message  /*
5593 String to print to indicate that a garbage collection is in progress.
5594 This is printed in the echo area.  If the selected frame is on a
5595 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer
5596 image instance) in the domain of the selected frame, the mouse pointer
5597 will change instead of this message being printed.
5598 If it has non-string value - nothing is printed.
5599                                                  */ );
5600         Vgc_message = build_string(gc_default_message);
5601
5602         DEFVAR_LISP("gc-pointer-glyph", &Vgc_pointer_glyph      /*
5603 Pointer glyph used to indicate that a garbage collection is in progress.
5604 If the selected window is on a window system and this glyph specifies a
5605 value (i.e. a pointer image instance) in the domain of the selected
5606 window, the pointer will be changed as specified during garbage collection.
5607 Otherwise, a message will be printed in the echo area, as controlled
5608 by `gc-message'.
5609                                                                  */ );
5610 }
5611
5612 void complex_vars_of_alloc(void)
5613 {
5614         Vgc_pointer_glyph = Fmake_glyph_internal(Qpointer);
5615 }