further autocompilation tweaks
[bpt/guile.git] / libguile / load.c
1 /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2004, 2006 Free Software Foundation, Inc.
2 *
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.
7 *
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.
12 *
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
16 */
17
18
19 \f
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <string.h>
26 #include <stdio.h>
27
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"
42
43 #include "libguile/validate.h"
44 #include "libguile/load.h"
45 #include "libguile/fluids.h"
46
47 #include "libguile/vm.h" /* for load-compiled/vm */
48
49 #include <sys/types.h>
50 #include <sys/stat.h>
51
52 #ifdef HAVE_UNISTD_H
53 #include <unistd.h>
54 #endif /* HAVE_UNISTD_H */
55
56 #ifdef HAVE_PWD_H
57 #include <pwd.h>
58 #endif /* HAVE_PWD_H */
59
60 #ifndef R_OK
61 #define R_OK 4
62 #endif
63
64 \f
65 /* Loading a file, given an absolute filename. */
66
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;
70
71 /* The current reader (a fluid). */
72 static SCM the_reader = SCM_BOOL_F;
73 static size_t the_reader_fluid_num = 0;
74
75 SCM_DEFINE (scm_primitive_load, "primitive-load", 1, 0, 0,
76 (SCM filename),
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
85 {
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",
90 SCM_EOL);
91
92 if (!scm_is_false (hook))
93 scm_call_1 (hook, filename);
94
95 { /* scope */
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);
99
100 while (1)
101 {
102 SCM reader, form;
103
104 /* Lookup and use the current reader to read the next
105 expression. */
106 reader = SCM_FAST_FLUID_REF (the_reader_fluid_num);
107 if (reader == SCM_BOOL_F)
108 form = scm_read (port);
109 else
110 form = scm_call_1 (reader, port);
111
112 if (SCM_EOF_OBJECT_P (form))
113 break;
114
115 scm_primitive_eval_x (form);
116 }
117
118 scm_dynwind_end ();
119 scm_close_port (port);
120 }
121 return SCM_UNSPECIFIED;
122 }
123 #undef FUNC_NAME
124
125 SCM
126 scm_c_primitive_load (const char *filename)
127 {
128 return scm_primitive_load (scm_from_locale_string (filename));
129 }
130
131 \f
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,
135 (),
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
140 {
141 return scm_from_locale_string (SCM_PKGDATA_DIR);
142 }
143 #undef FUNC_NAME
144 #endif /* SCM_PKGDATA_DIR */
145
146 #ifdef SCM_LIBRARY_DIR
147 SCM_DEFINE (scm_sys_library_dir, "%library-dir", 0,0,0,
148 (),
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
152 {
153 return scm_from_locale_string (SCM_LIBRARY_DIR);
154 }
155 #undef FUNC_NAME
156 #endif /* SCM_LIBRARY_DIR */
157
158 #ifdef SCM_SITE_DIR
159 SCM_DEFINE (scm_sys_site_dir, "%site-dir", 0,0,0,
160 (),
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
164 {
165 return scm_from_locale_string (SCM_SITE_DIR);
166 }
167 #undef FUNC_NAME
168 #endif /* SCM_SITE_DIR */
169
170
171
172 \f
173 /* Initializing the load path, and searching it. */
174
175 /* List of names of directories we search for files to load. */
176 static SCM *scm_loc_load_path;
177
178 /* List of extensions we try adding to the filenames. */
179 static SCM *scm_loc_load_extensions;
180
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;
184
185 /* Whether we should try to auto-compile. */
186 static SCM *scm_loc_load_should_autocompile;
187
188 /* The fallback path for autocompilation */
189 static SCM *scm_loc_compile_fallback_path;
190
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"
196 "is returned.")
197 #define FUNC_NAME s_scm_parse_path
198 {
199 #ifdef __MINGW32__
200 SCM sep = SCM_MAKE_CHAR (';');
201 #else
202 SCM sep = SCM_MAKE_CHAR (':');
203 #endif
204
205 if (SCM_UNBNDP (tail))
206 tail = SCM_EOL;
207 return (scm_is_false (path)
208 ? tail
209 : scm_append_x (scm_list_2 (scm_string_split (path, sep), tail)));
210 }
211 #undef FUNC_NAME
212
213
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. */
217 void
218 scm_init_load_path ()
219 {
220 char *env;
221 SCM path = SCM_EOL;
222 SCM cpath = SCM_EOL;
223
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
228 of '("") */
229 ;
230 else if (env)
231 path = scm_parse_path (scm_from_locale_string (env), path);
232 else
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));
236
237 env = getenv ("GUILE_SYSTEM_COMPILED_PATH");
238 if (env && strcmp (env, "") == 0)
239 /* like above */
240 ;
241 else if (env)
242 cpath = scm_parse_path (scm_from_locale_string (env), cpath);
243 else
244 {
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. */
249 char *home;
250
251 home = getenv ("HOME");
252 #ifdef HAVE_GETPWENT
253 if (!home)
254 {
255 struct passwd *pwd;
256 pwd = getpwuid (getuid ());
257 if (pwd)
258 home = pwd->pw_dir;
259 }
260 #endif /* HAVE_GETPWENT */
261 if (home)
262 { char buf[1024];
263 snprintf (buf, sizeof(buf),
264 "%s/.guile-ccache/" SCM_EFFECTIVE_VERSION, home);
265 *scm_loc_compile_fallback_path = scm_from_locale_string (buf);
266 }
267
268 cpath = scm_cons (scm_from_locale_string (SCM_CCACHE_DIR), cpath);
269 }
270 #endif /* SCM_LIBRARY_DIR */
271
272 env = getenv ("GUILE_LOAD_PATH");
273 if (env)
274 path = scm_parse_path (scm_from_locale_string (env), path);
275
276 env = getenv ("GUILE_LOAD_COMPILED_PATH");
277 if (env)
278 cpath = scm_parse_path (scm_from_locale_string (env), cpath);
279
280 *scm_loc_load_path = path;
281 *scm_loc_load_compiled_path = cpath;
282 }
283
284 SCM scm_listofnullstr;
285
286 /* Utility functions for assembling C strings in a buffer.
287 */
288
289 struct stringbuf {
290 char *buf, *ptr;
291 size_t buf_len;
292 };
293
294 static void
295 stringbuf_free (void *data)
296 {
297 struct stringbuf *buf = (struct stringbuf *)data;
298 free (buf->buf);
299 }
300
301 static void
302 stringbuf_grow (struct stringbuf *buf)
303 {
304 size_t ptroff = buf->ptr - buf->buf;
305 buf->buf_len *= 2;
306 buf->buf = scm_realloc (buf->buf, buf->buf_len);
307 buf->ptr = buf->buf + ptroff;
308 }
309
310 static void
311 stringbuf_cat_locale_string (struct stringbuf *buf, SCM str)
312 {
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);
315 if (len > max_len)
316 {
317 /* buffer is too small, double its size and try again.
318 */
319 stringbuf_grow (buf);
320 stringbuf_cat_locale_string (buf, str);
321 }
322 else
323 {
324 /* string fits, terminate it and check for embedded '\0'.
325 */
326 buf->ptr[len] = '\0';
327 if (strlen (buf->ptr) != len)
328 scm_misc_error (NULL,
329 "string contains #\\nul character: ~S",
330 scm_list_1 (str));
331 buf->ptr += len;
332 }
333 }
334
335 static void
336 stringbuf_cat (struct stringbuf *buf, char *str)
337 {
338 size_t max_len = buf->buf_len - (buf->ptr - buf->buf) - 1;
339 size_t len = strlen (str);
340 if (len > max_len)
341 {
342 /* buffer is too small, double its size and try again.
343 */
344 stringbuf_grow (buf);
345 stringbuf_cat (buf, str);
346 }
347 else
348 {
349 /* string fits, copy it into buffer.
350 */
351 strcpy (buf->ptr, str);
352 buf->ptr += len;
353 }
354 }
355
356
357 static int
358 scm_c_string_has_an_ext (char *str, size_t len, SCM extensions)
359 {
360 for (; !scm_is_null (extensions); extensions = SCM_CDR (extensions))
361 {
362 char *ext;
363 size_t extlen;
364 int match;
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);
369 free (ext);
370 if (match)
371 return 1;
372 }
373 return 0;
374 }
375
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
392 {
393 struct stringbuf buf;
394 char *filename_chars;
395 size_t filename_len;
396 SCM result = SCM_BOOL_F;
397
398 if (SCM_UNBNDP (extensions))
399 extensions = SCM_EOL;
400
401 if (SCM_UNBNDP (require_exts))
402 require_exts = SCM_BOOL_F;
403
404 scm_dynwind_begin (0);
405
406 filename_chars = scm_to_locale_string (filename);
407 filename_len = strlen (filename_chars);
408 scm_dynwind_free (filename_chars);
409
410 /* If FILENAME is absolute, return it unchanged. */
411 #ifdef __MINGW32__
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] == '\\')))
418 #else
419 if (filename_len >= 1 && filename_chars[0] == '/')
420 #endif
421 {
422 SCM res = filename;
423 if (scm_is_true (require_exts) &&
424 !scm_c_string_has_an_ext (filename_chars, filename_len,
425 extensions))
426 res = SCM_BOOL_F;
427
428 scm_dynwind_end ();
429 return res;
430 }
431
432 /* If FILENAME has an extension, don't try to add EXTENSIONS to it. */
433 {
434 char *endp;
435
436 for (endp = filename_chars + filename_len - 1;
437 endp >= filename_chars;
438 endp--)
439 {
440 if (*endp == '.')
441 {
442 if (scm_is_true (require_exts) &&
443 !scm_c_string_has_an_ext (filename_chars, filename_len,
444 extensions))
445 {
446 /* This filename has an extension, but not one of the right
447 ones... */
448 scm_dynwind_end ();
449 return SCM_BOOL_F;
450 }
451 /* This filename already has an extension, so cancel the
452 list of extensions. */
453 extensions = SCM_EOL;
454 break;
455 }
456 #ifdef __MINGW32__
457 else if (*endp == '/' || *endp == '\\')
458 #else
459 else if (*endp == '/')
460 #endif
461 /* This filename has no extension, so keep the current list
462 of extensions. */
463 break;
464 }
465 }
466
467 /* This simplifies the loop below a bit.
468 */
469 if (scm_is_null (extensions))
470 extensions = scm_listofnullstr;
471
472 buf.buf_len = 512;
473 buf.buf = scm_malloc (buf.buf_len);
474 scm_dynwind_unwind_handler (stringbuf_free, &buf, SCM_F_WIND_EXPLICITLY);
475
476 /* Try every path element.
477 */
478 for (; scm_is_pair (path); path = SCM_CDR (path))
479 {
480 SCM dir = SCM_CAR (path);
481 SCM exts;
482 size_t sans_ext_len;
483
484 buf.ptr = buf.buf;
485 stringbuf_cat_locale_string (&buf, dir);
486
487 /* Concatenate the path name and the filename. */
488
489 #ifdef __MINGW32__
490 if ((buf.ptr > buf.buf) && (buf.ptr[-1] != '/') && (buf.ptr[-1] != '\\'))
491 #else
492 if ((buf.ptr > buf.buf) && (buf.ptr[-1] != '/'))
493 #endif
494 stringbuf_cat (&buf, "/");
495
496 stringbuf_cat (&buf, filename_chars);
497 sans_ext_len = buf.ptr - buf.buf;
498
499 /* Try every extension. */
500 for (exts = extensions; scm_is_pair (exts); exts = SCM_CDR (exts))
501 {
502 SCM ext = SCM_CAR (exts);
503 struct stat mode;
504
505 buf.ptr = buf.buf + sans_ext_len;
506 stringbuf_cat_locale_string (&buf, ext);
507
508 /* If the file exists at all, we should return it. If the
509 file is inaccessible, then that's an error. */
510
511 if (stat (buf.buf, &mode) == 0
512 && ! (mode.st_mode & S_IFDIR))
513 {
514 result = scm_from_locale_string (buf.buf);
515 goto end;
516 }
517 }
518
519 if (!SCM_NULL_OR_NIL_P (exts))
520 scm_wrong_type_arg_msg (NULL, 0, extensions, "proper list");
521 }
522
523 if (!SCM_NULL_OR_NIL_P (path))
524 scm_wrong_type_arg_msg (NULL, 0, path, "proper list");
525
526 end:
527 scm_dynwind_end ();
528 return result;
529 }
530 #undef FUNC_NAME
531
532
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,
538 (SCM filename),
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
547 {
548 SCM path = *scm_loc_load_path;
549 SCM exts = *scm_loc_load_extensions;
550 SCM_VALIDATE_STRING (1, filename);
551
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);
557 }
558 #undef FUNC_NAME
559
560
561 static int
562 compiled_is_newer (SCM full_filename, SCM compiled_filename)
563 {
564 char *source, *compiled;
565 struct stat stat_source, stat_compiled;
566 int res;
567
568 source = scm_to_locale_string (full_filename);
569 compiled = scm_to_locale_string (compiled_filename);
570
571 if (stat (source, &stat_source) == 0
572 && stat (compiled, &stat_compiled) == 0
573 && stat_source.st_mtime <= stat_compiled.st_mtime)
574 {
575 res = 1;
576 }
577 else
578 {
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 ());
584 res = 0;
585
586 }
587 free (source);
588 free (compiled);
589 return res;
590 }
591
592 SCM_KEYWORD (k_output_file, "output-file");
593
594 static SCM
595 do_try_autocompile (void *data)
596 {
597 SCM pair = PTR2SCM (data);
598 SCM comp_mod, compile_file, res;
599
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 ());
603
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));
608
609 scm_puts (";;; compiled ", scm_current_error_port ());
610 scm_display (res, scm_current_error_port ());
611 scm_newline (scm_current_error_port ());
612
613 return res;
614 }
615
616 static SCM
617 autocompile_catch_handler (void *data, SCM tag, SCM throw_args)
618 {
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 ());
630 return SCM_BOOL_F;
631 }
632
633 static SCM
634 scm_try_autocompile (SCM source, SCM compiled)
635 {
636 static int message_shown = 0;
637 SCM pair;
638
639 if (scm_is_false (*scm_loc_load_should_autocompile))
640 return SCM_BOOL_F;
641
642 if (!message_shown)
643 {
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 ());
647 message_shown = 1;
648 }
649
650 pair = scm_cons (source, compiled);
651 return scm_c_catch (SCM_BOOL_T,
652 do_try_autocompile,
653 SCM2PTR (pair),
654 autocompile_catch_handler,
655 SCM2PTR (pair),
656 NULL, NULL);
657 }
658
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
668 {
669 SCM full_filename, compiled_filename;
670
671 if (SCM_UNBNDP (exception_on_not_found))
672 exception_on_not_found = SCM_BOOL_T;
673
674 full_filename = scm_sys_search_load_path (filename);
675 compiled_filename = scm_search_path (*scm_loc_load_compiled_path,
676 filename,
677 *scm_loc_load_compiled_extensions,
678 SCM_BOOL_T);
679
680 if (scm_is_false (compiled_filename)
681 && scm_is_true (full_filename)
682 && scm_is_true (*scm_loc_compile_fallback_path))
683 {
684 SCM comp_mod, compiled_file_name;
685
686 comp_mod = scm_c_resolve_module ("system base compile");
687 compiled_file_name =
688 scm_module_variable (comp_mod,
689 scm_from_locale_symbol ("compiled-file-name"));
690
691 if (scm_is_false (compiled_file_name))
692 {
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 ());
697 return SCM_BOOL_F;
698 }
699
700 /* very confusing var names ... */
701 compiled_filename = scm_call_1 (scm_variable_ref (compiled_file_name),
702 full_filename);
703 }
704
705 if (scm_is_false (full_filename) && scm_is_false (compiled_filename))
706 {
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));
710 else
711 return SCM_BOOL_F;
712 }
713
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);
718
719 if (scm_is_true (compiled_filename))
720 compiled_filename = scm_try_autocompile (full_filename, compiled_filename);
721
722 if (scm_is_true (compiled_filename))
723 return scm_load_compiled_with_vm (compiled_filename);
724 else
725 return scm_primitive_load (full_filename);
726 }
727 #undef FUNC_NAME
728
729 SCM
730 scm_c_primitive_load_path (const char *filename)
731 {
732 return scm_primitive_load_path (scm_from_locale_string (filename),
733 SCM_BOOL_T);
734 }
735
736 \f
737 /* Information about the build environment. */
738
739 /* Initialize the scheme variable %guile-build-info, based on data
740 provided by the Makefile, via libpath.h. */
741 static void
742 init_build_info ()
743 {
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));
746 unsigned long i;
747
748 for (i = 0; i < (sizeof (info) / sizeof (info[0])); i++)
749 {
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);
753 }
754 }
755
756 \f
757 void
758 scm_init_load ()
759 {
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"),
765 scm_nullstr)));
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));
772
773 scm_loc_compile_fallback_path
774 = SCM_VARIABLE_LOC (scm_c_define ("%compile-fallback-path", SCM_BOOL_F));
775
776 scm_loc_load_should_autocompile
777 = SCM_VARIABLE_LOC (scm_c_define ("%load-should-autocompile", SCM_BOOL_F));
778
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);
783
784 init_build_info ();
785
786 #include "libguile/load.x"
787 }
788
789 /*
790 Local Variables:
791 c-file-style: "gnu"
792 End:
793 */