PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/liblangtag/lt-error.c

https://bitbucket.org/jlec/liblangtag
C | 242 lines | 137 code | 25 blank | 80 comment | 32 complexity | 3bba6700290ea5e83a9db72d4eff3acc MD5 | raw file
Possible License(s): LGPL-3.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
  2. /*
  3. * lt-error.c
  4. * Copyright (C) 2011-2012 Akira TAGOH
  5. *
  6. * Authors:
  7. * Akira TAGOH <akira@tagoh.org>
  8. *
  9. * You may distribute under the terms of either the GNU
  10. * Lesser General Public License or the Mozilla Public
  11. * License, as specified in the README file.
  12. */
  13. #ifdef HAVE_CONFIG_H
  14. #include "config.h"
  15. #endif
  16. #ifdef HAVE_EXECINFO_H
  17. #include <execinfo.h>
  18. #endif
  19. #include <stdlib.h>
  20. #include "lt-list.h"
  21. #include "lt-mem.h"
  22. #include "lt-messages.h"
  23. #include "lt-utils.h"
  24. #include "lt-error.h"
  25. struct _lt_error_t {
  26. lt_mem_t parent;
  27. lt_list_t *data;
  28. };
  29. typedef struct _lt_error_data_t {
  30. lt_mem_t parent;
  31. lt_error_type_t type;
  32. char *message;
  33. char **traces;
  34. size_t stack_size;
  35. } lt_error_data_t;
  36. /**
  37. * SECTION:lt-error
  38. * @Short_Description: Error handling
  39. * @Title: Error
  40. *
  41. * This section describes the error handling in this library.
  42. */
  43. /*< private >*/
  44. /**
  45. * lt_error_new:
  46. *
  47. * Creates #lt_error_t object. this function is protected and not supposed
  48. * to use in applications directly. Use lt_error_set().
  49. *
  50. * Returns: (transfer full): a newly allocated #lt_error_t. it has to be freed
  51. * with lt_error_unref().
  52. */
  53. lt_error_t *
  54. lt_error_new(void)
  55. {
  56. return lt_mem_alloc_object(sizeof (lt_error_t));
  57. }
  58. /*< public >*/
  59. /**
  60. * lt_error_ref:
  61. * @error: a #lt_error_t
  62. *
  63. * Inscreases the reference count of @error.
  64. *
  65. * Returns: (transfer none): the same @error object.
  66. */
  67. lt_error_t *
  68. lt_error_ref(lt_error_t *error)
  69. {
  70. lt_return_val_if_fail (error != NULL, NULL);
  71. return lt_mem_ref(&error->parent);
  72. }
  73. /**
  74. * lt_error_unref:
  75. * @error: a #lt_error_t
  76. *
  77. * Decreases the reference count of @error. when its reference count
  78. * drops to 0, the object is finalized (i.e. its memory is freed).
  79. */
  80. void
  81. lt_error_unref(lt_error_t *error)
  82. {
  83. if (error)
  84. lt_mem_unref(&error->parent);
  85. }
  86. /**
  87. * lt_error_set:
  88. * @error: a return location for a #lt_error_t
  89. * @type: a #lt_error_type_t
  90. * @message: the string format to output the error messages
  91. * @...: the parameters to insert into the format string
  92. *
  93. * Sets the error into @error according to the given parameters.
  94. *
  95. * Returns: an instance of #lt_error_t
  96. */
  97. lt_error_t *
  98. lt_error_set(lt_error_t **error,
  99. lt_error_type_t type,
  100. const char *message,
  101. ...)
  102. {
  103. va_list ap;
  104. #if HAVE_BACKTRACE
  105. void *traces[1024];
  106. #endif
  107. lt_error_data_t *d = lt_mem_alloc_object(sizeof (lt_error_data_t));
  108. int size = 0;
  109. lt_bool_t allocated;
  110. lt_return_val_if_fail (error != NULL, NULL);
  111. if (!d)
  112. goto bail0;
  113. if (!*error)
  114. *error = lt_error_new();
  115. if (!*error)
  116. goto bail0;
  117. d->type = type;
  118. va_start(ap, message);
  119. d->message = lt_strdup_vprintf(message, ap);
  120. va_end(ap);
  121. #if HAVE_BACKTRACE
  122. size = backtrace(traces, 1024);
  123. if (size > 0)
  124. d->traces = backtrace_symbols(traces, size);
  125. #else
  126. d->traces = NULL;
  127. #endif
  128. d->stack_size = size;
  129. lt_mem_add_ref(&d->parent, d->message, free);
  130. if (d->traces)
  131. lt_mem_add_ref(&d->parent, d->traces, free);
  132. allocated = (*error)->data == NULL;
  133. (*error)->data = lt_list_append((*error)->data, d, (lt_destroy_func_t)lt_mem_unref);
  134. if (allocated)
  135. lt_mem_add_ref(&(*error)->parent,
  136. (*error)->data,
  137. (lt_destroy_func_t)lt_list_free);
  138. return *error;
  139. bail0:
  140. lt_critical("Out of memory");
  141. return *error;
  142. }
  143. /**
  144. * lt_error_clear:
  145. * @error: a #lt_error_t
  146. *
  147. * Clean up all of the errors in @error.
  148. */
  149. void
  150. lt_error_clear(lt_error_t *error)
  151. {
  152. if (error) {
  153. if (error->data)
  154. lt_mem_delete_ref(&error->parent, error->data);
  155. error->data = NULL;
  156. }
  157. }
  158. /**
  159. * lt_error_is_set:
  160. * @error: a #lt_error_t
  161. * @type: a #lt_error_type_t
  162. *
  163. * Checks if @error contains @type of errors. if #LT_ERR_ANY is set to @type,
  164. * all the types of the errors are targeted. otherwise the result is filtered
  165. * out by @type.
  166. *
  167. * Returns: %TRUE if any, otherwise %FALSE
  168. */
  169. lt_bool_t
  170. lt_error_is_set(lt_error_t *error,
  171. lt_error_type_t type)
  172. {
  173. if (type == LT_ERR_ANY) {
  174. return error && error->data;
  175. } else {
  176. if (error && error->data) {
  177. lt_list_t *l;
  178. for (l = error->data; l != NULL; l = lt_list_next(l)) {
  179. lt_error_data_t *d = lt_list_value(l);
  180. if (d->type == type)
  181. return TRUE;
  182. }
  183. }
  184. }
  185. return FALSE;
  186. }
  187. /**
  188. * lt_error_print:
  189. * @error: a #lt_error_t
  190. * @type: a #lt_error_type_t
  191. *
  192. * Output the error messages in @error according to @type.
  193. */
  194. void
  195. lt_error_print(lt_error_t *error,
  196. lt_error_type_t type)
  197. {
  198. lt_list_t *l;
  199. if (lt_error_is_set(error, type)) {
  200. lt_warning("Error raised:");
  201. for (l = error->data; l != NULL; l = lt_list_next(l)) {
  202. lt_error_data_t *d = lt_list_value(l);
  203. int i;
  204. if (type == LT_ERR_ANY || type == d->type) {
  205. lt_warning(" %s", d->message);
  206. if (d->stack_size > 0) {
  207. lt_warning(" Backtraces:");
  208. } else {
  209. lt_warning(" No backtraces");
  210. }
  211. for (i = 1; i < d->stack_size; i++) {
  212. lt_warning(" %d. %s", i - 1, d->traces[i]);
  213. }
  214. }
  215. }
  216. }
  217. }