libgeda
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * libgeda - gEDA's library 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 #include <config.h> 00021 #include <missing.h> 00022 00023 #include <stdio.h> 00024 #include <sys/stat.h> 00025 #ifdef HAVE_STDLIB_H 00026 #include <stdlib.h> 00027 #endif 00028 00029 #ifdef HAVE_UNISTD_H 00030 #include <unistd.h> 00031 #endif 00032 00033 #ifdef HAVE_STRING_H 00034 #include <string.h> 00035 #endif 00036 00037 #include "libgeda_priv.h" 00038 #include "libgedaguile.h" 00039 00040 #ifdef HAVE_LIBDMALLOC 00041 #include <dmalloc.h> 00042 #endif 00043 00044 static void process_error_stack (SCM s_stack, SCM s_key, SCM s_args, GError **err); 00045 00046 /* Pre-unwind handler called in the context in which the exception was 00047 * thrown. */ 00048 static SCM protected_pre_unwind_handler (void *data, SCM key, SCM args) 00049 { 00050 /* Capture the stack trace */ 00051 *((SCM *) data) = scm_make_stack (SCM_BOOL_T, SCM_EOL); 00052 00053 return SCM_BOOL_T; 00054 } 00055 00056 /* Post-unwind handler called in the context of the catch expression. 00057 * This actually does the work of parsing the stack and generating log 00058 * messages. */ 00059 static SCM protected_post_unwind_handler (void *data, SCM key, SCM args) 00060 { 00061 /* The stack was captured pre-unwind */ 00062 SCM s_stack = *(SCM *) data; 00063 00064 process_error_stack (s_stack, key, args, NULL); 00065 00066 return SCM_BOOL_F; 00067 } 00068 00069 /* Actually carries out evaluation for protected eval */ 00070 static SCM protected_body_eval (void *data) 00071 { 00072 SCM args = *((SCM *)data); 00073 return scm_eval (scm_car (args), scm_cadr (args)); 00074 } 00075 00097 SCM g_scm_eval_protected (SCM exp, SCM module_or_state) 00098 { 00099 SCM stack = SCM_BOOL_T; 00100 SCM body_data; 00101 SCM result; 00102 00103 if (module_or_state == SCM_UNDEFINED) { 00104 body_data = scm_list_2 (exp, scm_interaction_environment ()); 00105 } else { 00106 body_data = scm_list_2 (exp, module_or_state); 00107 } 00108 00109 result = scm_c_catch (SCM_BOOL_T, 00110 protected_body_eval, /* catch body */ 00111 &body_data, /* body data */ 00112 protected_post_unwind_handler, /* post handler */ 00113 &stack, /* post data */ 00114 protected_pre_unwind_handler, /* pre handler */ 00115 &stack /* pre data */ 00116 ); 00117 00118 scm_remember_upto_here_2 (body_data, stack); 00119 00120 return result; 00121 } 00122 00133 SCM g_scm_c_eval_string_protected (const gchar *str) { 00134 SCM s_str; 00135 g_return_val_if_fail ((str != NULL), SCM_BOOL_F); 00136 s_str = scm_from_utf8_string (str); 00137 return g_scm_eval_string_protected (s_str); 00138 } 00139 00153 SCM g_scm_eval_string_protected (SCM str) 00154 { 00155 SCM expr = scm_list_2 (scm_from_utf8_symbol ("eval-string"), 00156 str); 00157 00158 return g_scm_eval_protected (expr, SCM_UNDEFINED); 00159 } 00160 00161 /* Data to be passed to g_read_file()'s worker functions. */ 00162 struct g_read_file_data_t 00163 { 00164 SCM stack; 00165 SCM filename; 00166 GError *err; 00167 }; 00168 00169 /* Body function for g_read_file(). Simply loads the specified 00170 * file. */ 00171 SCM 00172 g_read_file__body (struct g_read_file_data_t *data) 00173 { 00174 return scm_primitive_load (data->filename); 00175 } 00176 00177 /* Post-unwind handler for g_read_file(). Processes the stack captured 00178 * in the pre-unwind handler. */ 00179 SCM 00180 g_read_file__post_handler (struct g_read_file_data_t *data, SCM key, SCM args) 00181 { 00182 process_error_stack (data->stack, key, args, &data->err); 00183 return SCM_BOOL_F; 00184 } 00185 00186 /* Pre-unwind handler for g_read_file(). Captures the Guile stack for 00187 * processing in the post-unwind handler. */ 00188 SCM 00189 g_read_file__pre_handler (struct g_read_file_data_t *data, SCM key, SCM args) 00190 { 00191 data->stack = scm_make_stack (SCM_BOOL_T, SCM_EOL); 00192 return SCM_BOOL_F; 00193 } 00194 00207 gboolean 00208 g_read_file(TOPLEVEL *toplevel, const gchar *filename, GError **err) 00209 { 00210 struct g_read_file_data_t data; 00211 00212 g_return_val_if_fail ((filename != NULL), FALSE); 00213 00214 data.stack = SCM_BOOL_F; 00215 data.filename = scm_from_utf8_string (filename); 00216 data.err = NULL; 00217 00218 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE); 00219 edascm_dynwind_toplevel (toplevel); 00220 00221 scm_c_catch (SCM_BOOL_T, 00222 (scm_t_catch_body) g_read_file__body, &data, 00223 (scm_t_catch_handler) g_read_file__post_handler, &data, 00224 (scm_t_catch_handler) g_read_file__pre_handler, &data); 00225 00226 scm_dynwind_end (); 00227 00228 /* If no error occurred, indicate success. */ 00229 if (data.err == NULL) return TRUE; 00230 00231 g_propagate_error (err, data.err); 00232 return FALSE; 00233 } 00234 00235 00243 static void 00244 process_error_stack (SCM s_stack, SCM s_key, SCM s_args, GError **err) { 00245 char *long_message; 00246 char *short_message; 00247 SCM s_port, s_subr, s_message, s_message_args, s_rest, s_location; 00248 00249 /* Split s_args up */ 00250 s_rest = s_args; 00251 s_subr = scm_car (s_rest); s_rest = scm_cdr (s_rest); 00252 s_message = scm_car (s_rest); s_rest = scm_cdr (s_rest); 00253 s_message_args = scm_car (s_rest); s_rest = scm_cdr (s_rest); 00254 00255 /* Capture short error message */ 00256 s_port = scm_open_output_string (); 00257 scm_display_error_message (s_message, s_message_args, s_port); 00258 short_message = scm_to_utf8_string (scm_get_output_string (s_port)); 00259 scm_close_output_port (s_port); 00260 00261 /* Capture long error message (including possible backtrace) */ 00262 s_port = scm_open_output_string (); 00263 if (scm_is_true (scm_stack_p (s_stack))) { 00264 scm_puts (_("\nBacktrace:\n"), s_port); 00265 scm_display_backtrace (s_stack, s_port, SCM_BOOL_F, SCM_BOOL_F); 00266 scm_puts ("\n", s_port); 00267 } 00268 00269 s_location = SCM_BOOL_F; 00270 #ifdef HAVE_SCM_DISPLAY_ERROR_STACK 00271 s_location = s_stack; 00272 #endif /* HAVE_SCM_DISPLAY_ERROR_STACK */ 00273 #ifdef HAVE_SCM_DISPLAY_ERROR_FRAME 00274 s_location = 00275 scm_is_true (s_stack) ? scm_stack_ref (s_stack, SCM_INUM0) : SCM_BOOL_F; 00276 #endif /* HAVE_SCM_DISPLAY_ERROR_FRAME */ 00277 00278 scm_display_error (s_location, s_port, s_subr, 00279 s_message, s_message_args, s_rest); 00280 00281 long_message = scm_to_utf8_string (scm_get_output_string (s_port)); 00282 scm_close_output_port (s_port); 00283 00284 /* Send long message to log */ 00285 s_log_message ("%s", long_message); 00286 00287 /* Populate any GError */ 00288 g_set_error (err, EDA_ERROR, EDA_ERROR_SCHEME, "%s", short_message); 00289 }