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.
This commit is contained in:
2008-12-29 13:38:08 +00:00
parent d51bc24384
commit 0a8a00cd10
23 changed files with 340 additions and 227 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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, "<memory2>");
} 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, "<memory1>");
} 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,9 +498,9 @@ 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);
@@ -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;
}

View File

@@ -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;

View File

@@ -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");
if(reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
report= MEM_callocN(sizeof(Report), "Report");
va_start(args, format);
retval= vsnprintf(message, len, format, args);
va_end(args);
ds= BLI_dynstr_new();
va_start(args, format);
BLI_dynstr_vappendf(ds, 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;
report->message= BLI_dynstr_get_cstring(ds);
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;
BLI_dynstr_free(ds);
len= retval;
}
else
break;
}
report->type= type;
report->typestr= report_type_str(type);
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);
}
}
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;
}

View File

@@ -38,6 +38,8 @@
#ifndef BLI_DYNSTR_H
#define BLI_DYNSTR_H
#include <stdarg.h>
struct DynStr;
/** The abstract DynStr type */
@@ -65,6 +67,7 @@ void BLI_dynstr_append (DynStr *ds, const char *cstr);
* @param format The printf format string to use.
*/
void BLI_dynstr_appendf (DynStr *ds, const char *format, ...);
void BLI_dynstr_vappendf (DynStr *ds, const char *format, va_list args);
/**
* Find the length of a DynStr.

View File

@@ -83,9 +83,8 @@ void BLI_dynstr_append(DynStr *ds, const char *cstr) {
ds->curlen+= cstrlen;
}
void BLI_dynstr_appendf(DynStr *ds, const char *format, ...)
void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args)
{
va_list args;
char *message, fixedmessage[256];
int len= 256, maxlen= 65536, retval;
@@ -95,9 +94,7 @@ void BLI_dynstr_appendf(DynStr *ds, const char *format, ...)
else
message= MEM_callocN(sizeof(char)*len+1, "BLI_dynstr_appendf");
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
@@ -132,6 +129,15 @@ void BLI_dynstr_appendf(DynStr *ds, const char *format, ...)
}
}
void BLI_dynstr_appendf(DynStr *ds, const char *format, ...)
{
va_list args;
va_start(args, format);
BLI_dynstr_vappendf(ds, format, args);
va_end(args);
}
int BLI_dynstr_get_len(DynStr *ds) {
return ds->curlen;
}

View File

@@ -200,10 +200,10 @@ BLO_blendhandle_close(
char *BLO_gethome(void);
int BLO_has_bfile_extension(char *str);
void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode, struct Main *mainvar, struct Scene *scene);
void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode, struct Main *mainvar, struct Scene *scene, struct ReportList *reports);
void BLO_library_append_(BlendHandle **libfiledata, struct direntry* filelist, int totfile,
char *dir, char* file, short flag, int idcode, struct Main *mainvar, struct Scene *scene);
void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Main *mainvar, struct Scene *scene);
char *dir, char* file, short flag, int idcode, struct Main *mainvar, struct Scene *scene, struct ReportList *reports);
void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Main *mainvar, struct Scene *scene, struct ReportList *reports);
BlendFileData* blo_read_blendafterruntime(int file, char *name, int actualsize, struct ReportList *reports);

View File

@@ -166,12 +166,9 @@ int BLO_idcode_from_name(char *name)
BlendHandle *BLO_blendhandle_from_file(char *file)
{
ReportList reports;
BlendHandle *bh;
BKE_reports_init(&reports, 0);
bh= (BlendHandle*)blo_openblenderfile(file, &reports);
BKE_reports_clear(&reports);
bh= (BlendHandle*)blo_openblenderfile(file, NULL);
return bh;
}
@@ -330,7 +327,8 @@ BlendFileData *BLO_read_from_file(char *file, ReportList *reports)
fd = blo_openblenderfile(file, reports);
if (fd) {
bfd= blo_read_file_internal(fd, reports);
fd->reports= reports;
bfd= blo_read_file_internal(fd);
if (bfd) {
bfd->type= BLENFILETYPE_BLEND;
strncpy(bfd->main->name, file, sizeof(bfd->main->name)-1);
@@ -348,7 +346,8 @@ BlendFileData *BLO_read_from_memory(void *mem, int memsize, ReportList *reports)
fd = blo_openblendermemory(mem, memsize, reports);
if (fd) {
bfd= blo_read_file_internal(fd, reports);
fd->reports= reports;
bfd= blo_read_file_internal(fd);
if (bfd) {
bfd->type= BLENFILETYPE_BLEND;
strcpy(bfd->main->name, "");
@@ -367,6 +366,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
fd = blo_openblendermemfile(memfile, reports);
if (fd) {
fd->reports= reports;
strcpy(fd->filename, filename);
/* clear ob->proxy_from pointers in old main */
@@ -380,7 +380,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
/* makes lookup of existing images in old main */
blo_make_image_pointer_map(fd, oldmain);
bfd= blo_read_file_internal(fd, reports);
bfd= blo_read_file_internal(fd);
if (bfd) {
bfd->type= BLENFILETYPE_BLEND;
strcpy(bfd->main->name, "");

View File

@@ -150,8 +150,6 @@
#include "readfile.h"
//XXX #include "wm_event_types.h"
#include <errno.h>
/*
@@ -3111,7 +3109,7 @@ static void lib_link_object(FileData *fd, Main *main)
ob= ob->id.next;
}
if(warn) //XXX error("WARNING IN CONSOLE");
if(warn)
BKE_report(fd->reports, RPT_WARNING, "Warning in console");
}
@@ -3808,7 +3806,7 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
}
}
/* ************ READ SCREEN ***************** */
/* ****************** READ GREASE PENCIL ***************** */
/* relinks grease-pencil data for 3d-view(s) - used for direct_link */
static void link_gpencil(FileData *fd, bGPdata *gpd)
@@ -3836,6 +3834,29 @@ static void link_gpencil(FileData *fd, bGPdata *gpd)
}
}
/* ****************** READ SCREEN ***************** */
static void butspace_version_132(SpaceButs *buts)
{
buts->v2d.tot.xmin= 0.0f;
buts->v2d.tot.ymin= 0.0f;
buts->v2d.tot.xmax= 1279.0f;
buts->v2d.tot.ymax= 228.0f;
buts->v2d.min[0]= 256.0f;
buts->v2d.min[1]= 42.0f;
buts->v2d.max[0]= 2048.0f;
buts->v2d.max[1]= 450.0f;
buts->v2d.minzoom= 0.5f;
buts->v2d.maxzoom= 1.21f;
buts->v2d.scroll= 0;
buts->v2d.keepzoom= 1;
buts->v2d.keeptot= 1;
}
/* note: file read without screens option G_FILE_NO_UI;
check lib pointers in call below */
static void lib_link_screen(FileData *fd, Main *main)
@@ -3887,7 +3908,8 @@ static void lib_link_screen(FileData *fd, Main *main)
SpaceButs *sbuts= (SpaceButs *)sl;
sbuts->lockpoin= NULL;
sbuts->ri= NULL;
// XXX if(main->versionfile<132) set_rects_butspace(sbuts);
if(main->versionfile<132)
butspace_version_132(sbuts);
}
else if(sl->spacetype==SPACE_FILE) {
SpaceFile *sfile= (SpaceFile *)sl;
@@ -4189,6 +4211,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
link_list(fd, &(sc->edgebase));
link_list(fd, &(sc->areabase));
sc->regionbase.first= sc->regionbase.last= NULL;
sc->context= NULL;
sc->mainwin= sc->subwinactive= 0; /* indices */
@@ -4340,7 +4363,6 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
BLI_remlink(&main->library, lib);
MEM_freeN(lib);
//XXX error("Library had multiple instances, save and reload!");
BKE_report(fd->reports, RPT_WARNING, "Library had multiple instances, save and reload!");
return;
@@ -5602,8 +5624,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
SpaceLink *sl= sa->spacedata.first;
while(sl) {
if(sl->spacetype==SPACE_BUTS) {
//SpaceButs *sbuts= (SpaceButs*) sl;
//XXX sbuts->scaflag= BUTS_SENS_LINK|BUTS_SENS_ACT|BUTS_CONT_ACT|BUTS_ACT_ACT|BUTS_ACT_LINK;
SpaceButs *sbuts= (SpaceButs*) sl;
sbuts->scaflag= BUTS_SENS_LINK|BUTS_SENS_ACT|BUTS_CONT_ACT|BUTS_ACT_ACT|BUTS_ACT_LINK;
}
sl= sl->next;
}
@@ -6254,8 +6276,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
sbuts->v2d.maxzoom= 1.2f;
sbuts->align= 1; /* horizontal default */
//XXX
#if 0
if(sbuts->mainb==BUTS_LAMP) {
sbuts->mainb= CONTEXT_SHADING;
sbuts->tab[CONTEXT_SHADING]= TAB_SHADING_LAMP;
@@ -6299,7 +6319,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
sbuts->mainb= CONTEXT_EDITING;
}
else sbuts->mainb= CONTEXT_SCENE;
#endif
}
}
}
@@ -8424,7 +8443,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
return bhead;
}
BlendFileData *blo_read_file_internal(FileData *fd, ReportList *reports)
BlendFileData *blo_read_file_internal(FileData *fd)
{
BHead *bhead= blo_firstbhead(fd);
BlendFileData *bfd;
@@ -9480,26 +9499,33 @@ static Library* library_append(Main *mainvar, Scene *scene, char* file, char *di
/* this should probably be moved into the Python code anyway */
void BLO_script_library_append(BlendHandle **bh, char *dir, char *name,
int idcode, short flag, Main *mainvar, Scene *scene)
int idcode, short flag, Main *mainvar, Scene *scene, ReportList *reports)
{
FileData *fd= (FileData*)(*bh);
/* try to append the requested object */
library_append(mainvar, scene, name, dir, idcode, 0, (FileData **)bh, NULL, 0, flag );
fd->reports= reports;
library_append(mainvar, scene, name, dir, idcode, 0, &fd, NULL, 0, flag );
if(fd) fd->reports= NULL;
/* do we need to do this? */
DAG_scene_sort(scene);
*bh= (BlendHandle*)fd;
}
/* append to scene */
/* dir is a full path */
void BLO_library_append(SpaceFile *sfile, char *dir, int idcode, Main *mainvar, Scene *scene)
void BLO_library_append(SpaceFile *sfile, char *dir, int idcode, Main *mainvar, Scene *scene, ReportList *reports)
{
BLO_library_append_(&sfile->libfiledata, sfile->filelist, sfile->totfile,
dir, sfile->file, sfile->flag, idcode, mainvar, scene);
dir, sfile->file, sfile->flag, idcode, mainvar, scene, reports);
}
void BLO_library_append_(BlendHandle** libfiledata, struct direntry* filelist, int totfile,
char *dir, char* file, short flag, int idcode, Main *mainvar, Scene *scene)
void BLO_library_append_(BlendHandle** bh, struct direntry* filelist, int totfile,
char *dir, char* file, short flag, int idcode, Main *mainvar, Scene *scene, ReportList *reports)
{
FileData *fd= (FileData*)(*bh);
Library *curlib;
Base *centerbase;
Object *ob;
@@ -9519,12 +9545,12 @@ void BLO_library_append_(BlendHandle** libfiledata, struct direntry* filelist, i
if( strcmp(filelist[a].relname, file)==0) break;
}
if(a==totfile) {
//XXX error("Wrong indicated name");
BKE_report(reports, RPT_ERROR, "Wrong indicated name");
return;
}
}
else {
//XXX error("Nothing indicated");
BKE_report(reports, RPT_ERROR, "Nothing indicated");
return;
}
}
@@ -9532,7 +9558,11 @@ void BLO_library_append_(BlendHandle** libfiledata, struct direntry* filelist, i
if(flag & FILE_AUTOSELECT) scene_deselect_all(scene);
curlib = library_append(mainvar, scene, file, dir, idcode, totsel, (FileData**) libfiledata, filelist, totfile,flag );
fd->reports= reports;
curlib = library_append(mainvar, scene, file, dir, idcode, totsel, &fd, filelist, totfile,flag );
if(fd) fd->reports= NULL;
*bh= (BlendHandle*)fd;
/* when not linking (appending)... */
if((flag & FILE_LINK)==0) {
@@ -9614,9 +9644,8 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
ReportList reports;
printf("read library: lib %s\n", mainptr->curlib->name);
BKE_reports_init(&reports, 0);
fd= blo_openblenderfile(mainptr->curlib->filename, &reports);
BKE_reports_clear(&reports);
fd->reports= basefd->reports;
if (fd) {
if (fd->libmap)
@@ -9731,7 +9760,8 @@ BlendFileData *blo_read_blendafterruntime(int file, char *name, int actualsize,
if (!fd)
return NULL;
bfd= blo_read_file_internal(fd, reports);
fd->reports= reports;
bfd= blo_read_file_internal(fd);
blo_freefiledata(fd);
return bfd;

View File

@@ -107,10 +107,10 @@ struct Main;
void blo_join_main(ListBase *mainlist);
void blo_split_main(ListBase *mainlist, struct Main *main);
BlendFileData *blo_read_file_internal( FileData *fd, struct ReportList *reports);
BlendFileData *blo_read_file_internal(FileData *fd);
FileData *blo_openblenderfile( char *name, struct ReportList *reports);
FileData *blo_openblendermemory( void *buffer, int buffersize, struct ReportList *reports);
FileData *blo_openblenderfile(char *name, struct ReportList *reports);
FileData *blo_openblendermemory(void *buffer, int buffersize, struct ReportList *reports);
FileData *blo_openblendermemfile(struct MemFile *memfile, struct ReportList *reports);
void blo_clear_proxy_pointers_from_lib(FileData *fd, Main *oldmain);

View File

@@ -2265,20 +2265,22 @@ cleanup:
if (runtime)
MEM_freeN(runtime);
return !(reports->flag & RPT_HAS_ERROR);
return !BKE_reports_have_error(reports);
}
int BLO_write_runtime(Main *mainvar, char *file, char *exename, ReportList *reports)
{
char gamename[FILE_MAXDIR+FILE_MAXFILE];
int outfd = -1;
int outfd = -1, error= 0;
// remove existing file / bundle
//printf("Delete file %s\n", file);
BLI_delete(file, 0, TRUE);
if (!recursive_copy_runtime(file, exename, reports))
if (!recursive_copy_runtime(file, exename, reports)) {
error= 1;
goto cleanup;
}
strcpy(gamename, file);
strcat(gamename, "/Contents/Resources/game.blend");
@@ -2290,18 +2292,20 @@ int BLO_write_runtime(Main *mainvar, char *file, char *exename, ReportList *repo
if (write(outfd, " ", 1) != 1) {
BKE_report(reports, RPT_ERROR, "Unable to write to output file.");
error= 1;
goto cleanup;
}
} else {
BKE_report(reports, RPT_ERROR, "Unable to open blenderfile.");
error= 1;
}
cleanup:
if (outfd!=-1)
close(outfd);
//XXX error("Unable to make runtime: %s", cause);
return !(reports->flag & RPT_HAS_ERROR);
BKE_reports_prepend(reports, "Unable to make runtime: ");
return !error;
}
#else /* !__APPLE__ */
@@ -2310,22 +2314,25 @@ static int handle_append_runtime(int handle, char *exename, ReportList *reports)
{
char *runtime= get_runtime_path(exename);
unsigned char buf[1024];
int count, progfd= -1;
int count, progfd= -1, error= 0;
if (!BLI_exists(runtime)) {
BKE_report(reports, RPT_ERROR, "Unable to find runtime.");
error= 1;
goto cleanup;
}
progfd= open(runtime, O_BINARY|O_RDONLY, 0);
if (progfd==-1) {
BKE_report(reports, RPT_ERROR, "Unable to find runtime.@");
error= 1;
goto cleanup;
}
while ((count= read(progfd, buf, sizeof(buf)))>0) {
if (write(handle, buf, count)!=count) {
BKE_report(reports, RPT_ERROR, "Unable to write to output file.");
error= 1;
goto cleanup;
}
}
@@ -2336,7 +2343,7 @@ cleanup:
if (runtime)
MEM_freeN(runtime);
return !(reports->flag & RPT_HAS_ERROR);
return !error;
}
static int handle_write_msb_int(int handle, int i)
@@ -2353,14 +2360,17 @@ static int handle_write_msb_int(int handle, int i)
int BLO_write_runtime(Main *mainvar, char *file, char *exename, ReportList *reports)
{
int outfd= open(file, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, 0777);
int datastart;
int datastart, error= 0;
if (!outfd) {
BKE_report(reports, RPT_ERROR, "Unable to open output file.");
error= 1;
goto cleanup;
}
if (!handle_append_runtime(outfd, exename, reports))
if (!handle_append_runtime(outfd, exename, reports)) {
error= 1;
goto cleanup;
}
datastart= lseek(outfd, 0, SEEK_CUR);
@@ -2368,6 +2378,7 @@ int BLO_write_runtime(Main *mainvar, char *file, char *exename, ReportList *repo
if (!handle_write_msb_int(outfd, datastart) || (write(outfd, "BRUNTIME", 8)!=8)) {
BKE_report(reports, RPT_ERROR, "Unable to write to output file.");
error= 1;
goto cleanup;
}
@@ -2375,8 +2386,8 @@ cleanup:
if (outfd!=-1)
close(outfd);
//XXX error("Unable to make runtime: %s", cause);
return !(reports->flag & RPT_HAS_ERROR);
BKE_reports_prepend(reports, "Unable to make runtime: ");
return !error;
}
#endif /* !__APPLE__ */

View File

@@ -40,6 +40,7 @@ struct AutoComplete;
struct bContext;
struct PointerRNA;
struct PropertyRNA;
struct ReportList;
/* uiBlock->dt */
#define UI_EMBOSS 0 /* use one of the themes for drawing */
@@ -216,6 +217,7 @@ void uiPupmenuOkee(struct bContext *C, char *opname, char *str, ...);
void uiPupmenuSaveOver(struct bContext *C, char *opname, char *filename, ...);
void uiPupmenuNotice(struct bContext *C, char *str, ...);
void uiPupmenuError(struct bContext *C, char *str, ...);
void uiPupmenuReports(struct bContext *C, struct ReportList *reports);
/* Block */

View File

@@ -36,8 +36,10 @@
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "BKE_context.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_utildefines.h"
@@ -1765,3 +1767,30 @@ void uiPupmenuError(bContext *C, char *str, ...)
va_end(ap);
}
void uiPupmenuReports(bContext *C, ReportList *reports)
{
Report *report;
DynStr *ds;
char *str;
if(!reports || !reports->list.first)
return;
if(!CTX_wm_window(C))
return;
ds= BLI_dynstr_new();
for(report=reports->list.first; report; report=report->next) {
if(report->type >= RPT_ERROR)
BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message);
else if(report->type >= RPT_WARNING)
BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message);
}
str= BLI_dynstr_get_cstring(ds);
uiPupmenu(C, 0, NULL, NULL, str);
MEM_freeN(str);
BLI_dynstr_free(ds);
}

View File

@@ -907,7 +907,8 @@ void filelist_from_library(struct FileList* filelist)
void filelist_append_library(struct FileList *filelist, char *dir, char *file, short flag, int idcode, struct Main *mainvar, struct Scene* scene)
{
BLO_library_append_(&filelist->libfiledata, filelist->filelist, filelist->numfiles, dir, file, flag, idcode, mainvar, scene);
// XXX todo: replace NULL with op->reports
BLO_library_append_(&filelist->libfiledata, filelist->filelist, filelist->numfiles, dir, file, flag, idcode, mainvar, scene, NULL);
}
void filelist_from_main(struct FileList *filelist)

View File

@@ -447,6 +447,23 @@ typedef struct SpaceImaSel {
#define CONTEXT_SCRIPT 5
#define CONTEXT_LOGIC 6
/* sbuts->mainb old */
#define BUTS_VIEW 0
#define BUTS_LAMP 1
#define BUTS_MAT 2
#define BUTS_TEX 3
#define BUTS_ANIM 4
#define BUTS_WORLD 5
#define BUTS_RENDER 6
#define BUTS_EDIT 7
#define BUTS_GAME 8
#define BUTS_FPAINT 9
#define BUTS_RADIO 10
#define BUTS_SCRIPT 11
#define BUTS_SOUND 12
#define BUTS_CONSTRAINT 13
#define BUTS_EFFECTS 14
/* sbuts->tab new */
#define TAB_SHADING_MAT 0
#define TAB_SHADING_TEX 1
@@ -471,6 +488,19 @@ typedef struct SpaceImaSel {
#define BUT_HORIZONTAL 1
#define BUT_VERTICAL 2
/* sbuts->scaflag */
#define BUTS_SENS_SEL 1
#define BUTS_SENS_ACT 2
#define BUTS_SENS_LINK 4
#define BUTS_CONT_SEL 8
#define BUTS_CONT_ACT 16
#define BUTS_CONT_LINK 32
#define BUTS_ACT_SEL 64
#define BUTS_ACT_ACT 128
#define BUTS_ACT_LINK 256
#define BUTS_SENS_STATE 512
#define BUTS_ACT_STATE 1024
/* these values need to be hardcoded in structs, dna does not recognize defines */
/* also defined in BKE */
#define FILE_MAXDIR 160

View File

@@ -50,6 +50,7 @@ struct wmSubWindow;
struct wmTimer;
struct StructRNA;
struct PointerRNA;
struct ReportList;
/* windowmanager is saved, tag WMAN */
typedef struct wmWindowManager {
@@ -188,6 +189,7 @@ typedef struct wmOperator {
wmOperatorType *type; /* operator type definition from idname */
void *customdata; /* custom storage, only while operator runs */
struct PointerRNA *ptr; /* rna pointer to access properties */
struct ReportList *reports; /* errors and warnings storage */
} wmOperator;
/* operator type exec(), invoke() modal(), return values */

View File

@@ -50,8 +50,8 @@ wmWindow *WM_window_open (struct bContext *C, struct rcti *rect);
/* files */
int WM_read_homefile (struct bContext *C, int from_memory);
int WM_write_homefile (struct bContext *C, struct wmOperator *op);
void WM_read_file (struct bContext *C, char *name);
void WM_write_file (struct bContext *C, char *target);
void WM_read_file (struct bContext *C, char *name, struct ReportList *reports);
void WM_write_file (struct bContext *C, char *target, struct ReportList *reports);
void WM_read_autosavefile(struct bContext *C);
void WM_write_autosave (struct bContext *C);
@@ -112,9 +112,6 @@ int WM_operator_confirm (struct bContext *C, struct wmOperator *op, struct wm
/* poll callback, context checks */
int WM_operator_winactive (struct bContext *C);
/* default error box */
void WM_error(struct bContext *C, char *str);
/* operator api */
void WM_operator_free (struct wmOperator *op);
wmOperatorType *WM_operatortype_find(const char *idname);

View File

@@ -34,9 +34,10 @@
#include "BKE_blender.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_idprop.h"
#include "BKE_report.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -65,6 +66,11 @@ void WM_operator_free(wmOperator *op)
if(op->ptr)
MEM_freeN(op->ptr);
if(op->reports) {
BKE_reports_clear(op->reports);
MEM_freeN(op->reports);
}
MEM_freeN(op);
}

View File

@@ -44,6 +44,7 @@
#include "BKE_context.h"
#include "BKE_idprop.h"
#include "BKE_global.h"
#include "BKE_report.h"
#include "BKE_utildefines.h"
#include "ED_screen.h"
@@ -52,6 +53,8 @@
#include "RNA_access.h"
#include "UI_interface.h"
#include "WM_api.h"
#include "WM_types.h"
#include "wm.h"
@@ -337,6 +340,10 @@ int WM_operator_call(bContext *C, wmOperator *op)
if(op->type->exec)
retval= op->type->exec(C, op);
if(!(retval & OPERATOR_RUNNING_MODAL))
if(op->reports->list.first)
uiPupmenuReports(C, op->reports);
if((retval & OPERATOR_FINISHED) && (op->type->flag & OPTYPE_REGISTER)) {
wm_operator_register(CTX_wm_manager(C), op);
}
@@ -364,6 +371,9 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, I
op->ptr= MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA");
RNA_pointer_create(&RNA_WindowManager, &wm->id, ot->srna, &op->properties, op->ptr);
op->reports= MEM_callocN(sizeof(ReportList), "wmOperatorReportList");
BKE_reports_init(op->reports, RPT_STORE);
if(op->type->invoke && event)
retval= (*op->type->invoke)(C, op, event);
else if(op->type->exec)
@@ -374,6 +384,10 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, I
if(G.f & G_DEBUG)
WM_operator_print(op);
if(!(retval & OPERATOR_RUNNING_MODAL))
if(op->reports->list.first)
uiPupmenuReports(C, op->reports);
if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
wm_operator_register(wm, op);
}
@@ -589,6 +603,10 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
CTX_wm_region_set(C, NULL);
}
if(!(retval & OPERATOR_RUNNING_MODAL))
if(op->reports->list.first)
uiPupmenuReports(C, op->reports);
if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
wm_operator_register(CTX_wm_manager(C), op);
handler->op= NULL;

View File

@@ -481,7 +481,7 @@ static void verse_unsub(void)
}
#endif
void WM_read_file(bContext *C, char *name)
void WM_read_file(bContext *C, char *name, ReportList *reports)
{
int retval;
@@ -501,7 +501,7 @@ void WM_read_file(bContext *C, char *name)
/* put aside screens to match with persistant windows later */
wm_window_match_init(C, &wmbase);
retval= BKE_read_file(C, name, NULL);
retval= BKE_read_file(C, name, NULL, reports);
/* match the read WM with current WM */
wm_window_match_do(C, &wmbase);
@@ -524,8 +524,10 @@ void WM_read_file(bContext *C, char *name)
}
// else if(retval==1)
// XXX BIF_undo_push("Import file");
else if(retval == -1)
WM_error(C, "Cannot read file");
else if(retval == -1) {
if(reports && reports->list.first == NULL)
BKE_report(reports, RPT_ERROR, "Cannot read file.");
}
}
static void outliner_242_patch(void)
@@ -573,9 +575,9 @@ int WM_read_homefile(bContext *C, int from_memory)
wm_window_match_init(C, &wmbase);
if (!from_memory && BLI_exists(tstr)) {
success = BKE_read_file(C, tstr, NULL);
success = BKE_read_file(C, tstr, NULL, NULL);
} else {
success = BKE_read_file_from_memory(C, datatoc_B_blend, datatoc_B_blend_size, NULL);
success = BKE_read_file_from_memory(C, datatoc_B_blend, datatoc_B_blend_size, NULL, NULL);
/* outliner patch for 2.42 .b.blend */
outliner_242_patch();
}
@@ -643,7 +645,7 @@ void WM_read_autosavefile(bContext *C)
get_autosave_location(tstr);
save_over = G.save_over;
BKE_read_file(C, tstr, NULL);
BKE_read_file(C, tstr, NULL, NULL);
G.save_over = save_over;
BLI_strncpy(G.sce, scestr, FILE_MAX);
}
@@ -781,7 +783,7 @@ static void writeBlog(void)
}
}
static void do_history(char *name)
static void do_history(char *name, ReportList *reports)
{
char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
int hisnr= U.versions;
@@ -789,12 +791,12 @@ static void do_history(char *name)
if(U.versions==0) return;
if(strlen(name)<2) return;
while( hisnr > 1) {
while(hisnr > 1) {
sprintf(tempname1, "%s%d", name, hisnr-1);
sprintf(tempname2, "%s%d", name, hisnr);
// if(BLI_rename(tempname1, tempname2))
// XXX error("Unable to make version backup");
if(BLI_rename(tempname1, tempname2))
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
hisnr--;
}
@@ -802,22 +804,21 @@ static void do_history(char *name)
/* is needed when hisnr==1 */
sprintf(tempname1, "%s%d", name, hisnr);
// if(BLI_rename(name, tempname1))
// XXX error("Unable to make version backup");
if(BLI_rename(name, tempname1))
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
}
void WM_write_file(bContext *C, char *target)
void WM_write_file(bContext *C, char *target, ReportList *reports)
{
Library *li;
int writeflags, len;
char di[FILE_MAX];
ReportList reports;
len = strlen(target);
if (len == 0) return;
if (len >= FILE_MAX) {
// XXX error("Path too long, cannot save");
BKE_report(reports, RPT_ERROR, "Path too long, cannot save");
return;
}
@@ -826,7 +827,7 @@ void WM_write_file(bContext *C, char *target)
for (li= G.main->library.first; li; li= li->id.next) {
if (BLI_streq(li->name, target)) {
// XXX error("Cannot overwrite used library");
BKE_report(reports, RPT_ERROR, "Cannot overwrite used library");
return;
}
}
@@ -851,16 +852,14 @@ void WM_write_file(bContext *C, char *target)
// XXX waitcursor(1); // exit_editmode sets cursor too
do_history(di);
do_history(di, reports);
/* we use the UserDef to define compression flag */
writeflags= G.fileflags & ~G_FILE_COMPRESS;
if(U.flag & USER_FILECOMPRESS)
writeflags |= G_FILE_COMPRESS;
BKE_reports_init(&reports, RPT_STORE);
if (BLO_write_file(CTX_data_main(C), di, writeflags, &reports)) {
if (BLO_write_file(CTX_data_main(C), di, writeflags, reports)) {
strcpy(G.sce, di);
G.relbase_valid = 1;
strcpy(G.main->name, di); /* is guaranteed current file */
@@ -870,38 +869,29 @@ void WM_write_file(bContext *C, char *target)
G.save_over = 1;
writeBlog();
} else {
// XXX error("%s", err);
}
BKE_reports_clear(&reports);
// XXX waitcursor(0);
}
/* operator entry */
int WM_write_homefile(bContext *C, wmOperator *op)
{
ReportList reports;
char tstr[FILE_MAXDIR+FILE_MAXFILE];
int write_flags;
BLI_make_file_string("/", tstr, BLI_gethome(), ".B.blend");
BLI_make_file_string("/", tstr, "/", ".B.blend");
/* force save as regular blend file */
write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
// XXX error reporting to the user
BKE_reports_init(&reports, RPT_PRINT);
BLO_write_file(CTX_data_main(C), tstr, write_flags, &reports);
BKE_reports_clear(&reports);
BLO_write_file(CTX_data_main(C), tstr, write_flags, op->reports);
return OPERATOR_FINISHED;
}
void WM_write_autosave(bContext *C)
{
ReportList reports;
char tstr[FILE_MAXDIR+FILE_MAXFILE];
int write_flags;
@@ -910,9 +900,8 @@ void WM_write_autosave(bContext *C)
/* force save as regular blend file */
write_flags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_LOCK | G_FILE_SIGN);
BKE_reports_init(&reports, RPT_PRINT);
BLO_write_file(CTX_data_main(C), tstr, write_flags, &reports);
BKE_reports_clear(&reports);
/* error reporting to console */
BLO_write_file(CTX_data_main(C), tstr, write_flags, NULL);
}
/* if global undo; remove tempsave, otherwise rename */
@@ -933,7 +922,3 @@ void delete_autosave(void)
/***/

View File

@@ -195,17 +195,6 @@ int WM_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_CANCELLED;
}
/* call anywhere */
void WM_error(bContext *C, char *str)
{
char buf[148], testbuf[128];
BLI_strncpy(testbuf, str, 128);
sprintf(buf, "Error %%i%d%%t|%s", ICON_ERROR, testbuf);
uiPupmenu(C, 0, NULL, NULL, buf);
}
/* op->invoke */
int WM_operator_confirm(bContext *C, wmOperator *op, wmEvent *event)
{
@@ -276,11 +265,11 @@ static int recentfile_exec(bContext *C, wmOperator *op)
if(event>0) {
if (G.sce[0] && (event==1))
WM_read_file(C, G.sce);
WM_read_file(C, G.sce, op->reports);
else {
struct RecentFile *recent = BLI_findlink(&(G.recent_files), event-2);
if(recent) {
WM_read_file(C, recent->filename);
WM_read_file(C, recent->filename, op->reports);
}
}
}

View File

@@ -61,6 +61,7 @@
#include "BKE_packedFile.h"
#include "BKE_scene.h"
#include "BKE_node.h"
#include "BKE_report.h"
#include "IMB_imbuf.h" // for quicktime_init
@@ -71,9 +72,8 @@
#include "RE_pipeline.h"
//XXX #include "playanim_ext.h"
#include "wm_event_types.h"
#include "ED_datafiles.h"
//XXX #include "datatoc.h"
#include "UI_interface.h"
#include "WM_api.h"
@@ -784,7 +784,7 @@ int main(int argc, char **argv)
BLI_convertstringcwd(filename);
if (G.background) {
int retval = BKE_read_file(C, argv[a], NULL);
int retval = BKE_read_file(C, argv[a], NULL, NULL);
// XXX sound_initialize_sounds();
/*we successfully loaded a blend file, get sure that
@@ -797,7 +797,7 @@ int main(int argc, char **argv)
} else {
/* we are not running in background mode here, but start blender in UI mode with
a file - this should do everything a 'load file' does */
WM_read_file(C, filename);
WM_read_file(C, filename, NULL);
}
}
}
@@ -827,7 +827,7 @@ static void error_cb(char *err)
static void mem_error_cb(char *errorStr)
{
fprintf(stderr, errorStr);
fprintf(stderr, "%s", errorStr);
fflush(stderr);
}