root/src/doc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. read_bytecode_char
  2. close_file_unwind_android_fd
  3. get_doc_string
  4. read_doc_string
  5. reread_doc_file
  6. DEFUN
  7. store_function_docstring
  8. DEFUN
  9. default_to_grave_quoting_style
  10. DEFUN
  11. syms_of_doc

     1 /* Record indices of function doc strings stored in a file. -*- coding: utf-8 -*-
     2 
     3 Copyright (C) 1985-1986, 1993-1995, 1997-2023 Free Software Foundation,
     4 Inc.
     5 
     6 This file is part of GNU Emacs.
     7 
     8 GNU Emacs is free software: you can redistribute it and/or modify
     9 it under the terms of the GNU General Public License as published by
    10 the Free Software Foundation, either version 3 of the License, or (at
    11 your option) any later version.
    12 
    13 GNU Emacs is distributed in the hope that it will be useful,
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16 GNU General Public License for more details.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    20 
    21 
    22 #include <config.h>
    23 
    24 #include <errno.h>
    25 #include <sys/types.h>
    26 #include <sys/file.h>   /* Must be after sys/types.h for USG.  */
    27 #include <fcntl.h>
    28 #include <unistd.h>
    29 
    30 #include <c-ctype.h>
    31 
    32 #include "lisp.h"
    33 #include "character.h"
    34 #include "coding.h"
    35 #include "buffer.h"
    36 #include "disptab.h"
    37 #include "intervals.h"
    38 #include "keymap.h"
    39 
    40 
    41 
    42 #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY    \
    43   || (__ANDROID_API__ < 9)
    44 #define doc_fd          int
    45 #define doc_fd_p(fd)    ((fd) >= 0)
    46 #define doc_open        emacs_open
    47 #define doc_read_quit   emacs_read_quit
    48 #define doc_lseek       lseek
    49 #else /* HAVE_ANDROID && !defined ANDROID_STUBIFY
    50          && __ANDROID_API__ >= 9 */
    51 
    52 #include "android.h"
    53 
    54 /* Use an Android file descriptor under Android instead, as this
    55    allows loading directly from asset files without loading each asset
    56    into memory and creating a separate file descriptor every time.
    57 
    58    However, lread requires the ability to seek inside asset files,
    59    which is not provided under Android 2.2.  So when building for that
    60    particular system, fall back to the usual file descriptor-based
    61    code.  */
    62 
    63 #define doc_fd          struct android_fd_or_asset
    64 #define doc_fd_p(fd)    ((fd).asset != (void *) -1)
    65 #define doc_open        android_open_asset
    66 #define doc_read_quit   android_asset_read_quit
    67 #define doc_lseek       android_asset_lseek
    68 #define USE_ANDROID_ASSETS
    69 #endif /* !HAVE_ANDROID || ANDROID_STUBIFY || __ANDROID_API__ < 9 */
    70 
    71 
    72 
    73 /* Buffer used for reading from documentation file.  */
    74 static char *get_doc_string_buffer;
    75 static ptrdiff_t get_doc_string_buffer_size;
    76 
    77 static unsigned char *read_bytecode_pointer;
    78 
    79 static char const sibling_etc[] = "../etc/";
    80 
    81 /* `readchar' in lread.c calls back here to fetch the next byte.
    82    If UNREADFLAG is 1, we unread a byte.  */
    83 
    84 int
    85 read_bytecode_char (bool unreadflag)
    86 {
    87   if (unreadflag)
    88     {
    89       read_bytecode_pointer--;
    90       return 0;
    91     }
    92   return *read_bytecode_pointer++;
    93 }
    94 
    95 #ifdef USE_ANDROID_ASSETS
    96 
    97 /* Like `close_file_unwind'.  However, PTR is a pointer to an Android
    98    file descriptor instead of a system file descriptor.  */
    99 
   100 static void
   101 close_file_unwind_android_fd (void *ptr)
   102 {
   103   struct android_fd_or_asset *fd;
   104 
   105   fd = ptr;
   106   android_close_asset (*fd);
   107 }
   108 
   109 #endif /* USE_ANDROID_ASSETS */
   110 
   111 /* Extract a doc string from a file.  FILEPOS says where to get it.
   112    If it is an integer, use that position in the standard DOC file.
   113    If it is (FILE . INTEGER), use FILE as the file name
   114    and INTEGER as the position in that file.
   115    But if INTEGER is negative, make it positive.
   116    (A negative integer is used for user variables, so we can distinguish
   117    them without actually fetching the doc string.)
   118 
   119    If the location does not point to the beginning of a docstring
   120    (e.g. because the file has been modified and the location is stale),
   121    return nil.
   122 
   123    If UNIBYTE, always make a unibyte string.
   124 
   125    If DEFINITION, assume this is for reading
   126    a dynamic function definition; convert the bytestring
   127    and the constants vector with appropriate byte handling,
   128    and return a cons cell.  */
   129 
   130 Lisp_Object
   131 get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
   132 {
   133   char *from, *to, *name, *p, *p1;
   134   Lisp_Object file, pos;
   135   specpdl_ref count = SPECPDL_INDEX ();
   136   Lisp_Object dir;
   137   USE_SAFE_ALLOCA;
   138 
   139   if (FIXNUMP (filepos))
   140     {
   141       file = Vdoc_file_name;
   142       dir = Vdoc_directory;
   143       pos = filepos;
   144     }
   145   else if (CONSP (filepos))
   146     {
   147       file = XCAR (filepos);
   148       dir = Fsymbol_value (Qlisp_directory);
   149       pos = XCDR (filepos);
   150     }
   151   else
   152     return Qnil;
   153 
   154   EMACS_INT position = eabs (XFIXNUM (pos));
   155 
   156   if (!STRINGP (dir))
   157     return Qnil;
   158 
   159   if (!STRINGP (file))
   160     return Qnil;
   161 
   162   /* Put the file name in NAME as a C string.
   163      If it is relative, combine it with Vdoc_directory.  */
   164 
   165   Lisp_Object tem = Ffile_name_absolute_p (file);
   166   file = ENCODE_FILE (file);
   167   Lisp_Object docdir
   168     = NILP (tem) ? ENCODE_FILE (dir) : empty_unibyte_string;
   169   ptrdiff_t docdir_sizemax = SBYTES (docdir) + 1;
   170   if (will_dump_p ())
   171     docdir_sizemax = max (docdir_sizemax, sizeof sibling_etc);
   172   name = SAFE_ALLOCA (docdir_sizemax + SBYTES (file));
   173   lispstpcpy (lispstpcpy (name, docdir), file);
   174 
   175   doc_fd fd = doc_open (name, O_RDONLY, 0);
   176   if (!doc_fd_p (fd))
   177     {
   178       if (will_dump_p ())
   179         {
   180           /* Preparing to dump; DOC file is probably not installed.
   181              So check in ../etc.  */
   182           lispstpcpy (stpcpy (name, sibling_etc), file);
   183 
   184           fd = doc_open (name, O_RDONLY, 0);
   185         }
   186       if (!doc_fd_p (fd))
   187         {
   188           if (errno != ENOENT && errno != ENOTDIR)
   189             report_file_error ("Read error on documentation file", file);
   190 
   191           SAFE_FREE ();
   192           AUTO_STRING (cannot_open, "Cannot open doc string file \"");
   193           AUTO_STRING (quote_nl, "\"\n");
   194           return concat3 (cannot_open, file, quote_nl);
   195         }
   196     }
   197 #ifndef USE_ANDROID_ASSETS
   198   record_unwind_protect_int (close_file_unwind, fd);
   199 #else /* USE_ANDROID_ASSETS */
   200   record_unwind_protect_ptr (close_file_unwind_android_fd, &fd);
   201 #endif /* !USE_ANDROID_ASSETS */
   202 
   203   /* Seek only to beginning of disk block.  */
   204   /* Make sure we read at least 1024 bytes before `position'
   205      so we can check the leading text for consistency.  */
   206   int offset = min (position, max (1024, position % (8 * 1024)));
   207   if (TYPE_MAXIMUM (off_t) < position
   208       || doc_lseek (fd, position - offset, 0) < 0)
   209     error ("Position %"pI"d out of range in doc string file \"%s\"",
   210            position, name);
   211 
   212   /* Read the doc string into get_doc_string_buffer.
   213      P points beyond the data just read.  */
   214 
   215   p = get_doc_string_buffer;
   216   while (1)
   217     {
   218       ptrdiff_t space_left = (get_doc_string_buffer_size - 1
   219                               - (p - get_doc_string_buffer));
   220 
   221       /* Allocate or grow the buffer if we need to.  */
   222       if (space_left <= 0)
   223         {
   224           ptrdiff_t in_buffer = p - get_doc_string_buffer;
   225           get_doc_string_buffer
   226             = xpalloc (get_doc_string_buffer, &get_doc_string_buffer_size,
   227                        16 * 1024, -1, 1);
   228           p = get_doc_string_buffer + in_buffer;
   229           space_left = (get_doc_string_buffer_size - 1
   230                         - (p - get_doc_string_buffer));
   231         }
   232 
   233       /* Read a disk block at a time.
   234          If we read the same block last time, maybe skip this?  */
   235       if (space_left > 1024 * 8)
   236         space_left = 1024 * 8;
   237       int nread = doc_read_quit (fd, p, space_left);
   238       if (nread < 0)
   239         report_file_error ("Read error on documentation file", file);
   240       p[nread] = 0;
   241       if (!nread)
   242         break;
   243       if (p == get_doc_string_buffer)
   244         p1 = strchr (p + offset, '\037');
   245       else
   246         p1 = strchr (p, '\037');
   247       if (p1)
   248         {
   249           *p1 = 0;
   250           p = p1;
   251           break;
   252         }
   253       p += nread;
   254     }
   255   SAFE_FREE_UNBIND_TO (count, Qnil);
   256 
   257   /* Sanity checking.  */
   258   if (CONSP (filepos))
   259     {
   260       int test = 1;
   261       /* A dynamic docstring should be either at the very beginning of a "#@
   262          comment" or right after a dynamic docstring delimiter (in case we
   263          pack several such docstrings within the same comment).  */
   264       if (get_doc_string_buffer[offset - test] != '\037')
   265         {
   266           if (get_doc_string_buffer[offset - test++] != ' ')
   267             return Qnil;
   268           while (get_doc_string_buffer[offset - test] >= '0'
   269                  && get_doc_string_buffer[offset - test] <= '9')
   270             test++;
   271           if (get_doc_string_buffer[offset - test++] != '@'
   272               || get_doc_string_buffer[offset - test] != '#')
   273             return Qnil;
   274         }
   275     }
   276   else
   277     {
   278       int test = 1;
   279       if (get_doc_string_buffer[offset - test++] != '\n')
   280         return Qnil;
   281       while (get_doc_string_buffer[offset - test] > ' ')
   282         test++;
   283       if (get_doc_string_buffer[offset - test] != '\037')
   284         return Qnil;
   285     }
   286 
   287   /* Scan the text and perform quoting with ^A (char code 1).
   288      ^A^A becomes ^A, ^A0 becomes a null char, and ^A_ becomes a ^_.  */
   289   from = get_doc_string_buffer + offset;
   290   to = get_doc_string_buffer + offset;
   291   while (from != p)
   292     {
   293       if (*from == 1)
   294         {
   295           from++;
   296           int c = *from++;
   297           if (c == 1)
   298             *to++ = c;
   299           else if (c == '0')
   300             *to++ = 0;
   301           else if (c == '_')
   302             *to++ = 037;
   303           else
   304             {
   305               unsigned char uc = c;
   306               error ("\
   307 Invalid data in documentation file -- %c followed by code %03o",
   308                      1, uc);
   309             }
   310         }
   311       else
   312         *to++ = *from++;
   313     }
   314 
   315   /* If DEFINITION, read from this buffer
   316      the same way we would read bytes from a file.  */
   317   if (definition)
   318     {
   319       read_bytecode_pointer = (unsigned char *) get_doc_string_buffer + offset;
   320       return Fread (Qlambda);
   321     }
   322 
   323   if (unibyte)
   324     return make_unibyte_string (get_doc_string_buffer + offset,
   325                                 to - (get_doc_string_buffer + offset));
   326   else
   327     {
   328       /* The data determines whether the string is multibyte.  */
   329       ptrdiff_t nchars
   330         = multibyte_chars_in_text (((unsigned char *) get_doc_string_buffer
   331                                     + offset),
   332                                    to - (get_doc_string_buffer + offset));
   333       return make_string_from_bytes (get_doc_string_buffer + offset,
   334                                      nchars,
   335                                      to - (get_doc_string_buffer + offset));
   336     }
   337 }
   338 
   339 /* Get a string from position FILEPOS and pass it through the Lisp reader.
   340    We use this for fetching the bytecode string and constants vector
   341    of a compiled function from the .elc file.  */
   342 
   343 Lisp_Object
   344 read_doc_string (Lisp_Object filepos)
   345 {
   346   return get_doc_string (filepos, 0, 1);
   347 }
   348 
   349 static bool
   350 reread_doc_file (Lisp_Object file)
   351 {
   352   if (NILP (file))
   353     Fsnarf_documentation (Vdoc_file_name);
   354   else
   355     save_match_data_load (file, Qt, Qt, Qt, Qnil);
   356 
   357   return 1;
   358 }
   359 
   360 DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
   361        doc: /* Return the documentation string of FUNCTION.
   362 Unless a non-nil second argument RAW is given, the
   363 string is passed through `substitute-command-keys'.  */)
   364   (Lisp_Object function, Lisp_Object raw)
   365 {
   366   Lisp_Object doc;
   367   bool try_reload = true;
   368 
   369  documentation:
   370 
   371   doc = Qnil;
   372 
   373   if (SYMBOLP (function))
   374     {
   375       Lisp_Object tem = Fget (function, Qfunction_documentation);
   376       if (!NILP (tem))
   377         return Fdocumentation_property (function, Qfunction_documentation,
   378                                         raw);
   379     }
   380 
   381   Lisp_Object fun = Findirect_function (function, Qnil);
   382   if (NILP (fun))
   383     xsignal1 (Qvoid_function, function);
   384   if (CONSP (fun) && EQ (XCAR (fun), Qmacro))
   385     fun = XCDR (fun);
   386   doc = call1 (Qfunction_documentation, fun);
   387 
   388   /* If DOC is 0, it's typically because of a dumped file missing
   389      from the DOC file (bug in src/Makefile.in).  */
   390   if (BASE_EQ (doc, make_fixnum (0)))
   391     doc = Qnil;
   392   if (FIXNUMP (doc) || CONSP (doc))
   393     {
   394       Lisp_Object tem;
   395       tem = get_doc_string (doc, 0, 0);
   396       if (NILP (tem) && try_reload)
   397         {
   398           /* The file is newer, we need to reset the pointers.  */
   399           try_reload = reread_doc_file (Fcar_safe (doc));
   400           if (try_reload)
   401             {
   402               try_reload = false;
   403               goto documentation;
   404             }
   405         }
   406       else
   407         doc = tem;
   408     }
   409 
   410   if (NILP (raw))
   411     doc = call1 (Qsubstitute_command_keys, doc);
   412   return doc;
   413 }
   414 
   415 DEFUN ("internal-subr-documentation", Fsubr_documentation, Ssubr_documentation, 1, 1, 0,
   416        doc: /* Return the raw documentation info of a C primitive.  */)
   417   (Lisp_Object function)
   418 {
   419 #ifdef HAVE_NATIVE_COMP
   420   if (!NILP (Fsubr_native_elisp_p (function)))
   421     return native_function_doc (function);
   422   else
   423 #endif
   424   if (SUBRP (function))
   425     return make_fixnum (XSUBR (function)->doc);
   426 #ifdef HAVE_MODULES
   427   else if (MODULE_FUNCTIONP (function))
   428     return module_function_documentation (XMODULE_FUNCTION (function));
   429 #endif
   430   else
   431     return Qt;
   432 }
   433 
   434 DEFUN ("documentation-property", Fdocumentation_property,
   435        Sdocumentation_property, 2, 3, 0,
   436        doc: /* Return the documentation string that is SYMBOL's PROP property.
   437 Third argument RAW omitted or nil means pass the result through
   438 `substitute-command-keys' if it is a string.
   439 
   440 This differs from `get' in that it can refer to strings stored in the
   441 `etc/DOC' file; and that it evaluates documentation properties that
   442 aren't strings.  */)
   443   (Lisp_Object symbol, Lisp_Object prop, Lisp_Object raw)
   444 {
   445   bool try_reload = true;
   446   Lisp_Object tem;
   447 
   448  documentation_property:
   449 
   450   tem = Fget (symbol, prop);
   451 
   452   /* If we don't have any documentation for this symbol (and we're asking for
   453      the variable documentation), try to see whether it's an indirect variable
   454      and get the documentation from there instead. */
   455   if (EQ (prop, Qvariable_documentation)
   456       && NILP (tem))
   457     {
   458       Lisp_Object indirect = Findirect_variable (symbol);
   459       if (!NILP (indirect))
   460         tem = Fget (indirect, prop);
   461     }
   462 
   463   if (BASE_EQ (tem, make_fixnum (0)))
   464     tem = Qnil;
   465 
   466   /* See if we want to look for the string in the DOC file. */
   467   if (FIXNUMP (tem) || (CONSP (tem) && FIXNUMP (XCDR (tem))))
   468     {
   469       Lisp_Object doc = tem;
   470       tem = get_doc_string (tem, 0, 0);
   471       if (NILP (tem) && try_reload)
   472         {
   473           /* The file is newer, we need to reset the pointers.  */
   474           try_reload = reread_doc_file (Fcar_safe (doc));
   475           if (try_reload)
   476             {
   477               try_reload = false;
   478               goto documentation_property;
   479             }
   480         }
   481     }
   482   else if (!STRINGP (tem))
   483     /* Feval protects its argument.  */
   484     tem = Feval (tem, Qnil);
   485 
   486   if (NILP (raw) && STRINGP (tem))
   487     tem = call1 (Qsubstitute_command_keys, tem);
   488   return tem;
   489 }
   490 
   491 /* Scanning the DOC files and placing docstring offsets into functions.  */
   492 
   493 static void
   494 store_function_docstring (Lisp_Object obj, EMACS_INT offset)
   495 {
   496   /* Don't use indirect_function here, or defaliases will apply their
   497      docstrings to the base functions (Bug#2603).  */
   498   Lisp_Object fun = SYMBOLP (obj) ? XSYMBOL (obj)->u.s.function : obj;
   499 
   500   /* The type determines where the docstring is stored.  */
   501 
   502   /* If it's a lisp form, stick it in the form.  */
   503   if (CONSP (fun) && EQ (XCAR (fun), Qmacro))
   504     fun = XCDR (fun);
   505   if (CONSP (fun))
   506     {
   507       Lisp_Object tem = XCAR (fun);
   508       if (EQ (tem, Qlambda) || EQ (tem, Qautoload)
   509           || (EQ (tem, Qclosure) && (fun = XCDR (fun), 1)))
   510         {
   511           tem = Fcdr (Fcdr (fun));
   512           if (CONSP (tem) && FIXNUMP (XCAR (tem)))
   513             /* FIXME: This modifies typically pure hash-cons'd data, so its
   514                correctness is quite delicate.  */
   515             XSETCAR (tem, make_fixnum (offset));
   516         }
   517     }
   518   /* Lisp_Subrs have a slot for it.  */
   519   else if (SUBRP (fun) && !SUBR_NATIVE_COMPILEDP (fun))
   520     {
   521       XSUBR (fun)->doc = offset;
   522     }
   523 
   524   /* Bytecode objects sometimes have slots for it.  */
   525   else if (COMPILEDP (fun))
   526     {
   527       /* This bytecode object must have a slot for the
   528          docstring, since we've found a docstring for it.  */
   529       if (PVSIZE (fun) > COMPILED_DOC_STRING
   530           /* Don't overwrite a non-docstring value placed there,
   531            * such as the symbols used for Oclosures.  */
   532           && VALID_DOCSTRING_P (AREF (fun, COMPILED_DOC_STRING)))
   533         ASET (fun, COMPILED_DOC_STRING, make_fixnum (offset));
   534       else
   535         {
   536           AUTO_STRING (format,
   537                        (PVSIZE (fun) > COMPILED_DOC_STRING
   538                         ? "Docstring slot busy for %s"
   539                         : "No docstring slot for %s"));
   540           CALLN (Fmessage, format,
   541                  (SYMBOLP (obj)
   542                   ? SYMBOL_NAME (obj)
   543                   : build_string ("<anonymous>")));
   544         }
   545     }
   546 }
   547 
   548 
   549 DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation,
   550        1, 1, 0,
   551        doc: /* Used during Emacs initialization to scan the `etc/DOC...' file.
   552 This searches the `etc/DOC...' file for doc strings and
   553 records them in function and variable definitions.
   554 The function takes one argument, FILENAME, a string;
   555 it specifies the file name (without a directory) of the DOC file.
   556 That file is found in `../etc' now; later, when the dumped Emacs is run,
   557 the same file name is found in the `doc-directory'.  */)
   558   (Lisp_Object filename)
   559 {
   560   doc_fd fd;
   561   char buf[1024 + 1];
   562   int filled;
   563   EMACS_INT pos;
   564   Lisp_Object sym;
   565   char *p, *name;
   566   char const *dirname;
   567   ptrdiff_t dirlen;
   568   /* Preloaded defcustoms using custom-initialize-delay are added to
   569      this list, but kept unbound.  See https://debbugs.gnu.org/11565  */
   570   Lisp_Object delayed_init =
   571     find_symbol_value (intern ("custom-delayed-init-variables"));
   572 
   573   if (!CONSP (delayed_init)) delayed_init = Qnil;
   574 
   575   CHECK_STRING (filename);
   576 
   577   if (will_dump_p ())
   578     {
   579       dirname = sibling_etc;
   580       dirlen = sizeof sibling_etc - 1;
   581     }
   582   else
   583     {
   584       CHECK_STRING (Vdoc_directory);
   585       dirname = SSDATA (Vdoc_directory);
   586       dirlen = SBYTES (Vdoc_directory);
   587     }
   588 
   589   specpdl_ref count = SPECPDL_INDEX ();
   590   USE_SAFE_ALLOCA;
   591   name = SAFE_ALLOCA (dirlen + SBYTES (filename) + 1);
   592   lispstpcpy (stpcpy (name, dirname), filename);        /*** Add this line ***/
   593 
   594   /* Vbuild_files is nil when temacs is run, and non-nil after that.  */
   595   if (NILP (Vbuild_files))
   596     {
   597       static char const *const buildobj[] =
   598         {
   599           #include "buildobj.h"
   600         };
   601       int i = ARRAYELTS (buildobj);
   602       while (0 <= --i)
   603         Vbuild_files = Fcons (build_string (buildobj[i]), Vbuild_files);
   604       Vbuild_files = Fpurecopy (Vbuild_files);
   605     }
   606 
   607   fd = doc_open (name, O_RDONLY, 0);
   608   if (!doc_fd_p (fd))
   609     {
   610       int open_errno = errno;
   611       report_file_errno ("Opening doc string file", build_string (name),
   612                          open_errno);
   613     }
   614 #ifndef USE_ANDROID_ASSETS
   615   record_unwind_protect_int (close_file_unwind, fd);
   616 #else /* USE_ANDROID_ASSETS */
   617   record_unwind_protect_ptr (close_file_unwind_android_fd, &fd);
   618 #endif /* !USE_ANDROID_ASSETS */
   619   Vdoc_file_name = filename;
   620   filled = 0;
   621   pos = 0;
   622   while (true)
   623     {
   624       if (filled < 512)
   625         filled += doc_read_quit (fd, &buf[filled], sizeof buf - 1 - filled);
   626       if (!filled)
   627         break;
   628 
   629       buf[filled] = 0;
   630       char *end = buf + (filled < 512 ? filled : filled - 128);
   631       p = memchr (buf, '\037', end - buf);
   632       /* p points to ^_Ffunctionname\n or ^_Vvarname\n or ^_Sfilename\n.  */
   633       if (p)
   634         {
   635           end = strchr (p, '\n');
   636           if (!end)
   637             error ("DOC file invalid at position %"pI"d", pos);
   638 
   639           /* We used to skip files not in build_files, so that when a
   640              function was defined several times in different files
   641              (typically, once in xterm, once in w32term, ...), we only
   642              paid attention to the relevant one.
   643 
   644              But this meant the doc had to be kept and updated in
   645              multiple files.  Nowadays we keep the doc only in eg xterm.
   646              The (f)boundp checks below ensure we don't report
   647              docs for eg w32-specific items on X.
   648           */
   649 
   650           sym = oblookup (Vobarray, p + 2,
   651                           multibyte_chars_in_text ((unsigned char *) p + 2,
   652                                                    end - p - 2),
   653                           end - p - 2);
   654           /* Ignore docs that start with SKIP.  These mark
   655              placeholders where the real doc is elsewhere.  */
   656           if (SYMBOLP (sym))
   657             {
   658               /* Attach a docstring to a variable?  */
   659               if (p[1] == 'V')
   660                 {
   661                   /* Install file-position as variable-documentation property
   662                      and make it negative for a user-variable
   663                      (doc starts with a `*').  */
   664                   if ((!NILP (Fboundp (sym))
   665                       || !NILP (Fmemq (sym, delayed_init)))
   666                       && strncmp (end, "\nSKIP", 5))
   667                     Fput (sym, Qvariable_documentation,
   668                           make_fixnum ((pos + end + 1 - buf)
   669                                        * (end[1] == '*' ? -1 : 1)));
   670                 }
   671 
   672               /* Attach a docstring to a function?  */
   673               else if (p[1] == 'F')
   674                 {
   675                   if (!NILP (Ffboundp (sym)) && strncmp (end, "\nSKIP", 5))
   676                     store_function_docstring (sym, pos + end + 1 - buf);
   677                 }
   678               else if (p[1] == 'S')
   679                 ; /* Just a source file name boundary marker.  Ignore it.  */
   680 
   681               else
   682                 error ("DOC file invalid at position %"pI"d", pos);
   683             }
   684         }
   685       pos += end - buf;
   686       filled -= end - buf;
   687       memmove (buf, end, filled);
   688     }
   689 
   690   return SAFE_FREE_UNBIND_TO (count, Qnil);
   691 }
   692 
   693 /* Return true if text quoting style should default to quote `like this'.  */
   694 static bool
   695 default_to_grave_quoting_style (void)
   696 {
   697   if (!text_quoting_flag)
   698     return true;
   699   if (! DISP_TABLE_P (Vstandard_display_table))
   700     return false;
   701   Lisp_Object dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table),
   702                                      LEFT_SINGLE_QUOTATION_MARK);
   703   return (VECTORP (dv) && ASIZE (dv) == 1
   704           && BASE_EQ (AREF (dv, 0), make_fixnum ('`')));
   705 }
   706 
   707 DEFUN ("text-quoting-style", Ftext_quoting_style,
   708        Stext_quoting_style, 0, 0, 0,
   709        doc: /* Return the current effective text quoting style.
   710 If the variable `text-quoting-style' is `grave', `straight' or
   711 `curve', just return that value.  If it is nil (the default), return
   712 `grave' if curved quotes cannot be displayed (for instance, on a
   713 terminal with no support for these characters), otherwise return
   714 `quote'.  Any other value is treated as `grave'.
   715 
   716 Note that in contrast to the variable `text-quoting-style', this
   717 function will never return nil.  */)
   718   (void)
   719 {
   720   /* Use grave accent and apostrophe `like this'.  */
   721   if (NILP (Vtext_quoting_style)
   722       ? default_to_grave_quoting_style ()
   723       : EQ (Vtext_quoting_style, Qgrave))
   724     return Qgrave;
   725 
   726   /* Use apostrophes 'like this'.  */
   727   else if (EQ (Vtext_quoting_style, Qstraight))
   728     return Qstraight;
   729 
   730   /* Use curved single quotes ‘like this’.  */
   731   else
   732     return Qcurve;
   733 }
   734 
   735 
   736 void
   737 syms_of_doc (void)
   738 {
   739   DEFSYM (Qlisp_directory, "lisp-directory");
   740   DEFSYM (Qsubstitute_command_keys, "substitute-command-keys");
   741   DEFSYM (Qfunction_documentation, "function-documentation");
   742   DEFSYM (Qgrave, "grave");
   743   DEFSYM (Qstraight, "straight");
   744   DEFSYM (Qcurve, "curve");
   745 
   746   DEFVAR_LISP ("internal-doc-file-name", Vdoc_file_name,
   747                doc: /* Name of file containing documentation strings of built-in symbols.  */);
   748   Vdoc_file_name = Qnil;
   749 
   750   DEFVAR_LISP ("build-files", Vbuild_files,
   751                doc: /* A list of files used to build this Emacs binary.  */);
   752   Vbuild_files = Qnil;
   753 
   754   DEFVAR_LISP ("text-quoting-style", Vtext_quoting_style,
   755                doc: /* Style to use for single quotes in help and messages.
   756 
   757 The value of this variable determines substitution of grave accents
   758 and apostrophes in help output (but not for display of Info
   759 manuals) and in functions like `message' and `format-message', but not
   760 in `format'.
   761 
   762 The value should be one of these symbols:
   763   `curve':    quote with curved single quotes ‘like this’.
   764   `straight': quote with straight apostrophes \\='like this\\='.
   765   `grave':    quote with grave accent and apostrophe \\=`like this\\=';
   766               i.e., do not alter the original quote marks.
   767   nil:        like `curve' if curved single quotes are displayable,
   768               and like `grave' otherwise.  This is the default.
   769 
   770 You should never read the value of this variable directly from a Lisp
   771 program.  Use the function `text-quoting-style' instead, as that will
   772 compute the correct value for the current terminal in the nil case.  */);
   773   Vtext_quoting_style = Qnil;
   774 
   775   DEFVAR_BOOL ("internal--text-quoting-flag", text_quoting_flag,
   776                doc: /* If nil, a nil `text-quoting-style' is treated as `grave'.  */);
   777   /* Initialized by ‘main’.  */
   778 
   779   defsubr (&Sdocumentation);
   780   defsubr (&Ssubr_documentation);
   781   defsubr (&Sdocumentation_property);
   782   defsubr (&Ssnarf_documentation);
   783   defsubr (&Stext_quoting_style);
   784 }

/* [<][>][^][v][top][bottom][index][help] */