report.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*
  2. * ***** BEGIN GPL LICENSE BLOCK *****
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software Foundation,
  16. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. *
  18. * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  19. * All rights reserved.
  20. *
  21. * Contributor(s): Blender Foundation (2008).
  22. *
  23. * ***** END GPL LICENSE BLOCK *****
  24. */
  25. /** \file blender/blenkernel/intern/report.c
  26. * \ingroup bke
  27. */
  28. #include <stdarg.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <errno.h>
  32. #include "MEM_guardedalloc.h"
  33. #include "BLI_blenlib.h"
  34. #include "BLI_dynstr.h"
  35. #include "BLI_utildefines.h"
  36. #include "BLT_translation.h"
  37. #include "BKE_report.h"
  38. #include "BKE_global.h" /* G.background only */
  39. const char *BKE_report_type_str(ReportType type)
  40. {
  41. switch (type) {
  42. case RPT_DEBUG:
  43. return TIP_("Debug");
  44. case RPT_INFO:
  45. return TIP_("Info");
  46. case RPT_OPERATOR:
  47. return TIP_("Operator");
  48. case RPT_PROPERTY:
  49. return TIP_("Property");
  50. case RPT_WARNING:
  51. return TIP_("Warning");
  52. case RPT_ERROR:
  53. return TIP_("Error");
  54. case RPT_ERROR_INVALID_INPUT:
  55. return TIP_("Invalid Input Error");
  56. case RPT_ERROR_INVALID_CONTEXT:
  57. return TIP_("Invalid Context Error");
  58. case RPT_ERROR_OUT_OF_MEMORY:
  59. return TIP_("Out Of Memory Error");
  60. default:
  61. return TIP_("Undefined Type");
  62. }
  63. }
  64. void BKE_reports_init(ReportList *reports, int flag)
  65. {
  66. if (!reports)
  67. return;
  68. memset(reports, 0, sizeof(ReportList));
  69. reports->storelevel = RPT_INFO;
  70. reports->printlevel = RPT_ERROR;
  71. reports->flag = flag;
  72. }
  73. void BKE_reports_clear(ReportList *reports)
  74. {
  75. Report *report, *report_next;
  76. if (!reports)
  77. return;
  78. report = reports->list.first;
  79. while (report) {
  80. report_next = report->next;
  81. MEM_freeN((void *)report->message);
  82. MEM_freeN(report);
  83. report = report_next;
  84. }
  85. BLI_listbase_clear(&reports->list);
  86. }
  87. void BKE_report(ReportList *reports, ReportType type, const char *_message)
  88. {
  89. Report *report;
  90. int len;
  91. const char *message = TIP_(_message);
  92. /* in background mode always print otherwise there are cases the errors wont be displayed,
  93. * but still add to the report list since this is used for python exception handling */
  94. if (G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
  95. printf("%s: %s\n", BKE_report_type_str(type), message);
  96. fflush(stdout); /* this ensures the message is printed before a crash */
  97. }
  98. if (reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
  99. char *message_alloc;
  100. report = MEM_callocN(sizeof(Report), "Report");
  101. report->type = type;
  102. report->typestr = BKE_report_type_str(type);
  103. len = strlen(message);
  104. message_alloc = MEM_callocN(sizeof(char) * (len + 1), "ReportMessage");
  105. memcpy(message_alloc, message, sizeof(char) * (len + 1));
  106. report->message = message_alloc;
  107. report->len = len;
  108. BLI_addtail(&reports->list, report);
  109. }
  110. }
  111. void BKE_reportf(ReportList *reports, ReportType type, const char *_format, ...)
  112. {
  113. DynStr *ds;
  114. Report *report;
  115. va_list args;
  116. const char *format = TIP_(_format);
  117. if (G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
  118. printf("%s: ", BKE_report_type_str(type));
  119. va_start(args, _format);
  120. vprintf(format, args);
  121. va_end(args);
  122. fprintf(stdout, "\n"); /* otherise each report needs to include a \n */
  123. fflush(stdout); /* this ensures the message is printed before a crash */
  124. }
  125. if (reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
  126. report = MEM_callocN(sizeof(Report), "Report");
  127. ds = BLI_dynstr_new();
  128. va_start(args, _format);
  129. BLI_dynstr_vappendf(ds, format, args);
  130. va_end(args);
  131. report->message = BLI_dynstr_get_cstring(ds);
  132. report->len = BLI_dynstr_get_len(ds);
  133. BLI_dynstr_free(ds);
  134. report->type = type;
  135. report->typestr = BKE_report_type_str(type);
  136. BLI_addtail(&reports->list, report);
  137. }
  138. }
  139. void BKE_reports_prepend(ReportList *reports, const char *_prepend)
  140. {
  141. Report *report;
  142. DynStr *ds;
  143. const char *prepend = TIP_(_prepend);
  144. if (!reports)
  145. return;
  146. for (report = reports->list.first; report; report = report->next) {
  147. ds = BLI_dynstr_new();
  148. BLI_dynstr_append(ds, prepend);
  149. BLI_dynstr_append(ds, report->message);
  150. MEM_freeN((void *)report->message);
  151. report->message = BLI_dynstr_get_cstring(ds);
  152. report->len = BLI_dynstr_get_len(ds);
  153. BLI_dynstr_free(ds);
  154. }
  155. }
  156. void BKE_reports_prependf(ReportList *reports, const char *_prepend, ...)
  157. {
  158. Report *report;
  159. DynStr *ds;
  160. va_list args;
  161. const char *prepend = TIP_(_prepend);
  162. if (!reports)
  163. return;
  164. for (report = reports->list.first; report; report = report->next) {
  165. ds = BLI_dynstr_new();
  166. va_start(args, _prepend);
  167. BLI_dynstr_vappendf(ds, prepend, args);
  168. va_end(args);
  169. BLI_dynstr_append(ds, report->message);
  170. MEM_freeN((void *)report->message);
  171. report->message = BLI_dynstr_get_cstring(ds);
  172. report->len = BLI_dynstr_get_len(ds);
  173. BLI_dynstr_free(ds);
  174. }
  175. }
  176. ReportType BKE_report_print_level(ReportList *reports)
  177. {
  178. if (!reports)
  179. return RPT_ERROR;
  180. return reports->printlevel;
  181. }
  182. void BKE_report_print_level_set(ReportList *reports, ReportType level)
  183. {
  184. if (!reports)
  185. return;
  186. reports->printlevel = level;
  187. }
  188. ReportType BKE_report_store_level(ReportList *reports)
  189. {
  190. if (!reports)
  191. return RPT_ERROR;
  192. return reports->storelevel;
  193. }
  194. void BKE_report_store_level_set(ReportList *reports, ReportType level)
  195. {
  196. if (!reports)
  197. return;
  198. reports->storelevel = level;
  199. }
  200. char *BKE_reports_string(ReportList *reports, ReportType level)
  201. {
  202. Report *report;
  203. DynStr *ds;
  204. char *cstring;
  205. if (!reports || !reports->list.first)
  206. return NULL;
  207. ds = BLI_dynstr_new();
  208. for (report = reports->list.first; report; report = report->next)
  209. if (report->type >= level)
  210. BLI_dynstr_appendf(ds, "%s: %s\n", report->typestr, report->message);
  211. if (BLI_dynstr_get_len(ds))
  212. cstring = BLI_dynstr_get_cstring(ds);
  213. else
  214. cstring = NULL;
  215. BLI_dynstr_free(ds);
  216. return cstring;
  217. }
  218. void BKE_reports_print(ReportList *reports, ReportType level)
  219. {
  220. char *cstring = BKE_reports_string(reports, level);
  221. if (cstring == NULL)
  222. return;
  223. puts(cstring);
  224. fflush(stdout);
  225. MEM_freeN(cstring);
  226. }
  227. Report *BKE_reports_last_displayable(ReportList *reports)
  228. {
  229. Report *report;
  230. for (report = reports->list.last; report; report = report->prev) {
  231. if (ELEM(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO))
  232. return report;
  233. }
  234. return NULL;
  235. }
  236. bool BKE_reports_contain(ReportList *reports, ReportType level)
  237. {
  238. Report *report;
  239. if (reports != NULL) {
  240. for (report = reports->list.first; report; report = report->next)
  241. if (report->type >= level)
  242. return true;
  243. }
  244. return false;
  245. }
  246. bool BKE_report_write_file_fp(FILE *fp, ReportList *reports, const char *header)
  247. {
  248. Report *report;
  249. if (header) {
  250. fputs(header, fp);
  251. }
  252. for (report = reports->list.first; report; report = report->next) {
  253. fprintf((FILE *)fp, "%s # %s\n", report->message, report->typestr);
  254. }
  255. return true;
  256. }
  257. bool BKE_report_write_file(const char *filepath, ReportList *reports, const char *header)
  258. {
  259. FILE *fp;
  260. errno = 0;
  261. fp = BLI_fopen(filepath, "wb");
  262. if (fp == NULL) {
  263. fprintf(stderr, "Unable to save '%s': %s\n",
  264. filepath, errno ? strerror(errno) : "Unknown error opening file");
  265. return false;
  266. }
  267. BKE_report_write_file_fp(fp, reports, header);
  268. fclose(fp);
  269. return true;
  270. }