Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_error.h
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Adaptive Framework Error Handling Header
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
9 #ifndef __AFW_ERROR_H__
10 #define __AFW_ERROR_H__
11 
12 #include "afw_interface.h"
13 #include <stdio.h>
14 
31 
33 #define AFW_ERROR_RV_SOURCE_ID_Z_NULL NULL
34 
40 #define AFW_ERROR_RV_SOURCE_ID_Z_apr "apr"
41 
47 #define AFW_ERROR_RV_SOURCE_ID_Z_icu "icu"
48 
49 
54  afw_error_context_t *next;
55  const afw_utf8_t *info;
56 };
57 
58 
59 
65 struct afw_error_s {
66  afw_xctx_t *xctx;
67 
68  /*
69  * IMPORTANT AFW_ERROR_CLEAR_PARTIAL() will clear from code up to
70  * decode_rv_wa.
71  */
72 
75 
78 
81 
84 
87 
90 
93 
102 
110 
112  int rv;
113 
116 
119 
120  /*IMPORTANT AFW_ERROR_CLEAR_PARTIAL() will clear up to decode_rv_wa. */
121 
124 
127 
130 
133 };
134 
137 /* @brief Macro used to clear an error between code and decode_rv_wa. */
138 #define AFW_ERROR_CLEAR_PARTIAL(__ERROR_) \
139 memset( \
140  (char *)&((__ERROR_)->code), \
141  0, \
142  ( \
143  (char *)&((__ERROR_)->decode_rv_wa[0]) - \
144  (char *)&((__ERROR_)->code) \
145  ) \
146 );
147 
154 typedef struct afw_error_footprint_s {
155  const afw_utf8_z_t *z;
156  const afw_utf8_z_t *source_z;
158 
171 #define AFW_ERROR_FOOTPRINT(_footprint_) \
172  footprint.z = _footprint_; \
173  footprint.source_z = AFW__FILE_LINE__;
174 
182 #define AFW_THROW_UNHANDLED_ERROR(unhandled_error, _ERROR, _CODE, _RV_SOURCE_ID, _RV, _MESSAGE_Z) \
183 do { \
184  (_ERROR)->code = afw_error_code_ ## _CODE; \
185  (_ERROR)->source_z = AFW__FILE_LINE__;\
186  (_ERROR)->rv_source_id_z = #_RV_SOURCE_ID; \
187  (_ERROR)->rv = _RV; \
188  (_ERROR)->rv_decoded_z = NULL; \
189  (_ERROR)->message_z = _MESSAGE_Z; \
190  longjmp((unhandled_error)->throw_jmp_buf, afw_error_code_ ##_CODE); \
191 } while (0);
192 
193 
200 #define AFW_SUCCESS(__ERROR_) ((__ERROR_)->code == afw_error_code_none)
201 
208 #define AFW_ERROR_OCCURRED(__ERROR_) ((__ERROR_)->code != afw_error_code_none)
209 
211 struct afw_try_s {
212  jmp_buf throw_jmp_buf;
213  struct afw_try_s *prev;
214 };
215 
216 
217 AFW_DECLARE(void)
218 afw_error_rv_set_z(
219  afw_error_code_t code,
220  const afw_utf8_z_t *rv_source_id_z,
221  int related_rv,
222  const afw_utf8_z_t * source_z,
223  const afw_utf8_z_t * message_z,
224  afw_xctx_t *xctx);
225 
226 AFW_DECLARE(void)
227 afw_error_set_z(
228  afw_error_code_t code,
229  const afw_utf8_z_t * source_z,
230  const afw_utf8_z_t * message_z,
231  afw_xctx_t *xctx);
232 
234 afw_error_rv_set_fz(
235  afw_error_code_t code,
236  const afw_utf8_z_t *rv_source_id_z,
237  int related_rv,
238  const afw_utf8_z_t * source_z,
239  afw_xctx_t *xctx,
240  const afw_utf8_z_t * format_z, ...);
241 
243 afw_error_set_fz(
244  afw_error_code_t code,
245  const afw_utf8_z_t * source_z,
246  afw_xctx_t *xctx,
247  const afw_utf8_z_t * format_z, ...);
248 
249 AFW_DECLARE(void)
250 afw_error_rv_set_vz(
251  afw_error_code_t code,
252  const afw_utf8_z_t *rv_source_id_z,
253  int related_rv,
254  const afw_utf8_z_t * source_z,
255  const afw_utf8_z_t * format_z, va_list ap,
256  afw_xctx_t *xctx);
257 
258 AFW_DECLARE(void
259 ) afw_error_set_vz(
260  afw_error_code_t code,
261  const afw_utf8_z_t * source_z,
262  const afw_utf8_z_t * format_z, va_list ap,
263  afw_xctx_t *xctx);
264 
271 #define AFW_THROW(xctx) \
272  longjmp(((xctx)->current_try->throw_jmp_buf), (xctx)->error->code)
273 
274 
283 #define AFW_THROW_ERROR_Z(code, message_z, xctx) \
284 do { \
285  afw_error_set_z(afw_error_code_ ## code, \
286  AFW__FILE_LINE__, message_z, xctx); \
287  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
288 } while (0)
289 
290 
301 #define AFW_THROW_ERROR_RV_Z(code, rv_source_id, rv, message_z, xctx) \
302 do { \
303  afw_error_rv_set_z(afw_error_code_ ## code, \
304  AFW_ERROR_RV_SOURCE_ID_Z_ ## rv_source_id, rv, \
305  AFW__FILE_LINE__, message_z, xctx); \
306  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
307 } while (0)
308 
309 
319 #define AFW_THROW_ERROR_FZ(code, xctx, format_z, ...) \
320 do { \
321  afw_error_set_fz(afw_error_code_ ## code, \
322  AFW__FILE_LINE__, xctx, format_z, __VA_ARGS__); \
323  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
324 } while (0)
325 
326 
338 #define AFW_THROW_ERROR_RV_FZ(code, rv_source_id, rv, xctx, format_z, ...) \
339 do { \
340  afw_error_rv_set_fz(afw_error_code_ ## code, \
341  AFW_ERROR_RV_SOURCE_ID_Z_ ## rv_source_id, rv, \
342  AFW__FILE_LINE__, xctx, format_z, __VA_ARGS__); \
343  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
344 } while (0)
345 
355 #define AFW_THROW_ERROR_VZ(code, format_z, ap, xctx) \
356 do { \
357  afw_error_set_vz(afw_error_code_ ## code, \
358  AFW__FILE_LINE__, format_z, ap, xctx); \
359  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
360 } while (0)
361 
371 #define AFW_THROW_ERROR_RV_VZ(code, rv_source_id, rv, format_z, ap, xctx) \
372 do { \
373  afw_error_rv_set_vz(afw_error_code_ ## code, \
374  AFW_ERROR_RV_SOURCE_ID_Z_ ## rv_source_id, rv, \
375  AFW__FILE_LINE__, format_z, ap, xctx); \
376  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
377 } while (0)
378 
388 #define AFW_THROW_ERROR_FOOTPRINT_Z(code, message_z, xctx) \
389 do { \
390  afw_error_set_z(afw_error_code_ ## code, \
391  footprint.source_z, message_z, xctx); \
392  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
393 } while (0)
394 
395 
408 #define AFW_THROW_ERROR_FOOTPRINT_RV_Z(code, rv_source_id, rv, message_z, xctx) \
409 do { \
410  afw_error_rv_set_z(afw_error_code_ ## code, \
411  AFW_ERROR_RV_SOURCE_ID_Z_ ## rv_source_id, rv, \
412  footprint.source_z, message_z, xctx); \
413  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
414 } while (0)
415 
416 
428 #define AFW_THROW_ERROR_FOOTPRINT_FZ(code, xctx, format_z, ...) \
429 do { \
430  afw_error_set_fz(afw_error_code_ ## code, \
431  footprint.source_z, xctx, format_z, __VA_ARGS__); \
432  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
433 } while (0)
434 
435 
449 #define AFW_THROW_ERROR_FOOTPRINT_RV_FZ(code, rv_source_id, rv, xctx, format_z, ...) \
450 do { \
451  afw_error_rv_set_fz(afw_error_code_ ## code, \
452  AFW_ERROR_RV_SOURCE_ID_Z_ ## rv_source_id, rv, \
453  footprint.source_z, xctx, format_z, __VA_ARGS__); \
454  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
455 } while (0)
456 
468 #define AFW_THROW_ERROR_FOOTPRINT_VZ(code, format_z, ap, xctx) \
469 do { \
470  afw_error_set_vz(afw_error_code_ ## code, \
471  footprint.source_z, format_z, ap, xctx); \
472  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
473 } while (0)
474 
486 #define AFW_THROW_ERROR_FOOTPRINT_RV_VZ(code, rv_source_id, rv, format_z, ap, xctx) \
487 do { \
488  afw_error_rv_set_vz(afw_error_code_ ## code, \
489  AFW_ERROR_RV_SOURCE_ID_Z_ ## rv_source_id, rv, \
490  footprint.source_z, format_z, ap, xctx); \
491  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_ ## code)); \
492 } while (0)
493 
499 #define AFW_THROW_MEMORY_ERROR(xctx) \
500 do { \
501  afw_error_set_z(afw_error_code_memory, \
502  AFW__FILE_LINE__, "Memory error", xctx); \
503  longjmp(((xctx)->current_try->throw_jmp_buf), (afw_error_code_memory)); \
504 } while (0)
505 
525 #define AFW_ERROR_INTERNAL_ON_UNHANDLED(__TRY_) \
526  (__TRY_).prev = NULL;\
527  if ((setjmp((__TRY_).throw_jmp_buf)) != 0)
528 
529 
539 #define AFW_ERROR_COPY(to, from) \
540  memcpy((to), (from), sizeof(afw_error_t)); \
541  if ((from)->message_z == &(from)->message_wa[0]) { \
542  (to)->message_z = &(to)->message_wa[0]; \
543  } \
544  if ((from)->rv_decoded_z == &(from)->decode_rv_wa[0]) { \
545  (to)->rv_decoded_z = &(to)->decode_rv_wa[0]; \
546  }
547 
548 
554 #define AFW_ERROR_THROWN ((const afw_error_t *)&this_THROWN_ERROR)
555 
634 #define AFW_TRY \
635 do {\
636 \
637  afw_size_t this_TOP_OFFSET; \
638  afw_try_t this_TRY; \
639  afw_error_t this_THROWN_ERROR; \
640  afw_boolean_t this_ERROR_OCCURRED = false; \
641  afw_boolean_t this_ERROR_CAUGHT = false; \
642  AFW_POSSIBLY_UNUSED_VARIABLE afw_boolean_t this_FINALLY_ENTERED = false; \
643  this_TRY.prev = xctx->current_try;\
644  xctx->current_try = &this_TRY;\
645  this_TOP_OFFSET = xctx->evaluation_stack->top - \
646  xctx->evaluation_stack->first; \
647  do { \
648  if (setjmp(this_TRY.throw_jmp_buf) != 0) { \
649  AFW_ERROR_COPY(&this_THROWN_ERROR, xctx->error); \
650  AFW_ERROR_CLEAR_PARTIAL(xctx->error); \
651  if (this_ERROR_OCCURRED) { \
652  this_THROWN_ERROR.recursive_error = true; \
653  this_ERROR_CAUGHT = false; \
654  break; \
655  } \
656  this_ERROR_OCCURRED = true; \
657  } \
658  else { \
659  do
660 
668 #define AFW_CATCH( __CODE_ ) \
669  while(0); \
670  break; \
671  } \
672  if (xctx->error->code == (afw_error_code_ ## __CODE_)) \
673  { \
674  this_ERROR_CAUGHT = true; \
675  do
676 
684 #define AFW_CATCH_UNHANDLED \
685  while(0); \
686  break; \
687  } \
688  { \
689  this_ERROR_CAUGHT = true; \
690  do
691 
702 #define AFW_FINALLY \
703  while(0); \
704  } \
705  } while(0); \
706  do { \
707  if (this_FINALLY_ENTERED) { \
708  this_THROWN_ERROR.recursive_error_in_finally = true; \
709  break; \
710  } \
711  this_FINALLY_ENTERED = true; \
712  { \
713  do
714 
727 #define AFW_ENDTRY \
728  while(0); \
729  } \
730  } while(0); \
731  xctx->current_try = this_TRY.prev; \
732  if (this_ERROR_OCCURRED && !this_ERROR_CAUGHT) { \
733  AFW_ERROR_COPY(xctx->error, &this_THROWN_ERROR); \
734  longjmp(xctx->current_try->throw_jmp_buf, this_THROWN_ERROR.code); \
735  }\
736  xctx->evaluation_stack->top = xctx->evaluation_stack->first + \
737  this_TOP_OFFSET; \
738 } while (0)
739 
740 
741 
750 #define AFW_MARK_UNHANDLED \
751  this_ERROR_CAUGHT = false; \
752  break;
753 
763 AFW_DECLARE(const afw_object_t *)
765  const afw_error_t *error,
766  const afw_pool_t *p, afw_xctx_t *xctx);
767 
768 
777 AFW_DECLARE(void)
779  const afw_object_t *object,
780  const afw_error_t *error,
781  afw_xctx_t *xctx);
782 
783 
784 
792 
793 
794 
801 AFW_DECLARE(int)
802 afw_error_print(FILE *fp, const afw_error_t *error);
803 
804 
805 
817 AFW_DECLARE(int)
819  FILE *fp,
820  const afw_error_t *error,
821  const afw_pool_t *p,
822  afw_xctx_t *xctx);
823 
824 
833 AFW_DECLARE(void)
834 afw_error_write_log(afw_log_priority_t priority, const afw_error_t *error,
835  afw_xctx_t *xctx);
836 
837 
851 afw_error_message(afw_xctx_t *xctx, const afw_utf8_z_t *format, ...);
852 
853 
866 AFW_DECLARE(const afw_utf8_z_t *)
867 afw_error_message_vz(const afw_utf8_z_t *format, va_list ap,
868  afw_xctx_t *xctx);
869 
870 
879 #define afw_error_source_file(error) \
880  afw_utf8_z_source_file((error)->source_z)
881 
882 
888 AFW_DEFINE(const afw_utf8_t *)
889 afw_error_http_status(const afw_error_t *error);
890 
891 
897 AFW_DECLARE(const afw_utf8_z_t *)
898 afw_error_code_id_z(const afw_error_t *error);
899 
900 
901 
909 AFW_DECLARE(const afw_utf8_t *)
911  const afw_error_t *error,
912  const afw_pool_t *p,
913  afw_xctx_t *xctx);
914 
915 
916 AFW_END_DECLARES
917 
920 #endif /* __AFW_ERROR_H__ */
AFW_DEFINE(const afw_object_t *)
#define AFW_DECLARE_ELLIPSIS(type)
Declare a public afw function with variable arguments.
#define AFW_BEGIN_DECLARES
#define AFW_DECLARE(type)
Declare a public afw function.
Interfaceafw_interface header.
_Bool afw_boolean_t
Definition: afw_common.h:373
enum afw_error_code_e afw_error_code_t
afw_utf8_octet_t afw_utf8_z_t
NFC normalized UTF-8 null terminated string.
Definition: afw_common.h:523
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
enum afw_log_priority_e afw_log_priority_t
Log levels. See afw_log.h for more information.
afw_error_http_status(const afw_error_t *error)
Returns http status for error.
Definition: afw_error.c:1041
int afw_error_print_with_xctx(FILE *fp, const afw_error_t *error, const afw_pool_t *p, afw_xctx_t *xctx)
Print error when xctx is available.
Definition: afw_error.c:783
int afw_error_print(FILE *fp, const afw_error_t *error)
Print error.
Definition: afw_error.c:679
void afw_error_write_log(afw_log_priority_t priority, const afw_error_t *error, afw_xctx_t *xctx)
Write error to environment log.
Definition: afw_error.c:639
const afw_utf8_z_t * afw_error_code_id_z(const afw_error_t *error)
Returns error->code id.
Definition: afw_error.c:1062
void afw_error_add_to_object(const afw_object_t *object, const afw_error_t *error, afw_xctx_t *xctx)
Add error info to existing object using specified pool.
Definition: afw_error.c:862
const afw_utf8_z_t * afw_error_message(afw_xctx_t *xctx, const afw_utf8_z_t *format,...)
Build message in xctx error message_wa and return pointer.
Definition: afw_error.c:1023
const afw_utf8_t * afw_error_to_utf8(const afw_error_t *error, const afw_pool_t *p, afw_xctx_t *xctx)
Convert error to utf8.
Definition: afw_error.c:547
struct afw_error_footprint_s afw_error_footprint_t
error footprint
afw_boolean_t afw_error_allow_in_response(afw_error_code_t code)
Determine if the error object for code is allowed in HTTP response.
Definition: afw_error.c:1082
const afw_object_t * afw_error_to_object(const afw_error_t *error, const afw_pool_t *p, afw_xctx_t *xctx)
Create an object with error info in specified pool.
Definition: afw_error.c:998
const afw_utf8_z_t * afw_error_message_vz(const afw_utf8_z_t *format, va_list ap, afw_xctx_t *xctx)
Build message in xctx error message_wa and return pointer.
Definition: afw_error.c:1012
Contextual information provided in some values.
Adaptive Framework Error Context.
Definition: afw_error.h:53
error footprint
Definition: afw_error.h:154
Adaptive Framework Error.
Definition: afw_error.h:65
afw_error_code_t code
Error code.
Definition: afw_error.h:74
afw_boolean_t recursive_error
Recursive error.
Definition: afw_error.h:115
afw_boolean_t recursive_error_in_finally
Recursive error in finally.
Definition: afw_error.h:118
const afw_utf8_z_t * rv_source_id_z
This is the source of the non-zero rv.
Definition: afw_error.h:86
const afw_utf8_z_t * message_z
Message.
Definition: afw_error.h:80
afw_utf8_z_t message_wa_safety_zero_terminator
Makes sure there is a zero terminator after message_wa.
Definition: afw_error.h:132
const afw_compile_value_contextual_t * contextual
Contextual information or NULL.
Definition: afw_error.h:83
const afw_utf8_t * backtrace
If not memory error and afw_os_backtrace() supplies one.
Definition: afw_error.h:92
int rv
If non-zero, this is rc, rv, or any int value related to error.
Definition: afw_error.h:112
const afw_utf8_t * parser_source
If syntax error, this is partial/full source or NULL.
Definition: afw_error.h:109
afw_utf8_z_t decode_rv_wa[23]
Place to optionally hold rv_decoded_z.
Definition: afw_error.h:123
const afw_utf8_z_t * source_z
File:line in source error was thrown.
Definition: afw_error.h:77
const afw_utf8_z_t * rv_decoded_z
Human readable decode of rv.
Definition: afw_error.h:89
afw_utf8_z_t message_wa[255]
Place to optionally hold message_z.
Definition: afw_error.h:129
afw_utf8_z_t decode_rv_wa_safety_zero_terminator
Makes sure there is a zero terminator after decode_rv_wa.
Definition: afw_error.h:126
afw_size_t parser_cursor
If syntax error, this is cursor when parse error occurred or 0.
Definition: afw_error.h:101
Interface afw_object public struct.
Interface afw_pool public struct.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
Interface afw_xctx public struct.