From 0a8a00cd1060ee7aa9eae4223fc8c2577533247f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 29 Dec 2008 13:38:08 +0000 Subject: 2.5: Error reporting * Added a report list to operator, to which they can report errors and warnings. When the operator ends, it will display them with a popup. For python these should become exceptions when calling operators. * Added a function to make a popup menu from a report list. * Also added a utility function to prepend a string before the reports to indicate what they relates to. Also made the report functions used BLI_dynstr to simplify the code. * Made file reading and writing report errors to the user again using this system, also replacing the left over uncommented bad level error() calls. --- source/blender/blenkernel/BKE_blender.h | 7 +- source/blender/blenkernel/BKE_report.h | 4 +- source/blender/blenkernel/intern/blender.c | 62 ++++--------- source/blender/blenkernel/intern/context.c | 25 +++--- source/blender/blenkernel/intern/report.c | 140 +++++++++++++++++------------ 5 files changed, 121 insertions(+), 117 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 5eb3de4404e..dbdb570b2f8 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -40,6 +40,7 @@ extern "C" { struct ListBase; struct MemFile; struct bContext; +struct ReportList; #define BLENDER_VERSION 250 #define BLENDER_SUBVERSION 0 @@ -47,9 +48,9 @@ struct bContext; #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 -int BKE_read_file(struct bContext *C, char *dir, void *type_r); -int BKE_read_file_from_memory(struct bContext *C, char* filebuf, int filelength, void *type_r); -int BKE_read_file_from_memfile(struct bContext *C, struct MemFile *memfile); +int BKE_read_file(struct bContext *C, char *dir, void *type_r, struct ReportList *reports); +int BKE_read_file_from_memory(struct bContext *C, char* filebuf, int filelength, void *type_r, struct ReportList *reports); +int BKE_read_file_from_memfile(struct bContext *C, struct MemFile *memfile, struct ReportList *reports); void free_blender(void); void initglobals(void); diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index f87910d7872..8a5c623a225 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -49,7 +49,6 @@ typedef enum ReportType { enum ReportListFlags { RPT_PRINT = 1, RPT_STORE = 2, - RPT_HAS_ERROR = 4 }; typedef struct Report { @@ -72,6 +71,9 @@ void BKE_reports_clear(ReportList *reports); void BKE_report(ReportList *reports, ReportType type, const char *message); void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...); +void BKE_reports_prepend(ReportList *reports, const char *prepend); +void BKE_reports_prependf(ReportList *reports, const char *prepend, ...); + ReportType BKE_report_print_level(ReportList *reports); void BKE_report_print_level_set(ReportList *reports, ReportType level); diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 7c2d4502e5e..1ae61bad8b2 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -424,15 +424,12 @@ static void handle_subversion_warning(Main *main) 2: OK, and with new user settings */ -int BKE_read_file(bContext *C, char *dir, void *unused) +int BKE_read_file(bContext *C, char *dir, void *unused, ReportList *reports) { - ReportList reports; BlendFileData *bfd; int retval= 1; - - BKE_reports_init(&reports, RPT_STORE); - bfd= BLO_read_from_file(dir, &reports); + bfd= BLO_read_from_file(dir, reports); if (bfd) { if(bfd->user) retval= 2; @@ -440,50 +437,35 @@ int BKE_read_file(bContext *C, char *dir, void *unused) handle_subversion_warning(G.main); } - else { -// XXX error("Loading %s failed: %s", dir, BLO_bre_as_string(bre)); - } - - BKE_reports_clear(&reports); + else + BKE_reports_prependf(reports, "Loading %s failed: ", dir); return (bfd?retval:0); } -int BKE_read_file_from_memory(bContext *C, char* filebuf, int filelength, void *unused) +int BKE_read_file_from_memory(bContext *C, char* filebuf, int filelength, void *unused, ReportList *reports) { - ReportList reports; BlendFileData *bfd; - BKE_reports_init(&reports, RPT_STORE); - - bfd= BLO_read_from_memory(filebuf, filelength, &reports); - if (bfd) { + bfd= BLO_read_from_memory(filebuf, filelength, reports); + if (bfd) setup_app_data(C, bfd, ""); - } else { -// XXX error("Loading failed: %s", BLO_bre_as_string(bre)); - } - - BKE_reports_clear(&reports); + else + BKE_reports_prepend(reports, "Loading failed: "); return (bfd?1:0); } /* memfile is the undo buffer */ -int BKE_read_file_from_memfile(bContext *C, MemFile *memfile) +int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *reports) { - ReportList reports; BlendFileData *bfd; - - BKE_reports_init(&reports, RPT_STORE); - bfd= BLO_read_from_memfile(CTX_data_main(C), G.sce, memfile, &reports); - if (bfd) { + bfd= BLO_read_from_memfile(CTX_data_main(C), G.sce, memfile, reports); + if (bfd) setup_app_data(C, bfd, ""); - } else { -// XXX error("Loading failed: %s", BLO_bre_as_string(bre)); - } - - BKE_reports_clear(&reports); + else + BKE_reports_prepend(reports, "Loading failed: "); return (bfd?1:0); } @@ -516,10 +498,10 @@ static int read_undosave(bContext *C, UndoElem *uel) G.fileflags |= G_FILE_NO_UI; if(UNDO_DISK) - success= BKE_read_file(C, uel->str, NULL); + success= BKE_read_file(C, uel->str, NULL, NULL); else - success= BKE_read_file_from_memfile(C, &uel->memfile); - + success= BKE_read_file_from_memfile(C, &uel->memfile, NULL); + /* restore */ strcpy(G.sce, scestr); G.fileflags= fileflags; @@ -571,7 +553,6 @@ void BKE_write_undo(bContext *C, char *name) /* disk save version */ if(UNDO_DISK) { - ReportList reports; static int counter= 0; char tstr[FILE_MAXDIR+FILE_MAXFILE]; char numstr[32]; @@ -583,22 +564,17 @@ void BKE_write_undo(bContext *C, char *name) sprintf(numstr, "%d.blend", counter); BLI_make_file_string("/", tstr, btempdir, numstr); - BKE_reports_init(&reports, 0); - success= BLO_write_file(CTX_data_main(C), tstr, G.fileflags, &reports); - BKE_reports_clear(&reports); + success= BLO_write_file(CTX_data_main(C), tstr, G.fileflags, NULL); strcpy(curundo->str, tstr); } else { - ReportList reports; MemFile *prevfile=NULL; if(curundo->prev) prevfile= &(curundo->prev->memfile); memused= MEM_get_memory_in_use(); - BKE_reports_init(&reports, 0); - success= BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags, &reports); - BKE_reports_clear(&reports); + success= BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags, NULL); curundo->undosize= MEM_get_memory_in_use() - memused; } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index fa5740f74e9..aec497537cf 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -60,9 +60,6 @@ struct bContext { struct ARegion *region; struct uiBlock *block; - bContextDataCallback screen_cb; - bContextDataCallback area_cb; - bContextDataCallback region_cb; bContextDataCallback block_cb; } wm; @@ -191,26 +188,22 @@ void CTX_wm_window_set(bContext *C, wmWindow *win) C->wm.window= win; C->wm.screen= (win)? win->screen: NULL; C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL; - C->wm.screen_cb= (C->wm.screen)? C->wm.screen->context: NULL; } void CTX_wm_screen_set(bContext *C, bScreen *screen) { C->wm.screen= screen; C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL; - C->wm.screen_cb= (C->wm.screen)? C->wm.screen->context: NULL; } void CTX_wm_area_set(bContext *C, ScrArea *area) { C->wm.area= area; - C->wm.area_cb= (area && area->type)? area->type->context: NULL; } void CTX_wm_region_set(bContext *C, ARegion *region) { C->wm.region= region; - C->wm.region_cb= (region && region->type)? region->type->context: NULL; } void CTX_wm_ui_block_set(bContext *C, struct uiBlock *block, bContextDataCallback cb) @@ -240,21 +233,25 @@ static int ctx_data_get(bContext *C, const bContextDataMember *member, bContextD /* we check recursion to ensure that we do not get infinite * loops requesting data from ourselfs in a context callback */ - if(!done && recursion < 1 && C->wm.block_cb) { + if(!done && recursion < 1 && C->wm.block) { C->data.recursion= 1; done= C->wm.block_cb(C, member, result); } - if(!done && recursion < 2 && C->wm.region_cb) { + if(!done && recursion < 2 && C->wm.region) { C->data.recursion= 2; - done= C->wm.region_cb(C, member, result); + if(C->wm.region->type->context) + done= C->wm.region->type->context(C, member, result); } - if(!done && recursion < 3 && C->wm.area_cb) { + if(!done && recursion < 3 && C->wm.area) { C->data.recursion= 3; - done= C->wm.area_cb(C, member, result); + if(C->wm.area->type->context) + done= C->wm.area->type->context(C, member, result); } - if(!done && recursion < 4 && C->wm.screen_cb) { + if(!done && recursion < 4 && C->wm.screen) { + bContextDataCallback cb= C->wm.screen->context; C->data.recursion= 4; - done= C->wm.screen_cb(C, member, result); + if(cb) + done= cb(C, member, result); } C->data.recursion= recursion; diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 12fbaf806d5..97bbaf66b3a 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -30,6 +30,7 @@ #include "DNA_listBase.h" #include "BLI_blenlib.h" +#include "BLI_dynstr.h" #include "BKE_report.h" @@ -59,6 +60,9 @@ static char *report_type_str(int type) void BKE_reports_init(ReportList *reports, int flag) { + if(!reports) + return; + memset(reports, 0, sizeof(ReportList)); reports->storelevel= RPT_WARNING; @@ -70,6 +74,9 @@ void BKE_reports_clear(ReportList *reports) { Report *report; + if(!reports) + return; + for(report=reports->list.first; report; report=report->next) MEM_freeN(report->message); @@ -81,18 +88,12 @@ void BKE_report(ReportList *reports, ReportType type, const char *message) Report *report; int len; - if(!reports) - return; - - if(type >= RPT_ERROR) - reports->flag |= RPT_HAS_ERROR; - - if((reports->flag & RPT_PRINT) && (type >= reports->printlevel)) { + if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { printf("%s: %s\n", report_type_str(type), message); fflush(stdout); /* this ensures the message is printed before a crash */ } - if((reports->flag & RPT_STORE) && (type >= reports->storelevel)) { + if(reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) { report= MEM_callocN(sizeof(Report), "Report"); report->type= type; report->typestr= report_type_str(type); @@ -107,83 +108,110 @@ void BKE_report(ReportList *reports, ReportType type, const char *message) void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) { + DynStr *ds; Report *report; va_list args; - char *message; - int len= 256, maxlen= 65536, retval; - - if(!reports) - return; - - if(type >= RPT_ERROR) - reports->flag |= RPT_HAS_ERROR; - if((reports->flag & RPT_PRINT) && (type >= reports->printlevel)) { + if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { va_start(args, format); vprintf(format, args); va_end(args); fflush(stdout); /* this ensures the message is printed before a crash */ } - if((reports->flag & RPT_STORE) && (type >= reports->storelevel)) { - while(1) { - message= MEM_callocN(sizeof(char)*len+1, "ReportMessage"); - - va_start(args, format); - retval= vsnprintf(message, len, format, args); - va_end(args); - - if(retval == -1) { - /* -1 means not enough space, but on windows it may also mean - * there is a formatting error, so we impose a maximum length */ - MEM_freeN(message); - message= NULL; - - len *= 2; - if(len > maxlen) { - fprintf(stderr, "BKE_reportf message too long or format error.\n"); - break; - } - } - else if(retval > len) { - /* in C99 the actual length required is returned */ - MEM_freeN(message); - message= NULL; - - len= retval; - } - else - break; - } - - if(message) { - report= MEM_callocN(sizeof(Report), "Report"); - report->type= type; - report->typestr= report_type_str(type); - report->message= message; - - BLI_addtail(&reports->list, report); - } + if(reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) { + report= MEM_callocN(sizeof(Report), "Report"); + + ds= BLI_dynstr_new(); + va_start(args, format); + BLI_dynstr_vappendf(ds, format, args); + va_end(args); + + report->message= BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); + + report->type= type; + report->typestr= report_type_str(type); + + BLI_addtail(&reports->list, report); + } +} + +void BKE_reports_prepend(ReportList *reports, const char *prepend) +{ + Report *report; + DynStr *ds; + + if(!reports) + return; + + for(report=reports->list.first; report; report=report->next) { + ds= BLI_dynstr_new(); + + BLI_dynstr_append(ds, prepend); + BLI_dynstr_append(ds, report->message); + MEM_freeN(report->message); + + report->message= BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); + } +} + +void BKE_reports_prependf(ReportList *reports, const char *prepend, ...) +{ + Report *report; + DynStr *ds; + va_list args; + + if(!reports) + return; + + for(report=reports->list.first; report; report=report->next) { + ds= BLI_dynstr_new(); + va_start(args, prepend); + BLI_dynstr_vappendf(ds, prepend, args); + va_end(args); + + BLI_dynstr_append(ds, report->message); + MEM_freeN(report->message); + + report->message= BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); } } ReportType BKE_report_print_level(ReportList *reports) { + if(!reports) + return RPT_ERROR; + return reports->printlevel; } void BKE_report_print_level_set(ReportList *reports, ReportType level) { + if(!reports) + return; + reports->printlevel= level; } ReportType BKE_report_store_level(ReportList *reports) { + if(!reports) + return RPT_ERROR; + return reports->storelevel; } void BKE_report_store_level_set(ReportList *reports, ReportType level) { + if(!reports) + return; + reports->storelevel= level; } -- cgit v1.2.3