X-Git-Url: https://git.hcoop.net/bpt/guile.git/blobdiff_plain/628132c5acfb804e798a6a240a0333587831f837..b2208d2e987759270c712e35c8164394a47a52aa:/libguile/load.c diff --git a/libguile/load.c b/libguile/load.c index 6c2cd92be..14f411aa7 100644 --- a/libguile/load.c +++ b/libguile/load.c @@ -1,18 +1,19 @@ -/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 1995,1996,1998,1999,2000,2001, 2004, 2006, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA */ @@ -26,6 +27,7 @@ #include #include "libguile/_scm.h" +#include "libguile/private-gc.h" /* scm_getenv_int */ #include "libguile/libpath.h" #include "libguile/fports.h" #include "libguile/read.h" @@ -36,7 +38,6 @@ #include "libguile/root.h" #include "libguile/strings.h" #include "libguile/modules.h" -#include "libguile/lang.h" #include "libguile/chars.h" #include "libguile/srfi-13.h" @@ -61,6 +62,8 @@ #define R_OK 4 #endif +#include + /* Loading a file, given an absolute filename. */ @@ -70,7 +73,7 @@ static SCM *scm_loc_load_hook; /* The current reader (a fluid). */ static SCM the_reader = SCM_BOOL_F; -static size_t the_reader_fluid_num = 0; + SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0, (SCM filename), @@ -84,6 +87,7 @@ SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0, #define FUNC_NAME s_scm_primitive_load { SCM hook = *scm_loc_load_hook; + char *encoding; SCM_VALIDATE_STRING (1, filename); if (scm_is_true (hook) && scm_is_false (scm_procedure_p (hook))) SCM_MISC_ERROR ("value of %load-hook is neither a procedure nor #f", @@ -97,14 +101,22 @@ SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0, scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE); scm_i_dynwind_current_load_port (port); + encoding = scm_i_scan_for_encoding (port); + if (encoding) + scm_i_set_port_encoding_x (port, encoding); + else + /* The file has no encoding declared. We'll presume UTF-8, like + compile-file does. */ + scm_i_set_port_encoding_x (port, "UTF-8"); + while (1) { SCM reader, form; /* Lookup and use the current reader to read the next expression. */ - reader = SCM_FAST_FLUID_REF (the_reader_fluid_num); - if (reader == SCM_BOOL_F) + reader = scm_fluid_ref (the_reader); + if (scm_is_false (reader)) form = scm_read (port); else form = scm_call_1 (reader, port); @@ -158,8 +170,9 @@ SCM_DEFINE (scm_sys_library_dir, "%library-dir", 0,0,0, #ifdef SCM_SITE_DIR SCM_DEFINE (scm_sys_site_dir, "%site-dir", 0,0,0, (), - "Return the directory where the Guile site files are installed.\n" - "E.g., may return \"/usr/share/guile/site\".") + "Return the directory where users should install Scheme code for use\n" + "with this version of Guile.\n\n" + "E.g., may return \"/usr/share/guile/site/" SCM_EFFECTIVE_VERSION "\".") #define FUNC_NAME s_scm_sys_site_dir { return scm_from_locale_string (SCM_SITE_DIR); @@ -167,6 +180,18 @@ SCM_DEFINE (scm_sys_site_dir, "%site-dir", 0,0,0, #undef FUNC_NAME #endif /* SCM_SITE_DIR */ +#ifdef SCM_GLOBAL_SITE_DIR +SCM_DEFINE (scm_sys_global_site_dir, "%global-site-dir", 0,0,0, + (), + "Return the directory where users should install Scheme code for use\n" + "with all versions of Guile.\n\n" + "E.g., may return \"/usr/share/guile/site\".") +#define FUNC_NAME s_scm_sys_global_site_dir +{ + return scm_from_locale_string (SCM_GLOBAL_SITE_DIR); +} +#undef FUNC_NAME +#endif /* SCM_GLOBAL_SITE_DIR */ @@ -183,9 +208,12 @@ static SCM *scm_loc_load_compiled_path; static SCM *scm_loc_load_compiled_extensions; /* Whether we should try to auto-compile. */ -static SCM *scm_loc_load_should_autocompile; +static SCM *scm_loc_load_should_auto_compile; + +/* Whether to treat all auto-compiled files as stale. */ +static SCM *scm_loc_fresh_auto_compile; -/* The fallback path for autocompilation */ +/* The fallback path for auto-compilation */ static SCM *scm_loc_compile_fallback_path; SCM_DEFINE (scm_parse_path, "parse-path", 1, 1, 0, @@ -230,8 +258,9 @@ scm_init_load_path () else if (env) path = scm_parse_path (scm_from_locale_string (env), path); else - path = scm_list_3 (scm_from_locale_string (SCM_SITE_DIR), - scm_from_locale_string (SCM_LIBRARY_DIR), + path = scm_list_4 (scm_from_locale_string (SCM_LIBRARY_DIR), + scm_from_locale_string (SCM_SITE_DIR), + scm_from_locale_string (SCM_GLOBAL_SITE_DIR), scm_from_locale_string (SCM_PKGDATA_DIR)); env = getenv ("GUILE_SYSTEM_COMPILED_PATH"); @@ -241,29 +270,43 @@ scm_init_load_path () else if (env) cpath = scm_parse_path (scm_from_locale_string (env), cpath); else - cpath = scm_cons (scm_from_locale_string (SCM_CCACHE_DIR), cpath); + { + cpath = scm_list_2 (scm_from_locale_string (SCM_CCACHE_DIR), + scm_from_locale_string (SCM_SITE_CCACHE_DIR)); + } #endif /* SCM_LIBRARY_DIR */ { - char *home; + char cachedir[1024]; + char *e; +#ifdef HAVE_GETPWENT + struct passwd *pwd; +#endif + +#define FALLBACK_DIR \ + "guile/ccache/" SCM_EFFECTIVE_VERSION "-" SCM_OBJCODE_MACHINE_VERSION_STRING - home = getenv ("HOME"); + if ((e = getenv ("XDG_CACHE_HOME"))) + snprintf (cachedir, sizeof(cachedir), "%s/" FALLBACK_DIR, e); + else if ((e = getenv ("HOME"))) + snprintf (cachedir, sizeof(cachedir), "%s/.cache/" FALLBACK_DIR, e); #ifdef HAVE_GETPWENT - if (!home) - { - struct passwd *pwd; - pwd = getpwuid (getuid ()); - if (pwd) - home = pwd->pw_dir; - } + else if ((pwd = getpwuid (getuid ())) && pwd->pw_dir) + snprintf (cachedir, sizeof(cachedir), "%s/.cache/" FALLBACK_DIR, + pwd->pw_dir); #endif /* HAVE_GETPWENT */ - if (home) - { char buf[1024]; - snprintf (buf, sizeof(buf), - "%s/.guile-ccache/" SCM_EFFECTIVE_VERSION, home); - *scm_loc_compile_fallback_path = scm_from_locale_string (buf); - } +#ifdef __MINGW32__ + else if ((e = getenv ("LOCALAPPDATA"))) + snprintf (cachedir, sizeof (cachedir), "%s/.cache/" FALLBACK_DIR, e); + else if ((e = getenv ("APPDATA"))) + snprintf (cachedir, sizeof (cachedir), "%s/.cache/" FALLBACK_DIR, e); +#endif /* __MINGW32__ */ + else + cachedir[0] = 0; + + if (cachedir[0]) + *scm_loc_compile_fallback_path = scm_from_locale_string (cachedir); } env = getenv ("GUILE_LOAD_PATH"); @@ -376,27 +419,21 @@ scm_c_string_has_an_ext (char *str, size_t len, SCM extensions) If FILENAME is absolute, return it unchanged. If given, EXTENSIONS is a list of strings; for each directory in PATH, we search for FILENAME concatenated with each EXTENSION. */ -SCM_DEFINE (scm_search_path, "search-path", 2, 2, 0, - (SCM path, SCM filename, SCM extensions, SCM require_exts), - "Search @var{path} for a directory containing a file named\n" - "@var{filename}. The file must be readable, and not a directory.\n" - "If we find one, return its full filename; otherwise, return\n" - "@code{#f}. If @var{filename} is absolute, return it unchanged.\n" - "If given, @var{extensions} is a list of strings; for each\n" - "directory in @var{path}, we search for @var{filename}\n" - "concatenated with each @var{extension}.") -#define FUNC_NAME s_scm_search_path +static SCM +search_path (SCM path, SCM filename, SCM extensions, SCM require_exts, + struct stat *stat_buf) { struct stringbuf buf; char *filename_chars; size_t filename_len; SCM result = SCM_BOOL_F; - if (SCM_UNBNDP (extensions)) - extensions = SCM_EOL; - - if (SCM_UNBNDP (require_exts)) - require_exts = SCM_BOOL_F; + if (scm_ilength (path) < 0) + scm_misc_error ("%search-path", "path is not a proper list: ~a", + scm_list_1 (path)); + if (scm_ilength (extensions) < 0) + scm_misc_error ("%search-path", "bad extensions list: ~a", + scm_list_1 (extensions)); scm_dynwind_begin (0); @@ -497,7 +534,6 @@ SCM_DEFINE (scm_search_path, "search-path", 2, 2, 0, for (exts = extensions; scm_is_pair (exts); exts = SCM_CDR (exts)) { SCM ext = SCM_CAR (exts); - struct stat mode; buf.ptr = buf.buf + sans_ext_len; stringbuf_cat_locale_string (&buf, ext); @@ -505,8 +541,8 @@ SCM_DEFINE (scm_search_path, "search-path", 2, 2, 0, /* If the file exists at all, we should return it. If the file is inaccessible, then that's an error. */ - if (stat (buf.buf, &mode) == 0 - && ! (mode.st_mode & S_IFDIR)) + if (stat (buf.buf, stat_buf) == 0 + && ! (stat_buf->st_mode & S_IFDIR)) { result = scm_from_locale_string (buf.buf); goto end; @@ -524,6 +560,62 @@ SCM_DEFINE (scm_search_path, "search-path", 2, 2, 0, scm_dynwind_end (); return result; } + +SCM_DEFINE (scm_search_path, "search-path", 2, 0, 1, + (SCM path, SCM filename, SCM rest), + "Search @var{path} for a directory containing a file named\n" + "@var{filename}. The file must be readable, and not a directory.\n" + "If we find one, return its full filename; otherwise, return\n" + "@code{#f}. If @var{filename} is absolute, return it unchanged.\n" + "If given, @var{extensions} is a list of strings; for each\n" + "directory in @var{path}, we search for @var{filename}\n" + "concatenated with each @var{extension}.") +#define FUNC_NAME s_scm_search_path +{ + SCM extensions, require_exts; + struct stat stat_buf; + + if (SCM_UNBNDP (rest) || scm_is_null (rest)) + { + /* Called either by Scheme code that didn't provide the optional + arguments, or C code that used the Guile 1.8 signature (2 required, + 1 optional arg) and passed '() or nothing as the EXTENSIONS + argument. */ + extensions = SCM_EOL; + require_exts = SCM_UNDEFINED; + } + else + { + if (scm_is_null (SCM_CAR (rest)) || scm_is_pair (SCM_CAR (rest))) + { + /* Called by Scheme code written for 1.9. */ + extensions = SCM_CAR (rest); + if (scm_is_null (SCM_CDR (rest))) + require_exts = SCM_UNDEFINED; + else + { + require_exts = SCM_CADR (rest); + if (SCM_UNLIKELY (!scm_is_null (SCM_CDDR (rest)))) + scm_wrong_num_args (scm_from_locale_string (FUNC_NAME)); + } + } + else + { + /* Called by C code that uses the 1.8 signature, i.e., which + expects the 3rd argument to be EXTENSIONS. */ + extensions = rest; + require_exts = SCM_UNDEFINED; + } + } + + if (SCM_UNBNDP (extensions)) + extensions = SCM_EOL; + + if (SCM_UNBNDP (require_exts)) + require_exts = SCM_BOOL_F; + + return search_path (path, filename, extensions, require_exts, &stat_buf); +} #undef FUNC_NAME @@ -542,123 +634,184 @@ SCM_DEFINE (scm_sys_search_load_path, "%search-load-path", 1, 0, 0, "will try each extension automatically.") #define FUNC_NAME s_scm_sys_search_load_path { - SCM path = *scm_loc_load_path; - SCM exts = *scm_loc_load_extensions; + struct stat stat_buf; + SCM_VALIDATE_STRING (1, filename); - if (scm_ilength (path) < 0) - SCM_MISC_ERROR ("%load-path is not a proper list", SCM_EOL); - if (scm_ilength (exts) < 0) - SCM_MISC_ERROR ("%load-extension list is not a proper list", SCM_EOL); - return scm_search_path (path, filename, exts, SCM_UNDEFINED); + return search_path (*scm_loc_load_path, filename, *scm_loc_load_extensions, + SCM_BOOL_F, &stat_buf); } #undef FUNC_NAME +/* Return true if COMPILED_FILENAME is newer than source file + FULL_FILENAME, false otherwise. */ static int -compiled_is_newer (SCM full_filename, SCM compiled_filename) +compiled_is_fresh (SCM full_filename, SCM compiled_filename, + struct stat *stat_source, struct stat *stat_compiled) { - char *source, *compiled; - struct stat stat_source, stat_compiled; - int res; - - 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 - && stat_source.st_mtime <= stat_compiled.st_mtime) - { - res = 1; - } + int compiled_is_newer; + 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 { - 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 ()); - res = 0; + compiled_is_newer = 0; + scm_puts_unlocked (";;; note: source file ", scm_current_error_port ()); + scm_display (full_filename, scm_current_error_port ()); + scm_puts_unlocked ("\n;;; newer than compiled ", scm_current_error_port ()); + scm_display (compiled_filename, scm_current_error_port ()); + scm_puts_unlocked ("\n", scm_current_error_port ()); } - free (source); - free (compiled); - return res; + return compiled_is_newer; } +SCM_KEYWORD (kw_env, "env"); +SCM_KEYWORD (kw_opts, "opts"); + +SCM_SYMBOL (sym_compile_file, "compile-file"); +SCM_SYMBOL (sym_auto_compilation_options, "%auto-compilation-options"); + static SCM -do_try_autocompile (void *data) +do_try_auto_compile (void *data) { - SCM source = PTR2SCM (data); + SCM source = SCM_PACK_POINTER (data); SCM comp_mod, compile_file; - scm_puts (";;; compiling ", scm_current_error_port ()); + scm_puts_unlocked (";;; 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_locale_symbol ("compile-file")); + compile_file = scm_module_variable (comp_mod, sym_compile_file); if (scm_is_true (compile_file)) { - SCM res = scm_call_1 (scm_variable_ref (compile_file), source); - scm_puts (";;; compiled ", scm_current_error_port ()); + /* Auto-compile in the context of the current module. */ + SCM res, opts; + SCM args[5]; + + opts = scm_module_variable (scm_the_root_module (), + sym_auto_compilation_options); + if (SCM_VARIABLEP (opts)) + opts = SCM_VARIABLE_REF (opts); + else + opts = SCM_EOL; + + args[0] = source; + args[1] = kw_opts; + args[2] = opts; + args[3] = kw_env; + args[4] = scm_current_module (); + + /* Assume `*current-warning-prefix*' has an appropriate value. */ + res = scm_call_n (scm_variable_ref (compile_file), args, 5); + + scm_puts_unlocked (";;; 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_puts_unlocked (";;; it seems ", scm_current_error_port ()); scm_display (source, scm_current_error_port ()); - scm_puts ("\n;;; is part of the compiler; skipping autocompilation\n", + scm_puts_unlocked ("\n;;; is part of the compiler; skipping auto-compilation\n", scm_current_error_port ()); return SCM_BOOL_F; } } static SCM -autocompile_catch_handler (void *data, SCM tag, SCM throw_args) +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 source = SCM_PACK_POINTER (data); + SCM oport, lines; + + oport = scm_open_output_string (); + scm_print_exception (oport, SCM_BOOL_F, tag, throw_args); + + scm_puts_unlocked (";;; 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 ()); + scm_puts_unlocked (" failed:\n", scm_current_error_port ()); + + lines = scm_string_split (scm_get_output_string (oport), + SCM_MAKE_CHAR ('\n')); + for (; scm_is_pair (lines); lines = scm_cdr (lines)) + if (scm_c_string_length (scm_car (lines))) + { + scm_puts_unlocked (";;; ", scm_current_error_port ()); + scm_display (scm_car (lines), scm_current_error_port ()); + scm_newline (scm_current_error_port ()); + } + + scm_close_port (oport); + return SCM_BOOL_F; } -static SCM -scm_try_autocompile (SCM source) +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 (scm_is_false (*scm_loc_load_should_autocompile)) - return SCM_BOOL_F; if (!message_shown) { - scm_puts (";;; note: autocompilation is enabled, set GUILE_AUTO_COMPILE=0\n" - ";;; or pass the --no-autocompile argument to disable.\n", + scm_puts_unlocked (";;; 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_autocompile, - SCM2PTR (source), - autocompile_catch_handler, - SCM2PTR (source), + do_try_auto_compile, + SCM_UNPACK_POINTER (source), + auto_compile_catch_handler, + SCM_UNPACK_POINTER (source), NULL, NULL); } -SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 1, 1, 0, - (SCM filename, SCM exception_on_not_found), +/* See also (system base compile):compiled-file-name. */ +static SCM +canonical_suffix (SCM fname) +{ + SCM canon; + size_t len; + + canon = scm_canonicalize_path (fname); + len = scm_c_string_length (canon); + + if (len > 1 && scm_is_eq (scm_c_string_ref (canon, 0), SCM_MAKE_CHAR ('/'))) + return canon; + else if (len > 2 && scm_is_eq (scm_c_string_ref (canon, 1), SCM_MAKE_CHAR (':'))) + return scm_string_append (scm_list_3 (scm_from_latin1_string ("/"), + scm_c_substring (canon, 0, 1), + scm_c_substring (canon, 2, len))); + else + return canon; +} + +SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 0, 0, 1, + (SCM args), "Search @var{%load-path} for the file named @var{filename} and\n" "load it into the top-level environment. If @var{filename} is a\n" "relative pathname and is not found in the list of search paths,\n" @@ -667,33 +820,73 @@ SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 1, 1, 0, "@code{#f} is returned instead.") #define FUNC_NAME s_scm_primitive_load_path { + SCM filename, exception_on_not_found; SCM full_filename, compiled_filename; int compiled_is_fallback = 0; + SCM hook = *scm_loc_load_hook; + struct stat stat_source, stat_compiled; + + if (scm_is_true (hook) && scm_is_false (scm_procedure_p (hook))) + SCM_MISC_ERROR ("value of %load-hook is neither a procedure nor #f", + SCM_EOL); + + if (scm_is_string (args)) + { + /* C code written for 1.8 and earlier expects this function to take a + single argument (the file name). */ + filename = args; + exception_on_not_found = SCM_UNDEFINED; + } + else + { + /* Starting from 1.9, this function takes 1 required and 1 optional + argument. */ + long len; + + SCM_VALIDATE_LIST_COPYLEN (SCM_ARG1, args, len); + if (len < 1 || len > 2) + scm_error_num_args_subr (FUNC_NAME); + + filename = SCM_CAR (args); + SCM_VALIDATE_STRING (SCM_ARG1, filename); + + exception_on_not_found = len > 1 ? SCM_CADR (args) : SCM_UNDEFINED; + } if (SCM_UNBNDP (exception_on_not_found)) exception_on_not_found = SCM_BOOL_T; - full_filename = scm_sys_search_load_path (filename); - compiled_filename = scm_search_path (*scm_loc_load_compiled_path, - filename, - *scm_loc_load_compiled_extensions, - SCM_BOOL_T); - + full_filename = search_path (*scm_loc_load_path, filename, + *scm_loc_load_extensions, SCM_BOOL_F, + &stat_source); + + compiled_filename = + search_path (*scm_loc_load_compiled_path, filename, + *scm_loc_load_compiled_extensions, SCM_BOOL_T, + &stat_compiled); + if (scm_is_false (compiled_filename) && scm_is_true (full_filename) && scm_is_true (*scm_loc_compile_fallback_path) + && scm_is_false (*scm_loc_fresh_auto_compile) && scm_is_pair (*scm_loc_load_compiled_extensions) && scm_is_string (scm_car (*scm_loc_load_compiled_extensions))) { - SCM fallback = scm_string_append + SCM fallback; + char *fallback_chars; + + fallback = scm_string_append (scm_list_3 (*scm_loc_compile_fallback_path, - full_filename, + canonical_suffix (full_filename), scm_car (*scm_loc_load_compiled_extensions))); - if (scm_is_true (scm_stat (fallback, SCM_BOOL_F))) + + fallback_chars = scm_to_locale_string (fallback); + if (stat (fallback_chars, &stat_compiled) == 0) { compiled_filename = fallback; compiled_is_fallback = 1; } + free (fallback_chars); } if (scm_is_false (full_filename) && scm_is_false (compiled_filename)) @@ -705,9 +898,14 @@ SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 1, 1, 0, return SCM_BOOL_F; } + if (!scm_is_false (hook)) + scm_call_1 (hook, (scm_is_true (full_filename) + ? full_filename : compiled_filename)); + if (scm_is_false (full_filename) || (scm_is_true (compiled_filename) - && compiled_is_newer (full_filename, compiled_filename))) + && compiled_is_fresh (full_filename, compiled_filename, + &stat_source, &stat_compiled))) return scm_load_compiled_with_vm (compiled_filename); /* Perhaps there was the installed .go that was stale, but our fallback is @@ -715,26 +913,36 @@ SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 1, 1, 0, if (!compiled_is_fallback && scm_is_true (*scm_loc_compile_fallback_path) + && scm_is_false (*scm_loc_fresh_auto_compile) && scm_is_pair (*scm_loc_load_compiled_extensions) && scm_is_string (scm_car (*scm_loc_load_compiled_extensions))) { - SCM fallback = scm_string_append + SCM fallback; + char *fallback_chars; + int stat_ret; + + fallback = scm_string_append (scm_list_3 (*scm_loc_compile_fallback_path, - full_filename, + canonical_suffix (full_filename), scm_car (*scm_loc_load_compiled_extensions))); - if (scm_is_true (scm_stat (fallback, SCM_BOOL_F)) - && compiled_is_newer (full_filename, fallback)) + + fallback_chars = scm_to_locale_string (fallback); + stat_ret = stat (fallback_chars, &stat_compiled); + free (fallback_chars); + + if (stat_ret == 0 && compiled_is_fresh (full_filename, fallback, + &stat_source, &stat_compiled)) { - scm_puts (";;; found fresh local cache at ", scm_current_error_port ()); + scm_puts_unlocked (";;; found fresh local cache at ", scm_current_error_port ()); scm_display (fallback, scm_current_error_port ()); scm_newline (scm_current_error_port ()); - return scm_load_compiled_with_vm (compiled_filename); + return scm_load_compiled_with_vm (fallback); } } /* Otherwise, we bottom out here. */ { - SCM freshly_compiled = scm_try_autocompile (full_filename); + SCM freshly_compiled = scm_try_auto_compile (full_filename); if (scm_is_true (freshly_compiled)) return scm_load_compiled_with_vm (freshly_compiled); @@ -747,13 +955,38 @@ SCM_DEFINE (scm_primitive_load_path, "primitive-load-path", 1, 1, 0, SCM scm_c_primitive_load_path (const char *filename) { - return scm_primitive_load_path (scm_from_locale_string (filename), - SCM_BOOL_T); + return scm_primitive_load_path (scm_from_locale_string (filename)); +} + +void +scm_init_eval_in_scheme (void) +{ + SCM eval_scm, eval_go; + struct stat stat_source, stat_compiled; + + eval_scm = search_path (*scm_loc_load_path, + scm_from_locale_string ("ice-9/eval.scm"), + SCM_EOL, SCM_BOOL_F, &stat_source); + eval_go = search_path (*scm_loc_load_compiled_path, + scm_from_locale_string ("ice-9/eval.go"), + SCM_EOL, SCM_BOOL_F, &stat_compiled); + + if (scm_is_true (eval_scm) && scm_is_true (eval_go) + && compiled_is_fresh (eval_scm, eval_go, + &stat_source, &stat_compiled)) + scm_load_compiled_with_vm (eval_go); + else + /* if we have no eval.go, we shouldn't load any compiled code at all */ + *scm_loc_load_compiled_path = SCM_EOL; } /* Information about the build environment. */ +SCM_VARIABLE_INIT (sys_host_type, "%host-type", + scm_from_locale_string (HOST_TYPE)); + + /* Initialize the scheme variable %guile-build-info, based on data provided by the Makefile, via libpath.h. */ static void @@ -765,17 +998,32 @@ init_build_info () for (i = 0; i < (sizeof (info) / sizeof (info[0])); i++) { - SCM key = scm_from_locale_symbol (info[i].name); + SCM key = scm_from_utf8_symbol (info[i].name); SCM val = scm_from_locale_string (info[i].value); *loc = scm_acons (key, val, *loc); } +#ifdef PACKAGE_PACKAGER + *loc = scm_acons (scm_from_latin1_symbol ("packager"), + scm_from_latin1_string (PACKAGE_PACKAGER), + *loc); +#endif +#ifdef PACKAGE_PACKAGER_VERSION + *loc = scm_acons (scm_from_latin1_symbol ("packager-version"), + scm_from_latin1_string (PACKAGE_PACKAGER_VERSION), + *loc); +#endif +#ifdef PACKAGE_PACKAGER_BUG_REPORTS + *loc = scm_acons (scm_from_latin1_symbol ("packager-bug-reports"), + scm_from_latin1_string (PACKAGE_PACKAGER_BUG_REPORTS), + *loc); +#endif } void scm_init_load () { - scm_listofnullstr = scm_permanent_object (scm_list_1 (scm_nullstr)); + scm_listofnullstr = scm_list_1 (scm_nullstr); scm_loc_load_path = SCM_VARIABLE_LOC (scm_c_define ("%load-path", SCM_EOL)); scm_loc_load_extensions = SCM_VARIABLE_LOC (scm_c_define ("%load-extensions", @@ -790,20 +1038,48 @@ scm_init_load () scm_loc_compile_fallback_path = SCM_VARIABLE_LOC (scm_c_define ("%compile-fallback-path", SCM_BOOL_F)); + scm_loc_load_should_auto_compile + = SCM_VARIABLE_LOC (scm_c_define ("%load-should-auto-compile", SCM_BOOL_F)); + scm_loc_fresh_auto_compile + = SCM_VARIABLE_LOC (scm_c_define ("%fresh-auto-compile", SCM_BOOL_F)); - scm_loc_load_should_autocompile - = SCM_VARIABLE_LOC (scm_c_define ("%load-should-autocompile", SCM_BOOL_F)); - - the_reader = scm_make_fluid (); - the_reader_fluid_num = SCM_FLUID_NUM (the_reader); - SCM_FAST_FLUID_SET_X (the_reader_fluid_num, SCM_BOOL_F); + the_reader = scm_make_fluid_with_default (SCM_BOOL_F); scm_c_define("current-reader", the_reader); + scm_c_define ("load-compiled", + scm_c_make_gsubr ("load-compiled/vm", 1, 0, 0, + scm_load_compiled_with_vm)); + init_build_info (); #include "libguile/load.x" } +void +scm_init_load_should_auto_compile () +{ + char *auto_compile = getenv ("GUILE_AUTO_COMPILE"); + + if (auto_compile && strcmp (auto_compile, "0") == 0) + { + *scm_loc_load_should_auto_compile = SCM_BOOL_F; + *scm_loc_fresh_auto_compile = SCM_BOOL_F; + } + /* Allow "freshen" also. */ + else if (auto_compile && strncmp (auto_compile, "fresh", 5) == 0) + { + *scm_loc_load_should_auto_compile = SCM_BOOL_T; + *scm_loc_fresh_auto_compile = SCM_BOOL_T; + } + else + { + *scm_loc_load_should_auto_compile = SCM_BOOL_T; + *scm_loc_fresh_auto_compile = SCM_BOOL_F; + } +} + + + /* Local Variables: c-file-style: "gnu"