This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Guile 1.3 Bug Fix


I found and fixed a bug in Guile 1.3; the description of the bug and the fix
follow.

The basic problem is that the Guile init/boot code is not called until the
repl-loop is started.  So, if you are using the gh interface and have started
some code via gh_enter, any scheme commands that you execute or load cannot use
things like "load" "defmacro" etcetera.  This was not the case with Guile 1.2. 
Here is a minimal program that demonstrates the bug:

#include <guile/gh.h>
void main_entry(int argc, char *argv[])
{
  gh_eval_str("(display defmacro)");
}
int main (int argc, char *argv[])
{
  gh_enter (argc, argv, main_entry);
  return 0;
}

When run under Guile 1.3, this program will exit with an error, complaining that
defmacro is not defined.  (I reported this earlier to bug-guile@gnu.org.)

My solution was to separate the code that loads the init files into a separate
routine, scm_load_init (it was previously a part of scm_compile_shell_switches). 
This function is called by scm_compile_shell_switches and by gh_enter (actually,
gh_launch_pad), so that the init files are guaranteed to be loaded before any
user code executes.  scm_load_init maintains a static already_called variable to
make sure it is only executed once, making it safe to call gh_repl (which also
results in scm_load_init being called via scm_shell).

My patches, applied to the 5/19 snapshot of Guile 1.3, are as follows (diff
output for gh_init.c, script.h, and script.c):

diff gh_init.c.old gh_init.c

60a61
>   scm_load_init(); /* load the boot code, etcetera */

diff script.h.old script.h

56a57
> extern void scm_load_init(void);

diff script.c.old script.c

452a453,479
> /* Load initialization files (e.g. the ice-9 system).  This is called
>    by scm_shell (or rather, by scm_compile_shell_switches), but you
>    need to call it separately if you want to use the Scheme functions
>    defined in this file when running non-interactively.  For example,
>    it is called via gh_enter so that gh user code can use things
>    like load, defmacro, etcetera. */
> void scm_load_init(void)
> {
>   static int already_called = 0; /* we only want to do this once */
>   if (!already_called)   {
>     /* We want a path only containing directories from GUILE_LOAD_PATH,
>        SCM_SITE_DIR and SCM_LIBRARY_DIR when searching for the site init
>        file, so we do this before loading Ice-9.  */
>     SCM init_path = scm_sys_search_load_path (scm_makfrom0str ("init.scm"));
>
>     /* Load Ice-9.  */
>     if (!scm_ice_9_already_loaded)
>       scm_primitive_load_path (scm_makfrom0str ("ice-9/boot-9.scm"));
>
>     /* Load the init.scm file.  */
>     if (SCM_NFALSEP (init_path))
>       scm_primitive_load (init_path);
>
>     already_called = 1; /* don't call next time */
>   }
> }
>
623,627d649
<   {
<     /* We want a path only containing directories from GUILE_LOAD_PATH,
<        SCM_SITE_DIR and SCM_LIBRARY_DIR when searching for the site init
<        file, so we do this before loading Ice-9.  */
<     SCM init_path = scm_sys_search_load_path (scm_makfrom0str ("init.scm"));
629,636c651,652
<     /* Load Ice-9.  */
<     if (!scm_ice_9_already_loaded)
<       scm_primitive_load_path (scm_makfrom0str ("ice-9/boot-9.scm"));
<
<     /* Load the init.scm file.  */
<     if (SCM_NFALSEP (init_path))
<       scm_primitive_load (init_path);
<   }
---
>   /* load initialization files */
>   scm_load_init();