Line | Count | Source |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /*------------------------------------------------------------------------- |
14 | | * |
15 | | * Created: H5Eint.c |
16 | | * |
17 | | * Purpose: General use, "internal" routines for error handling. |
18 | | * |
19 | | *------------------------------------------------------------------------- |
20 | | */ |
21 | | |
22 | | /****************/ |
23 | | /* Module Setup */ |
24 | | /****************/ |
25 | | |
26 | | #include "H5Emodule.h" /* This source code file is part of the H5E module */ |
27 | | |
28 | | /***********/ |
29 | | /* Headers */ |
30 | | /***********/ |
31 | | #include "H5private.h" /* Generic Functions */ |
32 | | #include "H5Epkg.h" /* Error handling */ |
33 | | #include "H5FLprivate.h" /* Free lists */ |
34 | | #include "H5Iprivate.h" /* IDs */ |
35 | | #include "H5MMprivate.h" /* Memory management */ |
36 | | #include "H5TSprivate.h" /* Thread stuff */ |
37 | | |
38 | | /****************/ |
39 | | /* Local Macros */ |
40 | | /****************/ |
41 | | |
42 | | /* HDF5 error class */ |
43 | | #define H5E_CLS_NAME "HDF5" |
44 | | #define H5E_CLS_LIB_NAME "HDF5" |
45 | | |
46 | | /******************/ |
47 | | /* Local Typedefs */ |
48 | | /******************/ |
49 | | |
50 | | /* Printing information */ |
51 | | typedef struct H5E_print_t { |
52 | | FILE *stream; |
53 | | H5E_cls_t cls; |
54 | | } H5E_print_t; |
55 | | |
56 | | /********************/ |
57 | | /* Package Typedefs */ |
58 | | /********************/ |
59 | | |
60 | | /********************/ |
61 | | /* Local Prototypes */ |
62 | | /********************/ |
63 | | #ifndef H5_NO_DEPRECATED_SYMBOLS |
64 | | static herr_t H5E__walk1_cb(int n, H5E_error1_t *err_desc, void *client_data); |
65 | | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
66 | | static herr_t H5E__walk2_cb(unsigned n, const H5E_error2_t *err_desc, void *client_data); |
67 | | static herr_t H5E__copy_stack_entry(H5E_entry_t *dst_entry, const H5E_entry_t *src_entry); |
68 | | static herr_t H5E__set_stack_entry(H5E_error2_t *err_entry, const char *file, const char *func, unsigned line, |
69 | | hid_t cls_id, hid_t maj_id, hid_t min_id, const char *desc, va_list *ap); |
70 | | static herr_t H5E__clear_entries(H5E_stack_t *estack, size_t nentries); |
71 | | static herr_t H5E__unregister_class(void *cls, void **request); |
72 | | static int H5E__close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata); |
73 | | static void H5E__free_msg(H5E_msg_t *msg); |
74 | | static herr_t H5E__close_msg(void *err, void **request); |
75 | | static herr_t H5E__close_stack(void *err_stack, void **request); |
76 | | |
77 | | /*********************/ |
78 | | /* Package Variables */ |
79 | | /*********************/ |
80 | | |
81 | | #ifndef H5_HAVE_THREADSAFE_API |
82 | | /* |
83 | | * The current error stack. |
84 | | */ |
85 | | H5E_stack_t H5E_stack_g[1]; |
86 | | #endif /* H5_HAVE_THREADSAFE_API */ |
87 | | |
88 | | /* Declare a free list to manage the H5E_stack_t struct */ |
89 | | H5FL_DEFINE(H5E_stack_t); |
90 | | |
91 | | /* Declare a free list to manage the H5E_cls_t struct */ |
92 | | H5FL_DEFINE_STATIC(H5E_cls_t); |
93 | | |
94 | | /* Declare a free list to manage the H5E_msg_t struct */ |
95 | | H5FL_DEFINE_STATIC(H5E_msg_t); |
96 | | |
97 | | /*****************************/ |
98 | | /* Library Private Variables */ |
99 | | /*****************************/ |
100 | | |
101 | | /* HDF5 error class ID */ |
102 | | hid_t H5E_ERR_CLS_g = FAIL; |
103 | | |
104 | | /* |
105 | | * Predefined errors. These are initialized at runtime in H5E_init_interface() |
106 | | * in this source file. |
107 | | */ |
108 | | /* Include the automatically generated error code definitions */ |
109 | | #include "H5Edefin.h" |
110 | | |
111 | | /*******************/ |
112 | | /* Local Variables */ |
113 | | /*******************/ |
114 | | |
115 | | /* Default value to initialize error stacks */ |
116 | | static const H5E_stack_t H5E_err_stack_def = { |
117 | | 0, /* nused */ |
118 | | { /*entries[] */ |
119 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
120 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
121 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
122 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
123 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
124 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
125 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
126 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
127 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
128 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
129 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
130 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
131 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
132 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
133 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
134 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
135 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
136 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
137 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
138 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
139 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
140 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
141 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
142 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
143 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
144 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
145 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
146 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
147 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
148 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
149 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}, |
150 | | {false, {H5I_INVALID_HID, H5I_INVALID_HID, H5I_INVALID_HID, 0, NULL, NULL, NULL}}}, |
151 | | |
152 | | /* H5E_auto_op_t */ |
153 | | #ifndef H5_NO_DEPRECATED_SYMBOLS |
154 | | #ifdef H5_USE_16_API_DEFAULT |
155 | | {1, true, (H5E_auto1_t)H5Eprint1, H5E__print2, (H5E_auto1_t)H5Eprint1, H5E__print2}, |
156 | | #else /* H5_USE_16_API */ |
157 | | {2, true, (H5E_auto1_t)H5Eprint1, H5E__print2, (H5E_auto1_t)H5Eprint1, H5E__print2}, |
158 | | #endif /* H5_USE_16_API_DEFAULT */ |
159 | | #else /* H5_NO_DEPRECATED_SYMBOLS */ |
160 | | {H5E__print2}, |
161 | | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
162 | | |
163 | | NULL, /* auto_data */ |
164 | | 0 /* paused */ |
165 | | }; |
166 | | |
167 | | /* First & last major and minor error codes registered by the library */ |
168 | | hid_t H5E_first_maj_id_g = H5I_INVALID_HID; |
169 | | hid_t H5E_last_maj_id_g = H5I_INVALID_HID; |
170 | | hid_t H5E_first_min_id_g = H5I_INVALID_HID; |
171 | | hid_t H5E_last_min_id_g = H5I_INVALID_HID; |
172 | | |
173 | | /* Error class ID class */ |
174 | | static const H5I_class_t H5I_ERRCLS_CLS[1] = {{ |
175 | | H5I_ERROR_CLASS, /* ID class value */ |
176 | | 0, /* Class flags */ |
177 | | 0, /* # of reserved IDs for class */ |
178 | | H5E__unregister_class /* Callback routine for closing objects of this class */ |
179 | | }}; |
180 | | |
181 | | /* Error message ID class */ |
182 | | static const H5I_class_t H5I_ERRMSG_CLS[1] = {{ |
183 | | H5I_ERROR_MSG, /* ID class value */ |
184 | | 0, /* Class flags */ |
185 | | 0, /* # of reserved IDs for class */ |
186 | | H5E__close_msg /* Callback routine for closing objects of this class */ |
187 | | }}; |
188 | | |
189 | | /* Error stack ID class */ |
190 | | static const H5I_class_t H5I_ERRSTK_CLS[1] = {{ |
191 | | H5I_ERROR_STACK, /* ID class value */ |
192 | | 0, /* Class flags */ |
193 | | 0, /* # of reserved IDs for class */ |
194 | | H5E__close_stack /* Callback routine for closing objects of this class */ |
195 | | }}; |
196 | | |
197 | | /* Library's error class */ |
198 | | static const H5E_cls_t H5E_err_cls_s = {false, H5E_CLS_NAME, H5E_CLS_LIB_NAME, H5_VERS_STR}; |
199 | | |
200 | | /* Include the automatically generated major error message definitions */ |
201 | | #include "H5Emajdef.h" |
202 | | |
203 | | /* Include the automatically generated minor error message definitions */ |
204 | | #include "H5Emindef.h" |
205 | | |
206 | | /*------------------------------------------------------------------------- |
207 | | * Function: H5E_init |
208 | | * |
209 | | * Purpose: Initialize the interface from some other layer. |
210 | | * |
211 | | * Return: Success: non-negative |
212 | | * Failure: negative |
213 | | *------------------------------------------------------------------------- |
214 | | */ |
215 | | herr_t |
216 | | H5E_init(void) |
217 | 1 | { |
218 | 1 | herr_t ret_value = SUCCEED; /* Return value */ |
219 | | |
220 | 1 | FUNC_ENTER_NOAPI(FAIL) |
221 | | /* FUNC_ENTER() does all the work */ |
222 | | |
223 | 1 | done: |
224 | 1 | FUNC_LEAVE_NOAPI(ret_value) |
225 | 1 | } /* end H5E_init() */ |
226 | | |
227 | | /*-------------------------------------------------------------------------- |
228 | | * Function: H5E__init_package |
229 | | * |
230 | | * Purpose: Initialize interface-specific information |
231 | | * |
232 | | * Return: SUCCEED/FAIL |
233 | | * |
234 | | * Programmer: Raymond Lu |
235 | | * Friday, July 11, 2003 |
236 | | * |
237 | | *-------------------------------------------------------------------------- |
238 | | */ |
239 | | herr_t |
240 | | H5E__init_package(void) |
241 | 1 | { |
242 | 1 | herr_t ret_value = SUCCEED; /* Return value */ |
243 | | |
244 | 1 | FUNC_ENTER_PACKAGE |
245 | | |
246 | | /* Initialize the ID group for the error class IDs */ |
247 | 1 | if (H5I_register_type(H5I_ERRCLS_CLS) < 0) |
248 | 0 | HGOTO_ERROR(H5E_ID, H5E_CANTINIT, FAIL, "unable to initialize ID group"); |
249 | | |
250 | | /* Initialize the ID group for the major error IDs */ |
251 | 1 | if (H5I_register_type(H5I_ERRMSG_CLS) < 0) |
252 | 0 | HGOTO_ERROR(H5E_ID, H5E_CANTINIT, FAIL, "unable to initialize ID group"); |
253 | | |
254 | | /* Initialize the ID group for the error stacks */ |
255 | 1 | if (H5I_register_type(H5I_ERRSTK_CLS) < 0) |
256 | 0 | HGOTO_ERROR(H5E_ID, H5E_CANTINIT, FAIL, "unable to initialize ID group"); |
257 | | |
258 | 1 | #ifndef H5_HAVE_THREADSAFE_API |
259 | 1 | H5E__set_default_auto(H5E_stack_g); |
260 | 1 | #endif /* H5_HAVE_THREADSAFE_API */ |
261 | | |
262 | | /* Register the HDF5 error class */ |
263 | 1 | if ((H5E_ERR_CLS_g = H5I_register(H5I_ERROR_CLASS, &H5E_err_cls_s, false)) < 0) |
264 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error class"); |
265 | | |
266 | | /* Include the automatically generated error code initialization */ |
267 | 182 | #include "H5Einit.h" |
268 | | |
269 | 182 | done: |
270 | 1 | FUNC_LEAVE_NOAPI(ret_value) |
271 | 1 | } /* end H5E__init_package() */ |
272 | | |
273 | | /*------------------------------------------------------------------------- |
274 | | * Function: H5E_term_package |
275 | | * |
276 | | * Purpose: Terminates the H5E interface |
277 | | * |
278 | | * Return: Success: Positive if anything is done that might |
279 | | * affect other interfaces; zero otherwise. |
280 | | * |
281 | | * Failure: Negative |
282 | | * |
283 | | *------------------------------------------------------------------------- |
284 | | */ |
285 | | int |
286 | | H5E_term_package(void) |
287 | 3 | { |
288 | 3 | int n = 0; |
289 | | |
290 | 3 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
291 | | |
292 | 2 | if (H5_PKG_INIT_VAR) { |
293 | 2 | int64_t ncls, nmsg, nstk; |
294 | | |
295 | | /* Check if there are any open error stacks, classes or messages */ |
296 | 2 | ncls = H5I_nmembers(H5I_ERROR_CLASS); |
297 | 2 | nmsg = H5I_nmembers(H5I_ERROR_MSG); |
298 | 2 | nstk = H5I_nmembers(H5I_ERROR_STACK); |
299 | | |
300 | 2 | if ((ncls + nmsg + nstk) > 0) { |
301 | | /* Clear the default error stack. Note that |
302 | | * the following H5I_clear_type calls do not |
303 | | * force the clears and will not be able to |
304 | | * clear any error message IDs that are still |
305 | | * in use by the default error stack unless we |
306 | | * clear that stack manually. |
307 | | * |
308 | | * Error message IDs will typically still be |
309 | | * in use by the default error stack when the |
310 | | * application does H5E_BEGIN/END_TRY cleanup |
311 | | * at the very end. |
312 | | */ |
313 | 1 | H5E_clear_stack(); |
314 | | |
315 | | /* Clear any outstanding error stacks */ |
316 | 1 | if (nstk > 0) |
317 | 0 | (void)H5I_clear_type(H5I_ERROR_STACK, false, false); |
318 | | |
319 | | /* Clear all the error classes */ |
320 | 1 | if (ncls > 0) { |
321 | 1 | (void)H5I_clear_type(H5I_ERROR_CLASS, false, false); |
322 | | |
323 | | /* Reset the HDF5 error class, if its been closed */ |
324 | 1 | if (H5I_nmembers(H5I_ERROR_CLASS) == 0) |
325 | 1 | H5E_ERR_CLS_g = H5I_INVALID_HID; |
326 | 1 | } /* end if */ |
327 | | |
328 | | /* Clear all the error messages */ |
329 | 1 | if (nmsg > 0) { |
330 | 1 | (void)H5I_clear_type(H5I_ERROR_MSG, false, false); |
331 | | |
332 | | /* Reset the HDF5 error messages, if they've been closed */ |
333 | 1 | if (H5I_nmembers(H5I_ERROR_MSG) == 0) { |
334 | | /* Include the automatically generated error code termination */ |
335 | 1 | #include "H5Eterm.h" |
336 | 1 | } /* end if */ |
337 | 1 | } /* end if */ |
338 | | |
339 | 1 | n++; /*H5I*/ |
340 | 1 | } /* end if */ |
341 | 1 | else { |
342 | | /* Destroy the error class, message, and stack id groups */ |
343 | 1 | n += (H5I_dec_type_ref(H5I_ERROR_STACK) > 0); |
344 | 1 | n += (H5I_dec_type_ref(H5I_ERROR_CLASS) > 0); |
345 | 1 | n += (H5I_dec_type_ref(H5I_ERROR_MSG) > 0); |
346 | | |
347 | | /* Mark closed */ |
348 | 1 | if (0 == n) |
349 | 1 | H5_PKG_INIT_VAR = false; |
350 | 1 | } /* end else */ |
351 | 2 | } /* end if */ |
352 | | |
353 | 2 | FUNC_LEAVE_NOAPI(n) |
354 | 3 | } /* end H5E_term_package() */ |
355 | | |
356 | | /*------------------------------------------------------------------------- |
357 | | * Function: H5E_user_cb_prepare |
358 | | * |
359 | | * Purpose: Prepare the H5E package before a user callback |
360 | | * |
361 | | * Return: SUCCEED/FAIL |
362 | | * |
363 | | *------------------------------------------------------------------------- |
364 | | */ |
365 | | herr_t |
366 | | H5E_user_cb_prepare(H5E_user_cb_state_t *state) |
367 | 1.06k | { |
368 | 1.06k | H5E_stack_t *stack; /* Pointer to the current error stack */ |
369 | 1.06k | herr_t ret_value = SUCCEED; /* Return value */ |
370 | | |
371 | 1.06k | FUNC_ENTER_NOAPI(FAIL) |
372 | | |
373 | | /* Get a pointer to the current error stack */ |
374 | 1.06k | if (NULL == (stack = H5E__get_my_stack())) |
375 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack"); |
376 | | |
377 | | /* Save state for current error stack */ |
378 | 1.06k | #ifndef H5_NO_DEPRECATED_SYMBOLS |
379 | 1.06k | assert(1 == stack->auto_op.vers || 2 == stack->auto_op.vers); |
380 | | |
381 | 1.06k | state->vers = stack->auto_op.vers; |
382 | 1.06k | if (1 == stack->auto_op.vers) |
383 | 0 | state->u.func1 = stack->auto_op.func1; |
384 | 1.06k | else |
385 | 1.06k | state->u.func2 = stack->auto_op.func2; |
386 | | #else /* H5_NO_DEPRECATED_SYMBOLS */ |
387 | | state->func2 = stack->auto_op.func2; |
388 | | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
389 | 1.06k | state->data = stack->auto_data; |
390 | | |
391 | 1.06k | done: |
392 | 1.06k | FUNC_LEAVE_NOAPI(ret_value) |
393 | 1.06k | } /* end H5E_user_cb_prepare() */ |
394 | | |
395 | | /*------------------------------------------------------------------------- |
396 | | * Function: H5E_user_cb_restore |
397 | | * |
398 | | * Purpose: Restores the state of the H5E package after a user callback |
399 | | * |
400 | | * Return: SUCCEED/FAIL |
401 | | * |
402 | | *------------------------------------------------------------------------- |
403 | | */ |
404 | | herr_t |
405 | | H5E_user_cb_restore(const H5E_user_cb_state_t *state) |
406 | 1.06k | { |
407 | 1.06k | H5E_stack_t *stack; /* Pointer to the current error stack */ |
408 | 1.06k | herr_t ret_value = SUCCEED; /* Return value */ |
409 | | |
410 | 1.06k | FUNC_ENTER_NOAPI(FAIL) |
411 | | |
412 | | /* Get a pointer to the current error stack */ |
413 | 1.06k | if (NULL == (stack = H5E__get_my_stack())) |
414 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack"); |
415 | | |
416 | | /* Restore state for current error stack */ |
417 | 1.06k | #ifndef H5_NO_DEPRECATED_SYMBOLS |
418 | 1.06k | stack->auto_op.vers = state->vers; |
419 | 1.06k | if (1 == state->vers) |
420 | 0 | stack->auto_op.func1 = state->u.func1; |
421 | 1.06k | else |
422 | 1.06k | stack->auto_op.func2 = state->u.func2; |
423 | | #else /* H5_NO_DEPRECATED_SYMBOLS */ |
424 | | stack->auto_op.func2 = state->func2; |
425 | | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
426 | 1.06k | stack->auto_data = state->data; |
427 | | |
428 | 1.06k | done: |
429 | 1.06k | FUNC_LEAVE_NOAPI(ret_value) |
430 | 1.06k | } /* end H5E_user_cb_restore() */ |
431 | | |
432 | | /*------------------------------------------------------------------------- |
433 | | * Function: H5E__free_class |
434 | | * |
435 | | * Purpose: Private function to free an error class. |
436 | | * |
437 | | * Return: SUCCEED/FAIL |
438 | | * |
439 | | *------------------------------------------------------------------------- |
440 | | */ |
441 | | static herr_t |
442 | | H5E__free_class(H5E_cls_t *cls) |
443 | 1 | { |
444 | 1 | FUNC_ENTER_PACKAGE_NOERR |
445 | | |
446 | | /* Check arguments */ |
447 | 1 | assert(cls); |
448 | | |
449 | | /* Free resources, if application registered this class */ |
450 | 1 | if (cls->app_cls) { |
451 | | /* Free error class structure */ |
452 | 0 | cls->cls_name = H5MM_xfree_const(cls->cls_name); |
453 | 0 | cls->lib_name = H5MM_xfree_const(cls->lib_name); |
454 | 0 | cls->lib_vers = H5MM_xfree_const(cls->lib_vers); |
455 | 0 | cls = H5FL_FREE(H5E_cls_t, cls); |
456 | 0 | } |
457 | | |
458 | 1 | FUNC_LEAVE_NOAPI(SUCCEED) |
459 | 1 | } /* end H5E__free_class() */ |
460 | | |
461 | | /*------------------------------------------------------------------------- |
462 | | * Function: H5E__register_class |
463 | | * |
464 | | * Purpose: Private function to register an error class. |
465 | | * |
466 | | * Return: Success: Pointer to an error class struct |
467 | | * Failure: NULL |
468 | | * |
469 | | *------------------------------------------------------------------------- |
470 | | */ |
471 | | H5E_cls_t * |
472 | | H5E__register_class(const char *cls_name, const char *lib_name, const char *version) |
473 | 0 | { |
474 | 0 | H5E_cls_t *cls = NULL; /* Pointer to error class */ |
475 | 0 | H5E_cls_t *ret_value = NULL; /* Return value */ |
476 | |
|
477 | 0 | FUNC_ENTER_PACKAGE |
478 | | |
479 | | /* Check arguments */ |
480 | 0 | assert(cls_name); |
481 | 0 | assert(lib_name); |
482 | 0 | assert(version); |
483 | | |
484 | | /* Allocate space for new error class */ |
485 | 0 | if (NULL == (cls = H5FL_CALLOC(H5E_cls_t))) |
486 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
487 | | |
488 | | /* Application registered class */ |
489 | 0 | cls->app_cls = true; |
490 | | |
491 | | /* Duplicate string information */ |
492 | 0 | if (NULL == (cls->cls_name = strdup(cls_name))) |
493 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
494 | 0 | if (NULL == (cls->lib_name = strdup(lib_name))) |
495 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
496 | 0 | if (NULL == (cls->lib_vers = strdup(version))) |
497 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
498 | | |
499 | | /* Set the return value */ |
500 | 0 | ret_value = cls; |
501 | |
|
502 | 0 | done: |
503 | 0 | if (!ret_value) |
504 | 0 | if (cls && H5E__free_class(cls) < 0) |
505 | 0 | HDONE_ERROR(H5E_ERROR, H5E_CANTRELEASE, NULL, "unable to free error class"); |
506 | |
|
507 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
508 | 0 | } /* end H5E__register_class() */ |
509 | | |
510 | | /*------------------------------------------------------------------------- |
511 | | * Function: H5E__unregister_class |
512 | | * |
513 | | * Purpose: Private function to close an error class. |
514 | | * |
515 | | * Return: SUCCEED/FAIL |
516 | | * |
517 | | *------------------------------------------------------------------------- |
518 | | */ |
519 | | static herr_t |
520 | | H5E__unregister_class(void *cls, void H5_ATTR_UNUSED **request) |
521 | 1 | { |
522 | 1 | H5E_cls_t *cls_p = (H5E_cls_t *)cls; |
523 | 1 | herr_t ret_value = SUCCEED; /* Return value */ |
524 | | |
525 | 1 | FUNC_ENTER_PACKAGE |
526 | | |
527 | | /* Check arguments */ |
528 | 1 | assert(cls_p); |
529 | | |
530 | | /* Iterate over all the messages and delete those in this error class */ |
531 | 1 | if (H5I_iterate(H5I_ERROR_MSG, H5E__close_msg_cb, cls_p, false) < 0) |
532 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_BADITER, FAIL, "unable to free all messages in this error class"); |
533 | | |
534 | | /* Free error class structure */ |
535 | 1 | if (H5E__free_class(cls_p) < 0) |
536 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, FAIL, "unable to free error class"); |
537 | | |
538 | 1 | done: |
539 | 1 | FUNC_LEAVE_NOAPI(ret_value) |
540 | 1 | } /* end H5E__unregister_class() */ |
541 | | |
542 | | /*------------------------------------------------------------------------- |
543 | | * Function: H5E__get_class_name |
544 | | * |
545 | | * Purpose: Private function to retrieve error class name. |
546 | | * |
547 | | * Return: Success: Name length (zero means no name) |
548 | | * Failure: -1 |
549 | | * |
550 | | *------------------------------------------------------------------------- |
551 | | */ |
552 | | ssize_t |
553 | | H5E__get_class_name(const H5E_cls_t *cls, char *name, size_t size) |
554 | 0 | { |
555 | 0 | ssize_t len = -1; /* Length of error class's name */ |
556 | |
|
557 | 0 | FUNC_ENTER_PACKAGE_NOERR |
558 | | |
559 | | /* Check arguments */ |
560 | 0 | assert(cls); |
561 | | |
562 | | /* Get the class's name */ |
563 | 0 | len = (ssize_t)strlen(cls->cls_name); |
564 | | |
565 | | /* Set the user's buffer, if provided */ |
566 | 0 | if (name) { |
567 | 0 | strncpy(name, cls->cls_name, size); |
568 | 0 | if ((size_t)len >= size) |
569 | 0 | name[size - 1] = '\0'; |
570 | 0 | } /* end if */ |
571 | | |
572 | | /* Return the full length */ |
573 | 0 | FUNC_LEAVE_NOAPI(len) |
574 | 0 | } /* end H5E__get_class_name() */ |
575 | | |
576 | | /*------------------------------------------------------------------------- |
577 | | * Function: H5E__close_msg_cb |
578 | | * |
579 | | * Purpose: H5I_iterate callback function to close error messages in the |
580 | | * error class. |
581 | | * |
582 | | * Return: Success: H5_ITER_CONT (0) |
583 | | * Failure: H5_ITER_ERROR (-1) |
584 | | * |
585 | | *------------------------------------------------------------------------- |
586 | | */ |
587 | | static int |
588 | | H5E__close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata) |
589 | 181 | { |
590 | 181 | H5E_msg_t *err_msg = (H5E_msg_t *)obj_ptr; |
591 | 181 | H5E_cls_t *cls = (H5E_cls_t *)udata; |
592 | 181 | int ret_value = H5_ITER_CONT; /* Return value */ |
593 | | |
594 | 181 | FUNC_ENTER_PACKAGE |
595 | | |
596 | | /* Check arguments */ |
597 | 181 | assert(err_msg); |
598 | | |
599 | | /* Close the message if it is in the class being closed */ |
600 | 181 | if (err_msg->cls == cls) { |
601 | 181 | if (H5E__close_msg(err_msg, NULL) < 0) |
602 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTCLOSEOBJ, H5_ITER_ERROR, "unable to close error message"); |
603 | 181 | if (NULL == H5I_remove(obj_id)) |
604 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTREMOVE, H5_ITER_ERROR, "unable to remove error message"); |
605 | 181 | } /* end if */ |
606 | | |
607 | 181 | done: |
608 | 181 | FUNC_LEAVE_NOAPI(ret_value) |
609 | 181 | } /* end H5E__close_msg_cb() */ |
610 | | |
611 | | /*------------------------------------------------------------------------- |
612 | | * Function: H5E__free_msg |
613 | | * |
614 | | * Purpose: Private function to free an application error message. |
615 | | * |
616 | | * Return: none |
617 | | * |
618 | | *------------------------------------------------------------------------- |
619 | | */ |
620 | | static void |
621 | | H5E__free_msg(H5E_msg_t *msg) |
622 | 0 | { |
623 | 0 | FUNC_ENTER_PACKAGE_NOERR |
624 | | |
625 | | /* Check arguments */ |
626 | 0 | assert(msg); |
627 | 0 | assert(msg->app_msg); |
628 | | |
629 | | /* Free resources */ |
630 | 0 | msg->msg = H5MM_xfree_const(msg->msg); |
631 | 0 | msg = H5FL_FREE(H5E_msg_t, msg); |
632 | |
|
633 | 0 | FUNC_LEAVE_NOAPI_VOID |
634 | 0 | } /* end H5E__free_msg() */ |
635 | | |
636 | | /*------------------------------------------------------------------------- |
637 | | * Function: H5E__close_msg |
638 | | * |
639 | | * Purpose: Private function to close an error message. |
640 | | * |
641 | | * Return: SUCCEED/FAIL |
642 | | * |
643 | | *------------------------------------------------------------------------- |
644 | | */ |
645 | | static herr_t |
646 | | H5E__close_msg(void *err, void H5_ATTR_UNUSED **request) |
647 | 181 | { |
648 | 181 | H5E_msg_t *err_p = (H5E_msg_t *)err; |
649 | | |
650 | 181 | FUNC_ENTER_PACKAGE_NOERR |
651 | | |
652 | | /* Check arguments */ |
653 | 181 | assert(err_p); |
654 | | |
655 | | /* Free resources, if application registered this message */ |
656 | 181 | if (err_p->app_msg) |
657 | | /* Free message */ |
658 | 0 | H5E__free_msg(err_p); |
659 | | |
660 | 181 | FUNC_LEAVE_NOAPI(SUCCEED) |
661 | 181 | } /* end H5E__close_msg() */ |
662 | | |
663 | | /*------------------------------------------------------------------------- |
664 | | * Function: H5E__create_msg |
665 | | * |
666 | | * Purpose: Private function to create a major or minor error. |
667 | | * |
668 | | * Return: Success: Pointer to a message struct |
669 | | * Failure: NULL |
670 | | * |
671 | | *------------------------------------------------------------------------- |
672 | | */ |
673 | | H5E_msg_t * |
674 | | H5E__create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg_str) |
675 | 0 | { |
676 | 0 | H5E_msg_t *msg = NULL; /* Pointer to new error message */ |
677 | 0 | H5E_msg_t *ret_value = NULL; /* Return value */ |
678 | |
|
679 | 0 | FUNC_ENTER_PACKAGE |
680 | | |
681 | | /* Check arguments */ |
682 | 0 | assert(cls); |
683 | 0 | assert(msg_type == H5E_MAJOR || msg_type == H5E_MINOR); |
684 | 0 | assert(msg_str); |
685 | | |
686 | | /* Allocate new message object */ |
687 | 0 | if (NULL == (msg = H5FL_CALLOC(H5E_msg_t))) |
688 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTALLOC, NULL, "memory allocation failed"); |
689 | | |
690 | | /* Fill new message object */ |
691 | 0 | msg->app_msg = true; |
692 | 0 | msg->cls = cls; |
693 | 0 | msg->type = msg_type; |
694 | 0 | if (NULL == (msg->msg = strdup(msg_str))) |
695 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTALLOC, NULL, "memory allocation failed"); |
696 | | |
697 | | /* Set return value */ |
698 | 0 | ret_value = msg; |
699 | |
|
700 | 0 | done: |
701 | 0 | if (!ret_value) |
702 | 0 | if (msg) |
703 | 0 | H5E__free_msg(msg); |
704 | |
|
705 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
706 | 0 | } /* end H5E__create_msg() */ |
707 | | |
708 | | /*------------------------------------------------------------------------- |
709 | | * Function: H5E__get_current_stack |
710 | | * |
711 | | * Purpose: Private function to register an error stack. |
712 | | * |
713 | | * Return: Success: Pointer to an error class struct |
714 | | * Failure: NULL |
715 | | * |
716 | | *------------------------------------------------------------------------- |
717 | | */ |
718 | | H5E_stack_t * |
719 | | H5E__get_current_stack(void) |
720 | 0 | { |
721 | 0 | H5E_stack_t *current_stack; /* Pointer to the current error stack */ |
722 | 0 | H5E_stack_t *estack_copy = NULL; /* Pointer to new error stack to return */ |
723 | 0 | unsigned u; /* Local index variable */ |
724 | 0 | H5E_stack_t *ret_value = NULL; /* Return value */ |
725 | |
|
726 | 0 | FUNC_ENTER_PACKAGE |
727 | | |
728 | | /* Get a pointer to the current error stack */ |
729 | 0 | if (NULL == (current_stack = H5E__get_my_stack())) |
730 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get current error stack"); |
731 | | |
732 | | /* Allocate a new error stack */ |
733 | 0 | if (NULL == (estack_copy = H5FL_CALLOC(H5E_stack_t))) |
734 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed"); |
735 | | |
736 | | /* Make a copy of current error stack */ |
737 | 0 | estack_copy->nused = current_stack->nused; |
738 | 0 | for (u = 0; u < current_stack->nused; u++) |
739 | 0 | if (H5E__copy_stack_entry(&estack_copy->entries[u], ¤t_stack->entries[u]) < 0) |
740 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, NULL, "can't set error entry"); |
741 | | |
742 | | /* Copy the "automatic" error reporting information */ |
743 | 0 | estack_copy->auto_op = current_stack->auto_op; |
744 | 0 | estack_copy->auto_data = current_stack->auto_data; |
745 | | |
746 | | /* Empty current error stack */ |
747 | 0 | H5E__destroy_stack(current_stack); |
748 | | |
749 | | /* Set the return value */ |
750 | 0 | ret_value = estack_copy; |
751 | |
|
752 | 0 | done: |
753 | 0 | if (ret_value == NULL) |
754 | 0 | if (estack_copy) |
755 | 0 | estack_copy = H5FL_FREE(H5E_stack_t, estack_copy); |
756 | |
|
757 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
758 | 0 | } /* end H5E__get_current_stack() */ |
759 | | |
760 | | /*------------------------------------------------------------------------- |
761 | | * Function: H5E__set_current_stack |
762 | | * |
763 | | * Purpose: Private function to replace an error stack. |
764 | | * |
765 | | * Return: SUCCEED/FAIL |
766 | | * |
767 | | *------------------------------------------------------------------------- |
768 | | */ |
769 | | herr_t |
770 | | H5E__set_current_stack(H5E_stack_t *estack) |
771 | 0 | { |
772 | 0 | H5E_stack_t *current_stack; /* Default error stack */ |
773 | 0 | unsigned u; /* Local index variable */ |
774 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
775 | |
|
776 | 0 | FUNC_ENTER_PACKAGE |
777 | | |
778 | | /* Sanity check */ |
779 | 0 | assert(estack); |
780 | | |
781 | | /* Get a pointer to the current error stack */ |
782 | 0 | if (NULL == (current_stack = H5E__get_my_stack())) |
783 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack"); |
784 | | |
785 | | /* Empty current error stack */ |
786 | 0 | H5E__destroy_stack(current_stack); |
787 | | |
788 | | /* Copy new stack to current error stack */ |
789 | 0 | current_stack->nused = estack->nused; |
790 | 0 | for (u = 0; u < current_stack->nused; u++) |
791 | 0 | if (H5E__copy_stack_entry(¤t_stack->entries[u], &estack->entries[u]) < 0) |
792 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set error entry"); |
793 | | |
794 | 0 | done: |
795 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
796 | 0 | } /* end H5E__set_current_stack() */ |
797 | | |
798 | | /*------------------------------------------------------------------------- |
799 | | * Function: H5E__close_stack |
800 | | * |
801 | | * Purpose: Private function to close an error stack. |
802 | | * |
803 | | * Return: SUCCEED/FAIL |
804 | | * |
805 | | *------------------------------------------------------------------------- |
806 | | */ |
807 | | static herr_t |
808 | | H5E__close_stack(void *estack, void H5_ATTR_UNUSED **request) |
809 | 0 | { |
810 | 0 | H5E_stack_t *estack_p = (H5E_stack_t *)estack; |
811 | |
|
812 | 0 | FUNC_ENTER_PACKAGE_NOERR |
813 | | |
814 | | /* Sanity check */ |
815 | 0 | assert(estack_p); |
816 | | |
817 | | /* Release the stack's error information */ |
818 | 0 | H5E__destroy_stack(estack_p); |
819 | | |
820 | | /* Free the stack structure */ |
821 | 0 | estack_p = H5FL_FREE(H5E_stack_t, estack_p); |
822 | |
|
823 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
824 | 0 | } /* end H5E__close_stack() */ |
825 | | |
826 | | /*------------------------------------------------------------------------- |
827 | | * Function: H5E__get_num |
828 | | * |
829 | | * Purpose: Private function to retrieve number of errors in error stack. |
830 | | * |
831 | | * Return: Success: The number of errors |
832 | | * Failure: -1 (can't fail at this time) |
833 | | * |
834 | | *------------------------------------------------------------------------- |
835 | | */ |
836 | | ssize_t |
837 | | H5E__get_num(const H5E_stack_t *estack) |
838 | 0 | { |
839 | 0 | FUNC_ENTER_PACKAGE_NOERR |
840 | |
|
841 | 0 | assert(estack); |
842 | |
|
843 | 0 | FUNC_LEAVE_NOAPI((ssize_t)estack->nused) |
844 | 0 | } /* end H5E__get_num() */ |
845 | | |
846 | | /*------------------------------------------------------------------------- |
847 | | * Function: H5E__print2 |
848 | | * |
849 | | * Purpose: Internal helper routine for H5Eprint2. |
850 | | * |
851 | | * Return: Non-negative on success/Negative on failure |
852 | | * |
853 | | *------------------------------------------------------------------------- |
854 | | */ |
855 | | herr_t |
856 | | H5E__print2(hid_t err_stack, void *_stream) |
857 | 10 | { |
858 | 10 | H5E_stack_t *estack; /* Error stack to operate on */ |
859 | 10 | FILE *stream = (FILE *)_stream; |
860 | 10 | herr_t ret_value = SUCCEED; /* Return value */ |
861 | | |
862 | 10 | FUNC_ENTER_PACKAGE |
863 | | |
864 | | /* Need to check for errors */ |
865 | 10 | if (err_stack == H5E_DEFAULT) { |
866 | 10 | if (NULL == (estack = H5E__get_my_stack())) |
867 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack"); |
868 | 10 | } /* end if */ |
869 | 0 | else { |
870 | | /* Only clear the error stack if it's not the default stack */ |
871 | 0 | H5E_clear_stack(); |
872 | |
|
873 | 0 | if (NULL == (estack = (H5E_stack_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK))) |
874 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID"); |
875 | 0 | } /* end else */ |
876 | | |
877 | | /* Print error stack */ |
878 | 10 | if (H5E__print(estack, stream, false) < 0) |
879 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack"); |
880 | | |
881 | 10 | done: |
882 | 10 | FUNC_LEAVE_NOAPI(ret_value) |
883 | 10 | } /* end H5E__print2() */ |
884 | | |
885 | | /*------------------------------------------------------------------------- |
886 | | * Function: H5E__append_stack |
887 | | * |
888 | | * Purpose: Private function to append error stacks. |
889 | | * |
890 | | * Return: Non-negative value on success/Negative on failure |
891 | | * |
892 | | *------------------------------------------------------------------------- |
893 | | */ |
894 | | herr_t |
895 | | H5E__append_stack(H5E_stack_t *dst_stack, const H5E_stack_t *src_stack) |
896 | 0 | { |
897 | 0 | unsigned u; /* Local index variable */ |
898 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
899 | |
|
900 | 0 | FUNC_ENTER_PACKAGE |
901 | | |
902 | | /* Sanity checks */ |
903 | 0 | assert(dst_stack); |
904 | 0 | assert(src_stack); |
905 | | |
906 | | /* Copy the errors from the source stack to the destination stack */ |
907 | 0 | for (u = 0; u < src_stack->nused; u++) { |
908 | | /* Copy error stack entry */ |
909 | 0 | if (H5E__copy_stack_entry(&dst_stack->entries[dst_stack->nused], &src_stack->entries[u]) < 0) |
910 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set error entry"); |
911 | | |
912 | | /* Increment # of errors in destination stack */ |
913 | 0 | dst_stack->nused++; |
914 | | |
915 | | /* Check for destination stack full */ |
916 | 0 | if (dst_stack->nused >= H5E_MAX_ENTRIES) |
917 | 0 | break; |
918 | 0 | } /* end for */ |
919 | | |
920 | 0 | done: |
921 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
922 | 0 | } /* end H5E__append_stack() */ |
923 | | |
924 | | /*-------------------------------------------------------------------------- |
925 | | * Function: H5E__set_default_auto |
926 | | * |
927 | | * Purpose: Initialize error stack to library default |
928 | | * |
929 | | * Return: SUCCEED/FAIL |
930 | | * |
931 | | *-------------------------------------------------------------------------- |
932 | | */ |
933 | | void |
934 | | H5E__set_default_auto(H5E_stack_t *stk) |
935 | 1 | { |
936 | 1 | FUNC_ENTER_PACKAGE_NOERR |
937 | | |
938 | | /* Initialize with default error stack */ |
939 | 1 | memcpy(stk, &H5E_err_stack_def, sizeof(H5E_err_stack_def)); |
940 | | |
941 | 1 | FUNC_LEAVE_NOAPI_VOID |
942 | 1 | } /* end H5E__set_default_auto() */ |
943 | | |
944 | | /*------------------------------------------------------------------------- |
945 | | * Function: H5E__get_msg |
946 | | * |
947 | | * Purpose: Private function to retrieve an error message. |
948 | | * |
949 | | * Return: Success: Message length (zero means no message) |
950 | | * Failure: -1 |
951 | | * |
952 | | *------------------------------------------------------------------------- |
953 | | */ |
954 | | ssize_t |
955 | | H5E__get_msg(const H5E_msg_t *msg, H5E_type_t *type, char *msg_str, size_t size) |
956 | 0 | { |
957 | 0 | ssize_t len = -1; /* Length of error message */ |
958 | |
|
959 | 0 | FUNC_ENTER_PACKAGE_NOERR |
960 | | |
961 | | /* Check arguments */ |
962 | 0 | assert(msg); |
963 | | |
964 | | /* Get the length of the message string */ |
965 | 0 | len = (ssize_t)strlen(msg->msg); |
966 | | |
967 | | /* Copy the message into the user's buffer, if given */ |
968 | 0 | if (msg_str) { |
969 | 0 | strncpy(msg_str, msg->msg, size); |
970 | 0 | if ((size_t)len >= size) |
971 | 0 | msg_str[size - 1] = '\0'; |
972 | 0 | } /* end if */ |
973 | | |
974 | | /* Give the message type, if asked */ |
975 | 0 | if (type) |
976 | 0 | *type = msg->type; |
977 | | |
978 | | /* Set the return value to the full length of the message */ |
979 | 0 | FUNC_LEAVE_NOAPI(len) |
980 | 0 | } /* end H5E__get_msg() */ |
981 | | |
982 | | #ifndef H5_NO_DEPRECATED_SYMBOLS |
983 | | |
984 | | /*------------------------------------------------------------------------- |
985 | | * Function: H5E__walk1_cb |
986 | | * |
987 | | * Purpose: This function is for backward compatibility. |
988 | | * This is a default error stack traversal callback function |
989 | | * that prints error messages to the specified output stream. |
990 | | * This function is for backward compatibility with v1.6. |
991 | | * It is not meant to be called directly but rather as an |
992 | | * argument to the H5Ewalk() function. This function is called |
993 | | * also by H5Eprint(). Application writers are encouraged to |
994 | | * use this function as a model for their own error stack |
995 | | * walking functions. |
996 | | * |
997 | | * N is a counter for how many times this function has been |
998 | | * called for this particular traversal of the stack. It always |
999 | | * begins at zero for the first error on the stack (either the |
1000 | | * top or bottom error, or even both, depending on the traversal |
1001 | | * direction and the size of the stack). |
1002 | | * |
1003 | | * ERR_DESC is an error description. It contains all the |
1004 | | * information about a particular error. |
1005 | | * |
1006 | | * CLIENT_DATA is the same pointer that was passed as the |
1007 | | * CLIENT_DATA argument of H5Ewalk(). It is expected to be a |
1008 | | * file pointer (or stderr if null). |
1009 | | * |
1010 | | * Return: SUCCEED/FAIL |
1011 | | * |
1012 | | *------------------------------------------------------------------------- |
1013 | | */ |
1014 | | static herr_t |
1015 | | H5E__walk1_cb(int n, H5E_error1_t *err_desc, void *client_data) |
1016 | 0 | { |
1017 | 0 | H5E_print_t *eprint = (H5E_print_t *)client_data; |
1018 | 0 | FILE *stream; /* I/O stream to print output to */ |
1019 | 0 | const H5E_cls_t *cls_ptr; /* Pointer to error class */ |
1020 | 0 | H5E_msg_t *maj_ptr; /* Pointer to major error info */ |
1021 | 0 | H5E_msg_t *min_ptr; /* Pointer to minor error info */ |
1022 | 0 | const char *maj_str = "No major description"; /* Major error description */ |
1023 | 0 | const char *min_str = "No minor description"; /* Minor error description */ |
1024 | 0 | bool have_desc = true; /* Flag to indicate whether the error has a "real" description */ |
1025 | | #ifdef H5_HAVE_THREADSAFE_API |
1026 | | uint64_t thread_id = 0; /* ID of thread */ |
1027 | | #endif |
1028 | 0 | herr_t ret_value = SUCCEED; |
1029 | |
|
1030 | 0 | FUNC_ENTER_PACKAGE_NOERR |
1031 | | |
1032 | | /* Check arguments */ |
1033 | 0 | assert(err_desc); |
1034 | | |
1035 | | /* If no client data was passed, output to stderr */ |
1036 | 0 | if (!client_data) |
1037 | 0 | stream = stderr; |
1038 | 0 | else |
1039 | 0 | stream = eprint->stream; |
1040 | | |
1041 | | /* Get descriptions for the major and minor error numbers */ |
1042 | 0 | maj_ptr = (H5E_msg_t *)H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG); |
1043 | 0 | min_ptr = (H5E_msg_t *)H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG); |
1044 | | |
1045 | | /* Check for bad pointer(s), but can't issue error, just leave */ |
1046 | 0 | if (!maj_ptr || !min_ptr) |
1047 | 0 | HGOTO_DONE(FAIL); |
1048 | | |
1049 | 0 | if (maj_ptr->msg) |
1050 | 0 | maj_str = maj_ptr->msg; |
1051 | 0 | if (min_ptr->msg) |
1052 | 0 | min_str = min_ptr->msg; |
1053 | | |
1054 | | /* Get error class info */ |
1055 | 0 | cls_ptr = maj_ptr->cls; |
1056 | |
|
1057 | | #ifdef H5_HAVE_THREADSAFE_API |
1058 | | if (H5TS_thread_id(&thread_id) < 0) |
1059 | | HGOTO_DONE(FAIL); |
1060 | | #endif |
1061 | | |
1062 | | /* Print error class header if new class */ |
1063 | 0 | if (eprint->cls.lib_name == NULL || strcmp(cls_ptr->lib_name, eprint->cls.lib_name) != 0) { |
1064 | | /* update to the new class information */ |
1065 | 0 | if (cls_ptr->cls_name) |
1066 | 0 | eprint->cls.cls_name = cls_ptr->cls_name; |
1067 | 0 | if (cls_ptr->lib_name) |
1068 | 0 | eprint->cls.lib_name = cls_ptr->lib_name; |
1069 | 0 | if (cls_ptr->lib_vers) |
1070 | 0 | eprint->cls.lib_vers = cls_ptr->lib_vers; |
1071 | |
|
1072 | 0 | fprintf(stream, "%s-DIAG: Error detected in %s (%s)", |
1073 | 0 | (cls_ptr->cls_name ? cls_ptr->cls_name : "(null)"), |
1074 | 0 | (cls_ptr->lib_name ? cls_ptr->lib_name : "(null)"), |
1075 | 0 | (cls_ptr->lib_vers ? cls_ptr->lib_vers : "(null)")); |
1076 | | |
1077 | | /* try show the process or thread id in multiple processes cases*/ |
1078 | | #ifdef H5_HAVE_PARALLEL |
1079 | | { |
1080 | | int mpi_rank, mpi_initialized, mpi_finalized; |
1081 | | |
1082 | | MPI_Initialized(&mpi_initialized); |
1083 | | MPI_Finalized(&mpi_finalized); |
1084 | | |
1085 | | if (mpi_initialized && !mpi_finalized) { |
1086 | | MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); |
1087 | | fprintf(stream, " MPI-process %d", mpi_rank); |
1088 | | } /* end if */ |
1089 | | #ifdef H5_HAVE_THREADSAFE_API |
1090 | | else |
1091 | | fprintf(stream, " thread %" PRIu64, thread_id); |
1092 | | #endif |
1093 | | } /* end block */ |
1094 | | #else |
1095 | | #ifdef H5_HAVE_THREADSAFE_API |
1096 | | fprintf(stream, " thread %" PRIu64, thread_id); |
1097 | | #endif |
1098 | 0 | #endif |
1099 | 0 | fprintf(stream, ":\n"); |
1100 | 0 | } /* end if */ |
1101 | | |
1102 | | /* Check for "real" error description - used to format output more nicely */ |
1103 | 0 | if (err_desc->desc == NULL || strlen(err_desc->desc) == 0) |
1104 | 0 | have_desc = false; |
1105 | | |
1106 | | /* Print error message */ |
1107 | 0 | fprintf(stream, "%*s#%03d: %s line %u in %s()%s%s\n", H5E_INDENT, "", n, err_desc->file_name, |
1108 | 0 | err_desc->line, err_desc->func_name, (have_desc ? ": " : ""), (have_desc ? err_desc->desc : "")); |
1109 | 0 | fprintf(stream, "%*smajor: %s\n", (H5E_INDENT * 2), "", maj_str); |
1110 | 0 | fprintf(stream, "%*sminor: %s\n", (H5E_INDENT * 2), "", min_str); |
1111 | |
|
1112 | 0 | done: |
1113 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1114 | 0 | } /* end H5E__walk1_cb() */ |
1115 | | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
1116 | | |
1117 | | /*------------------------------------------------------------------------- |
1118 | | * Function: H5E__walk2_cb |
1119 | | * |
1120 | | * Purpose: This is a default error stack traversal callback function |
1121 | | * that prints error messages to the specified output stream. |
1122 | | * It is not meant to be called directly but rather as an |
1123 | | * argument to the H5Ewalk2() function. This function is |
1124 | | * called also by H5Eprint2(). Application writers are |
1125 | | * encouraged to use this function as a model for their own |
1126 | | * error stack walking functions. |
1127 | | * |
1128 | | * N is a counter for how many times this function has been |
1129 | | * called for this particular traversal of the stack. It always |
1130 | | * begins at zero for the first error on the stack (either the |
1131 | | * top or bottom error, or even both, depending on the traversal |
1132 | | * direction and the size of the stack). |
1133 | | * |
1134 | | * ERR_DESC is an error description. It contains all the |
1135 | | * information about a particular error. |
1136 | | * |
1137 | | * CLIENT_DATA is the same pointer that was passed as the |
1138 | | * CLIENT_DATA argument of H5Ewalk(). It is expected to be a |
1139 | | * file pointer (or stderr if null). |
1140 | | * |
1141 | | * Return: SUCCEED/FAIL |
1142 | | * |
1143 | | *------------------------------------------------------------------------- |
1144 | | */ |
1145 | | static herr_t |
1146 | | H5E__walk2_cb(unsigned n, const H5E_error2_t *err_desc, void *client_data) |
1147 | 82 | { |
1148 | 82 | H5E_print_t *eprint = (H5E_print_t *)client_data; |
1149 | 82 | FILE *stream; /* I/O stream to print output to */ |
1150 | 82 | H5E_cls_t *cls_ptr; /* Pointer to error class */ |
1151 | 82 | H5E_msg_t *maj_ptr; /* Pointer to major error info */ |
1152 | 82 | H5E_msg_t *min_ptr; /* Pointer to minor error info */ |
1153 | 82 | const char *maj_str = "No major description"; /* Major error description */ |
1154 | 82 | const char *min_str = "No minor description"; /* Minor error description */ |
1155 | 82 | bool have_desc = true; /* Flag to indicate whether the error has a "real" description */ |
1156 | | #ifdef H5_HAVE_THREADSAFE_API |
1157 | | uint64_t thread_id = 0; /* ID of thread */ |
1158 | | #endif |
1159 | 82 | herr_t ret_value = SUCCEED; |
1160 | | |
1161 | 82 | FUNC_ENTER_PACKAGE_NOERR |
1162 | | |
1163 | | /* Check arguments */ |
1164 | 82 | assert(err_desc); |
1165 | | |
1166 | | /* If no client data was passed, output to stderr */ |
1167 | 82 | if (!client_data) |
1168 | 0 | stream = stderr; |
1169 | 82 | else |
1170 | 82 | stream = eprint->stream; |
1171 | | |
1172 | | /* Get descriptions for the major and minor error numbers */ |
1173 | 82 | maj_ptr = (H5E_msg_t *)H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG); |
1174 | 82 | min_ptr = (H5E_msg_t *)H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG); |
1175 | | |
1176 | | /* Check for bad pointer(s), but can't issue error, just leave */ |
1177 | 82 | if (!maj_ptr || !min_ptr) |
1178 | 0 | HGOTO_DONE(FAIL); |
1179 | | |
1180 | 82 | if (maj_ptr->msg) |
1181 | 82 | maj_str = maj_ptr->msg; |
1182 | 82 | if (min_ptr->msg) |
1183 | 82 | min_str = min_ptr->msg; |
1184 | | |
1185 | | /* Get error class info. Don't use the class of the major or minor error because |
1186 | | * they might be different. */ |
1187 | 82 | cls_ptr = (H5E_cls_t *)H5I_object_verify(err_desc->cls_id, H5I_ERROR_CLASS); |
1188 | | |
1189 | | /* Check for bad pointer(s), but can't issue error, just leave */ |
1190 | 82 | if (!cls_ptr) |
1191 | 0 | HGOTO_DONE(FAIL); |
1192 | | |
1193 | | #ifdef H5_HAVE_THREADSAFE_API |
1194 | | if (H5TS_thread_id(&thread_id) < 0) |
1195 | | HGOTO_DONE(FAIL); |
1196 | | #endif |
1197 | | |
1198 | | /* Print error class header if new class */ |
1199 | 82 | if (eprint->cls.lib_name == NULL || strcmp(cls_ptr->lib_name, eprint->cls.lib_name) != 0) { |
1200 | | /* update to the new class information */ |
1201 | 10 | if (cls_ptr->cls_name) |
1202 | 10 | eprint->cls.cls_name = cls_ptr->cls_name; |
1203 | 10 | if (cls_ptr->lib_name) |
1204 | 10 | eprint->cls.lib_name = cls_ptr->lib_name; |
1205 | 10 | if (cls_ptr->lib_vers) |
1206 | 10 | eprint->cls.lib_vers = cls_ptr->lib_vers; |
1207 | | |
1208 | 10 | fprintf(stream, "%s-DIAG: Error detected in %s (%s)", |
1209 | 10 | (cls_ptr->cls_name ? cls_ptr->cls_name : "(null)"), |
1210 | 10 | (cls_ptr->lib_name ? cls_ptr->lib_name : "(null)"), |
1211 | 10 | (cls_ptr->lib_vers ? cls_ptr->lib_vers : "(null)")); |
1212 | | |
1213 | | /* try show the process or thread id in multiple processes cases*/ |
1214 | | #ifdef H5_HAVE_PARALLEL |
1215 | | { |
1216 | | int mpi_rank, mpi_initialized, mpi_finalized; |
1217 | | |
1218 | | MPI_Initialized(&mpi_initialized); |
1219 | | MPI_Finalized(&mpi_finalized); |
1220 | | |
1221 | | if (mpi_initialized && !mpi_finalized) { |
1222 | | MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); |
1223 | | fprintf(stream, " MPI-process %d", mpi_rank); |
1224 | | } /* end if */ |
1225 | | #ifdef H5_HAVE_THREADSAFE_API |
1226 | | else |
1227 | | fprintf(stream, " thread %" PRIu64, thread_id); |
1228 | | #endif |
1229 | | } /* end block */ |
1230 | | #else |
1231 | | #ifdef H5_HAVE_THREADSAFE_API |
1232 | | fprintf(stream, " thread %" PRIu64, thread_id); |
1233 | | #endif |
1234 | 10 | #endif |
1235 | 10 | fprintf(stream, ":\n"); |
1236 | 10 | } /* end if */ |
1237 | | |
1238 | | /* Check for "real" error description - used to format output more nicely */ |
1239 | 82 | if (err_desc->desc == NULL || strlen(err_desc->desc) == 0) |
1240 | 0 | have_desc = false; |
1241 | | |
1242 | | /* Print error message */ |
1243 | 82 | fprintf(stream, "%*s#%03u: %s line %u in %s()%s%s\n", H5E_INDENT, "", n, err_desc->file_name, |
1244 | 82 | err_desc->line, err_desc->func_name, (have_desc ? ": " : ""), (have_desc ? err_desc->desc : "")); |
1245 | 82 | fprintf(stream, "%*smajor: %s\n", (H5E_INDENT * 2), "", maj_str); |
1246 | 82 | fprintf(stream, "%*sminor: %s\n", (H5E_INDENT * 2), "", min_str); |
1247 | | |
1248 | 82 | done: |
1249 | 82 | FUNC_LEAVE_NOAPI(ret_value) |
1250 | 82 | } /* end H5E__walk2_cb() */ |
1251 | | |
1252 | | /*------------------------------------------------------------------------- |
1253 | | * Function: H5E__print |
1254 | | * |
1255 | | * Purpose: Private function to print the error stack in some default |
1256 | | * way. This is just a convenience function for H5Ewalk() and |
1257 | | * H5Ewalk2() with a function that prints error messages. |
1258 | | * Users are encouraged to write their own more specific error |
1259 | | * handlers. |
1260 | | * |
1261 | | * Return: SUCCEED/FAIL |
1262 | | * |
1263 | | *------------------------------------------------------------------------- |
1264 | | */ |
1265 | | herr_t |
1266 | | H5E__print(const H5E_stack_t *estack, FILE *stream, bool bk_compatible) |
1267 | 10 | { |
1268 | 10 | H5E_print_t eprint; /* Callback information to pass to H5E_walk() */ |
1269 | 10 | H5E_walk_op_t walk_op; /* Error stack walking callback */ |
1270 | 10 | herr_t ret_value = SUCCEED; |
1271 | | |
1272 | 10 | FUNC_ENTER_PACKAGE |
1273 | | |
1274 | | /* Sanity check */ |
1275 | 10 | assert(estack); |
1276 | | |
1277 | | /* If no stream was given, use stderr */ |
1278 | 10 | if (!stream) |
1279 | 10 | eprint.stream = stderr; |
1280 | 0 | else |
1281 | 0 | eprint.stream = stream; |
1282 | | |
1283 | | /* Reset the original error class information */ |
1284 | 10 | memset(&eprint.cls, 0, sizeof(H5E_cls_t)); |
1285 | | |
1286 | | /* Walk the error stack */ |
1287 | 10 | if (bk_compatible) { |
1288 | 0 | #ifndef H5_NO_DEPRECATED_SYMBOLS |
1289 | 0 | walk_op.vers = 1; |
1290 | 0 | walk_op.u.func1 = H5E__walk1_cb; |
1291 | 0 | if (H5E__walk(estack, H5E_WALK_DOWNWARD, &walk_op, (void *)&eprint) < 0) |
1292 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack"); |
1293 | | #else /* H5_NO_DEPRECATED_SYMBOLS */ |
1294 | | assert(0 && "version 1 error stack print without deprecated symbols!"); |
1295 | | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
1296 | 0 | } /* end if */ |
1297 | 10 | else { |
1298 | 10 | walk_op.vers = 2; |
1299 | 10 | walk_op.u.func2 = H5E__walk2_cb; |
1300 | 10 | if (H5E__walk(estack, H5E_WALK_DOWNWARD, &walk_op, (void *)&eprint) < 0) |
1301 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack"); |
1302 | 10 | } /* end else */ |
1303 | | |
1304 | 10 | done: |
1305 | 10 | FUNC_LEAVE_NOAPI(ret_value) |
1306 | 10 | } /* end H5E__print() */ |
1307 | | |
1308 | | /*------------------------------------------------------------------------- |
1309 | | * Function: H5E__walk |
1310 | | * |
1311 | | * Purpose: Private function for H5Ewalk. |
1312 | | * Walks the error stack, calling the specified function for |
1313 | | * each error on the stack. The DIRECTION argument determines |
1314 | | * whether the stack is walked from the inside out or the |
1315 | | * outside in. The value H5E_WALK_UPWARD means begin with the |
1316 | | * most specific error and end at the API; H5E_WALK_DOWNWARD |
1317 | | * means to start at the API and end at the inner-most function |
1318 | | * where the error was first detected. |
1319 | | * |
1320 | | * The function pointed to by STACK_FUNC will be called for |
1321 | | * each error record in the error stack. It's arguments will |
1322 | | * include an index number (beginning at zero regardless of |
1323 | | * stack traversal direction), an error stack entry, and the |
1324 | | * CLIENT_DATA pointer passed to H5E_print. |
1325 | | * |
1326 | | * The function FUNC is also provided for backward compatibility. |
1327 | | * When BK_COMPATIBLE is set to be true, FUNC is used to be |
1328 | | * compatible with older library. If BK_COMPATIBLE is false, |
1329 | | * STACK_FUNC is used. |
1330 | | * |
1331 | | * Return: SUCCEED/FAIL |
1332 | | * |
1333 | | *------------------------------------------------------------------------- |
1334 | | */ |
1335 | | herr_t |
1336 | | H5E__walk(const H5E_stack_t *estack, H5E_direction_t direction, const H5E_walk_op_t *op, void *client_data) |
1337 | 10 | { |
1338 | 10 | int i; /* Local index variable */ |
1339 | 10 | herr_t ret_value = H5_ITER_CONT; /* Return value */ |
1340 | | |
1341 | 10 | FUNC_ENTER_PACKAGE_NOERR |
1342 | | |
1343 | | /* Sanity check */ |
1344 | 10 | assert(estack); |
1345 | 10 | assert(op); |
1346 | | |
1347 | | /* check args, but rather than failing use some default value */ |
1348 | 10 | if (direction != H5E_WALK_UPWARD && direction != H5E_WALK_DOWNWARD) |
1349 | 0 | direction = H5E_WALK_UPWARD; |
1350 | | |
1351 | | /* Walk the stack if a callback function was given */ |
1352 | 10 | if (op->vers == 1) { |
1353 | 0 | #ifndef H5_NO_DEPRECATED_SYMBOLS |
1354 | 0 | if (op->u.func1) { |
1355 | 0 | H5E_error1_t old_err; |
1356 | |
|
1357 | 0 | ret_value = SUCCEED; |
1358 | 0 | if (H5E_WALK_UPWARD == direction) { |
1359 | 0 | for (i = 0; i < (int)estack->nused && ret_value == H5_ITER_CONT; i++) { |
1360 | | /* Point to each error record on the stack and pass it to callback function.*/ |
1361 | 0 | old_err.maj_num = estack->entries[i].err.maj_num; |
1362 | 0 | old_err.min_num = estack->entries[i].err.min_num; |
1363 | 0 | old_err.file_name = estack->entries[i].err.file_name; |
1364 | 0 | old_err.func_name = estack->entries[i].err.func_name; |
1365 | 0 | old_err.line = estack->entries[i].err.line; |
1366 | 0 | old_err.desc = estack->entries[i].err.desc; |
1367 | | |
1368 | | /* Prepare & restore library for user callback */ |
1369 | 0 | H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR) |
1370 | 0 | { |
1371 | 0 | ret_value = (op->u.func1)(i, &old_err, client_data); |
1372 | 0 | } |
1373 | 0 | H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR) |
1374 | 0 | } /* end for */ |
1375 | 0 | } /* end if */ |
1376 | 0 | else { |
1377 | 0 | H5_CHECK_OVERFLOW(estack->nused - 1, size_t, int); |
1378 | 0 | for (i = (int)(estack->nused - 1); i >= 0 && ret_value == H5_ITER_CONT; i--) { |
1379 | | /* Point to each error record on the stack and pass it to callback function.*/ |
1380 | 0 | old_err.maj_num = estack->entries[i].err.maj_num; |
1381 | 0 | old_err.min_num = estack->entries[i].err.min_num; |
1382 | 0 | old_err.file_name = estack->entries[i].err.file_name; |
1383 | 0 | old_err.func_name = estack->entries[i].err.func_name; |
1384 | 0 | old_err.line = estack->entries[i].err.line; |
1385 | 0 | old_err.desc = estack->entries[i].err.desc; |
1386 | | |
1387 | | /* Prepare & restore library for user callback */ |
1388 | 0 | H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR) |
1389 | 0 | { |
1390 | 0 | ret_value = |
1391 | 0 | (op->u.func1)((int)(estack->nused - (size_t)(i + 1)), &old_err, client_data); |
1392 | 0 | } |
1393 | 0 | H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR) |
1394 | 0 | } /* end for */ |
1395 | 0 | } /* end else */ |
1396 | |
|
1397 | 0 | if (ret_value < 0) |
1398 | 0 | HERROR(H5E_ERROR, H5E_CANTLIST, "can't walk error stack"); |
1399 | 0 | } /* end if */ |
1400 | | #else /* H5_NO_DEPRECATED_SYMBOLS */ |
1401 | | assert(0 && "version 1 error stack walk without deprecated symbols!"); |
1402 | | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
1403 | 0 | } /* end if */ |
1404 | 10 | else { |
1405 | 10 | assert(op->vers == 2); |
1406 | 10 | if (op->u.func2) { |
1407 | 10 | ret_value = SUCCEED; |
1408 | 10 | if (H5E_WALK_UPWARD == direction) { |
1409 | 0 | for (i = 0; i < (int)estack->nused && ret_value == H5_ITER_CONT; i++) { |
1410 | | /* Prepare & restore library for user callback */ |
1411 | 0 | H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR) |
1412 | 0 | { |
1413 | 0 | ret_value = (op->u.func2)((unsigned)i, &estack->entries[i].err, client_data); |
1414 | 0 | } |
1415 | 0 | H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR) |
1416 | 0 | } |
1417 | 0 | } /* end if */ |
1418 | 10 | else { |
1419 | 10 | H5_CHECK_OVERFLOW(estack->nused - 1, size_t, int); |
1420 | 92 | for (i = (int)(estack->nused - 1); i >= 0 && ret_value == H5_ITER_CONT; i--) { |
1421 | | /* Prepare & restore library for user callback */ |
1422 | 82 | H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR) |
1423 | 82 | { |
1424 | 82 | ret_value = (op->u.func2)((unsigned)(estack->nused - (size_t)(i + 1)), |
1425 | 82 | &estack->entries[i].err, client_data); |
1426 | 82 | } |
1427 | 82 | H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR) |
1428 | 82 | } |
1429 | 10 | } /* end else */ |
1430 | | |
1431 | 10 | if (ret_value < 0) |
1432 | 0 | HERROR(H5E_ERROR, H5E_CANTLIST, "can't walk error stack"); |
1433 | 10 | } /* end if */ |
1434 | 10 | } /* end else */ |
1435 | | |
1436 | 10 | FUNC_LEAVE_NOAPI(ret_value) |
1437 | 10 | } /* end H5E__walk() */ |
1438 | | |
1439 | | /*------------------------------------------------------------------------- |
1440 | | * Function: H5E__get_auto |
1441 | | * |
1442 | | * Purpose: Private function to return the current settings for the |
1443 | | * automatic error stack traversal function and its data |
1444 | | * for specific error stack. Either (or both) arguments may |
1445 | | * be null in which case the value is not returned. |
1446 | | * |
1447 | | * Return: SUCCEED/FAIL |
1448 | | * |
1449 | | *------------------------------------------------------------------------- |
1450 | | */ |
1451 | | herr_t |
1452 | | H5E__get_auto(const H5E_stack_t *estack, H5E_auto_op_t *op, void **client_data) |
1453 | 1 | { |
1454 | 1 | FUNC_ENTER_PACKAGE_NOERR |
1455 | | |
1456 | 1 | assert(estack); |
1457 | | |
1458 | | /* Retrieve the requested information */ |
1459 | 1 | if (op) |
1460 | 1 | *op = estack->auto_op; |
1461 | 1 | if (client_data) |
1462 | 0 | *client_data = estack->auto_data; |
1463 | | |
1464 | 1 | FUNC_LEAVE_NOAPI(SUCCEED) |
1465 | 1 | } /* end H5E__get_auto() */ |
1466 | | |
1467 | | /*------------------------------------------------------------------------- |
1468 | | * Function: H5E_get_default_auto_func |
1469 | | * |
1470 | | * Purpose: Private function to retrieve the default error stack's |
1471 | | * reporting function. |
1472 | | * |
1473 | | * Return: SUCCEED/FAIL |
1474 | | * |
1475 | | *------------------------------------------------------------------------- |
1476 | | */ |
1477 | | herr_t |
1478 | | H5E_get_default_auto_func(H5E_auto2_t *func) |
1479 | 1 | { |
1480 | 1 | H5E_stack_t *estack; /* Error stack to operate on */ |
1481 | 1 | H5E_auto_op_t op; /* Error stack function */ |
1482 | 1 | herr_t ret_value = SUCCEED; /* Return value */ |
1483 | | |
1484 | 1 | FUNC_ENTER_NOAPI(FAIL) |
1485 | | |
1486 | | /* Retrieve default error stack */ |
1487 | 1 | if (NULL == (estack = H5E__get_my_stack())) |
1488 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack"); |
1489 | | |
1490 | | /* Get the automatic error reporting information */ |
1491 | 1 | if (H5E__get_auto(estack, &op, NULL) < 0) |
1492 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info"); |
1493 | | |
1494 | | /* Retrieve error output function */ |
1495 | 1 | *func = op.func2; |
1496 | | |
1497 | 1 | done: |
1498 | 1 | FUNC_LEAVE_NOAPI(ret_value) |
1499 | 1 | } /* end H5E_get_default_auto_func() */ |
1500 | | |
1501 | | /*------------------------------------------------------------------------- |
1502 | | * Function: H5E__set_auto |
1503 | | * |
1504 | | * Purpose: Private function to turn on or off automatic printing of |
1505 | | * errors for certain error stack. When turned on (non-null |
1506 | | * FUNC pointer) any API function which returns an error |
1507 | | * indication will first call FUNC passing it CLIENT_DATA |
1508 | | * as an argument. |
1509 | | * |
1510 | | * The default values before this function is called are |
1511 | | * H5Eprint2() with client data being the standard error stream, |
1512 | | * stderr. |
1513 | | * |
1514 | | * Automatic stack traversal is always in the H5E_WALK_DOWNWARD |
1515 | | * direction. |
1516 | | * |
1517 | | * Return: SUCCEED/FAIL |
1518 | | * |
1519 | | *------------------------------------------------------------------------- |
1520 | | */ |
1521 | | herr_t |
1522 | | H5E__set_auto(H5E_stack_t *estack, const H5E_auto_op_t *op, void *client_data) |
1523 | 0 | { |
1524 | 0 | FUNC_ENTER_PACKAGE_NOERR |
1525 | |
|
1526 | 0 | assert(estack); |
1527 | | |
1528 | | /* Set the automatic error reporting info */ |
1529 | 0 | estack->auto_op = *op; |
1530 | 0 | estack->auto_data = client_data; |
1531 | |
|
1532 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
1533 | 0 | } /* end H5E__set_auto() */ |
1534 | | |
1535 | | /*------------------------------------------------------------------------- |
1536 | | * Function: H5E_printf_stack |
1537 | | * |
1538 | | * Purpose: Printf-like wrapper around H5E__push_stack. |
1539 | | * |
1540 | | * Return: SUCCEED/FAIL |
1541 | | * |
1542 | | *------------------------------------------------------------------------- |
1543 | | */ |
1544 | | herr_t |
1545 | | H5E_printf_stack(const char *file, const char *func, unsigned line, hid_t maj_id, hid_t min_id, |
1546 | | const char *fmt, ...) |
1547 | 82 | { |
1548 | 82 | H5E_stack_t *estack; /* Pointer to error stack to modify */ |
1549 | 82 | va_list ap; /* Varargs info */ |
1550 | 82 | bool va_started = false; /* Whether the variable argument list is open */ |
1551 | 82 | herr_t ret_value = SUCCEED; /* Return value */ |
1552 | | |
1553 | | /* |
1554 | | * WARNING: We cannot call HERROR() from within this function or else we |
1555 | | * could enter infinite recursion. Furthermore, we also cannot |
1556 | | * call any other HDF5 macro or function which might call |
1557 | | * HERROR(). HERROR() is called by HRETURN_ERROR() which could |
1558 | | * be called by FUNC_ENTER(). |
1559 | | */ |
1560 | 82 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
1561 | | |
1562 | | /* Sanity check */ |
1563 | 82 | assert(maj_id >= H5E_first_maj_id_g && maj_id <= H5E_last_maj_id_g); |
1564 | 82 | assert(min_id >= H5E_first_min_id_g && min_id <= H5E_last_min_id_g); |
1565 | 82 | assert(fmt); |
1566 | | |
1567 | | /* Get the 'default' error stack */ |
1568 | 82 | if (NULL == (estack = H5E__get_my_stack())) |
1569 | 0 | HGOTO_DONE(FAIL); |
1570 | | |
1571 | | /* Check if error reporting is paused for this stack */ |
1572 | 82 | if (!estack->paused) { |
1573 | | /* Start the variable-argument parsing */ |
1574 | 82 | va_start(ap, fmt); |
1575 | 82 | va_started = true; |
1576 | | |
1577 | | /* Push the error on the stack */ |
1578 | 82 | if (H5E__push_stack(estack, false, file, func, line, H5E_ERR_CLS_g, maj_id, min_id, fmt, &ap) < 0) |
1579 | 0 | HGOTO_DONE(FAIL); |
1580 | 82 | } |
1581 | | |
1582 | 82 | done: |
1583 | 82 | if (va_started) |
1584 | 82 | va_end(ap); |
1585 | | |
1586 | 82 | FUNC_LEAVE_NOAPI(ret_value) |
1587 | 82 | } /* end H5E_printf_stack() */ |
1588 | | |
1589 | | /*------------------------------------------------------------------------- |
1590 | | * Function: H5E__push_stack |
1591 | | * |
1592 | | * Purpose: Pushes a new error record onto error stack for the current |
1593 | | * thread. The error has major and minor IDs MAJ_ID and |
1594 | | * MIN_ID, the name of a function where the error was detected, |
1595 | | * the name of the file where the error was detected, the |
1596 | | * line within that file, and an error description string. The |
1597 | | * function name, file name, and error description strings must |
1598 | | * be statically allocated (the FUNC_ENTER() macro takes care of |
1599 | | * the function name and file name automatically, but the |
1600 | | * programmer is responsible for the description string). |
1601 | | * |
1602 | | * Return: SUCCEED/FAIL |
1603 | | * |
1604 | | *------------------------------------------------------------------------- |
1605 | | */ |
1606 | | herr_t |
1607 | | H5E__push_stack(H5E_stack_t *estack, bool app_entry, const char *file, const char *func, unsigned line, |
1608 | | hid_t cls_id, hid_t maj_id, hid_t min_id, const char *fmt, va_list *ap) |
1609 | 82 | { |
1610 | 82 | herr_t ret_value = SUCCEED; /* Return value */ |
1611 | | |
1612 | | /* |
1613 | | * WARNING: We cannot call HERROR() from within this function or else we |
1614 | | * could enter infinite recursion. Furthermore, we also cannot |
1615 | | * call any other HDF5 macro or function which might call |
1616 | | * HERROR(). HERROR() is called by HRETURN_ERROR() which could |
1617 | | * be called by FUNC_ENTER(). |
1618 | | */ |
1619 | 82 | FUNC_ENTER_PACKAGE_NOERR |
1620 | | |
1621 | | /* Sanity check */ |
1622 | 82 | assert(cls_id > 0); |
1623 | 82 | assert(maj_id > 0); |
1624 | 82 | assert(min_id > 0); |
1625 | | |
1626 | | /* |
1627 | | * Push the error if there's room. Otherwise just forget it. |
1628 | | */ |
1629 | 82 | if (estack->nused < H5E_MAX_ENTRIES) { |
1630 | 82 | estack->entries[estack->nused].app_entry = app_entry; |
1631 | 82 | if (H5E__set_stack_entry(&estack->entries[estack->nused].err, file, func, line, cls_id, maj_id, |
1632 | 82 | min_id, fmt, ap) < 0) |
1633 | 0 | HGOTO_DONE(FAIL); |
1634 | 82 | estack->nused++; |
1635 | 82 | } /* end if */ |
1636 | | |
1637 | 82 | done: |
1638 | 82 | FUNC_LEAVE_NOAPI(ret_value) |
1639 | 82 | } /* end H5E__push_stack() */ |
1640 | | |
1641 | | /*------------------------------------------------------------------------- |
1642 | | * Function: H5E__copy_stack_entry |
1643 | | * |
1644 | | * Purpose: Copy a stack entry |
1645 | | * |
1646 | | * Return: SUCCEED/FAIL |
1647 | | * |
1648 | | *------------------------------------------------------------------------- |
1649 | | */ |
1650 | | static herr_t |
1651 | | H5E__copy_stack_entry(H5E_entry_t *dst_entry, const H5E_entry_t *src_entry) |
1652 | 0 | { |
1653 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1654 | |
|
1655 | 0 | FUNC_ENTER_PACKAGE |
1656 | | |
1657 | | /* Sanity check */ |
1658 | 0 | assert(dst_entry); |
1659 | 0 | assert(src_entry); |
1660 | | |
1661 | | /* Shallow copy all fields */ |
1662 | 0 | *dst_entry = *src_entry; |
1663 | | |
1664 | | /* Deep copy application entries */ |
1665 | 0 | if (dst_entry->app_entry) { |
1666 | | /* Note: don't waste time incrementing library internal error IDs */ |
1667 | 0 | if (dst_entry->err.cls_id != H5E_ERR_CLS_g) |
1668 | 0 | if (H5I_inc_ref(dst_entry->err.cls_id, false) < 0) |
1669 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error class"); |
1670 | 0 | if (dst_entry->err.maj_num < H5E_first_maj_id_g || dst_entry->err.maj_num > H5E_last_maj_id_g) |
1671 | 0 | if (H5I_inc_ref(dst_entry->err.maj_num, false) < 0) |
1672 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error message"); |
1673 | 0 | if (dst_entry->err.min_num < H5E_first_min_id_g || dst_entry->err.min_num > H5E_last_min_id_g) |
1674 | 0 | if (H5I_inc_ref(dst_entry->err.min_num, false) < 0) |
1675 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error message"); |
1676 | | /* The library's 'func' & 'file' strings are statically allocated (by the compiler) |
1677 | | * there's no need to duplicate them. |
1678 | | */ |
1679 | 0 | if (NULL == (dst_entry->err.file_name = strdup(src_entry->err.file_name))) |
1680 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTCOPY, FAIL, "unable to duplicate file name"); |
1681 | 0 | if (NULL == (dst_entry->err.func_name = strdup(src_entry->err.func_name))) |
1682 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTCOPY, FAIL, "unable to duplicate function name"); |
1683 | 0 | } |
1684 | 0 | if (NULL == (dst_entry->err.desc = strdup(src_entry->err.desc))) |
1685 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTCOPY, FAIL, "unable to duplicate error description"); |
1686 | | |
1687 | 0 | done: |
1688 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1689 | 0 | } /* end H5E__copy_stack_entry() */ |
1690 | | |
1691 | | /*------------------------------------------------------------------------- |
1692 | | * Function: H5E__set_stack_entry |
1693 | | * |
1694 | | * Purpose: Sets the information for a given stack entry. |
1695 | | * |
1696 | | * Return: SUCCEED/FAIL |
1697 | | * |
1698 | | *------------------------------------------------------------------------- |
1699 | | */ |
1700 | | static herr_t |
1701 | | H5E__set_stack_entry(H5E_error2_t *err_entry, const char *file, const char *func, unsigned line, hid_t cls_id, |
1702 | | hid_t maj_id, hid_t min_id, const char *fmt, va_list *ap) |
1703 | 82 | { |
1704 | 82 | herr_t ret_value = SUCCEED; /* Return value */ |
1705 | | |
1706 | | /* |
1707 | | * WARNING: We cannot call HERROR() from within this function or else we |
1708 | | * could enter infinite recursion. Furthermore, we also cannot |
1709 | | * call any other HDF5 macro or function which might call |
1710 | | * HERROR(). HERROR() is called by HRETURN_ERROR() which could |
1711 | | * be called by FUNC_ENTER(). |
1712 | | */ |
1713 | 82 | FUNC_ENTER_PACKAGE_NOERR |
1714 | | |
1715 | | /* Sanity check */ |
1716 | 82 | assert(err_entry); |
1717 | 82 | assert(cls_id > 0); |
1718 | 82 | assert(maj_id > 0); |
1719 | 82 | assert(min_id > 0); |
1720 | | |
1721 | | /* |
1722 | | * Don't fail if arguments are bad. Instead, substitute some default |
1723 | | * value. |
1724 | | */ |
1725 | 82 | if (!func) |
1726 | 0 | func = "Unknown_Function"; |
1727 | 82 | if (!file) |
1728 | 0 | file = "Unknown_File"; |
1729 | 82 | if (!fmt) |
1730 | 0 | fmt = "No description given"; |
1731 | | |
1732 | | /* Set the entry fields */ |
1733 | | /* NOTE: non-library IDs have already been incremented */ |
1734 | 82 | err_entry->cls_id = cls_id; |
1735 | 82 | err_entry->maj_num = maj_id; |
1736 | 82 | err_entry->min_num = min_id; |
1737 | | /* The 'func' & 'file' strings are either statically allocated (by the |
1738 | | * compiler), for internal error messages, or have already been duplicated, |
1739 | | * for application errors, so there's no need to duplicate them here. |
1740 | | */ |
1741 | 82 | err_entry->func_name = func; |
1742 | 82 | err_entry->file_name = file; |
1743 | 82 | err_entry->line = line; |
1744 | 82 | if (ap) { |
1745 | 82 | char *desc = NULL; |
1746 | | |
1747 | 82 | H5_WARN_FORMAT_NONLITERAL_OFF |
1748 | 82 | if (HDvasprintf(&desc, fmt, *ap) < 0) |
1749 | 0 | HGOTO_DONE(FAIL); |
1750 | 82 | H5_WARN_FORMAT_NONLITERAL_ON |
1751 | | |
1752 | 82 | err_entry->desc = desc; |
1753 | 82 | } |
1754 | 0 | else { |
1755 | 0 | if (NULL == (err_entry->desc = strdup(fmt))) |
1756 | 0 | HGOTO_DONE(FAIL); |
1757 | 0 | } |
1758 | | |
1759 | 82 | done: |
1760 | 82 | FUNC_LEAVE_NOAPI(ret_value) |
1761 | 82 | } /* end H5E__set_stack_entry() */ |
1762 | | |
1763 | | /*------------------------------------------------------------------------- |
1764 | | * Function: H5E__clear_entries |
1765 | | * |
1766 | | * Purpose: Private function to clear the error stack entries for the |
1767 | | * specified error stack. |
1768 | | * |
1769 | | * Return: SUCCEED/FAIL |
1770 | | * |
1771 | | *------------------------------------------------------------------------- |
1772 | | */ |
1773 | | static herr_t |
1774 | | H5E__clear_entries(H5E_stack_t *estack, size_t nentries) |
1775 | 10 | { |
1776 | 10 | unsigned u; /* Local index variable */ |
1777 | 10 | herr_t ret_value = SUCCEED; /* Return value */ |
1778 | | |
1779 | 10 | FUNC_ENTER_PACKAGE |
1780 | | |
1781 | | /* Sanity check */ |
1782 | 10 | assert(estack); |
1783 | 10 | assert(estack->nused >= nentries); |
1784 | | |
1785 | | /* Empty the error stack from the top down */ |
1786 | 92 | for (u = 0; nentries > 0; nentries--, u++) { |
1787 | 82 | H5E_entry_t *error; /* Pointer to error stack entry to clear */ |
1788 | | |
1789 | 82 | error = &(estack->entries[estack->nused - (u + 1)]); |
1790 | | |
1791 | | /* Decrement the IDs to indicate that they are no longer used by this stack */ |
1792 | | /* (In reverse order that they were incremented, so that reference counts work well) */ |
1793 | | /* Note: don't decrement library internal error IDs, since they weren't incremented */ |
1794 | 82 | if (error->err.min_num < H5E_first_min_id_g || error->err.min_num > H5E_last_min_id_g) |
1795 | 0 | if (H5I_dec_ref(error->err.min_num) < 0) |
1796 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message"); |
1797 | 82 | if (error->err.maj_num < H5E_first_maj_id_g || error->err.maj_num > H5E_last_maj_id_g) |
1798 | 0 | if (H5I_dec_ref(error->err.maj_num) < 0) |
1799 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message"); |
1800 | 82 | if (error->err.cls_id != H5E_ERR_CLS_g) |
1801 | 0 | if (H5I_dec_ref(error->err.cls_id) < 0) |
1802 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error class"); |
1803 | | |
1804 | | /* Release strings */ |
1805 | | /* The library's 'func' & 'file' strings are statically allocated (by the |
1806 | | * compiler) and are not allocated, so there's no need to free them. |
1807 | | */ |
1808 | 82 | if (error->app_entry) { |
1809 | 0 | H5MM_xfree_const(error->err.file_name); |
1810 | 0 | H5MM_xfree_const(error->err.func_name); |
1811 | 0 | } |
1812 | 82 | error->err.file_name = NULL; |
1813 | 82 | error->err.func_name = NULL; |
1814 | 82 | error->err.desc = (const char *)H5MM_xfree_const(error->err.desc); |
1815 | 82 | } |
1816 | | |
1817 | | /* Decrement number of errors on stack */ |
1818 | 10 | estack->nused -= u; |
1819 | | |
1820 | 10 | done: |
1821 | 10 | FUNC_LEAVE_NOAPI(ret_value) |
1822 | 10 | } /* end H5E__clear_entries() */ |
1823 | | |
1824 | | /*------------------------------------------------------------------------- |
1825 | | * Function: H5E_clear_stack |
1826 | | * |
1827 | | * Purpose: Clear the default error stack |
1828 | | * |
1829 | | * Note: This routine should _not_ be used inside general library |
1830 | | * code in general. It creates complex locking issues for |
1831 | | * threadsafe code. Generally, using a 'try' parameter or |
1832 | | * an 'exists' parameter should be used if an operation is |
1833 | | * being used to probe for information. Remember: failing |
1834 | | * to locate a record is not an error for a data structure, |
1835 | | * although it could be an error for the user of the data |
1836 | | * structure. |
1837 | | * |
1838 | | * Return: SUCCEED/FAIL |
1839 | | * |
1840 | | *------------------------------------------------------------------------- |
1841 | | */ |
1842 | | herr_t |
1843 | | H5E_clear_stack(void) |
1844 | 11 | { |
1845 | 11 | H5E_stack_t *estack; /* Error stack to clear */ |
1846 | 11 | herr_t ret_value = SUCCEED; /* Return value */ |
1847 | | |
1848 | 11 | FUNC_ENTER_NOAPI(FAIL) |
1849 | | |
1850 | | /* Get 'default' error stack */ |
1851 | 11 | if (NULL == (estack = H5E__get_my_stack())) |
1852 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack"); |
1853 | | |
1854 | | /* Empty the error stack */ |
1855 | 11 | if (estack->nused) |
1856 | 10 | if (H5E__clear_entries(estack, estack->nused) < 0) |
1857 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack"); |
1858 | | |
1859 | 11 | done: |
1860 | 11 | FUNC_LEAVE_NOAPI(ret_value) |
1861 | 11 | } /* end H5E_clear_stack() */ |
1862 | | |
1863 | | /*------------------------------------------------------------------------- |
1864 | | * Function: H5E__destroy_stack |
1865 | | * |
1866 | | * Purpose: Clear all internal state within an error stack, as a precursor to freeing it. |
1867 | | * |
1868 | | * At present, this is nearly identical to H5E_clear_stack(), |
1869 | | * but if additional resources are added to the error stack in the future, |
1870 | | * they will only be released by this routine and not by H5E_clear_stack(). |
1871 | | * |
1872 | | * Return: SUCCEED/FAIL |
1873 | | * |
1874 | | *------------------------------------------------------------------------- |
1875 | | */ |
1876 | | herr_t |
1877 | | H5E__destroy_stack(H5E_stack_t *estack) |
1878 | 0 | { |
1879 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1880 | |
|
1881 | 0 | FUNC_ENTER_PACKAGE |
1882 | | |
1883 | | /* Check for 'default' error stack */ |
1884 | 0 | if (estack == NULL) |
1885 | 0 | if (NULL == (estack = H5E__get_my_stack())) |
1886 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack"); |
1887 | | |
1888 | | /* Empty the error stack */ |
1889 | 0 | if (estack->nused) |
1890 | 0 | if (H5E__clear_entries(estack, estack->nused) < 0) |
1891 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack"); |
1892 | | |
1893 | 0 | done: |
1894 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1895 | 0 | } /* end H5E__destroy_stack() */ |
1896 | | |
1897 | | /*------------------------------------------------------------------------- |
1898 | | * Function: H5E__pop |
1899 | | * |
1900 | | * Purpose: Private function to delete some error messages from the top |
1901 | | * of error stack. |
1902 | | * |
1903 | | * Return: SUCCEED/FAIL |
1904 | | * |
1905 | | *------------------------------------------------------------------------- |
1906 | | */ |
1907 | | herr_t |
1908 | | H5E__pop(H5E_stack_t *estack, size_t count) |
1909 | 0 | { |
1910 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
1911 | |
|
1912 | 0 | FUNC_ENTER_PACKAGE |
1913 | | |
1914 | | /* Sanity check */ |
1915 | 0 | assert(estack); |
1916 | 0 | assert(estack->nused >= count); |
1917 | | |
1918 | | /* Remove the entries from the error stack */ |
1919 | 0 | if (H5E__clear_entries(estack, count) < 0) |
1920 | 0 | HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, FAIL, "can't remove errors from stack"); |
1921 | | |
1922 | 0 | done: |
1923 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
1924 | 0 | } /* end H5E__pop() */ |
1925 | | |
1926 | | /*------------------------------------------------------------------------- |
1927 | | * Function: H5E_dump_api_stack |
1928 | | * |
1929 | | * Purpose: Private function to dump the error stack during an error in |
1930 | | * an API function if a callback function is defined for the |
1931 | | * current error stack. |
1932 | | * |
1933 | | * Return: SUCCEED/FAIL |
1934 | | * |
1935 | | *------------------------------------------------------------------------- |
1936 | | */ |
1937 | | herr_t |
1938 | | H5E_dump_api_stack(void) |
1939 | 10 | { |
1940 | 10 | H5E_stack_t *estack = H5E__get_my_stack(); |
1941 | 10 | herr_t ret_value = SUCCEED; /* Return value */ |
1942 | | |
1943 | 10 | FUNC_ENTER_NOAPI(FAIL) |
1944 | | |
1945 | 10 | assert(estack); |
1946 | | |
1947 | | #ifdef H5_NO_DEPRECATED_SYMBOLS |
1948 | | if (estack->auto_op.func2) { |
1949 | | /* Prepare & restore library for user callback */ |
1950 | | H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR) |
1951 | | { |
1952 | | (void)((estack->auto_op.func2)(H5E_DEFAULT, estack->auto_data)); |
1953 | | } |
1954 | | H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR) |
1955 | | } |
1956 | | #else /* H5_NO_DEPRECATED_SYMBOLS */ |
1957 | 10 | if (estack->auto_op.vers == 1) { |
1958 | 0 | if (estack->auto_op.func1) { |
1959 | | /* Prepare & restore library for user callback */ |
1960 | 0 | H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR) |
1961 | 0 | { |
1962 | 0 | (void)((estack->auto_op.func1)(estack->auto_data)); |
1963 | 0 | } |
1964 | 0 | H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR) |
1965 | 0 | } |
1966 | 0 | } /* end if */ |
1967 | 10 | else { |
1968 | 10 | if (estack->auto_op.func2) { |
1969 | | /* Prepare & restore library for user callback */ |
1970 | 10 | H5_BEFORE_USER_CB_NOERR(H5_ITER_ERROR) |
1971 | 10 | { |
1972 | 10 | (void)((estack->auto_op.func2)(H5E_DEFAULT, estack->auto_data)); |
1973 | 10 | } |
1974 | 10 | H5_AFTER_USER_CB_NOERR(H5_ITER_ERROR) |
1975 | 10 | } |
1976 | 10 | } /* end else */ |
1977 | 10 | #endif /* H5_NO_DEPRECATED_SYMBOLS */ |
1978 | | |
1979 | 10 | done: |
1980 | 10 | FUNC_LEAVE_NOAPI(ret_value) |
1981 | 10 | } /* end H5E_dump_api_stack() */ |
1982 | | |
1983 | | /*------------------------------------------------------------------------- |
1984 | | * Function: H5E_pause_stack |
1985 | | * |
1986 | | * Purpose: Pause pushing errors on the default error stack. |
1987 | | * |
1988 | | * Generally used via the H5E_PAUSE_ERRORS / H5E_RESUME_ERRORS |
1989 | | * macros. |
1990 | | * |
1991 | | * When one needs to temporarily disable recording errors while |
1992 | | * trying something that's likely or expected to fail. The code |
1993 | | * to try can be nested between these macros like: |
1994 | | * |
1995 | | * H5E_PAUSE_ERRORS { |
1996 | | * ...stuff here that's likely to fail... |
1997 | | * } H5E_RESUME_ERRORS |
1998 | | * |
1999 | | * Warning: don't break, return, or longjmp() from the block of |
2000 | | * code or the error reporting won't be properly restored! |
2001 | | * |
2002 | | * Return: none |
2003 | | * |
2004 | | *------------------------------------------------------------------------- |
2005 | | */ |
2006 | | void |
2007 | | H5E_pause_stack(void) |
2008 | 0 | { |
2009 | 0 | H5E_stack_t *estack = H5E__get_my_stack(); |
2010 | |
|
2011 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
2012 | |
|
2013 | 0 | assert(estack); |
2014 | | |
2015 | | /* Increment pause counter */ |
2016 | 0 | estack->paused++; |
2017 | |
|
2018 | 0 | FUNC_LEAVE_NOAPI_VOID |
2019 | 0 | } /* end H5E_pause_stack() */ |
2020 | | |
2021 | | /*------------------------------------------------------------------------- |
2022 | | * Function: H5E_resume_stack |
2023 | | * |
2024 | | * Purpose: Resume pushing errors on the default error stack. |
2025 | | * |
2026 | | * Generally used via the H5E_PAUSE_ERRORS / H5E_RESUME_ERRORS |
2027 | | * macros. |
2028 | | * |
2029 | | * When one needs to temporarily disable recording errors while |
2030 | | * trying something that's likely or expected to fail. The code |
2031 | | * to try can be nested between these macros like: |
2032 | | * |
2033 | | * H5E_PAUSE_ERRORS { |
2034 | | * ...stuff here that's likely to fail... |
2035 | | * } H5E_RESUME_ERRORS |
2036 | | * |
2037 | | * Warning: don't break, return, or longjmp() from the block of |
2038 | | * code or the error reporting won't be properly restored! |
2039 | | * |
2040 | | * Return: none |
2041 | | * |
2042 | | *------------------------------------------------------------------------- |
2043 | | */ |
2044 | | void |
2045 | | H5E_resume_stack(void) |
2046 | 0 | { |
2047 | 0 | H5E_stack_t *estack = H5E__get_my_stack(); |
2048 | |
|
2049 | 0 | FUNC_ENTER_NOAPI_NOINIT_NOERR |
2050 | |
|
2051 | 0 | assert(estack); |
2052 | 0 | assert(estack->paused); |
2053 | | |
2054 | | /* Decrement pause counter */ |
2055 | 0 | estack->paused--; |
2056 | |
|
2057 | 0 | FUNC_LEAVE_NOAPI_VOID |
2058 | 0 | } /* end H5E_resume_stack() */ |