comparison src/dumper.c @ 2367:ecf1ebac70d8

[xemacs-hg @ 2004-11-04 23:05:23 by ben] commit mega-patch configure.in: Turn off -Winline and -Wchar-subscripts. Use the right set of cflags when compiling modules. Rewrite ldap configuration to separate the inclusion of lber (needed in recent Cygwin) from the basic checks for the needed libraries. add a function for MAKE_JUNK_C; initially code was added to generate xemacs.def using this, but it will need to be rewritten. add an rm -f for junk.c to avoid weird Cygwin bug with cp -f onto an existing file. Sort list of auto-detected functions and eliminate unused checks for stpcpy, setlocale and getwd. Add autodetection of Cygwin scanf problems BETA: Rewrite section on configure to indicate what flags are important and what not. digest-doc.c, make-dump-id.c, profile.c, sorted-doc.c: Add proper decls for main(). make-msgfile.c: Document that this is old junk. Move proposal to text.c. make-msgfile.lex: Move proposal to text.c. make-mswin-unicode.pl: Convert error-generating code so that the entire message will be seen as a single unrecognized token. mule/mule-ccl.el: Update docs. lispref/mule.texi: Update CCL docs. ldap/eldap.c: Mule-ize. Use EXTERNAL_LIST_LOOP_2 instead of deleted EXTERNAL_LIST_LOOP. * XEmacs 21.5.18 "chestnut" is released. --------------------------------------------------------------- MULE-RELATED WORK: --------------------------------------------------------------- --------------------------- byte-char conversion --------------------------- buffer.c, buffer.h, insdel.c, text.c: Port FSF algorithm for byte-char conversion, replacing broken previous version. Track the char position of the gap. Add functions to do char-byte conversion downwards as well as upwards. Move comments about algorithm workings to internals manual. --------------------------- work on types --------------------------- alloc.c, console-x-impl.h, dump-data.c, dump-data.h, dumper.c, dialog-msw.c, dired-msw.c, doc.c, editfns.c, esd.c, event-gtk.h, event-msw.c, events.c, file-coding.c, file-coding.h, fns.c, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-shared.c, glyphs-x.c, glyphs.c, glyphs.h, gui.c, hpplay.c, imgproc.c, intl-win32.c, lrecord.h, lstream.c, keymap.c, lisp.h, libsst.c, linuxplay.c, miscplay.c, miscplay.h, mule-coding.c, nas.c, nt.c, ntheap.c, ntplay.c, objects-msw.c, objects-tty.c, objects-x.c, print.c, process-nt.c, process.c, redisplay.h, select-common.h, select-gtk.c, select-x.c, sgiplay.c, sound.c, sound.h, sunplay.c, sysfile.h, sysdep.c, syswindows.h, text.c, unexnt.c, win32.c, xgccache.c: Further work on types. This creates a full set of types for all the basic semantics of `char' that I have so far identified, so that its semantics can always be identified for the purposes of proper Mule-safe code, and the raw use of `char' always avoided. (1) More type renaming, for consistency of naming. Char_ASCII -> Ascbyte UChar_ASCII -> UAscbyte Char_Binary -> CBinbyte UChar_Binary -> Binbyte SChar_Binary -> SBinbyte (2) Introduce Rawbyte, CRawbyte, Boolbyte, Chbyte, UChbyte, and Bitbyte and use them. (3) New types Itext, Wexttext and Textcount for separating out the concepts of bytes and textual units (different under UTF-16 and UTF-32, which are potential internal encodings). (4) qxestr*_c -> qxestr*_ascii. lisp.h: New; goes with other qxe() functions. #### Maybe goes in a different section. lisp.h: Group generic int-type defs together with EMACS_INT defs. lisp.h: * lisp.h (WEXTTEXT_IS_WIDE) New defns. lisp.h: New type to replace places where int occurs as a boolean. It's signed because occasionally people may want to use -1 as an error value, and because unsigned ints are viral -- see comments in the internals manual against using them. dynarr.c: int -> Bytecount. --------------------------- Mule-izing --------------------------- device-x.c: Partially Mule-ize. dumper.c, dumper.h: Mule-ize. Use Rawbyte. Use stderr_out not printf. Use wext_*(). sysdep.c, syswindows.h, text.c: New Wexttext API for manipulation of external text that may be Unicode (e.g. startup code under Windows). emacs.c: Mule-ize. Properly deal with argv in external encoding. Use wext_*() and Wexttext. Use Rawbyte. #if 0 some old junk on SCO that is unlikely to be correct. Rewrite allocation code in run-temacs. emacs.c, symsinit.h, win32.c: Rename win32 init function and call it even earlier, to initialize mswindows_9x_p even earlier, for use in startup code (XEUNICODE_P). process.c: Use _wenviron not environ under Windows, to get Unicode environment variables. event-Xt.c: Mule-ize drag-n-drop related stuff. dragdrop.c, dragdrop.h, frame-x.c: Mule-ize. text.h: Add some more stand-in defines for particular kinds of conversion; use in Mule-ization work in frame-x.c etc. --------------------------- Freshening --------------------------- intl-auto-encap-win32.c, intl-auto-encap-win32.h: Regenerate. --------------------------- Unicode-work --------------------------- intl-win32.c, syswindows.h: Factor out common options to MultiByteToWideChar and WideCharToMultiByte. Add convert_unicode_to_multibyte_malloc() and convert_unicode_to_multibyte_dynarr() and use. Add stuff for alloca() conversion of multibyte/unicode. alloc.c: Use dfc_external_data_len() in case of unicode coding system. alloc.c, mule-charset.c: Don't zero out and reinit charset Unicode tables. This fucks up dump-time loading. Anyway, either we load them at dump time or run time, never both. unicode.c: Dump the blank tables as well. --------------------------------------------------------------- DOCUMENTATION, MOSTLY MULE-RELATED: --------------------------------------------------------------- EmacsFrame.c, emodules.c, event-Xt.c, fileio.c, input-method-xlib.c, mule-wnnfns.c, redisplay-gtk.c, redisplay-tty.c, redisplay-x.c, regex.c, sysdep.c: Add comment about Mule work needed. text.h: Add more documentation describing why DFC routines were not written to return their value. Add some other DFC documentation. console-msw.c, console-msw.h: Add pointer to docs in win32.c. emacs.c: Add comments on sources of doc info. text.c, charset.h, unicode.c, intl-win32.c, intl-encap-win32.c, text.h, file-coding.c, mule-coding.c: Collect background comments and related to text matters and internationalization, and proposals for work to be done, in text.c or Internals manual, stuff related to specific textual API's in text.h, and stuff related to internal implementation of Unicode conversion in unicode.c. Put lots of pointers to the comments to make them easier to find. s/mingw32.h, s/win32-common.h, s/win32-native.h, s/windowsnt.h, win32.c: Add bunches of new documentation on the different kinds of builds and environments under Windows and how they work. Collect this info in win32.c. Add pointers to these docs in the relevant s/* files. emacs.c: Document places with long comments. Remove comment about exiting, move to internals manual, put in pointer. event-stream.c: Move docs about event queues and focus to internals manual, put in pointer. events.h: Move docs about event stream callbacks to internals manual, put in pointer. profile.c, redisplay.c, signal.c: Move documentation to the Internals manual. process-nt.c: Add pointer to comment in win32-native.el. lisp.h: Add comments about some comment conventions. lisp.h: Add comment about the second argument. device-msw.c, redisplay-msw.c: @@#### comments are out-of-date. --------------------------------------------------------------- PDUMP WORK (MOTIVATED BY UNICODE CHANGES) --------------------------------------------------------------- alloc.c, buffer.c, bytecode.c, console-impl.h, console.c, device.c, dumper.c, lrecord.h, elhash.c, emodules.h, events.c, extents.c, frame.c, glyphs.c, glyphs.h, mule-charset.c, mule-coding.c, objects.c, profile.c, rangetab.c, redisplay.c, specifier.c, specifier.h, window.c, lstream.c, file-coding.h, file-coding.c: PDUMP: Properly implement dump_add_root_block(), which never worked before, and is necessary for dumping Unicode tables. Pdump name changes for accuracy: XD_STRUCT_PTR -> XD_BLOCK_PTR. XD_STRUCT_ARRAY -> XD_BLOCK_ARRAY. XD_C_STRING -> XD_ASCII_STRING. *_structure_* -> *_block_*. lrecord.h: some comments added about dump_add_root_block() vs dump_add_root_block_ptr(). extents.c: remove incorrect comment about pdump problems with gap array. --------------------------------------------------------------- ALLOCATION --------------------------------------------------------------- abbrev.c, alloc.c, bytecode.c, casefiddle.c, device-msw.c, device-x.c, dired-msw.c, doc.c, doprnt.c, dragdrop.c, editfns.c, emodules.c, file-coding.c, fileio.c, filelock.c, fns.c, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-x.c, gui-msw.c, gui-x.c, imgproc.c, intl-win32.c, lread.c, menubar-gtk.c, menubar.c, nt.c, objects-msw.c, objects-x.c, print.c, process-nt.c, process-unix.c, process.c, realpath.c, redisplay.c, search.c, select-common.c, symbols.c, sysdep.c, syswindows.h, text.c, text.h, ui-byhand.c: New macros {alloca,xnew}_{itext,{i,ext,raw,bin,asc}bytes} for more convenient allocation of these commonly requested items. Modify functions to use alloca_ibytes, alloca_array, alloca_extbytes, xnew_ibytes, etc. also XREALLOC_ARRAY, xnew. alloc.c: Rewrite the allocation functions to factor out repeated code. Add assertions for freeing dumped data. lisp.h: Moved down and consolidated with other allocation stuff. lisp.h, dynarr.c: New functions for allocation that's very efficient when mostly in LIFO order. lisp.h, text.c, text.h: Factor out some stuff for general use by alloca()-conversion funs. text.h, lisp.h: Fill out convenience routines for allocating various kinds of bytes and put them in lisp.h. Use them in place of xmalloc(), ALLOCA(). text.h: Fill out the convenience functions so the _MALLOC() kinds match the alloca() kinds. --------------------------------------------------------------- ERROR-CHECKING --------------------------------------------------------------- text.h: Create ASSERT_ASCTEXT_ASCII() and ASSERT_ASCTEXT_ASCII_LEN() from similar Eistring checkers and change the Eistring checkers to use them instead. --------------------------------------------------------------- MACROS IN LISP.H --------------------------------------------------------------- lisp.h: Redo GCPRO declarations. Create a "base" set of functions that can be used to generate any kind of gcpro sets -- regular, ngcpro, nngcpro, private ones used in GC_EXTERNAL_LIST_LOOP_2. buffer.c, callint.c, chartab.c, console-msw.c, device-x.c, dialog-msw.c, dired.c, extents.c, ui-gtk.c, rangetab.c, nt.c, mule-coding.c, minibuf.c, menubar-msw.c, menubar.c, menubar-gtk.c, lread.c, lisp.h, gutter.c, glyphs.c, glyphs-widget.c, fns.c, fileio.c, file-coding.c, specifier.c: Eliminate EXTERNAL_LIST_LOOP, which does not check for circularities. Use EXTERNAL_LIST_LOOP_2 instead or EXTERNAL_LIST_LOOP_3 or EXTERNAL_PROPERTY_LIST_LOOP_3 or GC_EXTERNAL_LIST_LOOP_2 (new macro). Removed/redid comments on EXTERNAL_LIST_LOOP. --------------------------------------------------------------- SPACING FIXES --------------------------------------------------------------- callint.c, hftctl.c, number-gmp.c, process-unix.c: Spacing fixes. --------------------------------------------------------------- FIX FOR GEOMETRY PROBLEM IN FIRST FRAME --------------------------------------------------------------- unicode.c: Add workaround for newlib bug in sscanf() [should be fixed by release 1.5.12 of Cygwin]. toolbar.c: bug fix for problem of initial frame being 77 chars wide on Windows. will be overridden by my other ws. --------------------------------------------------------------- FIX FOR LEAKING PROCESS HANDLES: --------------------------------------------------------------- process-nt.c: Fixes for leaking handles. Inspired by work done by Adrian Aichner <adrian@xemacs.org>. --------------------------------------------------------------- FIX FOR CYGWIN BUG (Unicode-related): --------------------------------------------------------------- unicode.c: Add workaround for newlib bug in sscanf() [should be fixed by release 1.5.12 of Cygwin]. --------------------------------------------------------------- WARNING FIXES: --------------------------------------------------------------- console-stream.c: `reinit' is unused. compiler.h, event-msw.c, frame-msw.c, intl-encap-win32.c, text.h: Add stuff to deal with ANSI-aliasing warnings I got. regex.c: Gather includes together to avoid warning. --------------------------------------------------------------- CHANGES TO INITIALIZATION ROUTINES: --------------------------------------------------------------- buffer.c, emacs.c, console.c, debug.c, device-x.c, device.c, dragdrop.c, emodules.c, eval.c, event-Xt.c, event-gtk.c, event-msw.c, event-stream.c, event-tty.c, events.c, extents.c, faces.c, file-coding.c, fileio.c, font-lock.c, frame-msw.c, glyphs-widget.c, glyphs.c, gui-x.c, insdel.c, lread.c, lstream.c, menubar-gtk.c, menubar-x.c, minibuf.c, mule-wnnfns.c, objects-msw.c, objects.c, print.c, scrollbar-x.c, search.c, select-x.c, text.c, undo.c, unicode.c, window.c, symsinit.h: Call reinit_*() functions directly from emacs.c, for clarity. Factor out some redundant init code. Move disallowed stuff that had crept into vars_of_glyphs() into complex_vars_of_glyphs(). Call init_eval_semi_early() from eval.c not in the middle of vars_of_() in emacs.c since there should be no order dependency in the latter calls. --------------------------------------------------------------- ARMAGEDDON: --------------------------------------------------------------- alloc.c, emacs.c, lisp.h, print.c: Rename inhibit_non_essential_printing_operations to inhibit_non_essential_conversion_operations. text.c: Assert on !inhibit_non_essential_conversion_operations. console-msw.c, print.c: Don't do conversion in SetConsoleTitle or FindWindow to avoid problems during armageddon. Put #errors for NON_ASCII_INTERNAL_FORMAT in places where problems would arise. --------------------------------------------------------------- CHANGES TO THE BUILD PROCEDURE: --------------------------------------------------------------- config.h.in, s/cxux.h, s/usg5-4-2.h, m/powerpc.h: Add comment about correct ordering of this file. Rearrange everything to follow this -- put all #undefs together and before the s&m files. Add undefs for HAVE_ALLOCA, C_ALLOCA, BROKEN_ALLOCA_IN_FUNCTION_CALLS, STACK_DIRECTION. Remove unused HAVE_STPCPY, HAVE_GETWD, HAVE_SETLOCALE. m/gec63.h: Deleted; totally broken, not used at all, not in FSF. m/7300.h, m/acorn.h, m/alliant-2800.h, m/alliant.h, m/altos.h, m/amdahl.h, m/apollo.h, m/att3b.h, m/aviion.h, m/celerity.h, m/clipper.h, m/cnvrgnt.h, m/convex.h, m/cydra5.h, m/delta.h, m/delta88k.h, m/dpx2.h, m/elxsi.h, m/ews4800r.h, m/gould.h, m/hp300bsd.h, m/hp800.h, m/hp9000s300.h, m/i860.h, m/ibmps2-aix.h, m/ibmrs6000.h, m/ibmrt-aix.h, m/ibmrt.h, m/intel386.h, m/iris4d.h, m/iris5d.h, m/iris6d.h, m/irist.h, m/isi-ov.h, m/luna88k.h, m/m68k.h, m/masscomp.h, m/mg1.h, m/mips-nec.h, m/mips-siemens.h, m/mips.h, m/news.h, m/nh3000.h, m/nh4000.h, m/ns32000.h, m/orion105.h, m/pfa50.h, m/plexus.h, m/pmax.h, m/powerpc.h, m/pyrmips.h, m/sequent-ptx.h, m/sequent.h, m/sgi-challenge.h, m/symmetry.h, m/tad68k.h, m/tahoe.h, m/targon31.h, m/tekxd88.h, m/template.h, m/tower32.h, m/tower32v3.h, m/ustation.h, m/vax.h, m/wicat.h, m/xps100.h: Delete C_ALLOCA, HAVE_ALLOCA, STACK_DIRECTION, BROKEN_ALLOCA_IN_FUNCTION_CALLS. All of this is auto-detected. When in doubt, I followed recent FSF sources, which also have these things deleted.
author ben
date Thu, 04 Nov 2004 23:08:28 +0000
parents 04bc9d2f42c7
children ab71ad6ff3dd
comparison
equal deleted inserted replaced
2366:2a392e0c390a 2367:ecf1ebac70d8
1 /* Portable data dumper for XEmacs. 1 /* Portable data dumper for XEmacs.
2 Copyright (C) 1999-2000 Olivier Galibert 2 Copyright (C) 1999-2000 Olivier Galibert
3 Copyright (C) 2001 Martin Buchholz 3 Copyright (C) 2001 Martin Buchholz
4 Copyright (C) 2001, 2002, 2003 Ben Wing. 4 Copyright (C) 2001, 2002, 2003, 2004 Ben Wing.
5 5
6 This file is part of XEmacs. 6 This file is part of XEmacs.
7 7
8 XEmacs is free software; you can redistribute it and/or modify it 8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */ 21 Boston, MA 02111-1307, USA. */
22 22
23 /* Synched up with: Not in FSF. */ 23 /* Synched up with: Not in FSF. */
24 24
25 /* !!#### Not yet Mule-ized */ 25 /* This file has been Mule-ized, Ben Wing, 10-10-04. */
26
27 /* #### Put in much more assertions. Whenever we store fixups in the
28 process or writing out data, make sure the fixups (offsets) point to the
29 beginning of an object, i.e. are registered. Same whenever we read in
30 -- verify offsets as registered, and when compute a fixup, verify the
31 pointer is pointing within the pdump area. registered and check within
32 pdump area. For specific types of pointers (e.g. to Lisp_Objects),
33 check if they're pointing to the right kinds of types. It should be
34 possible to check that a putative Lisp_Object is really a Lisp_Object
35 since it will follow a strict format in its header. */
26 36
27 #include <config.h> 37 #include <config.h>
28 #include "lisp.h" 38 #include "lisp.h"
29 39
30 #include "specifier.h" 40 #include "specifier.h"
43 #include "dump-data.h" 53 #include "dump-data.h"
44 #endif 54 #endif
45 55
46 typedef struct 56 typedef struct
47 { 57 {
48 const void *varaddress; 58 const void *blockaddr;
49 Bytecount size; 59 Bytecount size;
50 const struct memory_description *desc; 60 const struct memory_description *desc;
51 } pdump_root_block; 61 } pdump_root_block;
52 62
53 typedef struct 63 typedef struct
57 67
58 typedef struct 68 typedef struct
59 { 69 {
60 void **ptraddress; 70 void **ptraddress;
61 const struct sized_memory_description *desc; 71 const struct sized_memory_description *desc;
62 } pdump_root_struct_ptr; 72 } pdump_root_block_ptr;
63 73
64 typedef struct 74 typedef struct
65 { 75 {
66 Dynarr_declare (pdump_root_struct_ptr); 76 Dynarr_declare (pdump_root_block_ptr);
67 } pdump_root_struct_ptr_dynarr; 77 } pdump_root_block_ptr_dynarr;
68 78
69 typedef struct 79 typedef struct
70 { 80 {
71 Lisp_Object *address; 81 Lisp_Object *address;
72 Lisp_Object value; 82 Lisp_Object value;
73 } pdump_static_Lisp_Object; 83 } pdump_static_Lisp_Object;
74 84
75 typedef struct 85 typedef struct
76 { 86 {
77 char **address; /* char * for ease of doing relocation */ 87 Rawbyte **address; /* Rawbyte * for ease of doing relocation */
78 char * value; 88 Rawbyte * value;
79 } pdump_static_pointer; 89 } pdump_static_pointer;
80 90
81 static pdump_root_block_dynarr *pdump_root_blocks; 91 static pdump_root_block_dynarr *pdump_root_blocks;
82 static pdump_root_struct_ptr_dynarr *pdump_root_struct_ptrs; 92 static pdump_root_block_ptr_dynarr *pdump_root_block_ptrs;
83 static Lisp_Object_ptr_dynarr *pdump_root_lisp_objects; 93 static Lisp_Object_ptr_dynarr *pdump_root_lisp_objects;
84 static Lisp_Object_ptr_dynarr *pdump_weak_object_chains; 94 static Lisp_Object_ptr_dynarr *pdump_weak_object_chains;
85 95
86 /* Mark SIZE bytes at non-heap address VARADDRESS for dumping, described 96 /* Mark SIZE bytes at non-heap address BLOCKADDR for dumping, described
87 by DESC. */ 97 by DESC. Called by outside callers during XEmacs initialization. */
98
88 void 99 void
89 dump_add_root_block (const void *varaddress, Bytecount size, 100 dump_add_root_block (const void *blockaddr, Bytecount size,
90 const struct memory_description *desc) 101 const struct memory_description *desc)
91 { 102 {
92 pdump_root_block info; 103 pdump_root_block info;
93 info.varaddress = varaddress; 104 info.blockaddr = blockaddr;
94 info.size = size; 105 info.size = size;
95 info.desc = desc; 106 info.desc = desc;
96 if (pdump_root_blocks == NULL) 107 if (pdump_root_blocks == NULL)
97 pdump_root_blocks = Dynarr_new (pdump_root_block); 108 pdump_root_blocks = Dynarr_new (pdump_root_block);
98 Dynarr_add (pdump_root_blocks, info); 109 Dynarr_add (pdump_root_blocks, info);
99 } 110 }
100 111
101 /* Mark the struct described by DESC and pointed to by the pointer at 112 /* Mark the block described by DESC and pointed to by the pointer at
102 non-heap address VARADDRESS for dumping. 113 non-heap address PTRADDRESS for dumping.
103 All the objects reachable from this pointer will also be dumped. */ 114 All the objects reachable from this pointer will also be dumped.
115 Called by outside callers during XEmacs initialization. */
104 void 116 void
105 dump_add_root_struct_ptr (void *ptraddress, 117 dump_add_root_block_ptr (void *ptraddress,
106 const struct sized_memory_description *desc) 118 const struct sized_memory_description *desc)
107 { 119 {
108 pdump_root_struct_ptr info; 120 pdump_root_block_ptr info;
109 info.ptraddress = (void **) ptraddress; 121 info.ptraddress = (void **) ptraddress;
110 info.desc = desc; 122 info.desc = desc;
111 if (pdump_root_struct_ptrs == NULL) 123 if (pdump_root_block_ptrs == NULL)
112 pdump_root_struct_ptrs = Dynarr_new (pdump_root_struct_ptr); 124 pdump_root_block_ptrs = Dynarr_new (pdump_root_block_ptr);
113 Dynarr_add (pdump_root_struct_ptrs, info); 125 Dynarr_add (pdump_root_block_ptrs, info);
114 } 126 }
115 127
116 /* Mark the Lisp_Object at non-heap address VARADDRESS for dumping. 128 /* Mark the Lisp_Object at non-heap address VARADDRESS for dumping.
117 All the objects reachable from this var will also be dumped. */ 129 All the objects reachable from this var will also be dumped.
130 Called by outside callers during XEmacs initialization. */
118 void 131 void
119 dump_add_root_lisp_object (Lisp_Object *varaddress) 132 dump_add_root_lisp_object (Lisp_Object *varaddress)
120 { 133 {
121 if (pdump_root_lisp_objects == NULL) 134 if (pdump_root_lisp_objects == NULL)
122 pdump_root_lisp_objects = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); 135 pdump_root_lisp_objects = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
123 Dynarr_add (pdump_root_lisp_objects, varaddress); 136 Dynarr_add (pdump_root_lisp_objects, varaddress);
124 } 137 }
125 138
126 /* Mark the list pointed to by the Lisp_Object at VARADDRESS for dumping. */ 139 /* Mark the list pointed to by the Lisp_Object at VARADDRESS for dumping.
140 Called by outside callers during XEmacs initialization. */
127 void 141 void
128 dump_add_weak_object_chain (Lisp_Object *varaddress) 142 dump_add_weak_object_chain (Lisp_Object *varaddress)
129 { 143 {
130 if (pdump_weak_object_chains == NULL) 144 if (pdump_weak_object_chains == NULL)
131 pdump_weak_object_chains = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); 145 pdump_weak_object_chains = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
151 PDUMP_ALIGN_OUTPUT (type); \ 165 PDUMP_ALIGN_OUTPUT (type); \
152 PDUMP_WRITE (type, object); \ 166 PDUMP_WRITE (type, object); \
153 } while (0) 167 } while (0)
154 168
155 #define PDUMP_READ(ptr, type) \ 169 #define PDUMP_READ(ptr, type) \
156 (((type *) (ptr = (char*) (((type *) ptr) + 1)))[-1]) 170 (((type *) (ptr = (Rawbyte *) (((type *) ptr) + 1)))[-1])
157 171
158 #define PDUMP_READ_ALIGNED(ptr, type) \ 172 #define PDUMP_READ_ALIGNED(ptr, type) \
159 ((ptr = (char *) ALIGN_PTR (ptr, type)), PDUMP_READ (ptr, type)) 173 ((ptr = (Rawbyte *) ALIGN_PTR (ptr, type)), PDUMP_READ (ptr, type))
160 174
161 175
162 176
163 typedef struct 177 typedef struct
164 { 178 {
165 const struct memory_description *desc; 179 const struct memory_description *desc;
166 int count; 180 int count;
167 } pdump_reloc_table; 181 } pdump_reloc_table;
168 182
169 static char *pdump_rt_list = 0; 183 static Rawbyte *pdump_rt_list = 0;
170 184
171 void 185 void
172 pdump_objects_unmark (void) 186 pdump_objects_unmark (void)
173 { 187 {
174 int i; 188 int i;
175 char *p = pdump_rt_list; 189 Rawbyte *p = pdump_rt_list;
176 if (p) 190 if (p)
177 for (;;) 191 for (;;)
178 { 192 {
179 pdump_reloc_table *rt = (pdump_reloc_table *)p; 193 pdump_reloc_table *rt = (pdump_reloc_table *)p;
180 p += sizeof (pdump_reloc_table); 194 p += sizeof (pdump_reloc_table);
194 208
195 209
196 /* The structure of the dump file looks like this: 210 /* The structure of the dump file looks like this:
197 0 - header 211 0 - header
198 - dumped objects 212 - dumped objects
199 stab_offset - nb_root_struct_ptrs*struct(void *, adr) 213 stab_offset - nb_root_block_ptrs*struct(void *, adr)
200 for global pointers to structures 214 for global pointers to heap blocks
201 - nb_root_blocks*struct(void *, size, info) for global 215 - nb_root_blocks*struct(void *, size, info) for global
202 objects to restore 216 data-segment blocks to restore
203 - relocation table 217 - relocation table
204 - root lisp object address/value couples with the count 218 - root lisp object address/value couples with the count
205 preceding the list 219 preceding the list
206 */ 220 */
207 221
213 { 227 {
214 char signature[PDUMP_SIGNATURE_LEN]; 228 char signature[PDUMP_SIGNATURE_LEN];
215 unsigned int id; 229 unsigned int id;
216 EMACS_UINT stab_offset; 230 EMACS_UINT stab_offset;
217 EMACS_UINT reloc_address; 231 EMACS_UINT reloc_address;
218 int nb_root_struct_ptrs; 232 int nb_root_block_ptrs;
219 int nb_root_blocks; 233 int nb_root_blocks;
220 } pdump_header; 234 } pdump_header;
221 235
222 char *pdump_start; 236 Rawbyte *pdump_start;
223 char *pdump_end; 237 Rawbyte *pdump_end;
224 static Bytecount pdump_length; 238 static Bytecount pdump_length;
225 239
226 #ifdef WIN32_NATIVE 240 #ifdef WIN32_NATIVE
227 /* Handle for the dump file */ 241 /* Handle for the dump file */
228 static HANDLE pdump_hFile = INVALID_HANDLE_VALUE; 242 static HANDLE pdump_hFile = INVALID_HANDLE_VALUE;
244 pdump_size_to_align (Bytecount size) 258 pdump_size_to_align (Bytecount size)
245 { 259 {
246 return pdump_align_table[size % countof (pdump_align_table)]; 260 return pdump_align_table[size % countof (pdump_align_table)];
247 } 261 }
248 262
249 typedef struct pdump_entry_list_elt 263 /************************************************************************/
250 { 264 /* Registering memory blocks */
251 struct pdump_entry_list_elt *next; 265 /************************************************************************/
266
267 /* "Registering" or recording a heap memory block (which will need to be
268 written out, reloaded and relocated, and to which there may be pointers
269 from other heap blocks or from the data segment) happens both in a list
270 and in a hash table. There is a single hash table covering all
271 registered blocks, but different lists for different kinds of blocks.
272 There is one list for "opaque data" (stuff identified as
273 XD_OPAQUE_DATA_PTR, XD_ASCII_STRING, XD_DOC_STRING), one list for each
274 type of Lisp object, and one list for each different memory descriptor.
275 This lets similar-sized and aligned objects be grouped together when
276 they are written out, to save space.
277
278 pdump_block_list is a list keeping track of registered memory blocks.
279 pdump_block_list_elt is a single entry through the list, and the list is
280 threaded through the NEXT pointer. The information in this list
281 associated with a particular block of memory is
282
283 -- address of the beginning
284 -- number of elements at that address
285 -- size of each element
286 -- offset to this block in the dumped data
287
288 pdump_desc_list is a list keeping track of the various descriptions
289 that we've seen. The primary purpose of this is so that memory blocks
290 can be grouped depending on the particular memory description
291 appropriate for them. The format of the list is different from
292 pdump_block_list -- a single array is used. (#### Dynarr should have
293 been used!!!). The information in this list associated with a
294 description is
295
296 -- pointer to the description
297 -- a pdump_block_list of blocks using that description
298
299 Functions for working with lists of memory blocks:
300
301 -- Add a memory block to a list using pdump_add_block()
302
303 -- Get a memory block from a pointer to its beginning using
304 pdump_get_block(). This uses the hash table, which lists everything.
305
306 -- Return the memory-block list (pdump_block_list) associated with a
307 descriptor, using pdump_get_block_list(). If no entry found in the
308 pdump_desc_list, add a new one.
309
310 */
311
312 typedef struct pdump_block_list_elt
313 {
314 struct pdump_block_list_elt *next;
252 const void *obj; 315 const void *obj;
253 Bytecount size; 316 Bytecount size;
254 int count; 317 int count;
255 EMACS_INT save_offset; 318 EMACS_INT save_offset;
256 } pdump_entry_list_elt; 319 } pdump_block_list_elt;
257 320
258 typedef struct 321 typedef struct
259 { 322 {
260 pdump_entry_list_elt *first; 323 pdump_block_list_elt *first;
261 int align; 324 int align;
262 int count; 325 int count;
263 } pdump_entry_list; 326 } pdump_block_list;
264 327
265 typedef struct pdump_struct_list_elt 328 typedef struct pdump_desc_list_elt
266 { 329 {
267 pdump_entry_list list; 330 pdump_block_list list;
268 const struct memory_description *desc; 331 const struct memory_description *desc;
269 } pdump_struct_list_elt; 332 } pdump_desc_list_elt;
270 333
271 typedef struct 334 typedef struct
272 { 335 {
273 pdump_struct_list_elt *list; 336 pdump_desc_list_elt *list;
274 int count; 337 int count;
275 int size; 338 int size;
276 } pdump_struct_list; 339 } pdump_desc_list;
277 340
278 static pdump_entry_list *pdump_object_table; 341 static pdump_block_list *pdump_object_table;
279 static pdump_entry_list pdump_opaque_data_list; 342 static pdump_block_list pdump_opaque_data_list;
280 static pdump_struct_list pdump_struct_table; 343 static pdump_desc_list pdump_desc_table;
281 344
282 static int *pdump_alert_undump_object; 345 static int *pdump_alert_undump_object;
283 346
284 static unsigned long cur_offset; 347 static unsigned long cur_offset;
285 static Bytecount max_size; 348 static Bytecount max_size;
287 static void *pdump_buf; 350 static void *pdump_buf;
288 static FILE *pdump_out; 351 static FILE *pdump_out;
289 352
290 #define PDUMP_HASHSIZE 200001 353 #define PDUMP_HASHSIZE 200001
291 354
292 static pdump_entry_list_elt **pdump_hash; 355 static pdump_block_list_elt **pdump_hash;
293 356
294 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */ 357 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
295 static int 358 static int
296 pdump_make_hash (const void *obj) 359 pdump_make_hash (const void *obj)
297 { 360 {
298 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE; 361 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
299 } 362 }
300 363
301 static pdump_entry_list_elt * 364 /* Return the entry for an already-registered memory block at OBJ,
302 pdump_get_entry (const void *obj) 365 or NULL if none. */
366
367 static pdump_block_list_elt *
368 pdump_get_block (const void *obj)
303 { 369 {
304 int pos = pdump_make_hash (obj); 370 int pos = pdump_make_hash (obj);
305 pdump_entry_list_elt *e; 371 pdump_block_list_elt *e;
306 372
307 assert (obj != 0); 373 assert (obj != 0);
308 374
309 while ((e = pdump_hash[pos]) != 0) 375 while ((e = pdump_hash[pos]) != 0)
310 { 376 {
316 pos = 0; 382 pos = 0;
317 } 383 }
318 return 0; 384 return 0;
319 } 385 }
320 386
387 /* Register a new memory block on Return the entry for an already-registered heap (?) memory block at OBJ,
388 or NULL if none. */
389
321 static void 390 static void
322 pdump_add_entry (pdump_entry_list *list, const void *obj, Bytecount size, 391 pdump_add_block (pdump_block_list *list, const void *obj, Bytecount size,
323 int count) 392 int count)
324 { 393 {
325 pdump_entry_list_elt *e; 394 pdump_block_list_elt *e;
326 int pos = pdump_make_hash (obj); 395 int pos = pdump_make_hash (obj);
327 396
328 while ((e = pdump_hash[pos]) != 0) 397 while ((e = pdump_hash[pos]) != 0)
329 { 398 {
330 if (e->obj == obj) 399 if (e->obj == obj)
333 pos++; 402 pos++;
334 if (pos == PDUMP_HASHSIZE) 403 if (pos == PDUMP_HASHSIZE)
335 pos = 0; 404 pos = 0;
336 } 405 }
337 406
338 e = xnew (pdump_entry_list_elt); 407 e = xnew (pdump_block_list_elt);
339 408
340 e->next = list->first; 409 e->next = list->first;
341 e->obj = obj; 410 e->obj = obj;
342 e->size = size; 411 e->size = size;
343 e->count = count; 412 e->count = count;
352 if (align < list->align) 421 if (align < list->align)
353 list->align = align; 422 list->align = align;
354 } 423 }
355 } 424 }
356 425
357 static pdump_entry_list * 426 static pdump_block_list *
358 pdump_get_entry_list (const struct memory_description *desc) 427 pdump_get_block_list (const struct memory_description *desc)
359 { 428 {
360 int i; 429 int i;
361 for (i=0; i<pdump_struct_table.count; i++) 430 for (i=0; i<pdump_desc_table.count; i++)
362 if (pdump_struct_table.list[i].desc == desc) 431 if (pdump_desc_table.list[i].desc == desc)
363 return &pdump_struct_table.list[i].list; 432 return &pdump_desc_table.list[i].list;
364 433
365 if (pdump_struct_table.size <= pdump_struct_table.count) 434 if (pdump_desc_table.size <= pdump_desc_table.count)
366 { 435 {
367 if (pdump_struct_table.size == -1) 436 if (pdump_desc_table.size == -1)
368 pdump_struct_table.size = 10; 437 pdump_desc_table.size = 10;
369 else 438 else
370 pdump_struct_table.size = pdump_struct_table.size * 2; 439 pdump_desc_table.size = pdump_desc_table.size * 2;
371 pdump_struct_table.list = (pdump_struct_list_elt *) 440 pdump_desc_table.list = (pdump_desc_list_elt *)
372 xrealloc (pdump_struct_table.list, 441 xrealloc (pdump_desc_table.list,
373 pdump_struct_table.size * sizeof (pdump_struct_list_elt)); 442 pdump_desc_table.size * sizeof (pdump_desc_list_elt));
374 } 443 }
375 pdump_struct_table.list[pdump_struct_table.count].list.first = 0; 444 pdump_desc_table.list[pdump_desc_table.count].list.first = 0;
376 pdump_struct_table.list[pdump_struct_table.count].list.align = ALIGNOF (max_align_t); 445 pdump_desc_table.list[pdump_desc_table.count].list.align = ALIGNOF (max_align_t);
377 pdump_struct_table.list[pdump_struct_table.count].list.count = 0; 446 pdump_desc_table.list[pdump_desc_table.count].list.count = 0;
378 pdump_struct_table.list[pdump_struct_table.count].desc = desc; 447 pdump_desc_table.list[pdump_desc_table.count].desc = desc;
379 448
380 return &pdump_struct_table.list[pdump_struct_table.count++].list; 449 return &pdump_desc_table.list[pdump_desc_table.count++].list;
381 } 450 }
382 451
383 static struct 452 static struct
384 { 453 {
385 struct lrecord_header *obj; 454 struct lrecord_header *obj;
437 backtrace[me].position = 0; 506 backtrace[me].position = 0;
438 backtrace[me].offset = 0; 507 backtrace[me].offset = 0;
439 } 508 }
440 509
441 static void pdump_register_object (Lisp_Object obj); 510 static void pdump_register_object (Lisp_Object obj);
442 static void pdump_register_struct_contents (const void *data, 511 static void pdump_register_block_contents (const void *data,
443 const struct sized_memory_description * 512 Bytecount size,
444 sdesc, 513 const struct memory_description *
445 int count); 514 desc,
446 static void pdump_register_struct (const void *data, 515 int count);
447 const struct sized_memory_description *sdesc, 516 static void pdump_register_block (const void *data,
448 int count); 517 Bytecount size,
518 const struct memory_description *desc,
519 int count);
449 520
450 static void 521 static void
451 pdump_register_sub (const void *data, const struct memory_description *desc) 522 pdump_register_sub (const void *data, const struct memory_description *desc)
452 { 523 {
453 int pos; 524 int pos;
456 for (pos = 0; desc[pos].type != XD_END; pos++) 527 for (pos = 0; desc[pos].type != XD_END; pos++)
457 { 528 {
458 const struct memory_description *desc1 = &desc[pos]; 529 const struct memory_description *desc1 = &desc[pos];
459 EMACS_INT offset = lispdesc_indirect_count (desc1->offset, desc, 530 EMACS_INT offset = lispdesc_indirect_count (desc1->offset, desc,
460 data); 531 data);
461 const void *rdata = (const char *) data + offset; 532 const void *rdata = (const Rawbyte *) data + offset;
462 533
463 backtrace[me].position = pos; 534 backtrace[me].position = pos;
464 backtrace[me].offset = offset; 535 backtrace[me].offset = offset;
465 536
466 union_switcheroo: 537 union_switcheroo:
482 case XD_OPAQUE_DATA_PTR: 553 case XD_OPAQUE_DATA_PTR:
483 { 554 {
484 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc, 555 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
485 data); 556 data);
486 557
487 pdump_add_entry (&pdump_opaque_data_list, 558 pdump_add_block (&pdump_opaque_data_list,
488 *(void **)rdata, count, 1); 559 *(void **)rdata, count, 1);
489 break; 560 break;
490 } 561 }
491 case XD_C_STRING: 562 case XD_ASCII_STRING:
492 { 563 {
493 const char *str = * (const char **) rdata; 564 const Ascbyte *str = * (const Ascbyte **) rdata;
494 if (str) 565 if (str)
495 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str) + 1, 566 pdump_add_block (&pdump_opaque_data_list, str, strlen (str) + 1,
496 1); 567 1);
497 break; 568 break;
498 } 569 }
499 case XD_DOC_STRING: 570 case XD_DOC_STRING:
500 { 571 {
501 const char *str = * (const char **) rdata; 572 const Ascbyte *str = * (const Ascbyte **) rdata;
502 if ((EMACS_INT) str > 0) 573 if ((EMACS_INT) str > 0)
503 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str) + 1, 574 pdump_add_block (&pdump_opaque_data_list, str, strlen (str) + 1,
504 1); 575 1);
505 break; 576 break;
506 } 577 }
507 case XD_LISP_OBJECT: 578 case XD_LISP_OBJECT:
508 { 579 {
509 const Lisp_Object *pobj = (const Lisp_Object *) rdata; 580 const Lisp_Object *pobj = (const Lisp_Object *) rdata;
510 581
511 assert (desc1->data1 == 0); 582 assert (desc1->data1 == 0);
512 583
513 backtrace[me].offset = (const char *) pobj - (const char *) data; 584 backtrace[me].offset =
585 (const Rawbyte *) pobj - (const Rawbyte *) data;
514 pdump_register_object (*pobj); 586 pdump_register_object (*pobj);
515 break; 587 break;
516 } 588 }
517 case XD_LISP_OBJECT_ARRAY: 589 case XD_LISP_OBJECT_ARRAY:
518 { 590 {
524 { 596 {
525 const Lisp_Object *pobj = ((const Lisp_Object *) rdata) + i; 597 const Lisp_Object *pobj = ((const Lisp_Object *) rdata) + i;
526 Lisp_Object dobj = *pobj; 598 Lisp_Object dobj = *pobj;
527 599
528 backtrace[me].offset = 600 backtrace[me].offset =
529 (const char *) pobj - (const char *) data; 601 (const Rawbyte *) pobj - (const Rawbyte *) data;
530 pdump_register_object (dobj); 602 pdump_register_object (dobj);
531 } 603 }
532 break; 604 break;
533 } 605 }
534 case XD_STRUCT_PTR: 606 case XD_BLOCK_PTR:
535 { 607 {
536 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc, 608 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
537 data); 609 data);
538 const struct sized_memory_description *sdesc = 610 const struct sized_memory_description *sdesc =
539 lispdesc_indirect_description (data, desc1->data2); 611 lispdesc_indirect_description (data, desc1->data2);
540 const char *dobj = *(const char **)rdata; 612 const Rawbyte *dobj = *(const Rawbyte **)rdata;
541 if (dobj) 613 if (dobj)
542 pdump_register_struct (dobj, sdesc, count); 614 pdump_register_block (dobj, sdesc->size, sdesc->description,
615 count);
543 break; 616 break;
544 } 617 }
545 case XD_STRUCT_ARRAY: 618 case XD_BLOCK_ARRAY:
546 { 619 {
547 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc, 620 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
548 data); 621 data);
549 const struct sized_memory_description *sdesc = 622 const struct sized_memory_description *sdesc =
550 lispdesc_indirect_description (data, desc1->data2); 623 lispdesc_indirect_description (data, desc1->data2);
551 624
552 pdump_register_struct_contents (rdata, sdesc, count); 625 pdump_register_block_contents (rdata, sdesc->size,
626 sdesc->description, count);
553 break; 627 break;
554 } 628 }
555 case XD_UNION: 629 case XD_UNION:
556 case XD_UNION_DYNAMIC_SIZE: 630 case XD_UNION_DYNAMIC_SIZE:
557 desc1 = lispdesc_process_xd_union (desc1, desc, data); 631 desc1 = lispdesc_process_xd_union (desc1, desc, data);
576 650
577 objh = XRECORD_LHEADER (obj); 651 objh = XRECORD_LHEADER (obj);
578 if (!objh) 652 if (!objh)
579 return; 653 return;
580 654
581 if (pdump_get_entry (objh)) 655 if (pdump_get_block (objh))
582 return; 656 return;
583 657
584 imp = LHEADER_IMPLEMENTATION (objh); 658 imp = LHEADER_IMPLEMENTATION (objh);
585 659
586 if (imp->description 660 if (imp->description
587 && RECORD_DUMPABLE (objh)) 661 && RECORD_DUMPABLE (objh))
588 { 662 {
589 pdump_bump_depth (); 663 pdump_bump_depth ();
590 backtrace[pdump_depth - 1].obj = objh; 664 backtrace[pdump_depth - 1].obj = objh;
591 pdump_add_entry (pdump_object_table + objh->type, 665 pdump_add_block (pdump_object_table + objh->type,
592 objh, detagged_lisp_object_size (objh), 1); 666 objh, detagged_lisp_object_size (objh), 1);
593 pdump_register_sub (objh, imp->description); 667 pdump_register_sub (objh, imp->description);
594 --pdump_depth; 668 --pdump_depth;
595 } 669 }
596 else 670 else
599 stderr_out ("Undumpable object type : %s\n", imp->name); 673 stderr_out ("Undumpable object type : %s\n", imp->name);
600 pdump_backtrace (); 674 pdump_backtrace ();
601 } 675 }
602 } 676 }
603 677
604 /* Register the referenced objects in the array of COUNT objects of 678 /* Register the referenced objects in the array of COUNT blocks located at
605 located at DATA; each object is described by SDESC. "Object" here 679 DATA; each block is described by SIZE and DESC. "Block" here simply
606 simply means any block of memory; it need not actually be a C 680 means any block of memory.
607 "struct". It could be a single integer or Lisp_Object, for
608 example, as long as the description is accurate.
609 681
610 This does not register the block of memory itself; it may, for 682 This does not register the block of memory itself; it may, for
611 example, be an array of structures inlined in another memory block 683 example, be an array of structures inlined in another memory block
612 and thus should not be registered. See pdump_register_struct(), 684 and thus should not be registered. See pdump_register_block(),
613 which does register the memory block. */ 685 which does register the memory block. */
614 686
615 static void 687 static void
616 pdump_register_struct_contents (const void *data, 688 pdump_register_block_contents (const void *data,
617 const struct sized_memory_description *sdesc, 689 Bytecount size,
618 int count) 690 const struct memory_description *desc,
619 691 int count)
620 { 692 {
621 int i; 693 int i;
622 Bytecount elsize; 694 Bytecount elsize;
623 695
624 pdump_bump_depth (); 696 pdump_bump_depth ();
625 elsize = lispdesc_structure_size (data, sdesc); 697 elsize = lispdesc_block_size_1 (data, size, desc);
626 for (i = 0; i < count; i++) 698 for (i = 0; i < count; i++)
627 { 699 {
628 pdump_register_sub (((char *) data) + elsize * i, sdesc->description); 700 pdump_register_sub (((Rawbyte *) data) + elsize * i, desc);
629 } 701 }
630 --pdump_depth; 702 --pdump_depth;
631 } 703 }
632 704
633 /* Register the array of COUNT objects of located at DATA; each object is 705 /* Register the array of COUNT blocks located at DATA; each block is
634 described by SDESC. "Object" here simply means any block of memory; 706 described by SDESC. "Block" here simply means any block of memory,
635 it need not actually be a C "struct". It could be a single integer 707 which is more accurate and less confusing than terms like `struct' and
636 or Lisp_Object, for example, as long as the description is accurate. 708 `object'. A `block' need not actually be a C "struct". It could be a
637 709 single integer or Lisp_Object, for example, as long as the description
638 This is like pdump_register_struct_contents() but also registers 710 is accurate.
711
712 This is like pdump_register_block_contents() but also registers
639 the memory block itself. */ 713 the memory block itself. */
640 714
641 static void 715 static void
642 pdump_register_struct (const void *data, 716 pdump_register_block (const void *data,
643 const struct sized_memory_description *sdesc, 717 Bytecount size,
644 int count) 718 const struct memory_description *desc,
645 { 719 int count)
646 if (data && !pdump_get_entry (data)) 720 {
647 { 721 if (data && !pdump_get_block (data))
648 pdump_add_entry (pdump_get_entry_list (sdesc->description), data, 722 {
649 lispdesc_structure_size (data, sdesc), count); 723 pdump_add_block (pdump_get_block_list (desc), data,
650 724 lispdesc_block_size_1 (data, size, desc), count);
651 pdump_register_struct_contents (data, sdesc, count); 725 pdump_register_block_contents (data, size, desc, count);
652 } 726 }
653 } 727 }
654 728
655 /* Store the already-calculated new pointer offsets for all pointers in the 729 /* Store the already-calculated new pointer offsets for all pointers in the
656 COUNT contiguous blocks of memory, each described by DESC and of size 730 COUNT contiguous blocks of memory, each described by DESC and of size
657 SIZE, whose original is located at ORIG_DATA and the modifiable copy at 731 SIZE, whose original is located at ORIG_DATA and the modifiable copy at
658 DATA. We examine the description to figure out where the pointers are, 732 DATA. We examine the description to figure out where the pointers are,
659 and then look up the replacement values using pdump_get_entry(). 733 and then look up the replacement values using pdump_get_block().
660 734
661 This is done just before writing the modified block of memory to the 735 This is done just before writing the modified block of memory to the
662 dump file. The new pointer offsets have been carefully calculated so 736 dump file. The new pointer offsets have been carefully calculated so
663 that the data being pointed gets written at that offset in the dump 737 that the data being pointed gets written at that offset in the dump
664 file. That way, the dump file is a correct memory image except perhaps 738 file. That way, the dump file is a correct memory image except perhaps
686 int pos, i; 760 int pos, i;
687 /* Process each block one by one */ 761 /* Process each block one by one */
688 for (i = 0; i < count; i++) 762 for (i = 0; i < count; i++)
689 { 763 {
690 /* CUR points to the beginning of each block in the new data. */ 764 /* CUR points to the beginning of each block in the new data. */
691 char *cur = ((char *)data) + i*size; 765 Rawbyte *cur = ((Rawbyte *)data) + i * size;
692 /* Scan each line of the description for relocatable pointers */ 766 /* Scan each line of the description for relocatable pointers */
693 for (pos = 0; desc[pos].type != XD_END; pos++) 767 for (pos = 0; desc[pos].type != XD_END; pos++)
694 { 768 {
695 /* RDATA points to the beginning of each element in the new data. */ 769 /* RDATA points to the beginning of each element in the new data. */
696 const struct memory_description *desc1 = &desc[pos]; 770 const struct memory_description *desc1 = &desc[pos];
717 orig_data); 791 orig_data);
718 * (int *) rdata = val; 792 * (int *) rdata = val;
719 break; 793 break;
720 } 794 }
721 case XD_OPAQUE_DATA_PTR: 795 case XD_OPAQUE_DATA_PTR:
722 case XD_C_STRING: 796 case XD_ASCII_STRING:
723 case XD_STRUCT_PTR: 797 case XD_BLOCK_PTR:
724 { 798 {
725 void *ptr = * (void **) rdata; 799 void *ptr = * (void **) rdata;
726 if (ptr) 800 if (ptr)
727 * (EMACS_INT *) rdata = pdump_get_entry (ptr)->save_offset; 801 * (EMACS_INT *) rdata = pdump_get_block (ptr)->save_offset;
728 break; 802 break;
729 } 803 }
730 case XD_LO_LINK: 804 case XD_LO_LINK:
731 { 805 {
732 /* As described in lrecord.h, this is a weak link. 806 /* As described in lrecord.h, this is a weak link.
736 intermediate objects will be written out, so we 810 intermediate objects will be written out, so we
737 traverse down the chain of objects until we find a 811 traverse down the chain of objects until we find a
738 referenced one. (The Qnil or Qunbound that ends the 812 referenced one. (The Qnil or Qunbound that ends the
739 chain will always be a referenced object.) */ 813 chain will always be a referenced object.) */
740 Lisp_Object obj = * (Lisp_Object *) rdata; 814 Lisp_Object obj = * (Lisp_Object *) rdata;
741 pdump_entry_list_elt *elt1; 815 pdump_block_list_elt *elt1;
742 /* #### Figure out how to handle indirect offsets here. 816 /* #### Figure out how to handle indirect offsets here.
743 #### In general, when computing indirect counts, do we 817 #### In general, when computing indirect counts, do we
744 really need to use the orig_data pointer? Why not just 818 really need to use the orig_data pointer? Why not just
745 use the new stuff? 819 use the new stuff?
746 820
750 should change the other places to DATA to emphasize 824 should change the other places to DATA to emphasize
751 this. */ 825 this. */
752 assert (!XD_IS_INDIRECT (desc1->offset)); 826 assert (!XD_IS_INDIRECT (desc1->offset));
753 for (;;) 827 for (;;)
754 { 828 {
755 elt1 = pdump_get_entry (XRECORD_LHEADER (obj)); 829 elt1 = pdump_get_block (XRECORD_LHEADER (obj));
756 if (elt1) 830 if (elt1)
757 break; 831 break;
758 obj = * (Lisp_Object *) (desc1->offset + 832 obj = * (Lisp_Object *) (desc1->offset +
759 (char *)(XRECORD_LHEADER (obj))); 833 (Rawbyte *)
834 (XRECORD_LHEADER (obj)));
760 } 835 }
761 * (EMACS_INT *) rdata = elt1->save_offset; 836 * (EMACS_INT *) rdata = elt1->save_offset;
762 break; 837 break;
763 } 838 }
764 case XD_LISP_OBJECT: 839 case XD_LISP_OBJECT:
767 842
768 assert (desc1->data1 == 0); 843 assert (desc1->data1 == 0);
769 844
770 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj)) 845 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
771 * (EMACS_INT *) pobj = 846 * (EMACS_INT *) pobj =
772 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset; 847 pdump_get_block (XRECORD_LHEADER (*pobj))->save_offset;
773 break; 848 break;
774 } 849 }
775 case XD_LISP_OBJECT_ARRAY: 850 case XD_LISP_OBJECT_ARRAY:
776 { 851 {
777 EMACS_INT num = lispdesc_indirect_count (desc1->data1, desc, 852 EMACS_INT num = lispdesc_indirect_count (desc1->data1, desc,
782 { 857 {
783 Lisp_Object *pobj = ((Lisp_Object *) rdata) + j; 858 Lisp_Object *pobj = ((Lisp_Object *) rdata) + j;
784 if (POINTER_TYPE_P (XTYPE (*pobj)) && 859 if (POINTER_TYPE_P (XTYPE (*pobj)) &&
785 XRECORD_LHEADER (*pobj)) 860 XRECORD_LHEADER (*pobj))
786 * (EMACS_INT *) pobj = 861 * (EMACS_INT *) pobj =
787 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset; 862 pdump_get_block (XRECORD_LHEADER (*pobj))->save_offset;
788 } 863 }
789 break; 864 break;
790 } 865 }
791 case XD_DOC_STRING: 866 case XD_DOC_STRING:
792 { 867 {
793 EMACS_INT str = *(EMACS_INT *)rdata; 868 EMACS_INT str = *(EMACS_INT *)rdata;
794 if (str > 0) 869 if (str > 0)
795 * (EMACS_INT *) rdata = 870 * (EMACS_INT *) rdata =
796 pdump_get_entry ((void *)str)->save_offset; 871 pdump_get_block ((void *)str)->save_offset;
797 break; 872 break;
798 } 873 }
799 case XD_STRUCT_ARRAY: 874 case XD_BLOCK_ARRAY:
800 { 875 {
801 EMACS_INT num = lispdesc_indirect_count (desc1->data1, desc, 876 EMACS_INT num = lispdesc_indirect_count (desc1->data1, desc,
802 orig_data); 877 orig_data);
803 const struct sized_memory_description *sdesc = 878 const struct sized_memory_description *sdesc =
804 lispdesc_indirect_description (orig_data, desc1->data2); 879 lispdesc_indirect_description (orig_data, desc1->data2);
805 880
806 pdump_store_new_pointer_offsets 881 pdump_store_new_pointer_offsets
807 (num, rdata, 882 (num, rdata,
808 ((char *) rdata - (char *) data) + (char *) orig_data, 883 ((Rawbyte *) rdata - (Rawbyte *) data) +
884 (Rawbyte *) orig_data,
809 sdesc->description, 885 sdesc->description,
810 lispdesc_structure_size 886 lispdesc_block_size
811 (((char *) rdata - (char *) data) + (char *) orig_data, 887 (((Rawbyte *) rdata - (Rawbyte *) data) +
812 sdesc)); 888 (Rawbyte *) orig_data, sdesc));
813 break; 889 break;
814 } 890 }
815 case XD_UNION: 891 case XD_UNION:
816 case XD_UNION_DYNAMIC_SIZE: 892 case XD_UNION_DYNAMIC_SIZE:
817 desc1 = lispdesc_process_xd_union (desc1, desc, orig_data); 893 desc1 = lispdesc_process_xd_union (desc1, desc, orig_data);
832 and then all pointers (this includes Lisp_Objects other than 908 and then all pointers (this includes Lisp_Objects other than
833 integer/character) are relocated to the (pre-computed) offset in 909 integer/character) are relocated to the (pre-computed) offset in
834 the dump file. */ 910 the dump file. */
835 911
836 static void 912 static void
837 pdump_dump_data (pdump_entry_list_elt *elt, 913 pdump_dump_data (pdump_block_list_elt *elt,
838 const struct memory_description *desc) 914 const struct memory_description *desc)
839 { 915 {
840 Bytecount size = elt->size; 916 Bytecount size = elt->size;
841 int count = elt->count; 917 int count = elt->count;
842 if (desc) 918 if (desc)
853 /* Relocate a single memory block at DATA, described by DESC, from its 929 /* Relocate a single memory block at DATA, described by DESC, from its
854 assumed load location to its actual one by adding DELTA to all pointers 930 assumed load location to its actual one by adding DELTA to all pointers
855 in the block. Does not recursively relocate any other memory blocks 931 in the block. Does not recursively relocate any other memory blocks
856 pointed to. (We already have a list of all memory blocks in the dump 932 pointed to. (We already have a list of all memory blocks in the dump
857 file.) This is used once the dump data has been loaded back in, both 933 file.) This is used once the dump data has been loaded back in, both
858 for blocks sitting in the dumped data and in global data objects whose 934 for blocks sitting in the dumped data (former heap blocks) and in global
859 contents have been restored from the dumped data. */ 935 data-sgment blocks whose contents have been restored from the dumped
936 data. */
860 937
861 static void 938 static void
862 pdump_reloc_one (void *data, EMACS_INT delta, 939 pdump_reloc_one (void *data, EMACS_INT delta,
863 const struct memory_description *desc) 940 const struct memory_description *desc)
864 { 941 {
865 int pos; 942 int pos;
866 943
867 for (pos = 0; desc[pos].type != XD_END; pos++) 944 for (pos = 0; desc[pos].type != XD_END; pos++)
868 { 945 {
869 const struct memory_description *desc1 = &desc[pos]; 946 const struct memory_description *desc1 = &desc[pos];
870 void *rdata = (char *) data + lispdesc_indirect_count (desc1->offset, 947 void *rdata =
871 desc, data); 948 (Rawbyte *) data + lispdesc_indirect_count (desc1->offset,
949 desc, data);
872 950
873 union_switcheroo: 951 union_switcheroo:
874 952
875 /* If the flag says don't dump, then don't dump. */ 953 /* If the flag says don't dump, then don't dump. */
876 if ((desc1->flags) & XD_FLAG_NO_PDUMP) 954 if ((desc1->flags) & XD_FLAG_NO_PDUMP)
884 case XD_INT: 962 case XD_INT:
885 case XD_LONG: 963 case XD_LONG:
886 case XD_INT_RESET: 964 case XD_INT_RESET:
887 break; 965 break;
888 case XD_OPAQUE_DATA_PTR: 966 case XD_OPAQUE_DATA_PTR:
889 case XD_C_STRING: 967 case XD_ASCII_STRING:
890 case XD_STRUCT_PTR: 968 case XD_BLOCK_PTR:
891 case XD_LO_LINK: 969 case XD_LO_LINK:
892 { 970 {
893 EMACS_INT ptr = *(EMACS_INT *)rdata; 971 EMACS_INT ptr = *(EMACS_INT *)rdata;
894 if (ptr) 972 if (ptr)
895 *(EMACS_INT *)rdata = ptr+delta; 973 *(EMACS_INT *)rdata = ptr+delta;
901 979
902 assert (desc1->data1 == 0); 980 assert (desc1->data1 == 0);
903 981
904 if (POINTER_TYPE_P (XTYPE (*pobj)) 982 if (POINTER_TYPE_P (XTYPE (*pobj))
905 && ! EQ (*pobj, Qnull_pointer)) 983 && ! EQ (*pobj, Qnull_pointer))
906 *pobj = wrap_pointer_1 ((char *) XPNTR (*pobj) + delta); 984 *pobj = wrap_pointer_1 ((Rawbyte *) XPNTR (*pobj) + delta);
907 985
908 break; 986 break;
909 } 987 }
910 case XD_LISP_OBJECT_ARRAY: 988 case XD_LISP_OBJECT_ARRAY:
911 { 989 {
917 { 995 {
918 Lisp_Object *pobj = (Lisp_Object *) rdata + j; 996 Lisp_Object *pobj = (Lisp_Object *) rdata + j;
919 997
920 if (POINTER_TYPE_P (XTYPE (*pobj)) 998 if (POINTER_TYPE_P (XTYPE (*pobj))
921 && ! EQ (*pobj, Qnull_pointer)) 999 && ! EQ (*pobj, Qnull_pointer))
922 *pobj = wrap_pointer_1 ((char *) XPNTR (*pobj) + delta); 1000 *pobj = wrap_pointer_1 ((Rawbyte *) XPNTR (*pobj) +
1001 delta);
923 } 1002 }
924 break; 1003 break;
925 } 1004 }
926 case XD_DOC_STRING: 1005 case XD_DOC_STRING:
927 { 1006 {
928 EMACS_INT str = *(EMACS_INT *)rdata; 1007 EMACS_INT str = *(EMACS_INT *)rdata;
929 if (str > 0) 1008 if (str > 0)
930 *(EMACS_INT *)rdata = str + delta; 1009 *(EMACS_INT *)rdata = str + delta;
931 break; 1010 break;
932 } 1011 }
933 case XD_STRUCT_ARRAY: 1012 case XD_BLOCK_ARRAY:
934 { 1013 {
935 EMACS_INT num = lispdesc_indirect_count (desc1->data1, desc, 1014 EMACS_INT num = lispdesc_indirect_count (desc1->data1, desc,
936 data); 1015 data);
937 int j; 1016 int j;
938 const struct sized_memory_description *sdesc = 1017 const struct sized_memory_description *sdesc =
939 lispdesc_indirect_description (data, desc1->data2); 1018 lispdesc_indirect_description (data, desc1->data2);
940 Bytecount size = lispdesc_structure_size (rdata, sdesc); 1019 Bytecount size = lispdesc_block_size (rdata, sdesc);
941 1020
942 /* Note: We are recursing over data in the block itself */ 1021 /* Note: We are recursing over data in the block itself */
943 for (j = 0; j < num; j++) 1022 for (j = 0; j < num; j++)
944 pdump_reloc_one ((char *) rdata + j * size, delta, 1023 pdump_reloc_one ((Rawbyte *) rdata + j * size, delta,
945 sdesc->description); 1024 sdesc->description);
946 1025
947 break; 1026 break;
948 } 1027 }
949 case XD_UNION: 1028 case XD_UNION:
958 } 1037 }
959 } 1038 }
960 } 1039 }
961 1040
962 static void 1041 static void
963 pdump_allocate_offset (pdump_entry_list_elt *elt, 1042 pdump_allocate_offset (pdump_block_list_elt *elt,
964 const struct memory_description *UNUSED (desc)) 1043 const struct memory_description *UNUSED (desc))
965 { 1044 {
966 Bytecount size = elt->count * elt->size; 1045 Bytecount size = elt->count * elt->size;
967 elt->save_offset = cur_offset; 1046 elt->save_offset = cur_offset;
968 if (size>max_size) 1047 if (size > max_size)
969 max_size = size; 1048 max_size = size;
970 cur_offset += size; 1049 cur_offset += size;
971 } 1050 }
972 1051
1052 /* Traverse through all the heap blocks, once the "register" stage of
1053 dumping has finished. To compress space as much as possible, we
1054 logically sort all blocks by alignment, hitting all blocks with
1055 alignment == the maximum (which may be 8 bytes, for doubles), then
1056 all blocks with the next lower alignment (4 bytes), etc.
1057
1058 Within each alignment we hit
1059
1060 -- first the Lisp objects, type-by-type
1061
1062 -- then the heap memory blocks that are not Lisp objects, description-by-
1063 description -- i.e. all blocks with the same description will be
1064 placed together
1065
1066 -- then the "opaque" data objects declared as XD_OPAQUE_DATA_PTR,
1067 XD_ASCII_STRING and XD_DOC_STRING.
1068
1069 The idea is to have as little blank space as possible in the laid-out
1070 data.
1071
1072 For each item that we have hit, we process it by calling F, the function
1073 passed it. In dumper.c, pdump_scan_by_alignment() is called twice with
1074 two different functions -- pdump_allocate_offset() in stage 2 to compute
1075 the offset to each block, and pdump_dump_data() in stage 3 to
1076 successively write each block to disk.
1077
1078 It's extremely important that the SAME traversal order gets invoked
1079 in both stage 2 and 3.
1080 */
1081
973 static void 1082 static void
974 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elt *, 1083 pdump_scan_by_alignment (void (*f)(pdump_block_list_elt *,
975 const struct memory_description *)) 1084 const struct memory_description *))
976 { 1085 {
977 int align; 1086 int align;
978 1087
979 for (align = ALIGNOF (max_align_t); align; align>>=1) 1088 for (align = ALIGNOF (max_align_t); align; align>>=1)
980 { 1089 {
981 int i; 1090 int i;
982 pdump_entry_list_elt *elt; 1091 pdump_block_list_elt *elt;
983 1092
984 for (i=0; i<lrecord_type_count; i++) 1093 for (i=0; i<lrecord_type_count; i++)
985 if (pdump_object_table[i].align == align) 1094 if (pdump_object_table[i].align == align)
986 for (elt = pdump_object_table[i].first; elt; elt = elt->next) 1095 for (elt = pdump_object_table[i].first; elt; elt = elt->next)
987 f (elt, lrecord_implementations_table[i]->description); 1096 f (elt, lrecord_implementations_table[i]->description);
988 1097
989 for (i=0; i<pdump_struct_table.count; i++) 1098 for (i=0; i<pdump_desc_table.count; i++)
990 { 1099 {
991 pdump_struct_list_elt list = pdump_struct_table.list[i]; 1100 pdump_desc_list_elt list = pdump_desc_table.list[i];
992 if (list.list.align == align) 1101 if (list.list.align == align)
993 for (elt = list.list.first; elt; elt = elt->next) 1102 for (elt = list.list.first; elt; elt = elt->next)
994 f (elt, list.desc); 1103 f (elt, list.desc);
995 } 1104 }
996 1105
998 if (pdump_size_to_align (elt->size) == align) 1107 if (pdump_size_to_align (elt->size) == align)
999 f (elt, 0); 1108 f (elt, 0);
1000 } 1109 }
1001 } 1110 }
1002 1111
1112 /* Dump out the root block pointers, part of stage 3 (the "WRITE" stage) of
1113 dumping. For each pointer we dump out a structure containing the
1114 location of the pointer and its value, replaced by the appropriate
1115 offset into the dumped data. */
1116
1003 static void 1117 static void
1004 pdump_dump_root_struct_ptrs (void) 1118 pdump_dump_root_block_ptrs (void)
1005 { 1119 {
1006 int i; 1120 int i;
1007 Elemcount count = Dynarr_length (pdump_root_struct_ptrs); 1121 Elemcount count = Dynarr_length (pdump_root_block_ptrs);
1008 pdump_static_pointer *data = alloca_array (pdump_static_pointer, count); 1122 pdump_static_pointer *data = alloca_array (pdump_static_pointer, count);
1009 for (i = 0; i < count; i++) 1123 for (i = 0; i < count; i++)
1010 { 1124 {
1011 data[i].address = 1125 data[i].address =
1012 (char **) Dynarr_atp (pdump_root_struct_ptrs, i)->ptraddress; 1126 (Rawbyte **) Dynarr_atp (pdump_root_block_ptrs, i)->ptraddress;
1013 data[i].value = 1127 data[i].value =
1014 (char *) pdump_get_entry (* data[i].address)->save_offset; 1128 (Rawbyte *) pdump_get_block (* data[i].address)->save_offset;
1015 } 1129 }
1016 PDUMP_ALIGN_OUTPUT (pdump_static_pointer); 1130 PDUMP_ALIGN_OUTPUT (pdump_static_pointer);
1017 retry_fwrite (data, sizeof (pdump_static_pointer), count, pdump_out); 1131 retry_fwrite (data, sizeof (pdump_static_pointer), count, pdump_out);
1018 } 1132 }
1019 1133
1134 /* Dump out the root blocks, part of stage 3 (the "WRITE" stage) of
1135 dumping. For each block we dump a structure containing info about the
1136 block (its location, size and description) and then the block itself,
1137 with its pointers replaced with offsets into the dump data. */
1138
1020 static void 1139 static void
1021 pdump_dump_root_blocks (void) 1140 pdump_dump_root_blocks (void)
1022 { 1141 {
1023 int i; 1142 int i;
1024 for (i = 0; i < Dynarr_length (pdump_root_blocks); i++) 1143 for (i = 0; i < Dynarr_length (pdump_root_blocks); i++)
1025 { 1144 {
1026 pdump_root_block *info = Dynarr_atp (pdump_root_blocks, i); 1145 pdump_root_block info = Dynarr_at (pdump_root_blocks, i);
1027 PDUMP_WRITE_ALIGNED (pdump_root_block, *info); 1146 PDUMP_WRITE_ALIGNED (pdump_root_block, info);
1028 retry_fwrite (info->varaddress, info->size, 1, pdump_out); 1147
1148 if (info.desc)
1149 {
1150 /* Copy to temporary buffer */
1151 memcpy (pdump_buf, info.blockaddr, info.size);
1152
1153 /* Store new offsets into all pointers in block */
1154 pdump_store_new_pointer_offsets (1, pdump_buf, info.blockaddr,
1155 info.desc, info.size);
1156 }
1157 retry_fwrite (info.desc ? pdump_buf : info.blockaddr,
1158 info.size, 1, pdump_out);
1029 } 1159 }
1030 } 1160 }
1031 1161
1032 static void 1162 static void
1033 pdump_dump_rtables (void) 1163 pdump_dump_rtables (void)
1034 { 1164 {
1035 int i; 1165 int i;
1036 pdump_entry_list_elt *elt; 1166 pdump_block_list_elt *elt;
1037 pdump_reloc_table rt; 1167 pdump_reloc_table rt;
1038 1168
1039 for (i=0; i<lrecord_type_count; i++) 1169 for (i=0; i<lrecord_type_count; i++)
1040 { 1170 {
1041 elt = pdump_object_table[i].first; 1171 elt = pdump_object_table[i].first;
1044 rt.desc = lrecord_implementations_table[i]->description; 1174 rt.desc = lrecord_implementations_table[i]->description;
1045 rt.count = pdump_object_table[i].count; 1175 rt.count = pdump_object_table[i].count;
1046 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt); 1176 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
1047 while (elt) 1177 while (elt)
1048 { 1178 {
1049 EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset; 1179 EMACS_INT rdata = pdump_get_block (elt->obj)->save_offset;
1050 PDUMP_WRITE_ALIGNED (EMACS_INT, rdata); 1180 PDUMP_WRITE_ALIGNED (EMACS_INT, rdata);
1051 elt = elt->next; 1181 elt = elt->next;
1052 } 1182 }
1053 } 1183 }
1054 1184
1055 rt.desc = 0; 1185 rt.desc = 0;
1056 rt.count = 0; 1186 rt.count = 0;
1057 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt); 1187 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
1058 1188
1059 for (i=0; i<pdump_struct_table.count; i++) 1189 for (i=0; i<pdump_desc_table.count; i++)
1060 { 1190 {
1061 elt = pdump_struct_table.list[i].list.first; 1191 elt = pdump_desc_table.list[i].list.first;
1062 rt.desc = pdump_struct_table.list[i].desc; 1192 rt.desc = pdump_desc_table.list[i].desc;
1063 rt.count = pdump_struct_table.list[i].list.count; 1193 rt.count = pdump_desc_table.list[i].list.count;
1064 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt); 1194 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
1065 while (elt) 1195 while (elt)
1066 { 1196 {
1067 EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset; 1197 EMACS_INT rdata = pdump_get_block (elt->obj)->save_offset;
1068 int j; 1198 int j;
1069 for (j=0; j<elt->count; j++) 1199 for (j=0; j<elt->count; j++)
1070 { 1200 {
1071 PDUMP_WRITE_ALIGNED (EMACS_INT, rdata); 1201 PDUMP_WRITE_ALIGNED (EMACS_INT, rdata);
1072 rdata += elt->size; 1202 rdata += elt->size;
1095 obj.address = Dynarr_at (pdump_root_lisp_objects, i); 1225 obj.address = Dynarr_at (pdump_root_lisp_objects, i);
1096 obj.value = * obj.address; 1226 obj.value = * obj.address;
1097 1227
1098 if (POINTER_TYPE_P (XTYPE (obj.value))) 1228 if (POINTER_TYPE_P (XTYPE (obj.value)))
1099 obj.value = 1229 obj.value =
1100 wrap_pointer_1 ((void *) pdump_get_entry (XRECORD_LHEADER 1230 wrap_pointer_1 ((void *) pdump_get_block (XRECORD_LHEADER
1101 (obj.value))->save_offset); 1231 (obj.value))->save_offset);
1102 1232
1103 PDUMP_WRITE (pdump_static_Lisp_Object, obj); 1233 PDUMP_WRITE (pdump_static_Lisp_Object, obj);
1104 } 1234 }
1105 1235
1106 for (i=0; i<Dynarr_length (pdump_weak_object_chains); i++) 1236 for (i = 0; i < Dynarr_length (pdump_weak_object_chains); i++)
1107 { 1237 {
1108 pdump_entry_list_elt *elt; 1238 pdump_block_list_elt *elt;
1109 pdump_static_Lisp_Object obj; 1239 pdump_static_Lisp_Object obj;
1110 1240
1111 obj.address = Dynarr_at (pdump_weak_object_chains, i); 1241 obj.address = Dynarr_at (pdump_weak_object_chains, i);
1112 obj.value = * obj.address; 1242 obj.value = * obj.address;
1113 1243
1114 for (;;) 1244 for (;;)
1115 { 1245 {
1116 const struct memory_description *desc; 1246 const struct memory_description *desc;
1117 int pos; 1247 int pos;
1118 elt = pdump_get_entry (XRECORD_LHEADER (obj.value)); 1248 elt = pdump_get_block (XRECORD_LHEADER (obj.value));
1119 if (elt) 1249 if (elt)
1120 break; 1250 break;
1121 desc = XRECORD_LHEADER_IMPLEMENTATION (obj.value)->description; 1251 desc = XRECORD_LHEADER_IMPLEMENTATION (obj.value)->description;
1122 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++) 1252 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
1123 assert (desc[pos].type != XD_END); 1253 assert (desc[pos].type != XD_END);
1124 1254
1125 /* #### Figure out how to handle indirect offsets here. */ 1255 /* #### Figure out how to handle indirect offsets here. */
1126 assert (!XD_IS_INDIRECT (desc[pos].offset)); 1256 assert (!XD_IS_INDIRECT (desc[pos].offset));
1127 obj.value = 1257 obj.value =
1128 * (Lisp_Object *) (desc[pos].offset + 1258 * (Lisp_Object *) (desc[pos].offset +
1129 (char *) (XRECORD_LHEADER (obj.value))); 1259 (Rawbyte *) (XRECORD_LHEADER (obj.value)));
1130 } 1260 }
1131 obj.value = wrap_pointer_1 ((void *) elt->save_offset); 1261 obj.value = wrap_pointer_1 ((void *) elt->save_offset);
1132 1262
1133 PDUMP_WRITE (pdump_static_Lisp_Object, obj); 1263 PDUMP_WRITE (pdump_static_Lisp_Object, obj);
1134 } 1264 }
1135 } 1265 }
1266
1267
1268 /*########################################################################
1269 # Pdump #
1270 ########################################################################
1271
1272 [ben]
1273
1274 DISCUSSION OF DUMPING:
1275
1276 The idea of dumping is to record the state of XEmacs in a file, so that
1277 it can be reloaded later. This avoids having to reload all of the basic
1278 Lisp code each time XEmacs is run, which is a rather time-consuming
1279 process. (Less so on new machines, but still noticeable. As an example
1280 of a program with similar issues but which does not have a dumping
1281 process and as a result has a slow startup time, consider Adobe Photoshop
1282 5.0 or Adobe Photoshop Elements 2.0.)
1283
1284 We don't actually record ALL the state of XEmacs (some of it, for example,
1285 is dependent on the run-time environment and needs to be initialized
1286 whenever XEmacs is run), but whatever state we don't record needs to be
1287 reinitialized every time XEmacs is run.
1288
1289 The old way of dumping was to make a new executable file with the data
1290 segment expanded to contain the heap and written out from memory. This
1291 is what the unex* files do. Unfortunately this process is extremely
1292 system-specific and breaks easily with OS changes.
1293
1294 Another simple, more portable trick, the "static heap" method, involves
1295 replacing the allocator with our own allocator which allocates all space
1296 out of a very large array declared in our data segment until we run out,
1297 then uses the underlying malloc() to start allocating on the heap. If we
1298 ensure that the large array is big enough to hold all data allocated
1299 during the dump stage, then all of the data we need to save is in the
1300 data segment, and it's easy to calculate the location and size of the
1301 data segment we want to save (we don't want to record and reinitialize
1302 the data segment of library functions) by using appropriately declared
1303 variables in the first and last file linked. This method is known as the
1304 "static heap" method, and is used by the non-pdump version of the dumper
1305 under Cygwin, and was also used under VMS and in Win-Emacs.
1306
1307 The "static heap" method works well in practice. Nonetheless, a more
1308 complex method of dumping was written by Olivier Galibert, which requires
1309 that structural descriptions of all data allocated in the heap be provided
1310 and the roots of all pointers into the heap be noted through function calls
1311 to the pdump API. This way, all the heap data can be traversed and written
1312 out to a file, and then reloaded at run-time and the pointers relocated to
1313 point at the new location of the loaded data. This is the "pdump" method
1314 used in this file.
1315
1316 There are two potential advantages of "pdump" over the "static heap":
1317
1318 (1) It doesn't require any tricks to calculate the beginning and end of
1319 the data segment, or even that the XEmacs section of the data segment
1320 be contiguous. (It's not clear whether this is an issue in practice.)
1321 (2) Potentially, it could handle an OS that does not always load the
1322 static data segment at a predictable location. The "static heap"
1323 method by its nature needs the data segment to stay in the same place
1324 from invocation to invocation, since it simply dumps out memory and
1325 reloads it, without any pointer relocation. I say "potentially"
1326 because as it is currently written pdump does assume that the data
1327 segment is never relocated. However, changing pdump to remove this
1328 assumption is probably not difficult, as all the mechanism to handle
1329 pointer relocation is already present.
1330
1331
1332 DISCUSSION OF PDUMP WORKINGS:
1333
1334 See man/internals/internals.texi for more information.
1335
1336 NOTE that we have two kinds of memory to handle: memory on the heap
1337 (i.e. allocated through malloc()) or the like, and static memory in the
1338 data segment of the program, i.e. stuff declared as global or static.
1339 All heap memory needs to be written out to the dump file and reproduced
1340 (i.e. reloaded and any necessary relocations performed). Data-segment
1341 memory that is not statically initialized (i.e. through declarations in
1342 the C code) needs either to be written out and reloaded, or
1343 reinitialized. In addition, any pointers in data-segment memory to heap
1344 memory must be written out, reloaded and relocated.
1345
1346 NOTE that we currently don't handle relocation of pointers into data-
1347 segment memory. (See overview discussion above.) These are treated in
1348 the descriptions as opaque data not needing relocation. If this becomes a
1349 problem, it can be fixed through new kinds of types in
1350 enum memory_description_type.
1351
1352 Three basic steps to dumping out:
1353
1354 (1) "REGISTER":
1355 Starting with all sources of relocatable memory (currently this means
1356 all data-segment pointers to heap memory -- see above about pointers
1357 to data-segment memory), recursively traverse the tree of pointers
1358 and "register" (make a note of) every memory block seen.
1359
1360 (2) "LAYOUT":
1361 Go through all of the registered blocks and compute the location of
1362 each one in the dump data (i.e. the "offset" that will be added to
1363 the address corresponding to start of the loaded-in data to get the
1364 new pointer referring to this block). The blocks will be laid out
1365 sequentially according to the order we traverse them. Also note the
1366 maximum-sized block for use in step 3.
1367
1368 (3) "WRITE":
1369 After writing some header stuff, go through all of the registered
1370 blocks and write out each one to the dump file. Note that we are
1371 simply writing out the blocks sequentially as we see them, and our
1372 traversal path is identical to that in step 2, so blocks will end up
1373 at the locations computed for them. In order to write out a block,
1374 first copy it to a temporary location (hence the maximum-block-size
1375 computation in the previous step), then for each relocatable pointer
1376 in the block, write in its place the offset to the heap block in the
1377 dump data. When the dump data is loaded, the address of the
1378 beginning of the dump data will be added to the offset in each
1379 pointer, and thence become accurate.
1380
1381 --ben
1382 */
1136 1383
1137 void 1384 void
1138 pdump (void) 1385 pdump (void)
1139 { 1386 {
1140 int i; 1387 int i;
1142 int none; 1389 int none;
1143 pdump_header header; 1390 pdump_header header;
1144 1391
1145 in_pdump = 1; 1392 in_pdump = 1;
1146 1393
1147 pdump_object_table = xnew_array (pdump_entry_list, lrecord_type_count); 1394 pdump_object_table = xnew_array (pdump_block_list, lrecord_type_count);
1148 pdump_alert_undump_object = xnew_array (int, lrecord_type_count); 1395 pdump_alert_undump_object = xnew_array (int, lrecord_type_count);
1149 1396
1150 assert (ALIGNOF (max_align_t) <= pdump_align_table[0]); 1397 assert (ALIGNOF (max_align_t) <= pdump_align_table[0]);
1151 1398
1152 for (i = 0; i < countof (pdump_align_table); i++) 1399 for (i = 0; i < countof (pdump_align_table); i++)
1170 #else /* not USE_KKCC */ 1417 #else /* not USE_KKCC */
1171 dump_add_opaque (&lrecord_markers, 1418 dump_add_opaque (&lrecord_markers,
1172 lrecord_type_count * sizeof (lrecord_markers[0])); 1419 lrecord_type_count * sizeof (lrecord_markers[0]));
1173 #endif /* not USE_KKCC */ 1420 #endif /* not USE_KKCC */
1174 1421
1175 pdump_hash = xnew_array_and_zero (pdump_entry_list_elt *, PDUMP_HASHSIZE); 1422 pdump_hash = xnew_array_and_zero (pdump_block_list_elt *, PDUMP_HASHSIZE);
1176 1423
1177 for (i=0; i<lrecord_type_count; i++) 1424 for (i = 0; i<lrecord_type_count; i++)
1178 { 1425 {
1179 pdump_object_table[i].first = 0; 1426 pdump_object_table[i].first = 0;
1180 pdump_object_table[i].align = ALIGNOF (max_align_t); 1427 pdump_object_table[i].align = ALIGNOF (max_align_t);
1181 pdump_object_table[i].count = 0; 1428 pdump_object_table[i].count = 0;
1182 pdump_alert_undump_object[i] = 0; 1429 pdump_alert_undump_object[i] = 0;
1183 } 1430 }
1184 pdump_struct_table.count = 0; 1431 pdump_desc_table.count = 0;
1185 pdump_struct_table.size = -1; 1432 pdump_desc_table.size = -1;
1186 1433
1187 pdump_opaque_data_list.first = 0; 1434 pdump_opaque_data_list.first = 0;
1188 pdump_opaque_data_list.align = ALIGNOF (max_align_t); 1435 pdump_opaque_data_list.align = ALIGNOF (max_align_t);
1189 pdump_opaque_data_list.count = 0; 1436 pdump_opaque_data_list.count = 0;
1190 pdump_depth = 0; 1437 pdump_depth = 0;
1191 1438
1439 /* (I) The "register" stage: Note all heap memory blocks to be relocated
1440 */
1441
1442 /* Try various roots of accessibility: */
1443
1444 /* (1) Lisp objects, both those declared using DEFVAR_LISP*() and those
1445 staticpro()d. */
1192 for (i = 0; i < Dynarr_length (pdump_root_lisp_objects); i++) 1446 for (i = 0; i < Dynarr_length (pdump_root_lisp_objects); i++)
1193 pdump_register_object (* Dynarr_at (pdump_root_lisp_objects, i)); 1447 pdump_register_object (* Dynarr_at (pdump_root_lisp_objects, i));
1194 1448
1195 none = 1; 1449 none = 1;
1196 for (i=0; i<lrecord_type_count; i++) 1450 for (i = 0; i < lrecord_type_count; i++)
1197 if (pdump_alert_undump_object[i]) 1451 if (pdump_alert_undump_object[i])
1198 { 1452 {
1199 if (none) 1453 if (none)
1200 printf ("Undumpable types list :\n"); 1454 stderr_out ("Undumpable types list :\n");
1201 none = 0; 1455 none = 0;
1202 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, 1456 stderr_out (" - %s (%d)\n", lrecord_implementations_table[i]->name,
1203 pdump_alert_undump_object[i]); 1457 pdump_alert_undump_object[i]);
1204 } 1458 }
1205 if (!none) 1459 if (!none)
1206 { 1460 {
1207 in_pdump = 0; 1461 in_pdump = 0;
1208 return; 1462 return;
1209 } 1463 }
1210 1464
1211 for (i=0; i<Dynarr_length (pdump_root_struct_ptrs); i++) 1465 /* (2) Register out the data-segment pointer variables to heap blocks */
1212 { 1466 for (i = 0; i < Dynarr_length (pdump_root_block_ptrs); i++)
1213 pdump_root_struct_ptr info = Dynarr_at (pdump_root_struct_ptrs, i); 1467 {
1214 pdump_register_struct (*(info.ptraddress), info.desc, 1); 1468 pdump_root_block_ptr info = Dynarr_at (pdump_root_block_ptrs, i);
1215 } 1469 pdump_register_block (*(info.ptraddress), info.desc->size,
1216 1470 info.desc->description, 1);
1471 }
1472
1473 /* (3) Register out the data-segment blocks, maybe with pointers to heap
1474 blocks */
1475 for (i = 0; i < Dynarr_length (pdump_root_blocks); i++)
1476 {
1477 pdump_root_block *info = Dynarr_atp (pdump_root_blocks, i);
1478 if (info->desc)
1479 {
1480 /* Size may have been given as 0 meaning "compute later".
1481 Compute now and update. If no DESC, size must always be
1482 correct as there is no other way of computing it. */
1483 info->size = lispdesc_block_size_1 (info->blockaddr, info->size,
1484 info->desc);
1485 pdump_register_block_contents (info->blockaddr, info->size,
1486 info->desc, 1);
1487 }
1488 }
1489
1490 /* (II) The "layout" stage: Compute the offsets and max-size */
1491
1492 /* (1) Determine header size */
1217 memcpy (header.signature, PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN); 1493 memcpy (header.signature, PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN);
1218 header.id = dump_id; 1494 header.id = dump_id;
1219 header.reloc_address = 0; 1495 header.reloc_address = 0;
1220 header.nb_root_struct_ptrs = Dynarr_length (pdump_root_struct_ptrs); 1496 header.nb_root_block_ptrs = Dynarr_length (pdump_root_block_ptrs);
1221 header.nb_root_blocks = Dynarr_length (pdump_root_blocks); 1497 header.nb_root_blocks = Dynarr_length (pdump_root_blocks);
1222 1498
1223 cur_offset = MAX_ALIGN_SIZE (sizeof (header)); 1499 cur_offset = MAX_ALIGN_SIZE (sizeof (header));
1224 max_size = 0; 1500 max_size = 0;
1225 1501
1502 /* (2) Traverse all heap blocks and compute their offsets; keep track
1503 of maximum block size seen */
1226 pdump_scan_by_alignment (pdump_allocate_offset); 1504 pdump_scan_by_alignment (pdump_allocate_offset);
1227 cur_offset = MAX_ALIGN_SIZE (cur_offset); 1505 cur_offset = MAX_ALIGN_SIZE (cur_offset);
1228 header.stab_offset = cur_offset; 1506 header.stab_offset = cur_offset;
1229 1507
1508 /* (3) Update maximum size based on root (data-segment) blocks */
1509 for (i = 0; i < Dynarr_length (pdump_root_blocks); i++)
1510 {
1511 pdump_root_block info = Dynarr_at (pdump_root_blocks, i);
1512
1513 /* If no DESC, no relocation needed and we copy directly instead of
1514 into a temp buffer. */
1515 if (info.desc)
1516 {
1517 if (info.size > max_size)
1518 max_size = info.size;
1519 }
1520 }
1521
1522 /* (III) The "write "stage: Dump out the data, storing the offsets in
1523 place of pointers whenever we write out memory blocks */
1524
1230 pdump_buf = xmalloc (max_size); 1525 pdump_buf = xmalloc (max_size);
1526 /* EMACS_PROGNAME is entirely ASCII so this should be Mule-safe */
1231 pdump_fd = open (EMACS_PROGNAME ".dmp", 1527 pdump_fd = open (EMACS_PROGNAME ".dmp",
1232 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666); 1528 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
1233 if (pdump_fd < 0) 1529 if (pdump_fd < 0)
1234 report_file_error ("Unable to open dump file", 1530 report_file_error ("Unable to open dump file",
1235 build_string (EMACS_PROGNAME ".dmp")); 1531 build_string (EMACS_PROGNAME ".dmp"));
1243 1539
1244 pdump_scan_by_alignment (pdump_dump_data); 1540 pdump_scan_by_alignment (pdump_dump_data);
1245 1541
1246 fseek (pdump_out, header.stab_offset, SEEK_SET); 1542 fseek (pdump_out, header.stab_offset, SEEK_SET);
1247 1543
1248 pdump_dump_root_struct_ptrs (); 1544 pdump_dump_root_block_ptrs ();
1249 pdump_dump_root_blocks (); 1545 pdump_dump_root_blocks ();
1250 pdump_dump_rtables (); 1546 pdump_dump_rtables ();
1251 pdump_dump_root_lisp_objects (); 1547 pdump_dump_root_lisp_objects ();
1252 1548
1253 retry_fclose (pdump_out); 1549 retry_fclose (pdump_out);
1264 } 1560 }
1265 1561
1266 static int 1562 static int
1267 pdump_load_check (void) 1563 pdump_load_check (void)
1268 { 1564 {
1269 return (!memcmp (((pdump_header *)pdump_start)->signature, 1565 return (!memcmp (((pdump_header *) pdump_start)->signature,
1270 PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN) 1566 PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN)
1271 && ((pdump_header *)pdump_start)->id == dump_id); 1567 && ((pdump_header *)pdump_start)->id == dump_id);
1272 } 1568 }
1273 1569
1274 /*----------------------------------------------------------------------*/ 1570 /*----------------------------------------------------------------------*/
1276 /*----------------------------------------------------------------------*/ 1572 /*----------------------------------------------------------------------*/
1277 static int 1573 static int
1278 pdump_load_finish (void) 1574 pdump_load_finish (void)
1279 { 1575 {
1280 int i; 1576 int i;
1281 char *p; 1577 Rawbyte *p;
1282 EMACS_INT delta; 1578 EMACS_INT delta;
1283 EMACS_INT count; 1579 EMACS_INT count;
1284 pdump_header *header = (pdump_header *) pdump_start; 1580 pdump_header *header = (pdump_header *) pdump_start;
1285 1581
1286 pdump_end = pdump_start + pdump_length; 1582 pdump_end = pdump_start + pdump_length;
1287 1583
1288 delta = ((EMACS_INT) pdump_start) - header->reloc_address; 1584 delta = ((EMACS_INT) pdump_start) - header->reloc_address;
1289 p = pdump_start + header->stab_offset; 1585 p = pdump_start + header->stab_offset;
1290 1586
1291 /* Put back the pdump_root_struct_ptrs */ 1587 /* Put back the pdump_root_block_ptrs */
1292 p = (char *) ALIGN_PTR (p, pdump_static_pointer); 1588 p = (Rawbyte *) ALIGN_PTR (p, pdump_static_pointer);
1293 for (i = 0; i < header->nb_root_struct_ptrs; i++) 1589 for (i = 0; i < header->nb_root_block_ptrs; i++)
1294 { 1590 {
1295 pdump_static_pointer ptr = PDUMP_READ (p, pdump_static_pointer); 1591 pdump_static_pointer ptr = PDUMP_READ (p, pdump_static_pointer);
1296 (* ptr.address) = ptr.value + delta; 1592 (* ptr.address) = ptr.value + delta;
1297 } 1593 }
1298 1594
1299 /* Put back the pdump_root_blocks and relocate */ 1595 /* Put back the pdump_root_blocks and relocate */
1300 for (i = 0; i < header->nb_root_blocks; i++) 1596 for (i = 0; i < header->nb_root_blocks; i++)
1301 { 1597 {
1302 pdump_root_block info = PDUMP_READ_ALIGNED (p, pdump_root_block); 1598 pdump_root_block info = PDUMP_READ_ALIGNED (p, pdump_root_block);
1303 memcpy ((void *) info.varaddress, p, info.size); 1599 memcpy ((void *) info.blockaddr, p, info.size);
1304 if (info.desc) 1600 if (info.desc)
1305 pdump_reloc_one ((void *) info.varaddress, delta, info.desc); 1601 pdump_reloc_one ((void *) info.blockaddr, delta, info.desc);
1306 p += info.size; 1602 p += info.size;
1307 } 1603 }
1308 1604
1309 /* Relocate the heap objects */ 1605 /* Relocate the heap objects */
1310 pdump_rt_list = p; 1606 pdump_rt_list = p;
1311 count = 2; 1607 count = 2;
1312 for (;;) 1608 for (;;)
1313 { 1609 {
1314 pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table); 1610 pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table);
1315 p = (char *) ALIGN_PTR (p, char *); 1611 p = (Rawbyte *) ALIGN_PTR (p, Rawbyte *);
1316 if (rt.desc) 1612 if (rt.desc)
1317 { 1613 {
1318 char **reloc = (char **) p; 1614 Rawbyte **reloc = (Rawbyte **) p;
1319 for (i = 0; i < rt.count; i++) 1615 for (i = 0; i < rt.count; i++)
1320 { 1616 {
1321 reloc[i] += delta; 1617 reloc[i] += delta;
1322 pdump_reloc_one (reloc[i], delta, rt.desc); 1618 pdump_reloc_one (reloc[i], delta, rt.desc);
1323 } 1619 }
1324 p += rt.count * sizeof (char *); 1620 p += rt.count * sizeof (Rawbyte *);
1325 } 1621 }
1326 else if (!(--count)) 1622 else if (!(--count))
1327 break; 1623 break;
1328 } 1624 }
1329 1625
1330 /* Put the pdump_root_lisp_objects variables in place */ 1626 /* Put the pdump_root_lisp_objects variables in place */
1331 i = PDUMP_READ_ALIGNED (p, Elemcount); 1627 i = PDUMP_READ_ALIGNED (p, Elemcount);
1332 p = (char *) ALIGN_PTR (p, pdump_static_Lisp_Object); 1628 p = (Rawbyte *) ALIGN_PTR (p, pdump_static_Lisp_Object);
1333 while (i--) 1629 while (i--)
1334 { 1630 {
1335 pdump_static_Lisp_Object obj = PDUMP_READ (p, pdump_static_Lisp_Object); 1631 pdump_static_Lisp_Object obj = PDUMP_READ (p, pdump_static_Lisp_Object);
1336 1632
1337 if (POINTER_TYPE_P (XTYPE (obj.value))) 1633 if (POINTER_TYPE_P (XTYPE (obj.value)))
1338 obj.value = wrap_pointer_1 ((char *) XPNTR (obj.value) + delta); 1634 obj.value = wrap_pointer_1 ((Rawbyte *) XPNTR (obj.value) + delta);
1339 1635
1340 (* obj.address) = obj.value; 1636 (* obj.address) = obj.value;
1341 } 1637 }
1342 1638
1343 /* Final cleanups */ 1639 /* Final cleanups */
1344 /* reorganize hash tables */ 1640 /* reorganize hash tables */
1345 p = pdump_rt_list; 1641 p = pdump_rt_list;
1346 for (;;) 1642 for (;;)
1347 { 1643 {
1348 pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table); 1644 pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table);
1349 p = (char *) ALIGN_PTR (p, Lisp_Object); 1645 p = (Rawbyte *) ALIGN_PTR (p, Lisp_Object);
1350 if (!rt.desc) 1646 if (!rt.desc)
1351 break; 1647 break;
1352 if (rt.desc == hash_table_description) 1648 if (rt.desc == hash_table_description)
1353 { 1649 {
1354 for (i = 0; i < rt.count; i++) 1650 for (i = 0; i < rt.count; i++)
1371 CloseHandle (pdump_hFile); 1667 CloseHandle (pdump_hFile);
1372 CloseHandle (pdump_hMap); 1668 CloseHandle (pdump_hMap);
1373 } 1669 }
1374 1670
1375 static int 1671 static int
1376 pdump_file_get (const char *path) 1672 pdump_file_get (const Wexttext *wpath)
1377 { 1673 {
1378 1674 Extbyte *path;
1379 pdump_hFile = CreateFileA (path, 1675 if (XEUNICODE_P)
1380 GENERIC_READ + GENERIC_WRITE, /* Required for copy on write */ 1676 path = (Extbyte *) wpath;
1381 0, /* Not shared */ 1677 else
1382 NULL, /* Not inheritable */ 1678 path = WEXTTEXT_TO_MULTIBYTE (wpath);
1383 OPEN_EXISTING, 1679
1384 FILE_ATTRIBUTE_NORMAL, 1680 pdump_hFile =
1385 NULL); /* No template file */ 1681 qxeCreateFile (path,
1682 GENERIC_READ + GENERIC_WRITE, /* Required for copy on
1683 write */
1684 0, /* Not shared */
1685 NULL, /* Not inheritable */
1686 OPEN_EXISTING,
1687 FILE_ATTRIBUTE_NORMAL,
1688 NULL); /* No template file */
1386 if (pdump_hFile == INVALID_HANDLE_VALUE) 1689 if (pdump_hFile == INVALID_HANDLE_VALUE)
1387 return 0; 1690 return 0;
1388 1691
1389 pdump_length = GetFileSize (pdump_hFile, NULL); 1692 pdump_length = GetFileSize (pdump_hFile, NULL);
1390 pdump_hMap = CreateFileMappingA (pdump_hFile, 1693 pdump_hMap =
1391 NULL, /* No security attributes */ 1694 qxeCreateFileMapping (pdump_hFile,
1392 PAGE_WRITECOPY, /* Copy on write */ 1695 NULL, /* No security attributes */
1393 0, /* Max size, high half */ 1696 PAGE_WRITECOPY, /* Copy on write */
1394 0, /* Max size, low half */ 1697 0, /* Max size, high half */
1395 NULL); /* Unnamed */ 1698 0, /* Max size, low half */
1699 NULL); /* Unnamed */
1396 if (pdump_hMap == INVALID_HANDLE_VALUE) 1700 if (pdump_hMap == INVALID_HANDLE_VALUE)
1397 return 0; 1701 return 0;
1398 1702
1399 pdump_start = (char *) MapViewOfFile (pdump_hMap, 1703 pdump_start =
1400 FILE_MAP_COPY, /* Copy on write */ 1704 (Rawbyte *) MapViewOfFile (pdump_hMap,
1401 0, /* Start at zero */ 1705 FILE_MAP_COPY, /* Copy on write */
1402 0, 1706 0, /* Start at zero */
1403 0); /* Map all of it */ 1707 0,
1708 0); /* Map all of it */
1404 pdump_free = pdump_file_unmap; 1709 pdump_free = pdump_file_unmap;
1405 return 1; 1710 return 1;
1406 } 1711 }
1407 1712
1408 /* pdump_resource_free is called (via the pdump_free pointer) to release 1713 /* pdump_resource_free is called (via the pdump_free pointer) to release
1437 /* Found it, use the data in the resource */ 1742 /* Found it, use the data in the resource */
1438 hResLoad = (HRSRC) LoadResource (NULL, hRes); 1743 hResLoad = (HRSRC) LoadResource (NULL, hRes);
1439 if (hResLoad == NULL) 1744 if (hResLoad == NULL)
1440 return 0; 1745 return 0;
1441 1746
1442 pdump_start = (char *) LockResource (hResLoad); 1747 pdump_start = (Rawbyte *) LockResource (hResLoad);
1443 if (pdump_start == NULL) 1748 if (pdump_start == NULL)
1444 return 0; 1749 return 0;
1445 1750
1446 pdump_free = pdump_resource_free; 1751 pdump_free = pdump_resource_free;
1447 pdump_length = SizeofResource (NULL, hRes); 1752 pdump_length = SizeofResource (NULL, hRes);
1457 #else /* !WIN32_NATIVE */ 1762 #else /* !WIN32_NATIVE */
1458 1763
1459 static void 1764 static void
1460 pdump_file_free (void) 1765 pdump_file_free (void)
1461 { 1766 {
1462 xfree (pdump_start, char *); 1767 xfree (pdump_start, Rawbyte *);
1463 } 1768 }
1464 1769
1465 #ifdef HAVE_MMAP 1770 #ifdef HAVE_MMAP
1466 static void 1771 static void
1467 pdump_file_unmap (void) 1772 pdump_file_unmap (void)
1469 munmap (pdump_start, pdump_length); 1774 munmap (pdump_start, pdump_length);
1470 } 1775 }
1471 #endif 1776 #endif
1472 1777
1473 static int 1778 static int
1474 pdump_file_get (const char *path) 1779 pdump_file_get (const Wexttext *path)
1475 { 1780 {
1476 int fd = open (path, O_RDONLY | OPEN_BINARY); 1781 int fd = wext_retry_open (path, O_RDONLY | OPEN_BINARY);
1477 if (fd<0) 1782 if (fd < 0)
1478 return 0; 1783 return 0;
1479 1784
1480 pdump_length = lseek (fd, 0, SEEK_END); 1785 pdump_length = lseek (fd, 0, SEEK_END);
1481 if (pdump_length < (Bytecount) sizeof (pdump_header)) 1786 if (pdump_length < (Bytecount) sizeof (pdump_header))
1482 { 1787 {
1490 /* Unix 98 requires that sys/mman.h define MAP_FAILED, 1795 /* Unix 98 requires that sys/mman.h define MAP_FAILED,
1491 but many earlier implementations don't. */ 1796 but many earlier implementations don't. */
1492 # ifndef MAP_FAILED 1797 # ifndef MAP_FAILED
1493 # define MAP_FAILED ((void *) -1L) 1798 # define MAP_FAILED ((void *) -1L)
1494 # endif 1799 # endif
1495 pdump_start = (char *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 1800 pdump_start =
1496 if (pdump_start != (char *) MAP_FAILED) 1801 (Rawbyte *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE,
1802 fd, 0);
1803 if (pdump_start != (Rawbyte *) MAP_FAILED)
1497 { 1804 {
1498 pdump_free = pdump_file_unmap; 1805 pdump_free = pdump_file_unmap;
1499 retry_close (fd); 1806 retry_close (fd);
1500 return 1; 1807 return 1;
1501 } 1808 }
1502 #endif /* HAVE_MMAP */ 1809 #endif /* HAVE_MMAP */
1503 1810
1504 pdump_start = xnew_array (char, pdump_length); 1811 pdump_start = xnew_array (Rawbyte, pdump_length);
1505 pdump_free = pdump_file_free; 1812 pdump_free = pdump_file_free;
1506 retry_read (fd, pdump_start, pdump_length); 1813 retry_read (fd, pdump_start, pdump_length);
1507 1814
1508 retry_close (fd); 1815 retry_close (fd);
1509 return 1; 1816 return 1;
1510 } 1817 }
1511 1818
1512 static int 1819 static int
1513 pdump_ram_try (void) 1820 pdump_ram_try (void)
1514 { 1821 {
1515 pdump_start = dumped_data_get(); 1822 pdump_start = dumped_data_get ();
1516 pdump_length = dumped_data_size(); 1823 pdump_length = dumped_data_size ();
1517 1824
1518 return pdump_load_check(); 1825 return pdump_load_check ();
1519 } 1826 }
1520 1827
1521 #endif /* !WIN32_NATIVE */ 1828 #endif /* !WIN32_NATIVE */
1522 1829
1523 1830
1524 static int 1831 static int
1525 pdump_file_try (char *exe_path) 1832 pdump_file_try (Wexttext *exe_path)
1526 { 1833 {
1527 char *w = exe_path + strlen (exe_path); 1834 Wexttext *w = exe_path + wext_strlen (exe_path);
1528 1835
1529 do 1836 do
1530 { 1837 {
1531 sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id); 1838 wext_sprintf (w, WEXTSTRING ("-%s-%08x.dmp"), WEXTSTRING (EMACS_VERSION),
1839 dump_id);
1532 if (pdump_file_get (exe_path)) 1840 if (pdump_file_get (exe_path))
1533 { 1841 {
1534 if (pdump_load_check ()) 1842 if (pdump_load_check ())
1535 return 1; 1843 return 1;
1536 pdump_free (); 1844 pdump_free ();
1537 } 1845 }
1538 1846
1539 sprintf (w, "-%08x.dmp", dump_id); 1847 wext_sprintf (w, WEXTSTRING ("-%08x.dmp"), dump_id);
1540 if (pdump_file_get (exe_path)) 1848 if (pdump_file_get (exe_path))
1541 { 1849 {
1542 if (pdump_load_check ()) 1850 if (pdump_load_check ())
1543 return 1; 1851 return 1;
1544 pdump_free (); 1852 pdump_free ();
1545 } 1853 }
1546 1854
1547 sprintf (w, ".dmp"); 1855 wext_sprintf (w, WEXTSTRING (".dmp"));
1548 if (pdump_file_get (exe_path)) 1856 if (pdump_file_get (exe_path))
1549 { 1857 {
1550 if (pdump_load_check ()) 1858 if (pdump_load_check ())
1551 return 1; 1859 return 1;
1552 pdump_free (); 1860 pdump_free ();
1553 } 1861 }
1554 1862
1555 do 1863 do
1556 w--; 1864 w--;
1557 while (w>exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && (*w != '.')); 1865 /* !!#### See comment below about how this is unsafe. */
1558 } 1866 while (w > exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') &&
1559 while (w>exe_path && !IS_DIRECTORY_SEP (*w)); 1867 (*w != '.'));
1868 }
1869 while (w > exe_path && !IS_DIRECTORY_SEP (*w));
1560 return 0; 1870 return 0;
1561 } 1871 }
1562 1872
1563 int 1873 int
1564 pdump_load (const Extbyte *argv0) 1874 pdump_load (const Wexttext *argv0)
1565 { 1875 {
1566 Extbyte exe_path[PATH_MAX]; 1876 Wexttext exe_path[PATH_MAX];
1567
1568 #ifdef WIN32_NATIVE 1877 #ifdef WIN32_NATIVE
1569 GetModuleFileNameA (NULL, exe_path, PATH_MAX); 1878 qxeGetModuleFileName (NULL, (Extbyte *) exe_path, PATH_MAX);
1879 if (!XEUNICODE_P)
1880 {
1881 Wexttext *wexe = MULTIBYTE_TO_WEXTTEXT ((Extbyte *) exe_path);
1882 wext_strcpy (exe_path, wexe);
1883 }
1570 #else /* !WIN32_NATIVE */ 1884 #else /* !WIN32_NATIVE */
1571 Extbyte *w; 1885 Wexttext *w;
1572 const Extbyte *dir, *p; 1886 const Wexttext *dir, *p;
1573 1887
1574 if(pdump_ram_try()) { 1888 if (pdump_ram_try ())
1575 pdump_load_finish(); 1889 {
1576 in_pdump = 0; 1890 pdump_load_finish ();
1577 return 1; 1891 in_pdump = 0;
1578 } 1892 return 1;
1893 }
1579 1894
1580 in_pdump = 1; 1895 in_pdump = 1;
1581 dir = argv0; 1896 dir = argv0;
1582 if (dir[0] == '-') 1897 if (dir[0] == '-')
1583 { 1898 {
1584 /* XEmacs as a login shell, oh goody! */ 1899 /* XEmacs as a login shell, oh goody! */
1585 dir = getenv ("SHELL"); /* not egetenv -- not yet initialized */ 1900 dir = wext_getenv ("SHELL"); /* not egetenv -- not yet initialized and we
1586 } 1901 want external-format data */
1587 1902 }
1588 p = dir + strlen (dir); 1903
1589 while (p != dir && !IS_ANY_SEP (p[-1])) p--; 1904 p = dir + wext_strlen (dir);
1905 /* !!#### This is bad as it may fail with certain non-ASCII-compatible
1906 external formats such as JIS. Maybe we should be using the mb*()
1907 routines in libc? But can we reliably trust them on all Unix
1908 platforms? (We can't convert to internal since those conversion
1909 routines aren't yet initialized) */
1910 while (p != dir && !IS_ANY_SEP (p[-1]))
1911 p--;
1590 1912
1591 if (p != dir) 1913 if (p != dir)
1592 { 1914 {
1593 /* invocation-name includes a directory component -- presumably it 1915 /* invocation-name includes a directory component -- presumably it
1594 is relative to cwd, not $PATH */ 1916 is relative to cwd, not $PATH */
1595 strcpy (exe_path, dir); 1917 wext_strcpy (exe_path, dir);
1596 } 1918 }
1597 else 1919 else
1598 { 1920 {
1599 const Extbyte *path = getenv ("PATH"); /* not egetenv -- not yet init. */ 1921 const Wexttext *path = wext_getenv ("PATH"); /* not egetenv --
1600 const Extbyte *name = p; 1922 not yet init. */
1923 const Wexttext *name = p;
1601 for (;;) 1924 for (;;)
1602 { 1925 {
1603 p = path; 1926 p = path;
1604 while (*p && *p != SEPCHAR) 1927 while (*p && *p != SEPCHAR)
1605 p++; 1928 p++;
1608 exe_path[0] = '.'; 1931 exe_path[0] = '.';
1609 w = exe_path + 1; 1932 w = exe_path + 1;
1610 } 1933 }
1611 else 1934 else
1612 { 1935 {
1613 memcpy (exe_path, path, p - path); 1936 memcpy (exe_path, path, (p - path) * sizeof (Wexttext));
1614 w = exe_path + (p - path); 1937 w = exe_path + (p - path);
1615 } 1938 }
1616 if (!IS_DIRECTORY_SEP (w[-1])) 1939 if (!IS_DIRECTORY_SEP (w[-1]))
1617 { 1940 *w++ = '/';
1618 *w++ = '/'; 1941 wext_strcpy (w, name);
1619 }
1620 strcpy (w, name);
1621
1622 #undef access /* avoid !@#$%^& encapsulated access */
1623 #undef stat /* avoid !@#$%^& encapsulated stat */
1624 1942
1625 { 1943 {
1626 struct stat statbuf; 1944 struct stat statbuf;
1627 if (access (exe_path, X_OK) == 0 1945 if (wext_access (exe_path, X_OK) == 0
1628 && stat (exe_path, &statbuf) == 0 1946 && wext_stat (exe_path, &statbuf) == 0
1629 && ! S_ISDIR (statbuf.st_mode)) 1947 && ! S_ISDIR (statbuf.st_mode))
1630 break; 1948 break;
1631 } 1949 }
1632 1950
1633 if (!*p) 1951 if (!*p)
1634 { 1952 {
1635 /* Oh well, let's have some kind of default */ 1953 /* Oh well, let's have some kind of default */
1636 sprintf (exe_path, "./%s", name); 1954 wext_sprintf (exe_path, "./%s", name);
1637 break; 1955 break;
1638 } 1956 }
1639 path = p+1; 1957 path = p+1;
1640 } 1958 }
1641 } 1959 }