mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-07 16:10:46 -08:00
Add a new portable dumper as an alternative to unexec. Use it by default. * src/dmpstruct.awk: New file. * src/doc.c (get_doc_string): use will_dump_p(). * src/editfns.c (styled_format): silence compiler warning with UNINIT. * src/emacs-module.c (syms_of_module): staticpro ltv_mark. * src/emacs.c (gflags): new variable. (init_cmdargs): unwrap (string_starts_with_p, find_argument, dump_error_to_string) (load_pdump): new functions. (main): detect pdumper and --temacs invocation; actually load portable dump when detected; set gflags as appropriate; changes to init functions throughout to avoid passing explicit 'initialized' argument. * src/eval.c (inhibit_lisp_code): remove unused variable. (init_eval_once_for_pdumper): new function. (init_eval_once): call it. * src/filelock.c: CANNOT_DUMP -> will_dump_p() * src/fingerprint-dummy.c: new file * src/fingerprint.h: new file * src/fns.c: CANNOT_DUMP -> will_dump_p(), etc. (weak_hash_tables): remove (hashfn_equal, hashfn_eql): un-staticify (make_hash_table): set new 'next_weak' hash table field; drop global weak_hash_tables logic. (copy_hash_table): drop global weak_hash_tables logic. (hash_table_rehash): new function. (hash_lookup, hash_put, hash_remove_from_table, hash_clear): rehash if needed. (sweep_weak_table): un-staticify; explain logic; bool-ify. (sweep_weak_hash_tables): remove function. * src/font.c (syms_of_font): remember pdumper stuff. * src/fontset.c (syms_of_fontset): remember pdumper stuff. * src/frame.c (make_initial_frame): don't reset Vframe_list. (init_frame_once_for_pdumper, init_frame_once): new functions. (syms_of_frame): remove redundant staticpro. * src/fringe.c (init_fringe_once_for_pdumper): new functin. (init_fringe_once): call it. * src/ftcrfont.c (syms_of_ftcrfont_for_pdumper): new function. (syms_of_ftcrfont): call it. * src/ftfont.c (syms_of_ftfont_for_pdumper): new function. (syms_of_ftfont): call it. * src/ftxont.c (syms_of_ftxfont_for_pdumper): new function. (syms_of_ftxfont): call it. * src/gmalloc.c: adjust for pdumper througout (DUMPED): remove weird custom dumped indicator. * src/gnutls.c (syms_of_gnutls): pdumper note for gnutls_global_initialized. * src/image.c (syms_of_image): add pdumper comment, initializer note. * src/insdel.c (prepare_to_modify_buffer_1): account for buffer contents possibly being in dump image. * src/keyboard.c (syms_of_keyboard_for_pdumper): new function. (syms_of_keyboard): staticpro more; call pdumper syms function. * src/lisp.h: add comments throughout (gflags): declare. (will_dump_p, will_bootstrap_p, will_dump_with_pdumper_p) (dumped_with_pdumper_p, will_dump_with_unexec_p) (dumped_with_unexec_p, definitely_will_not_unexec_p): new functions. (POWER_OF_2, ROUNDUP): move macros. (PSEUDOVECTOR_TYPE, PSEUDOVECTOR_TYPEP): take vectorlike header pointer instead of vector; constify. (Lisp_Hash_Table): add comment about need to rehash on access; add comment for next_weak. (HASH_KEY, HASH_VALUE, HASH_HASH, HASH_TABLE_SIZE): const-ify. (hash_table_rehash): declare. (hash_rehash_needed_p, hash_rehash_if_needed): new functions. (finalizers, doomed_finalizers): declare extern. (SUBR_SECTION_ATTRIBUTE): new macro. (staticvec, staticidx): un-static-ify. (sweep_weak_hash_tables): remove declaration. (sweep_weak_table): declare. (hashfn_eql, hashfn_equal): declare. (number_finalizers_run): new variable. (Vdead): externify when ENABLE_CHECKING. (gc_root_type): new enumeration. (gc_root_visitor): new struct. (visit_static_gc_roots): declare. (vectorlike_nbytes): declare. (vector_nbytes): define as trivial inline function wrapper for vectorlike_nbytes. (init_obarray_once): change signature. (primary_thread): extern-ify. (init_buffer): change signature. (init_frame_once): declare. * src/lread.c (readevalloop): adjust for new dumped predicates. (init_obarray_once): new function. (ndefsubr): new variable. (defsubr): increment it. (load_path_check): adjust for pdumper. (load_path_default): use pdumper functions; adjust for dump search. * src/macfont.m (macfont_init_font_change_handler): avoid shadowing global. (syms_of_macfont_for_pdumper): new function. (syms_of_macfont): call it. * src/menu.c (syms_of_menu): staticpro more stuff. * src/minibuf.c (Ftry_completion): rehash if needed. (init_minibuf_once_for_pdumper): new function. (init_minibuf_once): call it. * src/nsfont.m (syms_of_nsfns): staticpro more. * src/nsfont.m (syms_of_nsfont_for_pdumper): new function. (syms_of_nsfont): call it. * src/nsterm.m (syms_of_nsfont): remember pdumper stuff. * src/pdumper.c: new file. * src/pdumper.h: new file. * src/process.c (init_process_emacs): use new pdumper functions instead of CANNOT_DUMP. * src/profiler.c (syms_of_profiler_for_pdumper): new function. (syms_of_profiler_for_pdumper): call it. * src/search.c (syms_of_search_for_pdumper): new function. (syms_of_search_for_pdumper): call it. * src/sheap.c (bss_sbrk_did_unexec): remove. * src/sheap.h (bss_sbrk_did_unexec): remove. * src/syntax.c (syms_of_syntax): don't redundantly staticpro re_match_object. * src/sysdep.c: use will_dump_with_unexec_p() instead of bss hack thing. * src/syssignals.h (init_sigsegv): declare. * src/systime.h (init_timefns): remove bool from signature. * src/textprop.c (syms_of_textprop): move staticpro. * src/thread.c (main_thread_p): constify. * src/thread.h (main_thread_p): constify. * src/timefns.c (init_timefns): remove bool from signature. (syms_of_timefns_for_pdumper): new function. (syms_of_timefns): call it. * src/w32.c: rearrange code. * src/w32.h (w32_relocate): declare. * src/w32fns.c (syms_of_w32fns): add pdumper note. * src/w32font.c (syms_of_w32font_for_pdumper): new function. (syms_of_w32font): call it. * src/w32heap.c (using_dynamic_heap): new variable. (init_heap): use it. * src/w32menu.c (syms_of_w32menu): add pdumper note. * src/w32proc.c (ctrl_c_handler, mainCRTStartup, _start, open_input_file) (rva_to_section, close_file_data): move here. * src/w32uniscribe.c (syms_of_w32uniscribe_for_pdumper): new function. (syms_of_w32uniscribe): call it. * src/window.c (init_window_once_for_pdumper): new function. (init_window_once): call it; staticpro more stuff. * src/xfont.c (syms_of_xfont_for_pdumper): new function. (syms_of_xfont): call it. * src/xftfont.c (syms_of_xftfont_for_pdumper): new function. (syms_of_xftfont): call it. * src/xmenu.c (syms_of_xmenu_for_pdumper): new function. (syms_of_xmenu): call it. * src/xselect.c (syms_of_xselect_for_pdumper): new function. (syms_of_xselect): call it. * src/xsettings.c (syms_of_xsettings): add more pdumper notes. * src/term.c (syms_of_xterm): add pdumper note. * src/dispnew.c (init_faces_initial): new function. (init_display_interactive): rename from init_display; use will_dump_p instead of !initialized. Initialize faces early for pdumper if needed. (init_display): new function. (syms_of_display_for_pdumper): new function. (syms_of_display): call it. * src/dbusbind.c (syms_of_dbusbind): Add TODO for bus reset on pdumper load. * src/data.c (Fdefalias): Use will_dump_p instead of Vpurify_flag. (Fmake_variable_buffer_local): silence compiler warning with -Og by making valcontents UNINIT. (arith_driver): silence compiler warning with UNINIT. * src/conf_post.h (ATTRIBUTE_SECTION): new macro. * src/composite.c (composition_gstring_put_cache): rehash hash table if needed. * src/coding.c (init_coding_once, syms_of_coding): remember pdumper stuff. * src/charset.h (charset_table_size, charset_table_user): declare. * src/charset.c (charset_table_used, charset_table_size): un-static. (init_charset_oncem, syms_of_charset): remember pdumper stuff. * src/category.c (category_table_version): remove obsolete variable. * src/callint.c (syms_of_callint): staticpro 'preserved_fns' (init_callproc): use will_dump_p instead of !CANNOT_DUMP. * src/bytecode.c (exec_byte_code): rehash table tables if needed * src/buffer.c (alloc_buffer_text, free_buffer_text): account for pdumper (init_buffer_once): add TODO; remember stuff for pdumper. (init_buffer): don't take initialized argument; adjust for pdumper. * src/atimer.c (init_atimer): initialize subr only if !initialized. * src/alloc.c: (vector_marked_p, set_vector_marked) (vectorlike_marked_p, set_vectorlike_marked, cons_marked_p) (set_cons_marked, string_marked_p, set_string_marked) (symbol_marked_p, set_symbol_marked, interval_marked_p) (set_interval_marked): new accessor routines. Use them instead of raw GC access throughout. (Vdead): make non-static when ENABLE_CHECKING. (vectorlike_nbytes): rename of 'vector_nbytes'; take a vectorlike header as input instead of a vector. (number_finalizers_run): new internal C variable. (mark_maybe_object): check for pdumper objects. (valid_pointer_p): don't be gratuitously inefficient under rr(1). (make_pure_c_string): add support for size_byte = -2 mode indicating that string data points into Emacs image rodata. (visit_vectorlike_root): visits GC roots embedded in vectorlike objects. (visit_buffer_root): visits GC roots embedded in our totally-not-a-buffer buffer global objects. (visit_static_gc_roots): visit GC roots in the Emacs data section. (mark_object_root_visitor): root callback used for conventional GC marking (weak_hash_tables): new internal variable for tracking found weak hash tables during GC. (mark_and_sweep_weak_table_contents): new weak hash table marking. (garbage_collect_1): use new GC root visitor machinery. (mark_vectorlike): accept a vectorlike_header instead of a Lisp_Vector. (mark_frame, mark_window, mark_hash_table): new functions. (mark_object): initialize 'm'; check for pdumper objects and use new mark-bit accessors throughout. Remove some object-specific marking code and move to helper functions above. (survives_gc_p): check for pdumper objects. (gc-sweep): clear pdumper mark bits. (init_alloc_once_for_pdumper): new helper function for early init called both during normal init and pdumper load. (init_alloc_once): pdumper integration. * src/Makefile.in: Rewrite dumping for pdumper; add pdumper.o; invoke temacs with --temacs command line option; build dmpstruct.h from dmpstruct.awk; stop relying on CANNOT_DUMP; clean up pdumper intermediate files during build. * nextstep/Makefile.in: build emacs.pdmp into NS packages * lisp/startup.el: account for new '--temacs' and '--dump-file' command line option. * lisp/loadup.el: rewrite early init to account for pdumper; use injected 'dump-mode' variable (set via the new '--temacs' option) instead of parsing command line. * lisp/cus-start.el: Check 'dump-mode' instead of 'purify-flag', since the new 'dump-mode' * lib-src/make-fingerprint.c: new program * lib-src/Makefile.in: built make-fingerprint utility program * configure.ac: Add --with-pdumper toggle to control pdumper support; add --with-unexec toggle to control unexec support. Add --with-dumping option to control which dumping strategy we use by default. Adjust for pdumper throughout. Check for posix_madvise. * Makefile.in: Add @DUMPING@ substitution; add pdumper mode. * .gitignore: Add make-fingerprint, temacs.in, fingerprint.c, dmpstruct.h, and pdumper dump files.
506 lines
16 KiB
C
506 lines
16 KiB
C
/* GNU Emacs routines to deal with category tables.
|
||
|
||
Copyright (C) 1998, 2001-2019 Free Software Foundation, Inc.
|
||
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||
2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||
National Institute of Advanced Industrial Science and Technology (AIST)
|
||
Registration Number H14PRO021
|
||
Copyright (C) 2003
|
||
National Institute of Advanced Industrial Science and Technology (AIST)
|
||
Registration Number H13PRO009
|
||
|
||
This file is part of GNU Emacs.
|
||
|
||
GNU Emacs is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or (at
|
||
your option) any later version.
|
||
|
||
GNU Emacs is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||
|
||
|
||
/* Here we handle three objects: category, category set, and category
|
||
table. Read comments in the file category.h to understand them. */
|
||
|
||
#include <config.h>
|
||
|
||
#include "lisp.h"
|
||
#include "character.h"
|
||
#include "buffer.h"
|
||
#include "category.h"
|
||
|
||
/* This setter is used only in this file, so it can be private. */
|
||
static void
|
||
bset_category_table (struct buffer *b, Lisp_Object val)
|
||
{
|
||
b->category_table_ = val;
|
||
}
|
||
|
||
|
||
/* Category set staff. */
|
||
|
||
static Lisp_Object
|
||
hash_get_category_set (Lisp_Object table, Lisp_Object category_set)
|
||
{
|
||
struct Lisp_Hash_Table *h;
|
||
ptrdiff_t i;
|
||
EMACS_UINT hash;
|
||
|
||
if (NILP (XCHAR_TABLE (table)->extras[1]))
|
||
set_char_table_extras
|
||
(table, 1,
|
||
make_hash_table (hashtest_equal, DEFAULT_HASH_SIZE,
|
||
DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
|
||
Qnil, false));
|
||
h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]);
|
||
i = hash_lookup (h, category_set, &hash);
|
||
if (i >= 0)
|
||
return HASH_KEY (h, i);
|
||
hash_put (h, category_set, Qnil, hash);
|
||
return category_set;
|
||
}
|
||
|
||
/* Make CATEGORY_SET include (if VAL) or exclude (if !VAL) CATEGORY. */
|
||
|
||
static void
|
||
set_category_set (Lisp_Object category_set, EMACS_INT category, bool val)
|
||
{
|
||
bool_vector_set (category_set, category, val);
|
||
}
|
||
|
||
DEFUN ("make-category-set", Fmake_category_set, Smake_category_set, 1, 1, 0,
|
||
doc: /* Return a newly created category-set which contains CATEGORIES.
|
||
CATEGORIES is a string of category mnemonics.
|
||
The value is a bool-vector which has t at the indices corresponding to
|
||
those categories. */)
|
||
(Lisp_Object categories)
|
||
{
|
||
Lisp_Object val;
|
||
ptrdiff_t len;
|
||
|
||
CHECK_STRING (categories);
|
||
val = MAKE_CATEGORY_SET;
|
||
|
||
if (STRING_MULTIBYTE (categories))
|
||
error ("Multibyte string in `make-category-set'");
|
||
|
||
len = SCHARS (categories);
|
||
while (--len >= 0)
|
||
{
|
||
unsigned char cat = SREF (categories, len);
|
||
Lisp_Object category = make_fixnum (cat);
|
||
|
||
CHECK_CATEGORY (category);
|
||
set_category_set (val, cat, 1);
|
||
}
|
||
return val;
|
||
}
|
||
|
||
|
||
/* Category staff. */
|
||
|
||
static Lisp_Object check_category_table (Lisp_Object table);
|
||
|
||
DEFUN ("define-category", Fdefine_category, Sdefine_category, 2, 3, 0,
|
||
doc: /* Define CATEGORY as a category which is described by DOCSTRING.
|
||
CATEGORY should be an ASCII printing character in the range ` ' to `~'.
|
||
DOCSTRING is the documentation string of the category. The first line
|
||
should be a terse text (preferably less than 16 characters),
|
||
and the rest lines should be the full description.
|
||
The category is defined only in category table TABLE, which defaults to
|
||
the current buffer's category table. */)
|
||
(Lisp_Object category, Lisp_Object docstring, Lisp_Object table)
|
||
{
|
||
CHECK_CATEGORY (category);
|
||
CHECK_STRING (docstring);
|
||
table = check_category_table (table);
|
||
|
||
if (!NILP (CATEGORY_DOCSTRING (table, XFIXNAT (category))))
|
||
error ("Category `%c' is already defined", (int) XFIXNAT (category));
|
||
if (!NILP (Vpurify_flag))
|
||
docstring = Fpurecopy (docstring);
|
||
SET_CATEGORY_DOCSTRING (table, XFIXNAT (category), docstring);
|
||
|
||
return Qnil;
|
||
}
|
||
|
||
DEFUN ("category-docstring", Fcategory_docstring, Scategory_docstring, 1, 2, 0,
|
||
doc: /* Return the documentation string of CATEGORY, as defined in TABLE.
|
||
TABLE should be a category table and defaults to the current buffer's
|
||
category table. */)
|
||
(Lisp_Object category, Lisp_Object table)
|
||
{
|
||
CHECK_CATEGORY (category);
|
||
table = check_category_table (table);
|
||
|
||
return CATEGORY_DOCSTRING (table, XFIXNAT (category));
|
||
}
|
||
|
||
DEFUN ("get-unused-category", Fget_unused_category, Sget_unused_category,
|
||
0, 1, 0,
|
||
doc: /* Return a category which is not yet defined in TABLE.
|
||
If no category remains available, return nil.
|
||
The optional argument TABLE specifies which category table to modify;
|
||
it defaults to the current buffer's category table. */)
|
||
(Lisp_Object table)
|
||
{
|
||
int i;
|
||
|
||
table = check_category_table (table);
|
||
|
||
for (i = ' '; i <= '~'; i++)
|
||
if (NILP (CATEGORY_DOCSTRING (table, i)))
|
||
return make_fixnum (i);
|
||
|
||
return Qnil;
|
||
}
|
||
|
||
|
||
/* Category-table staff. */
|
||
|
||
DEFUN ("category-table-p", Fcategory_table_p, Scategory_table_p, 1, 1, 0,
|
||
doc: /* Return t if ARG is a category table. */)
|
||
(Lisp_Object arg)
|
||
{
|
||
if (CHAR_TABLE_P (arg)
|
||
&& EQ (XCHAR_TABLE (arg)->purpose, Qcategory_table))
|
||
return Qt;
|
||
return Qnil;
|
||
}
|
||
|
||
/* If TABLE is nil, return the current category table. If TABLE is
|
||
not nil, check the validity of TABLE as a category table. If
|
||
valid, return TABLE itself, but if not valid, signal an error of
|
||
wrong-type-argument. */
|
||
|
||
static Lisp_Object
|
||
check_category_table (Lisp_Object table)
|
||
{
|
||
if (NILP (table))
|
||
return BVAR (current_buffer, category_table);
|
||
CHECK_TYPE (!NILP (Fcategory_table_p (table)), Qcategory_table_p, table);
|
||
return table;
|
||
}
|
||
|
||
DEFUN ("category-table", Fcategory_table, Scategory_table, 0, 0, 0,
|
||
doc: /* Return the current category table.
|
||
This is the one specified by the current buffer. */)
|
||
(void)
|
||
{
|
||
return BVAR (current_buffer, category_table);
|
||
}
|
||
|
||
DEFUN ("standard-category-table", Fstandard_category_table,
|
||
Sstandard_category_table, 0, 0, 0,
|
||
doc: /* Return the standard category table.
|
||
This is the one used for new buffers. */)
|
||
(void)
|
||
{
|
||
return Vstandard_category_table;
|
||
}
|
||
|
||
|
||
static void
|
||
copy_category_entry (Lisp_Object table, Lisp_Object c, Lisp_Object val)
|
||
{
|
||
val = Fcopy_sequence (val);
|
||
if (CONSP (c))
|
||
char_table_set_range (table, XFIXNUM (XCAR (c)), XFIXNUM (XCDR (c)), val);
|
||
else
|
||
char_table_set (table, XFIXNUM (c), val);
|
||
}
|
||
|
||
/* Return a copy of category table TABLE. We can't simply use the
|
||
function copy-sequence because no contents should be shared between
|
||
the original and the copy. This function is called recursively by
|
||
binding TABLE to a sub char table. */
|
||
|
||
static Lisp_Object
|
||
copy_category_table (Lisp_Object table)
|
||
{
|
||
table = copy_char_table (table);
|
||
|
||
if (! NILP (XCHAR_TABLE (table)->defalt))
|
||
set_char_table_defalt (table,
|
||
Fcopy_sequence (XCHAR_TABLE (table)->defalt));
|
||
set_char_table_extras
|
||
(table, 0, Fcopy_sequence (XCHAR_TABLE (table)->extras[0]));
|
||
map_char_table (copy_category_entry, Qnil, table, table);
|
||
|
||
return table;
|
||
}
|
||
|
||
DEFUN ("copy-category-table", Fcopy_category_table, Scopy_category_table,
|
||
0, 1, 0,
|
||
doc: /* Construct a new category table and return it.
|
||
It is a copy of the TABLE, which defaults to the standard category table. */)
|
||
(Lisp_Object table)
|
||
{
|
||
if (!NILP (table))
|
||
check_category_table (table);
|
||
else
|
||
table = Vstandard_category_table;
|
||
|
||
return copy_category_table (table);
|
||
}
|
||
|
||
DEFUN ("make-category-table", Fmake_category_table, Smake_category_table,
|
||
0, 0, 0,
|
||
doc: /* Construct a new and empty category table and return it. */)
|
||
(void)
|
||
{
|
||
Lisp_Object val;
|
||
int i;
|
||
|
||
val = Fmake_char_table (Qcategory_table, Qnil);
|
||
set_char_table_defalt (val, MAKE_CATEGORY_SET);
|
||
for (i = 0; i < (1 << CHARTAB_SIZE_BITS_0); i++)
|
||
set_char_table_contents (val, i, MAKE_CATEGORY_SET);
|
||
Fset_char_table_extra_slot (val, make_fixnum (0), make_nil_vector (95));
|
||
return val;
|
||
}
|
||
|
||
DEFUN ("set-category-table", Fset_category_table, Sset_category_table, 1, 1, 0,
|
||
doc: /* Specify TABLE as the category table for the current buffer.
|
||
Return TABLE. */)
|
||
(Lisp_Object table)
|
||
{
|
||
int idx;
|
||
table = check_category_table (table);
|
||
bset_category_table (current_buffer, table);
|
||
/* Indicate that this buffer now has a specified category table. */
|
||
idx = PER_BUFFER_VAR_IDX (category_table);
|
||
SET_PER_BUFFER_VALUE_P (current_buffer, idx, 1);
|
||
return table;
|
||
}
|
||
|
||
|
||
Lisp_Object
|
||
char_category_set (int c)
|
||
{
|
||
return CHAR_TABLE_REF (BVAR (current_buffer, category_table), c);
|
||
}
|
||
|
||
DEFUN ("char-category-set", Fchar_category_set, Schar_category_set, 1, 1, 0,
|
||
doc: /* Return the category set of CHAR.
|
||
usage: (char-category-set CHAR) */)
|
||
(Lisp_Object ch)
|
||
{
|
||
CHECK_CHARACTER (ch);
|
||
return CATEGORY_SET (XFIXNAT (ch));
|
||
}
|
||
|
||
DEFUN ("category-set-mnemonics", Fcategory_set_mnemonics,
|
||
Scategory_set_mnemonics, 1, 1, 0,
|
||
doc: /* Return a string containing mnemonics of the categories in CATEGORY-SET.
|
||
CATEGORY-SET is a bool-vector, and the categories \"in\" it are those
|
||
that are indexes where t occurs in the bool-vector.
|
||
The return value is a string containing those same categories. */)
|
||
(Lisp_Object category_set)
|
||
{
|
||
int i, j;
|
||
char str[96];
|
||
|
||
CHECK_CATEGORY_SET (category_set);
|
||
|
||
j = 0;
|
||
for (i = 32; i < 127; i++)
|
||
if (CATEGORY_MEMBER (i, category_set))
|
||
str[j++] = i;
|
||
str[j] = '\0';
|
||
|
||
return build_string (str);
|
||
}
|
||
|
||
DEFUN ("modify-category-entry", Fmodify_category_entry,
|
||
Smodify_category_entry, 2, 4, 0,
|
||
doc: /* Modify the category set of CHARACTER by adding CATEGORY to it.
|
||
The category is changed only for table TABLE, which defaults to
|
||
the current buffer's category table.
|
||
CHARACTER can be either a single character or a cons representing the
|
||
lower and upper ends of an inclusive character range to modify.
|
||
CATEGORY must be a category name (a character between ` ' and `~').
|
||
Use `describe-categories' to see existing category names.
|
||
If optional fourth argument RESET is non-nil,
|
||
then delete CATEGORY from the category set instead of adding it. */)
|
||
(Lisp_Object character, Lisp_Object category, Lisp_Object table, Lisp_Object reset)
|
||
{
|
||
bool set_value; /* Actual value to be set in category sets. */
|
||
Lisp_Object category_set;
|
||
int start, end;
|
||
int from, to;
|
||
|
||
if (FIXNUMP (character))
|
||
{
|
||
CHECK_CHARACTER (character);
|
||
start = end = XFIXNAT (character);
|
||
}
|
||
else
|
||
{
|
||
CHECK_CONS (character);
|
||
CHECK_CHARACTER_CAR (character);
|
||
CHECK_CHARACTER_CDR (character);
|
||
start = XFIXNAT (XCAR (character));
|
||
end = XFIXNAT (XCDR (character));
|
||
}
|
||
|
||
CHECK_CATEGORY (category);
|
||
table = check_category_table (table);
|
||
|
||
if (NILP (CATEGORY_DOCSTRING (table, XFIXNAT (category))))
|
||
error ("Undefined category: %c", (int) XFIXNAT (category));
|
||
|
||
set_value = NILP (reset);
|
||
|
||
while (start <= end)
|
||
{
|
||
from = start, to = end;
|
||
category_set = char_table_ref_and_range (table, start, &from, &to);
|
||
if (CATEGORY_MEMBER (XFIXNAT (category), category_set) != NILP (reset))
|
||
{
|
||
category_set = Fcopy_sequence (category_set);
|
||
set_category_set (category_set, XFIXNAT (category), set_value);
|
||
category_set = hash_get_category_set (table, category_set);
|
||
char_table_set_range (table, start, to, category_set);
|
||
}
|
||
start = to + 1;
|
||
}
|
||
|
||
return Qnil;
|
||
}
|
||
|
||
/* Return true if there is a word boundary between two word-constituent
|
||
characters C1 and C2 if they appear in this order.
|
||
Use the macro WORD_BOUNDARY_P instead of calling this function
|
||
directly. */
|
||
|
||
bool
|
||
word_boundary_p (int c1, int c2)
|
||
{
|
||
Lisp_Object category_set1, category_set2;
|
||
Lisp_Object tail;
|
||
bool default_result;
|
||
|
||
if (EQ (CHAR_TABLE_REF (Vchar_script_table, c1),
|
||
CHAR_TABLE_REF (Vchar_script_table, c2)))
|
||
{
|
||
tail = Vword_separating_categories;
|
||
default_result = 0;
|
||
}
|
||
else
|
||
{
|
||
tail = Vword_combining_categories;
|
||
default_result = 1;
|
||
}
|
||
|
||
category_set1 = CATEGORY_SET (c1);
|
||
if (NILP (category_set1))
|
||
return default_result;
|
||
category_set2 = CATEGORY_SET (c2);
|
||
if (NILP (category_set2))
|
||
return default_result;
|
||
|
||
for (; CONSP (tail); tail = XCDR (tail))
|
||
{
|
||
Lisp_Object elt = XCAR (tail);
|
||
|
||
if (CONSP (elt)
|
||
&& (NILP (XCAR (elt))
|
||
|| (CATEGORYP (XCAR (elt))
|
||
&& CATEGORY_MEMBER (XFIXNAT (XCAR (elt)), category_set1)
|
||
&& ! CATEGORY_MEMBER (XFIXNAT (XCAR (elt)), category_set2)))
|
||
&& (NILP (XCDR (elt))
|
||
|| (CATEGORYP (XCDR (elt))
|
||
&& ! CATEGORY_MEMBER (XFIXNAT (XCDR (elt)), category_set1)
|
||
&& CATEGORY_MEMBER (XFIXNAT (XCDR (elt)), category_set2))))
|
||
return !default_result;
|
||
}
|
||
return default_result;
|
||
}
|
||
|
||
|
||
void
|
||
init_category_once (void)
|
||
{
|
||
/* This has to be done here, before we call Fmake_char_table. */
|
||
DEFSYM (Qcategory_table, "category-table");
|
||
Fput (Qcategory_table, Qchar_table_extra_slots, make_fixnum (2));
|
||
|
||
Vstandard_category_table = Fmake_char_table (Qcategory_table, Qnil);
|
||
/* Set a category set which contains nothing to the default. */
|
||
set_char_table_defalt (Vstandard_category_table, MAKE_CATEGORY_SET);
|
||
Fset_char_table_extra_slot (Vstandard_category_table, make_fixnum (0),
|
||
make_nil_vector (95));
|
||
}
|
||
|
||
void
|
||
syms_of_category (void)
|
||
{
|
||
DEFSYM (Qcategoryp, "categoryp");
|
||
DEFSYM (Qcategorysetp, "categorysetp");
|
||
DEFSYM (Qcategory_table_p, "category-table-p");
|
||
|
||
DEFVAR_LISP ("word-combining-categories", Vword_combining_categories,
|
||
doc: /* List of pair (cons) of categories to determine word boundary.
|
||
|
||
Emacs treats a sequence of word constituent characters as a single
|
||
word (i.e. finds no word boundary between them) only if they belong to
|
||
the same script. But, exceptions are allowed in the following cases.
|
||
|
||
\(1) The case that characters are in different scripts is controlled
|
||
by the variable `word-combining-categories'.
|
||
|
||
Emacs finds no word boundary between characters of different scripts
|
||
if they have categories matching some element of this list.
|
||
|
||
More precisely, if an element of this list is a cons of category CAT1
|
||
and CAT2, and a multibyte character C1 which has CAT1 is followed by
|
||
C2 which has CAT2, there's no word boundary between C1 and C2.
|
||
|
||
For instance, to tell that Han characters followed by Hiragana
|
||
characters can form a single word, the element `(?C . ?H)' should be
|
||
in this list.
|
||
|
||
\(2) The case that character are in the same script is controlled by
|
||
the variable `word-separating-categories'.
|
||
|
||
Emacs finds a word boundary between characters of the same script
|
||
if they have categories matching some element of this list.
|
||
|
||
More precisely, if an element of this list is a cons of category CAT1
|
||
and CAT2, and a multibyte character C1 which has CAT1 but not CAT2 is
|
||
followed by C2 which has CAT2 but not CAT1, there's a word boundary
|
||
between C1 and C2.
|
||
|
||
For instance, to tell that there's a word boundary between Hiragana
|
||
and Katakana (both are in the same script `kana'),
|
||
the element `(?H . ?K)' should be in this list. */);
|
||
|
||
Vword_combining_categories = Qnil;
|
||
|
||
DEFVAR_LISP ("word-separating-categories", Vword_separating_categories,
|
||
doc: /* List of pair (cons) of categories to determine word boundary.
|
||
See the documentation of the variable `word-combining-categories'. */);
|
||
|
||
Vword_separating_categories = Qnil;
|
||
|
||
defsubr (&Smake_category_set);
|
||
defsubr (&Sdefine_category);
|
||
defsubr (&Scategory_docstring);
|
||
defsubr (&Sget_unused_category);
|
||
defsubr (&Scategory_table_p);
|
||
defsubr (&Scategory_table);
|
||
defsubr (&Sstandard_category_table);
|
||
defsubr (&Scopy_category_table);
|
||
defsubr (&Smake_category_table);
|
||
defsubr (&Sset_category_table);
|
||
defsubr (&Schar_category_set);
|
||
defsubr (&Scategory_set_mnemonics);
|
||
defsubr (&Smodify_category_entry);
|
||
}
|