1 /**
2  * \file
3  * \brief
4  * Datatypes and functions for error reporting.
5  *
6  * Copyrights
7  *
8  * Portions created or assigned to Cisco Systems, Inc. are
9  * Copyright (c) 2014-2016 Cisco Systems, Inc.  All Rights Reserved.
10  */
11 #ifndef CJOSE_ERROR_H
12 #define CJOSE_ERROR_H
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * Temporarily disable compiler warnings, if possible (>=gcc-4.6).
20  *
21  * In some cases (particularly within macros), certain compiler warnings are
22  * unavoidable.  In order to allow these warnings to be treated as errors in
23  * most cases, these macros will disable particular warnings only during
24  * specific points in the compilation.
25  */
26 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
27 #define GCC_END_IGNORED_WARNING _Pragma("GCC diagnostic pop")
28 
29 #define GCC_BEGIN_IGNORED_WARNING_ADDRESS \
30     _Pragma("GCC diagnostic push");       \
31     _Pragma("GCC diagnostic ignored \"-Waddress\"")
32 #define GCC_END_IGNORED_WARNING_ADDRESS GCC_END_IGNORED_WARNING
33 #else
34 #define GCC_BEGIN_IGNORED_WARNING_ADDRESS
35 #define GCC_END_IGNORED_WARNING_ADDRESS
36 #endif /* defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) */
37 
38 /**
39  * Enumeration of defined error codes.
40  */
41 typedef enum {
42     /** No error */
43     CJOSE_ERR_NONE = 0,
44 
45     /** argument was invalid (beyond invariants) */
46     CJOSE_ERR_INVALID_ARG,
47 
48     /** context is not in a valid state */
49     CJOSE_ERR_INVALID_STATE,
50 
51     /** out of memory */
52     CJOSE_ERR_NO_MEMORY,
53 
54     /** an error returned from the crypto libraries */
55     CJOSE_ERR_CRYPTO,
56 
57 } cjose_errcode;
58 
59 /**
60  * An instance of an error context. Unlike other structures, it
61  * is the API user's responsibility to allocate the structure; however
62  * the values provided are considered constants, and MUST NOT be
63  * deallocated.
64  */
65 typedef struct
66 {
67     /** The error code */
68     cjose_errcode code;
69 
70     /** The human readable message for the error code */
71     const char *message;
72 
73     /** The function where the error occured, or "<unknown>"
74         if it cannot be determined */
75     const char *function;
76 
77     /** The file where the error occured */
78     const char *file;
79 
80     /** The line number in the file where the error occured */
81     unsigned long line;
82 
83 } cjose_err;
84 
85 /**
86  * Retrieves the error message for the given error code.
87  *
88  * \param code The error code to lookup
89  * \retval const char * The message for {code}
90  */
91 const char *cjose_err_message(cjose_errcode code);
92 
93 /**
94  * \def CJOSE_ERROR(err, code)
95  *
96  * Macro to initialize an error context.
97  *
98  * \param err The pointer to the error context, or NULL if none
99  * \param errcode The error code
100  */
101 #define CJOSE_ERROR(err, errcode)                      \
102     GCC_BEGIN_IGNORED_WARNING_ADDRESS                  \
103     if ((err) != NULL && (errcode) != CJOSE_ERR_NONE)  \
104     {                                                  \
105         (err)->code = (errcode);                       \
106         (err)->message = cjose_err_message((errcode)); \
107         (err)->function = __func__;                    \
108         (err)->file = __FILE__;                        \
109         (err)->line = __LINE__;                        \
110     }                                                  \
111     GCC_END_IGNORED_WARNING_ADDRESS
112 
113 #ifdef __cplusplus
114 }
115 #endif
116 
117 #endif /* CJOSE_ERROR_H */
118