diff --git a/source/lib/lib.h b/source/lib/lib.h index 757db5de38..d75c15f7e8 100755 --- a/source/lib/lib.h +++ b/source/lib/lib.h @@ -96,52 +96,56 @@ STMT(\ ) -// note: UINT_MAX is necessary when testing a Handle value and -// also returning Handle. the negative value (error return) -// is guaranteed to fit into an int, but we need to "mask" -// it to avoid VC cast-to-smaller-type warnings. +// be careful here. the given expression (e.g. variable or +// function return value) may be a Handle (=i64), so it needs to be +// stored and compared as such. (very large but legitimate Handle values +// casted to int can end up negative) +// all functions using this return int (instead of i64) for efficiency and +// simplicity. if the input was negative, it is an error code and is +// therefore known to fit; we still mask with UINT_MAX to avoid +// VC cast-to-smaller-type warnings. #ifdef _WIN32 -#define CHECK_ERR(func)\ +#define CHECK_ERR(expression)\ STMT(\ - int err__ = (int)((func) & UINT_MAX);\ + i64 err__ = (i64)(expression);\ if(err__ < 0)\ {\ - debug_assert(0 && "FYI: CHECK_ERR reports that a function failed."\ - "feel free to ignore or suppress this warning.");\ - return err__;\ + debug_warn("FYI: CHECK_ERR reports that a function failed."\ + "feel free to ignore or suppress this warning.");\ + return (int)(err__ & UINT_MAX);\ }\ ) #else -#define CHECK_ERR(func)\ +#define CHECK_ERR(expression)\ STMT(\ - int err__ = (int)((func) & UINT_MAX);\ + i64 err__ = (i64)(expression);\ if(err__ < 0)\ {\ debug_printf("%s:%d: FYI: CHECK_ERR reports that a function failed."\ "feel free to ignore or suppress this warning.\n", __FILE__, __LINE__);\ - return err__;\ + return (int)(err__ & UINT_MAX);\ }\ ) #endif // just pass on errors without any kind of annoying warning // (useful for functions that can legitimately fail, e.g. vfs_exists). -#define RETURN_ERR(func)\ +#define RETURN_ERR(expression)\ STMT(\ - int err__ = (int)((func) & UINT_MAX);\ + i64 err__ = (i64)(expression);\ if(err__ < 0)\ - return err__;\ + return (int)(err__ & UINT_MAX);\ ) -#define THROW_ERR(func)\ +#define THROW_ERR(expression)\ STMT(\ - int err__ = (int)((func) & UINT_MAX);\ + i64 err__ = (i64)(expression);\ if(err__ < 0)\ {\ - debug_assert(0 && "FYI: CHECK_ERR reports that a function failed."\ - "feel free to ignore or suppress this warning.");\ - throw err__;\ + debug_warn("FYI: CHECK_ERR reports that a function failed."\ + "feel free to ignore or suppress this warning.");\ + throw (int)(err__ & UINT_MAX);\ }\ ) diff --git a/source/lib/res/cursor.cpp b/source/lib/res/cursor.cpp index ecf92c09c8..47f323d129 100755 --- a/source/lib/res/cursor.cpp +++ b/source/lib/res/cursor.cpp @@ -107,7 +107,7 @@ static int Cursor_reload(Cursor* c, const char* name, Handle) void* p; size_t size; Handle hm = vfs_load(filename, p, size); - CHECK_ERR(hm); + RETURN_ERR(hm); std::stringstream s(std::string((const char*)p, size)); s >> hotspotx >> hotspoty; diff --git a/source/lib/res/h_mgr.h b/source/lib/res/h_mgr.h index 9677729eef..501fd29b9f 100755 --- a/source/lib/res/h_mgr.h +++ b/source/lib/res/h_mgr.h @@ -135,7 +135,10 @@ typedef H_VTbl* H_Type; /* don't use STMT - var decl must be visible to "caller" */\ type* const var = H_USER_DATA(h, type);\ if(!var)\ - return ERR_INVALID_HANDLE; + {\ + debug_warn("H_DEREF failed");\ + return ERR_INVALID_HANDLE;\ + } // all functions check the passed tag (part of the handle) and type against diff --git a/source/lib/res/snd.cpp b/source/lib/res/snd.cpp index 2e8f9c3fe5..4a0f39e1df 100755 --- a/source/lib/res/snd.cpp +++ b/source/lib/res/snd.cpp @@ -986,7 +986,7 @@ static int SndData_reload(SndData* sd, const char* fn, Handle hsd) void* file; size_t file_size; - CHECK_ERR(vfs_load(fn, file, file_size)); + RETURN_ERR(vfs_load(fn, file, file_size)); ALvoid* al_data = file; ALsizei al_size = (ALsizei)file_size; @@ -1473,7 +1473,7 @@ static int VSrc_reload(VSrc* vs, const char* fn, Handle hvs) { void* def_file; size_t def_size; - CHECK_ERR(vfs_load(fn, def_file, def_size)); + RETURN_ERR(vfs_load(fn, def_file, def_size)); std::istringstream def(std::string((char*)def_file, (int)def_size)); mem_free(def_file); diff --git a/source/lib/res/tex.cpp b/source/lib/res/tex.cpp index 8906e8ee28..84e5e6a95e 100755 --- a/source/lib/res/tex.cpp +++ b/source/lib/res/tex.cpp @@ -1709,7 +1709,7 @@ int tex_load(const char* fn, TexInfo* t) // load file void* p; size_t size; // unused Handle hm = vfs_load(fn, p, size); - CHECK_ERR(hm); // (need handle below; can't test return value directly) + RETURN_ERR(hm); // (need handle below; can't test return value directly) int ret = tex_load_mem(hm, fn, t); mem_free_h(hm); if(ret < 0) diff --git a/source/lib/res/unifont.cpp b/source/lib/res/unifont.cpp index a40753c069..5e54ee4bf6 100755 --- a/source/lib/res/unifont.cpp +++ b/source/lib/res/unifont.cpp @@ -80,7 +80,7 @@ static int UniFont_reload(UniFont* f, const char* fn, Handle UNUSEDPARAM(h)) // // return ERR_FILE_NOT_FOUND; Handle hm = vfs_load(fnt_fn, RawFNT, FNTSize); - CHECK_ERR(hm); + RETURN_ERR(hm); // Get the data in a nicer object std::istringstream FNTStream (std::string((const char*)RawFNT, (int)FNTSize)); diff --git a/source/lib/res/vfs.cpp b/source/lib/res/vfs.cpp index aff4b07933..185d367455 100755 --- a/source/lib/res/vfs.cpp +++ b/source/lib/res/vfs.cpp @@ -1036,6 +1036,8 @@ ssize_t vfs_size(Handle hf) // open the file for synchronous or asynchronous IO. write access is // requested via FILE_WRITE flag, and is not possible for files in archives. // file_flags: default 0 +// +// on failure, a debug_warn is generated and a negative error code returned. Handle vfs_open(const char* v_fn, uint file_flags) { // keeping files open doesn't make sense in most cases (because the @@ -1044,25 +1046,26 @@ Handle vfs_open(const char* v_fn, uint file_flags) if(file_flags & FILE_CACHE) res_flags = 0; - Handle h = h_alloc(H_VFile, v_fn, res_flags, file_flags); + Handle hf = h_alloc(H_VFile, v_fn, res_flags, file_flags); // pass file flags to init #ifdef PARANOIA -debug_printf("vfs_open fn=%s %llx\n", v_fn, h); +debug_printf("vfs_open fn=%s %llx\n", v_fn, hf); #endif - return h; + CHECK_ERR(hf); + return hf; } // close the handle to a file. -int vfs_close(Handle& h) +int vfs_close(Handle& hf) { #ifdef PARANOIA -debug_printf("vfs_close %llx\n", h); +debug_printf("vfs_close %llx\n", hf); #endif - return h_free(h, H_VFile); + return h_free(hf, H_VFile); } @@ -1152,6 +1155,8 @@ static ssize_t vfs_timed_io(const Handle hf, const size_t size, void** p, FileIO // in addition to the regular file cache, the entire buffer is kept in memory // if flags & FILE_CACHE. // +// on failure, a debug_warn is generated and a negative error code returned. +// // note: we need the Handle return value for Tex.hm - the data pointer // must be protected against being accidentally free-d in that case. Handle vfs_load(const char* v_fn, void*& p, size_t& size, uint flags /* default 0 */) @@ -1163,9 +1168,10 @@ debug_printf("vfs_load v_fn=%s\n", v_fn); p = 0; size = 0; // zeroed in case vfs_open or H_DEREF fails Handle hf = vfs_open(v_fn, flags); - CHECK_ERR(hf); - // note: if we skip this and have H_DEREF report the error, - // we get "invalid handle" instead of vfs_open's error code. + RETURN_ERR(hf); + // necessary because if we skip this and have H_DEREF report the + // error, we get "invalid handle" instead of vfs_open's error code. + // don't CHECK_ERR because vfs_open already did. H_DEREF(hf, VFile, vf); @@ -1223,9 +1229,7 @@ ret: if(hm <= 0) p = 0, size = 0; - if (hm == 0) - debug_printf("hm == 0!!\n"); - + CHECK_ERR(hm); return hm; } @@ -1236,8 +1240,10 @@ ret: int vfs_store(const char* v_fn, void* p, const size_t size, uint flags /* default 0 */) { Handle hf = vfs_open(v_fn, flags|FILE_WRITE); - if(hf <= 0) - return (int)hf; // error code + RETURN_ERR(hf); + // necessary because if we skip this and have H_DEREF report the + // error, we get "invalid handle" instead of vfs_open's error code. + // don't CHECK_ERR because vfs_open already did. H_DEREF(hf, VFile, vf); const int ret = vfs_io(hf, size, &p); vfs_close(hf);