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] |
Maciej Stachowiak <mstachow@mit.edu> writes: > I have started on some code to allow this; specifically, so far I > have written a version of scm_eval which will print the same nicely > formatted messages in case of error that the Guile repl would, and > allow backtraces; I don't understand what you want to do. I don't think that `eval' is the right place for error reporting code. It seems more reasonable that this is associated with the repl loop or the error handler of the application. Could you please clarify? > I think versions of gh_eval_str, gh_apply and gh_call[0-3] that do > nice error handling would be a good addition to Guile. If the user has installed an error handler the handler can take care of error reporting for all of the above functions. > Optimally, I'd like to get this in for the next release. We're always open for including new code if we feel that it's a good solution and in line with future Guile development. Sometimes, however, knowing that this is the case requires thinking, which requires time, which is not always immediately available. > * Top-level expressions which are not lists do not have source > properties. This means that if I have a top-level expression like: > > some-silly-variable-reference > > in a file and I then load that file, the error message will be > prefixed with "ERROR:" instead of the filename and line and column > numbers, as would be the case for any other error in a file. As you point out, the reason is that source properties only are attached to pairs in the source code. Since this is a limitation in the basic source information code, I suggest that you simply ignore the problem until (and if) someone solves it on the basic level. Actually, I'm not sure that this is an important limitation, since top-level expressions which aren't lists aren't very interesting. (On the other hand, random characters mistakenly put into the source file could make it hard to load, and the user might want to easily locate the debris.) The purpose of source properties is to store source code information for later use when the error occurs during evaluation of procedures. Since the top-level-non-cons-problem occurs during loading, the right solution would perhaps be to take care of it in the loading code. > * On the other hand, the input file property appears to be there and > is used for the standard input, so you get errors prefixed with > "standard input:0:0:" instead of "ERROR:" for non-atomic expressions. While this may not be the nicest form of information to the user, I don't think it is wrong that the source properties tell the accurate origin of the source. The right solution is probably to handle this in the display routines (printing just ERROR when the file name is "standard input"). > * It's currently necessary to cons a list for each expression > evaluated to make scm_m_start_stack happy. This would surely slow > things down in batch mode. > > * Using scm_m_start_stack does not seem to generalize easily to doing > a call instead of an eval, e.g. gh_call0(). I've now separated the guts of scm_m_start_stack (which was never meant to be used from C) into a function: SCM scm_start_stack (SCM id, SCM exp, SCM env) BTW, have you noticed the function scm_internal_stack_catch? That's the function to use when writing an application error handler. Here's how to do it: ------- Start of forwarded message ------- To: russell.mcmanus@gs.com Cc: guile@cygnus.com Subject: Re: generating a backtrace from a custom error handler. References: <199708122232.SAA06339@nytrdc058.eq.gs.com> Cc: mdj@nada.kth.se From: Mikael Djurfeldt <mdj@nada.kth.se> Date: 13 Aug 1997 16:57:02 +0200 Message-ID: <xy7oh72uo5d.fsf@mdj.nada.kth.se> Russ McManus <mcmanr@eq.gs.com> writes: > i have a sizeable program that uses guile as an extension > language. the program frequently 'calls out' to scheme, which > is where the lion's share of the work happens. > > i am trying to set up the program so that i can catch scheme > errors and display them in the user interface, and -also- get a > backtrace of where the error occurred. > > after an hour of reading through ice-9/boot9.scm, ice-9/debug.scm, > backtrace.c, and stacks.c, the answer still eludes me. perhaps > someone can point me in the right direction? You can use the functions scm_display_backtrace and scm_display_error to display backtraces and errors. These functions take a stack object as their first argument. The stack object represents the state of the stack when the error occurred. It is normally created by a call to `make-stack' and stored in `the-last-stack' by the error handler in boot-9.scm. If you want to be able to display backtraces from C code you have to setup an error handler which captures the stack. This is not trivial since you cannot "pop" the stack before calling scm_make_stack. This means that should use a combination of a `catch' and a `lazy-catch'-handler. This is implemented by scm_internal_stack_catch. *** Unfortunately, this function was declared "static" and had another *** name in all previous snapshots. I've now corrected this, but you *** have to download the snapshot from tomorrow in order to access *** scm_internal_stack_catch. Below follows an example program which handles error from C. By using soft ports or string ports you can handle the output of scm_display_error and scm_display_backtrace any way you want. Best regards, /mdj ---------------------------------------------------------------------- /* Compile with: gcc myrepl.c -o myrepl -lguile -lqt -lreadline -lcurses */ #include <guile/gh.h> #include <readline/readline.h> /********************************************************************** * * Small example repl which handles errors. Uses readline. * **********************************************************************/ SCM my_handler (void *data, SCM tag, SCM throw_args) { SCM port = scm_def_errp; if (scm_ilength (throw_args) >= 3) { SCM stack = SCM_CDR (scm_the_last_stack_var); SCM subr = SCM_CAR (throw_args); SCM message = SCM_CADR (throw_args); SCM args = SCM_CADDR (throw_args); scm_newline (port); scm_display_backtrace (stack, port, SCM_UNDEFINED, SCM_UNDEFINED); scm_newline (port); scm_display_error (stack, port, subr, message, args, SCM_EOL); return SCM_BOOL_F; } else { scm_gen_puts (scm_regular_string, "uncaught throw to ", port); scm_prin1 (tag, port, 0); scm_gen_puts (scm_regular_string, ": ", port); scm_prin1 (throw_args, port, 1); scm_gen_putc ('\n', port); exit (2); } } static char *line = (char *)NULL; static SCM eval_str_wrapper (void *data, SCM jmpbuf) { return scm_eval_0str (data); } static void inner_main (int argc, char **argv) { SCM x; while (1) { line = readline ("> "); x = scm_internal_stack_catch (SCM_BOOL_T, (scm_catch_body_t) eval_str_wrapper, line, (scm_catch_handler_t) my_handler, line); gh_write (x); gh_newline (); } } int main (int argc, char **argv) { gh_enter (argc, argv, inner_main); return 0; /* never reached */ } ------- End of forwarded message -------