diff options
Diffstat (limited to 'src/doc.c')
-rw-r--r-- | src/doc.c | 600 |
1 files changed, 138 insertions, 462 deletions
diff --git a/src/doc.c b/src/doc.c index 3286c12675a..67a5f845b93 100644 --- a/src/doc.c +++ b/src/doc.c @@ -1,6 +1,6 @@ /* Record indices of function doc strings stored in a file. -*- coding: utf-8 -*- -Copyright (C) 1985-1986, 1993-1995, 1997-2017 Free Software Foundation, +Copyright (C) 1985-1986, 1993-1995, 1997-2022 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -82,29 +82,29 @@ Lisp_Object get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) { char *from, *to, *name, *p, *p1; - int fd; - int offset; - EMACS_INT position; - Lisp_Object file, tem, pos; - ptrdiff_t count; + Lisp_Object file, pos; + specpdl_ref count = SPECPDL_INDEX (); + Lisp_Object dir; USE_SAFE_ALLOCA; - if (INTEGERP (filepos)) + if (FIXNUMP (filepos)) { file = Vdoc_file_name; + dir = Vdoc_directory; pos = filepos; } else if (CONSP (filepos)) { file = XCAR (filepos); + dir = Fsymbol_value (Qlisp_directory); pos = XCDR (filepos); } else return Qnil; - position = eabs (XINT (pos)); + EMACS_INT position = eabs (XFIXNUM (pos)); - if (!STRINGP (Vdoc_directory)) + if (!STRINGP (dir)) return Qnil; if (!STRINGP (file)) @@ -113,22 +113,20 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) /* Put the file name in NAME as a C string. If it is relative, combine it with Vdoc_directory. */ - tem = Ffile_name_absolute_p (file); + Lisp_Object tem = Ffile_name_absolute_p (file); file = ENCODE_FILE (file); Lisp_Object docdir - = NILP (tem) ? ENCODE_FILE (Vdoc_directory) : empty_unibyte_string; + = NILP (tem) ? ENCODE_FILE (dir) : empty_unibyte_string; ptrdiff_t docdir_sizemax = SBYTES (docdir) + 1; -#ifndef CANNOT_DUMP - docdir_sizemax = max (docdir_sizemax, sizeof sibling_etc); -#endif + if (will_dump_p ()) + docdir_sizemax = max (docdir_sizemax, sizeof sibling_etc); name = SAFE_ALLOCA (docdir_sizemax + SBYTES (file)); lispstpcpy (lispstpcpy (name, docdir), file); - fd = emacs_open (name, O_RDONLY, 0); + int fd = emacs_open (name, O_RDONLY, 0); if (fd < 0) { -#ifndef CANNOT_DUMP - if (!NILP (Vpurify_flag)) + if (will_dump_p ()) { /* Preparing to dump; DOC file is probably not installed. So check in ../etc. */ @@ -136,10 +134,9 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) fd = emacs_open (name, O_RDONLY, 0); } -#endif if (fd < 0) { - if (errno == EMFILE || errno == ENFILE) + if (errno != ENOENT && errno != ENOTDIR) report_file_error ("Read error on documentation file", file); SAFE_FREE (); @@ -148,13 +145,12 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) return concat3 (cannot_open, file, quote_nl); } } - count = SPECPDL_INDEX (); record_unwind_protect_int (close_file_unwind, fd); /* Seek only to beginning of disk block. */ /* Make sure we read at least 1024 bytes before `position' so we can check the leading text for consistency. */ - offset = min (position, max (1024, position % (8 * 1024))); + int offset = min (position, max (1024, position % (8 * 1024))); if (TYPE_MAXIMUM (off_t) < position || lseek (fd, position - offset, 0) < 0) error ("Position %"pI"d out of range in doc string file \"%s\"", @@ -168,7 +164,6 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) { ptrdiff_t space_left = (get_doc_string_buffer_size - 1 - (p - get_doc_string_buffer)); - int nread; /* Allocate or grow the buffer if we need to. */ if (space_left <= 0) @@ -186,7 +181,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) If we read the same block last time, maybe skip this? */ if (space_left > 1024 * 8) space_left = 1024 * 8; - nread = emacs_read_quit (fd, p, space_left); + int nread = emacs_read_quit (fd, p, space_left); if (nread < 0) report_file_error ("Read error on documentation file", file); p[nread] = 0; @@ -204,8 +199,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) } p += nread; } - unbind_to (count, Qnil); - SAFE_FREE (); + SAFE_FREE_UNBIND_TO (count, Qnil); /* Sanity checking. */ if (CONSP (filepos)) @@ -245,10 +239,8 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) { if (*from == 1) { - int c; - from++; - c = *from++; + int c = *from++; if (c == 1) *to++ = c; else if (c == '0') @@ -307,7 +299,7 @@ reread_doc_file (Lisp_Object file) if (NILP (file)) Fsnarf_documentation (Vdoc_file_name); else - Fload (file, Qt, Qt, Qt, Qnil); + save_match_data_load (file, Qt, Qt, Qt, Qnil); return 1; } @@ -318,10 +310,8 @@ Unless a non-nil second argument RAW is given, the string is passed through `substitute-command-keys'. */) (Lisp_Object function, Lisp_Object raw) { - Lisp_Object fun; - Lisp_Object funcar; Lisp_Object doc; - bool try_reload = 1; + bool try_reload = true; documentation: @@ -335,69 +325,30 @@ string is passed through `substitute-command-keys'. */) raw); } - fun = Findirect_function (function, Qnil); + Lisp_Object fun = Findirect_function (function, Qnil); + if (NILP (fun)) + xsignal1 (Qvoid_function, function); if (CONSP (fun) && EQ (XCAR (fun), Qmacro)) fun = XCDR (fun); +#ifdef HAVE_NATIVE_COMP + if (!NILP (Fsubr_native_elisp_p (fun))) + doc = native_function_doc (fun); + else +#endif if (SUBRP (fun)) - doc = make_number (XSUBR (fun)->doc); + doc = make_fixnum (XSUBR (fun)->doc); +#ifdef HAVE_MODULES else if (MODULE_FUNCTIONP (fun)) - doc = XMODULE_FUNCTION (fun)->documentation; - else if (COMPILEDP (fun)) - { - if (PVSIZE (fun) <= COMPILED_DOC_STRING) - return Qnil; - else - { - Lisp_Object tem = AREF (fun, COMPILED_DOC_STRING); - if (STRINGP (tem)) - doc = tem; - else if (NATNUMP (tem) || CONSP (tem)) - doc = tem; - else - return Qnil; - } - } - else if (STRINGP (fun) || VECTORP (fun)) - { - return build_string ("Keyboard macro."); - } - else if (CONSP (fun)) - { - funcar = XCAR (fun); - if (!SYMBOLP (funcar)) - xsignal1 (Qinvalid_function, fun); - else if (EQ (funcar, Qkeymap)) - return build_string ("Prefix command (definition is a keymap associating keystrokes with commands)."); - else if (EQ (funcar, Qlambda) - || (EQ (funcar, Qclosure) && (fun = XCDR (fun), 1)) - || EQ (funcar, Qautoload)) - { - Lisp_Object tem1 = Fcdr (Fcdr (fun)); - Lisp_Object tem = Fcar (tem1); - if (STRINGP (tem)) - doc = tem; - /* Handle a doc reference--but these never come last - in the function body, so reject them if they are last. */ - else if ((NATNUMP (tem) || (CONSP (tem) && INTEGERP (XCDR (tem)))) - && !NILP (XCDR (tem1))) - doc = tem; - else - return Qnil; - } - else - goto oops; - } + doc = module_function_documentation (XMODULE_FUNCTION (fun)); +#endif else - { - oops: - xsignal1 (Qinvalid_function, fun); - } + doc = call1 (Qfunction_documentation, fun); /* If DOC is 0, it's typically because of a dumped file missing from the DOC file (bug in src/Makefile.in). */ - if (EQ (doc, make_number (0))) + if (BASE_EQ (doc, make_fixnum (0))) doc = Qnil; - if (INTEGERP (doc) || CONSP (doc)) + if (FIXNUMP (doc) || CONSP (doc)) { Lisp_Object tem; tem = get_doc_string (doc, 0, 0); @@ -407,7 +358,7 @@ string is passed through `substitute-command-keys'. */) try_reload = reread_doc_file (Fcar_safe (doc)); if (try_reload) { - try_reload = 0; + try_reload = false; goto documentation; } } @@ -416,7 +367,7 @@ string is passed through `substitute-command-keys'. */) } if (NILP (raw)) - doc = Fsubstitute_command_keys (doc); + doc = call1 (Qsubstitute_command_keys, doc); return doc; } @@ -431,15 +382,29 @@ This differs from `get' in that it can refer to strings stored in the aren't strings. */) (Lisp_Object symbol, Lisp_Object prop, Lisp_Object raw) { - bool try_reload = 1; + bool try_reload = true; Lisp_Object tem; documentation_property: tem = Fget (symbol, prop); - if (EQ (tem, make_number (0))) + + /* If we don't have any documentation for this symbol (and we're asking for + the variable documentation), try to see whether it's an indirect variable + and get the documentation from there instead. */ + if (EQ (prop, Qvariable_documentation) + && NILP (tem)) + { + Lisp_Object indirect = Findirect_variable (symbol); + if (!NILP (indirect)) + tem = Fget (indirect, prop); + } + + if (BASE_EQ (tem, make_fixnum (0))) tem = Qnil; - if (INTEGERP (tem) || (CONSP (tem) && INTEGERP (XCDR (tem)))) + + /* See if we want to look for the string in the DOC file. */ + if (FIXNUMP (tem) || (CONSP (tem) && FIXNUMP (XCDR (tem)))) { Lisp_Object doc = tem; tem = get_doc_string (tem, 0, 0); @@ -449,7 +414,7 @@ aren't strings. */) try_reload = reread_doc_file (Fcar_safe (doc)); if (try_reload) { - try_reload = 0; + try_reload = false; goto documentation_property; } } @@ -459,7 +424,7 @@ aren't strings. */) tem = Feval (tem, Qnil); if (NILP (raw) && STRINGP (tem)) - tem = Fsubstitute_command_keys (tem); + tem = call1 (Qsubstitute_command_keys, tem); return tem; } @@ -470,7 +435,7 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset) { /* Don't use indirect_function here, or defaliases will apply their docstrings to the base functions (Bug#2603). */ - Lisp_Object fun = SYMBOLP (obj) ? XSYMBOL (obj)->function : obj; + Lisp_Object fun = SYMBOLP (obj) ? XSYMBOL (obj)->u.s.function : obj; /* The type determines where the docstring is stored. */ @@ -479,34 +444,39 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset) fun = XCDR (fun); if (CONSP (fun)) { - Lisp_Object tem; - - tem = XCAR (fun); + Lisp_Object tem = XCAR (fun); if (EQ (tem, Qlambda) || EQ (tem, Qautoload) || (EQ (tem, Qclosure) && (fun = XCDR (fun), 1))) { tem = Fcdr (Fcdr (fun)); - if (CONSP (tem) && INTEGERP (XCAR (tem))) + if (CONSP (tem) && FIXNUMP (XCAR (tem))) /* FIXME: This modifies typically pure hash-cons'd data, so its correctness is quite delicate. */ - XSETCAR (tem, make_number (offset)); + XSETCAR (tem, make_fixnum (offset)); } } - /* Lisp_Subrs have a slot for it. */ - else if (SUBRP (fun)) - XSUBR (fun)->doc = offset; + else if (SUBRP (fun) && !SUBR_NATIVE_COMPILEDP (fun)) + { + XSUBR (fun)->doc = offset; + } /* Bytecode objects sometimes have slots for it. */ else if (COMPILEDP (fun)) { /* This bytecode object must have a slot for the docstring, since we've found a docstring for it. */ - if (PVSIZE (fun) > COMPILED_DOC_STRING) - ASET (fun, COMPILED_DOC_STRING, make_number (offset)); + if (PVSIZE (fun) > COMPILED_DOC_STRING + /* Don't overwrite a non-docstring value placed there, + * such as the symbols used for Oclosures. */ + && VALID_DOCSTRING_P (AREF (fun, COMPILED_DOC_STRING))) + ASET (fun, COMPILED_DOC_STRING, make_fixnum (offset)); else { - AUTO_STRING (format, "No docstring slot for %s"); + AUTO_STRING (format, + (PVSIZE (fun) > COMPILED_DOC_STRING + ? "Docstring slot busy for %s" + : "No docstring slot for %s")); CALLN (Fmessage, format, (SYMBOLP (obj) ? SYMBOL_NAME (obj) @@ -533,8 +503,6 @@ the same file name is found in the `doc-directory'. */) EMACS_INT pos; Lisp_Object sym; char *p, *name; - bool skip_file = 0; - ptrdiff_t count; char const *dirname; ptrdiff_t dirlen; /* Preloaded defcustoms using custom-initialize-delay are added to @@ -542,16 +510,11 @@ the same file name is found in the `doc-directory'. */) Lisp_Object delayed_init = find_symbol_value (intern ("custom-delayed-init-variables")); - if (EQ (delayed_init, Qunbound)) delayed_init = Qnil; + if (!CONSP (delayed_init)) delayed_init = Qnil; CHECK_STRING (filename); - if -#ifndef CANNOT_DUMP - (!NILP (Vpurify_flag)) -#else /* CANNOT_DUMP */ - (0) -#endif /* CANNOT_DUMP */ + if (will_dump_p ()) { dirname = sibling_etc; dirlen = sizeof sibling_etc - 1; @@ -563,7 +526,7 @@ the same file name is found in the `doc-directory'. */) dirlen = SBYTES (Vdoc_directory); } - count = SPECPDL_INDEX (); + specpdl_ref count = SPECPDL_INDEX (); USE_SAFE_ALLOCA; name = SAFE_ALLOCA (dirlen + SBYTES (filename) + 1); lispstpcpy (stpcpy (name, dirname), filename); /*** Add this line ***/ @@ -606,35 +569,27 @@ the same file name is found in the `doc-directory'. */) if (p) { end = strchr (p, '\n'); + if (!end) + error ("DOC file invalid at position %"pI"d", pos); - /* See if this is a file name, and if it is a file in build-files. */ - if (p[1] == 'S') - { - skip_file = 0; - if (end - p > 4 && end[-2] == '.' - && (end[-1] == 'o' || end[-1] == 'c')) - { - ptrdiff_t len = end - p - 2; - char *fromfile = SAFE_ALLOCA (len + 1); - memcpy (fromfile, &p[2], len); - fromfile[len] = 0; - if (fromfile[len-1] == 'c') - fromfile[len-1] = 'o'; - - skip_file = NILP (Fmember (build_string (fromfile), - Vbuild_files)); - } - } + /* We used to skip files not in build_files, so that when a + function was defined several times in different files + (typically, once in xterm, once in w32term, ...), we only + paid attention to the relevant one. + + But this meant the doc had to be kept and updated in + multiple files. Nowadays we keep the doc only in eg xterm. + The (f)boundp checks below ensure we don't report + docs for eg w32-specific items on X. + */ sym = oblookup (Vobarray, p + 2, multibyte_chars_in_text ((unsigned char *) p + 2, end - p - 2), end - p - 2); - /* Check skip_file so that when a function is defined several - times in different files (typically, once in xterm, once in - w32term, ...), we only pay attention to the one that - matters. */ - if (! skip_file && SYMBOLP (sym)) + /* Ignore docs that start with SKIP. These mark + placeholders where the real doc is elsewhere. */ + if (SYMBOLP (sym)) { /* Attach a docstring to a variable? */ if (p[1] == 'V') @@ -642,17 +597,18 @@ the same file name is found in the `doc-directory'. */) /* Install file-position as variable-documentation property and make it negative for a user-variable (doc starts with a `*'). */ - if (!NILP (Fboundp (sym)) + if ((!NILP (Fboundp (sym)) || !NILP (Fmemq (sym, delayed_init))) + && strncmp (end, "\nSKIP", 5)) Fput (sym, Qvariable_documentation, - make_number ((pos + end + 1 - buf) + make_fixnum ((pos + end + 1 - buf) * (end[1] == '*' ? -1 : 1))); } /* Attach a docstring to a function? */ else if (p[1] == 'F') { - if (!NILP (Ffboundp (sym))) + if (!NILP (Ffboundp (sym)) && strncmp (end, "\nSKIP", 5)) store_function_docstring (sym, pos + end + 1 - buf); } else if (p[1] == 'S') @@ -667,8 +623,7 @@ the same file name is found in the `doc-directory'. */) memmove (buf, end, filled); } - SAFE_FREE (); - return unbind_to (count, Qnil); + return SAFE_FREE_UNBIND_TO (count, Qnil); } /* Return true if text quoting style should default to quote `like this'. */ @@ -682,332 +637,47 @@ default_to_grave_quoting_style (void) Lisp_Object dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table), LEFT_SINGLE_QUOTATION_MARK); return (VECTORP (dv) && ASIZE (dv) == 1 - && EQ (AREF (dv, 0), make_number ('`'))); + && BASE_EQ (AREF (dv, 0), make_fixnum ('`'))); } -/* Return the current effective text quoting style. */ -enum text_quoting_style -text_quoting_style (void) +DEFUN ("text-quoting-style", Ftext_quoting_style, + Stext_quoting_style, 0, 0, 0, + doc: /* Return the current effective text quoting style. +If the variable `text-quoting-style' is `grave', `straight' or +`curve', just return that value. If it is nil (the default), return +`grave' if curved quotes cannot be displayed (for instance, on a +terminal with no support for these characters), otherwise return +`quote'. Any other value is treated as `grave'. + +Note that in contrast to the variable `text-quoting-style', this +function will never return nil. */) + (void) { + /* Use grave accent and apostrophe `like this'. */ if (NILP (Vtext_quoting_style) ? default_to_grave_quoting_style () : EQ (Vtext_quoting_style, Qgrave)) - return GRAVE_QUOTING_STYLE; - else if (EQ (Vtext_quoting_style, Qstraight)) - return STRAIGHT_QUOTING_STYLE; - else - return CURVE_QUOTING_STYLE; -} - -DEFUN ("substitute-command-keys", Fsubstitute_command_keys, - Ssubstitute_command_keys, 1, 1, 0, - doc: /* Substitute key descriptions for command names in STRING. -Each substring of the form \\=\\[COMMAND] is replaced by either a -keystroke sequence that invokes COMMAND, or "M-x COMMAND" if COMMAND -is not on any keys. - -Each substring of the form \\=\\{MAPVAR} is replaced by a summary of -the value of MAPVAR as a keymap. This summary is similar to the one -produced by `describe-bindings'. The summary ends in two newlines -\(used by the helper function `help-make-xrefs' to find the end of the -summary). - -Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR -as the keymap for future \\=\\[COMMAND] substrings. - -Each grave accent \\=` is replaced by left quote, and each apostrophe \\=' -is replaced by right quote. Left and right quote characters are -specified by `text-quoting-style'. - -\\=\\= quotes the following character and is discarded; thus, \\=\\=\\=\\= puts \\=\\= -into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and \\=\\=\\=` puts \\=` into the -output. - -Return the original STRING if no substitutions are made. -Otherwise, return a new string. */) - (Lisp_Object string) -{ - char *buf; - bool changed = false; - bool nonquotes_changed = false; - unsigned char *strp; - char *bufp; - ptrdiff_t idx; - ptrdiff_t bsize; - Lisp_Object tem; - Lisp_Object keymap; - unsigned char const *start; - ptrdiff_t length, length_byte; - Lisp_Object name; - ptrdiff_t nchars; - - if (NILP (string)) - return Qnil; - - /* If STRING contains non-ASCII unibyte data, process its - properly-encoded multibyte equivalent instead. This simplifies - the implementation and is OK since substitute-command-keys is - intended for use only on text strings. Keep STRING around, since - it will be returned if no changes occur. */ - Lisp_Object str = Fstring_make_multibyte (string); - - enum text_quoting_style quoting_style = text_quoting_style (); - - nchars = 0; - - /* KEYMAP is either nil (which means search all the active keymaps) - or a specified local map (which means search just that and the - global map). If non-nil, it might come from Voverriding_local_map, - or from a \\<mapname> construct in STRING itself.. */ - keymap = Voverriding_local_map; - - ptrdiff_t strbytes = SBYTES (str); - bsize = strbytes; + return Qgrave; - /* Fixed-size stack buffer. */ - char sbuf[MAX_ALLOCA]; - - /* Heap-allocated buffer, if any. */ - char *abuf; - - /* Extra room for expansion due to replacing ‘\[]’ with ‘M-x ’. */ - enum { EXTRA_ROOM = sizeof "M-x " - sizeof "\\[]" }; - - ptrdiff_t count = SPECPDL_INDEX (); - - if (bsize <= sizeof sbuf - EXTRA_ROOM) - { - abuf = NULL; - buf = sbuf; - bsize = sizeof sbuf; - } - else - { - buf = abuf = xpalloc (NULL, &bsize, EXTRA_ROOM, STRING_BYTES_BOUND, 1); - record_unwind_protect_ptr (xfree, abuf); - } - bufp = buf; - - strp = SDATA (str); - while (strp < SDATA (str) + strbytes) - { - unsigned char *close_bracket; - - if (strp[0] == '\\' && strp[1] == '=' - && strp + 2 < SDATA (str) + strbytes) - { - /* \= quotes the next character; - thus, to put in \[ without its special meaning, use \=\[. */ - changed = nonquotes_changed = true; - strp += 2; - /* Fall through to copy one char. */ - } - else if (strp[0] == '\\' && strp[1] == '[' - && (close_bracket - = memchr (strp + 2, ']', - SDATA (str) + strbytes - (strp + 2)))) - { - bool follow_remap = 1; - - start = strp + 2; - length_byte = close_bracket - start; - idx = close_bracket + 1 - SDATA (str); - - name = Fintern (make_string ((char *) start, length_byte), Qnil); - - do_remap: - tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil); - - if (VECTORP (tem) && ASIZE (tem) > 1 - && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1)) - && follow_remap) - { - name = AREF (tem, 1); - follow_remap = 0; - goto do_remap; - } - - /* Fwhere_is_internal can GC, so take relocation of string - contents into account. */ - strp = SDATA (str) + idx; - start = strp - length_byte - 1; - - if (NILP (tem)) /* but not on any keys */ - { - memcpy (bufp, "M-x ", 4); - bufp += 4; - nchars += 4; - length = multibyte_chars_in_text (start, length_byte); - goto subst; - } - else - { /* function is on a key */ - tem = Fkey_description (tem, Qnil); - goto subst_string; - } - } - /* \{foo} is replaced with a summary of the keymap (symbol-value foo). - \<foo> just sets the keymap used for \[cmd]. */ - else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<') - && (close_bracket - = memchr (strp + 2, strp[1] == '{' ? '}' : '>', - SDATA (str) + strbytes - (strp + 2)))) - { - { - bool generate_summary = strp[1] == '{'; - /* This is for computing the SHADOWS arg for describe_map_tree. */ - Lisp_Object active_maps = Fcurrent_active_maps (Qnil, Qnil); - ptrdiff_t count = SPECPDL_INDEX (); - - start = strp + 2; - length_byte = close_bracket - start; - idx = close_bracket + 1 - SDATA (str); - - /* Get the value of the keymap in TEM, or nil if undefined. - Do this while still in the user's current buffer - in case it is a local variable. */ - name = Fintern (make_string ((char *) start, length_byte), Qnil); - tem = Fboundp (name); - if (! NILP (tem)) - { - tem = Fsymbol_value (name); - if (! NILP (tem)) - tem = get_keymap (tem, 0, 1); - } - - /* Now switch to a temp buffer. */ - struct buffer *oldbuf = current_buffer; - set_buffer_internal (XBUFFER (Vprin1_to_string_buffer)); - /* This is for an unusual case where some after-change - function uses 'format' or 'prin1' or something else that - will thrash Vprin1_to_string_buffer we are using. */ - specbind (Qinhibit_modification_hooks, Qt); - - if (NILP (tem)) - { - name = Fsymbol_name (name); - AUTO_STRING (msg_prefix, "\nUses keymap `"); - insert1 (Fsubstitute_command_keys (msg_prefix)); - insert_from_string (name, 0, 0, - SCHARS (name), - SBYTES (name), 1); - AUTO_STRING (msg_suffix, "', which is not currently defined.\n"); - insert1 (Fsubstitute_command_keys (msg_suffix)); - if (!generate_summary) - keymap = Qnil; - } - else if (!generate_summary) - keymap = tem; - else - { - /* Get the list of active keymaps that precede this one. - If this one's not active, get nil. */ - Lisp_Object earlier_maps - = Fcdr (Fmemq (tem, Freverse (active_maps))); - describe_map_tree (tem, 1, Fnreverse (earlier_maps), - Qnil, 0, 1, 0, 0, 1); - } - tem = Fbuffer_string (); - Ferase_buffer (); - set_buffer_internal (oldbuf); - unbind_to (count, Qnil); - } - - subst_string: - /* Convert non-ASCII unibyte data to properly-encoded multibyte, - for the same reason STRING was converted to STR. */ - tem = Fstring_make_multibyte (tem); - start = SDATA (tem); - length = SCHARS (tem); - length_byte = SBYTES (tem); - subst: - nonquotes_changed = true; - subst_quote: - changed = true; - { - ptrdiff_t offset = bufp - buf; - ptrdiff_t avail = bsize - offset; - ptrdiff_t need = strbytes - idx; - if (INT_ADD_WRAPV (need, length_byte + EXTRA_ROOM, &need)) - string_overflow (); - if (avail < need) - { - abuf = xpalloc (abuf, &bsize, need - avail, - STRING_BYTES_BOUND, 1); - if (buf == sbuf) - { - record_unwind_protect_ptr (xfree, abuf); - memcpy (abuf, sbuf, offset); - } - else - set_unwind_protect_ptr (count, xfree, abuf); - buf = abuf; - bufp = buf + offset; - } - memcpy (bufp, start, length_byte); - bufp += length_byte; - nchars += length; - - /* Some of the previous code can GC, so take relocation of - string contents into account. */ - strp = SDATA (str) + idx; - - continue; - } - } - else if ((strp[0] == '`' || strp[0] == '\'') - && quoting_style == CURVE_QUOTING_STYLE) - { - start = (unsigned char const *) (strp[0] == '`' ? uLSQM : uRSQM); - length = 1; - length_byte = sizeof uLSQM - 1; - idx = strp - SDATA (str) + 1; - goto subst_quote; - } - else if (strp[0] == '`' && quoting_style == STRAIGHT_QUOTING_STYLE) - { - *bufp++ = '\''; - strp++; - nchars++; - changed = true; - continue; - } - - /* Copy one char. */ - do - *bufp++ = *strp++; - while (! CHAR_HEAD_P (*strp)); - nchars++; - } + /* Use apostrophes 'like this'. */ + else if (EQ (Vtext_quoting_style, Qstraight)) + return Qstraight; - if (changed) /* don't bother if nothing substituted */ - { - tem = make_string_from_bytes (buf, nchars, bufp - buf); - if (!nonquotes_changed) - { - /* Nothing has changed other than quoting, so copy the string’s - text properties. FIXME: Text properties should survive other - changes too. */ - INTERVAL interval_copy = copy_intervals (string_intervals (string), - 0, SCHARS (string)); - if (interval_copy) - { - set_interval_object (interval_copy, tem); - set_string_intervals (tem, interval_copy); - } - } - } + /* Use curved single quotes ‘like this’. */ else - tem = string; - return unbind_to (count, tem); + return Qcurve; } + void syms_of_doc (void) { + DEFSYM (Qlisp_directory, "lisp-directory"); + DEFSYM (Qsubstitute_command_keys, "substitute-command-keys"); DEFSYM (Qfunction_documentation, "function-documentation"); DEFSYM (Qgrave, "grave"); DEFSYM (Qstraight, "straight"); + DEFSYM (Qcurve, "curve"); DEFVAR_LISP ("internal-doc-file-name", Vdoc_file_name, doc: /* Name of file containing documentation strings of built-in symbols. */); @@ -1019,17 +689,23 @@ syms_of_doc (void) DEFVAR_LISP ("text-quoting-style", Vtext_quoting_style, doc: /* Style to use for single quotes in help and messages. -Its value should be a symbol. It works by substituting certain single -quotes for grave accent and apostrophe. This is done in help output -and in functions like `message' and `format-message'. It is not done + +The value of this variable determines substitution of grave accents +and apostrophes in help output (but not for display of Info +manuals) and in functions like `message' and `format-message', but not in `format'. -`curve' means quote with curved single quotes ‘like this’. -`straight' means quote with straight apostrophes \\='like this\\='. -`grave' means quote with grave accent and apostrophe \\=`like this\\='; -i.e., do not alter quote marks. The default value nil acts like -`curve' if curved single quotes are displayable, and like `grave' -otherwise. */); +The value should be one of these symbols: + `curve': quote with curved single quotes ‘like this’. + `straight': quote with straight apostrophes \\='like this\\='. + `grave': quote with grave accent and apostrophe \\=`like this\\='; + i.e., do not alter the original quote marks. + nil: like `curve' if curved single quotes are displayable, + and like `grave' otherwise. This is the default. + +You should never read the value of this variable directly from a Lisp +program. Use the function `text-quoting-style' instead, as that will +compute the correct value for the current terminal in the nil case. */); Vtext_quoting_style = Qnil; DEFVAR_BOOL ("internal--text-quoting-flag", text_quoting_flag, @@ -1039,5 +715,5 @@ otherwise. */); defsubr (&Sdocumentation); defsubr (&Sdocumentation_property); defsubr (&Ssnarf_documentation); - defsubr (&Ssubstitute_command_keys); + defsubr (&Stext_quoting_style); } |