GnuCash c935c2f+
Loading...
Searching...
No Matches
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
22static const QofLogModule log_module = G_LOG_DOMAIN;
23
24static SCM
25gfec_string_from_utf8(void *data)
26{
27 char *str = (char*)data;
28 return scm_from_utf8_string(str);
29}
30
31static SCM
32gfec_string_from_locale(void *data)
33{
34 char *str = (char*)data;
35 return scm_from_locale_string(str);
36}
37
38static SCM
39gfec_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
49SCM
50gfec_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
91SCM
92gfec_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
123SCM
124gfec_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
152static int error_in_scm_eval = FALSE;
153
154static void
155error_handler(const char *msg)
156{
157 g_warning("%s", msg);
158 error_in_scm_eval = TRUE;
159}
160
161gboolean
162gfec_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 DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264