Branch data Line data Source code
1 : : /* -*- mode: C -*-
2 : : *
3 : : * File: pdf-error.c
4 : : * Date: Sun Feb 24 20:22:05 2008
5 : : *
6 : : * GNU PDF Library - Implementation for the Error module
7 : : *
8 : : */
9 : :
10 : : /* Copyright (C) 2008-2011 Free Software Foundation, Inc. */
11 : :
12 : : /* This program is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU General Public License as published by
14 : : * the Free Software Foundation, either version 3 of the License, or
15 : : * (at your option) any later version.
16 : : *
17 : : * This program is distributed in the hope that it will be useful,
18 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : : * GNU General Public License for more details.
21 : : *
22 : : * You should have received a copy of the GNU General Public License
23 : : * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : : */
25 : :
26 : : #include <config.h>
27 : :
28 : : #include <stdio.h>
29 : : #include <stdlib.h>
30 : : #include <stdarg.h>
31 : : #include <string.h>
32 : :
33 : : /* From gnulib */
34 : : #include "vasnprintf.h"
35 : :
36 : : #include <pdf-alloc.h>
37 : : #include <pdf-global.h>
38 : : #include <pdf-error.h>
39 : :
40 : : extern pdf_char_t *pdf_library_name;
41 : :
42 : : /* Update this list according to pdf_status_t. */
43 : : #define ERROR_ENTRY(id, string) string
44 : : const pdf_char_t * pdf_error_stlist [] =
45 : : {
46 : : PDF_ERROR_LIST
47 : : };
48 : : #undef ERROR_ENTRY
49 : :
50 : : /* Update this list according to pdf_error_domain_t. */
51 : : #define ERROR_ENTRY(id, string) string
52 : : const pdf_char_t * pdf_error_domain_stlist [] =
53 : : {
54 : : PDF_ERROR_DOMAIN_LIST
55 : : };
56 : : #undef ERROR_ENTRY
57 : :
58 : : /* Structure of the PDF error object */
59 : : struct pdf_error_s {
60 : : pdf_error_domain_t domain;
61 : : pdf_status_t status;
62 : : pdf_char_t *message;
63 : : };
64 : :
65 : : /* This static constant structure is used as backup when setting a new error and
66 : : * memory allocation of the new error fails. */
67 : : static const pdf_error_t static_enomem_error = {
68 : : .domain = PDF_EDOMAIN_UNDEFINED,
69 : : .status = PDF_ENOMEM,
70 : : .message = "memory allocation failed"
71 : : };
72 : :
73 : : void
74 : 2 : pdf_perror (const pdf_status_t status,
75 : : const pdf_char_t *str)
76 : : {
77 : 2 : pdf_error ((int) status, stderr, str);
78 : 2 : }
79 : :
80 : : void
81 : 20 : pdf_error (const pdf_status_t status,
82 : : FILE *fd,
83 : : const pdf_char_t *format,
84 : : ...)
85 : : {
86 : : va_list args;
87 : : int errnum;
88 : :
89 : 20 : errnum = (int) status;
90 : :
91 [ + + ]: 20 : if (fd == NULL)
92 : 1 : fd = stderr;
93 : :
94 : 20 : fprintf (fd, "%s", pdf_library_name);
95 : :
96 [ + + ]: 20 : if (format != NULL)
97 : : {
98 : 18 : fprintf (fd, ": ");
99 : 18 : va_start (args, format);
100 : 18 : vfprintf (fd, format, args);
101 : 18 : va_end (args);
102 : : }
103 : :
104 [ + + ]: 20 : if (errnum > 0 && errnum < PDF_STATUS_ITEMS)
105 : 14 : fprintf (fd, ": %s", pdf_error_stlist[errnum-1]);
106 : :
107 : 20 : fprintf (fd, ".\n");
108 : 20 : fflush (fd);
109 : 20 : }
110 : :
111 : : static pdf_error_t *
112 : 8699 : error_new_valist (pdf_error_domain_t domain,
113 : : pdf_status_t status,
114 : : const pdf_char_t *format,
115 : : va_list args)
116 : : {
117 : : pdf_error_t *error;
118 : :
119 : 8699 : error = pdf_alloc (sizeof (struct pdf_error_s));
120 [ + - + - + : 17398 : if ((error != NULL) &&
- ]
121 : 8699 : (vasprintf (&(error->message), format, args) >= 0) &&
122 : 8699 : (error->message != NULL))
123 : : {
124 : 8699 : error->status = status;
125 : 8699 : error->domain = domain;
126 : : }
127 : : else
128 : : {
129 [ # # ]: 0 : if (error)
130 : 0 : pdf_dealloc (error);
131 : : /* Set backup enomem error */
132 : 0 : error = (pdf_error_t *)&static_enomem_error;
133 : : }
134 : 8699 : return error;
135 : : }
136 : :
137 : : pdf_error_t *
138 : 217 : pdf_error_new (pdf_error_domain_t domain,
139 : : pdf_status_t status,
140 : : const pdf_char_t *format,
141 : : ...)
142 : : {
143 : : va_list args;
144 : : pdf_error_t *error;
145 : :
146 : 217 : va_start (args, format);
147 : 217 : error = error_new_valist (domain,
148 : : status,
149 : : format,
150 : : args);
151 : 217 : va_end (args);
152 : 217 : return error;
153 : : }
154 : :
155 : : pdf_error_t *
156 : 210 : pdf_error_dup (const pdf_error_t *error)
157 : : {
158 [ - + ]: 210 : PDF_ASSERT_RETURN_VAL (error != NULL, NULL);
159 : :
160 : 210 : return pdf_error_new (error->domain,
161 : : error->status,
162 : 210 : error->message);
163 : : }
164 : :
165 : : pdf_status_t
166 : 26 : pdf_error_get_status (const pdf_error_t *error)
167 : : {
168 [ - + ]: 26 : PDF_ASSERT_RETURN_VAL (error != NULL, PDF_EBADDATA);
169 : :
170 : 26 : return error->status;
171 : : }
172 : :
173 : : pdf_error_domain_t
174 : 7 : pdf_error_get_domain (const pdf_error_t *error)
175 : : {
176 [ - + ]: 7 : PDF_ASSERT_RETURN_VAL (error != NULL, PDF_EDOMAIN_UNDEFINED);
177 : :
178 : 7 : return error->domain;
179 : : }
180 : :
181 : : const pdf_char_t *
182 : 7 : pdf_error_get_message (const pdf_error_t *error)
183 : : {
184 [ - + ]: 7 : PDF_ASSERT_RETURN_VAL (error != NULL, NULL);
185 : :
186 : 7 : return error->message;
187 : : }
188 : :
189 : : void
190 : 8537 : pdf_error_destroy (pdf_error_t *error)
191 : : {
192 [ + - ][ + - ]: 8537 : if (error != NULL &&
193 : : error != &static_enomem_error)
194 : : {
195 : 8537 : pdf_dealloc (error->message);
196 : 8537 : pdf_dealloc (error);
197 : : }
198 : 8537 : }
199 : :
200 : : void
201 : 8484 : pdf_set_error (pdf_error_t **err,
202 : : pdf_error_domain_t domain,
203 : : pdf_status_t status,
204 : : const pdf_char_t *format,
205 : : ...)
206 : : {
207 [ + + ]: 8484 : if (err != NULL)
208 : : {
209 : : va_list args;
210 : :
211 [ - + ]: 8482 : PDF_ASSERT (*err == NULL);
212 : :
213 : : #ifdef PDF_HAVE_DEBUG_BASE
214 : : if (*err != NULL)
215 : : PDF_DEBUG_BASE (" Previous error contents: %s",
216 : : (*err)->message);
217 : : #endif /* PDF_HAVE_DEBUG_BASE */
218 : :
219 : 8482 : va_start (args, format);
220 : 8482 : *err = error_new_valist (domain,
221 : : status,
222 : : format,
223 : : args);
224 : 8482 : va_end (args);
225 : : }
226 : 8484 : }
227 : :
228 : : void
229 : 7923 : pdf_prefix_error (pdf_error_t **err,
230 : : const pdf_char_t *format,
231 : : ...)
232 : : {
233 [ + + ][ + + ]: 7923 : if ((err != NULL) &&
[ + - ]
234 : 7921 : (*err != NULL) &&
235 : 7919 : (*err != &static_enomem_error))
236 : : {
237 : 7919 : pdf_char_t *new_message = NULL;
238 : : va_list args;
239 : 7919 : pdf_bool_t enomem = PDF_FALSE;
240 : :
241 : 7919 : va_start (args, format);
242 [ + - + - ]: 7919 : if ((vasprintf (&new_message, format, args) >= 0) &&
243 : 7919 : (new_message != NULL))
244 : : {
245 : : pdf_char_t *prefixed;
246 : : pdf_size_t new_message_len;
247 : :
248 : 7919 : new_message_len = (strlen (new_message) + strlen ((*err)->message) + 1);
249 : 7919 : prefixed = pdf_realloc (new_message, new_message_len);
250 [ - + ]: 7919 : if (!prefixed)
251 : : {
252 : 0 : pdf_dealloc (new_message);
253 : 0 : enomem = PDF_TRUE;
254 : : }
255 : : else
256 : : {
257 : 7919 : strcat (prefixed, (*err)->message);
258 : 7919 : prefixed[new_message_len - 1] = '\0';
259 : 7919 : pdf_dealloc ((*err)->message);
260 : 7919 : (*err)->message = prefixed;
261 : : }
262 : : }
263 : : else
264 : 0 : enomem = PDF_TRUE;
265 : :
266 [ - + ]: 7919 : if (enomem)
267 : : {
268 : : /* Oops, ENOMEM */
269 [ # # ]: 0 : if (new_message)
270 : 0 : pdf_dealloc (new_message);
271 : 0 : pdf_error_destroy (*err);
272 : : /* Set backup enomem error */
273 : 0 : *err = (pdf_error_t *)&static_enomem_error;
274 : : }
275 : 7919 : va_end (args);
276 : : }
277 : 7923 : }
278 : :
279 : : void
280 : 8090 : pdf_clear_error (pdf_error_t **err)
281 : : {
282 [ + + ][ + + ]: 8090 : if ((err == NULL) ||
283 : 8089 : (*err == NULL))
284 : : return;
285 : :
286 : 7822 : pdf_error_destroy (*err);
287 : 8090 : *err = NULL;
288 : : }
289 : :
290 : : void
291 : 212 : pdf_propagate_error (pdf_error_t **dest,
292 : : pdf_error_t *src)
293 : : {
294 [ - + ]: 212 : PDF_ASSERT_RETURN (src != NULL);
295 : :
296 [ + + ]: 212 : if (dest == NULL)
297 : 71 : pdf_error_destroy (src);
298 : : else
299 : 212 : *dest = src;
300 : : }
301 : :
302 : : void
303 : 210 : pdf_propagate_error_dup (pdf_error_t **dest,
304 : : const pdf_error_t *src)
305 : : {
306 [ - + ]: 210 : PDF_ASSERT_RETURN (src != NULL);
307 : :
308 [ + - ]: 210 : if (dest)
309 : 210 : *dest = pdf_error_dup (src);
310 : : }
311 : :
312 : : /* End of pdf-error.c */
|