+/* Return true if COMPILED_FILENAME is newer than source file
+ FULL_FILENAME, false otherwise. Also return false if one of the
+ files cannot be stat'd. */
+static int
+compiled_is_fresh (SCM full_filename, SCM compiled_filename)
+{
+ char *source, *compiled;
+ struct stat stat_source, stat_compiled;
+ int compiled_is_newer;
+
+ source = scm_to_locale_string (full_filename);
+ compiled = scm_to_locale_string (compiled_filename);
+
+ if (stat (source, &stat_source) == 0
+ && stat (compiled, &stat_compiled) == 0)
+ {
+ struct timespec source_mtime, compiled_mtime;
+
+ source_mtime = get_stat_mtime (&stat_source);
+ compiled_mtime = get_stat_mtime (&stat_compiled);
+
+ if (source_mtime.tv_sec < compiled_mtime.tv_sec
+ || (source_mtime.tv_sec == compiled_mtime.tv_sec
+ && source_mtime.tv_nsec <= compiled_mtime.tv_nsec))
+ compiled_is_newer = 1;
+ else
+ {
+ compiled_is_newer = 0;
+ scm_puts (";;; note: source file ", scm_current_error_port ());
+ scm_puts (source, scm_current_error_port ());
+ scm_puts ("\n;;; newer than compiled ", scm_current_error_port ());
+ scm_puts (compiled, scm_current_error_port ());
+ scm_puts ("\n", scm_current_error_port ());
+ }
+ }
+ else
+ /* At least one of the files isn't accessible. */
+ compiled_is_newer = 0;
+
+ free (source);
+ free (compiled);
+
+ return compiled_is_newer;
+}
+
+SCM_KEYWORD (kw_env, "env");
+
+static SCM
+do_try_auto_compile (void *data)
+{
+ SCM source = PTR2SCM (data);
+ SCM comp_mod, compile_file;
+
+ scm_puts (";;; compiling ", scm_current_error_port ());
+ scm_display (source, scm_current_error_port ());
+ scm_newline (scm_current_error_port ());
+
+ comp_mod = scm_c_resolve_module ("system base compile");
+ compile_file = scm_module_variable
+ (comp_mod, scm_from_latin1_symbol ("compile-file"));
+
+ if (scm_is_true (compile_file))
+ {
+ /* Auto-compile in the context of the current module. */
+ SCM res = scm_call_3 (scm_variable_ref (compile_file), source,
+ kw_env, scm_current_module ());
+ scm_puts (";;; compiled ", scm_current_error_port ());
+ scm_display (res, scm_current_error_port ());
+ scm_newline (scm_current_error_port ());
+ return res;
+ }
+ else
+ {
+ scm_puts (";;; it seems ", scm_current_error_port ());
+ scm_display (source, scm_current_error_port ());
+ scm_puts ("\n;;; is part of the compiler; skipping auto-compilation\n",
+ scm_current_error_port ());
+ return SCM_BOOL_F;
+ }
+}
+
+static SCM
+auto_compile_catch_handler (void *data, SCM tag, SCM throw_args)
+{
+ SCM source = PTR2SCM (data);
+ scm_puts (";;; WARNING: compilation of ", scm_current_error_port ());
+ scm_display (source, scm_current_error_port ());
+ scm_puts (" failed:\n", scm_current_error_port ());
+ scm_puts (";;; key ", scm_current_error_port ());
+ scm_write (tag, scm_current_error_port ());
+ scm_puts (", throw args ", scm_current_error_port ());
+ scm_write (throw_args, scm_current_error_port ());
+ scm_newline (scm_current_error_port ());
+ return SCM_BOOL_F;
+}
+
+SCM_DEFINE (scm_sys_warn_auto_compilation_enabled, "%warn-auto-compilation-enabled", 0, 0, 0,
+ (void), "")
+#define FUNC_NAME s_scm_sys_warn_auto_compilation_enabled
+{
+ static int message_shown = 0;
+
+ if (!message_shown)
+ {
+ scm_puts (";;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0\n"
+ ";;; or pass the --no-auto-compile argument to disable.\n",
+ scm_current_error_port ());
+ message_shown = 1;
+ }
+
+ return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
+static SCM
+scm_try_auto_compile (SCM source)
+{
+ if (scm_is_false (*scm_loc_load_should_auto_compile))
+ return SCM_BOOL_F;
+
+ scm_sys_warn_auto_compilation_enabled ();
+ return scm_c_catch (SCM_BOOL_T,
+ do_try_auto_compile,
+ SCM2PTR (source),
+ auto_compile_catch_handler,
+ SCM2PTR (source),
+ NULL, NULL);
+}
+
+SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 0, 0, 1,
+ (SCM args),