diff options
| author | Philipp Stephani | 2018-01-28 21:36:03 +0100 |
|---|---|---|
| committer | Philipp Stephani | 2018-02-02 20:56:01 +0100 |
| commit | 0443411f5ce2594a6ec092cd96b92d0b920372f5 (patch) | |
| tree | 7790497b70f0719498fe17043c956b42339a83e8 | |
| parent | 75c663f834528c5431973bf8dc6386c327f9fe0f (diff) | |
| download | emacs-0443411f5ce2594a6ec092cd96b92d0b920372f5.tar.gz emacs-0443411f5ce2594a6ec092cd96b92d0b920372f5.zip | |
Properly integrate modules into the loading process (Bug#30164).
* src/lread.c (Fload): Don't defer to module-load immediately when
encountering a module, but use the normal loading machinery to
properly set up load-history, check for recursive loads, print
messages, etc.
* test/src/emacs-module-tests.el (module/load-history): New test.
(module/describe-function-1): Adapt test.
* etc/NEWS: Mention fixed behavior.
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | src/lread.c | 82 | ||||
| -rw-r--r-- | test/src/emacs-module-tests.el | 19 |
3 files changed, 77 insertions, 28 deletions
| @@ -275,6 +275,10 @@ file name extensions. | |||
| 275 | ** The new function 'read-answer' accepts either long or short answers | 275 | ** The new function 'read-answer' accepts either long or short answers |
| 276 | depending on the new customizable variable 'read-answer-short'. | 276 | depending on the new customizable variable 'read-answer-short'. |
| 277 | 277 | ||
| 278 | ** The function 'load' now behaves correctly when loading modules. | ||
| 279 | Specifically, it puts the module name into 'load-history', prints | ||
| 280 | loading messages if requested, and protects against recursive loads. | ||
| 281 | |||
| 278 | 282 | ||
| 279 | * Changes in Emacs 27.1 on Non-Free Operating Systems | 283 | * Changes in Emacs 27.1 on Non-Free Operating Systems |
| 280 | 284 | ||
diff --git a/src/lread.c b/src/lread.c index 3b0a17c90be..1221dc9a05f 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -164,6 +164,8 @@ static int read_emacs_mule_char (int, int (*) (int, Lisp_Object), | |||
| 164 | static void readevalloop (Lisp_Object, struct infile *, Lisp_Object, bool, | 164 | static void readevalloop (Lisp_Object, struct infile *, Lisp_Object, bool, |
| 165 | Lisp_Object, Lisp_Object, | 165 | Lisp_Object, Lisp_Object, |
| 166 | Lisp_Object, Lisp_Object); | 166 | Lisp_Object, Lisp_Object); |
| 167 | |||
| 168 | static void build_load_history (Lisp_Object, bool); | ||
| 167 | 169 | ||
| 168 | /* Functions that read one byte from the current source READCHARFUN | 170 | /* Functions that read one byte from the current source READCHARFUN |
| 169 | or unreads one byte. If the integer argument C is -1, it returns | 171 | or unreads one byte. If the integer argument C is -1, it returns |
| @@ -1246,8 +1248,9 @@ Return t if the file exists and loads successfully. */) | |||
| 1246 | } | 1248 | } |
| 1247 | 1249 | ||
| 1248 | #ifdef HAVE_MODULES | 1250 | #ifdef HAVE_MODULES |
| 1249 | if (suffix_p (found, MODULES_SUFFIX)) | 1251 | bool is_module = suffix_p (found, MODULES_SUFFIX); |
| 1250 | return unbind_to (count, Fmodule_load (found)); | 1252 | #else |
| 1253 | bool is_module = false; | ||
| 1251 | #endif | 1254 | #endif |
| 1252 | 1255 | ||
| 1253 | /* Check if we're stuck in a recursive load cycle. | 1256 | /* Check if we're stuck in a recursive load cycle. |
| @@ -1348,7 +1351,7 @@ Return t if the file exists and loads successfully. */) | |||
| 1348 | } /* !load_prefer_newer */ | 1351 | } /* !load_prefer_newer */ |
| 1349 | } | 1352 | } |
| 1350 | } | 1353 | } |
| 1351 | else | 1354 | else if (!is_module) |
| 1352 | { | 1355 | { |
| 1353 | /* We are loading a source file (*.el). */ | 1356 | /* We are loading a source file (*.el). */ |
| 1354 | if (!NILP (Vload_source_file_function)) | 1357 | if (!NILP (Vload_source_file_function)) |
| @@ -1375,7 +1378,7 @@ Return t if the file exists and loads successfully. */) | |||
| 1375 | stream = NULL; | 1378 | stream = NULL; |
| 1376 | errno = EINVAL; | 1379 | errno = EINVAL; |
| 1377 | } | 1380 | } |
| 1378 | else | 1381 | else if (!is_module) |
| 1379 | { | 1382 | { |
| 1380 | #ifdef WINDOWSNT | 1383 | #ifdef WINDOWSNT |
| 1381 | emacs_close (fd); | 1384 | emacs_close (fd); |
| @@ -1386,9 +1389,23 @@ Return t if the file exists and loads successfully. */) | |||
| 1386 | stream = fdopen (fd, fmode); | 1389 | stream = fdopen (fd, fmode); |
| 1387 | #endif | 1390 | #endif |
| 1388 | } | 1391 | } |
| 1389 | if (! stream) | 1392 | |
| 1390 | report_file_error ("Opening stdio stream", file); | 1393 | if (is_module) |
| 1391 | set_unwind_protect_ptr (fd_index, close_infile_unwind, stream); | 1394 | { |
| 1395 | /* `module-load' uses the file name, so we can close the stream | ||
| 1396 | now. */ | ||
| 1397 | if (fd >= 0) | ||
| 1398 | { | ||
| 1399 | emacs_close (fd); | ||
| 1400 | clear_unwind_protect (fd_index); | ||
| 1401 | } | ||
| 1402 | } | ||
| 1403 | else | ||
| 1404 | { | ||
| 1405 | if (! stream) | ||
| 1406 | report_file_error ("Opening stdio stream", file); | ||
| 1407 | set_unwind_protect_ptr (fd_index, close_infile_unwind, stream); | ||
| 1408 | } | ||
| 1392 | 1409 | ||
| 1393 | if (! NILP (Vpurify_flag)) | 1410 | if (! NILP (Vpurify_flag)) |
| 1394 | Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list); | 1411 | Vpreloaded_file_list = Fcons (Fpurecopy (file), Vpreloaded_file_list); |
| @@ -1398,6 +1415,8 @@ Return t if the file exists and loads successfully. */) | |||
| 1398 | if (!safe_p) | 1415 | if (!safe_p) |
| 1399 | message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...", | 1416 | message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...", |
| 1400 | file, 1); | 1417 | file, 1); |
| 1418 | else if (is_module) | ||
| 1419 | message_with_string ("Loading %s (module)...", file, 1); | ||
| 1401 | else if (!compiled) | 1420 | else if (!compiled) |
| 1402 | message_with_string ("Loading %s (source)...", file, 1); | 1421 | message_with_string ("Loading %s (source)...", file, 1); |
| 1403 | else if (newer) | 1422 | else if (newer) |
| @@ -1411,24 +1430,39 @@ Return t if the file exists and loads successfully. */) | |||
| 1411 | specbind (Qinhibit_file_name_operation, Qnil); | 1430 | specbind (Qinhibit_file_name_operation, Qnil); |
| 1412 | specbind (Qload_in_progress, Qt); | 1431 | specbind (Qload_in_progress, Qt); |
| 1413 | 1432 | ||
| 1414 | struct infile input; | 1433 | if (is_module) |
| 1415 | input.stream = stream; | 1434 | { |
| 1416 | input.lookahead = 0; | 1435 | #ifdef HAVE_MODULES |
| 1417 | infile = &input; | 1436 | specbind (Qcurrent_load_list, Qnil); |
| 1418 | 1437 | LOADHIST_ATTACH (found); | |
| 1419 | if (lisp_file_lexically_bound_p (Qget_file_char)) | 1438 | Fmodule_load (found); |
| 1420 | Fset (Qlexical_binding, Qt); | 1439 | build_load_history (found, true); |
| 1421 | 1440 | #else | |
| 1422 | if (! version || version >= 22) | 1441 | /* This cannot happen. */ |
| 1423 | readevalloop (Qget_file_char, &input, hist_file_name, | 1442 | emacs_abort (); |
| 1424 | 0, Qnil, Qnil, Qnil, Qnil); | 1443 | #endif |
| 1444 | } | ||
| 1425 | else | 1445 | else |
| 1426 | { | 1446 | { |
| 1427 | /* We can't handle a file which was compiled with | 1447 | struct infile input; |
| 1428 | byte-compile-dynamic by older version of Emacs. */ | 1448 | input.stream = stream; |
| 1429 | specbind (Qload_force_doc_strings, Qt); | 1449 | input.lookahead = 0; |
| 1430 | readevalloop (Qget_emacs_mule_file_char, &input, hist_file_name, | 1450 | infile = &input; |
| 1431 | 0, Qnil, Qnil, Qnil, Qnil); | 1451 | |
| 1452 | if (lisp_file_lexically_bound_p (Qget_file_char)) | ||
| 1453 | Fset (Qlexical_binding, Qt); | ||
| 1454 | |||
| 1455 | if (! version || version >= 22) | ||
| 1456 | readevalloop (Qget_file_char, &input, hist_file_name, | ||
| 1457 | 0, Qnil, Qnil, Qnil, Qnil); | ||
| 1458 | else | ||
| 1459 | { | ||
| 1460 | /* We can't handle a file which was compiled with | ||
| 1461 | byte-compile-dynamic by older version of Emacs. */ | ||
| 1462 | specbind (Qload_force_doc_strings, Qt); | ||
| 1463 | readevalloop (Qget_emacs_mule_file_char, &input, hist_file_name, | ||
| 1464 | 0, Qnil, Qnil, Qnil, Qnil); | ||
| 1465 | } | ||
| 1432 | } | 1466 | } |
| 1433 | unbind_to (count, Qnil); | 1467 | unbind_to (count, Qnil); |
| 1434 | 1468 | ||
| @@ -1449,6 +1483,8 @@ Return t if the file exists and loads successfully. */) | |||
| 1449 | if (!safe_p) | 1483 | if (!safe_p) |
| 1450 | message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...done", | 1484 | message_with_string ("Loading %s (compiled; note unsafe, not compiled in Emacs)...done", |
| 1451 | file, 1); | 1485 | file, 1); |
| 1486 | else if (is_module) | ||
| 1487 | message_with_string ("Loading %s (module)...done", file, 1); | ||
| 1452 | else if (!compiled) | 1488 | else if (!compiled) |
| 1453 | message_with_string ("Loading %s (source)...done", file, 1); | 1489 | message_with_string ("Loading %s (source)...done", file, 1); |
| 1454 | else if (newer) | 1490 | else if (newer) |
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el index 052f5c2f12c..4751638968f 100644 --- a/test/src/emacs-module-tests.el +++ b/test/src/emacs-module-tests.el | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | ;; You should have received a copy of the GNU General Public License | 17 | ;; You should have received a copy of the GNU General Public License |
| 18 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | 18 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ |
| 19 | 19 | ||
| 20 | (require 'cl-lib) | ||
| 20 | (require 'ert) | 21 | (require 'ert) |
| 21 | (require 'help-fns) | 22 | (require 'help-fns) |
| 22 | 23 | ||
| @@ -267,13 +268,21 @@ during garbage collection." | |||
| 267 | (with-temp-buffer | 268 | (with-temp-buffer |
| 268 | (let ((standard-output (current-buffer))) | 269 | (let ((standard-output (current-buffer))) |
| 269 | (describe-function-1 #'mod-test-sum) | 270 | (describe-function-1 #'mod-test-sum) |
| 270 | (should (equal (buffer-substring-no-properties 1 (point-max)) | 271 | (should (equal |
| 271 | ;; FIXME: This should print the actual module | 272 | (buffer-substring-no-properties 1 (point-max)) |
| 272 | ;; filename. | 273 | (format "a module function in `data/emacs-module/mod-test%s'. |
| 273 | "a module function in `src/emacs-module-tests.el'. | ||
| 274 | 274 | ||
| 275 | (mod-test-sum a b) | 275 | (mod-test-sum a b) |
| 276 | 276 | ||
| 277 | Return A + B"))))) | 277 | Return A + B" |
| 278 | module-file-suffix)))))) | ||
| 279 | |||
| 280 | (ert-deftest module/load-history () | ||
| 281 | "Check that Bug#30164 is fixed." | ||
| 282 | (load mod-test-file) | ||
| 283 | (cl-destructuring-bind (file &rest entries) (car load-history) | ||
| 284 | (should (equal (file-name-sans-extension file) mod-test-file)) | ||
| 285 | (should (member '(provide . mod-test) entries)) | ||
| 286 | (should (member '(defun . mod-test-sum) entries)))) | ||
| 278 | 287 | ||
| 279 | ;;; emacs-module-tests.el ends here | 288 | ;;; emacs-module-tests.el ends here |