summaryrefslogtreecommitdiff
path: root/src/doc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc.c')
-rw-r--r--src/doc.c169
1 files changed, 108 insertions, 61 deletions
diff --git a/src/doc.c b/src/doc.c
index 6dae67b0c25..b5a9ed498af 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -37,6 +37,39 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "intervals.h"
#include "keymap.h"
+
+
+#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY \
+ || (__ANDROID_API__ < 9)
+#define doc_fd int
+#define doc_fd_p(fd) ((fd) >= 0)
+#define doc_open emacs_open
+#define doc_read_quit emacs_read_quit
+#define doc_lseek lseek
+#else /* HAVE_ANDROID && !defined ANDROID_STUBIFY
+ && __ANDROID_API__ >= 9 */
+
+#include "android.h"
+
+/* Use an Android file descriptor under Android instead, as this
+ allows loading directly from asset files without loading each asset
+ into memory and creating a separate file descriptor every time.
+
+ However, lread requires the ability to seek inside asset files,
+ which is not provided under Android 2.2. So when building for that
+ particular system, fall back to the usual file descriptor-based
+ code. */
+
+#define doc_fd struct android_fd_or_asset
+#define doc_fd_p(fd) ((fd).asset != (void *) -1)
+#define doc_open android_open_asset
+#define doc_read_quit android_asset_read_quit
+#define doc_lseek android_asset_lseek
+#define USE_ANDROID_ASSETS
+#endif /* !HAVE_ANDROID || ANDROID_STUBIFY || __ANDROID_API__ < 9 */
+
+
+
/* Buffer used for reading from documentation file. */
static char *get_doc_string_buffer;
static ptrdiff_t get_doc_string_buffer_size;
@@ -59,6 +92,22 @@ read_bytecode_char (bool unreadflag)
return *read_bytecode_pointer++;
}
+#ifdef USE_ANDROID_ASSETS
+
+/* Like `close_file_unwind'. However, PTR is a pointer to an Android
+ file descriptor instead of a system file descriptor. */
+
+static void
+close_file_unwind_android_fd (void *ptr)
+{
+ struct android_fd_or_asset *fd;
+
+ fd = ptr;
+ android_close_asset (*fd);
+}
+
+#endif /* USE_ANDROID_ASSETS */
+
/* Extract a doc string from a file. FILEPOS says where to get it.
If it is an integer, use that position in the standard DOC file.
If it is (FILE . INTEGER), use FILE as the file name
@@ -123,8 +172,8 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
name = SAFE_ALLOCA (docdir_sizemax + SBYTES (file));
lispstpcpy (lispstpcpy (name, docdir), file);
- int fd = emacs_open (name, O_RDONLY, 0);
- if (fd < 0)
+ doc_fd fd = doc_open (name, O_RDONLY, 0);
+ if (!doc_fd_p (fd))
{
if (will_dump_p ())
{
@@ -132,9 +181,9 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
So check in ../etc. */
lispstpcpy (stpcpy (name, sibling_etc), file);
- fd = emacs_open (name, O_RDONLY, 0);
+ fd = doc_open (name, O_RDONLY, 0);
}
- if (fd < 0)
+ if (!doc_fd_p (fd))
{
if (errno != ENOENT && errno != ENOTDIR)
report_file_error ("Read error on documentation file", file);
@@ -145,14 +194,18 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
return concat3 (cannot_open, file, quote_nl);
}
}
+#ifndef USE_ANDROID_ASSETS
record_unwind_protect_int (close_file_unwind, fd);
+#else /* USE_ANDROID_ASSETS */
+ record_unwind_protect_ptr (close_file_unwind_android_fd, &fd);
+#endif /* !USE_ANDROID_ASSETS */
/* 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. */
int offset = min (position, max (1024, position % (8 * 1024)));
if (TYPE_MAXIMUM (off_t) < position
- || lseek (fd, position - offset, 0) < 0)
+ || doc_lseek (fd, position - offset, 0) < 0)
error ("Position %"pI"d out of range in doc string file \"%s\"",
position, name);
@@ -181,7 +234,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;
- int nread = emacs_read_quit (fd, p, space_left);
+ int nread = doc_read_quit (fd, p, space_left);
if (nread < 0)
report_file_error ("Read error on documentation file", file);
p[nread] = 0;
@@ -304,6 +357,20 @@ reread_doc_file (Lisp_Object file)
return 1;
}
+DEFUN ("documentation-stringp", Fdocumentation_stringp, Sdocumentation_stringp,
+ 1, 1, 0,
+ doc: /* Return non-nil if OBJECT is a well-formed docstring object.
+OBJECT can be either a string or a reference if it's kept externally. */)
+ (Lisp_Object object)
+{
+ return (STRINGP (object)
+ || FIXNUMP (object) /* Reference to DOC. */
+ || (CONSP (object) /* Reference to .elc. */
+ && STRINGP (XCAR (object))
+ && FIXNUMP (XCDR (object)))
+ ? Qt : Qnil);
+}
+
DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
doc: /* Return the documentation string of FUNCTION.
Unless a non-nil second argument RAW is given, the
@@ -330,19 +397,7 @@ string is passed through `substitute-command-keys'. */)
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_fixnum (XSUBR (fun)->doc);
-#ifdef HAVE_MODULES
- else if (MODULE_FUNCTIONP (fun))
- doc = module_function_documentation (XMODULE_FUNCTION (fun));
-#endif
- else
- doc = call1 (Qfunction_documentation, 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). */
@@ -371,6 +426,25 @@ string is passed through `substitute-command-keys'. */)
return doc;
}
+DEFUN ("internal-subr-documentation", Fsubr_documentation, Ssubr_documentation, 1, 1, 0,
+ doc: /* Return the raw documentation info of a C primitive. */)
+ (Lisp_Object function)
+{
+#ifdef HAVE_NATIVE_COMP
+ if (!NILP (Fsubr_native_elisp_p (function)))
+ return native_function_doc (function);
+ else
+#endif
+ if (SUBRP (function))
+ return make_fixnum (XSUBR (function)->doc);
+#ifdef HAVE_MODULES
+ else if (MODULE_FUNCTIONP (function))
+ return module_function_documentation (XMODULE_FUNCTION (function));
+#endif
+ else
+ return Qt;
+}
+
DEFUN ("documentation-property", Fdocumentation_property,
Sdocumentation_property, 2, 3, 0,
doc: /* Return the documentation string that is SYMBOL's PROP property.
@@ -442,46 +516,13 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset)
/* If it's a lisp form, stick it in the form. */
if (CONSP (fun) && EQ (XCAR (fun), Qmacro))
fun = XCDR (fun);
- if (CONSP (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) && FIXNUMP (XCAR (tem)))
- /* FIXME: This modifies typically pure hash-cons'd data, so its
- correctness is quite delicate. */
- XSETCAR (tem, make_fixnum (offset));
- }
- }
/* Lisp_Subrs have a slot for it. */
- else if (SUBRP (fun) && !SUBR_NATIVE_COMPILEDP (fun))
- {
- XSUBR (fun)->doc = offset;
- }
-
- /* Bytecode objects sometimes have slots for it. */
- else if (COMPILEDP (fun))
+ if (SUBRP (fun) && !SUBR_NATIVE_COMPILEDP (fun))
+ XSUBR (fun)->doc = offset;
+ else
{
- /* This bytecode object must have a slot for the
- docstring, since we've found a docstring for it. */
- 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,
- (PVSIZE (fun) > COMPILED_DOC_STRING
- ? "Docstring slot busy for %s"
- : "No docstring slot for %s"));
- CALLN (Fmessage, format,
- (SYMBOLP (obj)
- ? SYMBOL_NAME (obj)
- : build_string ("<anonymous>")));
- }
+ AUTO_STRING (format, "Ignoring DOC string on non-subr: %S");
+ CALLN (Fmessage, format, obj);
}
}
@@ -497,7 +538,7 @@ That file is found in `../etc' now; later, when the dumped Emacs is run,
the same file name is found in the `doc-directory'. */)
(Lisp_Object filename)
{
- int fd;
+ doc_fd fd;
char buf[1024 + 1];
int filled;
EMACS_INT pos;
@@ -544,21 +585,25 @@ the same file name is found in the `doc-directory'. */)
Vbuild_files = Fpurecopy (Vbuild_files);
}
- fd = emacs_open (name, O_RDONLY, 0);
- if (fd < 0)
+ fd = doc_open (name, O_RDONLY, 0);
+ if (!doc_fd_p (fd))
{
int open_errno = errno;
report_file_errno ("Opening doc string file", build_string (name),
open_errno);
}
+#ifndef USE_ANDROID_ASSETS
record_unwind_protect_int (close_file_unwind, fd);
+#else /* USE_ANDROID_ASSETS */
+ record_unwind_protect_ptr (close_file_unwind_android_fd, &fd);
+#endif /* !USE_ANDROID_ASSETS */
Vdoc_file_name = filename;
filled = 0;
pos = 0;
while (true)
{
if (filled < 512)
- filled += emacs_read_quit (fd, &buf[filled], sizeof buf - 1 - filled);
+ filled += doc_read_quit (fd, &buf[filled], sizeof buf - 1 - filled);
if (!filled)
break;
@@ -712,7 +757,9 @@ compute the correct value for the current terminal in the nil case. */);
doc: /* If nil, a nil `text-quoting-style' is treated as `grave'. */);
/* Initialized by ‘main’. */
+ defsubr (&Sdocumentation_stringp);
defsubr (&Sdocumentation);
+ defsubr (&Ssubr_documentation);
defsubr (&Sdocumentation_property);
defsubr (&Ssnarf_documentation);
defsubr (&Stext_quoting_style);