Home | History | Annotate | Line # | Download | only in guile
scm-safe-call.c revision 1.1.1.8
      1      1.1  christos /* GDB/Scheme support for safe calls into the Guile interpreter.
      2      1.1  christos 
      3  1.1.1.8  christos    Copyright (C) 2014-2024 Free Software Foundation, Inc.
      4      1.1  christos 
      5      1.1  christos    This file is part of GDB.
      6      1.1  christos 
      7      1.1  christos    This program is free software; you can redistribute it and/or modify
      8      1.1  christos    it under the terms of the GNU General Public License as published by
      9      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10      1.1  christos    (at your option) any later version.
     11      1.1  christos 
     12      1.1  christos    This program is distributed in the hope that it will be useful,
     13      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  christos    GNU General Public License for more details.
     16      1.1  christos 
     17      1.1  christos    You should have received a copy of the GNU General Public License
     18      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19      1.1  christos 
     20      1.1  christos /* See README file in this directory for implementation notes, coding
     21      1.1  christos    conventions, et.al.  */
     22      1.1  christos 
     23      1.1  christos #include "filenames.h"
     24      1.1  christos #include "guile-internal.h"
     25  1.1.1.6  christos #include "gdbsupport/pathstuff.h"
     26      1.1  christos 
     27      1.1  christos /* Struct to marshall args to scscm_safe_call_body.  */
     28      1.1  christos 
     29      1.1  christos struct c_data
     30      1.1  christos {
     31  1.1.1.3  christos   const char *(*func) (void *);
     32      1.1  christos   void *data;
     33      1.1  christos   /* An error message or NULL for success.  */
     34  1.1.1.3  christos   const char *result;
     35      1.1  christos };
     36      1.1  christos 
     37      1.1  christos /* Struct to marshall args through gdbscm_with_catch.  */
     38      1.1  christos 
     39      1.1  christos struct with_catch_data
     40      1.1  christos {
     41      1.1  christos   scm_t_catch_body func;
     42      1.1  christos   void *data;
     43      1.1  christos   scm_t_catch_handler unwind_handler;
     44      1.1  christos   scm_t_catch_handler pre_unwind_handler;
     45      1.1  christos 
     46      1.1  christos   /* If EXCP_MATCHER is non-NULL, it is an excp_matcher_func function.
     47      1.1  christos      If the exception is recognized by it, the exception is recorded as is,
     48      1.1  christos      without wrapping it in gdb:with-stack.  */
     49      1.1  christos   excp_matcher_func *excp_matcher;
     50      1.1  christos 
     51      1.1  christos   SCM stack;
     52      1.1  christos   SCM catch_result;
     53      1.1  christos };
     54      1.1  christos 
     55      1.1  christos /* The "body" argument to scm_i_with_continuation_barrier.
     56      1.1  christos    Invoke the user-supplied function.  */
     57      1.1  christos 
     58      1.1  christos static SCM
     59      1.1  christos scscm_safe_call_body (void *d)
     60      1.1  christos {
     61      1.1  christos   struct c_data *data = (struct c_data *) d;
     62      1.1  christos 
     63      1.1  christos   data->result = data->func (data->data);
     64      1.1  christos 
     65      1.1  christos   return SCM_UNSPECIFIED;
     66      1.1  christos }
     67      1.1  christos 
     68      1.1  christos /* A "pre-unwind handler" to scm_c_catch that prints the exception
     69      1.1  christos    according to "set guile print-stack".  */
     70      1.1  christos 
     71      1.1  christos static SCM
     72      1.1  christos scscm_printing_pre_unwind_handler (void *data, SCM key, SCM args)
     73      1.1  christos {
     74      1.1  christos   SCM stack = scm_make_stack (SCM_BOOL_T, scm_list_1 (scm_from_int (2)));
     75      1.1  christos 
     76      1.1  christos   gdbscm_print_exception_with_stack (SCM_BOOL_F, stack, key, args);
     77      1.1  christos 
     78      1.1  christos   return SCM_UNSPECIFIED;
     79      1.1  christos }
     80      1.1  christos 
     81      1.1  christos /* A no-op unwind handler.  */
     82      1.1  christos 
     83      1.1  christos static SCM
     84      1.1  christos scscm_nop_unwind_handler (void *data, SCM key, SCM args)
     85      1.1  christos {
     86      1.1  christos   return SCM_UNSPECIFIED;
     87      1.1  christos }
     88      1.1  christos 
     89      1.1  christos /* The "pre-unwind handler" to scm_c_catch that records the exception
     90      1.1  christos    for possible later printing.  We do this in the pre-unwind handler because
     91      1.1  christos    we want the stack to include point where the exception occurred.
     92      1.1  christos 
     93      1.1  christos    If DATA is non-NULL, it is an excp_matcher_func function.
     94      1.1  christos    If the exception is recognized by it, the exception is recorded as is,
     95      1.1  christos    without wrapping it in gdb:with-stack.  */
     96      1.1  christos 
     97      1.1  christos static SCM
     98      1.1  christos scscm_recording_pre_unwind_handler (void *datap, SCM key, SCM args)
     99      1.1  christos {
    100  1.1.1.3  christos   struct with_catch_data *data = (struct with_catch_data *) datap;
    101      1.1  christos   excp_matcher_func *matcher = data->excp_matcher;
    102      1.1  christos 
    103      1.1  christos   if (matcher != NULL && matcher (key))
    104      1.1  christos     return SCM_UNSPECIFIED;
    105      1.1  christos 
    106      1.1  christos   /* There's no need to record the whole stack if we're not going to print it.
    107      1.1  christos      However, convention is to still print the stack frame in which the
    108      1.1  christos      exception occurred, even if we're not going to print a full backtrace.
    109      1.1  christos      For now, keep it simple.  */
    110      1.1  christos 
    111      1.1  christos   data->stack = scm_make_stack (SCM_BOOL_T, scm_list_1 (scm_from_int (2)));
    112      1.1  christos 
    113      1.1  christos   /* IWBN if we could return the <gdb:exception> here and skip the unwind
    114      1.1  christos      handler, but it doesn't work that way.  If we want to return a
    115      1.1  christos      <gdb:exception> object from the catch it needs to come from the unwind
    116      1.1  christos      handler.  So what we do is save the stack for later use by the unwind
    117      1.1  christos      handler.  */
    118      1.1  christos 
    119      1.1  christos   return SCM_UNSPECIFIED;
    120      1.1  christos }
    121      1.1  christos 
    122      1.1  christos /* Part two of the recording unwind handler.
    123      1.1  christos    Here we take the stack saved from the pre-unwind handler and create
    124      1.1  christos    the <gdb:exception> object.  */
    125      1.1  christos 
    126      1.1  christos static SCM
    127      1.1  christos scscm_recording_unwind_handler (void *datap, SCM key, SCM args)
    128      1.1  christos {
    129  1.1.1.3  christos   struct with_catch_data *data = (struct with_catch_data *) datap;
    130      1.1  christos 
    131      1.1  christos   /* We need to record the stack in the exception since we're about to
    132      1.1  christos      throw and lose the location that got the exception.  We do this by
    133      1.1  christos      wrapping the exception + stack in a new exception.  */
    134      1.1  christos 
    135      1.1  christos   if (gdbscm_is_true (data->stack))
    136      1.1  christos     return gdbscm_make_exception_with_stack (key, args, data->stack);
    137      1.1  christos 
    138      1.1  christos   return gdbscm_make_exception (key, args);
    139      1.1  christos }
    140      1.1  christos 
    141      1.1  christos /* Ugh. :-(
    142      1.1  christos    Guile doesn't export scm_i_with_continuation_barrier which is exactly
    143      1.1  christos    what we need.  To cope, have our own wrapper around scm_c_catch and
    144      1.1  christos    pass this as the "body" argument to scm_c_with_continuation_barrier.
    145      1.1  christos    Darn darn darn.  */
    146      1.1  christos 
    147      1.1  christos static void *
    148      1.1  christos gdbscm_with_catch (void *data)
    149      1.1  christos {
    150  1.1.1.3  christos   struct with_catch_data *d = (struct with_catch_data *) data;
    151      1.1  christos 
    152      1.1  christos   d->catch_result
    153      1.1  christos     = scm_c_catch (SCM_BOOL_T,
    154      1.1  christos 		   d->func, d->data,
    155      1.1  christos 		   d->unwind_handler, d,
    156      1.1  christos 		   d->pre_unwind_handler, d);
    157      1.1  christos 
    158  1.1.1.2  christos #if HAVE_GUILE_MANUAL_FINALIZATION
    159  1.1.1.2  christos   scm_run_finalizers ();
    160  1.1.1.2  christos #endif
    161  1.1.1.2  christos 
    162      1.1  christos   return NULL;
    163      1.1  christos }
    164      1.1  christos 
    165      1.1  christos /* A wrapper around scm_with_guile that prints backtraces and exceptions
    166      1.1  christos    according to "set guile print-stack".
    167      1.1  christos    The result if NULL if no exception occurred, otherwise it is a statically
    168      1.1  christos    allocated error message (caller must *not* free).  */
    169      1.1  christos 
    170  1.1.1.3  christos const char *
    171  1.1.1.3  christos gdbscm_with_guile (const char *(*func) (void *), void *data)
    172      1.1  christos {
    173      1.1  christos   struct c_data c_data;
    174      1.1  christos   struct with_catch_data catch_data;
    175      1.1  christos 
    176      1.1  christos   c_data.func = func;
    177      1.1  christos   c_data.data = data;
    178      1.1  christos   /* Set this now in case an exception is thrown.  */
    179      1.1  christos   c_data.result = _("Error while executing Scheme code.");
    180      1.1  christos 
    181      1.1  christos   catch_data.func = scscm_safe_call_body;
    182      1.1  christos   catch_data.data = &c_data;
    183      1.1  christos   catch_data.unwind_handler = scscm_nop_unwind_handler;
    184      1.1  christos   catch_data.pre_unwind_handler = scscm_printing_pre_unwind_handler;
    185      1.1  christos   catch_data.excp_matcher = NULL;
    186      1.1  christos   catch_data.stack = SCM_BOOL_F;
    187      1.1  christos   catch_data.catch_result = SCM_UNSPECIFIED;
    188      1.1  christos 
    189      1.1  christos   scm_with_guile (gdbscm_with_catch, &catch_data);
    190      1.1  christos 
    191      1.1  christos   return c_data.result;
    192      1.1  christos }
    193      1.1  christos 
    194      1.1  christos /* Another wrapper of scm_with_guile for use by the safe call/apply routines
    195      1.1  christos    in this file, as well as for general purpose calling other functions safely.
    196      1.1  christos    For these we want to record the exception, but leave the possible printing
    197      1.1  christos    of it to later.  */
    198      1.1  christos 
    199      1.1  christos SCM
    200      1.1  christos gdbscm_call_guile (SCM (*func) (void *), void *data,
    201      1.1  christos 		   excp_matcher_func *ok_excps)
    202      1.1  christos {
    203      1.1  christos   struct with_catch_data catch_data;
    204      1.1  christos 
    205      1.1  christos   catch_data.func = func;
    206      1.1  christos   catch_data.data = data;
    207      1.1  christos   catch_data.unwind_handler = scscm_recording_unwind_handler;
    208      1.1  christos   catch_data.pre_unwind_handler = scscm_recording_pre_unwind_handler;
    209      1.1  christos   catch_data.excp_matcher = ok_excps;
    210      1.1  christos   catch_data.stack = SCM_BOOL_F;
    211      1.1  christos   catch_data.catch_result = SCM_UNSPECIFIED;
    212      1.1  christos 
    213      1.1  christos #if 0
    214      1.1  christos   scm_c_with_continuation_barrier (gdbscm_with_catch, &catch_data);
    215      1.1  christos #else
    216      1.1  christos   scm_with_guile (gdbscm_with_catch, &catch_data);
    217      1.1  christos #endif
    218      1.1  christos 
    219      1.1  christos   return catch_data.catch_result;
    220      1.1  christos }
    221      1.1  christos 
    222      1.1  christos /* Utilities to safely call Scheme code, catching all exceptions, and
    224      1.1  christos    preventing continuation capture.
    225      1.1  christos    The result is the result of calling the function, or if an exception occurs
    226      1.1  christos    then the result is a <gdb:exception> smob, which can be tested for with
    227      1.1  christos    gdbscm_is_exception.  */
    228      1.1  christos 
    229      1.1  christos /* Helper for gdbscm_safe_call_0.  */
    230      1.1  christos 
    231      1.1  christos static SCM
    232      1.1  christos scscm_call_0_body (void *argsp)
    233  1.1.1.3  christos {
    234      1.1  christos   SCM *args = (SCM *) argsp;
    235      1.1  christos 
    236      1.1  christos   return scm_call_0 (args[0]);
    237      1.1  christos }
    238      1.1  christos 
    239      1.1  christos SCM
    240      1.1  christos gdbscm_safe_call_0 (SCM proc, excp_matcher_func *ok_excps)
    241      1.1  christos {
    242      1.1  christos   SCM args[] = { proc };
    243      1.1  christos 
    244      1.1  christos   return gdbscm_call_guile (scscm_call_0_body, args, ok_excps);
    245      1.1  christos }
    246      1.1  christos 
    247      1.1  christos /* Helper for gdbscm_safe_call_1.  */
    248      1.1  christos 
    249      1.1  christos static SCM
    250      1.1  christos scscm_call_1_body (void *argsp)
    251  1.1.1.3  christos {
    252      1.1  christos   SCM *args = (SCM *) argsp;
    253      1.1  christos 
    254      1.1  christos   return scm_call_1 (args[0], args[1]);
    255      1.1  christos }
    256      1.1  christos 
    257      1.1  christos SCM
    258      1.1  christos gdbscm_safe_call_1 (SCM proc, SCM arg0, excp_matcher_func *ok_excps)
    259      1.1  christos {
    260      1.1  christos   SCM args[] = { proc, arg0 };
    261      1.1  christos 
    262      1.1  christos   return gdbscm_call_guile (scscm_call_1_body, args, ok_excps);
    263      1.1  christos }
    264      1.1  christos 
    265      1.1  christos /* Helper for gdbscm_safe_call_2.  */
    266      1.1  christos 
    267      1.1  christos static SCM
    268      1.1  christos scscm_call_2_body (void *argsp)
    269  1.1.1.3  christos {
    270      1.1  christos   SCM *args = (SCM *) argsp;
    271      1.1  christos 
    272      1.1  christos   return scm_call_2 (args[0], args[1], args[2]);
    273      1.1  christos }
    274      1.1  christos 
    275      1.1  christos SCM
    276      1.1  christos gdbscm_safe_call_2 (SCM proc, SCM arg0, SCM arg1, excp_matcher_func *ok_excps)
    277      1.1  christos {
    278      1.1  christos   SCM args[] = { proc, arg0, arg1 };
    279      1.1  christos 
    280      1.1  christos   return gdbscm_call_guile (scscm_call_2_body, args, ok_excps);
    281      1.1  christos }
    282      1.1  christos 
    283      1.1  christos /* Helper for gdbscm_safe_call_3.  */
    284      1.1  christos 
    285      1.1  christos static SCM
    286      1.1  christos scscm_call_3_body (void *argsp)
    287  1.1.1.3  christos {
    288      1.1  christos   SCM *args = (SCM *) argsp;
    289      1.1  christos 
    290      1.1  christos   return scm_call_3 (args[0], args[1], args[2], args[3]);
    291      1.1  christos }
    292      1.1  christos 
    293      1.1  christos SCM
    294      1.1  christos gdbscm_safe_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3,
    295      1.1  christos 		    excp_matcher_func *ok_excps)
    296      1.1  christos {
    297      1.1  christos   SCM args[] = { proc, arg1, arg2, arg3 };
    298      1.1  christos 
    299      1.1  christos   return gdbscm_call_guile (scscm_call_3_body, args, ok_excps);
    300      1.1  christos }
    301      1.1  christos 
    302      1.1  christos /* Helper for gdbscm_safe_call_4.  */
    303      1.1  christos 
    304      1.1  christos static SCM
    305      1.1  christos scscm_call_4_body (void *argsp)
    306  1.1.1.3  christos {
    307      1.1  christos   SCM *args = (SCM *) argsp;
    308      1.1  christos 
    309      1.1  christos   return scm_call_4 (args[0], args[1], args[2], args[3], args[4]);
    310      1.1  christos }
    311      1.1  christos 
    312      1.1  christos SCM
    313      1.1  christos gdbscm_safe_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4,
    314      1.1  christos 		    excp_matcher_func *ok_excps)
    315      1.1  christos {
    316      1.1  christos   SCM args[] = { proc, arg1, arg2, arg3, arg4 };
    317      1.1  christos 
    318      1.1  christos   return gdbscm_call_guile (scscm_call_4_body, args, ok_excps);
    319      1.1  christos }
    320      1.1  christos 
    321      1.1  christos /* Helper for gdbscm_safe_apply_1.  */
    322      1.1  christos 
    323      1.1  christos static SCM
    324      1.1  christos scscm_apply_1_body (void *argsp)
    325  1.1.1.3  christos {
    326      1.1  christos   SCM *args = (SCM *) argsp;
    327      1.1  christos 
    328      1.1  christos   return scm_apply_1 (args[0], args[1], args[2]);
    329      1.1  christos }
    330      1.1  christos 
    331      1.1  christos SCM
    332      1.1  christos gdbscm_safe_apply_1 (SCM proc, SCM arg0, SCM rest, excp_matcher_func *ok_excps)
    333      1.1  christos {
    334      1.1  christos   SCM args[] = { proc, arg0, rest };
    335      1.1  christos 
    336      1.1  christos   return gdbscm_call_guile (scscm_apply_1_body, args, ok_excps);
    337      1.1  christos }
    338      1.1  christos 
    339      1.1  christos /* Utilities to call Scheme code, not catching exceptions, and
    341      1.1  christos    not preventing continuation capture.
    342      1.1  christos    The result is the result of calling the function.
    343      1.1  christos    If an exception occurs then Guile is left to handle the exception,
    344      1.1  christos    unwinding the stack as appropriate.
    345      1.1  christos 
    346      1.1  christos    USE THESE WITH CARE.
    347      1.1  christos    Typically these are called from functions that implement Scheme procedures,
    348      1.1  christos    and we don't want to catch the exception; otherwise it will get printed
    349      1.1  christos    twice: once when first caught and once if it ends up being rethrown and the
    350      1.1  christos    rethrow reaches the top repl, which will confuse the user.
    351      1.1  christos 
    352      1.1  christos    While these calls just pass the call off to the corresponding Guile
    353      1.1  christos    procedure, all such calls are routed through these ones to:
    354      1.1  christos    a) provide a place to put hooks or whatnot in if we need to,
    355      1.1  christos    b) add "unsafe" to the name to alert the reader.  */
    356      1.1  christos 
    357      1.1  christos SCM
    358      1.1  christos gdbscm_unsafe_call_1 (SCM proc, SCM arg0)
    359      1.1  christos {
    360      1.1  christos   return scm_call_1 (proc, arg0);
    361      1.1  christos }
    362      1.1  christos 
    363      1.1  christos /* Utilities for safely evaluating a Scheme expression string.  */
    365      1.1  christos 
    366      1.1  christos struct eval_scheme_string_data
    367      1.1  christos {
    368      1.1  christos   const char *string;
    369      1.1  christos   int display_result;
    370      1.1  christos };
    371      1.1  christos 
    372  1.1.1.3  christos /* Wrapper to eval a C string in the Guile interpreter.
    373      1.1  christos    This is passed to gdbscm_with_guile.  */
    374      1.1  christos 
    375  1.1.1.3  christos static const char *
    376  1.1.1.3  christos scscm_eval_scheme_string (void *datap)
    377      1.1  christos {
    378      1.1  christos   struct eval_scheme_string_data *data
    379      1.1  christos     = (struct eval_scheme_string_data *) datap;
    380      1.1  christos   SCM result = scm_c_eval_string (data->string);
    381      1.1  christos 
    382      1.1  christos   if (data->display_result && !scm_is_eq (result, SCM_UNSPECIFIED))
    383      1.1  christos     {
    384      1.1  christos       SCM port = scm_current_output_port ();
    385      1.1  christos 
    386      1.1  christos       scm_write (result, port);
    387      1.1  christos       scm_newline (port);
    388      1.1  christos     }
    389      1.1  christos 
    390      1.1  christos   /* If we get here the eval succeeded.  */
    391      1.1  christos   return NULL;
    392      1.1  christos }
    393      1.1  christos 
    394      1.1  christos /* Evaluate EXPR in the Guile interpreter, catching all exceptions
    395  1.1.1.5  christos    and preventing continuation capture.
    396      1.1  christos    The result is NULL if no exception occurred.  Otherwise, the exception is
    397  1.1.1.5  christos    printed according to "set guile print-stack" and the result is an error
    398      1.1  christos    message.  */
    399      1.1  christos 
    400      1.1  christos gdb::unique_xmalloc_ptr<char>
    401  1.1.1.3  christos gdbscm_safe_eval_string (const char *string, int display_result)
    402      1.1  christos {
    403      1.1  christos   struct eval_scheme_string_data data = { string, display_result };
    404      1.1  christos   const char *result;
    405      1.1  christos 
    406  1.1.1.6  christos   result = gdbscm_with_guile (scscm_eval_scheme_string, (void *) &data);
    407      1.1  christos 
    408      1.1  christos   if (result != NULL)
    409      1.1  christos     return make_unique_xstrdup (result);
    410      1.1  christos   return NULL;
    411      1.1  christos }
    412      1.1  christos 
    413      1.1  christos /* Utilities for safely loading Scheme scripts.  */
    415      1.1  christos 
    416      1.1  christos /* Helper function for gdbscm_safe_source_scheme_script.  */
    417  1.1.1.3  christos 
    418      1.1  christos static const char *
    419      1.1  christos scscm_source_scheme_script (void *data)
    420      1.1  christos {
    421      1.1  christos   const char *filename = (const char *) data;
    422      1.1  christos 
    423      1.1  christos   /* The Guile docs don't specify what the result is.
    424      1.1  christos      Maybe it's SCM_UNSPECIFIED, but the docs should specify that. :-) */
    425      1.1  christos   scm_c_primitive_load_path (filename);
    426      1.1  christos 
    427      1.1  christos   /* If we get here the load succeeded.  */
    428      1.1  christos   return NULL;
    429      1.1  christos }
    430      1.1  christos 
    431      1.1  christos /* Try to load a script, catching all exceptions,
    432      1.1  christos    and preventing continuation capture.
    433  1.1.1.7  christos    The result is NULL if the load succeeded.  Otherwise, the exception is
    434      1.1  christos    printed according to "set guile print-stack" and the result is an error
    435      1.1  christos    message allocated with malloc, caller must free.  */
    436      1.1  christos 
    437      1.1  christos gdb::unique_xmalloc_ptr<char>
    438      1.1  christos gdbscm_safe_source_script (const char *filename)
    439      1.1  christos {
    440      1.1  christos   /* scm_c_primitive_load_path only looks in %load-path for files with
    441  1.1.1.5  christos      relative paths.  An alternative could be to temporarily add "." to
    442  1.1.1.3  christos      %load-path, but we don't want %load-path to be searched.  At least not
    443      1.1  christos      by default.  This function is invoked by the "source" GDB command which
    444      1.1  christos      already has its own path search support.  */
    445      1.1  christos   gdb::unique_xmalloc_ptr<char> abs_filename;
    446      1.1  christos   const char *result;
    447  1.1.1.5  christos 
    448      1.1  christos   if (!IS_ABSOLUTE_PATH (filename))
    449      1.1  christos     {
    450      1.1  christos       abs_filename = gdb_realpath (filename);
    451      1.1  christos       filename = abs_filename.get ();
    452      1.1  christos     }
    453      1.1  christos 
    454  1.1.1.7  christos   result = gdbscm_with_guile (scscm_source_scheme_script,
    455      1.1  christos 			      (void *) filename);
    456      1.1  christos 
    457      1.1  christos   if (result != NULL)
    458      1.1  christos     return make_unique_xstrdup (result);
    459      1.1  christos   return NULL;
    460      1.1  christos }
    461      1.1  christos 
    462      1.1  christos /* Utility for entering an interactive Guile repl.  */
    464      1.1  christos 
    465      1.1  christos void
    466      1.1  christos gdbscm_enter_repl (void)
    467      1.1  christos {
    468                      /* It's unfortunate to have to resort to something like this, but
    469                         scm_shell doesn't return.  :-(  I found this code on guile-user@.  */
    470                      gdbscm_safe_call_1 (scm_c_public_ref ("system repl repl", "start-repl"),
    471                    		      scm_from_latin1_symbol ("scheme"), NULL);
    472                    }
    473