src/error.h
changeset 34 763f65f9df0c
parent 30 7f8dd120933f
child 37 4fe4a3c4496e
equal deleted inserted replaced
33:e5139b339b18 34:763f65f9df0c
     1 #ifndef ERROR_H
     1 #ifndef ERROR_H
     2 #define ERROR_H
     2 #define ERROR_H
     3 
     3 
     4 /*
     4 /**
       
     5  * @file
       
     6  *
     5  * Error-handling functions
     7  * Error-handling functions
     6  */
     8  */
     7 #include <errno.h>
     9 #include <errno.h>
     8 
    10 
     9 /*
    11 /**
    10  * Type used for error codes is an explicitly *unsigned* int, meaning that error codes themselves are positive.
    12  * The type used for error codes is an explicitly *unsigned* int, meaning that error codes themselves are positive.
    11  * Negative error codes also exist in some places, and they are just a negative err_t.
    13  * Negative error codes (as signed ints) also exist in some places, and they are just a negative err_t.
    12  */
    14  */
    13 typedef unsigned int err_t;
    15 typedef unsigned int err_t;
    14 
    16 
    15 /**
    17 /**
    16  * Ways to interpret error_info.extra
    18  * Ways to interpret error_info.extra
    17  */
    19  */
    18 enum error_extra_types {
    20 enum error_extra_types {
       
    21     /** No extra info */
    19     ERR_EXTRA_NONE      = 0,
    22     ERR_EXTRA_NONE      = 0,
    20 
    23 
    21     /** libc errno, using strerror() */
    24     /** libc errno, using strerror() */
    22     ERR_EXTRA_ERRNO,
    25     ERR_EXTRA_ERRNO,
    23 
    26 
    24     /** libc resolver, using gai_strerror() */
    27     /** libc resolver, using gai_strerror() */
    25     ERR_EXTRA_GAI,
    28     ERR_EXTRA_GAI,
    26 
    29 
    27     /** gnutls, using gnutls_strerror() */
    30     /** GnuTLS, using gnutls_strerror() */
    28     ERR_EXTRA_GNUTLS,
    31     ERR_EXTRA_GNUTLS,
    29 };
    32 };
    30 
    33 
    31 /**
    34 /**
    32  * List of defined error codes, organized mostly by function name
    35  * List of defined error codes, organized mostly by function name
    80 
    83 
    81     /** How to interpret .extra */
    84     /** How to interpret .extra */
    82     enum error_extra_types extra_type;
    85     enum error_extra_types extra_type;
    83 };
    86 };
    84 
    87 
    85 /*
    88 /**
    86  * An error code and associated extra infos
    89  * An error code and associated extra infos
    87  */
    90  */
    88 struct error_info {
    91 struct error_info {
    89     /* The base error code */
    92     /** The base error code */
    90     err_t code;
    93     err_t code;
    91 
    94 
    92     /* Additional detail info, usually some third-party error code */
    95     /** Additional detail info, usually some third-party error code, as defined by the code's ERR_EXTRA_* */
    93     int extra;
    96     int extra;
    94 };
    97 };
    95 
    98 
    96 /*
    99 /**
    97  * Translate an err_t into a function name.
   100  * Translate an err_t into a function name.
    98  */
   101  */
    99 const char *error_name (err_t code);
   102 const char *error_name (err_t code);
   100 
   103 
   101 /*
   104 /**
   102  * Maximum length of error messages returned by error_msg (including NUL byte)
   105  * Maximum length of error messages returned by error_msg (including NUL byte)
   103  */
   106  */
   104 #define ERROR_MSG_MAXLEN 1024
   107 #define ERROR_MSG_MAXLEN 1024
   105 
   108 
   106 /*
   109 /**
   107  * Translate an error_info into a message.
   110  * Translate an error_info into a message.
   108  *
   111  *
   109  * This is returned as a pointer into a statically allocated buffer. It is not re-entrant.
   112  * This is returned as a pointer into a statically allocated buffer. It is not re-entrant.
   110  */
   113  */
   111 const char *error_msg (const struct error_info *err);
   114 const char *error_msg (const struct error_info *err);
   112 
   115 
   113 /** No error, evaulates as logical false */
   116 /** No error, evaulates as logical false */
   114 #define SUCCESS (0)
   117 #define SUCCESS (0)
   115 
   118 
   116 /* Evaulates to error_info.code as lvalue */
   119 /** Evaulates to error_info.code as lvalue */
   117 #define ERROR_CODE(err_info_ptr) ((err_info_ptr)->code)
   120 #define ERROR_CODE(err_info_ptr) ((err_info_ptr)->code)
   118 
   121 
   119 /* Evaulates to error_info.extra as lvalue */
   122 /** Evaulates to error_info.extra as lvalue */
   120 #define ERROR_EXTRA(err_info_ptr) ((err_info_ptr)->extra)
   123 #define ERROR_EXTRA(err_info_ptr) ((err_info_ptr)->extra)
   121 
   124 
   122 /* Set error_info.code to SUCCESS, evaulates as zero */
   125 /** Set error_info.code to SUCCESS, evaulates as zero */
   123 #define RESET_ERROR(err_info_ptr) ((err_info_ptr)->code = SUCCESS)
   126 #define RESET_ERROR(err_info_ptr) ((err_info_ptr)->code = SUCCESS)
   124 
   127 
   125 /* Compare error_info.code != 0 */
   128 /** Compare error_info.code != 0 */
   126 #define IS_ERROR(err_info_ptr) (!!(err_info_ptr)->code)
   129 #define IS_ERROR(err_info_ptr) (!!(err_info_ptr)->code)
   127 
   130 
   128 /* Compare the err_code/err_extra for an err_info */
   131 /** Compare the err_code/err_extra for an err_info */
   129 #define MATCH_ERROR(err_info_ptr, err_code, err_extra) ((err_info_ptr)->code == (err_code) && (err_info_ptr)->extra == (err_extra))
   132 #define MATCH_ERROR(err_info_ptr, err_code, err_extra) ((err_info_ptr)->code == (err_code) && (err_info_ptr)->extra == (err_extra))
   130 
   133 
   131 /* Set error_info.code, but leave err_extra as-is. Evaluates to err_code */
   134 /** Set error_info.code, but leave err_extra as-is. Evaluates to err_code */
   132 #define SET_ERROR(err_info_ptr, err_code) ((err_info_ptr)->code = (err_code))
   135 #define SET_ERROR(err_info_ptr, err_code) ((err_info_ptr)->code = (err_code))
   133 
   136 
   134 /* Set error_info.code/extra. XXX: should evaluate to err_code */
   137 /** Set error_info.code/extra. XXX: should evaluate to err_code */
   135 #define _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) (err_info_ptr)->code = (err_code); (err_info_ptr)->extra = (err_extra)
   138 #define _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) (err_info_ptr)->code = (err_code); (err_info_ptr)->extra = (err_extra)
   136 #define SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); } while (0)
   139 #define SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); } while (0)
   137 
   140 
   138 /* Set error_info.code to err_code, and .extra to errno. XXX: should evaulate to err_code */
   141 /** Set error_info.code to err_code, and .extra to errno. XXX: should evaulate to err_code */
   139 #define _SET_ERROR_ERRNO(err_info_ptr, err_code) _SET_ERROR_EXTRA(err_info_ptr, err_code, errno);
   142 #define _SET_ERROR_ERRNO(err_info_ptr, err_code) _SET_ERROR_EXTRA(err_info_ptr, err_code, errno);
   140 #define SET_ERROR_ERRNO(err_info_ptr, err_code) SET_ERROR_EXTRA(err_info_ptr, err_code, errno);
   143 #define SET_ERROR_ERRNO(err_info_ptr, err_code) SET_ERROR_EXTRA(err_info_ptr, err_code, errno);
   141 
   144 
   142 /* Set error_info from another error_info. Evaluates to the new error_info */
   145 /** Set error_info from another error_info. Evaluates to the new error_info */
   143 #define SET_ERROR_INFO(err_info_ptr, from_ptr) (*err_info_ptr = *from_ptr)
   146 #define SET_ERROR_INFO(err_info_ptr, from_ptr) (*err_info_ptr = *from_ptr)
   144 
   147 
   145 /* Same as above, but also return err_code from func. XXX: use 'return SET_ERROR...' instead */
   148 /** Same as above, but also return err_code from func. XXX: use 'return SET_ERROR...' instead */
   146 #define RETURN_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); return (err_code); } while (0)
   149 #define RETURN_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); return (err_code); } while (0)
   147 #define RETURN_SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); return (err_code); } while (0)
   150 #define RETURN_SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra) do { _SET_ERROR_EXTRA(err_info_ptr, err_code, err_extra); return (err_code); } while (0)
   148 #define RETURN_SET_ERROR_ERRNO(err_info_ptr, err_code) do { _SET_ERROR_ERRNO(err_info_ptr, err_code); return (err_code); } while (0)
   151 #define RETURN_SET_ERROR_ERRNO(err_info_ptr, err_code) do { _SET_ERROR_ERRNO(err_info_ptr, err_code); return (err_code); } while (0)
   149 #define RETURN_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); return (from_ptr->code); } while (0)
   152 #define RETURN_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); return (from_ptr->code); } while (0)
   150 
   153 
   151 /* Same as above, but also do a 'goto error' */
   154 /** Same as above, but also do a 'goto error' */
   152 #define JUMP_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); goto error; } while (0)
   155 #define JUMP_SET_ERROR(err_info_ptr, err_code) do { SET_ERROR(err_info_ptr, err_code); goto error; } while (0)
   153 #define JUMP_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); goto error; } while (0)
   156 #define JUMP_SET_ERROR_INFO(err_info_ptr, from_ptr) do { SET_ERROR_INFO(err_info_ptr, from_ptr); goto error; } while (0)
   154 
   157 
   155 #endif
   158 #endif