GnuCash  5.6-150-g038405b370+
gfec.c
1 /* Authors: Eric M. Ludlam <zappo@ultranet.com>
2  * Russ McManus <russell.mcmanus@gs.com>
3  * Dave Peticolas <dave@krondo.com>
4  *
5  * gfec stands for 'guile fancy error catching'.
6  * This code is in the public domain.
7  */
8 
9 #include <assert.h>
10 #include <string.h>
11 
12 #include <config.h>
13 #include "gfec.h"
14 #include "gnc-guile-utils.h"
15 #include "platform.h"
16 #include <qoflog.h>
17 #include <glib.h>
18 #if COMPILER(MSVC)
19 # define strdup _strdup
20 #endif
21 
22 static const QofLogModule log_module = G_LOG_DOMAIN;
23 
24 static SCM
25 gfec_string_from_utf8(void *data)
26 {
27  char *str = (char*)data;
28  return scm_from_utf8_string(str);
29 }
30 
31 static SCM
32 gfec_string_from_locale(void *data)
33 {
34  char *str = (char*)data;
35  return scm_from_locale_string(str);
36 }
37 
38 static SCM
39 gfec_string_inner_handler(void *data, SCM key, SCM args)
40 {
41  char *str = (char*)data;
42  SCM scm_string = scm_internal_catch(SCM_BOOL_T,
43  gfec_string_from_locale, (void*)str,
44  gfec_string_inner_handler,
45  (void*)str);
46  return scm_string;
47 }
48 
49 SCM
50 gfec_eval_string(const char *str, gfec_error_handler error_handler)
51 {
52  SCM result = SCM_UNDEFINED;
53  SCM func = scm_c_eval_string("gnc:eval-string-with-error-handling");
54  if (scm_is_procedure(func))
55  {
56  char *err_msg = NULL;
57  SCM call_result, error = SCM_UNDEFINED;
58  /* Deal with the possibility that scm_from_utf8_string will
59  * throw, falling back to scm_from_locale_string. If that fails, log a
60  * warning and punt.
61  */
62  SCM scm_string = scm_internal_catch(SCM_BOOL_T,
63  gfec_string_from_utf8, (void*)str,
64  gfec_string_inner_handler,
65  (void*)str);
66  if (!scm_string)
67  {
68  error_handler("Contents could not be interpreted as UTF-8 or the current locale/codepage.");
69  return result;
70  }
71  call_result = scm_call_1 (func, scm_string);
72 
73  error = scm_list_ref (call_result, scm_from_uint (1));
74  if (scm_is_true (error))
75  err_msg = gnc_scm_to_utf8_string (error);
76  else
77  result = scm_list_ref (call_result, scm_from_uint (0));
78 
79  if (err_msg != NULL)
80  {
81  if (error_handler)
82  error_handler (err_msg);
83 
84  free(err_msg);
85  }
86  }
87 
88  return result;
89 }
90 
91 SCM
92 gfec_eval_file(const char *file, gfec_error_handler error_handler)
93 {
94  gchar *contents = NULL;
95  GError *save_error = NULL;
96  SCM result;
97 
98  if (!g_file_get_contents (file, &contents, NULL, &save_error))
99  {
100  gchar *full_msg = g_strdup_printf ("Couldn't read contents of %s.\nReason: %s", file, save_error->message);
101  error_handler(full_msg);
102 
103  g_error_free (save_error);
104  g_free(full_msg);
105 
106  return SCM_UNDEFINED;
107  }
108 
109  result = gfec_eval_string (contents, error_handler);
110  g_free (contents);
111 
112  if (!result)
113  {
114  gchar *full_msg = g_strdup_printf ("Couldn't read contents of %s", file);
115  error_handler(full_msg);
116 
117  g_free(full_msg);
118  }
119 
120  return result;
121 }
122 
123 SCM
124 gfec_apply(SCM proc, SCM arglist, gfec_error_handler error_handler)
125 {
126  SCM result = SCM_UNDEFINED;
127  SCM func = scm_c_eval_string("gnc:apply-with-error-handling");
128  if (scm_is_procedure(func))
129  {
130  char *err_msg = NULL;
131  SCM call_result, error;
132  call_result = scm_call_2 (func, proc, arglist);
133 
134  error = scm_list_ref (call_result, scm_from_uint (1));
135  if (scm_is_true (error))
136  err_msg = gnc_scm_to_utf8_string (error);
137  else
138  result = scm_list_ref (call_result, scm_from_uint (0));
139 
140  if (err_msg != NULL)
141  {
142  if (error_handler)
143  error_handler (err_msg);
144 
145  free(err_msg);
146  }
147  }
148 
149  return result;
150 }
151 
152 static int error_in_scm_eval = FALSE;
153 
154 static void
155 error_handler(const char *msg)
156 {
157  g_warning("%s", msg);
158  error_in_scm_eval = TRUE;
159 }
160 
161 gboolean
162 gfec_try_load(const gchar *fn)
163 {
164  DEBUG("looking for %s", fn);
165  if (g_file_test(fn, G_FILE_TEST_EXISTS))
166  {
167  DEBUG("trying to load %s", fn);
168  error_in_scm_eval = FALSE;
169  gfec_eval_file(fn, error_handler);
170  return !error_in_scm_eval;
171  }
172  return FALSE;
173 }
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define DEBUG(format, args...)
Print a debugging message.
Definition: qoflog.h:264