err.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* This file is part of nit.
  2. *
  3. * Nit is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU Lesser General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * Nit is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License
  14. * along with nit. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <errno.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include "err.h"
  20. static void
  21. reset(Err *err)
  22. {
  23. err->print_under = err->print_where = err->print_what =
  24. err->print_line = err->print_pos = err->occured = 0;
  25. }
  26. static void
  27. err_print(Err *err)
  28. {
  29. char buf[256];
  30. int space = err->print_where || err->print_line || err->print_pos;
  31. if (!err->occured) {
  32. fprintf(stderr, "No error has occured\n");
  33. return;
  34. }
  35. if (err->print_under) {
  36. /* It is useless to print this to stderr */
  37. for (unsigned i = 0; i < err->under; ++i)
  38. printf(" ");
  39. printf("^\n");
  40. }
  41. if (err->print_where) {
  42. if (err->where)
  43. fprintf(stderr, "%s:", err->where);
  44. else
  45. fprintf(stderr, "(Failed to allocate "
  46. "failure location string):");
  47. }
  48. if (err->print_line)
  49. fprintf(stderr, "%zu:", err->line);
  50. if (err->print_pos)
  51. fprintf(stderr, "%zu:", err->pos);
  52. if (space)
  53. fprintf(stderr, " ");
  54. if (err->custom) {
  55. fprintf(stderr, "%s", err->custom);
  56. } else {
  57. strerror_r(err->errnum, buf, sizeof(buf));
  58. fprintf(stderr, "%s", buf);
  59. }
  60. if (err->print_what) {
  61. if (err->what)
  62. fprintf(stderr, ": %s", err->what);
  63. else
  64. fprintf(stderr, ": (Failed to allocate "
  65. "failure content string)");
  66. }
  67. fprintf(stderr, "\n");
  68. }
  69. void
  70. err_init(Err *err, Err_log log)
  71. {
  72. err->where = err->what = NULL;
  73. err->where_len = err->what_len = 0;
  74. err->occured = 0;
  75. err->log = log ? log : err_print;
  76. }
  77. void
  78. err_dispose(Err *err)
  79. {
  80. free(err->where);
  81. free(err->what);
  82. }
  83. void
  84. err_std(Err *err)
  85. {
  86. reset(err);
  87. err->custom = NULL;
  88. err->errnum = errno;
  89. err->occured = 1;
  90. }
  91. void
  92. err_nit(Err *err, Nit_error error)
  93. {
  94. static const char *str_tbl[] = {
  95. [NIT_ERROR_FINE] = "No error",
  96. [NIT_ERROR_MEMORY] = "Ran out of memory",
  97. [NIT_ERROR_EMPTY] = "Data structure empty",
  98. [NIT_ERROR_NO_NEXT] = "Missing next value",
  99. [NIT_ERROR_ALREADY] = "Value already exists",
  100. [NIT_ERROR_NOT_FOUND] = "Value not found",
  101. [NIT_ERROR_NOT_DOABLE] = "Action is not doable",
  102. [NIT_ERROR_NOT_UNDOABLE] = "Action is not undoable",
  103. [NIT_ERROR_NOT_DIFF] = "Action cannot be done differently",
  104. [NIT_ERROR_FAILED] = "Failed to do action",
  105. [NIT_ERROR_ROI] = "Real action cannot be done on imaginary "
  106. "branch",
  107. [NIT_ERROR_REDO_PAST] = "Past cannot be redone for real"
  108. };
  109. err_cust(err, str_tbl[error]);
  110. }
  111. void
  112. err_cust(Err *err, const char *msg)
  113. {
  114. reset(err);
  115. err->custom = msg;
  116. err->occured = 1;
  117. }
  118. void
  119. err_under(Err *err, size_t under)
  120. {
  121. err->print_under = 1;
  122. err->under = under;
  123. }
  124. int
  125. err_where(Err *err, const char *where)
  126. {
  127. size_t new_len = strlen(where) + 1;
  128. size_t total_len = new_len;
  129. size_t old_len = 0;
  130. char *tmp;
  131. if (err->print_where)
  132. total_len += (old_len = strlen(err->where) + 1);
  133. if (total_len > err->where_len) {
  134. if (!(tmp = realloc(err->where, total_len))) {
  135. err->where_len = 0;
  136. free(err->where);
  137. err->where = NULL;
  138. return -1;
  139. }
  140. err->where = tmp;
  141. err->where_len = total_len;
  142. }
  143. memmove(err->where + new_len, err->where, old_len);
  144. strcpy(err->where, where);
  145. if (err->print_where)
  146. err->where[new_len - 1] = ':';
  147. err->print_where = 1;
  148. return 0;
  149. }
  150. int
  151. err_what(Err *err, const char *what)
  152. {
  153. size_t what_len = strlen(what) + 1;
  154. char *tmp;
  155. err->print_what = 1;
  156. if (what_len > err->what_len) {
  157. if (!(tmp = realloc(err->what, what_len))) {
  158. err->what_len = 0;
  159. free(err->what);
  160. err->what = NULL;
  161. return -1;
  162. }
  163. err->what = tmp;
  164. err->what_len = what_len;
  165. }
  166. strcpy(err->what, what);
  167. return 0;
  168. }
  169. void
  170. err_line(Err *err, size_t line)
  171. {
  172. err->print_line = 1;
  173. err->line = line;
  174. }
  175. void
  176. err_pos(Err *err, size_t pos)
  177. {
  178. err->print_pos = 1;
  179. err->pos = pos;
  180. }
  181. void
  182. err_log(Err *err)
  183. {
  184. err->log(err);
  185. }