1 /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2004, 2006 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include "libguile/_scm.h"
29 #include "libguile/libpath.h"
30 #include "libguile/fports.h"
31 #include "libguile/read.h"
32 #include "libguile/eval.h"
33 #include "libguile/throw.h"
34 #include "libguile/alist.h"
35 #include "libguile/dynwind.h"
36 #include "libguile/root.h"
37 #include "libguile/strings.h"
38 #include "libguile/modules.h"
39 #include "libguile/lang.h"
40 #include "libguile/chars.h"
41 #include "libguile/srfi-13.h"
43 #include "libguile/validate.h"
44 #include "libguile/load.h"
45 #include "libguile/fluids.h"
47 #include "libguile/vm.h" /* for load-compiled/vm */
49 #include <sys/types.h>
54 #endif /* HAVE_UNISTD_H */
58 #endif /* HAVE_PWD_H */
65 /* Loading a file, given an absolute filename. */
67 /* Hook to run when we load a file, perhaps to announce the fact somewhere.
68 Applied to the full name of the file. */
69 static SCM
*scm_loc_load_hook
;
71 /* The current reader (a fluid). */
72 static SCM the_reader
= SCM_BOOL_F
;
73 static size_t the_reader_fluid_num
= 0;
75 SCM_DEFINE (scm_primitive_load
, "primitive-load", 1, 0, 0,
77 "Load the file named @var{filename} and evaluate its contents in\n"
78 "the top-level environment. The load paths are not searched;\n"
79 "@var{filename} must either be a full pathname or be a pathname\n"
80 "relative to the current directory. If the variable\n"
81 "@code{%load-hook} is defined, it should be bound to a procedure\n"
82 "that will be called before any code is loaded. See the\n"
83 "documentation for @code{%load-hook} later in this section.")
84 #define FUNC_NAME s_scm_primitive_load
86 SCM hook
= *scm_loc_load_hook
;
87 SCM_VALIDATE_STRING (1, filename
);
88 if (scm_is_true (hook
) && scm_is_false (scm_procedure_p (hook
)))
89 SCM_MISC_ERROR ("value of %load-hook is neither a procedure nor #f",
92 if (!scm_is_false (hook
))
93 scm_call_1 (hook
, filename
);
96 SCM port
= scm_open_file (filename
, scm_from_locale_string ("r"));
97 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE
);
98 scm_i_dynwind_current_load_port (port
);
104 /* Lookup and use the current reader to read the next
106 reader
= SCM_FAST_FLUID_REF (the_reader_fluid_num
);
107 if (reader
== SCM_BOOL_F
)
108 form
= scm_read (port
);
110 form
= scm_call_1 (reader
, port
);
112 if (SCM_EOF_OBJECT_P (form
))
115 scm_primitive_eval_x (form
);
119 scm_close_port (port
);
121 return SCM_UNSPECIFIED
;
126 scm_c_primitive_load (const char *filename
)
128 return scm_primitive_load (scm_from_locale_string (filename
));
132 /* Builtin path to scheme library files. */
133 #ifdef SCM_PKGDATA_DIR
134 SCM_DEFINE (scm_sys_package_data_dir
, "%package-data-dir", 0, 0, 0,
136 "Return the name of the directory where Scheme packages, modules and\n"
137 "libraries are kept. On most Unix systems, this will be\n"
138 "@samp{/usr/local/share/guile}.")
139 #define FUNC_NAME s_scm_sys_package_data_dir
141 return scm_from_locale_string (SCM_PKGDATA_DIR
);
144 #endif /* SCM_PKGDATA_DIR */
146 #ifdef SCM_LIBRARY_DIR
147 SCM_DEFINE (scm_sys_library_dir
, "%library-dir", 0,0,0,
149 "Return the directory where the Guile Scheme library files are installed.\n"
150 "E.g., may return \"/usr/share/guile/1.3.5\".")
151 #define FUNC_NAME s_scm_sys_library_dir
153 return scm_from_locale_string (SCM_LIBRARY_DIR
);
156 #endif /* SCM_LIBRARY_DIR */
159 SCM_DEFINE (scm_sys_site_dir
, "%site-dir", 0,0,0,
161 "Return the directory where the Guile site files are installed.\n"
162 "E.g., may return \"/usr/share/guile/site\".")
163 #define FUNC_NAME s_scm_sys_site_dir
165 return scm_from_locale_string (SCM_SITE_DIR
);
168 #endif /* SCM_SITE_DIR */
173 /* Initializing the load path, and searching it. */
175 /* List of names of directories we search for files to load. */
176 static SCM
*scm_loc_load_path
;
178 /* List of extensions we try adding to the filenames. */
179 static SCM
*scm_loc_load_extensions
;
181 /* Like %load-path and %load-extensions, but for compiled files. */
182 static SCM
*scm_loc_load_compiled_path
;
183 static SCM
*scm_loc_load_compiled_extensions
;
185 /* Whether we should try to auto-compile. */
186 static SCM
*scm_loc_load_should_autocompile
;
188 /* The fallback path for autocompilation */
189 static SCM
*scm_loc_compile_fallback_path
;
191 SCM_DEFINE (scm_parse_path
, "parse-path", 1, 1, 0,
192 (SCM path
, SCM tail
),
193 "Parse @var{path}, which is expected to be a colon-separated\n"
194 "string, into a list and return the resulting list with\n"
195 "@var{tail} appended. If @var{path} is @code{#f}, @var{tail}\n"
197 #define FUNC_NAME s_scm_parse_path
200 SCM sep
= SCM_MAKE_CHAR (';');
202 SCM sep
= SCM_MAKE_CHAR (':');
205 if (SCM_UNBNDP (tail
))
207 return (scm_is_false (path
)
209 : scm_append_x (scm_list_2 (scm_string_split (path
, sep
), tail
)));
214 /* Initialize the global variable %load-path, given the value of the
215 SCM_SITE_DIR and SCM_LIBRARY_DIR preprocessor symbols and the
216 GUILE_LOAD_PATH environment variable. */
218 scm_init_load_path ()
224 #ifdef SCM_LIBRARY_DIR
225 env
= getenv ("GUILE_SYSTEM_PATH");
226 if (env
&& strcmp (env
, "") == 0)
227 /* special-case interpret system-path=="" as meaning no system path instead
231 path
= scm_parse_path (scm_from_locale_string (env
), path
);
233 path
= scm_list_3 (scm_from_locale_string (SCM_SITE_DIR
),
234 scm_from_locale_string (SCM_LIBRARY_DIR
),
235 scm_from_locale_string (SCM_PKGDATA_DIR
));
237 env
= getenv ("GUILE_SYSTEM_COMPILED_PATH");
238 if (env
&& strcmp (env
, "") == 0)
242 cpath
= scm_parse_path (scm_from_locale_string (env
), cpath
);
245 /* the idea: if GUILE_SYSTEM_COMPILED_PATH is set, then it seems we're working
246 against an uninstalled Guile, in which case we shouldn't be autocompiling,
247 otherwise offer up the user's home directory as penance for not having
248 up-to-date .go files. */
251 home
= getenv ("HOME");
256 pwd
= getpwuid (getuid ());
260 #endif /* HAVE_GETPWENT */
263 snprintf (buf
, sizeof(buf
),
264 "%s/.guile-ccache/" SCM_EFFECTIVE_VERSION
, home
);
265 *scm_loc_compile_fallback_path
= scm_from_locale_string (buf
);
268 cpath
= scm_cons (scm_from_locale_string (SCM_CCACHE_DIR
), cpath
);
270 #endif /* SCM_LIBRARY_DIR */
272 env
= getenv ("GUILE_LOAD_PATH");
274 path
= scm_parse_path (scm_from_locale_string (env
), path
);
276 env
= getenv ("GUILE_LOAD_COMPILED_PATH");
278 cpath
= scm_parse_path (scm_from_locale_string (env
), cpath
);
280 *scm_loc_load_path
= path
;
281 *scm_loc_load_compiled_path
= cpath
;
284 SCM scm_listofnullstr
;
286 /* Utility functions for assembling C strings in a buffer.
295 stringbuf_free (void *data
)
297 struct stringbuf
*buf
= (struct stringbuf
*)data
;
302 stringbuf_grow (struct stringbuf
*buf
)
304 size_t ptroff
= buf
->ptr
- buf
->buf
;
306 buf
->buf
= scm_realloc (buf
->buf
, buf
->buf_len
);
307 buf
->ptr
= buf
->buf
+ ptroff
;
311 stringbuf_cat_locale_string (struct stringbuf
*buf
, SCM str
)
313 size_t max_len
= buf
->buf_len
- (buf
->ptr
- buf
->buf
) - 1;
314 size_t len
= scm_to_locale_stringbuf (str
, buf
->ptr
, max_len
);
317 /* buffer is too small, double its size and try again.
319 stringbuf_grow (buf
);
320 stringbuf_cat_locale_string (buf
, str
);
324 /* string fits, terminate it and check for embedded '\0'.
326 buf
->ptr
[len
] = '\0';
327 if (strlen (buf
->ptr
) != len
)
328 scm_misc_error (NULL
,
329 "string contains #\\nul character: ~S",
336 stringbuf_cat (struct stringbuf
*buf
, char *str
)
338 size_t max_len
= buf
->buf_len
- (buf
->ptr
- buf
->buf
) - 1;
339 size_t len
= strlen (str
);
342 /* buffer is too small, double its size and try again.
344 stringbuf_grow (buf
);
345 stringbuf_cat (buf
, str
);
349 /* string fits, copy it into buffer.
351 strcpy (buf
->ptr
, str
);
358 scm_c_string_has_an_ext (char *str
, size_t len
, SCM extensions
)
360 for (; !scm_is_null (extensions
); extensions
= SCM_CDR (extensions
))
365 ext
= scm_to_locale_string (SCM_CAR (extensions
));
366 extlen
= strlen (ext
);
367 match
= (len
> extlen
&& str
[len
- extlen
- 1] == '.'
368 && strncmp (str
+ (len
- extlen
), ext
, extlen
) == 0);
376 /* Search PATH for a directory containing a file named FILENAME.
377 The file must be readable, and not a directory.
378 If we find one, return its full filename; otherwise, return #f.
379 If FILENAME is absolute, return it unchanged.
380 If given, EXTENSIONS is a list of strings; for each directory
381 in PATH, we search for FILENAME concatenated with each EXTENSION. */
382 SCM_DEFINE (scm_search_path
, "search-path", 2, 2, 0,
383 (SCM path
, SCM filename
, SCM extensions
, SCM require_exts
),
384 "Search @var{path} for a directory containing a file named\n"
385 "@var{filename}. The file must be readable, and not a directory.\n"
386 "If we find one, return its full filename; otherwise, return\n"
387 "@code{#f}. If @var{filename} is absolute, return it unchanged.\n"
388 "If given, @var{extensions} is a list of strings; for each\n"
389 "directory in @var{path}, we search for @var{filename}\n"
390 "concatenated with each @var{extension}.")
391 #define FUNC_NAME s_scm_search_path
393 struct stringbuf buf
;
394 char *filename_chars
;
396 SCM result
= SCM_BOOL_F
;
398 if (SCM_UNBNDP (extensions
))
399 extensions
= SCM_EOL
;
401 if (SCM_UNBNDP (require_exts
))
402 require_exts
= SCM_BOOL_F
;
404 scm_dynwind_begin (0);
406 filename_chars
= scm_to_locale_string (filename
);
407 filename_len
= strlen (filename_chars
);
408 scm_dynwind_free (filename_chars
);
410 /* If FILENAME is absolute, return it unchanged. */
412 if (((filename_len
>= 1) &&
413 (filename_chars
[0] == '/' || filename_chars
[0] == '\\')) ||
414 ((filename_len
>= 3) && filename_chars
[1] == ':' &&
415 ((filename_chars
[0] >= 'a' && filename_chars
[0] <= 'z') ||
416 (filename_chars
[0] >= 'A' && filename_chars
[0] <= 'Z')) &&
417 (filename_chars
[2] == '/' || filename_chars
[2] == '\\')))
419 if (filename_len
>= 1 && filename_chars
[0] == '/')
423 if (scm_is_true (require_exts
) &&
424 !scm_c_string_has_an_ext (filename_chars
, filename_len
,
432 /* If FILENAME has an extension, don't try to add EXTENSIONS to it. */
436 for (endp
= filename_chars
+ filename_len
- 1;
437 endp
>= filename_chars
;
442 if (scm_is_true (require_exts
) &&
443 !scm_c_string_has_an_ext (filename_chars
, filename_len
,
446 /* This filename has an extension, but not one of the right
451 /* This filename already has an extension, so cancel the
452 list of extensions. */
453 extensions
= SCM_EOL
;
457 else if (*endp
== '/' || *endp
== '\\')
459 else if (*endp
== '/')
461 /* This filename has no extension, so keep the current list
467 /* This simplifies the loop below a bit.
469 if (scm_is_null (extensions
))
470 extensions
= scm_listofnullstr
;
473 buf
.buf
= scm_malloc (buf
.buf_len
);
474 scm_dynwind_unwind_handler (stringbuf_free
, &buf
, SCM_F_WIND_EXPLICITLY
);
476 /* Try every path element.
478 for (; scm_is_pair (path
); path
= SCM_CDR (path
))
480 SCM dir
= SCM_CAR (path
);
485 stringbuf_cat_locale_string (&buf
, dir
);
487 /* Concatenate the path name and the filename. */
490 if ((buf
.ptr
> buf
.buf
) && (buf
.ptr
[-1] != '/') && (buf
.ptr
[-1] != '\\'))
492 if ((buf
.ptr
> buf
.buf
) && (buf
.ptr
[-1] != '/'))
494 stringbuf_cat (&buf
, "/");
496 stringbuf_cat (&buf
, filename_chars
);
497 sans_ext_len
= buf
.ptr
- buf
.buf
;
499 /* Try every extension. */
500 for (exts
= extensions
; scm_is_pair (exts
); exts
= SCM_CDR (exts
))
502 SCM ext
= SCM_CAR (exts
);
505 buf
.ptr
= buf
.buf
+ sans_ext_len
;
506 stringbuf_cat_locale_string (&buf
, ext
);
508 /* If the file exists at all, we should return it. If the
509 file is inaccessible, then that's an error. */
511 if (stat (buf
.buf
, &mode
) == 0
512 && ! (mode
.st_mode
& S_IFDIR
))
514 result
= scm_from_locale_string (buf
.buf
);
519 if (!SCM_NULL_OR_NIL_P (exts
))
520 scm_wrong_type_arg_msg (NULL
, 0, extensions
, "proper list");
523 if (!SCM_NULL_OR_NIL_P (path
))
524 scm_wrong_type_arg_msg (NULL
, 0, path
, "proper list");
533 /* Search %load-path for a directory containing a file named FILENAME.
534 The file must be readable, and not a directory.
535 If we find one, return its full filename; otherwise, return #f.
536 If FILENAME is absolute, return it unchanged. */
537 SCM_DEFINE (scm_sys_search_load_path
, "%search-load-path", 1, 0, 0,
539 "Search @var{%load-path} for the file named @var{filename},\n"
540 "which must be readable by the current user. If @var{filename}\n"
541 "is found in the list of paths to search or is an absolute\n"
542 "pathname, return its full pathname. Otherwise, return\n"
543 "@code{#f}. Filenames may have any of the optional extensions\n"
544 "in the @code{%load-extensions} list; @code{%search-load-path}\n"
545 "will try each extension automatically.")
546 #define FUNC_NAME s_scm_sys_search_load_path
548 SCM path
= *scm_loc_load_path
;
549 SCM exts
= *scm_loc_load_extensions
;
550 SCM_VALIDATE_STRING (1, filename
);
552 if (scm_ilength (path
) < 0)
553 SCM_MISC_ERROR ("%load-path is not a proper list", SCM_EOL
);
554 if (scm_ilength (exts
) < 0)
555 SCM_MISC_ERROR ("%load-extension list is not a proper list", SCM_EOL
);
556 return scm_search_path (path
, filename
, exts
, SCM_UNDEFINED
);
562 compiled_is_newer (SCM full_filename
, SCM compiled_filename
)
564 char *source
, *compiled
;
565 struct stat stat_source
, stat_compiled
;
568 source
= scm_to_locale_string (full_filename
);
569 compiled
= scm_to_locale_string (compiled_filename
);
571 if (stat (source
, &stat_source
) == 0
572 && stat (compiled
, &stat_compiled
) == 0
573 && stat_source
.st_mtime
<= stat_compiled
.st_mtime
)
579 scm_puts (";;; note: source file ", scm_current_error_port ());
580 scm_puts (source
, scm_current_error_port ());
581 scm_puts ("\n;;; newer than compiled ", scm_current_error_port ());
582 scm_puts (compiled
, scm_current_error_port ());
583 scm_puts ("\n", scm_current_error_port ());
592 SCM_KEYWORD (k_output_file
, "output-file");
595 do_try_autocompile (void *data
)
597 SCM pair
= PTR2SCM (data
);
598 SCM comp_mod
, compile_file
, res
;
600 scm_puts (";;; compiling ", scm_current_error_port ());
601 scm_display (scm_car (pair
), scm_current_error_port ());
602 scm_newline (scm_current_error_port ());
604 comp_mod
= scm_c_resolve_module ("system base compile");
605 compile_file
= scm_c_module_lookup (comp_mod
, "compile-file");
606 res
= scm_call_3 (scm_variable_ref (compile_file
), scm_car (pair
),
607 k_output_file
, scm_cdr (pair
));
609 scm_puts (";;; compiled ", scm_current_error_port ());
610 scm_display (res
, scm_current_error_port ());
611 scm_newline (scm_current_error_port ());
617 autocompile_catch_handler (void *data
, SCM tag
, SCM throw_args
)
619 SCM pair
= PTR2SCM (data
);
620 scm_puts (";;; WARNING: compilation of ", scm_current_error_port ());
621 scm_display (scm_car (pair
), scm_current_error_port ());
622 scm_puts ("\n;;; to ", scm_current_error_port ());
623 scm_display (scm_cdr (pair
), scm_current_error_port ());
624 scm_puts (" failed:\n", scm_current_error_port ());
625 scm_puts (";;; key ", scm_current_error_port ());
626 scm_write (tag
, scm_current_error_port ());
627 scm_puts (", throw args ", scm_current_error_port ());
628 scm_write (throw_args
, scm_current_error_port ());
629 scm_newline (scm_current_error_port ());
634 scm_try_autocompile (SCM source
, SCM compiled
)
636 static int message_shown
= 0;
639 if (scm_is_false (*scm_loc_load_should_autocompile
))
644 scm_puts (";;; note: autocompilation is enabled, set GUILE_AUTO_COMPILE=0\n"
645 ";;; or pass the --no-autocompile argument to disable.\n",
646 scm_current_error_port ());
650 pair
= scm_cons (source
, compiled
);
651 return scm_c_catch (SCM_BOOL_T
,
654 autocompile_catch_handler
,
659 SCM_DEFINE (scm_primitive_load_path
, "primitive-load-path", 1, 1, 0,
660 (SCM filename
, SCM exception_on_not_found
),
661 "Search @var{%load-path} for the file named @var{filename} and\n"
662 "load it into the top-level environment. If @var{filename} is a\n"
663 "relative pathname and is not found in the list of search paths,\n"
664 "an error is signalled, unless the optional argument\n"
665 "@var{exception_on_not_found} is @code{#f}, in which case\n"
666 "@code{#f} is returned instead.")
667 #define FUNC_NAME s_scm_primitive_load_path
669 SCM full_filename
, compiled_filename
;
671 if (SCM_UNBNDP (exception_on_not_found
))
672 exception_on_not_found
= SCM_BOOL_T
;
674 full_filename
= scm_sys_search_load_path (filename
);
675 compiled_filename
= scm_search_path (*scm_loc_load_compiled_path
,
677 *scm_loc_load_compiled_extensions
,
680 if (scm_is_false (compiled_filename
)
681 && scm_is_true (full_filename
)
682 && scm_is_true (*scm_loc_compile_fallback_path
))
684 SCM comp_mod
, compiled_file_name
;
686 comp_mod
= scm_c_resolve_module ("system base compile");
688 scm_module_variable (comp_mod
,
689 scm_from_locale_symbol ("compiled-file-name"));
691 if (scm_is_false (compiled_file_name
))
693 scm_puts (";;; it seems ", scm_current_error_port ());
694 scm_display (full_filename
, scm_current_error_port ());
695 scm_puts ("\n;;; is part of the compiler; skipping autocompilation\n",
696 scm_current_error_port ());
700 /* very confusing var names ... */
701 compiled_filename
= scm_call_1 (scm_variable_ref (compiled_file_name
),
705 if (scm_is_false (full_filename
) && scm_is_false (compiled_filename
))
707 if (scm_is_true (exception_on_not_found
))
708 SCM_MISC_ERROR ("Unable to find file ~S in load path",
709 scm_list_1 (filename
));
714 if (scm_is_false (full_filename
)
715 || (scm_is_true (compiled_filename
)
716 && compiled_is_newer (full_filename
, compiled_filename
)))
717 return scm_load_compiled_with_vm (compiled_filename
);
719 if (scm_is_true (compiled_filename
))
720 compiled_filename
= scm_try_autocompile (full_filename
, compiled_filename
);
722 if (scm_is_true (compiled_filename
))
723 return scm_load_compiled_with_vm (compiled_filename
);
725 return scm_primitive_load (full_filename
);
730 scm_c_primitive_load_path (const char *filename
)
732 return scm_primitive_load_path (scm_from_locale_string (filename
),
737 /* Information about the build environment. */
739 /* Initialize the scheme variable %guile-build-info, based on data
740 provided by the Makefile, via libpath.h. */
744 static struct { char *name
; char *value
; } info
[] = SCM_BUILD_INFO
;
745 SCM
*loc
= SCM_VARIABLE_LOC (scm_c_define ("%guile-build-info", SCM_EOL
));
748 for (i
= 0; i
< (sizeof (info
) / sizeof (info
[0])); i
++)
750 SCM key
= scm_from_locale_symbol (info
[i
].name
);
751 SCM val
= scm_from_locale_string (info
[i
].value
);
752 *loc
= scm_acons (key
, val
, *loc
);
760 scm_listofnullstr
= scm_permanent_object (scm_list_1 (scm_nullstr
));
761 scm_loc_load_path
= SCM_VARIABLE_LOC (scm_c_define ("%load-path", SCM_EOL
));
762 scm_loc_load_extensions
763 = SCM_VARIABLE_LOC (scm_c_define ("%load-extensions",
764 scm_list_2 (scm_from_locale_string (".scm"),
766 scm_loc_load_compiled_path
767 = SCM_VARIABLE_LOC (scm_c_define ("%load-compiled-path", SCM_EOL
));
768 scm_loc_load_compiled_extensions
769 = SCM_VARIABLE_LOC (scm_c_define ("%load-compiled-extensions",
770 scm_list_1 (scm_from_locale_string (".go"))));
771 scm_loc_load_hook
= SCM_VARIABLE_LOC (scm_c_define ("%load-hook", SCM_BOOL_F
));
773 scm_loc_compile_fallback_path
774 = SCM_VARIABLE_LOC (scm_c_define ("%compile-fallback-path", SCM_BOOL_F
));
776 scm_loc_load_should_autocompile
777 = SCM_VARIABLE_LOC (scm_c_define ("%load-should-autocompile", SCM_BOOL_F
));
779 the_reader
= scm_make_fluid ();
780 the_reader_fluid_num
= SCM_FLUID_NUM (the_reader
);
781 SCM_FAST_FLUID_SET_X (the_reader_fluid_num
, SCM_BOOL_F
);
782 scm_c_define("current-reader", the_reader
);
786 #include "libguile/load.x"