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