summaryrefslogtreecommitdiffstats
path: root/clib/err.h
diff options
context:
space:
mode:
Diffstat (limited to 'clib/err.h')
-rw-r--r--clib/err.h290
1 files changed, 290 insertions, 0 deletions
diff --git a/clib/err.h b/clib/err.h
new file mode 100644
index 0000000..5b326d7
--- /dev/null
+++ b/clib/err.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2014
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*!
+ * @file err.h
+ * @brief CLib error container
+ * @details Error is a special container that contains a library error
+ * @details For example,
+ * @code
+ * #include <clib/error.h>
+ * #include <clib/vector.h>
+ * #include <clib/vector_iter.h>
+ *
+ * FIX ME
+ *
+ * }
+ * @endcode
+ * @author Shaun Wetzstein <shaun@us.ibm.com>
+ * @date 2013
+ */
+
+#ifndef __ERR_H__
+#define __ERR_H__
+
+#include <sys/cdefs.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nargs.h"
+#include "list.h"
+
+/* ======================================================================= */
+
+#define ERR_NONE 0
+#define ERR_ERRNO 1
+#define ERR_UNEXPECTED 2
+#define ERR_VERSION 3
+#define ERR_LAST 4
+
+#define ERR_MAGIC 0x45525220 // "ERR "
+#define ERR_DATA_SIZE 1000
+
+#define INIT_ERR {ERR_MAGIC, 0, 0, NULL, 0, {0,}, 0}
+
+#define ERROR(t,c,f, ...) ({ \
+ err_t * _e = (err_t *)malloc(sizeof(*_e) + ERR_DATA_SIZE); \
+ memset(_e, 0, sizeof(*_e) + ERR_DATA_SIZE); \
+ _e->size = snprintf(_e->data, ERR_DATA_SIZE, (f), ##__VA_ARGS__); \
+ _e->magic = ERR_MAGIC, _e->type = (t), _e->code = (c); \
+ _e->file = __FILE__, _e->line = __LINE__; \
+ err_put(_e); \
+ })
+
+#define ERRNO(e) \
+ ERROR(ERR_ERRNO, (e), "%s => %s (errno=%d)", __func__, strerror(e), e)
+
+#define UNEXPECTED(f, ...) \
+ ERROR(ERR_UNEXPECTED, -1, (f), ##__VA_ARGS__)
+
+#define VERSION(v,f, ...) \
+ ERROR(ERR_VERSION, v, (f), ##__VA_ARGS__)
+
+/*!
+ * @brief error container
+ */
+struct err { //!< The error class
+ unsigned long magic; //!< Error magic number
+ list_node_t node; //!@ private
+
+ int type, code; //!< Error type & code
+ const char *file; //!< Error source file name
+ int line; //!< Error source line number
+
+ int size; //!< Extended error data size
+ char data[]; //!< Extended error data
+};
+typedef struct err err_t; //!< Alias for the @em error class
+
+/* ======================================================================= */
+
+extern void err_delete(err_t *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+
+/*!
+ * @brief Return the last library error
+ * @details For example,
+ * @code
+ * ...
+ * err_clear(err_get());
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @return None
+ */
+extern err_t *err_get(void);
+
+/*!
+ * @brief Set the last library error
+ * @details For example,
+ * @code
+ * ...
+ * err_out(&e);
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @return None
+ */
+extern void err_put(err_t *);
+
+/*!
+ * @fn int err_type(err_t *self, [ int type ])
+ * @brief Set or get the type from an @em error
+ * @details For example,
+ * @code
+ * ...
+ * err_type(&e, MY_ERROR_TYPE);
+ * if (err_type(&e) == MY_ERROR_TYPE)
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @param type [in] error type
+ * @return current error type
+ */
+/*! @cond */
+#define err_type(...) STRCAT(err_type, NARGS(__VA_ARGS__))(__VA_ARGS__)
+extern int err_type1(err_t *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+extern void err_type2(err_t *, int)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+/*! @endcond */
+
+/*!
+ * @fn int err_code(err_t *self, [ int code ])
+ * @brief Set or get the code from an @em error
+ * @details For example,
+ * @code
+ * ...
+ * err_code(&e, errno);
+ * if (err_code(&e) == EINVAL)
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @param code [in] error code
+ * @return current error code
+ */
+/*! @cond */
+#define err_code(...) STRCAT(err_code, NARGS(__VA_ARGS__))(__VA_ARGS__)
+extern int err_code1(err_t *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+extern void err_code2(err_t *, int)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+/*! @endcond */
+
+/*!
+ * @fn int err_file(err_t *self, [ const char * file ])
+ * @brief Set or get the file name from an @em error
+ * @details For example,
+ * @code
+ * ...
+ * err_file(&e, "example.txt");
+ * if (strcmp(err_file(&e), "example.txt") == 0)
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @param file [in] error file name
+ * @return current file name
+ */
+/*! @cond */
+#define err_file(...) STRCAT(err_file, NARGS(__VA_ARGS__))(__VA_ARGS__)
+extern const char *err_file1(err_t *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+extern void err_file2(err_t *, const char *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+/*! @endcond */
+
+/*!
+ * @fn int err_line(err_t *self, [ int line ])
+ * @brief Set or get the line number from an @em error
+ * @details For example,
+ * @code
+ * ...
+ * err_line(&e, errno);
+ * if (err_line(&e) == EINVAL)
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @param line [in] error line
+ * @return current error line
+ */
+/*! @cond */
+#define err_line(...) STRCAT(err_line, NARGS(__VA_ARGS__))(__VA_ARGS__)
+extern int err_line1(err_t *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+extern void err_line2(err_t *, int)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+/*! @endcond */
+
+/*!
+ * @fn int err_data(err_t *self, [ const void *data ])
+ * @brief Set or get the extended data from an @em error
+ * @details For example,
+ * @code
+ * ...
+ * err_data(&e, extended_data);
+ * memcpy(err_log, err_data(&e), err_size(&e));
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @param data [in] error extended data
+ * @return current error extended data
+ */
+/*! @cond */
+#define err_data(...) STRCAT(err_data, NARGS(__VA_ARGS__))(__VA_ARGS__)
+extern const void *err_data1(err_t *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+extern void err_data2(err_t *, int, const void *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+/*! @endcond */
+
+/*!
+ * @brief Get the data size from an @em error
+ * @details For example,
+ * @code
+ * ...
+ * err_size(&e, data_size);
+ * if (err_size(&e) <= 0)
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @return current error data size
+ */
+extern int err_size(err_t *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+
+/*!
+ * @brief Get the type name from an @em error
+ * @details For example,
+ * @code
+ * ...
+ * if (strcmp(err_name(&e), "errno") == 0)
+ * ...
+ * @endcode
+ * @memberof error
+ * @param self [in] error object @em self pointer
+ * @return current error data size
+ */
+/*! @cond */
+extern const char *err_type_name(err_t *)
+/*! @cond */
+__nonnull((1)) /*! @endcond */ ;
+
+/* ======================================================================= */
+
+#endif /* __ERR_H__ */
OpenPOWER on IntegriCloud