diff options
| author | Po Lu | 2023-03-07 14:20:50 +0800 |
|---|---|---|
| committer | Po Lu | 2023-03-07 14:20:50 +0800 |
| commit | 44cf1ed7e593022df01a47b701e7796e9d70d2fb (patch) | |
| tree | 09a0e49ee9d7eda6b201bbb07c574d6b4a4c35e0 /src | |
| parent | a11ad7149bc1908d205e78ecfb240b76ce190bef (diff) | |
| download | emacs-44cf1ed7e593022df01a47b701e7796e9d70d2fb.tar.gz emacs-44cf1ed7e593022df01a47b701e7796e9d70d2fb.zip | |
Update Android port
* src/lread.c (lread_fd, file_tell, infile, skip_dyn_bytes)
(skip_dyn_eof, readbyte_from_stdio, safe_to_load_version)
(close_infile_unwind, close_file_unwind_android_fd): New
function.
(Fload, Flocate_file_internal, openp): New argument PLATFORM.
All callers changed.
(skip_lazy_string): Add optimized versions of various functions
for accessing Android assets.
Diffstat (limited to 'src')
| -rw-r--r-- | src/callproc.c | 2 | ||||
| -rw-r--r-- | src/charset.c | 3 | ||||
| -rw-r--r-- | src/emacs.c | 3 | ||||
| -rw-r--r-- | src/image.c | 9 | ||||
| -rw-r--r-- | src/lisp.h | 3 | ||||
| -rw-r--r-- | src/lread.c | 283 | ||||
| -rw-r--r-- | src/process.c | 2 | ||||
| -rw-r--r-- | src/sound.c | 2 | ||||
| -rw-r--r-- | src/w32.c | 3 | ||||
| -rw-r--r-- | src/w32proc.c | 2 |
10 files changed, 268 insertions, 44 deletions
diff --git a/src/callproc.c b/src/callproc.c index ea9c946f158..8d3519fdab2 100644 --- a/src/callproc.c +++ b/src/callproc.c | |||
| @@ -516,7 +516,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, | |||
| 516 | int ok; | 516 | int ok; |
| 517 | 517 | ||
| 518 | ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, | 518 | ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, |
| 519 | make_fixnum (X_OK), false, false); | 519 | make_fixnum (X_OK), false, false, NULL); |
| 520 | if (ok < 0) | 520 | if (ok < 0) |
| 521 | report_file_error ("Searching for program", args[0]); | 521 | report_file_error ("Searching for program", args[0]); |
| 522 | } | 522 | } |
diff --git a/src/charset.c b/src/charset.c index 7987ffa0c5e..8e909c5f03c 100644 --- a/src/charset.c +++ b/src/charset.c | |||
| @@ -486,7 +486,8 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, | |||
| 486 | specpdl_ref count = SPECPDL_INDEX (); | 486 | specpdl_ref count = SPECPDL_INDEX (); |
| 487 | record_unwind_protect_nothing (); | 487 | record_unwind_protect_nothing (); |
| 488 | specbind (Qfile_name_handler_alist, Qnil); | 488 | specbind (Qfile_name_handler_alist, Qnil); |
| 489 | fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil, false, false); | 489 | fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil, false, false, |
| 490 | NULL); | ||
| 490 | fp = fd < 0 ? 0 : fdopen (fd, "r"); | 491 | fp = fd < 0 ? 0 : fdopen (fd, "r"); |
| 491 | if (!fp) | 492 | if (!fp) |
| 492 | { | 493 | { |
diff --git a/src/emacs.c b/src/emacs.c index 2f953510a3d..3df98e6fae2 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -531,7 +531,8 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd) | |||
| 531 | { | 531 | { |
| 532 | Lisp_Object found; | 532 | Lisp_Object found; |
| 533 | int yes = openp (Vexec_path, Vinvocation_name, Vexec_suffixes, | 533 | int yes = openp (Vexec_path, Vinvocation_name, Vexec_suffixes, |
| 534 | &found, make_fixnum (X_OK), false, false); | 534 | &found, make_fixnum (X_OK), false, false, |
| 535 | NULL); | ||
| 535 | if (yes == 1) | 536 | if (yes == 1) |
| 536 | { | 537 | { |
| 537 | /* Add /: to the front of the name | 538 | /* Add /: to the front of the name |
diff --git a/src/image.c b/src/image.c index 2e6aa0ce0e3..a244b23ecd2 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -760,7 +760,7 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 760 | 760 | ||
| 761 | /* Search bitmap-file-path for the file, if appropriate. */ | 761 | /* Search bitmap-file-path for the file, if appropriate. */ |
| 762 | if (openp (Vx_bitmap_file_path, file, Qnil, &found, | 762 | if (openp (Vx_bitmap_file_path, file, Qnil, &found, |
| 763 | make_fixnum (R_OK), false, false) | 763 | make_fixnum (R_OK), false, false, NULL) |
| 764 | < 0) | 764 | < 0) |
| 765 | return -1; | 765 | return -1; |
| 766 | 766 | ||
| @@ -807,7 +807,7 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 807 | 807 | ||
| 808 | /* Search bitmap-file-path for the file, if appropriate. */ | 808 | /* Search bitmap-file-path for the file, if appropriate. */ |
| 809 | if (openp (Vx_bitmap_file_path, file, Qnil, &found, | 809 | if (openp (Vx_bitmap_file_path, file, Qnil, &found, |
| 810 | make_fixnum (R_OK), false, false) | 810 | make_fixnum (R_OK), false, false, NULL) |
| 811 | < 0) | 811 | < 0) |
| 812 | return -1; | 812 | return -1; |
| 813 | 813 | ||
| @@ -896,7 +896,7 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 896 | 896 | ||
| 897 | /* Search bitmap-file-path for the file, if appropriate. */ | 897 | /* Search bitmap-file-path for the file, if appropriate. */ |
| 898 | if (openp (Vx_bitmap_file_path, file, Qnil, &found, | 898 | if (openp (Vx_bitmap_file_path, file, Qnil, &found, |
| 899 | make_fixnum (R_OK), false, false) | 899 | make_fixnum (R_OK), false, false, NULL) |
| 900 | < 0) | 900 | < 0) |
| 901 | return -1; | 901 | return -1; |
| 902 | 902 | ||
| @@ -4148,7 +4148,8 @@ image_find_image_fd (Lisp_Object file, int *pfd) | |||
| 4148 | 4148 | ||
| 4149 | /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ | 4149 | /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ |
| 4150 | fd = openp (search_path, file, Qnil, &file_found, | 4150 | fd = openp (search_path, file, Qnil, &file_found, |
| 4151 | pfd ? Qt : make_fixnum (R_OK), false, false); | 4151 | pfd ? Qt : make_fixnum (R_OK), false, false, |
| 4152 | NULL); | ||
| 4152 | if (fd == -2) | 4153 | if (fd == -2) |
| 4153 | { | 4154 | { |
| 4154 | /* The file exists locally, but has a file name handler. | 4155 | /* The file exists locally, but has a file name handler. |
diff --git a/src/lisp.h b/src/lisp.h index 56ef338a5b1..f7ba6775975 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4514,7 +4514,8 @@ extern bool suffix_p (Lisp_Object, const char *); | |||
| 4514 | extern Lisp_Object save_match_data_load (Lisp_Object, Lisp_Object, Lisp_Object, | 4514 | extern Lisp_Object save_match_data_load (Lisp_Object, Lisp_Object, Lisp_Object, |
| 4515 | Lisp_Object, Lisp_Object); | 4515 | Lisp_Object, Lisp_Object); |
| 4516 | extern int openp (Lisp_Object, Lisp_Object, Lisp_Object, | 4516 | extern int openp (Lisp_Object, Lisp_Object, Lisp_Object, |
| 4517 | Lisp_Object *, Lisp_Object, bool, bool); | 4517 | Lisp_Object *, Lisp_Object, bool, bool, |
| 4518 | void **); | ||
| 4518 | enum { S2N_IGNORE_TRAILING = 1 }; | 4519 | enum { S2N_IGNORE_TRAILING = 1 }; |
| 4519 | extern Lisp_Object string_to_number (char const *, int, ptrdiff_t *); | 4520 | extern Lisp_Object string_to_number (char const *, int, ptrdiff_t *); |
| 4520 | extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), | 4521 | extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), |
diff --git a/src/lread.c b/src/lread.c index 150d8a01e10..48f95ce5f40 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -62,6 +62,24 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 62 | 62 | ||
| 63 | #include <fcntl.h> | 63 | #include <fcntl.h> |
| 64 | 64 | ||
| 65 | #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY \ | ||
| 66 | || (__ANDROID_API__ < 9) | ||
| 67 | |||
| 68 | #define lread_fd int | ||
| 69 | #define lread_fd_cmp(n) (fd == (n)) | ||
| 70 | #define lread_fd_p (fd >= 0) | ||
| 71 | #define lread_close emacs_close | ||
| 72 | #define lread_fstat fstat | ||
| 73 | #define lread_read_quit emacs_read_quit | ||
| 74 | #define lread_lseek lseek | ||
| 75 | |||
| 76 | #define file_stream FILE * | ||
| 77 | #define file_seek fseek | ||
| 78 | #define file_stream_valid_p(p) (p) | ||
| 79 | #define file_stream_close emacs_fclose | ||
| 80 | #define file_stream_invalid NULL | ||
| 81 | #define file_get_char getc | ||
| 82 | |||
| 65 | #ifdef HAVE_FSEEKO | 83 | #ifdef HAVE_FSEEKO |
| 66 | #define file_offset off_t | 84 | #define file_offset off_t |
| 67 | #define file_tell ftello | 85 | #define file_tell ftello |
| @@ -70,6 +88,79 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 70 | #define file_tell ftell | 88 | #define file_tell ftell |
| 71 | #endif | 89 | #endif |
| 72 | 90 | ||
| 91 | #else | ||
| 92 | |||
| 93 | #include "android.h" | ||
| 94 | |||
| 95 | /* Use an Android file descriptor under Android instead, as this | ||
| 96 | allows loading directly from asset files without loading each asset | ||
| 97 | into memory and creating a separate file descriptor every time. | ||
| 98 | |||
| 99 | Note that `struct android_fd_or_asset' as used here is different | ||
| 100 | from that returned from `android_open_asset'; if fd.asset is NULL, | ||
| 101 | then fd.fd is either a valid file descriptor or -1, meaning that | ||
| 102 | the file descriptor is invalid. | ||
| 103 | |||
| 104 | However, lread requires the ability to seek inside asset files, | ||
| 105 | which is not provided under Android 2.2. So when building for that | ||
| 106 | particular system, fall back to the usual file descriptor-based | ||
| 107 | code. */ | ||
| 108 | |||
| 109 | #define lread_fd struct android_fd_or_asset | ||
| 110 | #define lread_fd_cmp(n) (!fd.asset && fd.fd == (n)) | ||
| 111 | #define lread_fd_p (fd.asset || fd.fd >= 0) | ||
| 112 | #define lread_close android_close_asset | ||
| 113 | #define lread_fstat android_asset_fstat | ||
| 114 | #define lread_read_quit android_asset_read_quit | ||
| 115 | #define lread_lseek android_asset_lseek | ||
| 116 | |||
| 117 | /* The invalid file stream. */ | ||
| 118 | |||
| 119 | static struct android_fd_or_asset invalid_file_stream = | ||
| 120 | { | ||
| 121 | -1, | ||
| 122 | NULL, | ||
| 123 | }; | ||
| 124 | |||
| 125 | #define file_stream struct android_fd_or_asset | ||
| 126 | #define file_offset off_t | ||
| 127 | #define file_tell(n) (android_asset_lseek ((n), 0, SEEK_CUR)) | ||
| 128 | #define file_seek android_asset_lseek | ||
| 129 | #define file_stream_valid_p(p) ((p).asset || (p).fd >= 0) | ||
| 130 | #define file_stream_close android_close_asset | ||
| 131 | #define file_stream_invalid invalid_file_stream | ||
| 132 | |||
| 133 | /* Return a single character from the file input stream STREAM. | ||
| 134 | Value and errors are the same as getc. */ | ||
| 135 | |||
| 136 | static int | ||
| 137 | file_get_char (file_stream stream) | ||
| 138 | { | ||
| 139 | int c; | ||
| 140 | char byte; | ||
| 141 | ssize_t rc; | ||
| 142 | |||
| 143 | retry: | ||
| 144 | rc = android_asset_read (stream, &byte, 1); | ||
| 145 | |||
| 146 | if (rc == 0) | ||
| 147 | c = EOF; | ||
| 148 | else if (rc == -1) | ||
| 149 | { | ||
| 150 | if (errno == EINTR) | ||
| 151 | goto retry; | ||
| 152 | else | ||
| 153 | c = EOF; | ||
| 154 | } | ||
| 155 | else | ||
| 156 | c = (unsigned char) byte; | ||
| 157 | |||
| 158 | return c; | ||
| 159 | } | ||
| 160 | |||
| 161 | #define USE_ANDROID_ASSETS | ||
| 162 | #endif | ||
| 163 | |||
| 73 | #if IEEE_FLOATING_POINT | 164 | #if IEEE_FLOATING_POINT |
| 74 | # include <ieee754.h> | 165 | # include <ieee754.h> |
| 75 | # ifndef INFINITY | 166 | # ifndef INFINITY |
| @@ -113,7 +204,7 @@ static Lisp_Object read_objects_completed; | |||
| 113 | static struct infile | 204 | static struct infile |
| 114 | { | 205 | { |
| 115 | /* The input stream. */ | 206 | /* The input stream. */ |
| 116 | FILE *stream; | 207 | file_stream stream; |
| 117 | 208 | ||
| 118 | /* Lookahead byte count. */ | 209 | /* Lookahead byte count. */ |
| 119 | signed char lookahead; | 210 | signed char lookahead; |
| @@ -375,7 +466,7 @@ skip_dyn_bytes (Lisp_Object readcharfun, ptrdiff_t n) | |||
| 375 | if (FROM_FILE_P (readcharfun)) | 466 | if (FROM_FILE_P (readcharfun)) |
| 376 | { | 467 | { |
| 377 | block_input (); /* FIXME: Not sure if it's needed. */ | 468 | block_input (); /* FIXME: Not sure if it's needed. */ |
| 378 | fseek (infile->stream, n - infile->lookahead, SEEK_CUR); | 469 | file_seek (infile->stream, n - infile->lookahead, SEEK_CUR); |
| 379 | unblock_input (); | 470 | unblock_input (); |
| 380 | infile->lookahead = 0; | 471 | infile->lookahead = 0; |
| 381 | } | 472 | } |
| @@ -399,7 +490,7 @@ skip_dyn_eof (Lisp_Object readcharfun) | |||
| 399 | if (FROM_FILE_P (readcharfun)) | 490 | if (FROM_FILE_P (readcharfun)) |
| 400 | { | 491 | { |
| 401 | block_input (); /* FIXME: Not sure if it's needed. */ | 492 | block_input (); /* FIXME: Not sure if it's needed. */ |
| 402 | fseek (infile->stream, 0, SEEK_END); | 493 | file_seek (infile->stream, 0, SEEK_END); |
| 403 | unblock_input (); | 494 | unblock_input (); |
| 404 | infile->lookahead = 0; | 495 | infile->lookahead = 0; |
| 405 | } | 496 | } |
| @@ -480,10 +571,12 @@ readbyte_from_stdio (void) | |||
| 480 | return infile->buf[--infile->lookahead]; | 571 | return infile->buf[--infile->lookahead]; |
| 481 | 572 | ||
| 482 | int c; | 573 | int c; |
| 483 | FILE *instream = infile->stream; | 574 | file_stream instream = infile->stream; |
| 484 | 575 | ||
| 485 | block_input (); | 576 | block_input (); |
| 486 | 577 | ||
| 578 | #if !defined USE_ANDROID_ASSETS | ||
| 579 | |||
| 487 | /* Interrupted reads have been observed while reading over the network. */ | 580 | /* Interrupted reads have been observed while reading over the network. */ |
| 488 | while ((c = getc (instream)) == EOF && errno == EINTR && ferror (instream)) | 581 | while ((c = getc (instream)) == EOF && errno == EINTR && ferror (instream)) |
| 489 | { | 582 | { |
| @@ -493,6 +586,35 @@ readbyte_from_stdio (void) | |||
| 493 | clearerr (instream); | 586 | clearerr (instream); |
| 494 | } | 587 | } |
| 495 | 588 | ||
| 589 | #else | ||
| 590 | |||
| 591 | { | ||
| 592 | char byte; | ||
| 593 | ssize_t rc; | ||
| 594 | |||
| 595 | retry: | ||
| 596 | rc = android_asset_read (instream, &byte, 1); | ||
| 597 | |||
| 598 | if (rc == 0) | ||
| 599 | c = EOF; | ||
| 600 | else if (rc == -1) | ||
| 601 | { | ||
| 602 | if (errno == EINTR) | ||
| 603 | { | ||
| 604 | unblock_input (); | ||
| 605 | maybe_quit (); | ||
| 606 | block_input (); | ||
| 607 | goto retry; | ||
| 608 | } | ||
| 609 | else | ||
| 610 | c = EOF; | ||
| 611 | } | ||
| 612 | else | ||
| 613 | c = (unsigned char) byte; | ||
| 614 | } | ||
| 615 | |||
| 616 | #endif | ||
| 617 | |||
| 496 | unblock_input (); | 618 | unblock_input (); |
| 497 | 619 | ||
| 498 | return (c == EOF ? -1 : c); | 620 | return (c == EOF ? -1 : c); |
| @@ -1062,7 +1184,7 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun) | |||
| 1062 | safe to load. Only files compiled with Emacs can be loaded. */ | 1184 | safe to load. Only files compiled with Emacs can be loaded. */ |
| 1063 | 1185 | ||
| 1064 | static int | 1186 | static int |
| 1065 | safe_to_load_version (Lisp_Object file, int fd) | 1187 | safe_to_load_version (Lisp_Object file, lread_fd fd) |
| 1066 | { | 1188 | { |
| 1067 | struct stat st; | 1189 | struct stat st; |
| 1068 | char buf[512]; | 1190 | char buf[512]; |
| @@ -1071,12 +1193,12 @@ safe_to_load_version (Lisp_Object file, int fd) | |||
| 1071 | 1193 | ||
| 1072 | /* If the file is not regular, then we cannot safely seek it. | 1194 | /* If the file is not regular, then we cannot safely seek it. |
| 1073 | Assume that it is not safe to load as a compiled file. */ | 1195 | Assume that it is not safe to load as a compiled file. */ |
| 1074 | if (sys_fstat (fd, &st) == 0 && !S_ISREG (st.st_mode)) | 1196 | if (lread_fstat (fd, &st) == 0 && !S_ISREG (st.st_mode)) |
| 1075 | return 0; | 1197 | return 0; |
| 1076 | 1198 | ||
| 1077 | /* Read the first few bytes from the file, and look for a line | 1199 | /* Read the first few bytes from the file, and look for a line |
| 1078 | specifying the byte compiler version used. */ | 1200 | specifying the byte compiler version used. */ |
| 1079 | nbytes = emacs_read_quit (fd, buf, sizeof buf); | 1201 | nbytes = lread_read_quit (fd, buf, sizeof buf); |
| 1080 | if (nbytes > 0) | 1202 | if (nbytes > 0) |
| 1081 | { | 1203 | { |
| 1082 | /* Skip to the next newline, skipping over the initial `ELC' | 1204 | /* Skip to the next newline, skipping over the initial `ELC' |
| @@ -1091,7 +1213,7 @@ safe_to_load_version (Lisp_Object file, int fd) | |||
| 1091 | version = 0; | 1213 | version = 0; |
| 1092 | } | 1214 | } |
| 1093 | 1215 | ||
| 1094 | if (lseek (fd, 0, SEEK_SET) < 0) | 1216 | if (lread_lseek (fd, 0, SEEK_SET) < 0) |
| 1095 | report_file_error ("Seeking to start of file", file); | 1217 | report_file_error ("Seeking to start of file", file); |
| 1096 | 1218 | ||
| 1097 | return version; | 1219 | return version; |
| @@ -1165,7 +1287,7 @@ close_infile_unwind (void *arg) | |||
| 1165 | { | 1287 | { |
| 1166 | struct infile *prev_infile = arg; | 1288 | struct infile *prev_infile = arg; |
| 1167 | eassert (infile && infile != prev_infile); | 1289 | eassert (infile && infile != prev_infile); |
| 1168 | emacs_fclose (infile->stream); | 1290 | file_stream_close (infile->stream); |
| 1169 | infile = prev_infile; | 1291 | infile = prev_infile; |
| 1170 | } | 1292 | } |
| 1171 | 1293 | ||
| @@ -1194,6 +1316,22 @@ loadhist_initialize (Lisp_Object filename) | |||
| 1194 | specbind (Qcurrent_load_list, Fcons (filename, Qnil)); | 1316 | specbind (Qcurrent_load_list, Fcons (filename, Qnil)); |
| 1195 | } | 1317 | } |
| 1196 | 1318 | ||
| 1319 | #ifdef USE_ANDROID_ASSETS | ||
| 1320 | |||
| 1321 | /* Like `close_file_unwind'. However, PTR is a pointer to an Android | ||
| 1322 | file descriptor instead of a system file descriptor. */ | ||
| 1323 | |||
| 1324 | static void | ||
| 1325 | close_file_unwind_android_fd (void *ptr) | ||
| 1326 | { | ||
| 1327 | struct android_fd_or_asset *fd; | ||
| 1328 | |||
| 1329 | fd = ptr; | ||
| 1330 | android_close_asset (*fd); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | #endif | ||
| 1334 | |||
| 1197 | DEFUN ("load", Fload, Sload, 1, 5, 0, | 1335 | DEFUN ("load", Fload, Sload, 1, 5, 0, |
| 1198 | doc: /* Execute a file of Lisp code named FILE. | 1336 | doc: /* Execute a file of Lisp code named FILE. |
| 1199 | First try FILE with `.elc' appended, then try with `.el', then try | 1337 | First try FILE with `.elc' appended, then try with `.el', then try |
| @@ -1242,8 +1380,12 @@ Return t if the file exists and loads successfully. */) | |||
| 1242 | (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage, | 1380 | (Lisp_Object file, Lisp_Object noerror, Lisp_Object nomessage, |
| 1243 | Lisp_Object nosuffix, Lisp_Object must_suffix) | 1381 | Lisp_Object nosuffix, Lisp_Object must_suffix) |
| 1244 | { | 1382 | { |
| 1245 | FILE *stream UNINIT; | 1383 | file_stream stream UNINIT; |
| 1246 | int fd; | 1384 | lread_fd fd; |
| 1385 | #ifdef USE_ANDROID_ASSETS | ||
| 1386 | int rc; | ||
| 1387 | void *asset; | ||
| 1388 | #endif | ||
| 1247 | specpdl_ref fd_index UNINIT; | 1389 | specpdl_ref fd_index UNINIT; |
| 1248 | specpdl_ref count = SPECPDL_INDEX (); | 1390 | specpdl_ref count = SPECPDL_INDEX (); |
| 1249 | Lisp_Object found, efound, hist_file_name; | 1391 | Lisp_Object found, efound, hist_file_name; |
| @@ -1284,7 +1426,12 @@ Return t if the file exists and loads successfully. */) | |||
| 1284 | since it would try to load a directory as a Lisp file. */ | 1426 | since it would try to load a directory as a Lisp file. */ |
| 1285 | if (SCHARS (file) == 0) | 1427 | if (SCHARS (file) == 0) |
| 1286 | { | 1428 | { |
| 1429 | #if !defined USE_ANDROID_ASSETS | ||
| 1287 | fd = -1; | 1430 | fd = -1; |
| 1431 | #else | ||
| 1432 | fd.asset = NULL; | ||
| 1433 | fd.fd = -1; | ||
| 1434 | #endif | ||
| 1288 | errno = ENOENT; | 1435 | errno = ENOENT; |
| 1289 | } | 1436 | } |
| 1290 | else | 1437 | else |
| @@ -1323,12 +1470,22 @@ Return t if the file exists and loads successfully. */) | |||
| 1323 | suffixes = CALLN (Fappend, suffixes, Vload_file_rep_suffixes); | 1470 | suffixes = CALLN (Fappend, suffixes, Vload_file_rep_suffixes); |
| 1324 | } | 1471 | } |
| 1325 | 1472 | ||
| 1326 | fd = | 1473 | #if !defined USE_ANDROID_ASSETS |
| 1327 | openp (Vload_path, file, suffixes, &found, Qnil, load_prefer_newer, | 1474 | fd = openp (Vload_path, file, suffixes, &found, Qnil, |
| 1328 | no_native); | 1475 | load_prefer_newer, no_native, NULL); |
| 1476 | #else | ||
| 1477 | asset = NULL; | ||
| 1478 | rc = openp (Vload_path, file, suffixes, &found, Qnil, | ||
| 1479 | load_prefer_newer, no_native, &asset); | ||
| 1480 | fd.fd = rc; | ||
| 1481 | fd.asset = asset; | ||
| 1482 | |||
| 1483 | /* fd.asset will be non-NULL if this is actually an asset | ||
| 1484 | file. */ | ||
| 1485 | #endif | ||
| 1329 | } | 1486 | } |
| 1330 | 1487 | ||
| 1331 | if (fd == -1) | 1488 | if (lread_fd_cmp (-1)) |
| 1332 | { | 1489 | { |
| 1333 | if (NILP (noerror)) | 1490 | if (NILP (noerror)) |
| 1334 | report_file_error ("Cannot open load file", file); | 1491 | report_file_error ("Cannot open load file", file); |
| @@ -1340,7 +1497,7 @@ Return t if the file exists and loads successfully. */) | |||
| 1340 | Vuser_init_file = found; | 1497 | Vuser_init_file = found; |
| 1341 | 1498 | ||
| 1342 | /* If FD is -2, that means openp found a magic file. */ | 1499 | /* If FD is -2, that means openp found a magic file. */ |
| 1343 | if (fd == -2) | 1500 | if (lread_fd_cmp (-2)) |
| 1344 | { | 1501 | { |
| 1345 | if (NILP (Fequal (found, file))) | 1502 | if (NILP (Fequal (found, file))) |
| 1346 | /* If FOUND is a different file name from FILE, | 1503 | /* If FOUND is a different file name from FILE, |
| @@ -1369,11 +1526,21 @@ Return t if the file exists and loads successfully. */) | |||
| 1369 | #endif | 1526 | #endif |
| 1370 | } | 1527 | } |
| 1371 | 1528 | ||
| 1529 | #if !defined USE_ANDROID_ASSETS | ||
| 1372 | if (0 <= fd) | 1530 | if (0 <= fd) |
| 1373 | { | 1531 | { |
| 1374 | fd_index = SPECPDL_INDEX (); | 1532 | fd_index = SPECPDL_INDEX (); |
| 1375 | record_unwind_protect_int (close_file_unwind, fd); | 1533 | record_unwind_protect_int (close_file_unwind, fd); |
| 1376 | } | 1534 | } |
| 1535 | #else | ||
| 1536 | if (fd.asset || fd.fd >= 0) | ||
| 1537 | { | ||
| 1538 | /* Use a different kind of unwind_protect here. */ | ||
| 1539 | fd_index = SPECPDL_INDEX (); | ||
| 1540 | record_unwind_protect_ptr (close_file_unwind_android_fd, | ||
| 1541 | &fd); | ||
| 1542 | } | ||
| 1543 | #endif | ||
| 1377 | 1544 | ||
| 1378 | #ifdef HAVE_MODULES | 1545 | #ifdef HAVE_MODULES |
| 1379 | bool is_module = | 1546 | bool is_module = |
| @@ -1439,11 +1606,12 @@ Return t if the file exists and loads successfully. */) | |||
| 1439 | if (is_elc | 1606 | if (is_elc |
| 1440 | /* version = 1 means the file is empty, in which case we can | 1607 | /* version = 1 means the file is empty, in which case we can |
| 1441 | treat it as not byte-compiled. */ | 1608 | treat it as not byte-compiled. */ |
| 1442 | || (fd >= 0 && (version = safe_to_load_version (file, fd)) > 1)) | 1609 | || (lread_fd_p |
| 1610 | && (version = safe_to_load_version (file, fd)) > 1)) | ||
| 1443 | /* Load .elc files directly, but not when they are | 1611 | /* Load .elc files directly, but not when they are |
| 1444 | remote and have no handler! */ | 1612 | remote and have no handler! */ |
| 1445 | { | 1613 | { |
| 1446 | if (fd != -2) | 1614 | if (!lread_fd_cmp (-2)) |
| 1447 | { | 1615 | { |
| 1448 | struct stat s1, s2; | 1616 | struct stat s1, s2; |
| 1449 | int result; | 1617 | int result; |
| @@ -1500,9 +1668,9 @@ Return t if the file exists and loads successfully. */) | |||
| 1500 | { | 1668 | { |
| 1501 | Lisp_Object val; | 1669 | Lisp_Object val; |
| 1502 | 1670 | ||
| 1503 | if (fd >= 0) | 1671 | if (lread_fd_p) |
| 1504 | { | 1672 | { |
| 1505 | emacs_close (fd); | 1673 | lread_close (fd); |
| 1506 | clear_unwind_protect (fd_index); | 1674 | clear_unwind_protect (fd_index); |
| 1507 | } | 1675 | } |
| 1508 | val = call4 (Vload_source_file_function, found, hist_file_name, | 1676 | val = call4 (Vload_source_file_function, found, hist_file_name, |
| @@ -1512,12 +1680,12 @@ Return t if the file exists and loads successfully. */) | |||
| 1512 | } | 1680 | } |
| 1513 | } | 1681 | } |
| 1514 | 1682 | ||
| 1515 | if (fd < 0) | 1683 | if (!lread_fd_p) |
| 1516 | { | 1684 | { |
| 1517 | /* We somehow got here with fd == -2, meaning the file is deemed | 1685 | /* We somehow got here with fd == -2, meaning the file is deemed |
| 1518 | to be remote. Don't even try to reopen the file locally; | 1686 | to be remote. Don't even try to reopen the file locally; |
| 1519 | just force a failure. */ | 1687 | just force a failure. */ |
| 1520 | stream = NULL; | 1688 | stream = file_stream_invalid; |
| 1521 | errno = EINVAL; | 1689 | errno = EINVAL; |
| 1522 | } | 1690 | } |
| 1523 | else if (!is_module && !is_native_elisp) | 1691 | else if (!is_module && !is_native_elisp) |
| @@ -1528,7 +1696,15 @@ Return t if the file exists and loads successfully. */) | |||
| 1528 | efound = ENCODE_FILE (found); | 1696 | efound = ENCODE_FILE (found); |
| 1529 | stream = emacs_fopen (SSDATA (efound), fmode); | 1697 | stream = emacs_fopen (SSDATA (efound), fmode); |
| 1530 | #else | 1698 | #else |
| 1699 | #if !defined USE_ANDROID_ASSETS | ||
| 1531 | stream = fdopen (fd, fmode); | 1700 | stream = fdopen (fd, fmode); |
| 1701 | #else | ||
| 1702 | /* Android systems use special file descriptors which can point | ||
| 1703 | into compressed data and double as file streams. FMODE is | ||
| 1704 | unused. */ | ||
| 1705 | ((void) fmode); | ||
| 1706 | stream = fd; | ||
| 1707 | #endif | ||
| 1532 | #endif | 1708 | #endif |
| 1533 | } | 1709 | } |
| 1534 | 1710 | ||
| @@ -1540,15 +1716,15 @@ Return t if the file exists and loads successfully. */) | |||
| 1540 | { | 1716 | { |
| 1541 | /* `module-load' uses the file name, so we can close the stream | 1717 | /* `module-load' uses the file name, so we can close the stream |
| 1542 | now. */ | 1718 | now. */ |
| 1543 | if (fd >= 0) | 1719 | if (lread_fd_p) |
| 1544 | { | 1720 | { |
| 1545 | emacs_close (fd); | 1721 | lread_close (fd); |
| 1546 | clear_unwind_protect (fd_index); | 1722 | clear_unwind_protect (fd_index); |
| 1547 | } | 1723 | } |
| 1548 | } | 1724 | } |
| 1549 | else | 1725 | else |
| 1550 | { | 1726 | { |
| 1551 | if (! stream) | 1727 | if (!file_stream_valid_p (stream)) |
| 1552 | report_file_error ("Opening stdio stream", file); | 1728 | report_file_error ("Opening stdio stream", file); |
| 1553 | set_unwind_protect_ptr (fd_index, close_infile_unwind, infile); | 1729 | set_unwind_protect_ptr (fd_index, close_infile_unwind, infile); |
| 1554 | input.stream = stream; | 1730 | input.stream = stream; |
| @@ -1684,7 +1860,8 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) | |||
| 1684 | (Lisp_Object filename, Lisp_Object path, Lisp_Object suffixes, Lisp_Object predicate) | 1860 | (Lisp_Object filename, Lisp_Object path, Lisp_Object suffixes, Lisp_Object predicate) |
| 1685 | { | 1861 | { |
| 1686 | Lisp_Object file; | 1862 | Lisp_Object file; |
| 1687 | int fd = openp (path, filename, suffixes, &file, predicate, false, true); | 1863 | int fd = openp (path, filename, suffixes, &file, predicate, false, true, |
| 1864 | NULL); | ||
| 1688 | if (NILP (predicate) && fd >= 0) | 1865 | if (NILP (predicate) && fd >= 0) |
| 1689 | emacs_close (fd); | 1866 | emacs_close (fd); |
| 1690 | return file; | 1867 | return file; |
| @@ -1825,14 +2002,20 @@ maybe_swap_for_eln (bool no_native, Lisp_Object *filename, int *fd, | |||
| 1825 | 2002 | ||
| 1826 | If NEWER is true, try all SUFFIXes and return the result for the | 2003 | If NEWER is true, try all SUFFIXes and return the result for the |
| 1827 | newest file that exists. Does not apply to remote files, | 2004 | newest file that exists. Does not apply to remote files, |
| 1828 | or if a non-nil and non-t PREDICATE is specified. | 2005 | platform-specific files, or if a non-nil and non-t PREDICATE is |
| 2006 | specified. | ||
| 1829 | 2007 | ||
| 1830 | if NO_NATIVE is true do not try to load native code. */ | 2008 | If NO_NATIVE is true do not try to load native code. |
| 2009 | |||
| 2010 | If PLATFORM is non-NULL and the file being loaded lies in a special | ||
| 2011 | directory, such as the Android `/assets' directory, return a handle | ||
| 2012 | to that directory in *PLATFORM instead of a file descriptor; in | ||
| 2013 | that case, value is -3. */ | ||
| 1831 | 2014 | ||
| 1832 | int | 2015 | int |
| 1833 | openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | 2016 | openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, |
| 1834 | Lisp_Object *storeptr, Lisp_Object predicate, bool newer, | 2017 | Lisp_Object *storeptr, Lisp_Object predicate, bool newer, |
| 1835 | bool no_native) | 2018 | bool no_native, void **platform) |
| 1836 | { | 2019 | { |
| 1837 | ptrdiff_t fn_size = 100; | 2020 | ptrdiff_t fn_size = 100; |
| 1838 | char buf[100]; | 2021 | char buf[100]; |
| @@ -1844,6 +2027,9 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1844 | ptrdiff_t max_suffix_len = 0; | 2027 | ptrdiff_t max_suffix_len = 0; |
| 1845 | int last_errno = ENOENT; | 2028 | int last_errno = ENOENT; |
| 1846 | int save_fd = -1; | 2029 | int save_fd = -1; |
| 2030 | #ifdef USE_ANDROID_ASSETS | ||
| 2031 | struct android_fd_or_asset platform_fd; | ||
| 2032 | #endif | ||
| 1847 | USE_SAFE_ALLOCA; | 2033 | USE_SAFE_ALLOCA; |
| 1848 | 2034 | ||
| 1849 | /* The last-modified time of the newest matching file found. | 2035 | /* The last-modified time of the newest matching file found. |
| @@ -2013,7 +2199,30 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 2013 | fd = -1; | 2199 | fd = -1; |
| 2014 | else | 2200 | else |
| 2015 | #endif | 2201 | #endif |
| 2016 | fd = emacs_open (pfn, O_RDONLY, 0); | 2202 | { |
| 2203 | #if !defined USE_ANDROID_ASSETS | ||
| 2204 | fd = emacs_open (pfn, O_RDONLY, 0); | ||
| 2205 | #else | ||
| 2206 | if (platform) | ||
| 2207 | { | ||
| 2208 | platform_fd = android_open_asset (pfn, O_RDONLY, 0); | ||
| 2209 | |||
| 2210 | if (platform_fd.asset | ||
| 2211 | && platform_fd.asset != (void *) -1) | ||
| 2212 | { | ||
| 2213 | *storeptr = string; | ||
| 2214 | goto handle_platform_fd; | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | if (platform_fd.asset == (void *) -1) | ||
| 2218 | fd = -1; | ||
| 2219 | else | ||
| 2220 | fd = platform_fd.fd; | ||
| 2221 | } | ||
| 2222 | else | ||
| 2223 | fd = emacs_open (pfn, O_RDONLY, 0); | ||
| 2224 | #endif | ||
| 2225 | } | ||
| 2017 | 2226 | ||
| 2018 | if (fd < 0) | 2227 | if (fd < 0) |
| 2019 | { | 2228 | { |
| @@ -2081,6 +2290,16 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 2081 | SAFE_FREE (); | 2290 | SAFE_FREE (); |
| 2082 | errno = last_errno; | 2291 | errno = last_errno; |
| 2083 | return -1; | 2292 | return -1; |
| 2293 | |||
| 2294 | #ifdef USE_ANDROID_ASSETS | ||
| 2295 | handle_platform_fd: | ||
| 2296 | |||
| 2297 | /* Here, openp found a platform specific file descriptor. It can't | ||
| 2298 | be a directory under Android, so return it in *PLATFORM and then | ||
| 2299 | -3 as the file descriptor. */ | ||
| 2300 | *platform = platform_fd.asset; | ||
| 2301 | return -3; | ||
| 2302 | #endif | ||
| 2084 | } | 2303 | } |
| 2085 | 2304 | ||
| 2086 | 2305 | ||
| @@ -3489,7 +3708,7 @@ skip_lazy_string (Lisp_Object readcharfun) | |||
| 3489 | ss->string = xrealloc (ss->string, ss->size); | 3708 | ss->string = xrealloc (ss->string, ss->size); |
| 3490 | } | 3709 | } |
| 3491 | 3710 | ||
| 3492 | FILE *instream = infile->stream; | 3711 | file_stream instream = infile->stream; |
| 3493 | ss->position = (file_tell (instream) - infile->lookahead); | 3712 | ss->position = (file_tell (instream) - infile->lookahead); |
| 3494 | 3713 | ||
| 3495 | /* Copy that many bytes into the saved string. */ | 3714 | /* Copy that many bytes into the saved string. */ |
| @@ -3499,7 +3718,7 @@ skip_lazy_string (Lisp_Object readcharfun) | |||
| 3499 | ss->string[i++] = c = infile->buf[--infile->lookahead]; | 3718 | ss->string[i++] = c = infile->buf[--infile->lookahead]; |
| 3500 | block_input (); | 3719 | block_input (); |
| 3501 | for (; i < nskip && c >= 0; i++) | 3720 | for (; i < nskip && c >= 0; i++) |
| 3502 | ss->string[i] = c = getc (instream); | 3721 | ss->string[i] = c = file_get_char (instream); |
| 3503 | unblock_input (); | 3722 | unblock_input (); |
| 3504 | 3723 | ||
| 3505 | ss->length = i; | 3724 | ss->length = i; |
diff --git a/src/process.c b/src/process.c index bdaaba70fea..0eff789e599 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -2008,7 +2008,7 @@ usage: (make-process &rest ARGS) */) | |||
| 2008 | { | 2008 | { |
| 2009 | tem = Qnil; | 2009 | tem = Qnil; |
| 2010 | openp (Vexec_path, program, Vexec_suffixes, &tem, | 2010 | openp (Vexec_path, program, Vexec_suffixes, &tem, |
| 2011 | make_fixnum (X_OK), false, false); | 2011 | make_fixnum (X_OK), false, false, NULL); |
| 2012 | if (NILP (tem)) | 2012 | if (NILP (tem)) |
| 2013 | report_file_error ("Searching for program", program); | 2013 | report_file_error ("Searching for program", program); |
| 2014 | tem = Fexpand_file_name (tem, Qnil); | 2014 | tem = Fexpand_file_name (tem, Qnil); |
diff --git a/src/sound.c b/src/sound.c index 145100cd433..a51cdb6d97a 100644 --- a/src/sound.c +++ b/src/sound.c | |||
| @@ -1384,7 +1384,7 @@ Internal use only, use `play-sound' instead. */) | |||
| 1384 | /* Open the sound file. */ | 1384 | /* Open the sound file. */ |
| 1385 | current_sound->fd = | 1385 | current_sound->fd = |
| 1386 | openp (list1 (Vdata_directory), attrs[SOUND_FILE], Qnil, &file, Qnil, | 1386 | openp (list1 (Vdata_directory), attrs[SOUND_FILE], Qnil, &file, Qnil, |
| 1387 | false, false); | 1387 | false, false, NULL); |
| 1388 | if (current_sound->fd < 0) | 1388 | if (current_sound->fd < 0) |
| 1389 | sound_perror ("Could not open sound file"); | 1389 | sound_perror ("Could not open sound file"); |
| 1390 | 1390 | ||
| @@ -10328,7 +10328,8 @@ check_windows_init_file (void) | |||
| 10328 | names from UTF-8 to ANSI. */ | 10328 | names from UTF-8 to ANSI. */ |
| 10329 | init_file = build_string ("term/w32-win"); | 10329 | init_file = build_string ("term/w32-win"); |
| 10330 | fd = | 10330 | fd = |
| 10331 | openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0, 0); | 10331 | openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0, 0, |
| 10332 | NULL); | ||
| 10332 | if (fd < 0) | 10333 | if (fd < 0) |
| 10333 | { | 10334 | { |
| 10334 | Lisp_Object load_path_print = Fprin1_to_string (Vload_path, | 10335 | Lisp_Object load_path_print = Fprin1_to_string (Vload_path, |
diff --git a/src/w32proc.c b/src/w32proc.c index 77a4ac1ff7e..edc4394b17f 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -1956,7 +1956,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) | |||
| 1956 | program = build_string (cmdname); | 1956 | program = build_string (cmdname); |
| 1957 | full = Qnil; | 1957 | full = Qnil; |
| 1958 | openp (Vexec_path, program, Vexec_suffixes, &full, make_fixnum (X_OK), | 1958 | openp (Vexec_path, program, Vexec_suffixes, &full, make_fixnum (X_OK), |
| 1959 | 0, 0); | 1959 | 0, 0, NULL); |
| 1960 | if (NILP (full)) | 1960 | if (NILP (full)) |
| 1961 | { | 1961 | { |
| 1962 | errno = EINVAL; | 1962 | errno = EINVAL; |