aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-03-07 14:20:50 +0800
committerPo Lu2023-03-07 14:20:50 +0800
commit44cf1ed7e593022df01a47b701e7796e9d70d2fb (patch)
tree09a0e49ee9d7eda6b201bbb07c574d6b4a4c35e0 /src
parenta11ad7149bc1908d205e78ecfb240b76ce190bef (diff)
downloademacs-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.c2
-rw-r--r--src/charset.c3
-rw-r--r--src/emacs.c3
-rw-r--r--src/image.c9
-rw-r--r--src/lisp.h3
-rw-r--r--src/lread.c283
-rw-r--r--src/process.c2
-rw-r--r--src/sound.c2
-rw-r--r--src/w32.c3
-rw-r--r--src/w32proc.c2
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 *);
4514extern Lisp_Object save_match_data_load (Lisp_Object, Lisp_Object, Lisp_Object, 4514extern Lisp_Object save_match_data_load (Lisp_Object, Lisp_Object, Lisp_Object,
4515 Lisp_Object, Lisp_Object); 4515 Lisp_Object, Lisp_Object);
4516extern int openp (Lisp_Object, Lisp_Object, Lisp_Object, 4516extern int openp (Lisp_Object, Lisp_Object, Lisp_Object,
4517 Lisp_Object *, Lisp_Object, bool, bool); 4517 Lisp_Object *, Lisp_Object, bool, bool,
4518 void **);
4518enum { S2N_IGNORE_TRAILING = 1 }; 4519enum { S2N_IGNORE_TRAILING = 1 };
4519extern Lisp_Object string_to_number (char const *, int, ptrdiff_t *); 4520extern Lisp_Object string_to_number (char const *, int, ptrdiff_t *);
4520extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object), 4521extern 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
119static 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
136static int
137file_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;
113static struct infile 204static 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
1064static int 1186static int
1065safe_to_load_version (Lisp_Object file, int fd) 1187safe_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
1324static void
1325close_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
1197DEFUN ("load", Fload, Sload, 1, 5, 0, 1335DEFUN ("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.
1199First try FILE with `.elc' appended, then try with `.el', then try 1337First 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
1832int 2015int
1833openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, 2016openp (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
diff --git a/src/w32.c b/src/w32.c
index 8d344d2e6da..f45750ea5c1 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -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;