diff --git a/source/lib/allocators.cpp b/source/lib/allocators.cpp index 96107f0986..015bcf9379 100644 --- a/source/lib/allocators.cpp +++ b/source/lib/allocators.cpp @@ -25,6 +25,7 @@ #include "lib/posix.h" // PROT_* constants for da_set_prot #include "lib/sysdep/cpu.h" // CAS #include "byte_order.h" +#include "lib/res/file/file_io.h" // IO_EOF #include "allocators.h" @@ -58,7 +59,7 @@ static inline size_t round_up_to_page(size_t size) static inline LibError LibError_from_mmap(void* ret, bool warn_if_failed = true) { if(ret != MAP_FAILED) - return INFO_OK; + return INFO::OK; return LibError_from_errno(warn_if_failed); } @@ -91,7 +92,7 @@ static LibError mem_commit(u8* p, size_t size, int prot) { if(prot == PROT_NONE) // not allowed - it would be misinterpreted by mmap. - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); errno = 0; void* ret = mmap(p, size, prot, mmap_flags|MAP_FIXED, -1, 0); @@ -162,7 +163,7 @@ const int DA_NOT_OUR_MEM = 0x40000000; static LibError validate_da(DynArray* da) { if(!da) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); u8* const base = da->base; const size_t max_size_pa = da->max_size_pa; const size_t cur_size = da->cur_size; @@ -170,21 +171,21 @@ static LibError validate_da(DynArray* da) const int prot = da->prot; if(debug_is_pointer_bogus(base)) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); // note: don't check if base is page-aligned - // might not be true for 'wrapped' mem regions. // if(!is_page_multiple((uintptr_t)base)) -// WARN_RETURN(ERR_2); +// WARN_RETURN(ERR::_2); if(!is_page_multiple(max_size_pa)) - WARN_RETURN(ERR_3); + WARN_RETURN(ERR::_3); if(cur_size > max_size_pa) - WARN_RETURN(ERR_4); + WARN_RETURN(ERR::_4); if(pos > cur_size || pos > max_size_pa) - WARN_RETURN(ERR_5); + WARN_RETURN(ERR::_5); if(prot & ~(PROT_READ|PROT_WRITE|PROT_EXEC|DA_NOT_OUR_MEM)) - WARN_RETURN(ERR_6); + WARN_RETURN(ERR::_6); - return INFO_OK; + return INFO::OK; } #define CHECK_DA(da) RETURN_ERR(validate_da(da)) @@ -213,7 +214,7 @@ LibError da_alloc(DynArray* da, size_t max_size) da->prot = PROT_READ|PROT_WRITE; da->pos = 0; CHECK_DA(da); - return INFO_OK; + return INFO::OK; } @@ -238,7 +239,7 @@ LibError da_wrap_fixed(DynArray* da, u8* p, size_t size) da->prot = PROT_READ|PROT_WRITE|DA_NOT_OUR_MEM; da->pos = 0; CHECK_DA(da); - return INFO_OK; + return INFO::OK; } @@ -267,7 +268,7 @@ LibError da_free(DynArray* da) // da_free is supposed to be called even in the above case. if(!was_wrapped) RETURN_ERR(mem_release(p, size)); - return INFO_OK; + return INFO::OK; } @@ -285,7 +286,7 @@ LibError da_set_size(DynArray* da, size_t new_size) CHECK_DA(da); if(da->prot & DA_NOT_OUR_MEM) - WARN_RETURN(ERR_LOGIC); + WARN_RETURN(ERR::LOGIC); // determine how much to add/remove const size_t cur_size_pa = round_up_to_page(da->cur_size); @@ -296,7 +297,7 @@ LibError da_set_size(DynArray* da, size_t new_size) // note: do not complain - some allocators (e.g. file_cache) // egitimately use up all available space. if(new_size_pa > da->max_size_pa) - return ERR_LIMIT; // NOWARN + return ERR::LIMIT; // NOWARN u8* end = da->base + cur_size_pa; // expanding @@ -310,7 +311,7 @@ LibError da_set_size(DynArray* da, size_t new_size) da->cur_size = new_size; CHECK_DA(da); - return INFO_OK; + return INFO::OK; } @@ -330,7 +331,7 @@ LibError da_reserve(DynArray* da, size_t size) if(da->pos + size > da->cur_size) return da_set_size(da, da->cur_size + expand_amount); - return INFO_OK; + return INFO::OK; } @@ -350,13 +351,13 @@ LibError da_set_prot(DynArray* da, int prot) // somewhat more subtle: POSIX mprotect requires the memory have been // mmap-ed, which it probably wasn't here. if(da->prot & DA_NOT_OUR_MEM) - WARN_RETURN(ERR_LOGIC); + WARN_RETURN(ERR::LOGIC); da->prot = prot; RETURN_ERR(mem_protect(da->base, da->cur_size, prot)); CHECK_DA(da); - return INFO_OK; + return INFO::OK; } @@ -373,11 +374,11 @@ LibError da_read(DynArray* da, void* data, size_t size) { // make sure we have enough data to read if(da->pos+size > da->cur_size) - WARN_RETURN(ERR_EOF); + WARN_RETURN(ERR::IO_EOF); memcpy2(data, da->base+da->pos, size); da->pos += size; - return INFO_OK; + return INFO::OK; } @@ -395,7 +396,7 @@ LibError da_append(DynArray* da, const void* data, size_t size) RETURN_ERR(da_reserve(da, size)); memcpy2(da->base+da->pos, data, size); da->pos += size; - return INFO_OK; + return INFO::OK; } @@ -456,7 +457,7 @@ LibError pool_create(Pool* p, size_t max_size, size_t el_size) p->el_size = round_up(el_size, ALIGN); p->freelist = 0; RETURN_ERR(da_alloc(&p->da, max_size)); - return INFO_OK; + return INFO::OK; } @@ -623,13 +624,13 @@ LibError bucket_create(Bucket* b, size_t el_size) // cause next bucket_alloc to retry the allocation b->pos = BUCKET_SIZE; b->num_buckets = 0; - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); } *(u8**)b->bucket = 0; // terminate list b->pos = round_up(sizeof(u8*), ALIGN); b->num_buckets = 1; - return INFO_OK; + return INFO::OK; } @@ -829,7 +830,7 @@ void* single_calloc(void* storage, volatile uintptr_t* in_use_flag, size_t size) p = malloc(size); if(!p) { - WARN_ERR(ERR_NO_MEM); + WARN_ERR(ERR::NO_MEM); return 0; } } diff --git a/source/lib/allocators.h b/source/lib/allocators.h index 4a1875f3f3..1360c408ec 100644 --- a/source/lib/allocators.h +++ b/source/lib/allocators.h @@ -526,7 +526,7 @@ private: if(da_alloc(&da, sizeof(T)) < 0) { fail: - WARN_ERR(ERR_NO_MEM); + WARN_ERR(ERR::NO_MEM); return; } if(da_set_size(&da, sizeof(T)) < 0) diff --git a/source/lib/debug.cpp b/source/lib/debug.cpp index a1d4b0dc95..9b98270b72 100644 --- a/source/lib/debug.cpp +++ b/source/lib/debug.cpp @@ -27,6 +27,7 @@ #include "lib.h" #include "posix.h" +#include "lib/res/file/file.h" // FILE_ACCESS #include "lib/sysdep/cpu.h" // CAS // some functions here are called from within mmgr; disable its hooks // so that our allocations don't cause infinite recursion. @@ -37,6 +38,20 @@ #include "debug.h" +AT_STARTUP(\ + error_setDescription(ERR::SYM_NO_STACK_FRAMES_FOUND, "No stack frames found");\ + error_setDescription(ERR::SYM_UNRETRIEVABLE_STATIC, "Value unretrievable (stored in external module)");\ + error_setDescription(ERR::SYM_UNRETRIEVABLE_REG, "Value unretrievable (stored in register)");\ + error_setDescription(ERR::SYM_TYPE_INFO_UNAVAILABLE, "Error getting type_info");\ + error_setDescription(ERR::SYM_INTERNAL_ERROR, "Exception raised while processing a symbol");\ + error_setDescription(ERR::SYM_UNSUPPORTED, "Symbol type not (fully) supported");\ + error_setDescription(ERR::SYM_CHILD_NOT_FOUND, "Symbol does not have the given child");\ + error_setDescription(ERR::SYM_NESTING_LIMIT, "Symbol nesting too deep or infinite recursion");\ + error_setDescription(ERR::SYM_SINGLE_SYMBOL_LIMIT, "Symbol has produced too much output");\ + error_setDescription(INFO::SYM_SUPPRESS_OUTPUT, "Symbol was suppressed");\ +) + + // needed when writing crashlog static const size_t LOG_CHARS = 16384; wchar_t debug_log[LOG_CHARS]; @@ -219,7 +234,7 @@ LibError debug_write_crashlog(const wchar_t* text) // avoid potential infinite loop if an error occurs here. static uintptr_t in_progress; if(!CAS(&in_progress, 0, 1)) - return ERR_REENTERED; // NOWARN + return ERR::REENTERED; // NOWARN // note: we go through some gyrations here (strcpy+strcat) to avoid // dependency on file code (path_append). @@ -230,7 +245,7 @@ LibError debug_write_crashlog(const wchar_t* text) if(!f) { in_progress = 0; - WARN_RETURN(ERR_FILE_ACCESS); + WARN_RETURN(ERR::FILE_ACCESS); } fputwc(0xfeff, f); // BOM @@ -244,7 +259,7 @@ LibError debug_write_crashlog(const wchar_t* text) fclose(f); in_progress = 0; - return INFO_OK; + return INFO::OK; } @@ -272,7 +287,7 @@ static const char* symbol_string_build(void* symbol, const char* name, const cha string_buf = (char*)malloc(STRING_BUF_SIZE); if(!string_buf) { - WARN_ERR(ERR_NO_MEM); + WARN_ERR(ERR::NO_MEM); return 0; } string_buf_pos = string_buf; @@ -282,7 +297,7 @@ static const char* symbol_string_build(void* symbol, const char* name, const cha char* string = string_buf_pos; if(string + STRING_MAX >= string_buf + STRING_BUF_SIZE) { - WARN_ERR(ERR_LIMIT); + WARN_ERR(ERR::LIMIT); return 0; } @@ -402,7 +417,7 @@ static void symbol_string_add_to_cache(const char* string, void* symbol) // hash table is completely full (guard against infinite loop below). // if this happens, the string won't be cached - nothing serious. if(total_symbols >= MAX_SYMBOLS) - WARN_ERR_RETURN(ERR_LIMIT); + WARN_ERR_RETURN(ERR::LIMIT); total_symbols++; // find Symbol slot in hash table @@ -539,11 +554,11 @@ const wchar_t* debug_error_message_build( char description_buf[100] = {'?'}; LibError errno_equiv = LibError_from_errno(false); - if(errno_equiv != ERR_FAIL) // meaningful translation + if(errno_equiv != ERR::FAIL) // meaningful translation error_description_r(errno_equiv, description_buf, ARRAY_SIZE(description_buf)); char os_error[100]; - if(sys_error_description_r(0, os_error, ARRAY_SIZE(os_error)) != INFO_OK) + if(sys_error_description_r(0, os_error, ARRAY_SIZE(os_error)) != INFO::OK) strcpy_s(os_error, ARRAY_SIZE(os_error), "?"); static const wchar_t fmt[] = @@ -568,14 +583,14 @@ const wchar_t* debug_error_message_build( if(!context) skip += 2; // skip debug_error_message_build and debug_display_error LibError ret = debug_dump_stack(pos, chars_left, skip, context); - if(ret == ERR_REENTERED) + if(ret == ERR::REENTERED) { wcscpy_s(pos, chars_left, L"(cannot start a nested stack trace; what probably happened is that " L"an debug_assert/debug_warn/CHECK_ERR fired during the current trace.)" ); } - else if(ret != INFO_OK) + else if(ret != INFO::OK) { swprintf(pos, chars_left, L"(error while dumping stack: %hs)", @@ -719,16 +734,16 @@ static bool should_skip_this_error(LibError err) // to share code between assert and error skip mechanism, we treat the former as // an error. choose the code such that no one would want to warn of it. -static const LibError assert_err = INFO_OK; +static const LibError assert_err = INFO::OK; void debug_skip_next_assert() { - debug_skip_next_err(INFO_OK); + debug_skip_next_err(INFO::OK); } static bool should_skip_this_assert() { - return should_skip_this_error(INFO_OK); + return should_skip_this_error(INFO::OK); } diff --git a/source/lib/debug.h b/source/lib/debug.h index 2827036277..f08e908a5c 100644 --- a/source/lib/debug.h +++ b/source/lib/debug.h @@ -290,7 +290,7 @@ extern void debug_wprintf_mem(const wchar_t* fmt, ...); * @param text description of the error (including stack trace); * typically generated by debug_error_message_build. * - * @return LibError; ERR_REENTERED if reentered via recursion or + * @return LibError; ERR::REENTERED if reentered via recursion or * multithreading (not allowed since an infinite loop may result). **/ extern LibError debug_write_crashlog(const wchar_t* text); @@ -461,7 +461,7 @@ enum DbgBreakType * for simplicity, the length (range of bytes to be checked) is derived * from addr's alignment, and is typically 1 machine word. * @param type the type of access to watch for (see DbgBreakType) - * @return LibError; ERR_LIMIT if no more breakpoints are available + * @return LibError; ERR::LIMIT if no more breakpoints are available * (they are a limited resource - only 4 on IA-32). **/ extern LibError debug_set_break(void* addr, DbgBreakType type); @@ -477,6 +477,31 @@ extern LibError debug_remove_all_breaks(); // symbol access //----------------------------------------------------------------------------- +namespace ERR +{ + const LibError SYM_NO_STACK_FRAMES_FOUND = -100400; + const LibError SYM_UNRETRIEVABLE_STATIC = -100401; + const LibError SYM_UNRETRIEVABLE_REG = -100402; + const LibError SYM_TYPE_INFO_UNAVAILABLE = -100403; + const LibError SYM_INTERNAL_ERROR = -100404; + const LibError SYM_UNSUPPORTED = -100405; + const LibError SYM_CHILD_NOT_FOUND = -100406; + // this limit is to prevent infinite recursion. + const LibError SYM_NESTING_LIMIT = -100407; + // this limit is to prevent large symbols (e.g. arrays or linked lists) + // from taking up all available output space. + const LibError SYM_SINGLE_SYMBOL_LIMIT = -100408; +} + +namespace INFO +{ + // one of the dump_sym* functions decided not to output anything at + // all (e.g. for member functions in UDTs - we don't want those). + // therefore, skip any post-symbol formatting (e.g. ) as well. + const LibError SYM_SUPPRESS_OUTPUT = +100809; +} + + /** * maximum number of characters (including trailing \0) written to * user's buffers by debug_resolve_symbol. @@ -499,7 +524,7 @@ const size_t DBG_FILE_LEN = 100; * * note: all of the output parameters are optional; we pass back as much * information as is available and desired. - * @return LibError; INFO_OK iff any information was successfully + * @return LibError; INFO::OK iff any information was successfully * retrieved and stored. **/ extern LibError debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int* line); @@ -516,7 +541,7 @@ extern LibError debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char * @param context platform-specific representation of execution state * (e.g. Win32 CONTEXT). if not NULL, tracing starts there; this is useful * for exceptions. otherwise, tracing starts from the current call stack. - * @return LibError; ERR_REENTERED if reentered via recursion or + * @return LibError; ERR::REENTERED if reentered via recursion or * multithreading (not allowed since static data is used). **/ extern LibError debug_dump_stack(wchar_t* buf, size_t max_chars, uint skip, void* context); diff --git a/source/lib/debug_stl.cpp b/source/lib/debug_stl.cpp index fb7e316f08..e52168e3e6 100644 --- a/source/lib/debug_stl.cpp +++ b/source/lib/debug_stl.cpp @@ -29,6 +29,13 @@ #include "debug_stl.h" #include "lib.h" // match_wildcard + +AT_STARTUP(\ + error_setDescription(ERR::STL_CNT_UNKNOWN, "Unknown STL container type_name");\ + error_setDescription(ERR::STL_CNT_INVALID, "Container type is known but contents are invalid");\ +) + + // used in debug_stl_simplify_name. // note: strcpy is safe because replacement happens in-place and // src is longer than dst (otherwise, we wouldn't be replacing). @@ -650,7 +657,7 @@ LibError debug_stl_get_container_info(const char* type_name, const u8* p, size_t // later pieces of code that try to manipulate the STL containers. Presumably // it needs to be altered/rewritten to work happily with the new STL debug iterators. #if MSC_VERSION >= 1400 - return ERR_FAIL; + return ERR::FAIL; #endif bool handled = false, valid = false; @@ -699,10 +706,10 @@ LibError debug_stl_get_container_info(const char* type_name, const u8* p, size_t // note: do not raise warnings - these can happen for new // STL classes or if the debuggee's memory is corrupted. if(!handled) - return ERR_STL_CNT_UNKNOWN; // NOWARN + return ERR::STL_CNT_UNKNOWN; // NOWARN if(!valid) - return ERR_STL_CNT_INVALID; // NOWARN - return INFO_OK; + return ERR::STL_CNT_INVALID; // NOWARN + return INFO::OK; } #endif diff --git a/source/lib/debug_stl.h b/source/lib/debug_stl.h index b6c3301f16..f81a630330 100644 --- a/source/lib/debug_stl.h +++ b/source/lib/debug_stl.h @@ -23,6 +23,15 @@ #ifndef DEBUG_STL_H_INCLUDED #define DEBUG_STL_H_INCLUDED + +namespace ERR +{ + const LibError STL_CNT_UNKNOWN = -100500; + // likely causes: not yet initialized or memory corruption. + const LibError STL_CNT_INVALID = -100501; +} + + /** * reduce complicated STL symbol names to human-readable form. * @@ -64,7 +73,7 @@ const size_t DEBUG_STL_MAX_ITERATOR_SIZE = 64; * @param el_iterator out; callback function that acts as an iterator * @param it_mem out; buffer holding the iterator state. must be * at least DEBUG_STL_MAX_ITERATOR_SIZE bytes. - * @return LibError (ERR_STL_*) + * @return LibError (ERR::STL_*) **/ extern LibError debug_stl_get_container_info(const char* type_name, const u8* p, size_t size, size_t el_size, size_t* el_count, DebugIterator* el_iterator, void* it_mem); diff --git a/source/lib/input.cpp b/source/lib/input.cpp index b49172f261..19e2feb9d6 100644 --- a/source/lib/input.cpp +++ b/source/lib/input.cpp @@ -29,6 +29,7 @@ #include "lib.h" #include "input.h" #include "sdl.h" +#include "lib/res/file/file.h" const uint MAX_HANDLERS = 8; static InHandler handler_stack[MAX_HANDLERS]; @@ -39,7 +40,7 @@ void in_add_handler(InHandler handler) debug_assert(handler); if(handler_stack_top >= MAX_HANDLERS) - WARN_ERR_RETURN(ERR_LIMIT); + WARN_ERR_RETURN(ERR::LIMIT); handler_stack[handler_stack_top++] = handler; } @@ -105,13 +106,13 @@ LibError in_record(const char* fn) f = fopen(fn, "wb"); if(!f) - WARN_RETURN(ERR_FILE_ACCESS); + WARN_RETURN(ERR::FILE_ACCESS); fwrite(&game_ticks, sizeof(u32), 1, f); state = RECORD; - return INFO_OK; + return INFO::OK; } @@ -124,7 +125,7 @@ LibError in_playback(const char* fn) f = fopen(fn, "rb"); if(!f) - WARN_RETURN(ERR_TNODE_NOT_FOUND); + WARN_RETURN(ERR::FILE_ACCESS); u32 rec_start_time; fread(&rec_start_time, sizeof(u32), 1, f); @@ -135,7 +136,7 @@ LibError in_playback(const char* fn) state = PLAYBACK; - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/input.h b/source/lib/input.h index 49f6d35e62..57157faf6e 100644 --- a/source/lib/input.h +++ b/source/lib/input.h @@ -27,11 +27,6 @@ #include "lib/sdl_fwd.h" -#ifdef __cplusplus -extern "C" { -#endif - - // input handler return values. enum InReaction { @@ -60,9 +55,4 @@ extern LibError in_record(const char* fn); extern LibError in_playback(const char* fn); extern void in_stop(void); - -#ifdef __cplusplus -} -#endif - #endif // #ifndef INPUT_H__ diff --git a/source/lib/lib.cpp b/source/lib/lib.cpp index 05706d2ff4..7783a842c2 100644 --- a/source/lib/lib.cpp +++ b/source/lib/lib.cpp @@ -194,7 +194,7 @@ uint rand(uint min_inclusive, uint max_exclusive) // huge interval or min >= max if(range == 0 || range > XRAND_MAX) { - WARN_ERR(ERR_INVALID_PARAM); + WARN_ERR(ERR::INVALID_PARAM); return 0; } diff --git a/source/lib/lib.h b/source/lib/lib.h index 69a666580f..675f40849e 100644 --- a/source/lib/lib.h +++ b/source/lib/lib.h @@ -74,6 +74,16 @@ const size_t KiB = 1ul << 10; const size_t MiB = 1ul << 20; const size_t GiB = 1ul << 30; +// generate a symbol containing the line number of the macro invocation. +// used to give a unique name (per file) to types made by cassert. +// we can't prepend __FILE__ to make it globally unique - the filename +// may be enclosed in quotes. PASTE3_HIDDEN__ is needed to make sure +// __LINE__ is expanded correctly. +#define PASTE3_HIDDEN__(a, b, c) a ## b ## c +#define PASTE3__(a, b, c) PASTE3_HIDDEN__(a, b, c) +#define UID__ PASTE3__(LINE_, __LINE__, _) +#define UID2__ PASTE3__(LINE_, __LINE__, _2) + //----------------------------------------------------------------------------- // code-generating macros @@ -131,6 +141,20 @@ STMT(\ ) +/** + * execute the code passed as a parameter before main is entered. + * + * WARNING: if the source file containing this is not directly referenced + * from anywhere, linkers may discard that object file (unless linking + * statically). see http://www.cbloom.com/3d/techdocs/more_coding.txt + **/ +#define AT_STARTUP(code__)\ + static struct UID__\ + {\ + UID__() { code__; }\ + } UID2__;\ + + /** * C++ new wrapper: allocates an instance of the given type and stores a * pointer to it. sets pointer to 0 on allocation failure. @@ -284,15 +308,6 @@ switch(x % 2) //----------------------------------------------------------------------------- // cassert -// generate a symbol containing the line number of the macro invocation. -// used to give a unique name (per file) to types made by cassert. -// we can't prepend __FILE__ to make it globally unique - the filename -// may be enclosed in quotes. need the 2 macro expansions to make sure -// __LINE__ is expanded correctly. -#define MAKE_UID2__(l) LINE_ ## l -#define MAKE_UID1__(l) MAKE_UID2__(l) -#define UID__ MAKE_UID1__(__LINE__) - /** * compile-time debug_assert. causes a compile error if the expression * evaluates to zero/false. diff --git a/source/lib/lib_errors.cpp b/source/lib/lib_errors.cpp index de7ffc2467..b5d797f69c 100644 --- a/source/lib/lib_errors.cpp +++ b/source/lib/lib_errors.cpp @@ -34,20 +34,44 @@ #include // abs #include -static const char* LibError_description(LibError err) -{ - // not in our range - const int ierr = abs((int)err); - if(!(ERR_MIN <= ierr && ierr < ERR_MAX)) - return 0; - switch(err) +struct LibErrorAssociation +{ + const char* description_; + int errno_equivalent_; + LibErrorAssociation() + : description_(0), errno_equivalent_(-1) {} + + void setDescription(const char* description) { -#define ERR(err, id, str) case id: return str; -#include "lib_errors.h" - default: return "Unknown error"; + debug_assert(description_ == 0); // not already set + description_ = description; } - UNREACHABLE; + + void setEquivalent(int errno_equivalent) + { + debug_assert(errno_equivalent_ == -1); // not already set + errno_equivalent_ = errno_equivalent; + } +}; +typedef std::map LibErrorAssociations; + +// wrapper required because error_set* is called from AT_STARTUP +// (potentially before our static map is constructed) +static LibErrorAssociations& associations() +{ + static LibErrorAssociations associations_; + return associations_; +}; + +void error_setDescription(LibError err, const char* description) +{ + associations()[err].setDescription(description); +} + +void error_setEquivalent(LibError err, int errno_equivalent) +{ + associations()[err].setEquivalent(errno_equivalent); } @@ -58,47 +82,44 @@ static const char* LibError_description(LibError err) char* error_description_r(LibError err, char* buf, size_t max_chars) { // lib error - const char* str = LibError_description(err); - if(str) + LibErrorAssociations::iterator it = associations().find(err); + if(it != associations().end()) { - // was one of our error codes (chosen so as not to conflict - // with any others), so we're done. - strcpy_s(buf, max_chars, str); - } - // unknown - else - { - snprintf(buf, max_chars, "Unknown error (%d, 0x%X)", err, err); + const LibErrorAssociation& a = it->second; + if(a.description_) + { + strcpy_s(buf, max_chars, a.description_); + return buf; + } } + // unknown + snprintf(buf, max_chars, "Unknown error (%d, 0x%X)", err, err); return buf; } -// return the LibError equivalent of errno, or ERR_FAIL if there's no equal. +// return the LibError equivalent of errno, or ERR::FAIL if there's no equal. // only call after a POSIX function indicates failure. // raises a warning (avoids having to on each call site). LibError LibError_from_errno(bool warn_if_failed) { - LibError err; - switch(errno) + LibError ret = ERR::FAIL; + + LibErrorAssociations::iterator it; + for(it = associations().begin(); it != associations().end(); ++it) { - case ENOMEM: err = ERR_NO_MEM; break; - - case EINVAL: err = ERR_INVALID_PARAM; break; - case ENOSYS: err = ERR_NOT_IMPLEMENTED; break; - - case ENOENT: err = ERR_TNODE_NOT_FOUND; break; - case EACCES: err = ERR_FILE_ACCESS; break; - case EIO: err = ERR_IO; break; - case ENAMETOOLONG: err = ERR_PATH_LENGTH; break; - - default: err = ERR_FAIL; break; + const LibErrorAssociation& a = it->second; + if(a.errno_equivalent_ == errno) + { + ret = it->first; + break; + } } - + if(warn_if_failed) - DEBUG_WARN_ERR(err); - return err; + DEBUG_WARN_ERR(ret); + return ret; } // translate the return value of any POSIX function into LibError. @@ -109,7 +130,7 @@ LibError LibError_from_posix(int ret, bool warn_if_failed) { debug_assert(ret == 0 || ret == -1); if(ret == 0) - return INFO_OK; + return INFO::OK; return LibError_from_errno(warn_if_failed); } @@ -118,25 +139,21 @@ LibError LibError_from_posix(int ret, bool warn_if_failed) // does not assign to errno (this simplifies code by allowing direct return) static int return_errno_from_LibError(LibError err) { - switch(err) + LibErrorAssociations::iterator it = associations().find(err); + if(it != associations().end()) { - case ERR_NO_MEM: return ENOMEM; - - case ERR_INVALID_PARAM: return EINVAL; - case ERR_NOT_IMPLEMENTED: return ENOSYS; - - case ERR_TNODE_NOT_FOUND: return ENOENT; - case ERR_FILE_ACCESS: return EACCES; - case ERR_IO: return EIO; - case ERR_PATH_LENGTH: return ENAMETOOLONG; + const LibErrorAssociation& a = it->second; + if(a.errno_equivalent_ != -1) + return a.errno_equivalent_; + } // somewhat of a quandary: the set of errnos in wposix.h doesn't // have an "unknown error". we pick EPERM because we don't expect // that to come up often otherwise. - default: return EPERM; - } + return EPERM; } + // set errno to the equivalent of . used in wposix - underlying // functions return LibError but must be translated to errno at // e.g. the mmap interface level. higher-level code that calls mmap will @@ -145,3 +162,68 @@ void LibError_set_errno(LibError err) { errno = return_errno_from_LibError(err); } + + +//----------------------------------------------------------------------------- + +AT_STARTUP(\ + /* INFO::OK doesn't really need a string because calling error_description_r(0) should never happen, but go the safe route. */\ + error_setDescription(INFO::OK, "(but return value was 0 which indicates success)");\ + error_setDescription(ERR::FAIL, "Function failed (no details available)");\ + \ + error_setDescription(INFO::CB_CONTINUE, "Continue (not an error)");\ + error_setDescription(INFO::SKIPPED, "Skipped (not an error)");\ + error_setDescription(INFO::CANNOT_HANDLE, "Cannot handle (not an error)");\ + error_setDescription(INFO::ALL_COMPLETE, "All complete (not an error)");\ + error_setDescription(INFO::ALREADY_EXISTS, "Already exists (not an error)");\ + \ + error_setDescription(ERR::LOGIC, "Logic error in code");\ + error_setDescription(ERR::TIMED_OUT, "Timed out");\ + error_setDescription(ERR::REENTERED, "Single-call function was reentered");\ + error_setDescription(ERR::CORRUPTED, "File/memory data is corrupted");\ + \ + error_setDescription(ERR::INVALID_PARAM, "Invalid function argument");\ + error_setDescription(ERR::INVALID_HANDLE, "Invalid Handle (argument)");\ + error_setDescription(ERR::BUF_SIZE, "Buffer argument too small");\ + error_setDescription(ERR::AGAIN, "Try again later");\ + error_setDescription(ERR::LIMIT, "Fixed limit exceeded");\ + error_setDescription(ERR::NO_SYS, "OS doesn't provide a required API");\ + error_setDescription(ERR::NOT_IMPLEMENTED, "Feature currently not implemented");\ + error_setDescription(ERR::NOT_SUPPORTED, "Feature isn't and won't be supported");\ + error_setDescription(ERR::NO_MEM, "Not enough memory");\ + \ + error_setDescription(ERR::_1, "Case 1");\ + error_setDescription(ERR::_2, "Case 2");\ + error_setDescription(ERR::_3, "Case 3");\ + error_setDescription(ERR::_4, "Case 4");\ + error_setDescription(ERR::_5, "Case 5");\ + error_setDescription(ERR::_6, "Case 6");\ + error_setDescription(ERR::_7, "Case 7");\ + error_setDescription(ERR::_8, "Case 8");\ + error_setDescription(ERR::_9, "Case 9");\ + error_setDescription(ERR::_11, "Case 11");\ + error_setDescription(ERR::_12, "Case 12");\ + error_setDescription(ERR::_13, "Case 13");\ + error_setDescription(ERR::_14, "Case 14");\ + error_setDescription(ERR::_15, "Case 15");\ + error_setDescription(ERR::_16, "Case 16");\ + error_setDescription(ERR::_17, "Case 17");\ + error_setDescription(ERR::_18, "Case 18");\ + error_setDescription(ERR::_19, "Case 19");\ + error_setDescription(ERR::_21, "Case 21");\ + error_setDescription(ERR::_22, "Case 22");\ + error_setDescription(ERR::_23, "Case 23");\ + error_setDescription(ERR::_24, "Case 24");\ + error_setDescription(ERR::_25, "Case 25");\ + error_setDescription(ERR::_26, "Case 26");\ + error_setDescription(ERR::_27, "Case 27");\ + error_setDescription(ERR::_28, "Case 28");\ + error_setDescription(ERR::_29, "Case 29");\ +) + + +AT_STARTUP(\ + error_setEquivalent(ERR::NO_MEM, ENOMEM);\ + error_setEquivalent(ERR::INVALID_PARAM, EINVAL);\ + error_setEquivalent(ERR::NOT_IMPLEMENTED, ENOSYS);\ +) diff --git a/source/lib/lib_errors.h b/source/lib/lib_errors.h index de8d4420b1..50ef4b9f92 100644 --- a/source/lib/lib_errors.h +++ b/source/lib/lib_errors.h @@ -25,6 +25,7 @@ Error handling system + Introduction ------------ @@ -32,6 +33,7 @@ This module defines error codes, translates them to/from other systems (e.g. errno), provides several macros that simplify returning errors / checking if a function failed, and associates codes with descriptive text. + Why Error Codes? ---------------- @@ -39,6 +41,7 @@ To convey information about what failed, the alternatives are unique integral codes and direct pointers to descriptive text. Both occupy the same amount of space, but codes are easier to internationalize. + Method of Propagating Errors ---------------------------- @@ -67,6 +70,7 @@ exceptions when checking call sites and propagating errors becomes tedious. However, inter-module boundaries should always return error codes for interoperability with other languages. + Simplifying Call-Site Checking ------------------------------ @@ -77,7 +81,7 @@ macros to simplify this task: function calls can be wrapped in an Consider the following example: LibError ret = doWork(); - if(ret != INFO_OK) { warnUser(ret); return ret; } + if(ret != INFO::OK) { warnUser(ret); return ret; } This can be replaced by: CHECK_ERR(doWork()); @@ -87,16 +91,17 @@ allows warning the user whenever an error occurs. Thus, no errors can be swept under the carpet by failing to check return value or catch(...) all exceptions. + When to warn the user? ---------------------- When a function fails, there are 2 places we can raise a warning: as soon as the error condition is known, or in the higher-level caller. -The former is the WARN_RETURN(ERR_FAIL) approach, while the latter +The former is the WARN_RETURN(ERR::FAIL) approach, while the latter corresponds to the example above. We prefer the former because it is easier to ensure that all -possible return paths have been covered: search for all "return ERR_*" +possible return paths have been covered: search for all "return ERR::*" that are not followed by a "// NOWARN" comment. Also, the latter approach raises the question of where exactly to issue the warning. Clearly API-level routines must raise the warning, but sometimes they will @@ -115,35 +120,50 @@ without warning, and having their callers take care of that. which caller of the validator failed anyway. Validator functions should therefore also use WARN_RETURN. + +Numbering Scheme +---------------- + +Each module header defines its own error codes to avoid a full rebuild +whenever a new obscure code is added. + +Error codes start at -100000 (warnings are positive, but reserves a +negative value; absolute values are unique). This avoids collisions +with all known error code schemes. + +Each header gets 100 possible values; the tens value may be +used to denote groups within that header. + +The subsystem is denoted by the ten-thousands digit: 1 for file, +2 for other resources (e.g. textures), 3 for sysdep, .. + +To summarize: +/-1SHHCC (S=subsystem, HH=header, CC=code number) + + Notes: - file is called lib_errors.h because 0ad has another errors.cpp and the MS linker isn't smart enough to deal with object files of the same name but in different paths. -- the first part of this file is a normal header; the second contains - X macros and is only active if ERR is defined (i.e. someone is - including this header for the purpose of using them). -- unfortunately Intellisense isn't smart enough to pick up the - ERR_* definitions. This is the price of automatically associating - descriptive text with the error code. **/ #ifndef ERRORS_H__ #define ERRORS_H__ -// limits on the errors defined above (used by error_description_r) -#define ERR_MIN 100000 -#define ERR_MAX 120000 +// note: this loses compiler type safety (being able to prevent +// return 1 when a LibError is the return value), but allows splitting +// up the error namespace into separate headers. +// Lint's 'strong type' checking can be used to find errors. +typedef long LibError; -// define error codes. -enum LibError { -#define ERR(err, id, str) id = err, -#include "lib_errors.h" - // necessary because the enum would otherwise end with a comma - // (which is often tolerated but not standards compliant). - // note: we cannot rely on this being the last value (in case the - // ERR x-macros aren't arranged in order), so don't use as such. - LIB_ERROR_DUMMY -}; + +/** + * associate textual description with an error code. + * + * @param err LibError to be associate with. if it already has a + * description, a warning will be generated. + * @param description string. Must remain valid until end of program. + **/ +extern void error_setDescription(LibError err, const char* description); /** * generate textual description of an error code. @@ -164,6 +184,17 @@ extern char* error_description_r(LibError err, char* buf, size_t max_chars); // note: other conversion routines (e.g. to/from Win32) are implemented in // the corresponding modules to keep this header portable. + +/** + * associate POSIX errno with an error code. + * + * @param err LibError to be associate with. if it already has a + * equivalent, a warning will be generated. + * @param errno (as defined by POSIX) + **/ +extern void error_setEquivalent(LibError err, int errno_); + + /** * translate errno to LibError. * @@ -171,9 +202,9 @@ extern char* error_description_r(LibError err, char* buf, size_t max_chars); * errno may otherwise still be set from another error cause. * * @param warn_if_failed if set, raise a warning when returning an error - * (i.e. ERR_*, but not INFO_OK). this avoids having to wrap all + * (i.e. ERR::*, but not INFO::OK). this avoids having to wrap all * call sites in WARN_ERR etc. - * @return LibError equivalent of errno, or ERR_FAIL if there's no equal. + * @return LibError equivalent of errno, or ERR::FAIL if there's no equal. **/ extern LibError LibError_from_errno(bool warn_if_failed = true); @@ -189,10 +220,10 @@ extern LibError LibError_from_errno(bool warn_if_failed = true); * @param ret return value of a POSIX function: 0 indicates success, * -1 is error. * @param warn_if_failed if set, raise a warning when returning an error - * (i.e. ERR_*, but not INFO_OK). this avoids having to wrap all + * (i.e. ERR::*, but not INFO::OK). this avoids having to wrap all * call sites in WARN_ERR etc. - * @return INFO_OK if the POSIX function succeeded, else the LibError - * equivalent of errno, or ERR_FAIL if there's no equal. + * @return INFO::OK if the POSIX function succeeded, else the LibError + * equivalent of errno, or ERR::FAIL if there's no equal. **/ extern LibError LibError_from_posix(int ret, bool warn_if_failed = true); @@ -318,7 +349,7 @@ STMT(\ {\ debug_warn("FYI: WARN_RETURN_IF_FALSE reports that a function failed."\ "feel free to ignore or suppress this warning.");\ - return ERR_FAIL;\ + return ERR::FAIL;\ }\ ) @@ -326,7 +357,7 @@ STMT(\ #define RETURN_IF_FALSE(ok)\ STMT(\ if(!(ok))\ - return ERR_FAIL;\ + return ERR::FAIL;\ ) // if ok evaluates to false or FALSE, warn user. @@ -338,37 +369,52 @@ STMT(\ ) -#endif // #ifndef ERRORS_H__ - //----------------------------------------------------------------------------- -#ifdef ERR - -// X macros: error code, symbolic name in code, user-visible string. -// error code is usually negative; positive denotes warnings. -// if negative, absolute value must be within [ERR_MIN, ERR_MAX). - -// INFO_OK doesn't really need a string, but must be part of enum LibError -// due to compiler checks. (and calling error_description_r(0) should -// never happen, but we set the text accordingly..) -ERR(0, INFO_OK, "(but return value was 0 which indicates success)") -ERR(-1, ERR_FAIL, "Function failed (no details available)") +namespace INFO +{ +const LibError OK = 0; // note: these values are > 100 to allow multiplexing them with // coroutine return values, which return completion percentage. -ERR(101, INFO_CB_CONTINUE, "1 (not an error)") -// these are all basically the same thing -ERR(102, INFO_CANNOT_HANDLE, "2 (not an error)") -ERR(103, INFO_NO_REPLACE, "3 (not an error)") -ERR(104, INFO_SKIPPED, "4 (not an error)") -ERR(105, INFO_ALL_COMPLETE, "5 (not an error)") -ERR(106, INFO_ALREADY_EXISTS, "6 (not an error)") -ERR(-100000, ERR_LOGIC, "Logic error in code") -ERR(-100001, ERR_TIMED_OUT, "Timed out") -ERR(-100002, ERR_REENTERED, "Single-call function was reentered") -ERR(-100010, ERR_STRING_NOT_TERMINATED, "Invalid string (no 0 terminator found in buffer)") +// function is a callback and indicates that it can (but need not +// necessarily) be called again. +const LibError CB_CONTINUE = +100000; +// notify caller that nothing was done. +const LibError SKIPPED = +100001; +// function is incapable of doing the requested task with the given inputs. +// this implies SKIPPED, but also conveys a bit more information. +const LibError CANNOT_HANDLE = +100002; +// function is meant to be called repeatedly, and now indicates that +// all jobs are complete. +const LibError ALL_COMPLETE = +100003; +// (returned e.g. when inserting into container) +const LibError ALREADY_EXISTS = +100004; +} +namespace ERR +{ +const LibError FAIL = -1; + +// general +const LibError LOGIC = -100010; +const LibError TIMED_OUT = -100011; +const LibError REENTERED = -100012; +const LibError CORRUPTED = -100013; + +// function arguments +const LibError INVALID_PARAM = -100020; +const LibError INVALID_HANDLE = -100021; +const LibError BUF_SIZE = -100022; + +// system limitations +const LibError AGAIN = -100030; +const LibError LIMIT = -100031; +const LibError NO_SYS = -100032; +const LibError NOT_IMPLEMENTED = -100033; +const LibError NOT_SUPPORTED = -100034; +const LibError NO_MEM = -100035; // these are for cases where we just want a distinct value to display and // a symbolic name + string would be overkill (e.g. the various @@ -379,133 +425,34 @@ ERR(-100010, ERR_STRING_NOT_TERMINATED, "Invalid string (no 0 terminator found i // used in a function that calls another validator and 21..29 are // for for functions that call 2 other validators (this avoids // ambiguity as to which error actually happened where) -ERR(-100101, ERR_1, "Case 1") -ERR(-100102, ERR_2, "Case 2") -ERR(-100103, ERR_3, "Case 3") -ERR(-100104, ERR_4, "Case 4") -ERR(-100105, ERR_5, "Case 5") -ERR(-100106, ERR_6, "Case 6") -ERR(-100107, ERR_7, "Case 7") -ERR(-100108, ERR_8, "Case 8") -ERR(-100109, ERR_9, "Case 9") -ERR(-100111, ERR_11, "Case 11") -ERR(-100112, ERR_12, "Case 12") -ERR(-100113, ERR_13, "Case 13") -ERR(-100114, ERR_14, "Case 14") -ERR(-100115, ERR_15, "Case 15") -ERR(-100116, ERR_16, "Case 16") -ERR(-100117, ERR_17, "Case 17") -ERR(-100118, ERR_18, "Case 18") -ERR(-100119, ERR_19, "Case 19") -ERR(-100121, ERR_21, "Case 21") -ERR(-100122, ERR_22, "Case 22") -ERR(-100123, ERR_23, "Case 23") -ERR(-100124, ERR_24, "Case 24") -ERR(-100125, ERR_25, "Case 25") -ERR(-100126, ERR_26, "Case 26") -ERR(-100127, ERR_27, "Case 27") -ERR(-100128, ERR_28, "Case 28") -ERR(-100129, ERR_29, "Case 29") +const LibError _1 = -100101; +const LibError _2 = -100102; +const LibError _3 = -100103; +const LibError _4 = -100104; +const LibError _5 = -100105; +const LibError _6 = -100106; +const LibError _7 = -100107; +const LibError _8 = -100108; +const LibError _9 = -100109; +const LibError _11 = -100111; +const LibError _12 = -100112; +const LibError _13 = -100113; +const LibError _14 = -100114; +const LibError _15 = -100115; +const LibError _16 = -100116; +const LibError _17 = -100117; +const LibError _18 = -100118; +const LibError _19 = -100119; +const LibError _21 = -100121; +const LibError _22 = -100122; +const LibError _23 = -100123; +const LibError _24 = -100124; +const LibError _25 = -100125; +const LibError _26 = -100126; +const LibError _27 = -100127; +const LibError _28 = -100128; +const LibError _29 = -100129; -// function arguments -ERR(-100220, ERR_INVALID_PARAM, "Invalid function argument") -ERR(-100221, ERR_INVALID_HANDLE, "Invalid Handle (argument)") -ERR(-100222, ERR_BUF_SIZE, "Buffer argument too small") +} // namespace ERR -// system limitations -ERR(-100240, ERR_AGAIN, "Try again later") -ERR(-100241, ERR_LIMIT, "Fixed limit exceeded") -ERR(-100242, ERR_NO_SYS, "OS doesn't provide a required API") -ERR(-100243, ERR_NOT_IMPLEMENTED, "Feature currently not implemented") -ERR(-100244, ERR_NOT_SUPPORTED, "Feature isn't and won't be supported") - -// memory -ERR(-100260, ERR_NO_MEM, "Not enough memory") -ERR(-100261, ERR_ALLOC_NOT_FOUND, "Not a valid allocated address") -ERR(-100262, ERR_MEM_OVERWRITTEN, "Wrote to memory outside valid allocation") - -// file + vfs -// .. path -ERR(-100300, ERR_PATH_LENGTH, "Path exceeds PATH_MAX characters") -ERR(-100301, ERR_PATH_EMPTY, "Path is an empty string") -ERR(-100302, ERR_PATH_NOT_RELATIVE, "Path is not relative") -ERR(-100303, ERR_PATH_NON_PORTABLE, "Path contains OS-specific dir separator") -ERR(-100304, ERR_PATH_NON_CANONICAL, "Path contains unsupported .. or ./") -ERR(-100305, ERR_PATH_COMPONENT_SEPARATOR, "Path component contains dir separator") -// .. tree node -ERR(-100310, ERR_TNODE_NOT_FOUND, "File/directory not found") -ERR(-100311, ERR_TNODE_WRONG_TYPE, "Using a directory as file or vice versa") -// .. open -ERR(-100320, ERR_FILE_ACCESS, "Insufficient access rights to open file") -// .. enum -ERR(-100330, ERR_DIR_END, "End of directory reached (no more files)") -// .. IO -ERR(-100340, ERR_IO, "Error during IO") -ERR(-100341, ERR_EOF, "Reading beyond end of file") -// .. mount -ERR(-100350, ERR_ALREADY_MOUNTED, "Directory (tree) already mounted") -ERR(-100351, ERR_NOT_MOUNTED, "Specified directory is not mounted") -ERR(-100352, ERR_INVALID_MOUNT_TYPE, "Invalid mount type (memory corruption?)") -ERR(-100353, ERR_ROOT_DIR_ALREADY_SET, "Attempting to set FS root dir more than once") -// .. misc -ERR(-100360, ERR_UNKNOWN_CMETHOD, "Unknown/unsupported compression method") -ERR(-100361, ERR_IS_COMPRESSED, "Invalid operation for a compressed file") -ERR(-100362, ERR_NOT_MAPPED, "File was not mapped") -ERR(-100363, ERR_NOT_IN_CACHE, "[Internal] Entry not found in cache") -ERR(-100364, ERR_TRACE_EMPTY, "No valid entries in trace") - -// file format -ERR(-100400, ERR_UNKNOWN_FORMAT, "Unknown file format") -ERR(-100401, ERR_INCOMPLETE_HEADER, "File header not completely read") -ERR(-100402, ERR_CORRUPTED, "File data is corrupted") - -// texture -ERR(-100500, ERR_TEX_FMT_INVALID, "Invalid/unsupported texture format") -ERR(-100501, ERR_TEX_INVALID_COLOR_TYPE, "Invalid color type") -ERR(-100502, ERR_TEX_NOT_8BIT_PRECISION, "Not 8-bit channel precision") -ERR(-100503, ERR_TEX_INVALID_LAYOUT, "Unsupported texel layout, e.g. right-to-left") -ERR(-100504, ERR_TEX_COMPRESSED, "Unsupported texture compression") -ERR(+100505, WARN_TEX_INVALID_DATA, "Warning: invalid texel data encountered") -ERR(-100506, ERR_TEX_INVALID_SIZE, "Texture size is incorrect") -ERR(+100507, INFO_TEX_CODEC_CANNOT_HANDLE, "Texture codec cannot handle the given format") - -// CPU -ERR(-100600, ERR_CPU_FEATURE_MISSING, "This CPU doesn't support a required feature") -ERR(-100601, ERR_CPU_UNKNOWN_OPCODE, "Disassembly failed") -ERR(-100602, ERR_CPU_RESTRICTED_AFFINITY, "Cannot set desired CPU affinity") - -// shaders -ERR(-100700, ERR_SHDR_CREATE, "Shader creation failed") -ERR(-100701, ERR_SHDR_COMPILE, "Shader compile failed") -ERR(-100702, ERR_SHDR_NO_SHADER, "Invalid shader reference") -ERR(-100703, ERR_SHDR_LINK, "Shader linking failed") -ERR(-100704, ERR_SHDR_NO_PROGRAM, "Invalid shader program reference") - -// debug symbol engine -ERR(-100800, ERR_SYM_NO_STACK_FRAMES_FOUND, "No stack frames found") -ERR(-100801, ERR_SYM_UNRETRIEVABLE_STATIC, "Value unretrievable (stored in external module)") -ERR(-100802, ERR_SYM_UNRETRIEVABLE_REG, "Value unretrievable (stored in register)") -ERR(-100803, ERR_SYM_TYPE_INFO_UNAVAILABLE, "Error getting type_info") -ERR(-100804, ERR_SYM_INTERNAL_ERROR, "Exception raised while processing a symbol") -ERR(-100805, ERR_SYM_UNSUPPORTED, "Symbol type not (fully) supported") -ERR(-100806, ERR_SYM_CHILD_NOT_FOUND, "Symbol does not have the given child") -// .. this limit is to prevent infinite recursion. -ERR(-100807, ERR_SYM_NESTING_LIMIT, "Symbol nesting too deep or infinite recursion") -// .. this limit is to prevent large symbols (e.g. arrays or linked lists) from -// hogging all stack trace buffer space. -ERR(-100808, ERR_SYM_SINGLE_SYMBOL_LIMIT, "Symbol has produced too much output") -// .. one of the dump_sym* functions decided not to output anything at -// all (e.g. for member functions in UDTs - we don't want those). -// therefore, skip any post-symbol formatting (e.g. ",") as well. -ERR(+100809, INFO_SYM_SUPPRESS_OUTPUT, "Symbol was suppressed") - -// STL debug -ERR(-100900, ERR_STL_CNT_UNKNOWN, "Unknown STL container type_name") -// .. likely causes: not yet initialized or memory corruption. -ERR(-100901, ERR_STL_CNT_INVALID, "Container type is known but contents are invalid") - -// timer -ERR(-101000, ERR_TIMER_NO_SAFE_IMPL, "No safe time source available") - -#undef ERR -#endif // #ifdef ERR +#endif // #ifndef ERRORS_H__ diff --git a/source/lib/lockfree.cpp b/source/lib/lockfree.cpp index a88929c587..9c454ca084 100644 --- a/source/lib/lockfree.cpp +++ b/source/lib/lockfree.cpp @@ -430,7 +430,7 @@ static inline Node* without_mark(Node* p) // make ready a previously unused(!) list object. if a negative error -// code (currently only ERR_NO_MEM) is returned, the list can't be used. +// code (currently only ERR::NO_MEM) is returned, the list can't be used. LibError lfl_init(LFList* list) { // make sure a TLS slot has been allocated for this thread. @@ -443,12 +443,12 @@ LibError lfl_init(LFList* list) if(!tls) { list->head = (void*)-1; // 'poison' prevents further use - return ERR_NO_MEM; + return ERR::NO_MEM; } list->head = 0; atomic_add(&active_data_structures, 1); - return INFO_OK; + return INFO::OK; } @@ -624,7 +624,7 @@ LibError lfl_erase(LFList* list, uintptr_t key) retry: // not found in list - abort. if(!list_lookup(list, key, pos)) - return ERR_FAIL; + return ERR::FAIL; // mark as removed (avoids subsequent linking to it). failure implies // at least of the following happened after list_lookup; we try again. // - next was removed @@ -640,7 +640,7 @@ retry: // call list_lookup to ensure # non-released nodes < # threads. else list_lookup(list, key, pos); - return INFO_OK; + return INFO::OK; } @@ -669,7 +669,7 @@ static LFList* chain(LFHash* hash, uintptr_t key) // make ready a previously unused(!) hash object. table size will be // ; this cannot currently be expanded. if a negative error -// code (currently only ERR_NO_MEM) is returned, the hash can't be used. +// code (currently only ERR::NO_MEM) is returned, the hash can't be used. LibError lfh_init(LFHash* hash, size_t num_entries) { hash->tbl = 0; @@ -678,12 +678,12 @@ LibError lfh_init(LFHash* hash, size_t num_entries) if(!is_pow2((long)num_entries)) { debug_warn("lfh_init: size must be power of 2"); - return ERR_INVALID_PARAM; + return ERR::INVALID_PARAM; } hash->tbl = (LFList*)malloc(sizeof(LFList) * num_entries); if(!hash->tbl) - return ERR_NO_MEM; + return ERR::NO_MEM; hash->mask = (uint)num_entries-1; for(int i = 0; i < (int)num_entries; i++) @@ -694,11 +694,11 @@ LibError lfh_init(LFHash* hash, size_t num_entries) // failed - free all and bail for(int j = 0; j < i; j++) lfl_free(&hash->tbl[j]); - return ERR_NO_MEM; + return ERR::NO_MEM; } } - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/lockfree.h b/source/lib/lockfree.h index ea887b5e13..ab3947e49d 100644 --- a/source/lib/lockfree.h +++ b/source/lib/lockfree.h @@ -112,7 +112,7 @@ struct LFList }; // make ready a previously unused(!) list object. if a negative error -// code (currently only ERR_NO_MEM) is returned, the list can't be used. +// code (currently only ERR::NO_MEM) is returned, the list can't be used. extern LibError lfl_init(LFList* list); // call when list is no longer needed; should no longer hold any references. @@ -144,7 +144,7 @@ struct LFHash // make ready a previously unused(!) hash object. table size will be // ; this cannot currently be expanded. if a negative error -// code (currently only ERR_NO_MEM) is returned, the hash can't be used. +// code (currently only ERR::NO_MEM) is returned, the hash can't be used. extern LibError lfh_init(LFHash* hash, size_t num_entries); // call when hash is no longer needed; should no longer hold any references. diff --git a/source/lib/mmgr.cpp b/source/lib/mmgr.cpp index 02d8004eb8..b30f082486 100644 --- a/source/lib/mmgr.cpp +++ b/source/lib/mmgr.cpp @@ -22,6 +22,13 @@ #include "precompiled.h" + +AT_STARTUP(\ + error_setDescription(ERR::MEM_ALLOC_NOT_FOUND, "Not a valid allocated address");\ + error_setDescription(ERR::MEM_OVERWRITTEN, "Wrote to memory outside valid allocation");\ +) + + // for easy removal in release builds, so that we don't cause any overhead. // note that any application calls to our functions must be removed also, // but this is preferable to stubbing them out here ("least surprise"). @@ -242,7 +249,7 @@ static Alloc* alloc_new() freelist = (Alloc*)calloc(256, sizeof(Alloc)); if(!freelist) { - debug_assert(0 && "mmgr: failed to allocate freelist (out of memory)"); + DEBUG_WARN_ERR(ERR::NO_MEM); return 0; } @@ -848,7 +855,7 @@ static bool alloc_is_valid(const Alloc* a) else log("[!] alloc_is_valid encountered an exception - something may be very wrong!\n"); log_this_alloc(a); - debug_assert(0 && "Memory over/underrun detected by mmgr"); + DEBUG_WARN_ERR(ERR::MEM_OVERWRITTEN); } return intact; } @@ -881,13 +888,13 @@ static bool validate_all() // enable MMGR_VALIDATE_ALL, trigger this condition again, // and check the log for the last successful operation. the problem // will have occurred between then and now. - DEBUG_WARN_ERR(ERR_CORRUPTED); + DEBUG_WARN_ERR(ERR::CORRUPTED); log("[!] Memory tracking hash table corrupt!\n"); } if(params.num_invalid) { - DEBUG_WARN_ERR(ERR_MEM_OVERWRITTEN); + DEBUG_WARN_ERR(ERR::MEM_OVERWRITTEN); log("[!] %d allocations are corrupt\n", params.num_invalid); return false; } @@ -1047,7 +1054,7 @@ void* alloc_dbg(size_t user_size, AllocType type, const char* file, int line, co void* p = malloc(size); if(!p) { - DEBUG_WARN_ERR(ERR_NO_MEM); + DEBUG_WARN_ERR(ERR::NO_MEM); log("[!] Allocation failed (out of memory)\n"); goto fail; } @@ -1114,9 +1121,8 @@ void free_dbg(const void* user_p, AllocType type, const char* file, int line, co Alloc* a = allocs_find(user_p); if(!a) { - // you tried to free a pointer mmgr didn't allocate - debug_assert(0 && "mmgr tried to free a pointer mmgr didn't allocate"); log("[!] mmgr_free: not allocated by this memory manager\n"); + DEBUG_WARN_ERR(ERR::ALLOC_NOT_FOUND); goto fail; } // .. overrun? (note: alloc_is_valid already asserts if invalid) @@ -1197,7 +1203,7 @@ void* realloc_dbg(const void* user_p, size_t user_size, AllocType type, const ch { // you called realloc for a pointer mmgr didn't allocate log("[!] realloc: wasn't previously allocated\n"); - debug_assert(0 && "realloc was called for a pointer mmgr didn't allocate"); + DEBUG_WARN_ERR(ERR::MEM_ALLOC_NOT_FOUND); goto fail; } // .. the owner wasn't compiled with mmgr.h diff --git a/source/lib/mmgr.h b/source/lib/mmgr.h index fb5d840f60..15b8bf09fa 100644 --- a/source/lib/mmgr.h +++ b/source/lib/mmgr.h @@ -105,6 +105,13 @@ good luck! #ifndef MMGR_H__ #define MMGR_H__ +namespace ERR +{ + const LibError MEM_ALLOC_NOT_FOUND = -100200; + const LibError MEM_OVERWRITTEN = -100201; +} + + // provide for completely disabling the memory manager // (e.g. when using other debug packages) // @@ -115,7 +122,6 @@ good luck! #include "lib/types.h" - // // optional additional checks, enabled via mmgr_set_options. // these slow down the application; see 'digging deeper' in documentation. diff --git a/source/lib/ogl.cpp b/source/lib/ogl.cpp index 37df6e5710..b7ecf72e2c 100644 --- a/source/lib/ogl.cpp +++ b/source/lib/ogl.cpp @@ -348,14 +348,14 @@ LibError ogl_get_gfx_info() // can fail if OpenGL not yet initialized, // or if called between glBegin and glEnd. if(!vendor || !renderer || !version) - WARN_RETURN(ERR_AGAIN); + WARN_RETURN(ERR::AGAIN); snprintf(gfx_card, ARRAY_SIZE(gfx_card), "%s %s", vendor, renderer); // add "OpenGL" to differentiate this from the real driver version // (returned by platform-specific detect routines). snprintf(gfx_drv_ver, ARRAY_SIZE(gfx_drv_ver), "OpenGL %s", version); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/ogl.h b/source/lib/ogl.h index 0f819a941d..c15e883adf 100644 --- a/source/lib/ogl.h +++ b/source/lib/ogl.h @@ -23,10 +23,6 @@ #ifndef __OGL_H__ #define __OGL_H__ -#ifdef __cplusplus -extern "C" { -#endif - #if OS_WIN // wgl.h is a private header and should only be included from here. // if this isn't defined, it'll complain. @@ -193,9 +189,4 @@ extern void oglSquelchError(GLenum err_to_ignore); **/ extern void oglInit(void); - -#ifdef __cplusplus -} -#endif - #endif // #ifndef __OGL_H__ diff --git a/source/lib/path_util.cpp b/source/lib/path_util.cpp index 4da517bea3..8b1f4ce144 100644 --- a/source/lib/path_util.cpp +++ b/source/lib/path_util.cpp @@ -29,6 +29,18 @@ #include "path_util.h" +AT_STARTUP(\ + error_setDescription(ERR::PATH_LENGTH, "Path exceeds PATH_MAX characters");\ + error_setDescription(ERR::PATH_EMPTY, "Path is an empty string");\ + error_setDescription(ERR::PATH_NOT_RELATIVE, "Path is not relative");\ + error_setDescription(ERR::PATH_NON_PORTABLE, "Path contains OSspecific dir separator");\ + error_setDescription(ERR::PATH_NON_CANONICAL, "Path contains unsupported .. or ./");\ + error_setDescription(ERR::PATH_COMPONENT_SEPARATOR, "Path component contains dir separator");\ + \ + error_setEquivalent(ERR::PATH_LENGTH, ENAMETOOLONG);\ +) + + static inline bool is_dir_sep(char c) { if(c == '/' || c == DIR_SEP) @@ -69,13 +81,13 @@ bool path_is_subpath(const char* s1, const char* s2) } -// if path is invalid, return a descriptive error code, otherwise INFO_OK. +// if path is invalid, return a descriptive error code, otherwise INFO::OK. LibError path_validate(const char* path) { // disallow "/", because it would create a second 'root' (with name = ""). // root dir is "". if(path[0] == '/') - WARN_RETURN(ERR_PATH_NOT_RELATIVE); + WARN_RETURN(ERR::PATH_NOT_RELATIVE); // scan each char in path string; count length. int c = 0; // current char; used for .. detection @@ -87,35 +99,35 @@ LibError path_validate(const char* path) // whole path is too long if(path_len >= PATH_MAX) - WARN_RETURN(ERR_PATH_LENGTH); + WARN_RETURN(ERR::PATH_LENGTH); // disallow: // - ".." (prevent going above the VFS root dir) // - "./" (security hole when mounting and not supported on Windows). // allow "/.", because CVS backup files include it. if(last_c == '.' && (c == '.' || c == '/')) - WARN_RETURN(ERR_PATH_NON_CANONICAL); + WARN_RETURN(ERR::PATH_NON_CANONICAL); // disallow OS-specific dir separators if(c == '\\' || c == ':') - WARN_RETURN(ERR_PATH_NON_PORTABLE); + WARN_RETURN(ERR::PATH_NON_PORTABLE); // end of string, no errors encountered if(c == '\0') break; } - return INFO_OK; + return INFO::OK; } -// if name is invalid, return a descriptive error code, otherwise INFO_OK. +// if name is invalid, return a descriptive error code, otherwise INFO::OK. // (name is a path component, i.e. that between directory separators) LibError path_component_validate(const char* name) { // disallow empty strings if(*name == '\0') - WARN_RETURN(ERR_PATH_EMPTY); + WARN_RETURN(ERR::PATH_EMPTY); for(;;) { @@ -124,14 +136,14 @@ LibError path_component_validate(const char* name) // disallow *any* dir separators (regardless of which // platform we're on). if(c == '\\' || c == ':' || c == '/') - WARN_RETURN(ERR_PATH_COMPONENT_SEPARATOR); + WARN_RETURN(ERR::PATH_COMPONENT_SEPARATOR); // end of string, no errors encountered if(c == '\0') break; } - return INFO_OK; + return INFO::OK; } @@ -175,7 +187,7 @@ LibError path_append(char* dst, const char* path1, const char* path2, uint flags } if(total_len > PATH_MAX) - WARN_RETURN(ERR_PATH_LENGTH); + WARN_RETURN(ERR::PATH_LENGTH); strcpy(dst, path1); // safe dst += len1; @@ -185,20 +197,20 @@ LibError path_append(char* dst, const char* path1, const char* path2, uint flags if(need_terminator) strcpy(dst+len2, "/"); // safe - return INFO_OK; + return INFO::OK; } // strip from the start of , prepend , // and write to . -// returns ERR_FAIL (without warning!) if the beginning of doesn't +// returns ERR::FAIL (without warning!) if the beginning of doesn't // match . LibError path_replace(char* dst, const char* src, const char* remove, const char* replace) { // remove doesn't match start of const size_t remove_len = strlen(remove); if(strncmp(src, remove, remove_len) != 0) - return ERR_FAIL; // NOWARN + return ERR::FAIL; // NOWARN // if removing will leave a separator at beginning of src, remove it // (example: "a/b"; removing "a" would yield "/b") @@ -208,7 +220,7 @@ LibError path_replace(char* dst, const char* src, const char* remove, const char // prepend replace. RETURN_ERR(path_append(dst, replace, start)); - return INFO_OK; + return INFO::OK; } @@ -329,7 +341,7 @@ LibError path_foreach_component(const char* path_org, PathComponentCb cb, void* LibError ret = cb(cur_component, is_dir, ctx); // callback wants to abort - return its value. - if(ret != INFO_CB_CONTINUE) + if(ret != INFO::CB_CONTINUE) return ret; // filename is by definition the last component. abort now @@ -344,7 +356,7 @@ LibError path_foreach_component(const char* path_org, PathComponentCb cb, void* cur_component = slash+1; } - return INFO_OK; + return INFO::OK; } @@ -366,7 +378,7 @@ LibError path_package_set_dir(PathPackage* pp, const char* dir) // -1 allows for trailing DIR_SEP that will be added if not // already present. if(strcpy_s(pp->path, ARRAY_SIZE(pp->path)-1, dir) != 0) - WARN_RETURN(ERR_PATH_LENGTH); + WARN_RETURN(ERR::PATH_LENGTH); size_t len = strlen(pp->path); // add directory separator if not already present // .. but only check this if dir != "" (=> len-1 is safe) @@ -386,7 +398,7 @@ LibError path_package_set_dir(PathPackage* pp, const char* dir) pp->end = pp->path+len; pp->chars_left = ARRAY_SIZE(pp->path)-len; - return INFO_OK; + return INFO::OK; } @@ -395,5 +407,5 @@ LibError path_package_set_dir(PathPackage* pp, const char* dir) LibError path_package_append_file(PathPackage* pp, const char* path) { CHECK_ERR(strcpy_s(pp->end, pp->chars_left, path)); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/path_util.h b/source/lib/path_util.h index 5966607cbd..a869efd735 100644 --- a/source/lib/path_util.h +++ b/source/lib/path_util.h @@ -35,10 +35,22 @@ #include "posix.h" // PATH_MAX + +namespace ERR +{ + const LibError PATH_LENGTH = -100300; + const LibError PATH_EMPTY = -100301; + const LibError PATH_NOT_RELATIVE = -100302; + const LibError PATH_NON_PORTABLE = -100303; + const LibError PATH_NON_CANONICAL = -100304; + const LibError PATH_COMPONENT_SEPARATOR = -100305; +} + + /** * check if path is valid. (see source for criteria) * - * @return LibError (ERR_PATH_* or INFO_OK) + * @return LibError (ERR::PATH_* or INFO::OK) **/ extern LibError path_validate(const char* path); @@ -50,7 +62,7 @@ extern LibError path_validate(const char* path); /** * check if name is valid. (see source for criteria) * - * @return LibError (ERR_PATH_* or INFO_OK) + * @return LibError (ERR::PATH_* or INFO::OK) **/ extern LibError path_component_validate(const char* name); @@ -106,7 +118,7 @@ extern LibError path_append(char* dst, const char* path1, const char* path2, * @param remove substring to remove; must match (case-sensitive) the * start of src. * @param replace string to prepend to output after stripping . - * @return LibError; ERR_FAIL (without warning!) if doesn't + * @return LibError; ERR::FAIL (without warning!) if doesn't * match . **/ extern LibError path_replace(char* dst, const char* src, const char* remove, const char* replace); @@ -170,9 +182,9 @@ extern const char* path_extension(const char* fn); * rationale: a bool isn't as nice as a flag or enum, but vfs_tree already * has TNodeType and we don't want to expose that or create a new one. * @param ctx: context parameter that was passed to path_foreach_component. - * @return LibError; INFO_CB_CONTINUE to continue operation normally; + * @return LibError; INFO::CB_CONTINUE to continue operation normally; * anything else will cause path_foreach_component to abort immediately and - * return that. no need to 'abort' (e.g. return INFO_OK) after a filename is + * return that. no need to 'abort' (e.g. return INFO::OK) after a filename is * encountered - that's taken care of automatically. **/ typedef LibError (*PathComponentCb)(const char* component, bool is_dir, void* ctx); diff --git a/source/lib/precompiled.h b/source/lib/precompiled.h index 7c8a69e54e..7543eca433 100644 --- a/source/lib/precompiled.h +++ b/source/lib/precompiled.h @@ -56,6 +56,7 @@ // #include "lib/types.h" +#include "lib/lib_errors.h" #include "lib/string_s.h" // CRT secure string #include "lib/sysdep/sysdep.h" #include "lib/debug.h" // (sysdep.h pulls in debug.h) diff --git a/source/lib/res/file/archive.cpp b/source/lib/res/file/archive.cpp index dabf32f10a..16fc3183c7 100644 --- a/source/lib/res/file/archive.cpp +++ b/source/lib/res/file/archive.cpp @@ -44,6 +44,12 @@ // uses file_* and inf_*. // - file mapping + +AT_STARTUP(\ + error_setDescription(ERR::IS_COMPRESSED, "Invalid operation for a compressed file");\ +) + + /////////////////////////////////////////////////////////////////////////////// // // lookup_*: file lookup @@ -121,7 +127,7 @@ static LibError Archive_reload(Archive* a, const char* fn, Handle) RETURN_ERR(zip_populate_archive(&a->f, a)); a->is_loaded = 1; - return INFO_OK; + return INFO::OK; } static LibError Archive_validate(const Archive* a) @@ -129,15 +135,15 @@ static LibError Archive_validate(const Archive* a) RETURN_ERR(file_validate(&a->f)); if(debug_is_pointer_bogus(a->ents)) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); - return INFO_OK; + return INFO::OK; } static LibError Archive_to_string(const Archive* a, char* buf) { snprintf(buf, H_STRING_LEN, "(%u files)", a->num_files); - return INFO_OK; + return INFO::OK; } @@ -169,7 +175,7 @@ static LibError archive_get_file_info(Archive* a, const char* fn, uintptr_t meme if(memento) { ent = (ArchiveEntry*)memento; - return INFO_OK; + return INFO::OK; } else { @@ -178,11 +184,11 @@ static LibError archive_get_file_info(Archive* a, const char* fn, uintptr_t meme if(a->ents[i].atom_fn == atom_fn) { ent = &a->ents[i]; - return INFO_OK; + return INFO::OK; } } - WARN_RETURN(ERR_TNODE_NOT_FOUND); + WARN_RETURN(ERR::TNODE_NOT_FOUND); } @@ -207,11 +213,11 @@ LibError archive_enum(const Handle ha, const FileCB cb, const uintptr_t user) s.st_mtime = ent->mtime; const uintptr_t memento = (uintptr_t)ent; LibError ret = cb(ent->atom_fn, &s, memento, user); - if(ret != INFO_CB_CONTINUE) + if(ret != INFO::CB_CONTINUE) return ret; } - return INFO_OK; + return INFO::OK; } @@ -222,8 +228,8 @@ LibError archive_allocate_entries(Archive* a, size_t num_entries) debug_assert(a->ents == 0); // must not have been allocated yet a->ents = (ArchiveEntry*)mem_alloc(num_entries * sizeof(ArchiveEntry), 32); if(!a->ents) - WARN_RETURN(ERR_NO_MEM); - return INFO_OK; + WARN_RETURN(ERR::NO_MEM); + return INFO::OK; } @@ -235,7 +241,7 @@ LibError archive_allocate_entries(Archive* a, size_t num_entries) LibError archive_add_file(Archive* a, const ArchiveEntry* ent) { a->ents[a->num_files++] = *ent; - return INFO_OK; + return INFO::OK; } @@ -290,7 +296,7 @@ LibError afile_stat(Handle ha, const char* fn, struct stat* s) s->st_size = ent->ucsize; s->st_mtime = ent->mtime; - return INFO_OK; + return INFO::OK; } @@ -299,16 +305,16 @@ LibError afile_stat(Handle ha, const char* fn, struct stat* s) LibError afile_validate(const File* f) { if(!f) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); const ArchiveFile* af = (const ArchiveFile*)f->opaque; UNUSED2(af); // note: don't check af->ha - it may be freed at shutdown before // its files. TODO: revisit once dependency support is added. if(!f->size) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); // note: af->ctx is 0 if file is not compressed. - return INFO_OK; + return INFO::OK; } #define CHECK_AFILE(f) RETURN_ERR(afile_validate(f)) @@ -322,7 +328,7 @@ LibError afile_open(const Handle ha, const char* fn, uintptr_t memento, uint fla memset(f, 0, sizeof(*f)); if(flags & FILE_WRITE) - WARN_RETURN(ERR_IS_COMPRESSED); + WARN_RETURN(ERR::IS_COMPRESSED); H_DEREF(ha, Archive, a); @@ -345,7 +351,7 @@ LibError afile_open(const Handle ha, const char* fn, uintptr_t memento, uint fla { ctx = comp_alloc(CT_DECOMPRESSION, ent->method); if(!ctx) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); } f->flags = flags; @@ -359,7 +365,7 @@ LibError afile_open(const Handle ha, const char* fn, uintptr_t memento, uint fla af->ctx = ctx; af->is_mapped = 0; CHECK_AFILE(f); - return INFO_OK; + return INFO::OK; } @@ -371,7 +377,7 @@ LibError afile_close(File* f) // other File fields don't need to be freed/cleared comp_free(af->ctx); af->ctx = 0; - return INFO_OK; + return INFO::OK; } @@ -415,7 +421,7 @@ LibError afile_io_issue(File* f, off_t user_ofs, size_t max_output_size, void* u ArchiveFileIo* aio = (ArchiveFileIo*)io->opaque; aio->io = io_allocator.alloc(); if(!aio->io) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); // not compressed; we'll just read directly from the archive file. // no need to clamp to EOF - that's done already by the VFS. @@ -441,12 +447,12 @@ LibError afile_io_issue(File* f, off_t user_ofs, size_t max_output_size, void* u void* cbuf = mem_alloc(csize, 4*KiB); if(!cbuf) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); RETURN_ERR(file_io_issue(&a->f, cofs, csize, cbuf, aio->io)); af->last_cofs += (off_t)csize; - return INFO_OK; + return INFO::OK; } @@ -489,7 +495,7 @@ LibError afile_io_wait(FileIo* io, void*& buf, size_t& size) size = raw_size; } - return INFO_OK; + return INFO::OK; } @@ -507,10 +513,10 @@ LibError afile_io_validate(const FileIo* io) { ArchiveFileIo* aio = (ArchiveFileIo*)io->opaque; if(debug_is_pointer_bogus(aio->user_buf)) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); // and have no invariants we could check. RETURN_ERR(file_io_validate(aio->io)); - return INFO_OK; + return INFO::OK; } @@ -544,11 +550,11 @@ public: debug_assert(ucsize <= ucsize_left); ucsize_left -= ucsize; - LibError ret = INFO_CB_CONTINUE; + LibError ret = INFO::CB_CONTINUE; if(user_cb) ret = user_cb(user_cb_ctx, ucblock, ucsize, bytes_processed); if(ucsize_left == 0) - ret = INFO_OK; + ret = INFO::OK; return ret; } @@ -667,7 +673,7 @@ LibError afile_map(File* f, void*& p, size_t& size) // mapping compressed files doesn't make sense because the // compression algorithm is unspecified - disallow it. if(is_compressed(af)) - WARN_RETURN(ERR_IS_COMPRESSED); + WARN_RETURN(ERR::IS_COMPRESSED); // note: we mapped the archive in archive_open, but unmapped it // in the meantime to save memory in case it wasn't going to be mapped. @@ -681,7 +687,7 @@ LibError afile_map(File* f, void*& p, size_t& size) size = f->size; af->is_mapped = 1; - return INFO_OK; + return INFO::OK; } @@ -698,7 +704,7 @@ LibError afile_unmap(File* f) // make sure archive mapping refcount remains balanced: // don't allow multiple|"false" unmaps. if(!af->is_mapped) - WARN_RETURN(ERR_NOT_MAPPED); + WARN_RETURN(ERR::FILE_NOT_MAPPED); af->is_mapped = 0; H_DEREF(af->ha, Archive, a); diff --git a/source/lib/res/file/archive.h b/source/lib/res/file/archive.h index b6fcae527e..b8a1471294 100644 --- a/source/lib/res/file/archive.h +++ b/source/lib/res/file/archive.h @@ -28,6 +28,10 @@ #include "file.h" // FileCB for afile_enum #include "compression.h" // CompressionMethod +namespace ERR +{ + const LibError IS_COMPRESSED = -110400; +} // note: filenames are case-insensitive. @@ -199,7 +203,7 @@ struct ArchiveEntry // successively called for each valid file in the archive, // passing the complete path and . -// return INFO_CB_CONTINUE to continue calling; anything else will cause +// return INFO::CB_CONTINUE to continue calling; anything else will cause // the caller to abort and immediately return that value. // // HACK: call back with negative index the first time; its abs. value is diff --git a/source/lib/res/file/archive_builder.cpp b/source/lib/res/file/archive_builder.cpp index cc55b87b5e..ef12faffa8 100644 --- a/source/lib/res/file/archive_builder.cpp +++ b/source/lib/res/file/archive_builder.cpp @@ -76,7 +76,7 @@ static LibError compress_cb(uintptr_t cb_ctx, const void* block, size_t size, si if(p->attempt_compress) (void)comp_feed(p->ctx, block, size); - return INFO_CB_CONTINUE; + return INFO::CB_CONTINUE; } @@ -123,7 +123,7 @@ static LibError read_and_compress_file(const char* atom_fn, uintptr_t ctx, // even less safe. // we thus skip 0-length files to avoid confusing them with dirs. if(!ucsize) - return INFO_SKIPPED; + return INFO::SKIPPED; const bool attempt_compress = !file_type_is_uncompressible(atom_fn); if(attempt_compress) @@ -179,7 +179,7 @@ static LibError read_and_compress_file(const char* atom_fn, uintptr_t ctx, // note: no need to free cdata - it is owned by the // compression context and can be reused. - return INFO_OK; + return INFO::OK; } @@ -195,7 +195,7 @@ LibError archive_build_init(const char* P_archive_filename, Filenames V_fns, for(ab->num_files = 0; ab->V_fns[ab->num_files]; ab->num_files++) {} ab->i = 0; - return INFO_OK; + return INFO::OK; } @@ -210,7 +210,7 @@ int archive_build_continue(ArchiveBuildState* ab) break; ArchiveEntry ent; void* file_contents; FileIOBuf buf; - if(read_and_compress_file(V_fn, ab->ctx, ent, file_contents, buf) == INFO_OK) + if(read_and_compress_file(V_fn, ab->ctx, ent, file_contents, buf) == INFO::OK) { (void)zip_archive_add_file(ab->za, &ent, file_contents); (void)file_buf_free(buf); @@ -226,7 +226,7 @@ int archive_build_continue(ArchiveBuildState* ab) comp_free(ab->ctx); ab->ctx = 0; (void)zip_archive_finish(ab->za); - return INFO_OK; + return INFO::OK; } @@ -251,7 +251,7 @@ LibError archive_build(const char* P_archive_filename, Filenames V_fns) { int ret = archive_build_continue(&ab); RETURN_ERR(ret); - if(ret == INFO_OK) - return INFO_OK; + if(ret == INFO::OK) + return INFO::OK; } } diff --git a/source/lib/res/file/compression.cpp b/source/lib/res/file/compression.cpp index 22803a9b86..8a91692896 100644 --- a/source/lib/res/file/compression.cpp +++ b/source/lib/res/file/compression.cpp @@ -29,6 +29,13 @@ #include "lib/allocators.h" #include "lib/timer.h" #include "compression.h" +#include "file_io.h" // IO_EOF + + +AT_STARTUP(\ + error_setDescription(ERR::COMPRESSION_UNKNOWN_METHOD, "Unknown/unsupported compression method");\ +) + // provision for removing all ZLib code (all inflate calls will fail). // used for checking DLL dependency; might also simulate corrupt Zip files. @@ -66,17 +73,17 @@ static LibError LibError_from_zlib(int zlib_err, bool warn_if_failed = true) switch(zlib_err) { case Z_OK: - return INFO_OK; + return INFO::OK; case Z_STREAM_END: - err = ERR_EOF; break; + err = ERR::IO_EOF; break; case Z_MEM_ERROR: - err = ERR_NO_MEM; break; + err = ERR::NO_MEM; break; case Z_DATA_ERROR: - err = ERR_CORRUPTED; break; + err = ERR::CORRUPTED; break; case Z_STREAM_ERROR: - err = ERR_INVALID_PARAM; break; + err = ERR::INVALID_PARAM; break; default: - err = ERR_FAIL; break; + err = ERR::FAIL; break; } if(warn_if_failed) @@ -112,7 +119,7 @@ public: { next_out = 0; avail_out = 0; - return INFO_OK; + return INFO::OK; } virtual LibError alloc_output(size_t in_size) = 0; @@ -186,7 +193,7 @@ public: { void* cdata_copy = malloc(buf.csize); if(!cdata_copy) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); memcpy2(cdata_copy, buf.cdata, buf.csize); buf.cdata = (const u8*)cdata_copy; } @@ -255,7 +262,7 @@ protected: // .. need to allocate anew out_mem = mem_alloc(alloc_size, 32*KiB); if(!out_mem) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); out_mem_size = alloc_size; have_out_mem: @@ -266,7 +273,7 @@ have_out_mem: next_out = out_mem; avail_out = out_mem_size; - return INFO_OK; + return INFO::OK; } }; // class Compressor @@ -339,10 +346,10 @@ public: { size_t required_size = (size_t)deflateBound(&zs, (uLong)in_size); RETURN_ERR(alloc_output_impl(required_size)); - return INFO_OK; + return INFO::OK; } else - WARN_RETURN(ERR_LOGIC); + WARN_RETURN(ERR::LOGIC); } @@ -396,7 +403,7 @@ public: *out = zs.next_out - zs.total_out; *out_size = zs.total_out; - return INFO_OK; + return INFO::OK; } @@ -443,7 +450,7 @@ uintptr_t comp_alloc(ContextType type, CompressionMethod method) #endif default: compressor_allocator.release(c_mem); - WARN_ERR(ERR_UNKNOWN_CMETHOD); + WARN_ERR(ERR::COMPRESSION_UNKNOWN_METHOD); return 0; } diff --git a/source/lib/res/file/compression.h b/source/lib/res/file/compression.h index ddf692b4c4..3d373e7ee5 100644 --- a/source/lib/res/file/compression.h +++ b/source/lib/res/file/compression.h @@ -24,6 +24,13 @@ #ifndef COMPRESSION_H__ #define COMPRESSION_H__ + +namespace ERR +{ + const LibError COMPRESSION_UNKNOWN_METHOD = -110300; +} + + enum ContextType { CT_COMPRESSION, diff --git a/source/lib/res/file/file.cpp b/source/lib/res/file/file.cpp index a609d36e55..54ce53e3ba 100644 --- a/source/lib/res/file/file.cpp +++ b/source/lib/res/file/file.cpp @@ -36,6 +36,14 @@ #include +AT_STARTUP(\ + error_setDescription(ERR::FILE_ACCESS, "Insufficient access rights to open file");\ + error_setDescription(ERR::DIR_END, "End of directory reached (no more files)");\ + error_setDescription(ERR::FILE_NOT_MAPPED, "File was not mapped");\ + \ + error_setEquivalent(ERR::FILE_ACCESS, EACCES);\ +) + // rationale for aio, instead of only using mmap: // - parallelism: instead of just waiting for the transfer to complete, // other work can be done in the meantime. @@ -80,7 +88,7 @@ static SingleAllocator pp_allocator; // prepare to iterate (once) over entries in the given directory. -// if INFO_OK is returned, is ready for subsequent dir_next_ent calls and +// if INFO::OK is returned, is ready for subsequent dir_next_ent calls and // must be freed via dir_close. LibError dir_open(const char* P_path, DirIterator* di) { @@ -102,7 +110,7 @@ LibError dir_open(const char* P_path, DirIterator* di) pdi->pp = pp_allocator.alloc(); if(!pdi->pp) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); errno = 0; pdi->os_dir = opendir(n_path); @@ -110,12 +118,12 @@ LibError dir_open(const char* P_path, DirIterator* di) return LibError_from_errno(); (void)path_package_set_dir(pdi->pp, n_path); - return INFO_OK; + return INFO::OK; } -// return ERR_DIR_END if all entries have already been returned once, -// another negative error code, or INFO_OK on success, in which case +// return ERR::DIR_END if all entries have already been returned once, +// another negative error code, or INFO::OK on success, in which case // describes the next (order is unspecified) directory entry. LibError dir_next_ent(DirIterator* di, DirEnt* ent) { @@ -128,7 +136,7 @@ get_another_entry: { // no error, just no more entries to return if(!errno) - return ERR_DIR_END; // NOWARN + return ERR::DIR_END; // NOWARN return LibError_from_errno(); } @@ -167,7 +175,7 @@ get_another_entry: ent->size = s.st_size; ent->mtime = s.st_mtime; ent->name = name; - return INFO_OK; + return INFO::OK; } @@ -181,7 +189,7 @@ LibError dir_close(DirIterator* di) errno = 0; if(closedir(pdi->os_dir) < 0) return LibError_from_errno(); - return INFO_OK; + return INFO::OK; } @@ -193,7 +201,7 @@ LibError dir_create(const char* P_path, mode_t mode) struct stat s; int ret = stat(N_path, &s); if(ret == 0) - return INFO_ALREADY_EXISTS; + return INFO::ALREADY_EXISTS; errno = 0; ret = mkdir(N_path, mode); @@ -219,27 +227,27 @@ LibError dir_delete(const char* P_path) { DirEnt ent; ret = dir_next_ent(&di, &ent); - if(ret == ERR_DIR_END) + if(ret == ERR::DIR_END) break; - if(ret != INFO_OK) goto fail; + if(ret != INFO::OK) goto fail; if(DIRENT_IS_DIR(&ent)) { char P_subdir[PATH_MAX]; ret = path_append(P_subdir, P_path, ent.name); - if(ret != INFO_OK) goto fail; + if(ret != INFO::OK) goto fail; ret = dir_delete(P_subdir); - if(ret != INFO_OK) goto fail; + if(ret != INFO::OK) goto fail; } else { ret = path_package_append_file(&N_pp, ent.name); - if(ret != INFO_OK) goto fail; + if(ret != INFO::OK) goto fail; errno = 0; int posix_ret = unlink(N_pp.path); ret = LibError_from_posix(posix_ret); - if(ret != INFO_OK) goto fail; + if(ret != INFO::OK) goto fail; } } @@ -281,7 +289,7 @@ bool file_exists(const char* fn) { struct stat s; const bool warn_if_failed = false; - return file_stat_impl(fn, &s, warn_if_failed) == INFO_OK; + return file_stat_impl(fn, &s, warn_if_failed) == INFO::OK; } @@ -346,17 +354,17 @@ int file_fd_from_PosixFile(File* f) LibError file_validate(const File* f) { if(!f) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); const PosixFile* pf = (PosixFile*)f->opaque; if(pf->fd < 0) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); // mapped but refcount is invalid else if((pf->mapping != 0) ^ (pf->map_refs != 0)) - WARN_RETURN(ERR_2); + WARN_RETURN(ERR::_2); // note: don't check atom_fn - that complains at the end of // file_open if flags & FILE_DONT_SET_FN and has no benefit, really. - return INFO_OK; + return INFO::OK; } @@ -366,7 +374,7 @@ LibError file_open(const char* P_fn, uint flags, File* f) memset(f, 0, sizeof(*f)); if(flags > FILE_FLAG_ALL) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); char N_fn[PATH_MAX]; RETURN_ERR(file_make_full_native_path(P_fn, N_fn)); @@ -383,7 +391,7 @@ LibError file_open(const char* P_fn, uint flags, File* f) // get file size struct stat s; if(stat(N_fn, &s) < 0) - WARN_RETURN(ERR_TNODE_NOT_FOUND); + WARN_RETURN(ERR::TNODE_NOT_FOUND); size = s.st_size; // note: despite increased overhead, the AIO read method is still @@ -397,7 +405,7 @@ LibError file_open(const char* P_fn, uint flags, File* f) // make sure is a regular file if(!S_ISREG(s.st_mode)) - WARN_RETURN(ERR_TNODE_WRONG_TYPE); + WARN_RETURN(ERR::TNODE_WRONG_TYPE); } #if OS_WIN @@ -413,7 +421,7 @@ LibError file_open(const char* P_fn, uint flags, File* f) int fd = open(N_fn, oflag, S_IRWXO|S_IRWXU|S_IRWXG); if(fd < 0) - WARN_RETURN(ERR_FILE_ACCESS); + WARN_RETURN(ERR::FILE_ACCESS); f->flags = flags; f->size = size; @@ -426,7 +434,7 @@ LibError file_open(const char* P_fn, uint flags, File* f) pf->fd = fd; CHECK_FILE(f); - return INFO_OK; + return INFO::OK; } @@ -459,7 +467,7 @@ LibError file_close(File* f) if(f->flags & FILE_WRITE) file_cache_invalidate(f->atom_fn); - return INFO_OK; + return INFO::OK; } @@ -500,7 +508,7 @@ LibError file_map(File* f, void*& p, size_t& size) { // prevent overflow; if we have this many refs, should find out why. if(pf->map_refs >= MAX_MAP_REFS) - WARN_RETURN(ERR_LIMIT); + WARN_RETURN(ERR::LIMIT); pf->map_refs++; goto have_mapping; } @@ -510,7 +518,7 @@ LibError file_map(File* f, void*& p, size_t& size) // then again, don't complain, because this might happen when mounting // a dir containing empty files; each is opened as a Zip file. if(f->size == 0) - return ERR_FAIL; // NOWARN + return ERR::FAIL; // NOWARN errno = 0; pf->mapping = mmap(0, f->size, prot, MAP_PRIVATE, pf->fd, (off_t)0); @@ -522,7 +530,7 @@ LibError file_map(File* f, void*& p, size_t& size) have_mapping: p = pf->mapping; size = f->size; - return INFO_OK; + return INFO::OK; } @@ -539,11 +547,11 @@ LibError file_unmap(File* f) // file is not currently mapped if(pf->map_refs == 0) - WARN_RETURN(ERR_NOT_MAPPED); + WARN_RETURN(ERR::FILE_NOT_MAPPED); // still more than one reference remaining - done. if(--pf->map_refs > 0) - return INFO_OK; + return INFO::OK; // no more references: remove the mapping void* p = pf->mapping; @@ -565,7 +573,7 @@ LibError file_init() // convenience file_sector_size = sys_max_sector_size(); - return INFO_OK; + return INFO::OK; } LibError file_shutdown() @@ -573,5 +581,5 @@ LibError file_shutdown() stats_dump(); path_shutdown(); file_io_shutdown(); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/file/file.h b/source/lib/res/file/file.h index c346a2f74a..a8d5064aaa 100644 --- a/source/lib/res/file/file.h +++ b/source/lib/res/file/file.h @@ -26,6 +26,14 @@ #include "lib/posix.h" // struct stat + +namespace ERR +{ + const LibError FILE_ACCESS = -110000; + const LibError FILE_NOT_MAPPED = -110001; + const LibError DIR_END = -110002; +} + extern LibError file_init(); // used by vfs_redirector to call various file objects' methods. @@ -37,7 +45,7 @@ struct FileProvider_VTbl; // for external libraries that require the real filename. // // replaces '/' with platform's directory separator and vice versa. -// verifies path length < PATH_MAX (otherwise return ERR_PATH_LENGTH). +// verifies path length < PATH_MAX (otherwise return ERR::PATH_LENGTH). // // relative paths (relative to root dir) @@ -137,12 +145,12 @@ struct DirEnt #define DIRENT_IS_DIR(p_ent) ((p_ent)->size == -1) // prepare to iterate (once) over entries in the given directory. -// if INFO_OK is returned, is ready for subsequent dir_next_ent calls and +// if INFO::OK is returned, is ready for subsequent dir_next_ent calls and // must be freed via dir_close. extern LibError dir_open(const char* P_path, DirIterator* d); -// return ERR_DIR_END if all entries have already been returned once, -// another negative error code, or INFO_OK on success, in which case +// return ERR::DIR_END if all entries have already been returned once, +// another negative error code, or INFO::OK on success, in which case // describes the next (order is unspecified) directory entry. extern LibError dir_next_ent(DirIterator* d, DirEnt* ent); @@ -170,7 +178,7 @@ extern LibError file_get_sorted_dirents(const char* P_path, DirEnts& dirents); // called by file_enum for each entry in the directory. // name doesn't include path! -// return INFO_CB_CONTINUE to continue calling; anything else will cause +// return INFO::CB_CONTINUE to continue calling; anything else will cause // file_enum to abort and immediately return that value. typedef LibError (*FileCB)(const char* name, const struct stat* s, uintptr_t memento, const uintptr_t user); @@ -322,122 +330,8 @@ extern LibError file_validate(const File* f); extern LibError file_cache_invalidate(const char* fn); -// -// asynchronous IO -// +#include "file_io.h" -// this is a thin wrapper on top of the system AIO calls. -// IOs are carried out exactly as requested - there is no caching or -// alignment done here. rationale: see source. - -// again chosen for nice alignment; each user checks if big enough. -const size_t FILE_IO_OPAQUE_SIZE = 28; - -struct FileIo -{ - const FileProvider_VTbl* type; - u8 opaque[FILE_IO_OPAQUE_SIZE]; -}; - -// queue the IO; it begins after the previous ones (if any) complete. -// -// rationale: this interface is more convenient than implicitly advancing a -// file pointer because archive.cpp often accesses random offsets. -extern LibError file_io_issue(File* f, off_t ofs, size_t size, void* buf, FileIo* io); - -// indicates if the given IO has completed. -// return value: 0 if pending, 1 if complete, < 0 on error. -extern int file_io_has_completed(FileIo* io); - -// wait for the given IO to complete. passes back its buffer and size. -extern LibError file_io_wait(FileIo* io, void*& p, size_t& size); - -// indicates the IO's buffer is no longer needed and frees that memory. -extern LibError file_io_discard(FileIo* io); - -extern LibError file_io_validate(const FileIo* io); - - -// -// synchronous IO -// - -extern size_t file_sector_size; - -// called by file_io after a block IO has completed. -// *bytes_processed must be set; file_io will return the sum of these values. -// example: when reading compressed data and decompressing in the callback, -// indicate #bytes decompressed. -// return value: INFO_CB_CONTINUE to continue calling; anything else: -// abort immediately and return that. -// note: in situations where the entire IO is not split into blocks -// (e.g. when reading from cache or not using AIO), this is still called but -// for the entire IO. we do not split into fake blocks because it is -// advantageous (e.g. for decompressors) to have all data at once, if available -// anyway. -typedef LibError (*FileIOCB)(uintptr_t ctx, const void* block, size_t size, size_t* bytes_processed); - - -typedef const u8* FileIOBuf; - -FileIOBuf* const FILE_BUF_TEMP = (FileIOBuf*)1; -const FileIOBuf FILE_BUF_ALLOC = (FileIOBuf)2; - - -enum FileBufFlags -{ - // indicates the buffer will not be freed immediately - // (i.e. before the next buffer alloc) as it normally should. - // this flag serves to suppress a warning and better avoid fragmentation. - // caller sets this when FILE_LONG_LIVED is specified. - // - // also used by file_cache_retrieve because it may have to - // 'reactivate' the buffer (transfer from cache to extant list), - // which requires knowing whether the buffer is long-lived or not. - FB_LONG_LIVED = 1, - - // statistics (e.g. # buffer allocs) should not be updated. - // (useful for simulation, e.g. trace_entry_causes_io) - FB_NO_STATS = 2, - - // file_cache_retrieve should not update item credit. - // (useful when just looking up buffer given atom_fn) - FB_NO_ACCOUNTING = 4, - - // memory will be allocated from the heap, not the (limited) file cache. - // this makes sense for write buffers that are never used again, - // because we avoid having to displace some other cached items. - FB_FROM_HEAP = 8 -}; - -// allocate a new buffer of bytes (possibly more due to internal -// fragmentation). never returns 0. -// : owner filename (buffer is intended to be used for data from -// this file). -extern FileIOBuf file_buf_alloc(size_t size, const char* atom_fn, uint fb_flags = 0); - -// mark as no longer needed. if its reference count drops to 0, -// it will be removed from the extant list. if it had been added to the -// cache, it remains there until evicted in favor of another buffer. -extern LibError file_buf_free(FileIOBuf buf, uint fb_flags = 0); - - - -// transfer bytes, starting at , to/from the given file. -// (read or write access was chosen at file-open time). -// -// if non-NULL, is called for each block transferred, passing . -// it returns how much data was actually transferred, or a negative error -// code (in which case we abort the transfer and return that value). -// the callback mechanism is useful for user progress notification or -// processing data while waiting for the next I/O to complete -// (quasi-parallel, without the complexity of threads). -// -// return number of bytes transferred (see above), or a negative error code. -extern ssize_t file_io(File* f, off_t ofs, size_t size, FileIOBuf* pbuf, FileIOCB cb = 0, uintptr_t ctx = 0); - -extern ssize_t file_read_from_cache(const char* atom_fn, off_t ofs, size_t size, - FileIOBuf* pbuf, FileIOCB cb, uintptr_t ctx); // // memory mapping diff --git a/source/lib/res/file/file_cache.cpp b/source/lib/res/file/file_cache.cpp index 9c1367d352..81f3910456 100644 --- a/source/lib/res/file/file_cache.cpp +++ b/source/lib/res/file/file_cache.cpp @@ -1048,7 +1048,7 @@ FileIOBuf file_buf_alloc(size_t size, const char* atom_fn, uint fb_flags) { buf = (FileIOBuf)page_aligned_alloc(size); if(!buf) - WARN_ERR(ERR_NO_MEM); + WARN_ERR(ERR::NO_MEM); } else buf = cache_alloc(size); @@ -1070,7 +1070,7 @@ LibError file_buf_free(FileIOBuf buf, uint fb_flags) const bool from_heap = (fb_flags & FB_FROM_HEAP) != 0; if(!buf) - return INFO_OK; + return INFO::OK; size_t size; const char* atom_fn; bool actually_removed = extant_bufs.find_and_remove(buf, size, atom_fn); @@ -1107,7 +1107,7 @@ free_immediately: stats_buf_free(); trace_notify_free(atom_fn, size); - return INFO_OK; + return INFO::OK; } @@ -1137,7 +1137,7 @@ LibError file_buf_set_real_fn(FileIOBuf buf, const char* atom_fn) // note: removing and reinserting would be easiest, but would // mess up the epoch field. extant_bufs.replace_owner(buf, atom_fn); - return INFO_OK; + return INFO::OK; } @@ -1171,7 +1171,7 @@ LibError file_cache_add(FileIOBuf buf, size_t size, const char* atom_fn, debug_assert(buf); if(!file_cache_would_add(size, atom_fn, file_flags)) - return INFO_SKIPPED; + return INFO::SKIPPED; // assign cost uint cost = 1; @@ -1182,7 +1182,7 @@ LibError file_cache_add(FileIOBuf buf, size_t size, const char* atom_fn, file_cache.add(atom_fn, buf, size, cost); - return INFO_OK; + return INFO::OK; } @@ -1247,7 +1247,7 @@ LibError file_cache_invalidate(const char* P_fn) free_padded_buf(cached_buf, size); } - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/file/file_internal.h b/source/lib/res/file/file_internal.h index 535d64b0fd..eaa0fb3b5d 100644 --- a/source/lib/res/file/file_internal.h +++ b/source/lib/res/file/file_internal.h @@ -57,7 +57,7 @@ const size_t FILE_BLOCK_SIZE = 32*KiB; // helper routine used by functions that call back to a FileIOCB. // -// bytes_processed is 0 if return value != { INFO_OK, INFO_CB_CONTINUE } +// bytes_processed is 0 if return value != { INFO::OK, INFO::CB_CONTINUE } // note: don't abort if = 0: zip callback may not actually // output anything if passed very little data. extern LibError file_io_call_back(const void* block, size_t size, @@ -65,7 +65,7 @@ extern LibError file_io_call_back(const void* block, size_t size, // retrieve the next (order is unspecified) dir entry matching . -// return 0 on success, ERR_DIR_END if no matching entry was found, +// return 0 on success, ERR::DIR_END if no matching entry was found, // or a negative error code on failure. // filter values: // - 0: anything; @@ -74,7 +74,7 @@ extern LibError file_io_call_back(const void* block, size_t size, // - : any file whose name matches; ? and * wildcards are allowed. // // note that the directory entries are only scanned once; after the -// end is reached (-> ERR_DIR_END returned), no further entries can +// end is reached (-> ERR::DIR_END returned), no further entries can // be retrieved, even if filter changes (which shouldn't happen - see impl). // // rationale: we do not sort directory entries alphabetically here. diff --git a/source/lib/res/file/file_io.cpp b/source/lib/res/file/file_io.cpp index efcd0ffa1e..65a5a4541a 100644 --- a/source/lib/res/file/file_io.cpp +++ b/source/lib/res/file/file_io.cpp @@ -31,6 +31,14 @@ #include "file_internal.h" +AT_STARTUP(\ + error_setDescription(ERR::IO, "Error during IO");\ + error_setDescription(ERR::IO_EOF, "Reading beyond end of file");\ + \ + error_setEquivalent(ERR::IO, EIO);\ +) + + //----------------------------------------------------------------------------- // async I/O //----------------------------------------------------------------------------- @@ -106,7 +114,7 @@ LibError file_io_issue(File* f, off_t ofs, size_t size, void* p, FileIo* io) // check params CHECK_FILE(f); if(!size || !p || !io) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); const bool is_write = (f->flags & FILE_WRITE) != 0; PosixFileIo* pio = (PosixFileIo*)io; @@ -130,7 +138,7 @@ LibError file_io_issue(File* f, off_t ofs, size_t size, void* p, FileIo* io) aiocb* cb = aiocb_allocator.alloc(); pio->cb = cb; if(!cb) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); memset(cb, 0, sizeof(*cb)); // send off async read/write request @@ -150,7 +158,7 @@ LibError file_io_issue(File* f, off_t ofs, size_t size, void* p, FileIo* io) const BlockId disk_pos = block_cache_make_id(f->atom_fn, ofs); stats_io_check_seek(disk_pos); - return INFO_OK; + return INFO::OK; } @@ -166,7 +174,7 @@ int file_io_has_completed(FileIo* io) if(ret == 0) return 1; - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); } @@ -197,7 +205,7 @@ LibError file_io_wait(FileIo* io, void*& p, size_t& size) p = (void*)cb->aio_buf; // cast from volatile void* size = bytes_transferred; - return INFO_OK; + return INFO::OK; } @@ -207,7 +215,7 @@ LibError file_io_discard(FileIo* io) memset(pio->cb, 0, sizeof(aiocb)); // prevent further use. aiocb_allocator.free_(pio->cb); pio->cb = 0; - return INFO_OK; + return INFO::OK; } @@ -218,13 +226,13 @@ LibError file_io_validate(const FileIo* io) // >= 0x100 is not necessarily bogus, but suspicious. // this also catches negative values. if((uint)cb->aio_fildes >= 0x100) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); if(debug_is_pointer_bogus((void*)cb->aio_buf)) - WARN_RETURN(ERR_2); + WARN_RETURN(ERR::_2); if(cb->aio_lio_opcode != LIO_WRITE && cb->aio_lio_opcode != LIO_READ && cb->aio_lio_opcode != LIO_NOP) - WARN_RETURN(ERR_3); + WARN_RETURN(ERR::_3); // all other aiocb fields have no invariants we could check. - return INFO_OK; + return INFO::OK; } @@ -253,7 +261,7 @@ size_t file_sector_size; // helper routine used by functions that call back to a FileIOCB. // -// bytes_processed is 0 if return value != { INFO_OK, INFO_CB_CONTINUE } +// bytes_processed is 0 if return value != { INFO::OK, INFO::CB_CONTINUE } // note: don't abort if = 0: zip callback may not actually // output anything if passed very little data. LibError file_io_call_back(const void* block, size_t size, @@ -266,7 +274,7 @@ LibError file_io_call_back(const void* block, size_t size, stats_cb_finish(); // failed - reset byte count in case callback didn't - if(ret != INFO_OK && ret != INFO_CB_CONTINUE) + if(ret != INFO::OK && ret != INFO::CB_CONTINUE) bytes_processed = 0; CHECK_ERR(ret); // user might not have raised a warning; make sure @@ -276,7 +284,7 @@ LibError file_io_call_back(const void* block, size_t size, else { bytes_processed = size; - return INFO_CB_CONTINUE; + return INFO::CB_CONTINUE; } } @@ -297,22 +305,22 @@ LibError file_io_get_buf(FileIOBuf* pbuf, size_t size, // reading into temp buffers - ok. if(!is_write && temp && cb != 0) - return INFO_OK; + return INFO::OK; // reading and want buffer allocated. if(!is_write && alloc) { *pbuf = file_buf_alloc(size, atom_fn, fb_flags); if(!*pbuf) // very unlikely (size totally bogus or cache hosed) - WARN_RETURN(ERR_NO_MEM); - return INFO_OK; + WARN_RETURN(ERR::NO_MEM); + return INFO::OK; } // writing from user-specified buffer - ok if(is_write && user) - return INFO_OK; + return INFO::OK; - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); } @@ -389,7 +397,7 @@ class IOManager { dst_mem = malloc(size); if(!dst_mem) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); dst = dst_mem; } else @@ -436,7 +444,7 @@ class IOManager // but cut off at EOF (necessary to prevent IO error). const off_t bytes_left = f->size - start_ofs; if(bytes_left < 0) - WARN_RETURN(ERR_EOF); + WARN_RETURN(ERR::IO_EOF); size = MIN(size, (size_t)bytes_left); // and round back up to sector size. @@ -446,7 +454,7 @@ class IOManager RETURN_ERR(file_io_get_buf(pbuf, size, f->atom_fn, f->flags, cb)); - return INFO_OK; + return INFO::OK; } void issue(IOSlot& slot) @@ -474,7 +482,7 @@ class IOManager LibError ret = file_io_issue(f, ofs, issue_size, buf, &slot.io); // transfer failed - loop will now terminate after // waiting for all pending transfers to complete. - if(ret != INFO_OK) + if(ret != INFO::OK) err = ret; } @@ -529,11 +537,11 @@ class IOManager void process(IOSlot& slot, void* block, size_t block_size, FileIOCB cb, uintptr_t ctx) { - if(err == INFO_CB_CONTINUE) + if(err == INFO::CB_CONTINUE) { size_t bytes_processed; err = file_io_call_back(block, block_size, cb, ctx, bytes_processed); - if(err == INFO_CB_CONTINUE || err == INFO_OK) + if(err == INFO::CB_CONTINUE || err == INFO::OK) total_processed += bytes_processed; // else: processing failed. // loop will now terminate after waiting for all @@ -558,7 +566,7 @@ again: { // data remaining to transfer, and no error: // start transferring next block. - if(total_issued < size && err == INFO_CB_CONTINUE && queue.size() < MAX_PENDING_IOS) + if(total_issued < size && err == INFO::CB_CONTINUE && queue.size() < MAX_PENDING_IOS) { queue.push_back(IOSlot()); IOSlot& slot = queue.back(); @@ -601,7 +609,7 @@ public: total_issued = 0; total_transferred = 0; total_processed = 0; - err = INFO_CB_CONTINUE; + err = INFO::CB_CONTINUE; } // now we read the file in 64 KiB chunks, N-buffered. @@ -626,7 +634,7 @@ public: file_buf_add_padding(org_buf, size, ofs_misalign); } - if(err != INFO_CB_CONTINUE && err != INFO_OK) + if(err != INFO::CB_CONTINUE && err != INFO::OK) return (ssize_t)err; return bytes_transferred; } diff --git a/source/lib/res/file/file_io.h b/source/lib/res/file/file_io.h index 3be2bad96b..152065f98a 100644 --- a/source/lib/res/file/file_io.h +++ b/source/lib/res/file/file_io.h @@ -23,9 +23,138 @@ #ifndef FILE_IO_H__ #define FILE_IO_H__ +struct FileProvider_VTbl; +struct File; + + +namespace ERR +{ + const LibError IO = -110100; + const LibError IO_EOF = -110101; +} + + extern void file_io_init(); extern void file_io_shutdown(); + +// +// asynchronous IO +// + +// this is a thin wrapper on top of the system AIO calls. +// IOs are carried out exactly as requested - there is no caching or +// alignment done here. rationale: see source. + +// again chosen for nice alignment; each user checks if big enough. +const size_t FILE_IO_OPAQUE_SIZE = 28; + +struct FileIo +{ + const FileProvider_VTbl* type; + u8 opaque[FILE_IO_OPAQUE_SIZE]; +}; + +// queue the IO; it begins after the previous ones (if any) complete. +// +// rationale: this interface is more convenient than implicitly advancing a +// file pointer because archive.cpp often accesses random offsets. +extern LibError file_io_issue(File* f, off_t ofs, size_t size, void* buf, FileIo* io); + +// indicates if the given IO has completed. +// return value: 0 if pending, 1 if complete, < 0 on error. +extern int file_io_has_completed(FileIo* io); + +// wait for the given IO to complete. passes back its buffer and size. +extern LibError file_io_wait(FileIo* io, void*& p, size_t& size); + +// indicates the IO's buffer is no longer needed and frees that memory. +extern LibError file_io_discard(FileIo* io); + +extern LibError file_io_validate(const FileIo* io); + + +// +// synchronous IO +// + +extern size_t file_sector_size; + +// called by file_io after a block IO has completed. +// *bytes_processed must be set; file_io will return the sum of these values. +// example: when reading compressed data and decompressing in the callback, +// indicate #bytes decompressed. +// return value: INFO::CB_CONTINUE to continue calling; anything else: +// abort immediately and return that. +// note: in situations where the entire IO is not split into blocks +// (e.g. when reading from cache or not using AIO), this is still called but +// for the entire IO. we do not split into fake blocks because it is +// advantageous (e.g. for decompressors) to have all data at once, if available +// anyway. +typedef LibError (*FileIOCB)(uintptr_t ctx, const void* block, size_t size, size_t* bytes_processed); + + +typedef const u8* FileIOBuf; + +FileIOBuf* const FILE_BUF_TEMP = (FileIOBuf*)1; +const FileIOBuf FILE_BUF_ALLOC = (FileIOBuf)2; + + +enum FileBufFlags +{ + // indicates the buffer will not be freed immediately + // (i.e. before the next buffer alloc) as it normally should. + // this flag serves to suppress a warning and better avoid fragmentation. + // caller sets this when FILE_LONG_LIVED is specified. + // + // also used by file_cache_retrieve because it may have to + // 'reactivate' the buffer (transfer from cache to extant list), + // which requires knowing whether the buffer is long-lived or not. + FB_LONG_LIVED = 1, + + // statistics (e.g. # buffer allocs) should not be updated. + // (useful for simulation, e.g. trace_entry_causes_io) + FB_NO_STATS = 2, + + // file_cache_retrieve should not update item credit. + // (useful when just looking up buffer given atom_fn) + FB_NO_ACCOUNTING = 4, + + // memory will be allocated from the heap, not the (limited) file cache. + // this makes sense for write buffers that are never used again, + // because we avoid having to displace some other cached items. + FB_FROM_HEAP = 8 +}; + +// allocate a new buffer of bytes (possibly more due to internal +// fragmentation). never returns 0. +// : owner filename (buffer is intended to be used for data from +// this file). +extern FileIOBuf file_buf_alloc(size_t size, const char* atom_fn, uint fb_flags = 0); + +// mark as no longer needed. if its reference count drops to 0, +// it will be removed from the extant list. if it had been added to the +// cache, it remains there until evicted in favor of another buffer. +extern LibError file_buf_free(FileIOBuf buf, uint fb_flags = 0); + + +// transfer bytes, starting at , to/from the given file. +// (read or write access was chosen at file-open time). +// +// if non-NULL, is called for each block transferred, passing . +// it returns how much data was actually transferred, or a negative error +// code (in which case we abort the transfer and return that value). +// the callback mechanism is useful for user progress notification or +// processing data while waiting for the next I/O to complete +// (quasi-parallel, without the complexity of threads). +// +// return number of bytes transferred (see above), or a negative error code. +extern ssize_t file_io(File* f, off_t ofs, size_t size, FileIOBuf* pbuf, FileIOCB cb = 0, uintptr_t ctx = 0); + +extern ssize_t file_read_from_cache(const char* atom_fn, off_t ofs, size_t size, + FileIOBuf* pbuf, FileIOCB cb, uintptr_t ctx); + + extern LibError file_io_get_buf(FileIOBuf* pbuf, size_t size, const char* atom_fn, uint file_flags, FileIOCB cb); diff --git a/source/lib/res/file/file_util.cpp b/source/lib/res/file/file_util.cpp index 42821b09ff..54da9c6676 100644 --- a/source/lib/res/file/file_util.cpp +++ b/source/lib/res/file/file_util.cpp @@ -22,7 +22,7 @@ LibError file_get_sorted_dirents(const char* P_path, DirEnts& dirents) for(;;) { LibError ret = dir_next_ent(&d, &ent); - if(ret == ERR_DIR_END) + if(ret == ERR::DIR_END) break; RETURN_ERR(ret); @@ -33,7 +33,7 @@ LibError file_get_sorted_dirents(const char* P_path, DirEnts& dirents) std::sort(dirents.begin(), dirents.end(), dirent_less); (void)dir_close(&d); - return INFO_OK; + return INFO::OK; } @@ -55,8 +55,8 @@ LibError file_get_sorted_dirents(const char* P_path, DirEnts& dirents) // of converting from/to native path (we just give 'em the dirent name). LibError file_enum(const char* P_path, const FileCB cb, const uintptr_t user) { - LibError stat_err = INFO_OK; // first error encountered by stat() - LibError cb_err = INFO_OK; // first error returned by cb + LibError stat_err = INFO::OK; // first error encountered by stat() + LibError cb_err = INFO::OK; // first error returned by cb DirEnts dirents; RETURN_ERR(file_get_sorted_dirents(P_path, dirents)); @@ -75,14 +75,14 @@ LibError file_enum(const char* P_path, const FileCB cb, const uintptr_t user) s.st_size = dirent.size; s.st_mtime = dirent.mtime; LibError ret = cb(dirent.name, &s, memento, user); - if(ret != INFO_CB_CONTINUE) + if(ret != INFO::CB_CONTINUE) { cb_err = ret; // first error (since we now abort) break; } } - if(cb_err != INFO_OK) + if(cb_err != INFO::OK) return cb_err; return stat_err; } @@ -90,7 +90,7 @@ LibError file_enum(const char* P_path, const FileCB cb, const uintptr_t user) // retrieve the next (order is unspecified) dir entry matching . -// return 0 on success, ERR_DIR_END if no matching entry was found, +// return 0 on success, ERR::DIR_END if no matching entry was found, // or a negative error code on failure. // filter values: // - 0: anything; @@ -99,7 +99,7 @@ LibError file_enum(const char* P_path, const FileCB cb, const uintptr_t user) // - : any file whose name matches; ? and * wildcards are allowed. // // note that the directory entries are only scanned once; after the -// end is reached (-> ERR_DIR_END returned), no further entries can +// end is reached (-> ERR::DIR_END returned), no further entries can // be retrieved, even if filter changes (which shouldn't happen - see impl). // // rationale: we do not sort directory entries alphabetically here. @@ -154,7 +154,7 @@ LibError dir_filtered_next_ent(DirIterator* di, DirEnt* ent, const char* filter) } } - return INFO_OK; + return INFO::OK; } @@ -234,7 +234,7 @@ LibError vfs_dir_enum(const char* start_path, uint flags, const char* user_filte } while(!dir_queue.empty()); - return INFO_OK; + return INFO::OK; } @@ -271,7 +271,7 @@ void next_numbered_filename(const char* fn_fmt, Handle hd = vfs_dir_open(dir); if(hd > 0) { - while(vfs_dir_next_ent(hd, &ent, 0) == INFO_OK) + while(vfs_dir_next_ent(hd, &ent, 0) == INFO::OK) { if(!DIRENT_IS_DIR(&ent) && sscanf(ent.name, name_fmt, &num) == 1) max_num = MAX(num, max_num); @@ -282,9 +282,9 @@ void next_numbered_filename(const char* fn_fmt, else { DirIterator it; - if(dir_open(dir, &it) == INFO_OK) + if(dir_open(dir, &it) == INFO::OK) { - while(dir_next_ent(&it, &ent) == INFO_OK) + while(dir_next_ent(&it, &ent) == INFO::OK) if(!DIRENT_IS_DIR(&ent) && sscanf(ent.name, name_fmt, &num) == 1) max_num = MAX(num, max_num); (void)dir_close(&it); diff --git a/source/lib/res/file/path.cpp b/source/lib/res/file/path.cpp index e0a42f3b4d..ed72903da3 100644 --- a/source/lib/res/file/path.cpp +++ b/source/lib/res/file/path.cpp @@ -30,6 +30,11 @@ #include "lib/allocators.h" +AT_STARTUP(\ + error_setDescription(ERR::ROOT_DIR_ALREADY_SET, "Attempting to set FS root dir more than once");\ +) + + // path types: // p_*: posix (e.g. mount object name or for open()) // v_*: vfs (e.g. mount point) @@ -45,7 +50,6 @@ // file ::= name // name ::= [^/] - enum Conversion { TO_NATIVE, @@ -69,7 +73,7 @@ static LibError convert_path(char* dst, const char* src, Conversion conv = TO_NA { len++; if(len >= PATH_MAX) - WARN_RETURN(ERR_PATH_LENGTH); + WARN_RETURN(ERR::PATH_LENGTH); char c = *s++; @@ -80,7 +84,7 @@ static LibError convert_path(char* dst, const char* src, Conversion conv = TO_NA // end of string - done if(c == '\0') - return INFO_OK; + return INFO::OK; } } @@ -129,7 +133,7 @@ LibError file_make_full_portable_path(const char* n_full_path, char* path) debug_assert(path != n_full_path); // doesn't work in-place if(strncmp(n_full_path, n_root_dir, n_root_dir_len) != 0) - WARN_RETURN(ERR_TNODE_NOT_FOUND); + WARN_RETURN(ERR::TNODE_NOT_FOUND); return convert_path(path, n_full_path+n_root_dir_len, TO_PORTABLE); } @@ -156,7 +160,7 @@ LibError file_set_root_dir(const char* argv0, const char* rel_path) // are likely bogus. static bool already_attempted; if(already_attempted) - WARN_RETURN(ERR_ROOT_DIR_ALREADY_SET); + WARN_RETURN(ERR::ROOT_DIR_ALREADY_SET); already_attempted = true; // get full path to executable @@ -185,7 +189,7 @@ LibError file_set_root_dir(const char* argv0, const char* rel_path) // (note: already 0-terminated, since it's static) n_root_dir_len = strlen(n_root_dir)+1; // +1 for trailing DIR_SEP n_root_dir[n_root_dir_len-1] = DIR_SEP; - return INFO_OK; + return INFO::OK; } @@ -233,7 +237,7 @@ const char* file_make_unique_fn_copy(const char* P_fn) unique_fn = (const char*)pool_alloc(&atom_pool, fn_len+1); if(!unique_fn) { - DEBUG_WARN_ERR(ERR_NO_MEM); + DEBUG_WARN_ERR(ERR::NO_MEM); return 0; } memcpy2((void*)unique_fn, P_fn, fn_len); diff --git a/source/lib/res/file/path.h b/source/lib/res/file/path.h index 22675f2a9c..beed66b3ec 100644 --- a/source/lib/res/file/path.h +++ b/source/lib/res/file/path.h @@ -25,6 +25,13 @@ #include "lib/lib.h" + +namespace ERR +{ + const LibError ROOT_DIR_ALREADY_SET = -110200; +} + + #define VFS_PATH_IS_DIR(path) (*path == '\0' || path[strlen(path)-1] == '/') struct NextNumberedFilenameInfo diff --git a/source/lib/res/file/trace.cpp b/source/lib/res/file/trace.cpp index e7e60975d6..aa2dd14a44 100644 --- a/source/lib/res/file/trace.cpp +++ b/source/lib/res/file/trace.cpp @@ -28,6 +28,12 @@ #include "lib/sysdep/cpu.h" #include "file_internal.h" + +AT_STARTUP(\ + error_setDescription(ERR::TRACE_EMPTY, "No valid entries in trace");\ +) + + static uintptr_t trace_initialized; // set via CAS static Pool trace_pool; @@ -70,20 +76,20 @@ static LibError trace_add(TraceOp op, const char* P_fn, size_t size, { trace_init(); if(!trace_enabled) - return INFO_OK; + return INFO::OK; if(timestamp == 0.0) timestamp = get_time(); TraceEntry* t = (TraceEntry*)pool_alloc(&trace_pool, 0); if(!t) - return ERR_LIMIT; // NOWARN + return ERR::LIMIT; // NOWARN t->timestamp = timestamp; t->atom_fn = file_make_unique_fn_copy(P_fn); t->size = size; t->op = op; t->flags = flags; - return INFO_OK; + return INFO::OK; } static void trace_get_raw_ents(const TraceEntry*& ents, size_t& num_ents) @@ -238,7 +244,7 @@ static void write_entry(FILE* f, const TraceEntry* ent) LibError trace_write_to_file(const char* trace_filename) { if(!trace_enabled) - return INFO_SKIPPED; + return INFO::SKIPPED; char N_fn[PATH_MAX]; RETURN_ERR(file_make_full_native_path(trace_filename, N_fn)); @@ -247,7 +253,7 @@ LibError trace_write_to_file(const char* trace_filename) // several trace runs per file. FILE* f = fopen(N_fn, "at"); if(!f) - WARN_RETURN(ERR_FILE_ACCESS); + WARN_RETURN(ERR::FILE_ACCESS); write_entry(f, &delimiter_entry); @@ -259,7 +265,7 @@ LibError trace_write_to_file(const char* trace_filename) write_entry(f, ent); (void)fclose(f); - return INFO_OK; + return INFO::OK; } @@ -271,7 +277,7 @@ LibError trace_read_from_file(const char* trace_filename, Trace* t) RETURN_ERR(file_make_full_native_path(trace_filename, N_fn)); FILE* f = fopen(N_fn, "rt"); if(!f) - WARN_RETURN(ERR_TNODE_NOT_FOUND); + WARN_RETURN(ERR::TNODE_NOT_FOUND); // we use trace_add, which is the same mechanism called by trace_notify*; // therefore, tracing needs to be enabled. @@ -306,7 +312,7 @@ LibError trace_read_from_file(const char* trace_filename, Trace* t) // storage in trace pool exhausted. must abort to avoid later // adding delimiters for items that weren't actually stored // into the pool. - if(ret == ERR_LIMIT) + if(ret == ERR::LIMIT) break; } } @@ -320,9 +326,9 @@ LibError trace_read_from_file(const char* trace_filename, Trace* t) trace_enabled = false; if(t->total_ents == 0) - WARN_RETURN(ERR_TRACE_EMPTY); + WARN_RETURN(ERR::TRACE_EMPTY); - return INFO_OK; + return INFO::OK; } @@ -346,7 +352,7 @@ void trace_gen_random(size_t num_entries) struct stat s; LibError ret = vfs_stat(atom_fn, &s); // ought to apply due to vfs_exists above. - debug_assert(ret == INFO_OK && S_ISREG(s.st_mode)); + debug_assert(ret == INFO::OK && S_ISREG(s.st_mode)); size = s.st_size; break; @@ -402,7 +408,7 @@ bool trace_entry_causes_io(const TraceEntry* ent) // since TO_FREE below uses the cache to find out which // buffer was allocated for atom_fn, we have to free it manually. // see note above. - if(ret == INFO_SKIPPED) + if(ret == INFO::SKIPPED) (void)file_buf_free(buf, fb_flags); return true; } @@ -474,6 +480,6 @@ LibError trace_run(const char* trace_filename, uint flags) trace_clear(); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/file/trace.h b/source/lib/res/file/trace.h index 432f8ffd0f..2bb6661508 100644 --- a/source/lib/res/file/trace.h +++ b/source/lib/res/file/trace.h @@ -24,6 +24,11 @@ #ifndef TRACE_H__ #define TRACE_H__ +namespace ERR +{ + const LibError TRACE_EMPTY = -110500; +} + extern void trace_enable(bool want_enabled); extern void trace_shutdown(); diff --git a/source/lib/res/file/vfs.cpp b/source/lib/res/file/vfs.cpp index a479c5adf7..b14659732f 100644 --- a/source/lib/res/file/vfs.cpp +++ b/source/lib/res/file/vfs.cpp @@ -119,15 +119,15 @@ static LibError VDir_reload(VDir* vd, const char* V_dir_path, Handle UNUSED(hvd) RETURN_ERR(xdir_open(V_dir_path, &vd->di)); vd->di_valid = 1; - return INFO_OK; + return INFO::OK; } static LibError VDir_validate(const VDir* vd) { // note: is mostly opaque and cannot be validated. if(vd->di.filter && !isprint(vd->di.filter[0])) - WARN_RETURN(ERR_1); - return INFO_OK; + WARN_RETURN(ERR::_1); + return INFO::OK; } static LibError VDir_to_string(const VDir* vd, char* buf) @@ -138,7 +138,7 @@ static LibError VDir_to_string(const VDir* vd, char* buf) if(!filter) filter = "*"; snprintf(buf, H_STRING_LEN, "(\"%s\")", filter); - return INFO_OK; + return INFO::OK; } @@ -160,7 +160,7 @@ LibError vfs_dir_close(Handle& hd) // retrieve the next (order is unspecified) dir entry matching . -// return 0 on success, ERR_DIR_END if no matching entry was found, +// return 0 on success, ERR::DIR_END if no matching entry was found, // or a negative error code on failure. // filter values: // - 0: anything; @@ -169,7 +169,7 @@ LibError vfs_dir_close(Handle& hd) // - : any file whose name matches; ? and * wildcards are allowed. // // note that the directory entries are only scanned once; after the -// end is reached (-> ERR_DIR_END returned), no further entries can +// end is reached (-> ERR::DIR_END returned), no further entries can // be retrieved, even if filter changes (which shouldn't happen - see impl). // // rationale: we do not sort directory entries alphabetically here. @@ -275,7 +275,7 @@ static LibError VFile_reload(VFile* vf, const char* V_path, Handle) // we're done if file is already open. need to check this because // reload order (e.g. if resource opens a file) is unspecified. if(xfile_is_open(&vf->f)) - return INFO_OK; + return INFO::OK; TFile* tf; uint lf = (flags & FILE_WRITE)? LF_CREATE_MISSING : 0; @@ -300,20 +300,20 @@ static LibError VFile_reload(VFile* vf, const char* V_path, Handle) vf->is_valid = 1; vf->tf = tf; - return INFO_OK; + return INFO::OK; } static LibError VFile_validate(const VFile* vf) { // doesn't have any invariant we can check. RETURN_ERR(xfile_validate(&vf->f)); - return INFO_OK; + return INFO::OK; } static LibError VFile_to_string(const VFile* UNUSED(vf), char* buf) { strcpy(buf, ""); // safe - return INFO_OK; + return INFO::OK; } @@ -418,8 +418,8 @@ LibError vfs_load(const char* V_fn, FileIOBuf& buf, size_t& size, // we don't care if the cb has "had enough" or whether it would // accept more data - this is all it gets and we need to // translate return value to avoid confusing callers. - if(ret == INFO_CB_CONTINUE) - ret = INFO_OK; + if(ret == INFO::CB_CONTINUE) + ret = INFO::OK; size = actual_size; return ret; } @@ -448,7 +448,7 @@ LibError vfs_load(const char* V_fn, FileIOBuf& buf, size_t& size, stats_cache(CR_MISS, size, atom_fn); (void)vfs_close(hf); - return INFO_OK; + return INFO::OK; } @@ -519,17 +519,17 @@ static LibError VIo_reload(VIo* vio, const char* UNUSED(fn), Handle UNUSED(h)) static LibError VIo_validate(const VIo* vio) { if(vio->hf < 0) - WARN_RETURN(ERR_21); + WARN_RETURN(ERR::_21); // doesn't have any invariant we can check. if(debug_is_pointer_bogus(vio->buf)) - WARN_RETURN(ERR_22); + WARN_RETURN(ERR::_22); return xfile_io_validate(&vio->io); } static LibError VIo_to_string(const VIo* vio, char* buf) { snprintf(buf, H_STRING_LEN, "buf=%p size=%d", vio->buf, vio->size); - return INFO_OK; + return INFO::OK; } @@ -621,7 +621,7 @@ static LibError reload_without_rebuild(const char* fn) RETURN_ERR(h_reload(fn)); - return INFO_OK; + return INFO::OK; } @@ -696,7 +696,7 @@ LibError vfs_reload_changed_files() // get next notification char N_path[PATH_MAX]; LibError ret = dir_get_changed_file(N_path); - if(ret == ERR_AGAIN) // none available; done. + if(ret == ERR::AGAIN) // none available; done. break; RETURN_ERR(ret); @@ -726,7 +726,7 @@ LibError vfs_reload_changed_files() for(uint i = 0; i < num_pending; i++) RETURN_ERR(reload_without_rebuild(pending_reloads[i])); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/file/vfs.h b/source/lib/res/file/vfs.h index 5b617fd3fd..31067a76e6 100644 --- a/source/lib/res/file/vfs.h +++ b/source/lib/res/file/vfs.h @@ -300,7 +300,7 @@ extern Handle vfs_dir_open(const char* V_dir_path); extern LibError vfs_dir_close(Handle& hd); // retrieve the next (order is unspecified) dir entry matching . -// return 0 on success, ERR_DIR_END if no matching entry was found, +// return 0 on success, ERR::DIR_END if no matching entry was found, // or a negative error code on failure. // filter values: // - 0: anything; @@ -309,7 +309,7 @@ extern LibError vfs_dir_close(Handle& hd); // - : any file whose name matches; ? and * wildcards are allowed. // // note that the directory entries are only scanned once; after the -// end is reached (-> ERR_DIR_END returned), no further entries can +// end is reached (-> ERR::DIR_END returned), no further entries can // be retrieved, even if filter changes (which shouldn't happen - see impl). // // see also the definition of DirEnt in file.h. diff --git a/source/lib/res/file/vfs_mount.cpp b/source/lib/res/file/vfs_mount.cpp index 4e3ee09e9a..965d65b397 100644 --- a/source/lib/res/file/vfs_mount.cpp +++ b/source/lib/res/file/vfs_mount.cpp @@ -33,6 +33,7 @@ #include #include + // location of a file: either archive or a real directory. // not many instances => don't worry about efficiency. struct Mount @@ -184,7 +185,7 @@ LibError mount_realpath(const char* V_path, const Mount* m, char* P_real_path) if(P_len != 0 && P_real_path[P_len-1] == '/') P_real_path[P_len-1] = '\0'; - return INFO_OK; + return INFO::OK; } @@ -264,7 +265,7 @@ static LibError afile_cb(const char* atom_fn, const struct stat* s, uintptr_t me WARN_ERR(tree_add_file(td, name, m, s->st_size, s->st_mtime, memento)); vfs_opt_notify_non_loose_file(atom_fn); - return INFO_CB_CONTINUE; + return INFO::CB_CONTINUE; } @@ -278,7 +279,7 @@ static bool archive_less(Handle hza1, Handle hza2) typedef std::vector Archives; typedef Archives::const_iterator ArchiveCIt; -// return value is INFO_OK iff archives != 0 and the file should not be +// return value is INFO::OK iff archives != 0 and the file should not be // added to VFS (e.g. because it is an archive). static LibError enqueue_archive(const char* name, const char* P_archive_dir, Archives* archives) { @@ -286,7 +287,7 @@ static LibError enqueue_archive(const char* name, const char* P_archive_dir, Arc // case in all subdirectories of the mount point, since checking for all // mounted files would be slow. see mount_dir_tree. if(!archives) - return INFO_SKIPPED; + return INFO::SKIPPED; // get complete path for archive_open. // this doesn't (need to) work for subdirectories of the mounted td! @@ -301,30 +302,30 @@ static LibError enqueue_archive(const char* name, const char* P_archive_dir, Arc // .. special case: is recognizable as a Zip file but is // invalid and can't be opened. avoid adding it to // archive list and/or VFS. - if(archive == ERR_CORRUPTED) + if(archive == ERR::CORRUPTED) goto do_not_add_to_VFS_or_list; RETURN_ERR(archive); archives->push_back(archive); // avoid also adding the archive file itself to VFS. - // (when caller sees INFO_OK, they skip the file) + // (when caller sees INFO::OK, they skip the file) do_not_add_to_VFS_or_list: - return INFO_OK; + return INFO::OK; } static LibError mount_archive(TDir* td, const Mount& m) { ZipCBParams params(td, &m); archive_enum(m.archive, afile_cb, (uintptr_t)¶ms); - return INFO_OK; + return INFO::OK; } static LibError mount_archives(TDir* td, Archives* archives, const Mount* mount) { // VFS_MOUNT_ARCHIVES flag wasn't set, or no archives present if(archives->empty()) - return INFO_OK; + return INFO::OK; std::sort(archives->begin(), archives->end(), archive_less); @@ -339,7 +340,7 @@ static LibError mount_archives(TDir* td, Archives* archives, const Mount* mount) mount_archive(td, m); } - return INFO_OK; + return INFO::OK; } @@ -373,7 +374,7 @@ static LibError enqueue_dir(TDir* parent_td, const char* name, { // caller doesn't want us to enqueue subdirectories; bail. if(!dir_queue) - return INFO_OK; + return INFO::OK; // skip versioning system directories - this avoids cluttering the // VFS with hundreds of irrelevant files. @@ -381,7 +382,7 @@ static LibError enqueue_dir(TDir* parent_td, const char* name, // strstr the entire path) and it is assumed the Zip file builder // will take care of it. if(!strcmp(name, "CVS") || !strcmp(name, ".svn")) - return INFO_OK; + return INFO::OK; // prepend parent path to get complete pathname. char P_path[PATH_MAX]; @@ -392,7 +393,7 @@ static LibError enqueue_dir(TDir* parent_td, const char* name, CHECK_ERR(tree_add_dir(parent_td, name, &td)); // .. and add it to the list of directories to visit. dir_queue->push_back(TDirAndPath(td, P_path)); - return INFO_OK; + return INFO::OK; } @@ -426,10 +427,10 @@ static LibError add_ent(TDir* td, DirEnt* ent, const char* P_parent_path, const // else: it's a file (dir_next_ent discards everything except for // file and subdirectory entries). - if(enqueue_archive(name, m->P_name.c_str(), archives) == INFO_OK) + if(enqueue_archive(name, m->P_name.c_str(), archives) == INFO::OK) // return value indicates this file shouldn't be added to VFS // (see enqueue_archive) - return INFO_OK; + return INFO::OK; // notify archive builder that this file could be archived but // currently isn't; if there are too many of these, archive will be @@ -468,7 +469,7 @@ static LibError populate_dir(TDir* td, const char* P_path, const Mount* m, { // don't RETURN_ERR since we need to close d. err = dir_next_ent(&d, &ent); - if(err != INFO_OK) + if(err != INFO::OK) break; err = add_ent(td, &ent, P_path, m, dir_queue, archives); @@ -476,7 +477,7 @@ static LibError populate_dir(TDir* td, const char* P_path, const Mount* m, } WARN_ERR(dir_close(&d)); - return INFO_OK; + return INFO::OK; } @@ -494,7 +495,7 @@ static LibError populate_dir(TDir* td, const char* P_path, const Mount* m, // every single file to see if it's an archive (slow!). static LibError mount_dir_tree(TDir* td, const Mount& m) { - LibError err = INFO_OK; + LibError err = INFO::OK; // add_ent fills these queues with dirs/archives if the corresponding // flags are set. @@ -517,7 +518,7 @@ static LibError mount_dir_tree(TDir* td, const Mount& m) const char* P_path = dir_queue.front().path.c_str(); LibError ret = populate_dir(td, P_path, &m, pdir_queue, parchives, m.flags); - if(err == INFO_OK) + if(err == INFO::OK) err = ret; // prevent searching for archives in subdirectories (slow!). this @@ -532,7 +533,7 @@ static LibError mount_dir_tree(TDir* td, const Mount& m) // do not pass parchives because that has been set to 0! mount_archives(td, &archives, &m); - return INFO_OK; + return INFO::OK; } @@ -605,7 +606,7 @@ static LibError remount(const Mount& m) case MT_FILE: return mount_dir_tree(td, m); default: - WARN_RETURN(ERR_INVALID_MOUNT_TYPE); + WARN_RETURN(ERR::MOUNT_INVALID_TYPE); } } @@ -646,14 +647,14 @@ LibError vfs_mount(const char* V_mount_point, const char* P_real_path, uint flag for(MountIt it = mounts.begin(); it != mounts.end(); ++it) { if(path_is_subpath(P_real_path, it->P_name.c_str())) - WARN_RETURN(ERR_ALREADY_MOUNTED); + WARN_RETURN(ERR::ALREADY_MOUNTED); } // disallow "." because "./" isn't supported on Windows. // it would also create a loophole for the parent td check above. // "./" and "/." are caught by CHECK_PATH. if(!strcmp(P_real_path, ".")) - WARN_RETURN(ERR_PATH_NON_CANONICAL); + WARN_RETURN(ERR::PATH_NON_CANONICAL); // (count this as "init" to obviate a separate timer) stats_vfs_init_start(); @@ -674,7 +675,7 @@ LibError mount_rebuild() { tree_clear(); remount_all(); - return INFO_OK; + return INFO::OK; } @@ -712,7 +713,7 @@ LibError vfs_unmount(const char* P_name) std::bind2nd(Mount::equal_to(), P_name)); // none were removed - need to complain so that the caller notices. if(last == end) - WARN_RETURN(ERR_TNODE_NOT_FOUND); + WARN_RETURN(ERR::TNODE_NOT_FOUND); // trim list and actually remove 'invalidated' entries. mounts.erase(last, end); @@ -738,11 +739,11 @@ LibError mount_make_vfs_path(const char* P_path, char* V_path) const char* remove = m.P_name.c_str(); const char* replace = m.V_mount_point.c_str(); - if(path_replace(V_path, P_path, remove, replace) == INFO_OK) - return INFO_OK; + if(path_replace(V_path, P_path, remove, replace) == INFO::OK) + return INFO::OK; } - WARN_RETURN(ERR_TNODE_NOT_FOUND); + WARN_RETURN(ERR::TNODE_NOT_FOUND); } @@ -799,11 +800,11 @@ LibError vfs_set_write_target(const char* P_target_dir) if(!strcmp(m.P_name.c_str(), P_target_dir)) { write_target = &m; - return INFO_OK; + return INFO::OK; } } - WARN_RETURN(ERR_NOT_MOUNTED); + WARN_RETURN(ERR::NOT_MOUNTED); } @@ -812,7 +813,7 @@ LibError vfs_set_write_target(const char* P_target_dir) LibError set_mount_to_write_target(TFile* tf) { if(!write_target) - WARN_RETURN(ERR_NOT_MOUNTED); + WARN_RETURN(ERR::NOT_MOUNTED); tfile_set_mount(tf, write_target); @@ -822,7 +823,7 @@ LibError set_mount_to_write_target(TFile* tf) // opened for writing, which will change these values anyway. tree_update_file(tf, 0, 0); - return INFO_OK; + return INFO::OK; } @@ -866,12 +867,12 @@ LibError mount_attach_real_dir(RealDir* rd, const char* P_path, const Mount* m, // note: do not cause this function to return an error if // something goes wrong - this step is basically optional. char N_path[PATH_MAX]; - if(file_make_full_native_path(P_path, N_path) == INFO_OK) + if(file_make_full_native_path(P_path, N_path) == INFO::OK) (void)dir_add_watch(N_path, &rd->watch); } #endif - return INFO_OK; + return INFO::OK; } @@ -892,7 +893,7 @@ LibError mount_create_real_dir(const char* V_path, const Mount* m) debug_assert(VFS_PATH_IS_DIR(V_path)); if(!m || m == MULTIPLE_MOUNTINGS || m->type != MT_FILE) - return INFO_OK; + return INFO::OK; char P_path[PATH_MAX]; RETURN_ERR(mount_realpath(V_path, m, P_path)); @@ -905,5 +906,5 @@ LibError mount_populate(TDir* td, RealDir* rd) { UNUSED2(td); UNUSED2(rd); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/file/vfs_mount.h b/source/lib/res/file/vfs_mount.h index 854957f046..83045fbd08 100644 --- a/source/lib/res/file/vfs_mount.h +++ b/source/lib/res/file/vfs_mount.h @@ -30,11 +30,20 @@ struct Mount; // must come before vfs_tree.h #include "zip.h" #include "vfs_tree.h" + +namespace ERR +{ + const LibError ALREADY_MOUNTED = -110700; + const LibError NOT_MOUNTED = -110701; + const LibError MOUNT_INVALID_TYPE = -110702; +} + + extern void mount_init(); extern void mount_shutdown(); -// If it was possible to forward-declare enums in gcc, this one wouldn't be in +// If it were possible to forward-declare enums in GCC, this one wouldn't be in // the header. Don't use. enum MountType { @@ -49,7 +58,7 @@ enum MountType // -// accessor routines that obviate the need to access Mount fields directly: +// accessors that obviate the need to access Mount fields directly: // extern bool mount_is_archivable(const Mount* m); diff --git a/source/lib/res/file/vfs_optimizer.cpp b/source/lib/res/file/vfs_optimizer.cpp index cf022665ae..d7becb34eb 100644 --- a/source/lib/res/file/vfs_optimizer.cpp +++ b/source/lib/res/file/vfs_optimizer.cpp @@ -170,7 +170,7 @@ public: // note: use this instead of resize because FileNode doesn't have // a default ctor. NB: this is how resize is implemented anyway. file_nodes.erase(file_nodes.begin() + MAX_IDS, file_nodes.end()); - WARN_ERR(ERR_LIMIT); + WARN_ERR(ERR::LIMIT); } } }; @@ -294,7 +294,7 @@ class ConnectionBuilder // note: this happens when trace contains by now // deleted or unarchivable files. TFile* tf; - if(tree_lookup(te->atom_fn, &tf) == INFO_OK) + if(tree_lookup(te->atom_fn, &tf) == INFO::OK) if(is_archivable(tf)) add_connection(connections, te->atom_fn); } @@ -320,7 +320,7 @@ public: add_connections_from_runs(t, connections); - return INFO_OK; + return INFO::OK; } }; @@ -578,13 +578,13 @@ static LibError vfs_opt_init(const char* trace_filename, const char* archive_fn_ // bail if we shouldn't rebuild the archive. if(!force_build && !should_rebuild_main_archive(trace_filename, existing_archives)) - return INFO_SKIPPED; + return INFO::SKIPPED; // build 'graph' (nodes only) of all files that must be added. FileNodes file_nodes; FileGatherer gatherer(file_nodes); if(file_nodes.empty()) - WARN_RETURN(ERR_DIR_END); + WARN_RETURN(ERR::DIR_END); // scan nodes and add them to filename->FileId mapping. id_mgr.init(&file_nodes); @@ -602,14 +602,14 @@ static LibError vfs_opt_init(const char* trace_filename, const char* archive_fn_ Filenames V_fns = &fn_vector[0]; RETURN_ERR(archive_build_init(archive_fn, V_fns, &ab)); - return INFO_OK; + return INFO::OK; } static int vfs_opt_continue() { int ret = archive_build_continue(&ab); - if(ret == INFO_OK) + if(ret == INFO::OK) { // do NOT delete source files! some apps might want to // keep them (e.g. for source control), or name them differently. @@ -659,11 +659,11 @@ static bool should_build_mini_archive(const char* UNUSED(mini_archive_fn_fmt)) static LibError build_mini_archive(const char* mini_archive_fn_fmt) { if(!should_build_mini_archive(mini_archive_fn_fmt)) - return INFO_SKIPPED; + return INFO::SKIPPED; Filenames V_fns = (Filenames)malloc((loose_files.size()+1) * sizeof(const char*)); if(!V_fns) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); std::copy(loose_files.begin(), loose_files.end(), &V_fns[0]); V_fns[loose_files.size()] = 0; // terminator @@ -674,7 +674,7 @@ static LibError build_mini_archive(const char* mini_archive_fn_fmt) next_numbered_filename(mini_archive_fn_fmt, &nfi, mini_archive_fn, use_vfs); RETURN_ERR(archive_build(mini_archive_fn, V_fns)); - return INFO_OK; + return INFO::OK; } @@ -697,11 +697,11 @@ int vfs_opt_auto_build(const char* trace_filename, const char* archive_fn_fmt, const char* mini_archive_fn_fmt, bool force_build) { if(state == NOP) - return INFO_ALL_COMPLETE; + return INFO::ALL_COMPLETE; if(state == DECIDE_IF_BUILD) { - if(vfs_opt_init(trace_filename, archive_fn_fmt, force_build) != INFO_SKIPPED) + if(vfs_opt_init(trace_filename, archive_fn_fmt, force_build) != INFO::SKIPPED) state = IN_PROGRESS; else { @@ -709,7 +709,7 @@ int vfs_opt_auto_build(const char* trace_filename, RETURN_ERR(build_mini_archive(mini_archive_fn_fmt)); state = NOP; - return INFO_OK; // "finished" + return INFO::OK; // "finished" } } @@ -717,7 +717,7 @@ int vfs_opt_auto_build(const char* trace_filename, { int ret = vfs_opt_continue(); // just finished - if(ret == INFO_OK) + if(ret == INFO::OK) state = NOP; return ret; } @@ -731,7 +731,7 @@ LibError vfs_opt_rebuild_main_archive(const char* trace_filename, const char* ar { int ret = vfs_opt_auto_build(trace_filename, archive_fn_fmt, 0, true); RETURN_ERR(ret); - if(ret == INFO_OK) - return INFO_OK; + if(ret == INFO::OK) + return INFO::OK; } } diff --git a/source/lib/res/file/vfs_redirector.cpp b/source/lib/res/file/vfs_redirector.cpp index 8650b53d14..88b30d36c4 100644 --- a/source/lib/res/file/vfs_redirector.cpp +++ b/source/lib/res/file/vfs_redirector.cpp @@ -51,7 +51,7 @@ LibError file_open_vfs(const char* V_path, uint flags, TFile* tf, RETURN_ERR(file_open(N_path, flags|FILE_DONT_SET_FN, f)); // file_open didn't set fc.atom_fn due to FILE_DONT_SET_FN. f->atom_fn = file_make_unique_fn_copy(V_path); - return INFO_OK; + return INFO::OK; } static const FileProvider_VTbl archive_vtbl = @@ -96,10 +96,10 @@ static const FileProvider_VTbl tree_vtbl = static LibError vtbl_validate(const FileProvider_VTbl* vtbl) { if(!vtbl) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); if(vtbl->magic != vtbl_magic) - WARN_RETURN(ERR_CORRUPTED); - return INFO_OK; + WARN_RETURN(ERR::CORRUPTED); + return INFO::OK; } #define CHECK_VTBL(type) RETURN_ERR(vtbl_validate(type)) @@ -163,7 +163,7 @@ const FileProvider_VTbl* vtbl = (c == 'F')? &file_vtbl : &archive_vtbl; // note: don't assign these unless we succeed to avoid the // false impression that all is well. f->type = vtbl; - return INFO_OK; + return INFO::OK; } LibError xfile_close(File* f) @@ -173,7 +173,7 @@ LibError xfile_close(File* f) // the dtor after reload fails. // note: this takes care of checking the vtbl. if(!xfile_is_open(f)) - return INFO_OK; + return INFO::OK; LibError ret = f->type->file_close(f); f->type = 0; return ret; diff --git a/source/lib/res/file/vfs_tree.cpp b/source/lib/res/file/vfs_tree.cpp index 002c290c28..da5c5a0dbe 100644 --- a/source/lib/res/file/vfs_tree.cpp +++ b/source/lib/res/file/vfs_tree.cpp @@ -34,6 +34,14 @@ #include "file_internal.h" +AT_STARTUP(\ + error_setDescription(ERR::TNODE_NOT_FOUND, "File/directory not found");\ + error_setDescription(ERR::TNODE_WRONG_TYPE, "Using a directory as file or vice versa");\ + \ + error_setEquivalent(ERR::TNODE_NOT_FOUND, ENOENT);\ +) + + // we add/cancel directory watches from the VFS mount code for convenience - // it iterates through all subdirectories anyway (*) and provides storage for // a key to identify the watch (obviates separate TDir -> watch mapping). @@ -253,7 +261,7 @@ RealDir rd; // HACK; removeme // pool, but that "can't happen" and is OK because pool is big enough. void* mem = node_alloc(); if(!mem) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); TNode* node; #include "lib/nommgr.h" if(type == NT_FILE) @@ -265,7 +273,7 @@ RealDir rd; // HACK; removeme children.insert(name, node); *pnode = node; - return INFO_OK; + return INFO::OK; } LibError find_and_add(const char* name, TNodeType type, TNode** pnode, const Mount* m = 0) @@ -275,10 +283,10 @@ RealDir rd; // HACK; removeme { // wrong type (dir vs. file) if(node->type != type) - WARN_RETURN(ERR_TNODE_WRONG_TYPE); + WARN_RETURN(ERR::TNODE_WRONG_TYPE); *pnode = node; - return INFO_ALREADY_EXISTS; + return INFO::ALREADY_EXISTS; } return add(name, type, pnode, m); @@ -426,15 +434,15 @@ static LibError lookup_cb(const char* component, bool is_dir, void* ctx) else // complaining is left to callers; vfs_exists must be // able to fail quietly. - return ERR_TNODE_NOT_FOUND; // NOWARN + return ERR::TNODE_NOT_FOUND; // NOWARN } if(p->node->type != type) - WARN_RETURN(ERR_TNODE_WRONG_TYPE); + WARN_RETURN(ERR::TNODE_WRONG_TYPE); if(is_dir) p->td = (TDir*)p->node; - return INFO_CB_CONTINUE; + return INFO::CB_CONTINUE; } static LibError lookup(TDir* td, const char* path, uint flags, TNode** pnode) @@ -447,7 +455,7 @@ static LibError lookup(TDir* td, const char* path, uint flags, TNode** pnode) // success. *pnode = p.node; - return INFO_OK; + return INFO::OK; } @@ -550,11 +558,11 @@ LibError tree_add_file(TDir* td, const char* name, TNode* node; LibError ret = td->find_and_add(name, NT_FILE, &node); RETURN_ERR(ret); - if(ret == INFO_ALREADY_EXISTS) + if(ret == INFO::ALREADY_EXISTS) { TFile* tf = (TFile*)node; if(!mount_should_replace(tf->m, m, tf->size, size, tf->mtime, mtime)) - return INFO_ALREADY_EXISTS; + return INFO::ALREADY_EXISTS; stats_vfs_file_remove(tf->size); } @@ -567,7 +575,7 @@ LibError tree_add_file(TDir* td, const char* name, stats_vfs_file_add(size); set_most_recent_if_newer(mtime); - return INFO_OK; + return INFO::OK; } @@ -576,7 +584,7 @@ LibError tree_add_dir(TDir* td, const char* name, TDir** ptd) TNode* node; RETURN_ERR(td->find_and_add(name, NT_DIR, &node)); *ptd = (TDir*)node; - return INFO_OK; + return INFO::OK; } @@ -585,14 +593,14 @@ LibError tree_lookup_dir(const char* V_path, TDir** ptd, uint flags) { // path is not a directory; TDir::lookup might return a file node if(!VFS_PATH_IS_DIR(V_path)) - WARN_RETURN(ERR_TNODE_WRONG_TYPE); + WARN_RETURN(ERR::TNODE_WRONG_TYPE); TDir* td = (flags & LF_START_DIR)? *ptd : tree_root; TNode* node; CHECK_ERR(lookup(td, V_path, flags, &node)); // directories should exist, so warn if this fails *ptd = (TDir*)node; - return INFO_OK; + return INFO::OK; } @@ -600,13 +608,13 @@ LibError tree_lookup(const char* V_path, TFile** pfile, uint flags) { // path is not a file; TDir::lookup might return a directory node if(VFS_PATH_IS_DIR(V_path)) - WARN_RETURN(ERR_TNODE_WRONG_TYPE); + WARN_RETURN(ERR::TNODE_WRONG_TYPE); TNode* node; LibError ret = lookup(tree_root, V_path, flags, &node); RETURN_ERR(ret); *pfile = (TFile*)node; - return INFO_OK; + return INFO::OK; } @@ -626,13 +634,13 @@ static LibError add_path_cb(const char* component, bool is_dir, void* ctx) // should only be called for directory paths, so complain if not dir. if(!is_dir) - WARN_RETURN(ERR_TNODE_WRONG_TYPE); + WARN_RETURN(ERR::TNODE_WRONG_TYPE); TNode* node; RETURN_ERR(p->td->find_and_add(component, NT_DIR, &node, p->m)); p->td = (TDir*)node; - return INFO_CB_CONTINUE; + return INFO::CB_CONTINUE; } // iterate over all components in V_dir_path (must reference a directory, @@ -647,7 +655,7 @@ LibError tree_add_path(const char* V_dir_path, const Mount* m, TDir** ptd) AddPathCbParams p(m); RETURN_ERR(path_foreach_component(V_dir_path, add_path_cb, &p)); *ptd = p.td; - return INFO_OK; + return INFO::OK; } @@ -682,7 +690,7 @@ LibError tree_dir_open(const char* V_dir_path, DirIterator* di) // we need to prevent modifications to this directory while an iterator is // active, otherwise entries may be skipped or no longer valid addresses // accessed. blocking other threads is much more convenient for callers - // than having to check for ERR_AGAIN on every call, so we use a mutex + // than having to check for ERR::AGAIN on every call, so we use a mutex // instead of a simple refcount. we don't bother with fine-grained locking // (e.g. per directory or read/write locks) because it would result in // more overhead (we have hundreds of directories) and is unnecessary. @@ -691,7 +699,7 @@ LibError tree_dir_open(const char* V_dir_path, DirIterator* di) tdi->it = td->begin(); tdi->end = td->end(); tdi->td = td; - return INFO_OK; + return INFO::OK; } @@ -700,7 +708,7 @@ LibError tree_dir_next_ent(DirIterator* di, DirEnt* ent) TreeDirIterator* tdi = (TreeDirIterator*)di->opaque; if(tdi->it == tdi->end) - return ERR_DIR_END; // NOWARN + return ERR::DIR_END; // NOWARN const TNode* node = *(tdi->it++); ent->name = node->name; @@ -725,7 +733,7 @@ LibError tree_dir_next_ent(DirIterator* di, DirEnt* ent) debug_warn("invalid TNode type"); } - return INFO_OK; + return INFO::OK; } @@ -735,7 +743,7 @@ LibError tree_dir_close(DirIterator* UNUSED(d)) // no further cleanup needed. we could zero out d but that might // hide bugs; the iterator is safe (will not go beyond end) anyway. - return INFO_OK; + return INFO::OK; } @@ -780,7 +788,7 @@ LibError tree_stat(const TFile* tf, struct stat* s) s->st_size = tf->size; s->st_mtime = tf->mtime; - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/file/vfs_tree.h b/source/lib/res/file/vfs_tree.h index c7a0f16879..2a1a51cd72 100644 --- a/source/lib/res/file/vfs_tree.h +++ b/source/lib/res/file/vfs_tree.h @@ -30,6 +30,13 @@ class TDir; #include "vfs_mount.h" // Mount +namespace ERR +{ + const LibError TNODE_NOT_FOUND = -110600; + // attemped to treat a file as directory or vice versa. + const LibError TNODE_WRONG_TYPE = -110601; +} + // establish a root node and prepare node_allocator for use. extern void tree_init(); @@ -73,7 +80,7 @@ enum TreeLookupFlags // a higher-priority file of the same name already exists // (used by VFile_reload when opening for writing). // -// output params are only valid if INFO_OK is returned. +// output params are only valid if INFO::OK is returned. extern LibError tree_lookup(const char* path, TFile** ptf, uint flags = 0); // starting at VFS root, traverse and pass back information @@ -87,7 +94,7 @@ extern LibError tree_lookup(const char* path, TFile** ptf, uint flags = 0); // can be to a file or dir (in which case it must end in '/', // to make sure the last component is treated as a directory). // -// output params are only valid if INFO_OK is returned. +// output params are only valid if INFO::OK is returned. extern LibError tree_lookup_dir(const char* V_path, TDir** ptd, uint flags = 0); diff --git a/source/lib/res/file/zip.cpp b/source/lib/res/file/zip.cpp index c67adb7b7d..355632bc01 100644 --- a/source/lib/res/file/zip.cpp +++ b/source/lib/res/file/zip.cpp @@ -30,6 +30,7 @@ #include "lib/allocators.h" #include "lib/timer.h" #include "file_internal.h" +#include "lib/res/res.h" // safe downcasters: cast from any integral type to u32 or u16; @@ -127,7 +128,7 @@ static ZipCompressionMethod zip_method_for(CompressionMethod method) case CM_DEFLATE: return ZIP_CM_DEFLATE; default: - WARN_ERR(ERR_UNKNOWN_CMETHOD); + WARN_ERR(ERR::COMPRESSION_UNKNOWN_METHOD); return ZIP_CM_NONE; } } @@ -142,7 +143,7 @@ static CompressionMethod method_for_zip_method(ZipCompressionMethod zip_method) case ZIP_CM_DEFLATE: return CM_DEFLATE; default: - WARN_ERR(ERR_UNKNOWN_CMETHOD); + WARN_ERR(ERR::COMPRESSION_UNKNOWN_METHOD); return CM_UNSUPPORTED; } } @@ -366,7 +367,7 @@ static const u8* za_find_id(const u8* buf, size_t size, const void* start, u32 m // search for ECDR in the last bytes of the file. // if found, fill with a copy of the (little-endian) ECDR and -// return INFO_OK, otherwise IO error or ERR_CORRUPTED. +// return INFO::OK, otherwise IO error or ERR::CORRUPTED. static LibError za_find_ecdr(File* f, size_t max_scan_amount, ECDR* dst_ecdr_le) { // don't scan more than the entire file @@ -381,13 +382,13 @@ static LibError za_find_ecdr(File* f, size_t max_scan_amount, ECDR* dst_ecdr_le) debug_assert(bytes_read == (ssize_t)scan_amount); // look for ECDR in buffer - LibError ret = ERR_CORRUPTED; + LibError ret = ERR::CORRUPTED; const u8* start = (const u8*)buf; const ECDR* ecdr_le = (const ECDR*)za_find_id(start, bytes_read, start, ecdr_magic, ECDR_SIZE); if(ecdr_le) { *dst_ecdr_le = *ecdr_le; - ret = INFO_OK; + ret = INFO::OK; } file_buf_free(buf); @@ -407,24 +408,24 @@ completely_bogus: // note: the VFS blindly opens files when mounting; it needs to open // all archives, but doesn't know their extension (e.g. ".pk3"). // therefore, do not warn user. - return ERR_UNKNOWN_FORMAT; // NOWARN + return ERR::RES_UNKNOWN_FORMAT; // NOWARN } ECDR ecdr_le; // expected case: ECDR at EOF; no file comment (=> we only need to // read 512 bytes) LibError ret = za_find_ecdr(f, ECDR_SIZE, &ecdr_le); - if(ret == INFO_OK) + if(ret == INFO::OK) { have_ecdr: ecdr_decompose(&ecdr_le, cd_entries, cd_ofs, cd_size); - return INFO_OK; + return INFO::OK; } // last resort: scan last 66000 bytes of file // (the Zip archive comment field - up to 64k - may follow ECDR). // if the zip file is < 66000 bytes, scan the whole file. ret = za_find_ecdr(f, 66000u, &ecdr_le); - if(ret == INFO_OK) + if(ret == INFO::OK) goto have_ecdr; // both ECDR scans failed - this is not a valid Zip file. @@ -441,19 +442,19 @@ have_ecdr: // the Zip file is mostly valid but lacking an ECDR. (can happen if // user hard-exits while building an archive) // notes: - // - return ERR_CORRUPTED so VFS will not include this file. + // - return ERR::CORRUPTED so VFS will not include this file. // - we could work around this by scanning all LFHs, but won't bother // because it'd be slow. // - do not warn - the corrupt archive will be deleted on next // successful archive builder run anyway. - return ERR_CORRUPTED; // NOWARN + return ERR::CORRUPTED; // NOWARN } // analyse an opened Zip file; call back into archive.cpp to // populate the Archive object with a list of the files it contains. -// returns INFO_OK on success, ERR_CORRUPTED if file is recognizable as -// a Zip file but invalid, otherwise ERR_UNKNOWN_FORMAT or IO error. +// returns INFO::OK on success, ERR::CORRUPTED if file is recognizable as +// a Zip file but invalid, otherwise ERR::RES_UNKNOWN_FORMAT or IO error. // // fairly slow - must read Central Directory from disk // (size ~= 60 bytes*num_files); observed time ~= 80ms. @@ -472,7 +473,7 @@ LibError zip_populate_archive(File* f, Archive* a) RETURN_ERR(file_io(f, cd_ofs, cd_size, &buf)); // iterate through Central Directory - LibError ret = INFO_OK; + LibError ret = INFO::OK; const CDFH* cdfh = (const CDFH*)buf; size_t ofs_to_next_cdfh = 0; for(uint i = 0; i < cd_entries; i++) @@ -482,7 +483,7 @@ LibError zip_populate_archive(File* f, Archive* a) cdfh = (CDFH*)za_find_id((const u8*)buf, cd_size, (const u8*)cdfh, cdfh_magic, CDFH_SIZE); if(!cdfh) // no (further) CDFH found: { - ret = ERR_CORRUPTED; + ret = ERR::CORRUPTED; break; } @@ -495,7 +496,7 @@ LibError zip_populate_archive(File* f, Archive* a) if(ae.csize && ae.ucsize) { ret = archive_add_file(a, &ae); - if(ret != INFO_OK) + if(ret != INFO::OK) break; } } @@ -531,7 +532,7 @@ static LibError lfh_copier_cb(uintptr_t ctx, const void* block, size_t size, siz p->lfh_bytes_remaining -= size; *bytes_processed = size; - return INFO_CB_CONTINUE; + return INFO::CB_CONTINUE; } @@ -603,10 +604,10 @@ LibError zip_archive_create(const char* zip_filename, ZipArchive** pza) ZipArchive* za = za_mgr.alloc(); if(!za) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); *za = za_copy; *pza = za; - return INFO_OK; + return INFO::OK; } @@ -639,14 +640,14 @@ LibError zip_archive_add_file(ZipArchive* za, const ArchiveEntry* ae, void* file const size_t prev_pos = za->cdfhs.da.pos; CDFH_Package* p = (CDFH_Package*)pool_alloc(&za->cdfhs, CDFH_SIZE+fn_len); if(!p) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); const size_t slack = za->cdfhs.da.pos-prev_pos - (CDFH_SIZE+fn_len); cdfh_assemble(&p->cdfh, ae->method, ae->mtime, ae->crc, ae->csize, ae->ucsize, fn_len, slack, lfh_ofs); memcpy2(p->fn, ae->atom_fn, fn_len); za->cd_entries++; - return INFO_OK; + return INFO::OK; } @@ -661,7 +662,7 @@ LibError zip_archive_finish(ZipArchive* za) // write out both to the archive file in one burst) ECDR* ecdr = (ECDR*)pool_alloc(&za->cdfhs, ECDR_SIZE); if(!ecdr) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); ecdr_assemble(ecdr, za->cd_entries, za->cur_file_size, cd_size); FileIOBuf buf = za->cdfhs.da.base; @@ -670,5 +671,5 @@ LibError zip_archive_finish(ZipArchive* za) (void)file_close(&za->f); (void)pool_destroy(&za->cdfhs); za_mgr.release(za); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/file/zip.h b/source/lib/res/file/zip.h index d15ff50aed..21c9f079c1 100644 --- a/source/lib/res/file/zip.h +++ b/source/lib/res/file/zip.h @@ -30,8 +30,8 @@ struct ArchiveEntry; // analyse an opened Zip file; call back into archive.cpp to // populate the Archive object with a list of the files it contains. -// returns INFO_OK on success, ERR_CORRUPTED if file is recognizable as -// a Zip file but invalid, otherwise ERR_UNKNOWN_FORMAT or IO error. +// returns INFO::OK on success, ERR::CORRUPTED if file is recognizable as +// a Zip file but invalid, otherwise ERR::RES_UNKNOWN_FORMAT or IO error. // // fairly slow - must read Central Directory from disk // (size ~= 60 bytes*num_files); observed time ~= 80ms. diff --git a/source/lib/res/graphics/cursor.cpp b/source/lib/res/graphics/cursor.cpp index bfe402db1c..9a25ab9c88 100644 --- a/source/lib/res/graphics/cursor.cpp +++ b/source/lib/res/graphics/cursor.cpp @@ -121,7 +121,7 @@ public: (void)ogl_tex_set_filter(ht, GL_NEAREST); (void)ogl_tex_upload(ht); - return INFO_OK; + return INFO::OK; } void destroy() @@ -155,10 +155,10 @@ public: { const uint A = 128; // no cursor is expected to get this big if(w > A || h > A || hotspotx > A || hotspoty > A) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); if(ht < 0) - WARN_RETURN(ERR_2); - return INFO_OK; + WARN_RETURN(ERR::_2); + return INFO::OK; } }; @@ -214,13 +214,13 @@ static LibError Cursor_reload(Cursor* c, const char* name, Handle) { LibError err=c->gl_cursor.create(filename, hotspotx, hotspoty); - if (err == INFO_OK) + if (err == INFO::OK) c->gl_sys_cursor = load_empty_sys_cursor(); return err; } - return INFO_OK; + return INFO::OK; } static LibError Cursor_validate(const Cursor* c) @@ -230,14 +230,14 @@ static LibError Cursor_validate(const Cursor* c) if(!c->sys_cursor) RETURN_ERR(c->gl_cursor.validate()); - return INFO_OK; + return INFO::OK; } static LibError Cursor_to_string(const Cursor* c, char* buf) { const char* type = c->sys_cursor? "sys" : "gl"; snprintf(buf, H_STRING_LEN, "(%s)", type); - return INFO_OK; + return INFO::OK; } @@ -268,7 +268,7 @@ LibError cursor_draw(const char* name, int x, int y) if(!name) { WARN_ERR(sys_cursor_set(0)); - return INFO_OK; + return INFO::OK; } Handle hc = cursor_load(name); @@ -287,5 +287,5 @@ LibError cursor_draw(const char* name, int x, int y) } (void)cursor_free(hc); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/graphics/ogl_shader.cpp b/source/lib/res/graphics/ogl_shader.cpp index ebf55ff0d9..7d8b96d5ee 100644 --- a/source/lib/res/graphics/ogl_shader.cpp +++ b/source/lib/res/graphics/ogl_shader.cpp @@ -22,6 +22,15 @@ #define LOG_CATEGORY "shaders" +AT_STARTUP(\ + error_setDescription(ERR::SHDR_CREATE, "Shader creation failed");\ + error_setDescription(ERR::SHDR_COMPILE, "Shader compile failed");\ + error_setDescription(ERR::SHDR_NO_SHADER, "Invalid shader reference");\ + error_setDescription(ERR::SHDR_LINK, "Shader linking failed");\ + error_setDescription(ERR::SHDR_NO_PROGRAM, "Invalid shader program reference");\ +) + + // Convert a shader object type into a descriptive string. // If the type enum is not known, the given buffer is used as scratch space // to format the type number. If buf is null, a generic string is returned. @@ -84,10 +93,10 @@ static void Ogl_Shader_init(Ogl_Shader* shdr, va_list args) // So, how can we inform the "parent object" (i.e. the program object) of our change? static LibError Ogl_Shader_reload(Ogl_Shader* shdr, const char* filename, Handle UNUSED(h)) { - LibError err = ERR_FAIL; + LibError err = ERR::FAIL; if (shdr->id) - return INFO_OK; + return INFO::OK; FileIOBuf file; size_t file_size; @@ -106,7 +115,7 @@ static LibError Ogl_Shader_reload(Ogl_Shader* shdr, const char* filename, Handle // bad code. oglCheck(); - err = ERR_SHDR_CREATE; + err = ERR::SHDR_CREATE; goto fail_fileloaded; } @@ -143,12 +152,12 @@ static LibError Ogl_Shader_reload(Ogl_Shader* shdr, const char* filename, Handle filename, shader_type_to_string(shdr->type, typenamebuf, ARRAY_SIZE(typenamebuf))); - err = ERR_SHDR_COMPILE; + err = ERR::SHDR_COMPILE; goto fail_shadercreated; } (void)file_buf_free(file); - return INFO_OK; + return INFO::OK; fail_shadercreated: pglDeleteObjectARB(shdr->id); @@ -173,13 +182,13 @@ static void Ogl_Shader_dtor(Ogl_Shader* shdr) static LibError Ogl_Shader_validate(const Ogl_Shader* UNUSED(shdr)) { // TODO - return INFO_OK; + return INFO::OK; } static LibError Ogl_Shader_to_string(const Ogl_Shader* UNUSED(shdr), char* buf) { snprintf(buf, H_STRING_LEN, ""); - return INFO_OK; + return INFO::OK; } @@ -208,11 +217,11 @@ LibError ogl_shader_attach(GLhandleARB program, Handle& h) H_DEREF(h, Ogl_Shader, shdr); if (!shdr->id) - WARN_RETURN(ERR_SHDR_NO_SHADER); + WARN_RETURN(ERR::SHDR_NO_SHADER); pglAttachObjectARB(program, shdr->id); - return INFO_OK; + return INFO::OK; } @@ -252,7 +261,7 @@ static LibError do_load_shader( { LOG(ERROR, LOG_CATEGORY, "%hs: Missing attribute \"type\" in element \"Shader\".", filename); - WARN_RETURN(ERR_CORRUPTED); + WARN_RETURN(ERR::CORRUPTED); } GLenum shadertype = string_to_shader_type(Type.c_str()); @@ -261,7 +270,7 @@ static LibError do_load_shader( { LOG(ERROR, LOG_CATEGORY, "%hs: Unknown shader type \"%hs\" (valid are: VERTEX_SHADER, FRAGMENT_SHADER).", filename, Type.c_str()); - WARN_RETURN(ERR_CORRUPTED); + WARN_RETURN(ERR::CORRUPTED); } CStr Name = Shader.getText(); @@ -269,7 +278,7 @@ static LibError do_load_shader( if (!Name.Length()) { LOG(ERROR, LOG_CATEGORY, "%hs: Missing shader name.", filename); - WARN_RETURN(ERR_CORRUPTED); + WARN_RETURN(ERR::CORRUPTED); } Handle hshader = ogl_shader_load(Name.c_str(), shadertype); @@ -283,7 +292,7 @@ static LibError do_load_shader( // TODO: How will this work with automatic reload? ogl_shader_free(hshader); - return INFO_OK; + return INFO::OK; } @@ -291,7 +300,7 @@ static LibError do_load_shader( static LibError Ogl_Program_reload(Ogl_Program* p, const char* filename, Handle h) { if (p->id) - return INFO_OK; + return INFO::OK; oglCheck(); @@ -302,12 +311,12 @@ static LibError Ogl_Program_reload(Ogl_Program* p, const char* filename, Handle // here, but it may still help spot bad code. oglCheck(); - WARN_RETURN(ERR_SHDR_CREATE); + WARN_RETURN(ERR::SHDR_CREATE); } CXeromyces XeroFile; if (XeroFile.Load(filename) != PSRETURN_OK) - WARN_RETURN(ERR_CORRUPTED); // more informative error message? + WARN_RETURN(ERR::CORRUPTED); // more informative error message? // Define all the elements and attributes used in the XML file #define EL(x) int el_##x = XeroFile.getElementID(#x) @@ -321,7 +330,7 @@ static LibError Ogl_Program_reload(Ogl_Program* p, const char* filename, Handle if (Root.getNodeName() != el_program) { LOG(ERROR, LOG_CATEGORY, "%hs: XML root was not \"Program\".", filename); - WARN_RETURN(ERR_CORRUPTED); + WARN_RETURN(ERR::CORRUPTED); } XMBElementList RootChildren = Root.getChildNodes(); @@ -343,7 +352,7 @@ static LibError Ogl_Program_reload(Ogl_Program* p, const char* filename, Handle { LOG(ERROR, LOG_CATEGORY, "%hs: Only \"Shader\" may be child of \"Shaders\".", filename); - WARN_RETURN(ERR_CORRUPTED); + WARN_RETURN(ERR::CORRUPTED); } RETURN_ERR(do_load_shader(p, filename, h, XeroFile, Shader)); @@ -374,10 +383,10 @@ static LibError Ogl_Program_reload(Ogl_Program* p, const char* filename, Handle if (!linked) { debug_printf("Link failed for %hs\n", filename); - WARN_RETURN(ERR_SHDR_LINK); + WARN_RETURN(ERR::SHDR_LINK); } - return INFO_OK; + return INFO::OK; } @@ -394,13 +403,13 @@ static void Ogl_Program_dtor(Ogl_Program* p) static LibError Ogl_Program_validate(const Ogl_Program* UNUSED(p)) { // TODO - return INFO_OK; + return INFO::OK; } static LibError Ogl_Program_to_string(const Ogl_Program* UNUSED(p), char* buf) { snprintf(buf, H_STRING_LEN, ""); - return INFO_OK; + return INFO::OK; } @@ -428,18 +437,18 @@ LibError ogl_program_use(Handle h) if (!h) { pglUseProgramObjectARB(0); - return INFO_OK; + return INFO::OK; } Ogl_Program* p = H_USER_DATA(h, Ogl_Program); if (!p || !p->id) { pglUseProgramObjectARB(0); - WARN_RETURN(ERR_INVALID_HANDLE); + WARN_RETURN(ERR::INVALID_HANDLE); } pglUseProgramObjectARB(p->id); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/graphics/ogl_shader.h b/source/lib/res/graphics/ogl_shader.h index 8bccfc695a..278de7b56f 100644 --- a/source/lib/res/graphics/ogl_shader.h +++ b/source/lib/res/graphics/ogl_shader.h @@ -16,6 +16,16 @@ #include "lib/types.h" #include "lib/ogl.h" + +namespace ERR +{ + const LibError SHDR_CREATE = -120200; + const LibError SHDR_COMPILE = -120201; + const LibError SHDR_NO_SHADER = -120202; + const LibError SHDR_LINK = -120203; + const LibError SHDR_NO_PROGRAM = -120204; +} + /* Encapsulate shader objects into handles, which transparently enables sharing of shader source files between programs as well as reloading shaders at diff --git a/source/lib/res/graphics/ogl_tex.cpp b/source/lib/res/graphics/ogl_tex.cpp index d43ca87943..9fc88e7436 100644 --- a/source/lib/res/graphics/ogl_tex.cpp +++ b/source/lib/res/graphics/ogl_tex.cpp @@ -409,7 +409,7 @@ static LibError OglTex_reload(OglTex* ot, const char* fn, Handle h) { // we're reusing a freed but still in-memory OglTex object if(ot->flags & OT_IS_UPLOADED) - return INFO_OK; + return INFO::OK; // if we don't already have the texture in memory (*), load from file. // * this happens if the texture is "wrapped". @@ -424,7 +424,7 @@ static LibError OglTex_reload(OglTex* ot, const char* fn, Handle h) if(ot->flags & OT_NEED_AUTO_UPLOAD) (void)ogl_tex_upload(h); - return INFO_OK; + return INFO::OK; } static LibError OglTex_validate(const OglTex* ot) @@ -438,41 +438,41 @@ static LibError OglTex_validate(const OglTex* ot) GLsizei h = (GLsizei)ot->t.h; // .. == 0; texture file probably not loaded successfully. if(w == 0 || h == 0) - WARN_RETURN(ERR_11); + WARN_RETURN(ERR::_11); // .. greater than max supported tex dimension. // no-op if oglInit not yet called if(w > (GLsizei)ogl_max_tex_size || h > (GLsizei)ogl_max_tex_size) - WARN_RETURN(ERR_12); + WARN_RETURN(ERR::_12); // .. not power-of-2. // note: we can't work around this because both NV_texture_rectangle // and subtexture require work for the client (changing tex coords). // TODO: ARB_texture_non_power_of_two if(!is_pow2(w) || !is_pow2(h)) - WARN_RETURN(ERR_13); + WARN_RETURN(ERR::_13); // texture state if(!filter_valid(ot->state.filter)) - WARN_RETURN(ERR_14); + WARN_RETURN(ERR::_14); if(!wrap_valid(ot->state.wrap)) - WARN_RETURN(ERR_15); + WARN_RETURN(ERR::_15); // misc if(!q_flags_valid(ot->q_flags)) - WARN_RETURN(ERR_16); + WARN_RETURN(ERR::_16); if(ot->tmu >= 128) // unexpected that there will ever be this many - WARN_RETURN(ERR_17); + WARN_RETURN(ERR::_17); if(ot->flags > OT_ALL_FLAGS) - WARN_RETURN(ERR_18); + WARN_RETURN(ERR::_18); // .. note: don't check ot->fmt and ot->int_fmt - they aren't set // until during ogl_tex_upload. - return INFO_OK; + return INFO::OK; } static LibError OglTex_to_string(const OglTex* ot, char* buf) { snprintf(buf, H_STRING_LEN, "id=%d", ot->id); - return INFO_OK; + return INFO::OK; } @@ -578,14 +578,14 @@ LibError ogl_tex_set_filter(Handle ht, GLint filter) H_DEREF(ht, OglTex, ot); if(!filter_valid(filter)) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); if(ot->state.filter != filter) { warn_if_uploaded(ht, ot); ot->state.filter = filter; } - return INFO_OK; + return INFO::OK; } @@ -598,14 +598,14 @@ LibError ogl_tex_set_wrap(Handle ht, GLint wrap) H_DEREF(ht, OglTex, ot); if(!wrap_valid(wrap)) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); if(ot->state.wrap != wrap) { warn_if_uploaded(ht, ot); ot->state.wrap = wrap; } - return INFO_OK; + return INFO::OK; } @@ -690,7 +690,7 @@ static LibError get_mipmaps(Tex* t, GLint filter, uint q_flags, int* plevels_to_ *plevels_to_skip = TEX_BASE_LEVEL_ONLY; if(!need_mipmaps) - return INFO_OK; + return INFO::OK; // image already contains pregenerated mipmaps; we need do nothing. // this is the nicest case, because they are fastest to load @@ -713,7 +713,7 @@ static LibError get_mipmaps(Tex* t, GLint filter, uint q_flags, int* plevels_to_ // all<->all transforms aren't implemented, it'd have to decompress // from S3TC first), and DDS images ought to include mipmaps! else if(is_s3tc) - return ERR_FAIL; // NOWARN + return ERR::FAIL; // NOWARN // image is uncompressed and we're on an old OpenGL implementation; // we will generate mipmaps in software. else @@ -735,7 +735,7 @@ static LibError get_mipmaps(Tex* t, GLint filter, uint q_flags, int* plevels_to_ *plevels_to_skip = log2(reduce); } - return INFO_OK; + return INFO::OK; } @@ -806,7 +806,7 @@ LibError ogl_tex_upload(const Handle ht, GLenum fmt_ovr, uint q_flags_ovr, GLint // upload already happened; no work to do. // (this also happens if a cached texture is "loaded") if(ot->flags & OT_IS_UPLOADED) - return INFO_OK; + return INFO::OK; debug_assert(ot->flags & OT_TEX_VALID); @@ -851,7 +851,7 @@ LibError ogl_tex_upload(const Handle ht, GLenum fmt_ovr, uint q_flags_ovr, GLint ot->flags &= ~OT_TEX_VALID; } - return INFO_OK; + return INFO::OK; } @@ -871,7 +871,7 @@ LibError ogl_tex_get_size(Handle ht, uint* w, uint* h, uint* bpp) *h = ot->t.h; if(bpp) *bpp = ot->t.bpp; - return INFO_OK; + return INFO::OK; } @@ -890,7 +890,7 @@ LibError ogl_tex_get_format(Handle ht, uint* flags, GLenum* fmt) debug_warn("hasn't been defined yet!"); *fmt = ot->fmt; } - return INFO_OK; + return INFO::OK; } @@ -906,7 +906,7 @@ LibError ogl_tex_get_data(Handle ht, void** p) H_DEREF(ht, OglTex, ot); *p = tex_get_data(&ot->t); - return INFO_OK; + return INFO::OK; } @@ -935,7 +935,7 @@ LibError ogl_tex_bind(Handle ht, uint unit) if(ht == 0) { glDisable(GL_TEXTURE_2D); - return INFO_OK; + return INFO::OK; } // if this fails, the texture unit's state remains unchanged. @@ -951,7 +951,7 @@ LibError ogl_tex_bind(Handle ht, uint unit) glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, ot->id); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/graphics/tex.cpp b/source/lib/res/graphics/tex.cpp index 97a9c2a860..90fa3e2903 100644 --- a/source/lib/res/graphics/tex.cpp +++ b/source/lib/res/graphics/tex.cpp @@ -34,6 +34,18 @@ #include "tex_codec.h" +AT_STARTUP(\ + error_setDescription(ERR::TEX_FMT_INVALID, "Invalid/unsupported texture format");\ + error_setDescription(ERR::TEX_INVALID_COLOR_TYPE, "Invalid color type");\ + error_setDescription(ERR::TEX_NOT_8BIT_PRECISION, "Not 8bit channel precision");\ + error_setDescription(ERR::TEX_INVALID_LAYOUT, "Unsupported texel layout, e.g. righttoleft");\ + error_setDescription(ERR::TEX_COMPRESSED, "Unsupported texture compression");\ + error_setDescription(WARN::TEX_INVALID_DATA, "Warning: invalid texel data encountered");\ + error_setDescription(ERR::TEX_INVALID_SIZE, "Texture size is incorrect");\ + error_setDescription(INFO::TEX_CODEC_CANNOT_HANDLE, "Texture codec cannot handle the given format");\ +) + + //----------------------------------------------------------------------------- // validation //----------------------------------------------------------------------------- @@ -52,25 +64,25 @@ LibError tex_validate(const Tex* t) // possible causes: texture file header is invalid, // or file wasn't loaded completely. if(tex_file_size < t->ofs + t->w*t->h*t->bpp/8) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); } // bits per pixel // (we don't bother checking all values; a sanity check is enough) if(t->bpp % 4 || t->bpp > 32) - WARN_RETURN(ERR_2); + WARN_RETURN(ERR::_2); // flags // .. DXT value const uint dxt = t->flags & TEX_DXT; if(dxt != 0 && dxt != 1 && dxt != DXT1A && dxt != 3 && dxt != 5) - WARN_RETURN(ERR_3); + WARN_RETURN(ERR::_3); // .. orientation const uint orientation = t->flags & TEX_ORIENTATION; if(orientation == (TEX_BOTTOM_UP|TEX_TOP_DOWN)) - WARN_RETURN(ERR_4); + WARN_RETURN(ERR::_4); - return INFO_OK; + return INFO::OK; } #define CHECK_TEX(t) RETURN_ERR(tex_validate(t)) @@ -88,22 +100,22 @@ LibError tex_validate_plain_format(uint bpp, uint flags) const bool mipmaps = (flags & TEX_MIPMAPS) != 0; if(dxt || mipmaps) - WARN_RETURN(ERR_TEX_FMT_INVALID); + WARN_RETURN(ERR::TEX_FMT_INVALID); // grey must be 8bpp without alpha, or it's invalid. if(grey) { if(bpp == 8 && !alpha) - return INFO_OK; - WARN_RETURN(ERR_TEX_FMT_INVALID); + return INFO::OK; + WARN_RETURN(ERR::TEX_FMT_INVALID); } if(bpp == 24 && !alpha) - return INFO_OK; + return INFO::OK; if(bpp == 32 && alpha) - return INFO_OK; + return INFO::OK; - WARN_RETURN(ERR_TEX_FMT_INVALID); + WARN_RETURN(ERR::TEX_FMT_INVALID); } @@ -241,20 +253,20 @@ static LibError add_mipmaps(Tex* t, uint w, uint h, uint bpp, // go to the trouble of implementing image scaling because // the only place this is used (ogl_tex_upload) requires POT anyway. if(!is_pow2(w) || !is_pow2(h)) - WARN_RETURN(ERR_TEX_INVALID_SIZE); + WARN_RETURN(ERR::TEX_INVALID_SIZE); t->flags |= TEX_MIPMAPS; // must come before tex_img_size! const size_t mipmap_size = tex_img_size(t); Handle hm; const u8* mipmap_data = (const u8*)mem_alloc(mipmap_size, 4*KiB, 0, &hm); if(!mipmap_data) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); CreateLevelData cld = { bpp/8, w, h, (const u8*)new_data, data_size }; tex_util_foreach_mipmap(w, h, bpp, mipmap_data, 0, 1, create_level, &cld); mem_free_h(t->hm); t->hm = hm; t->ofs = 0; - return INFO_OK; + return INFO::OK; } @@ -287,12 +299,12 @@ TIMER_ACCRUE(tc_plain_transform); // sanity checks (not errors, we just can't handle these cases) // .. unknown transform if(transforms & ~(TEX_BGR|TEX_ORIENTATION|TEX_MIPMAPS)) - return INFO_TEX_CODEC_CANNOT_HANDLE; + return INFO::TEX_CODEC_CANNOT_HANDLE; // .. data is not in "plain" format RETURN_ERR(tex_validate_plain_format(bpp, flags)); // .. nothing to do if(!transforms) - return INFO_OK; + return INFO::OK; // allocate copy of the image data. // rationale: L1 cache is typically A2 => swapping in-place with a @@ -304,7 +316,7 @@ TIMER_ACCRUE(tc_plain_transform); Handle hm; void* new_data = mem_alloc(data_size, 4*KiB, 0, &hm); if(!new_data) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); memcpy2(new_data, data, data_size); // setup row source/destination pointers (simplifies outer loop) @@ -372,7 +384,7 @@ TIMER_ACCRUE(tc_plain_transform); RETURN_ERR(add_mipmaps(t, w, h, bpp, new_data, data_size)); CHECK_TEX(t); - return INFO_OK; + return INFO::OK; } @@ -392,16 +404,16 @@ LibError tex_transform(Tex* t, uint transforms) remaining_transforms = target_flags ^ t->flags; // we're finished (all required transforms have been done) if(remaining_transforms == 0) - return INFO_OK; + return INFO::OK; LibError ret = tex_codec_transform(t, remaining_transforms); - if(ret != INFO_OK) + if(ret != INFO::OK) break; } // last chance RETURN_ERR(plain_transform(t, remaining_transforms)); - return INFO_OK; + return INFO::OK; } @@ -487,7 +499,7 @@ bool tex_is_known_extension(const char* filename) { const TexCodecVTbl* dummy; // found codec for it => known extension - if(tex_codec_for_filename(filename, &dummy) == INFO_OK) + if(tex_codec_for_filename(filename, &dummy) == INFO::OK) return true; return false; @@ -527,7 +539,7 @@ LibError tex_wrap(uint w, uint h, uint bpp, uint flags, void* img, Tex* t) t->ofs = (u8*)img - (u8*)reported_ptr; CHECK_TEX(t); - return INFO_OK; + return INFO::OK; } @@ -616,10 +628,10 @@ LibError tex_decode(const u8* data, size_t data_size, MEM_DTOR dtor, Tex* t) // make sure the entire header is available const size_t min_hdr_size = c->hdr_size(0); if(data_size < min_hdr_size) - WARN_RETURN(ERR_INCOMPLETE_HEADER); + WARN_RETURN(ERR::RES_INCOMPLETE_HEADER); const size_t hdr_size = c->hdr_size(data); if(data_size < hdr_size) - WARN_RETURN(ERR_INCOMPLETE_HEADER); + WARN_RETURN(ERR::RES_INCOMPLETE_HEADER); // wrap pointer into a Handle; required for Tex.hm. // rationale: a Handle protects the texture memory from being @@ -642,16 +654,16 @@ LibError tex_decode(const u8* data, size_t data_size, MEM_DTOR dtor, Tex* t) // sanity checks if(!t->w || !t->h || t->bpp > 32) - WARN_RETURN(ERR_TEX_FMT_INVALID); + WARN_RETURN(ERR::TEX_FMT_INVALID); // .. note: can't use data_size - decode may have decompressed the image. size_t hm_size; (void)mem_get_ptr(t->hm, &hm_size); if(hm_size < t->ofs + tex_img_size(t)) - WARN_RETURN(ERR_TEX_INVALID_SIZE); + WARN_RETURN(ERR::TEX_INVALID_SIZE); flip_to_global_orientation(t); - return INFO_OK; + return INFO::OK; } @@ -679,7 +691,7 @@ LibError tex_encode(Tex* t, const char* fn, DynArray* da) WARN_RETURN(err); } - return INFO_OK; + return INFO::OK; } @@ -709,7 +721,7 @@ LibError tex_load(const char* fn, Tex* t, uint file_flags) // wasn't compressed) or was replaced by a new buffer for the image data. CHECK_TEX(t); - return INFO_OK; + return INFO::OK; } @@ -722,7 +734,7 @@ LibError tex_write(Tex* t, const char* fn) RETURN_ERR(tex_encode(t, fn, &da)); // write to disk - LibError ret = INFO_OK; + LibError ret = INFO::OK; { const size_t sector_aligned_size = round_up(da.cur_size, file_sector_size); (void)da_set_size(&da, sector_aligned_size); diff --git a/source/lib/res/graphics/tex.h b/source/lib/res/graphics/tex.h index 5d191273fc..0b223bca2b 100644 --- a/source/lib/res/graphics/tex.h +++ b/source/lib/res/graphics/tex.h @@ -102,6 +102,28 @@ library and IO layer. Read and write are zero-copy. #include "lib/res/handle.h" + +namespace ERR +{ + const LibError TEX_FMT_INVALID = -120100; + const LibError TEX_INVALID_COLOR_TYPE = -120101; + const LibError TEX_NOT_8BIT_PRECISION = -120102; + const LibError TEX_INVALID_LAYOUT = -120103; + const LibError TEX_COMPRESSED = -120104; + const LibError TEX_INVALID_SIZE = -120105; +} + +namespace WARN +{ + const LibError TEX_INVALID_DATA = +120106; +} + +namespace INFO +{ + const LibError TEX_CODEC_CANNOT_HANDLE = +120107; +} + + /** * flags describing the pixel format. these are to be interpreted as * deviations from "plain" format, i.e. uncompressed RGB. diff --git a/source/lib/res/graphics/tex_bmp.cpp b/source/lib/res/graphics/tex_bmp.cpp index e912f9adea..6609b0a9d3 100644 --- a/source/lib/res/graphics/tex_bmp.cpp +++ b/source/lib/res/graphics/tex_bmp.cpp @@ -58,7 +58,7 @@ struct BmpHeader static LibError bmp_transform(Tex* UNUSED(t), uint UNUSED(transforms)) { - return INFO_TEX_CODEC_CANNOT_HANDLE; + return INFO::TEX_CODEC_CANNOT_HANDLE; } @@ -112,13 +112,13 @@ static LibError bmp_decode(DynArray* restrict da, Tex* restrict t) // sanity checks if(compress != BI_RGB) - WARN_RETURN(ERR_TEX_COMPRESSED); + WARN_RETURN(ERR::TEX_COMPRESSED); t->w = w; t->h = h; t->bpp = bpp; t->flags = flags; - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/graphics/tex_codec.cpp b/source/lib/res/graphics/tex_codec.cpp index 150804c935..03209ea200 100644 --- a/source/lib/res/graphics/tex_codec.cpp +++ b/source/lib/res/graphics/tex_codec.cpp @@ -50,7 +50,7 @@ int tex_codec_register(TexCodecVTbl* c) // find codec that recognizes the desired output file extension, -// or return ERR_UNKNOWN_FORMAT if unknown. +// or return ERR::RES_UNKNOWN_FORMAT if unknown. // note: does not raise a warning because it is used by // tex_is_known_extension. LibError tex_codec_for_filename(const char* fn, const TexCodecVTbl** c) @@ -60,10 +60,10 @@ LibError tex_codec_for_filename(const char* fn, const TexCodecVTbl** c) { // we found it if((*c)->is_ext(ext)) - return INFO_OK; + return INFO::OK; } - return ERR_UNKNOWN_FORMAT; // NOWARN + return ERR::RES_UNKNOWN_FORMAT; // NOWARN } @@ -72,16 +72,16 @@ LibError tex_codec_for_header(const u8* file, size_t file_size, const TexCodecVT { // we guarantee at least 4 bytes for is_hdr to look at if(file_size < 4) - WARN_RETURN(ERR_INCOMPLETE_HEADER); + WARN_RETURN(ERR::RES_INCOMPLETE_HEADER); for(*c = codecs; *c; *c = (*c)->next) { // we found it if((*c)->is_hdr(file)) - return INFO_OK; + return INFO::OK; } - WARN_RETURN(ERR_UNKNOWN_FORMAT); + WARN_RETURN(ERR::RES_UNKNOWN_FORMAT); } @@ -98,17 +98,17 @@ const TexCodecVTbl* tex_codec_next(const TexCodecVTbl* prev_codec) LibError tex_codec_transform(Tex* t, uint transforms) { - LibError ret = INFO_TEX_CODEC_CANNOT_HANDLE; + LibError ret = INFO::TEX_CODEC_CANNOT_HANDLE; // find codec that understands the data, and transform for(const TexCodecVTbl* c = codecs; c; c = c->next) { LibError err = c->transform(t, transforms); // success - if(err == INFO_OK) - return INFO_OK; + if(err == INFO::OK) + return INFO::OK; // something went wrong - else if(err != INFO_TEX_CODEC_CANNOT_HANDLE) + else if(err != INFO::TEX_CODEC_CANNOT_HANDLE) { ret = err; debug_warn("codec indicates error"); @@ -150,7 +150,7 @@ LibError tex_codec_alloc_rows(const u8* data, size_t h, size_t pitch, rows = (RowArray)malloc(h * sizeof(RowPtr)); if(!rows) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); // determine start position and direction RowPtr pos = flip? data+pitch*(h-1) : data; @@ -164,7 +164,7 @@ LibError tex_codec_alloc_rows(const u8* data, size_t h, size_t pitch, } debug_assert(pos == end); - return INFO_OK; + return INFO::OK; } @@ -175,5 +175,5 @@ LibError tex_codec_write(Tex* t, uint transforms, const void* hdr, size_t hdr_si void* img_data = tex_get_data(t); const size_t img_size = tex_img_size(t); RETURN_ERR(da_append(da, hdr, hdr_size)); RETURN_ERR(da_append(da, img_data, img_size)); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/graphics/tex_codec.h b/source/lib/res/graphics/tex_codec.h index 5e3a12f401..1eae9a9793 100644 --- a/source/lib/res/graphics/tex_codec.h +++ b/source/lib/res/graphics/tex_codec.h @@ -165,7 +165,7 @@ extern int tex_codec_register(TexCodecVTbl* c); * @param fn filename; only the extension (that after '.') is used. * case-insensitive. * @param c (out) vtbl of responsible codec - * @return LibError; ERR_UNKNOWN_FORMAT (without warning, because this is + * @return LibError; ERR::RES_UNKNOWN_FORMAT (without warning, because this is * called by tex_is_known_extension) if no codec indicates they can * handle the given extension. **/ @@ -178,7 +178,7 @@ extern LibError tex_codec_for_filename(const char* fn, const TexCodecVTbl** c); * (first 4 bytes of) header. * @param data_size [bytes] * @param c (out) vtbl of responsible codec - * @return LibError; ERR_UNKNOWN_FORMAT if no codec indicates they can + * @return LibError; ERR::RES_UNKNOWN_FORMAT if no codec indicates they can * handle the given format (header). **/ extern LibError tex_codec_for_header(const u8* data, size_t data_size, const TexCodecVTbl** c); diff --git a/source/lib/res/graphics/tex_dds.cpp b/source/lib/res/graphics/tex_dds.cpp index 4187abc257..292a36ad96 100644 --- a/source/lib/res/graphics/tex_dds.cpp +++ b/source/lib/res/graphics/tex_dds.cpp @@ -23,7 +23,6 @@ #include "precompiled.h" #include "lib/byte_order.h" -#include "lib/res/mem.h" #include "tex_codec.h" // NOTE: the convention is bottom-up for DDS, but there's no way to tell. @@ -289,7 +288,7 @@ static LibError s3tc_decompress(Tex* t) const size_t out_size = tex_img_size(t) * out_bpp / t->bpp; void* out_data = mem_alloc(out_size, 64*KiB, 0, &hm); if(!out_data) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); const uint s3tc_block_size = (dxt == 3 || dxt == 5)? 16 : 8; S3tcDecompressInfo di = { dxt, s3tc_block_size, out_bpp/8, (u8*)out_data }; @@ -301,7 +300,7 @@ static LibError s3tc_decompress(Tex* t) t->ofs = 0; t->bpp = out_bpp; t->flags &= ~TEX_DXT; - return INFO_OK; + return INFO::OK; } @@ -416,7 +415,7 @@ static LibError decode_pf(const DDPIXELFORMAT* pf, uint* bpp_, uint* flags_) // check struct size if(read_le32(&pf->dwSize) != sizeof(DDPIXELFORMAT)) - WARN_RETURN(ERR_TEX_INVALID_SIZE); + WARN_RETURN(ERR::TEX_INVALID_SIZE); // determine type const u32 pf_flags = read_le32(&pf->dwFlags); @@ -452,7 +451,7 @@ static LibError decode_pf(const DDPIXELFORMAT* pf, uint* bpp_, uint* flags_) // we do not allow any weird orderings that require runtime work. // instead, the artists must export with the correct settings. unsupported_component_ordering: - WARN_RETURN(ERR_TEX_FMT_INVALID); + WARN_RETURN(ERR::TEX_FMT_INVALID); } RETURN_ERR(tex_validate_plain_format(bpp, flags)); @@ -483,16 +482,16 @@ static LibError decode_pf(const DDPIXELFORMAT* pf, uint* bpp_, uint* flags_) break; default: - WARN_RETURN(ERR_TEX_FMT_INVALID); + WARN_RETURN(ERR::TEX_FMT_INVALID); } } // .. neither uncompressed nor compressed - invalid else - WARN_RETURN(ERR_TEX_FMT_INVALID); + WARN_RETURN(ERR::TEX_FMT_INVALID); *bpp_ = bpp; *flags_ = flags; - return INFO_OK; + return INFO::OK; } @@ -505,7 +504,7 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_, { // check header size if(read_le32(&sd->dwSize) != sizeof(*sd)) - WARN_RETURN(ERR_CORRUPTED); + WARN_RETURN(ERR::CORRUPTED); // flags (indicate which fields are valid) const u32 sd_flags = read_le32(&sd->dwFlags); @@ -513,14 +512,14 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_, // note: we can't guess dimensions - the image may not be square. const u32 sd_req_flags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT; if((sd_flags & sd_req_flags) != sd_req_flags) - WARN_RETURN(ERR_INCOMPLETE_HEADER); + WARN_RETURN(ERR::RES_INCOMPLETE_HEADER); // image dimensions const u32 h = read_le32(&sd->dwHeight); const u32 w = read_le32(&sd->dwWidth); // .. not padded to S3TC block size if(w % 4 || h % 4) - WARN_RETURN(ERR_TEX_INVALID_SIZE); + WARN_RETURN(ERR::TEX_INVALID_SIZE); // pixel format uint bpp, flags; @@ -532,12 +531,12 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_, if(sd_flags & DDSD_PITCH) { if(sd_pitch_or_size != round_up(pitch, 4)) - WARN_RETURN(ERR_CORRUPTED); + WARN_RETURN(ERR::CORRUPTED); } if(sd_flags & DDSD_LINEARSIZE) { if(sd_pitch_or_size != pitch*h) - WARN_RETURN(ERR_CORRUPTED); + WARN_RETURN(ERR::CORRUPTED); } // note: both flags set would be invalid; no need to check for that, // though, since one of the above tests would fail. @@ -551,7 +550,7 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_, // mipmap chain is incomplete // note: DDS includes the base level in its count, hence +1. if(mipmap_count != log2(MAX(w,h))+1) - WARN_RETURN(ERR_TEX_FMT_INVALID); + WARN_RETURN(ERR::TEX_FMT_INVALID); flags |= TEX_MIPMAPS; } } @@ -561,7 +560,7 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_, { const u32 depth = read_le32(&sd->dwDepth); if(depth) - WARN_RETURN(ERR_NOT_IMPLEMENTED); + WARN_RETURN(ERR::NOT_IMPLEMENTED); } // check caps @@ -580,7 +579,7 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_, *h_ = h; *bpp_ = bpp; *flags_ = flags; - return INFO_OK; + return INFO::OK; } @@ -618,15 +617,15 @@ static LibError dds_decode(DynArray* restrict da, Tex* restrict t) t->h = h; t->bpp = bpp; t->flags = flags; - return INFO_OK; + return INFO::OK; } static LibError dds_encode(Tex* restrict UNUSED(t), DynArray* restrict UNUSED(da)) { - // note: do not return ERR_NOT_IMPLEMENTED et al. because that would + // note: do not return ERR::NOT_IMPLEMENTED et al. because that would // break tex_write (which assumes either this, 0 or errors are returned). - return INFO_TEX_CODEC_CANNOT_HANDLE; + return INFO::TEX_CODEC_CANNOT_HANDLE; } @@ -640,13 +639,13 @@ static LibError dds_transform(Tex* t, uint transforms) if(dxt && transform_dxt) { RETURN_ERR(s3tc_decompress(t)); - return INFO_OK; + return INFO::OK; } // both are DXT (unsupported; there are no flags we can change while // compressed) or requesting compression (not implemented) or // both not DXT (nothing we can do) - bail. else - return INFO_TEX_CODEC_CANNOT_HANDLE; + return INFO::TEX_CODEC_CANNOT_HANDLE; } diff --git a/source/lib/res/graphics/tex_internal.h b/source/lib/res/graphics/tex_internal.h index 7d5a9088b2..bb0c9752cd 100644 --- a/source/lib/res/graphics/tex_internal.h +++ b/source/lib/res/graphics/tex_internal.h @@ -23,7 +23,7 @@ #ifndef TEX_INTERNAL_H__ #define TEX_INTERNAL_H__ -#include "../mem.h" // MEM_DTOR +#include "lib/res/res.h" // error codes and mem.h #include "lib/allocators.h" // DynArray /** diff --git a/source/lib/res/graphics/tex_jpg.cpp b/source/lib/res/graphics/tex_jpg.cpp index 8d6cb16f5f..590fad9f21 100644 --- a/source/lib/res/graphics/tex_jpg.cpp +++ b/source/lib/res/graphics/tex_jpg.cpp @@ -422,7 +422,7 @@ JpgErrorMgr::JpgErrorMgr(j_common_ptr cinfo) static LibError jpg_transform(Tex* UNUSED(t), uint UNUSED(transforms)) { - return INFO_TEX_CODEC_CANNOT_HANDLE; + return INFO::TEX_CODEC_CANNOT_HANDLE; } @@ -478,7 +478,7 @@ static LibError jpg_decode_impl(DynArray* da, const size_t img_size = pitch * h; // for allow_rows u8* img = (u8*)mem_alloc(img_size, 64*KiB, 0, &img_hm); if(!img) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); // read rows RETURN_ERR(tex_codec_alloc_rows(img, h, pitch, TEX_TOP_DOWN, 0, rows)); @@ -499,9 +499,9 @@ static LibError jpg_decode_impl(DynArray* da, // mem data source. (void)jpeg_finish_decompress(cinfo); - LibError ret = INFO_OK; + LibError ret = INFO::OK; if(cinfo->err->num_warnings != 0) - ret = WARN_TEX_INVALID_DATA; + ret = WARN::TEX_INVALID_DATA; // store image info // .. transparently switch handles - free the old (compressed) @@ -560,9 +560,9 @@ static LibError jpg_encode_impl(Tex* t, jpeg_finish_compress(cinfo); - LibError ret = INFO_OK; + LibError ret = INFO::OK; if(cinfo->err->num_warnings != 0) - ret = WARN_TEX_INVALID_DATA; + ret = WARN::TEX_INVALID_DATA; return ret; } @@ -606,7 +606,7 @@ static LibError jpg_decode(DynArray* restrict da, Tex* restrict t) JpgErrorMgr jerr((j_common_ptr)&cinfo); if(setjmp(jerr.call_site)) { - err = ERR_FAIL; + err = ERR::FAIL; goto fail; } @@ -642,7 +642,7 @@ static LibError jpg_encode(Tex* restrict t, DynArray* restrict da) JpgErrorMgr jerr((j_common_ptr)&cinfo); if(setjmp(jerr.call_site)) { - err = ERR_FAIL; + err = ERR::FAIL; goto fail; } diff --git a/source/lib/res/graphics/tex_png.cpp b/source/lib/res/graphics/tex_png.cpp index 1404981134..328dce34f1 100644 --- a/source/lib/res/graphics/tex_png.cpp +++ b/source/lib/res/graphics/tex_png.cpp @@ -88,7 +88,7 @@ static void io_flush(png_structp UNUSED(png_ptr)) static LibError png_transform(Tex* UNUSED(t), uint UNUSED(transforms)) { - return INFO_TEX_CODEC_CANNOT_HANDLE; + return INFO::TEX_CODEC_CANNOT_HANDLE; } @@ -119,14 +119,14 @@ static LibError png_decode_impl(DynArray* da, // make sure format is acceptable if(bit_depth != 8) - WARN_RETURN(ERR_TEX_NOT_8BIT_PRECISION); + WARN_RETURN(ERR::TEX_NOT_8BIT_PRECISION); if(colour_type & PNG_COLOR_MASK_PALETTE) - WARN_RETURN(ERR_TEX_INVALID_COLOR_TYPE); + WARN_RETURN(ERR::TEX_INVALID_COLOR_TYPE); const size_t img_size = pitch * h; u8* img = (u8*)mem_alloc(img_size, 64*KiB, 0, &img_hm); if(!img) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); RETURN_ERR(tex_codec_alloc_rows(img, h, pitch, TEX_TOP_DOWN, 0, rows)); @@ -146,7 +146,7 @@ static LibError png_decode_impl(DynArray* da, t->bpp = bpp; t->flags = flags; - return INFO_OK; + return INFO::OK; } @@ -189,7 +189,7 @@ static LibError png_encode_impl(Tex* t, png_set_rows(png_ptr, info_ptr, (png_bytepp)rows); png_write_png(png_ptr, info_ptr, png_transforms, 0); - return INFO_OK; + return INFO::OK; } @@ -221,7 +221,7 @@ static LibError png_decode(DynArray* restrict da, Tex* restrict t) { TIMER_ACCRUE(tc_png_decode); - LibError err = ERR_FAIL; + LibError err = ERR::FAIL; // freed when ret is reached: png_structp png_ptr = 0; png_infop info_ptr = 0; @@ -262,7 +262,7 @@ ret: // limitation: palette images aren't supported static LibError png_encode(Tex* restrict t, DynArray* restrict da) { - LibError err = ERR_FAIL; + LibError err = ERR::FAIL; // freed when ret is reached: png_structp png_ptr = 0; png_infop info_ptr = 0; diff --git a/source/lib/res/graphics/tex_tga.cpp b/source/lib/res/graphics/tex_tga.cpp index 831ca0d97a..b4380e410d 100644 --- a/source/lib/res/graphics/tex_tga.cpp +++ b/source/lib/res/graphics/tex_tga.cpp @@ -65,7 +65,7 @@ TgaHeader; static LibError tga_transform(Tex* UNUSED(t), uint UNUSED(transforms)) { - return INFO_TEX_CODEC_CANNOT_HANDLE; + return INFO::TEX_CODEC_CANNOT_HANDLE; } @@ -132,13 +132,13 @@ static LibError tga_decode(DynArray* restrict da, Tex* restrict t) // .. storing right-to-left is just stupid; // we're not going to bother converting it. if(desc & TGA_RIGHT_TO_LEFT) - WARN_RETURN(ERR_TEX_INVALID_LAYOUT); + WARN_RETURN(ERR::TEX_INVALID_LAYOUT); t->w = w; t->h = h; t->bpp = bpp; t->flags = flags; - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/graphics/unifont.cpp b/source/lib/res/graphics/unifont.cpp index 7615ab56f0..589320b97d 100644 --- a/source/lib/res/graphics/unifont.cpp +++ b/source/lib/res/graphics/unifont.cpp @@ -65,7 +65,7 @@ static LibError UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h)) { // already loaded if(f->ht > 0) - return INFO_OK; + return INFO::OK; f->glyphs_id = new glyphmap_id; f->glyphs_size = new glyphmap_size; @@ -85,7 +85,7 @@ static LibError UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h)) int Version; FNTStream >> Version; if (Version != 100) // Make sure this is from a recent version of the font builder - WARN_RETURN(ERR_UNKNOWN_FORMAT); + WARN_RETURN(ERR::RES_UNKNOWN_FORMAT); int TextureWidth, TextureHeight; FNTStream >> TextureWidth >> TextureHeight; @@ -102,7 +102,7 @@ static LibError UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h)) f->ListBase = glGenLists(NumGlyphs); if (f->ListBase == 0) // My Voodoo2 drivers didn't support display lists (although I'd be surprised if they got this far) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); // [cumulative for 12: 256ms] for (int i = 0; i < NumGlyphs; ++i) @@ -166,28 +166,28 @@ static LibError UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h)) f->ht = ht; - return INFO_OK; + return INFO::OK; } static LibError UniFont_validate(const UniFont* f) { if(f->ht < 0) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); if(debug_is_pointer_bogus(f->glyphs_id) || debug_is_pointer_bogus(f->glyphs_size)) - WARN_RETURN(ERR_2); + WARN_RETURN(ERR::_2); // and are read directly from font file. // negative values don't make sense, but that's all we can check. if(f->LineSpacing < 0 || f->Height < 0) - WARN_RETURN(ERR_3); + WARN_RETURN(ERR::_3); if(f->ListBase == 0 || f->ListBase > 1000000) // suspicious - WARN_RETURN(ERR_4); - return INFO_OK; + WARN_RETURN(ERR::_4); + return INFO::OK; } static LibError UniFont_to_string(const UniFont* UNUSED(f), char* buf) { snprintf(buf, H_STRING_LEN, ""); - return INFO_OK; + return INFO::OK; } @@ -211,7 +211,7 @@ LibError unifont_bind(const Handle h) glListBase(f->ListBase); BoundGlyphs = f->glyphs_id; - return INFO_OK; + return INFO::OK; } @@ -311,11 +311,11 @@ LibError unifont_stringsize(const Handle h, const wchar_t* text, int& width, int if (it == f->glyphs_size->end()) // Missing the missing glyph symbol - give up { debug_warn("Missing the missing glyph in a unifont!\n"); - return INFO_OK; + return INFO::OK; } width += it->second; // Add the character's advance distance } - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/h_mgr.cpp b/source/lib/res/h_mgr.cpp index 795a9d7d92..2a091e60cf 100644 --- a/source/lib/res/h_mgr.cpp +++ b/source/lib/res/h_mgr.cpp @@ -289,11 +289,11 @@ static LibError alloc_idx(i32& idx, HDATA*& hd) // add another // .. too many already: IDX_BITS must be increased. if(last_in_use >= hdata_cap) - WARN_RETURN(ERR_LIMIT); + WARN_RETURN(ERR::LIMIT); idx = last_in_use+1; // just incrementing idx would start it at 1 hd = h_data_from_idx(idx); if(!hd) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); // can't fail for any other reason - idx is checked above. { // VC6 goto fix bool is_unused = !hd->tag; @@ -313,7 +313,7 @@ have_idx:; if(idx > last_in_use) last_in_use = idx; - return INFO_OK; + return INFO::OK; } @@ -321,7 +321,7 @@ static LibError free_idx(i32 idx) { if(first_free == -1 || idx < first_free) first_free = idx; - return INFO_OK; + return INFO::OK; } @@ -351,7 +351,7 @@ static Handle key_find(uintptr_t key, H_Type type, KeyRemoveFlag remove_option = { Key2Idx* key2idx = key2idx_wrapper.get(); if(!key2idx) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); // initial return value: "not found at all, or it's of the // wrong type". the latter happens when called by h_alloc to @@ -441,7 +441,7 @@ static void fn_store(HDATA* hd, const char* fn) hd->fn = (const char*)malloc(size); // still failed - bail (avoid strcpy to 0) if(!hd->fn) - WARN_ERR_RETURN(ERR_NO_MEM); + WARN_ERR_RETURN(ERR::NO_MEM); } memcpy2((void*)hd->fn, fn, size); // faster than strcpy @@ -488,7 +488,7 @@ static void warn_if_invalid(HDATA* hd) // have the resource validate its user_data LibError err = vtbl->validate(hd->user); - debug_assert(err == INFO_OK); + debug_assert(err == INFO::OK); // make sure empty space in control block isn't touched // .. but only if we're not storing a filename there @@ -509,13 +509,13 @@ static void warn_if_invalid(HDATA* hd) static LibError type_validate(H_Type type) { if(!type) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); if(type->user_size > HDATA_USER_SIZE) - WARN_RETURN(ERR_LIMIT); + WARN_RETURN(ERR::LIMIT); if(type->name == 0) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); - return INFO_OK; + return INFO::OK; } @@ -545,7 +545,7 @@ static Handle reuse_existing_handle(uintptr_t key, H_Type type, uint flags) HDATA* hd = h_data_tag_type(h, type); // too many references - increase REF_BITS if(hd->refs == REF_MAX) - WARN_RETURN(ERR_LIMIT); + WARN_RETURN(ERR::LIMIT); hd->refs++; @@ -567,7 +567,7 @@ static Handle reuse_existing_handle(uintptr_t key, H_Type type, uint flags) static LibError call_init_and_reload(Handle h, H_Type type, HDATA* hd, const char* fn, va_list* init_args) { - LibError err = INFO_OK; + LibError err = INFO::OK; H_VTbl* vtbl = type; // exact same thing but for clarity // init @@ -581,12 +581,12 @@ static LibError call_init_and_reload(Handle h, H_Type type, HDATA* hd, const cha try { err = vtbl->reload(hd->user, fn, h); - if(err == INFO_OK) + if(err == INFO::OK) warn_if_invalid(hd); } catch(std::bad_alloc) { - err = ERR_NO_MEM; + err = ERR::NO_MEM; } } @@ -694,7 +694,7 @@ static LibError h_free_idx(i32 idx, HDATA* hd) // still references open or caching requests it stays - do not release. if(hd->refs > 0 || hd->keep_open) - return INFO_OK; + return INFO::OK; // actually release the resource (call dtor, free control block). @@ -732,7 +732,7 @@ static LibError h_free_idx(i32 idx, HDATA* hd) free_idx(idx); - return INFO_OK; + return INFO::OK; } @@ -751,10 +751,10 @@ LibError h_free(Handle& h, H_Type type) // 0-initialized or an error code; don't complain because this // happens often and is harmless. if(h_copy <= 0) - return INFO_OK; + return INFO::OK; // this was a valid handle but was probably freed in the meantime. // complain because this probably indicates a bug somewhere. - WARN_RETURN(ERR_INVALID_HANDLE); + WARN_RETURN(ERR::INVALID_HANDLE); } return h_free_idx(idx, hd); @@ -802,7 +802,7 @@ LibError h_reload(const char* fn) // must not continue - some resources not backed by files have // key = 0 and reloading those would be disastrous. if(!fn) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); const u32 key = fnv_hash(fn); @@ -818,7 +818,7 @@ LibError h_reload(const char* fn) hd->type->dtor(hd->user); } - LibError ret = INFO_OK; + LibError ret = INFO::OK; // now reload all affected handles for(i32 i = 0; i <= last_in_use; i++) @@ -863,7 +863,7 @@ LibError h_force_free(Handle h, H_Type type) // require valid index; ignore tag; type checked below. HDATA* hd = h_data_no_tag(h); if(!hd || hd->type != type) - WARN_RETURN(ERR_INVALID_HANDLE); + WARN_RETURN(ERR::INVALID_HANDLE); u32 idx = h_idx(h); hd->keep_open = 0; hd->refs = 0; @@ -904,7 +904,7 @@ int h_get_refcnt(Handle h) { HDATA* hd = h_data_tag(h); if(!hd) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); // if there are no refs, how did the caller manage to keep a Handle?! if(!hd->refs) diff --git a/source/lib/res/h_mgr.h b/source/lib/res/h_mgr.h index 172f087c28..d9760179f4 100644 --- a/source/lib/res/h_mgr.h +++ b/source/lib/res/h_mgr.h @@ -137,7 +137,7 @@ static LibError Type_reload(Res1* r, const char* filename, Handle); r->data = malloc(100); if(!r->data) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); // (read contents of into r->data) return 0; } @@ -191,9 +191,9 @@ static LibError Type_validate(const Res1* r); { const int permissible_flags = 0x01; if(debug_is_pointer_bogus(r->data)) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); if(r->flags & ~permissible_flags) - WARN_RETURN(ERR_2); + WARN_RETURN(ERR::_2); return 0; } @@ -359,12 +359,12 @@ typedef H_VTbl* H_Type; // note: don't use STMT - var decl must be visible to "caller" #define H_DEREF(h, type, var)\ /* h already indicates an error - return immediately to pass back*/\ - /* that specific error, rather than only ERR_INVALID_HANDLE*/\ + /* that specific error, rather than only ERR::INVALID_HANDLE*/\ if(h < 0)\ WARN_RETURN((LibError)h);\ type* const var = H_USER_DATA(h, type);\ if(!var)\ - WARN_RETURN(ERR_INVALID_HANDLE); + WARN_RETURN(ERR::INVALID_HANDLE); // all functions check the passed tag (part of the handle) and type against diff --git a/source/lib/res/mem.cpp b/source/lib/res/mem.cpp index cb1b2541cf..fbdf0863bc 100644 --- a/source/lib/res/mem.cpp +++ b/source/lib/res/mem.cpp @@ -74,7 +74,7 @@ static Handle find_alloc(void* target_raw_p, It* out_it = 0) { Ptr2H* ptr2h = ptr2h_wrapper.get(); if(!ptr2h) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); // early out optimization (don't pay for full subset check) It it = ptr2h->find(target_raw_p); @@ -182,20 +182,20 @@ static void Mem_dtor(Mem* m) static LibError Mem_reload(Mem* m, const char* UNUSED(fn), Handle hm) { set_alloc(m->raw_p, hm); - return INFO_OK; + return INFO::OK; } static LibError Mem_validate(const Mem* m) { if(debug_is_pointer_bogus(m->p)) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); if(!m->size) - WARN_RETURN(ERR_2); + WARN_RETURN(ERR::_2); if(m->raw_p && m->raw_p > m->p) - WARN_RETURN(ERR_3); + WARN_RETURN(ERR::_3); if(m->raw_size && m->raw_size < m->size) - WARN_RETURN(ERR_4); - return INFO_OK; + WARN_RETURN(ERR::_4); + return INFO::OK; } static LibError Mem_to_string(const Mem* m, char* buf) @@ -210,7 +210,7 @@ static LibError Mem_to_string(const Mem* m, char* buf) } snprintf(buf, H_STRING_LEN, "p=%p size=%d owner=%s", m->p, m->size, owner_sym); - return INFO_OK; + return INFO::OK; } @@ -253,7 +253,7 @@ LibError mem_free_h(Handle& hm) LibError mem_free_p(void*& p) { if(!p) - return INFO_OK; + return INFO::OK; Handle hm; { @@ -263,7 +263,7 @@ LibError mem_free_p(void*& p) p = 0; if(hm <= 0) - WARN_RETURN(ERR_ALLOC_NOT_FOUND); + WARN_RETURN(ERR::MEM_ALLOC_NOT_FOUND); return mem_free_h(hm); } @@ -274,7 +274,7 @@ LibError mem_free_p(void*& p) Handle mem_wrap(void* p, size_t size, uint flags, void* raw_p, size_t raw_size, MEM_DTOR dtor, uintptr_t ctx, void* owner) { if(!p || !size) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); SCOPED_LOCK; @@ -318,7 +318,7 @@ LibError mem_assign_user(Handle hm, void* user_p, size_t user_size) m->p = user_p; m->size = user_size; - return INFO_OK; + return INFO::OK; } */ @@ -328,7 +328,7 @@ LibError mem_assign_user(Handle hm, void* user_p, size_t user_size) void* mem_alloc(size_t size, const size_t align, uint flags, Handle* phm) { if(phm) - *phm = ERR_NO_MEM; + *phm = ERR::NO_MEM; #ifdef NDEBUG void* owner = 0; @@ -420,7 +420,7 @@ LibError mem_get(Handle hm, u8** pp, size_t* psize) if(psize) *psize = m->size; // leave hm locked - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/res/mem.h b/source/lib/res/mem.h index 4fab88f31b..b6991fd738 100644 --- a/source/lib/res/mem.h +++ b/source/lib/res/mem.h @@ -27,10 +27,6 @@ #include "handle.h" -#ifdef __cplusplus -extern "C" { -#endif - typedef void (*MEM_DTOR)(void* p, size_t size, uintptr_t ctx); // mem_alloc flags @@ -63,10 +59,4 @@ extern void mem_shutdown(void); - - -#ifdef __cplusplus -} -#endif - #endif // #ifndef MEM_H__ diff --git a/source/lib/res/res.cpp b/source/lib/res/res.cpp new file mode 100644 index 0000000000..5d8489928f --- /dev/null +++ b/source/lib/res/res.cpp @@ -0,0 +1,30 @@ +/** + * ========================================================================= + * File : res.cpp + * Project : 0 A.D. + * Description : + * + * @author Jan.Wassenberg@stud.uni-karlsruhe.de + * ========================================================================= + */ + +/* + * Copyright (c) 2004-2005 Jan Wassenberg + * + * Redistribution and/or modification are also permitted under the + * terms of the GNU General Public License as published by the + * Free Software Foundation (version 2 or later, at your option). + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "precompiled.h" + +#include "res.h" + +AT_STARTUP(\ + error_setDescription(ERR::RES_UNKNOWN_FORMAT, "Unknown file format");\ + error_setDescription(ERR::RES_INCOMPLETE_HEADER, "File header not completely read");\ +) diff --git a/source/lib/res/res.h b/source/lib/res/res.h index 21637c2918..951373dfd6 100644 --- a/source/lib/res/res.h +++ b/source/lib/res/res.h @@ -1,6 +1,18 @@ +#ifndef INCLUDED_RES +#define INCLUDED_RES + // common headers needed by lib/res code #include "h_mgr.h" #include "lib/res/file/vfs.h" #include "lib/path_util.h" #include "mem.h" + + +namespace ERR +{ + const LibError RES_UNKNOWN_FORMAT = -120000; + const LibError RES_INCOMPLETE_HEADER = -120001; +} + +#endif // #ifndef INCLUDED_RES diff --git a/source/lib/res/sound/snd_mgr.cpp b/source/lib/res/sound/snd_mgr.cpp index 03ef5aa65b..a1de6394ef 100644 --- a/source/lib/res/sound/snd_mgr.cpp +++ b/source/lib/res/sound/snd_mgr.cpp @@ -176,7 +176,7 @@ LibError snd_dev_set(const char * alc_new_dev_name) { // already using that device - done. (don't re-init) if(alc_dev_name && !strcmp(alc_dev_name, alc_new_dev_name)) - return INFO_OK; + return INFO::OK; // store name (need to copy it, since alc_init is called later, // and it must then still be valid) @@ -189,7 +189,7 @@ LibError snd_dev_set(const char * alc_new_dev_name) { // already using default device - done. (don't re-init) if(alc_dev_name == 0) - return INFO_OK; + return INFO::OK; alc_dev_name = 0; } @@ -226,7 +226,7 @@ static void alc_shutdown() */ static LibError alc_init() { - LibError ret = INFO_OK; + LibError ret = INFO::OK; #if WIN_LOADLIBRARY_HACK HMODULE dlls[3]; @@ -268,7 +268,7 @@ static LibError alc_init() if(err != ALC_NO_ERROR || !alc_dev || !alc_ctx) { debug_printf("alc_init failed. alc_dev=%p alc_ctx=%p alc_dev_name=%s err=%d\n", alc_dev, alc_ctx, alc_dev_name, err); - ret = ERR_FAIL; + ret = ERR::FAIL; } // make note of which sound device is actually being used @@ -332,7 +332,7 @@ static void al_listener_latch() LibError snd_set_master_gain(float gain) { if(gain < 0) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); al_listener_gain = gain; @@ -340,7 +340,7 @@ LibError snd_set_master_gain(float gain) // position will get sent too. // this isn't called often, so we don't care. - return INFO_OK; + return INFO::OK; } @@ -555,7 +555,7 @@ LibError snd_set_max_voices(uint limit) if(!al_src_allocated || limit < al_src_allocated) { al_src_cap = limit; - return INFO_OK; + return INFO::OK; } // user is requesting a cap higher than what we actually allocated. // that's fine (not an error), but we won't set the cap, since it @@ -563,7 +563,7 @@ LibError snd_set_max_voices(uint limit) // there's no return value to indicate this because the cap is // precisely that - an upper limit only, we don't care if it can't be met. else - return INFO_OK; + return INFO::OK; } @@ -585,7 +585,7 @@ static LibError al_init() { // only take action on first call, OR when re-initializing. if(al_initialized) - return INFO_OK; + return INFO::OK; RETURN_ERR(alc_init()); @@ -595,7 +595,7 @@ static LibError al_init() al_src_init(); al_listener_latch(); - return INFO_OK; + return INFO::OK; } @@ -639,7 +639,7 @@ static LibError al_reinit() // not yet initialized. settings have been saved, and will be // applied by the component init routines called from al_init. if(!al_initialized) - return INFO_OK; + return INFO::OK; // re-init (stops all currently playing sounds) al_shutdown(); @@ -673,10 +673,10 @@ static const char * devs; LibError snd_dev_prepare_enum() { if(alcIsExtensionPresent(0, (ALCchar*)"ALC_ENUMERATION_EXT") != AL_TRUE) - WARN_RETURN(ERR_NO_SYS); + WARN_RETURN(ERR::NO_SYS); devs = (const char*)alcGetString(0, ALC_DEVICE_SPECIFIER); - return INFO_OK; + return INFO::OK; } @@ -781,11 +781,11 @@ static void * io_buf_alloc() { // no buffer allocated if(!io_bufs) - WARN_ERR(ERR_NO_MEM); + WARN_ERR(ERR::NO_MEM); // too many streams - can't happen (tm) because // stream_open enforces MAX_STREAMS. else - WARN_ERR(ERR_LIMIT); + WARN_ERR(ERR::LIMIT); return 0; } @@ -839,16 +839,16 @@ struct Stream static LibError stream_issue(Stream * s) { if(s->active_ios >= MAX_IOS) - return INFO_OK; + return INFO::OK; void * buf = io_buf_alloc(); if(!buf) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); Handle h = vfs_io_issue(s->hf, STREAM_BUF_SIZE, buf); RETURN_ERR(h); s->ios[s->active_ios++] = h; - return INFO_OK; + return INFO::OK; } @@ -859,19 +859,19 @@ static LibError stream_issue(Stream * s) * @param data pointer to buffer * @param size [bytes] * @return LibError; if the first pending IO hasn't completed, - * ERR_AGAIN (not an error). + * ERR::AGAIN (not an error). */ static LibError stream_buf_get(Stream * s, void*& data, size_t& size) { if(s->active_ios == 0) - WARN_RETURN(ERR_EOF); + WARN_RETURN(ERR::IO_EOF); Handle hio = s->ios[0]; // has it finished? if not, bail. int is_complete = vfs_io_has_completed(hio); RETURN_ERR(is_complete); if(is_complete == 0) - return ERR_AGAIN; // NOWARN + return ERR::AGAIN; // NOWARN // get its buffer. // no delay, since vfs_io_has_completed == 1 @@ -879,7 +879,7 @@ static LibError stream_buf_get(Stream * s, void*& data, size_t& size) // (next stream_buf_discard will free this buffer) s->last_buf = data; - return INFO_OK; + return INFO::OK; } @@ -926,7 +926,7 @@ static LibError stream_open(Stream * s, const char * fn) { // bail because we wouldn't have enough IO buffers for all if(active_streams >= MAX_STREAMS) - WARN_RETURN(ERR_LIMIT); + WARN_RETURN(ERR::LIMIT); active_streams++; s->hf = vfs_open(fn); @@ -935,7 +935,7 @@ static LibError stream_open(Stream * s, const char * fn) for(int i = 0; i < MAX_IOS; i++) RETURN_ERR(stream_issue(s)); - return INFO_OK; + return INFO::OK; } @@ -948,7 +948,7 @@ static LibError stream_open(Stream * s, const char * fn) */ static LibError stream_close(Stream * s) { - LibError ret = INFO_OK; + LibError ret = INFO::OK; LibError err; // for each pending IO: @@ -958,7 +958,7 @@ static LibError stream_close(Stream * s) void * data; size_t size; // unused do err = stream_buf_get(s, data, size); - while(err == ERR_AGAIN); + while(err == ERR::AGAIN); if(err < 0 && ret == 0) ret = err; @@ -987,9 +987,9 @@ static LibError stream_close(Stream * s) static LibError stream_validate(const Stream * s) { if(s->active_ios > MAX_IOS) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); // has no invariant we could check. - return INFO_OK; + return INFO::OK; } @@ -1091,7 +1091,7 @@ static LibError SndData_reload(SndData * sd, const char * fn, Handle hsd) if(ogg_supported == -1) ogg_supported = alIsExtensionPresent((ALubyte*)"AL_EXT_vorbis")? 1 : 0; if(!ogg_supported) - WARN_RETURN(ERR_NO_SYS); + WARN_RETURN(ERR::NO_SYS); sd->al_fmt = AL_FORMAT_VORBIS_EXT; sd->al_freq = 0; @@ -1101,7 +1101,7 @@ static LibError SndData_reload(SndData * sd, const char * fn, Handle hsd) } // .. unknown extension else - WARN_RETURN(ERR_UNKNOWN_FORMAT); + WARN_RETURN(ERR::RES_UNKNOWN_FORMAT); // note: WAV is no longer supported. writing our own loader is infeasible // due to a seriously watered down spec with many incompatible variants. @@ -1113,11 +1113,11 @@ static LibError SndData_reload(SndData * sd, const char * fn, Handle hsd) // refuse to stream anything that cannot be passed directly to OpenAL - // we'd have to extract the audio data ourselves (not worth it). if(file_type != FT_OGG) - WARN_RETURN(ERR_NOT_SUPPORTED); + WARN_RETURN(ERR::NOT_SUPPORTED); RETURN_ERR(stream_open(&sd->s, fn)); sd->is_valid = 1; - return INFO_OK; + return INFO::OK; } // else: clip @@ -1162,29 +1162,29 @@ else (void)file_buf_free(file); - return INFO_OK; + return INFO::OK; } static LibError SndData_validate(const SndData * sd) { if(sd->al_fmt == 0) - WARN_RETURN(ERR_11); + WARN_RETURN(ERR::_11); if((uint)sd->al_freq > 100000) // suspicious - WARN_RETURN(ERR_12); + WARN_RETURN(ERR::_12); if(sd->al_buf == 0) - WARN_RETURN(ERR_13); + WARN_RETURN(ERR::_13); if(sd->is_stream) RETURN_ERR(stream_validate(&sd->s)); - return INFO_OK; + return INFO::OK; } static LibError SndData_to_string(const SndData * sd, char * buf) { const char * type = sd->is_stream? "stream" : "clip"; snprintf(buf, H_STRING_LEN, "%s; al_buf=%d", type, sd->al_buf); - return INFO_OK; + return INFO::OK; } @@ -1289,15 +1289,15 @@ static void hsd_list_free_all() * @param hsd Handle to SndData. * @param al_buf buffer name. * @return LibError, most commonly: - * INFO_OK = buffer has been returned; more are expected to be available. - * ERR_EOF = buffer has been returned but is the last one + * INFO::OK = buffer has been returned; more are expected to be available. + * ERR::IO_EOF = buffer has been returned but is the last one * (end of file reached) - * ERR_AGAIN = no buffer returned yet; still streaming in ATM. + * ERR::AGAIN = no buffer returned yet; still streaming in ATM. * call back later. */ static LibError snd_data_buf_get(Handle hsd, ALuint& al_buf) { - LibError err = INFO_OK; + LibError err = INFO::OK; // in case H_DEREF fails al_buf = 0; @@ -1308,7 +1308,7 @@ static LibError snd_data_buf_get(Handle hsd, ALuint& al_buf) if(!sd->is_stream) { al_buf = sd->al_buf; - return ERR_EOF; // NOWARN + return ERR::IO_EOF; // NOWARN } // stream: @@ -1317,8 +1317,8 @@ static LibError snd_data_buf_get(Handle hsd, ALuint& al_buf) void * data; size_t size; err = stream_buf_get(&sd->s, data, size); - if(err == ERR_AGAIN) - return ERR_AGAIN; // NOWARN + if(err == ERR::AGAIN) + return ERR::AGAIN; // NOWARN RETURN_ERR(err); // .. yes: pass to OpenAL and discard IO buffer. @@ -1328,12 +1328,12 @@ static LibError snd_data_buf_get(Handle hsd, ALuint& al_buf) // .. try to issue the next IO. // if EOF reached, indicate al_buf is the last that will be returned. err = stream_issue(&sd->s); - if(err == ERR_EOF) - return ERR_EOF; // NOWARN + if(err == ERR::IO_EOF) + return ERR::IO_EOF; // NOWARN RETURN_ERR(err); // al_buf valid and next IO issued successfully. - return INFO_OK; + return INFO::OK; } @@ -1351,11 +1351,11 @@ static LibError snd_data_buf_free(Handle hsd, ALuint al_buf) // clip: no-op (caller will later release hsd reference; // when hsd actually unloads, sd->al_buf will be freed). if(!sd->is_stream) - return INFO_OK; + return INFO::OK; // stream: we had allocated an additional buffer, so free it now. al_buf_free(al_buf); - return INFO_OK; + return INFO::OK; } @@ -1577,7 +1577,7 @@ static LibError VSrc_reload(VSrc * vs, const char * fn, Handle hvs) // must load OpenAL so that snd_data_load can check for OGG extension. LibError err = snd_init(); // .. don't complain if sound is disabled; fail silently. - if(err == ERR_AGAIN) + if(err == ERR::AGAIN) return err; // .. catch genuine errors during init. RETURN_ERR(err); @@ -1625,29 +1625,29 @@ static LibError VSrc_reload(VSrc * vs, const char * fn, Handle hvs) vs->hsd = snd_data_load(snd_fn, is_stream); RETURN_ERR(vs->hsd); - return INFO_OK; + return INFO::OK; } static LibError VSrc_validate(const VSrc * vs) { // al_src can legitimately be 0 (if vs is low-pri) if(vs->flags & ~VS_ALL_FLAGS) - WARN_RETURN(ERR_1); + WARN_RETURN(ERR::_1); // no limitations on if(!(0.0f <= vs->gain && vs->gain <= 1.0f)) - WARN_RETURN(ERR_2); + WARN_RETURN(ERR::_2); if(!(0.0f < vs->pitch && vs->pitch <= 1.0f)) - WARN_RETURN(ERR_3); + WARN_RETURN(ERR::_3); if(*(u8*)&vs->loop > 1 || *(u8*)&vs->relative > 1) - WARN_RETURN(ERR_4); + WARN_RETURN(ERR::_4); // and have no invariant we could check. - return INFO_OK; + return INFO::OK; } static LibError VSrc_to_string(const VSrc * vs, char * buf) { snprintf(buf, H_STRING_LEN, "al_src = %d", vs->al_src); - return INFO_OK; + return INFO::OK; } @@ -1665,7 +1665,7 @@ static LibError VSrc_to_string(const VSrc * vs, char * buf) * or loaded immediately. * @return Handle or LibError on failure */ -Handle snd_open(const char * snd_fn, bool is_stream) +Handle snd_open(const char* snd_fn, bool is_stream) { uint flags = 0; if(is_stream) @@ -1797,7 +1797,7 @@ static void vsrc_free(VSrc * vs) { snd_free(vs->hvs); } static LibError list_free_all() { list_foreach(vsrc_free); - return INFO_OK; + return INFO::OK; } @@ -1873,14 +1873,14 @@ static double snd_update_time; static LibError vsrc_update(VSrc * vs) { if(!vs->al_src) - return INFO_OK; + return INFO::OK; FadeRet ret = fade(vs->fade, snd_update_time, vs->gain); // auto-free after fadeout. if(ret == FADE_TO_0_FINISHED) { vsrc_free(vs); - return INFO_OK; // don't continue - has been freed. + return INFO::OK; // don't continue - has been freed. } // fade in progress; latch current gain value. else if(ret == FADE_CHANGED) @@ -1898,7 +1898,7 @@ static LibError vsrc_update(VSrc * vs) if(num_queued == 0) { snd_free(vs->hvs); - return INFO_OK; + return INFO::OK; } } // can still read from SndData @@ -1917,20 +1917,20 @@ static LibError vsrc_update(VSrc * vs) ALuint al_buf; ret = snd_data_buf_get(vs->hsd, al_buf); // these 2 are legit (see above); otherwise, bail. - if(ret != ERR_AGAIN && ret != ERR_EOF) + if(ret != ERR::AGAIN && ret != ERR::IO_EOF) RETURN_ERR(ret); alSourceQueueBuffers(vs->al_src, 1, &al_buf); al_check("vsrc_update alSourceQueueBuffers"); } - while(to_fill-- && ret == INFO_OK); + while(to_fill-- && ret == INFO::OK); // SndData has reported that no further buffers are available. - if(ret == ERR_EOF) + if(ret == ERR::IO_EOF) vs->flags |= VS_EOF; } - return INFO_OK; + return INFO::OK; } @@ -1939,19 +1939,19 @@ static LibError vsrc_update(VSrc * vs) * called by snd_play and voice management. * * @param VSrc* - * @return LibError (ERR_FAIL if no AL source is available) + * @return LibError (ERR::FAIL if no AL source is available) */ static LibError vsrc_grant(VSrc * vs) { // already playing - bail if(vs->al_src) - return INFO_OK; + return INFO::OK; // try to alloc source. if none are available, bail - // we get called in that hope that one is available by snd_play. vs->al_src = al_src_alloc(); if(!vs->al_src) - return ERR_FAIL; // NOWARN + return ERR::FAIL; // NOWARN // OpenAL docs don't specify default values, so initialize everything // ourselves to be sure. note: alSourcefv param is not const. @@ -1970,7 +1970,7 @@ static LibError vsrc_grant(VSrc * vs) alSourcePlay(vs->al_src); AL_CHECK; - return INFO_OK; + return INFO::OK; } @@ -1986,7 +1986,7 @@ static LibError vsrc_reclaim(VSrc * vs) { // don't own a source - bail. if(!vs->al_src) - return ERR_FAIL; // NOWARN + return ERR::FAIL; // NOWARN alSourceStop(vs->al_src); AL_CHECK; @@ -1996,7 +1996,7 @@ static LibError vsrc_reclaim(VSrc * vs) vsrc_deque_finished_bufs(vs); al_src_free(vs->al_src); - return INFO_OK; + return INFO::OK; } @@ -2031,7 +2031,7 @@ LibError snd_play(Handle hvs, float static_pri) // either we get a source and playing begins immediately, // or it'll be taken care of on next update. vsrc_grant(vs); - return INFO_OK; + return INFO::OK; } @@ -2055,7 +2055,7 @@ LibError snd_set_pos(Handle hvs, float x, float y, float z, bool relative) vs->relative = relative; vsrc_latch(vs); - return INFO_OK; + return INFO::OK; } @@ -2076,18 +2076,18 @@ LibError snd_set_gain(Handle hvs, float gain) H_DEREF(hvs, VSrc, vs); if(!(0.0f <= gain && gain <= 1.0f)) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); // if fading, gain changes would be overridden during the next // snd_update. attempting this indicates a logic error. we abort to // avoid undesired jumps in gain that might surprise (and deafen) user. if(fade_is_active(vs->fade)) - WARN_RETURN(ERR_LOGIC); + WARN_RETURN(ERR::LOGIC); vs->gain = gain; vsrc_latch(vs); - return INFO_OK; + return INFO::OK; } @@ -2107,12 +2107,12 @@ LibError snd_set_pitch(Handle hvs, float pitch) H_DEREF(hvs, VSrc, vs); if(!(0.0f < pitch && pitch <= 1.0f)) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); vs->pitch = pitch; vsrc_latch(vs); - return INFO_OK; + return INFO::OK; } @@ -2140,7 +2140,7 @@ LibError snd_set_loop(Handle hvs, bool loop) vs->loop = loop; vsrc_latch(vs); - return INFO_OK; + return INFO::OK; } @@ -2180,7 +2180,7 @@ LibError snd_fade(Handle hvs, float initial_gain, float final_gain, if(type != FT_LINEAR && type != FT_EXPONENTIAL && type != FT_S_CURVE && type != FT_ABORT) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); // special case - set initial value to current gain (see above). if(initial_gain < 0.0f) @@ -2198,7 +2198,7 @@ LibError snd_fade(Handle hvs, float initial_gain, float final_gain, (void)fade(fi, cur_time, vs->gain); vsrc_latch(vs); - return INFO_OK; + return INFO::OK; } @@ -2288,7 +2288,7 @@ static LibError vm_update() list_foreach(reclaim, first_unimportant, 0); list_foreach(grant, 0, first_unimportant); - return INFO_OK; + return INFO::OK; } @@ -2312,7 +2312,7 @@ LibError snd_update(const float * pos, const float * dir, const float * up) // this fails, so report success here (everything will work once // sound is re-enabled). if(!al_initialized) - return INFO_OK; + return INFO::OK; if(pos) al_listener_set_pos(pos, dir, up); @@ -2323,7 +2323,7 @@ LibError snd_update(const float * pos, const float * dir, const float * up) snd_update_time = get_time(); // see decl list_foreach((void (*)(VSrc*))vsrc_update); - return INFO_OK; + return INFO::OK; } @@ -2334,13 +2334,13 @@ static bool snd_disabled = false; * extra layer on top of al_init that allows 'disabling' sound. * called from each snd_open. * - * @return LibError from al_init, or ERR_AGAIN if sound disabled + * @return LibError from al_init, or ERR::AGAIN if sound disabled */ static inline LibError snd_init() { // (note: each VSrc_reload and therefore snd_open will fail) if(snd_disabled) - return ERR_AGAIN; // NOWARN + return ERR::AGAIN; // NOWARN return al_init(); } @@ -2370,11 +2370,11 @@ LibError snd_disable(bool disabled) { if(al_initialized) debug_warn("already initialized => disable is pointless"); - return INFO_OK; + return INFO::OK; } else return snd_init(); - // note: won't return ERR_AGAIN, since snd_disabled == false + // note: won't return ERR::AGAIN, since snd_disabled == false } diff --git a/source/lib/self_test.h b/source/lib/self_test.h index e68c6ea1cc..8417641995 100644 --- a/source/lib/self_test.h +++ b/source/lib/self_test.h @@ -186,7 +186,7 @@ extern bool self_test_active; #include -#define TS_ASSERT_OK(expr) TS_ASSERT_EQUALS((expr), INFO_OK) +#define TS_ASSERT_OK(expr) TS_ASSERT_EQUALS((expr), INFO::OK) #define TS_ASSERT_STR_EQUALS(str1, str2) TS_ASSERT_EQUALS(std::string(str1), std::string(str2)) #endif // #ifndef SELF_TEST_H__ diff --git a/source/lib/string_s.cpp b/source/lib/string_s.cpp index b72a298394..5643e37cae 100644 --- a/source/lib/string_s.cpp +++ b/source/lib/string_s.cpp @@ -28,6 +28,15 @@ #include "posix.h" // SIZE_MAX +// we were included from wstring_s.cpp; skip all stuff that +// must only be done once. +#ifndef WSTRING_S +AT_STARTUP(\ + error_setDescription(ERR::STRING_NOT_TERMINATED, "Invalid string (no 0 terminator found in buffer)")\ +) +#endif + + // written against http://std.dkuug.dk/jtc1/sc22/wg14/www/docs/n1031.pdf . // optimized for size - e.g. strcpy calls strncpy with n = SIZE_MAX. @@ -117,10 +126,10 @@ int tncpy_s(tchar* dst, size_t max_dst_chars, const tchar* src, size_t max_src_c // the MS implementation returns EINVAL and allows dst = 0 if // max_dst_chars = max_src_chars = 0. no mention of this in // 3.6.2.1.1, so don't emulate that behavior. - ENFORCE(dst != 0, ERR_INVALID_PARAM, EINVAL); - ENFORCE(max_dst_chars != 0, ERR_INVALID_PARAM, ERANGE); + ENFORCE(dst != 0, ERR::INVALID_PARAM, EINVAL); + ENFORCE(max_dst_chars != 0, ERR::INVALID_PARAM, ERANGE); *dst = '\0'; // in case src ENFORCE is triggered - ENFORCE(src != 0, ERR_INVALID_PARAM, EINVAL); + ENFORCE(src != 0, ERR::INVALID_PARAM, EINVAL); WARN_IF_PTR_LEN(max_dst_chars); WARN_IF_PTR_LEN(max_src_chars); @@ -143,7 +152,7 @@ int tncpy_s(tchar* dst, size_t max_dst_chars, const tchar* src, size_t max_src_c if(max_dst_chars <= max_src_chars) { *dst = '\0'; - ENFORCE(0, ERR_BUF_SIZE, ERANGE); + ENFORCE(0, ERR::BUF_SIZE, ERANGE); } // .. source: success, but still need to null-terminate the destination. *p = '\0'; @@ -167,8 +176,8 @@ int tcpy_s(tchar* dst, size_t max_dst_chars, const tchar* src) // 0 is returned to indicate success and that is null-terminated. int tncat_s(tchar* dst, size_t max_dst_chars, const tchar* src, size_t max_src_chars) { - ENFORCE(dst != 0, ERR_INVALID_PARAM, EINVAL); - ENFORCE(max_dst_chars != 0, ERR_INVALID_PARAM, ERANGE); + ENFORCE(dst != 0, ERR::INVALID_PARAM, EINVAL); + ENFORCE(max_dst_chars != 0, ERR::INVALID_PARAM, ERANGE); // src is checked in tncpy_s // WARN_IF_PTR_LEN not necessary: both max_dst_chars and max_src_chars @@ -178,7 +187,7 @@ int tncat_s(tchar* dst, size_t max_dst_chars, const tchar* src, size_t max_src_c if(dst_len == max_dst_chars) { *dst = '\0'; - ENFORCE(0, ERR_STRING_NOT_TERMINATED, ERANGE); + ENFORCE(0, ERR::STRING_NOT_TERMINATED, ERANGE); } tchar* const end = dst+dst_len; diff --git a/source/lib/string_s.h b/source/lib/string_s.h index b3a36f327c..d6b6576c76 100644 --- a/source/lib/string_s.h +++ b/source/lib/string_s.h @@ -26,6 +26,12 @@ #include "posix_types.h" // size_t #include "config.h" + +namespace ERR +{ + const LibError STRING_NOT_TERMINATED = -100600; +} + // only declare these functions if using our implementation // (otherwise, we risk incompatibilities) #if !HAVE_STRING_S diff --git a/source/lib/sysdep/cpu.cpp b/source/lib/sysdep/cpu.cpp index b9c2ff66d0..91fe715911 100644 --- a/source/lib/sysdep/cpu.cpp +++ b/source/lib/sysdep/cpu.cpp @@ -29,6 +29,14 @@ # include "lib/sysdep/ia32.h" #endif + +AT_STARTUP(\ + error_setDescription(ERR::CPU_FEATURE_MISSING, "This CPU doesn't support a required feature");\ + error_setDescription(ERR::CPU_UNKNOWN_OPCODE, "Disassembly failed");\ + error_setDescription(ERR::CPU_RESTRICTED_AFFINITY, "Cannot set desired CPU affinity");\ +) + + char cpu_type[CPU_TYPE_LEN] = ""; double cpu_freq = 0.f; diff --git a/source/lib/sysdep/cpu.h b/source/lib/sysdep/cpu.h index 7f0a80c45d..224257f5ef 100644 --- a/source/lib/sysdep/cpu.h +++ b/source/lib/sysdep/cpu.h @@ -23,9 +23,13 @@ #ifndef CPU_H__ #define CPU_H__ -#ifdef __cplusplus -extern "C" { -#endif + +namespace ERR +{ + const LibError CPU_FEATURE_MISSING = -130000; + const LibError CPU_UNKNOWN_OPCODE = -130001; + const LibError CPU_RESTRICTED_AFFINITY = -130002; +} const size_t CPU_TYPE_LEN = 49; // IA32 processor brand string is <= 48 chars @@ -36,7 +40,7 @@ extern double cpu_freq; // -1 if detect not yet called, or cannot be determined: -extern int cpus; // # packages (i.e. sockets; > 1 => SMP system) +extern "C" int cpus; // # packages (i.e. sockets; > 1 => SMP system) extern int cpu_ht_units; // degree of hyperthreading, typically 2 extern int cpu_cores; // cores per package, typically 2 @@ -56,7 +60,7 @@ extern void get_mem_status(void); // atomic "compare and swap". compare the machine word at against // ; if not equal, return false; otherwise, overwrite it with // and return true. -extern bool CAS_(uintptr_t* location, uintptr_t expected, uintptr_t new_value); +extern "C" bool CAS_(uintptr_t* location, uintptr_t expected, uintptr_t new_value); // this is often used for pointers, so the macro coerces parameters to // uinptr_t. invalid usage unfortunately also goes through without warnings. @@ -64,12 +68,12 @@ extern bool CAS_(uintptr_t* location, uintptr_t expected, uintptr_t new_value); // similar mishaps, the implementation verifies is a valid pointer. #define CAS(l,o,n) CAS_((uintptr_t*)l, (uintptr_t)o, (uintptr_t)n) -extern void atomic_add(intptr_t* location, intptr_t increment); +extern "C" void atomic_add(intptr_t* location, intptr_t increment); // enforce strong memory ordering. -extern void mfence(); +extern "C" void mfence(); -extern void serialize(); +extern "C" void serialize(); // Win32 CONTEXT field abstraction @@ -84,8 +88,4 @@ extern void serialize(); # define SP_ Esp #endif -#ifdef __cplusplus -} -#endif - #endif // #ifndef CPU_H__ diff --git a/source/lib/sysdep/gfx.cpp b/source/lib/sysdep/gfx.cpp index 8795cb05c8..3512823950 100644 --- a/source/lib/sysdep/gfx.cpp +++ b/source/lib/sysdep/gfx.cpp @@ -32,7 +32,7 @@ char gfx_drv_ver[GFX_DRV_VER_LEN] = ""; int gfx_mem = -1; // [MiB]; approximate -extern "C" LibError ogl_get_gfx_info(); +extern LibError ogl_get_gfx_info(); // detect graphics card and set the above information. void gfx_detect() diff --git a/source/lib/sysdep/gfx.h b/source/lib/sysdep/gfx.h index 94629fa75b..45f9942668 100644 --- a/source/lib/sysdep/gfx.h +++ b/source/lib/sysdep/gfx.h @@ -23,10 +23,6 @@ #ifndef GFX_H__ #define GFX_H__ -#ifdef __cplusplus -extern "C" { -#endif - const size_t GFX_CARD_LEN = 128; /** * description of graphics card. @@ -63,7 +59,7 @@ extern void gfx_detect(void); * @param xres, yres (optional out) resolution [pixels] * @param bpp (optional out) bits per pixel * @param freq (optional out) vertical refresh rate [Hz] - * @return LibError; INFO_OK unless: some information was requested + * @return LibError; INFO::OK unless: some information was requested * (i.e. pointer is non-NULL) but cannot be returned. * on failure, the outputs are all left unchanged (they are * assumed initialized to defaults) @@ -83,9 +79,4 @@ extern LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq); **/ extern LibError gfx_get_monitor_size(int& width_mm, int& height_mm); - -#ifdef __cplusplus -} -#endif - #endif // #ifndef GFX_H__ diff --git a/source/lib/sysdep/ia32.cpp b/source/lib/sysdep/ia32.cpp index 668df0ab43..1ae0288790 100644 --- a/source/lib/sysdep/ia32.cpp +++ b/source/lib/sysdep/ia32.cpp @@ -43,8 +43,10 @@ #error ia32.cpp needs inline assembly support! #endif +extern "C" { + // set by ia32_init, referenced by ia32_memcpy (asm) -extern "C" u32 ia32_memcpy_size_mask = 0; +extern u32 ia32_memcpy_size_mask = 0; void ia32_init() { @@ -616,7 +618,7 @@ void ia32_get_cpu_info() // checks if there is an IA-32 CALL instruction right before ret_addr. -// returns INFO_OK if so and ERR_FAIL if not. +// returns INFO::OK if so and ERR::FAIL if not. // also attempts to determine the call target. if that is possible // (directly addressed relative or indirect jumps), it is stored in // target, which is otherwise 0. @@ -637,13 +639,13 @@ LibError ia32_get_call_target(void* ret_addr, void** target) if(len >= 5 && c[-5] == 0xE8) { *target = (u8*)ret_addr + *(i32*)(c-4); - return INFO_OK; + return INFO::OK; } // CALL r/m32 (FF /2) // .. CALL [r32 + r32*s] => FF 14 SIB if(len >= 3 && c[-3] == 0xFF && c[-2] == 0x14) - return INFO_OK; + return INFO::OK; // .. CALL [disp32] => FF 15 disp32 if(len >= 6 && c[-6] == 0xFF && c[-5] == 0x15) { @@ -653,26 +655,28 @@ LibError ia32_get_call_target(void* ret_addr, void** target) // even if the pointer is 0, it's better to pass its value on // (may help in tracking down memory corruption) *target = *(void**)addr_of_target; - return INFO_OK; + return INFO::OK; } // .. CALL [r32] => FF 00-3F(!14/15) if(len >= 2 && c[-2] == 0xFF && c[-1] < 0x40 && c[-1] != 0x14 && c[-1] != 0x15) - return INFO_OK; + return INFO::OK; // .. CALL [r32 + r32*s + disp8] => FF 54 SIB disp8 if(len >= 4 && c[-4] == 0xFF && c[-3] == 0x54) - return INFO_OK; + return INFO::OK; // .. CALL [r32 + disp8] => FF 50-57(!54) disp8 if(len >= 3 && c[-3] == 0xFF && (c[-2] & 0xF8) == 0x50 && c[-2] != 0x54) - return INFO_OK; + return INFO::OK; // .. CALL [r32 + r32*s + disp32] => FF 94 SIB disp32 if(len >= 7 && c[-7] == 0xFF && c[-6] == 0x94) - return INFO_OK; + return INFO::OK; // .. CALL [r32 + disp32] => FF 90-97(!94) disp32 if(len >= 6 && c[-6] == 0xFF && (c[-5] & 0xF8) == 0x90 && c[-5] != 0x94) - return INFO_OK; + return INFO::OK; // .. CALL r32 => FF D0-D7 if(len >= 2 && c[-2] == 0xFF && (c[-1] & 0xF8) == 0xD0) - return INFO_OK; + return INFO::OK; - WARN_RETURN(ERR_CPU_UNKNOWN_OPCODE); + WARN_RETURN(ERR::CPU_UNKNOWN_OPCODE); } + +} // extern "C" diff --git a/source/lib/sysdep/ia32.h b/source/lib/sysdep/ia32.h index 2abe43e6a3..ec8e080215 100644 --- a/source/lib/sysdep/ia32.h +++ b/source/lib/sysdep/ia32.h @@ -143,7 +143,7 @@ extern void ia32_get_current_context(void* pcontext); extern void ia32_asm_init(); // checks if there is an IA-32 CALL instruction right before ret_addr. -// returns INFO_OK if so and ERR_FAIL if not. +// returns INFO::OK if so and ERR::FAIL if not. // also attempts to determine the call target. if that is possible // (directly addressed relative or indirect jumps), it is stored in // target, which is otherwise 0. diff --git a/source/lib/sysdep/snd.h b/source/lib/sysdep/snd.h index 6f0fb133eb..b6acc146be 100644 --- a/source/lib/sysdep/snd.h +++ b/source/lib/sysdep/snd.h @@ -23,11 +23,6 @@ #ifndef SND_H__ #define SND_H__ -#ifdef __cplusplus -extern "C" { -#endif - - const size_t SND_CARD_LEN = 128; /** * description of sound card. @@ -45,9 +40,4 @@ extern char snd_drv_ver[SND_DRV_VER_LEN]; **/ extern void snd_detect(void); - -#ifdef __cplusplus -} -#endif - #endif // #ifndef SND_H__ diff --git a/source/lib/sysdep/sysdep.h b/source/lib/sysdep/sysdep.h index 5971f26954..b02dac2433 100644 --- a/source/lib/sysdep/sysdep.h +++ b/source/lib/sysdep/sysdep.h @@ -78,11 +78,6 @@ #endif -#ifdef __cplusplus -extern "C" { -#endif - - //----------------------------------------------------------------------------- // C99 / SUSv3 emulation where needed //----------------------------------------------------------------------------- @@ -149,9 +144,7 @@ extern void* alloca(size_t size); // Some systems have C99 support but in C++ they provide only std::isfinite // and not isfinite. C99 specifies that isfinite is a macro, so we can use // #ifndef and define it if it's not there already. -// Since sysdep.h will normally be included before cmath is, we need to load -// cmath first to let it define/undef that macro. (That's awkward here inside -// the 'extern "C"', so it's included at the top of this file.) +// We've included above to make sure it defines that macro. # ifndef isfinite # define isfinite std::isfinite # define isnan std::isnan @@ -236,7 +229,7 @@ extern LibError sys_clipboard_free(wchar_t* copy); // it is no longer needed and can be freed after this call returns. // hotspot (hx,hy) is the offset from its upper-left corner to the // position where mouse clicks are registered. -// cursor is only valid when INFO_OK is returned; in that case, it must be +// cursor is only valid when INFO::OK is returned; in that case, it must be // sys_cursor_free-ed when no longer needed. extern LibError sys_cursor_create(uint w, uint h, void* bgra_img, uint hx, uint hy, void** cursor); @@ -360,11 +353,6 @@ extern size_t sys_max_sector_size(); #endif -#ifdef __cplusplus -} -#endif - - //----------------------------------------------------------------------------- // STL_HASH_MAP, STL_HASH_MULTIMAP, STL_HASH_SET //----------------------------------------------------------------------------- diff --git a/source/lib/sysdep/win/delay_load.cpp b/source/lib/sysdep/win/delay_load.cpp index e8328c2ecf..897c0a15bf 100644 --- a/source/lib/sysdep/win/delay_load.cpp +++ b/source/lib/sysdep/win/delay_load.cpp @@ -601,7 +601,7 @@ static LibError wdll_shutdown() // changes __puiHead! } - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/dll_ver.cpp b/source/lib/sysdep/win/dll_ver.cpp index 06e1be961a..258fb70e8c 100644 --- a/source/lib/sysdep/win/dll_ver.cpp +++ b/source/lib/sysdep/win/dll_ver.cpp @@ -46,14 +46,14 @@ static LibError get_ver(const char* module_path, char* out_ver, size_t out_ver_l wchar_t buf[1000]; swprintf(buf, 1000, L"path: %hs; GLE: %08X", module_path, GetLastError()); DISPLAY_ERROR(buf); - return ERR_FAIL; -// WARN_RETURN(ERR_FAIL); + return ERR::FAIL; +// WARN_RETURN(ERR::FAIL); } void* buf = malloc(ver_size); if(!buf) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); - LibError ret = ERR_FAIL; // single point of exit (for free()) + LibError ret = ERR::FAIL; // single point of exit (for free()) if(GetFileVersionInfo(module_path, 0, ver_size, buf)) { @@ -69,7 +69,7 @@ static LibError get_ver(const char* module_path, char* out_ver, size_t out_ver_l if(VerQueryValue(buf, subblock, (void**)&in_ver, &in_ver_len)) { strcpy_s(out_ver, out_ver_len, in_ver); - ret = INFO_OK; + ret = INFO::OK; } } } @@ -106,7 +106,7 @@ LibError dll_list_add(const char* name) { // not be called before dll_list_init or after failure if(!dll_list_pos) - WARN_RETURN(ERR_LOGIC); + WARN_RETURN(ERR::LOGIC); // some driver names are stored in the registry without .dll extension. // if necessary, copy to new buffer and add it there. @@ -141,11 +141,11 @@ LibError dll_list_add(const char* name) if(len > 0) { dll_list_pos += len; - return INFO_OK; + return INFO::OK; } // didn't fit; complain sprintf(dll_list_pos, "..."); // (room was reserved above) dll_list_pos = 0; // poison pill, prevent further calls - WARN_RETURN(ERR_BUF_SIZE); + WARN_RETURN(ERR::BUF_SIZE); } diff --git a/source/lib/sysdep/win/printf.cpp b/source/lib/sysdep/win/printf.cpp index e81953975d..ac4f06dd37 100644 --- a/source/lib/sysdep/win/printf.cpp +++ b/source/lib/sysdep/win/printf.cpp @@ -169,7 +169,7 @@ int type_size(TCHAR type, int length) return 0; } -extern "C" int vsnprintf2(TCHAR* buffer, size_t count, const TCHAR* format, va_list argptr) +int vsnprintf2(TCHAR* buffer, size_t count, const TCHAR* format, va_list argptr) { /* diff --git a/source/lib/sysdep/win/waio.cpp b/source/lib/sysdep/win/waio.cpp index 50faa69380..4e6663e928 100644 --- a/source/lib/sysdep/win/waio.cpp +++ b/source/lib/sysdep/win/waio.cpp @@ -207,7 +207,7 @@ static HANDLE aio_h_get(const int fd) static LibError aio_h_set(const int fd, const HANDLE h) { if(fd < 0) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); lock(); @@ -220,7 +220,7 @@ static LibError aio_h_set(const int fd, const HANDLE h) HANDLE* hs2 = (HANDLE*)realloc(aio_hs, size2*sizeof(HANDLE)); if(!hs2) { - err = ERR_NO_MEM; + err = ERR::NO_MEM; goto fail; } // don't assign directly from realloc - @@ -242,13 +242,13 @@ static LibError aio_h_set(const int fd, const HANDLE h) // already set if(aio_hs[fd] != INVALID_HANDLE_VALUE) { - err = ERR_LOGIC; + err = ERR::LOGIC; goto fail; } // setting invalid handle if(!is_valid_file_handle(h)) { - err = ERR_TNODE_WRONG_TYPE; + err = ERR::INVALID_HANDLE; goto fail; } } @@ -256,7 +256,7 @@ static LibError aio_h_set(const int fd, const HANDLE h) aio_hs[fd] = h; unlock(); - return INFO_OK; + return INFO::OK; fail: unlock(); @@ -435,7 +435,7 @@ static LibError req_free(Req* r) { debug_assert(r->cb != 0 && "req_free: not currently in use"); r->cb = 0; - return INFO_OK; + return INFO::OK; } @@ -596,7 +596,7 @@ static int aio_rw(struct aiocb* cb) ok = TRUE; // .. translate from Win32 result code to POSIX LibError err = LibError_from_win32(ok); - if(err == INFO_OK) + if(err == INFO::OK) ret = 0; LibError_set_errno(err); @@ -797,7 +797,7 @@ int aio_fsync(int, struct aiocb*) static LibError waio_init() { req_init(); - return INFO_OK; + return INFO::OK; } @@ -805,5 +805,5 @@ static LibError waio_shutdown() { req_cleanup(); aio_h_cleanup(); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wcpu.cpp b/source/lib/sysdep/win/wcpu.cpp index 79b0561408..e0bf89086f 100644 --- a/source/lib/sysdep/win/wcpu.cpp +++ b/source/lib/sysdep/win/wcpu.cpp @@ -117,7 +117,7 @@ LibError win_get_cpu_info() check_speedstep(); - return INFO_OK; + return INFO::OK; } @@ -136,11 +136,11 @@ LibError sys_on_each_cpu(void (*cb)()) const HANDLE hProcess = GetCurrentProcess(); DWORD process_affinity, system_affinity; if(!GetProcessAffinityMask(hProcess, &process_affinity, &system_affinity)) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); // our affinity != system affinity: OS is limiting the CPUs that // this process can run on. fail (cannot call back for each CPU). if(process_affinity != system_affinity) - WARN_RETURN(ERR_CPU_RESTRICTED_AFFINITY); + WARN_RETURN(ERR::CPU_RESTRICTED_AFFINITY); for(DWORD cpu_bit = 1; cpu_bit != 0 && cpu_bit <= process_affinity; cpu_bit *= 2) { @@ -150,7 +150,7 @@ LibError sys_on_each_cpu(void (*cb)()) // .. and do so. if(!SetProcessAffinityMask(hProcess, process_affinity)) { - WARN_ERR(ERR_CPU_RESTRICTED_AFFINITY); + WARN_ERR(ERR::CPU_RESTRICTED_AFFINITY); continue; } @@ -163,7 +163,7 @@ LibError sys_on_each_cpu(void (*cb)()) // restore to original value SetProcessAffinityMask(hProcess, process_affinity); - return INFO_OK; + return INFO::OK; } @@ -309,19 +309,19 @@ LibError prof_start() const DWORD access = THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME; HANDLE hThread = OpenThread(access, FALSE, GetCurrentThreadId()); if(hThread == INVALID_HANDLE_VALUE) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); prof_target_thread = hThread; sem_init(&exit_flag, 0, 0); pthread_create(&thread, 0, prof_thread_func, 0); - return INFO_OK; + return INFO::OK; } LibError prof_shutdown() { WARN_IF_FALSE(CloseHandle(prof_target_thread)); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wdbg.cpp b/source/lib/sysdep/win/wdbg.cpp index bf11cc3b49..4589678841 100644 --- a/source/lib/sysdep/win/wdbg.cpp +++ b/source/lib/sysdep/win/wdbg.cpp @@ -210,7 +210,7 @@ static LibError call_while_suspended(WhileSuspendedFunc func, void* user_arg) const DWORD access = THREAD_GET_CONTEXT|THREAD_SET_CONTEXT|THREAD_SUSPEND_RESUME; HANDLE hThread = OpenThread(access, FALSE, GetCurrentThreadId()); if(hThread == INVALID_HANDLE_VALUE) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); WhileSuspendedParam param = { hThread, func, user_arg }; @@ -264,7 +264,7 @@ static const uint MAX_BREAKPOINTS = 4; static LibError brk_disable_all_in_ctx(BreakInfo* UNUSED(bi), CONTEXT* context) { context->Dr7 &= ~brk_all_local_enables; - return INFO_OK; + return INFO::OK; } @@ -284,7 +284,7 @@ static LibError brk_enable_in_ctx(BreakInfo* bi, CONTEXT* context) if((context->Dr7 & LE) == 0) goto have_reg; } - WARN_RETURN(ERR_LIMIT); + WARN_RETURN(ERR::LIMIT); have_reg: // store breakpoint address in debug register. @@ -340,7 +340,7 @@ have_reg: context->Dr7 |= LE; brk_all_local_enables |= LE; - return INFO_OK; + return INFO::OK; } @@ -354,7 +354,7 @@ static LibError brk_do_request(HANDLE hThread, void* arg) CONTEXT context; context.ContextFlags = CONTEXT_DEBUG_REGISTERS; if(!GetThreadContext(hThread, &context)) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); #if CPU_IA32 if(bi->want_all_disabled) @@ -366,10 +366,10 @@ static LibError brk_do_request(HANDLE hThread, void* arg) #endif if(!SetThreadContext(hThread, &context)) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); RETURN_ERR(ret); - return INFO_OK; + return INFO::OK; } @@ -378,7 +378,7 @@ static LibError brk_do_request(HANDLE hThread, void* arg) // for simplicity, the length (range of bytes to be checked) is // derived from addr's alignment, and is typically 1 machine word. // breakpoints are a limited resource (4 on IA-32); abort and -// return ERR_LIMIT if none are available. +// return ERR::LIMIT if none are available. LibError debug_set_break(void* p, DbgBreakType type) { lock(); @@ -739,7 +739,7 @@ static LibError wdbg_init(void) pAddVectoredExceptionHandler(TRUE, vectored_exception_handler); #endif - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wdbg.h b/source/lib/sysdep/win/wdbg.h index 74e40f6c93..7e06e0b6b7 100644 --- a/source/lib/sysdep/win/wdbg.h +++ b/source/lib/sysdep/win/wdbg.h @@ -23,10 +23,6 @@ #ifndef WDBG_H__ #define WDBG_H__ -#ifdef __cplusplus -extern "C" { -#endif - #if HAVE_MS_ASM # define debug_break() __asm { int 3 } #else @@ -36,8 +32,4 @@ extern "C" { // internal use only: extern void wdbg_set_thread_name(const char* name); -#ifdef __cplusplus -} -#endif - #endif // #ifndef WDBG_H__ diff --git a/source/lib/sysdep/win/wdbg_sym.cpp b/source/lib/sysdep/win/wdbg_sym.cpp index a04ee29d29..89db1ac568 100644 --- a/source/lib/sysdep/win/wdbg_sym.cpp +++ b/source/lib/sysdep/win/wdbg_sym.cpp @@ -93,7 +93,7 @@ static LibError sym_init() // don't use pthread_once because we need to return success/error code. static uintptr_t already_initialized = 0; if(!CAS(&already_initialized, 0, 1)) - return INFO_OK; + return INFO::OK; hProcess = GetCurrentProcess(); @@ -120,7 +120,7 @@ static LibError sym_init() IMAGE_NT_HEADERS* header = ImageNtHeader((void*)mod_base); machine = header->FileHeader.Machine; - return INFO_OK; + return INFO::OK; } @@ -128,7 +128,7 @@ static LibError sym_init() static LibError sym_shutdown() { SymCleanup(hProcess); - return INFO_OK; + return INFO::OK; } @@ -209,7 +209,7 @@ static LibError debug_resolve_symbol_lk(void* ptr_of_interest, char* sym_name, c } } - return (successes != 0)? INFO_OK : ERR_FAIL; + return (successes != 0)? INFO::OK : ERR::FAIL; } // read and return symbol information for the given address. all of the @@ -284,21 +284,21 @@ static LibError ia32_walk_stack(STACKFRAME64* sf) void* prev_ip = (void*)sf->AddrPC .Offset; void* prev_ret = (void*)sf->AddrReturn.Offset; if(!debug_is_stack_ptr(prev_fp)) - WARN_RETURN(ERR_11); + WARN_RETURN(ERR::_11); if(prev_ip && !debug_is_code_ptr(prev_ip)) - WARN_RETURN(ERR_12); + WARN_RETURN(ERR::_12); if(prev_ret && !debug_is_code_ptr(prev_ret)) - WARN_RETURN(ERR_13); + WARN_RETURN(ERR::_13); // read stack frame void* fp = ((void**)prev_fp)[0]; void* ret_addr = ((void**)prev_fp)[1]; if(!fp) - return INFO_ALL_COMPLETE; + return INFO::ALL_COMPLETE; if(!debug_is_stack_ptr(fp)) - WARN_RETURN(ERR_14); + WARN_RETURN(ERR::_14); if(!debug_is_code_ptr(ret_addr)) - WARN_RETURN(ERR_15); + WARN_RETURN(ERR::_15); void* target; LibError err = ia32_get_call_target(ret_addr, &target); @@ -310,7 +310,7 @@ static LibError ia32_walk_stack(STACKFRAME64* sf) sf->AddrPC .Offset = (DWORD64)target; sf->AddrReturn.Offset = (DWORD64)ret_addr; - return INFO_OK; + return INFO::OK; } #endif // #if CPU_IA32 && !CONFIG_OMIT_FP @@ -318,7 +318,7 @@ static LibError ia32_walk_stack(STACKFRAME64* sf) // called for each stack frame found by walk_stack, passing information // about the frame and . -// return INFO_CB_CONTINUE to continue, anything else to stop immediately +// return INFO::CB_CONTINUE to continue, anything else to stop immediately // and return that value to walk_stack's caller. // // rationale: we can't just pass function's address to the callback - @@ -396,7 +396,7 @@ static LibError walk_stack(StackFrameCallback cb, void* user_arg = 0, uint skip sf.AddrStack.Mode = AddrModeFlat; // for each stack frame found: - LibError ret = ERR_SYM_NO_STACK_FRAMES_FOUND; + LibError ret = ERR::SYM_NO_STACK_FRAMES_FOUND; for(;;) { // rationale: @@ -425,13 +425,13 @@ static LibError walk_stack(StackFrameCallback cb, void* user_arg = 0, uint skip 0, SymFunctionTableAccess64, SymGetModuleBase64, 0); // note: don't use LibError_from_win32 because it raises a warning, // and this "fails" commonly (when no stack frames are left). - err = ok? INFO_OK : ERR_FAIL; + err = ok? INFO::OK : ERR::FAIL; #endif // no more frames found - abort. note: also test FP because // StackWalk64 sometimes erroneously reports success. void* fp = (void*)(uintptr_t)sf.AddrFrame.Offset; - if(err != INFO_OK || !fp) + if(err != INFO::OK || !fp) return ret; if(skip) @@ -442,8 +442,8 @@ static LibError walk_stack(StackFrameCallback cb, void* user_arg = 0, uint skip ret = cb(&sf, user_arg); // callback is allowing us to continue - if(ret == INFO_CB_CONTINUE) - ret = INFO_OK; // make sure this is never returned + if(ret == INFO::CB_CONTINUE) + ret = INFO::OK; // make sure this is never returned // callback reports it's done; stop calling it and return that value. // (can be either success or failure) else @@ -466,7 +466,7 @@ static LibError nth_caller_cb(const STACKFRAME64* sf, void* user_arg) // return its address *pfunc = (void*)sf->AddrPC.Offset; - return INFO_OK; + return INFO::OK; } @@ -487,7 +487,7 @@ void* debug_get_nth_caller(uint skip, void* pcontext) LibError err = walk_stack(nth_caller_cb, &func, skip, (const CONTEXT*)pcontext); unlock(); - return (err == INFO_OK)? func : 0; + return (err == INFO::OK)? func : 0; } @@ -534,7 +534,7 @@ static wchar_t* out_pos; // new position exceeds the limit and aborts if so. // slight wrinkle: since we don't want each level of UDTs to successively // realize the limit has been hit and display the error message, we -// return ERR_SYM_SINGLE_SYMBOL_LIMIT once and thereafter INFO_SYM_SUPPRESS_OUTPUT. +// return ERR::SYM_SINGLE_SYMBOL_LIMIT once and thereafter INFO::SYM_SUPPRESS_OUTPUT. // // * example: local variables, as opposed to child symbols in a UDT. static wchar_t* out_latched_pos; @@ -619,15 +619,15 @@ static void out_latch_pos() static LibError out_check_limit() { if(out_have_warned_of_limit) - return INFO_SYM_SUPPRESS_OUTPUT; + return INFO::SYM_SUPPRESS_OUTPUT; if(out_pos - out_latched_pos > 3000) // ~30 lines { out_have_warned_of_limit = true; - return ERR_SYM_SINGLE_SYMBOL_LIMIT; // NOWARN + return ERR::SYM_SINGLE_SYMBOL_LIMIT; // NOWARN } // no limit hit, proceed normally - return INFO_OK; + return INFO::OK; } //---------------------------------------------------------------------------- @@ -731,22 +731,22 @@ static void dump_error(LibError err, const u8* p) case 0: // no error => no output break; - case ERR_SYM_SINGLE_SYMBOL_LIMIT: + case ERR::SYM_SINGLE_SYMBOL_LIMIT: out(L"(too much output; skipping to next top-level symbol)"); break; - case ERR_SYM_UNRETRIEVABLE_STATIC: + case ERR::SYM_UNRETRIEVABLE_STATIC: out(L"(unavailable - located in another module)"); break; - case ERR_SYM_UNRETRIEVABLE_REG: + case ERR::SYM_UNRETRIEVABLE_REG: out(L"(unavailable - stored in register %s)", string_for_register((CV_HREG_e)(uintptr_t)p)); break; - case ERR_SYM_TYPE_INFO_UNAVAILABLE: + case ERR::SYM_TYPE_INFO_UNAVAILABLE: out(L"(unavailable - type info request failed (GLE=%d))", GetLastError()); break; - case ERR_SYM_INTERNAL_ERROR: + case ERR::SYM_INTERNAL_ERROR: out(L"(unavailable - internal error)\r\n"); break; - case INFO_SYM_SUPPRESS_OUTPUT: + case INFO::SYM_SUPPRESS_OUTPUT: // not an error; do not output anything. handled by caller. break; default: @@ -761,10 +761,10 @@ static LibError dump_string(const u8* p, size_t el_size) { // not char or wchar_t string if(el_size != sizeof(char) && el_size != sizeof(wchar_t)) - return INFO_CANNOT_HANDLE; + return INFO::CANNOT_HANDLE; // not text if(!is_string(p, el_size)) - return INFO_CANNOT_HANDLE; + return INFO::CANNOT_HANDLE; wchar_t buf[512]; if(el_size == sizeof(wchar_t)) @@ -783,7 +783,7 @@ static LibError dump_string(const u8* p, size_t el_size) } out(L"\"%s\"", buf); - return INFO_OK; + return INFO::OK; } @@ -827,7 +827,7 @@ static LibError dump_sequence(DebugIterator el_iterator, void* internal, el_p = el_iterator(internal, el_size); LibError ret = dump_string(el_p, el_size); - if(ret == INFO_OK) + if(ret == INFO::OK) return ret; } @@ -850,20 +850,20 @@ static LibError dump_sequence(DebugIterator el_iterator, void* internal, // there was no output for this child; undo its indentation (if any), // skip everything below and proceed with the next child. - if(err == INFO_SYM_SUPPRESS_OUTPUT) + if(err == INFO::SYM_SUPPRESS_OUTPUT) { if(!fits_on_one_line) UNINDENT; continue; } - dump_error(err, el_p); // nop if err == INFO_OK + dump_error(err, el_p); // nop if err == INFO::OK // add separator unless this is the last element (can't just // erase below due to additional "..."). if(i != num_elements_to_show-1) out(fits_on_one_line? L", " : L"\r\n"); - if(err == ERR_SYM_SINGLE_SYMBOL_LIMIT) + if(err == ERR::SYM_SINGLE_SYMBOL_LIMIT) break; } // for each child @@ -874,7 +874,7 @@ static LibError dump_sequence(DebugIterator el_iterator, void* internal, state.level--; if(fits_on_one_line) out(L" }"); - return INFO_OK; + return INFO::OK; } @@ -904,7 +904,7 @@ static LibError determine_symbol_address(DWORD id, DWORD UNUSED(type_id), const DWORD data_kind; if(!SymGetTypeInfo(hProcess, mod_base, id, TI_GET_DATAKIND, &data_kind)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); switch(data_kind) { // SymFromIndex will fail @@ -912,12 +912,12 @@ static LibError determine_symbol_address(DWORD id, DWORD UNUSED(type_id), const // pp is already correct (udt_dump_normal retrieved the offset; // we do it that way so we can check it against the total // UDT size for safety). - return INFO_OK; + return INFO::OK; // this symbol is defined as static in another module => // there's nothing we can do. case DataIsStaticMember: - return ERR_SYM_UNRETRIEVABLE_STATIC; // NOWARN + return ERR::SYM_UNRETRIEVABLE_STATIC; // NOWARN // ok; will handle below case DataIsLocal: @@ -939,7 +939,7 @@ static LibError determine_symbol_address(DWORD id, DWORD UNUSED(type_id), const SYMBOL_INFO_PACKAGEW2 sp; SYMBOL_INFOW* sym = &sp.si; if(!SymFromIndexW(hProcess, mod_base, id, sym)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); DWORD addrofs = 0; ULONG64 addr2 = 0; @@ -980,14 +980,14 @@ fp_rel: { in_register: *pp = (const u8*)(uintptr_t)sym->Register; - return ERR_SYM_UNRETRIEVABLE_REG; // NOWARN + return ERR::SYM_UNRETRIEVABLE_REG; // NOWARN } *pp = (const u8*)addr; debug_printf("SYM| %ws at %p flags=%X dk=%d sym->addr=%I64X addrofs=%X addr2=%I64X ofs2=%X\n", sym->Name, *pp, sym->Flags, data_kind, sym->Address, addrofs, addr2, ofs2); - return INFO_OK; + return INFO::OK; } @@ -1004,18 +1004,18 @@ static LibError dump_sym_array(DWORD type_id, const u8* p, DumpState state) { ULONG64 size_ = 0; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); const size_t size = (size_t)size_; // get element count and size DWORD el_type_id = 0; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &el_type_id)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); // .. workaround: TI_GET_COUNT returns total struct size for // arrays-of-struct. therefore, calculate as size / el_size. ULONG64 el_size_; if(!SymGetTypeInfo(hProcess, mod_base, el_type_id, TI_GET_LENGTH, &el_size_)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); const size_t el_size = (size_t)el_size_; debug_assert(el_size != 0); const size_t num_elements = size/el_size; @@ -1031,10 +1031,10 @@ static LibError dump_sym_base_type(DWORD type_id, const u8* p, DumpState state) { DWORD base_type; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_BASETYPE, &base_type)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); ULONG64 size_ = 0; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); const size_t size = (size_t)size_; // single out() call. note: we pass a single u64 for all sizes, @@ -1153,7 +1153,7 @@ display_as_hex: case btBit: case btBSTR: case btHresult: - return ERR_SYM_UNSUPPORTED; // NOWARN + return ERR::SYM_UNSUPPORTED; // NOWARN } out(fmt, data); @@ -1167,7 +1167,7 @@ display_as_hex: out(L" ('%hc')", c); } - return INFO_OK; + return INFO::OK; } @@ -1177,14 +1177,14 @@ static LibError dump_sym_base_class(DWORD type_id, const u8* p, DumpState state) { DWORD base_class_type_id; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &base_class_type_id)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); // this is a virtual base class. we can't display those because it'd // require reading the VTbl, which is difficult given lack of documentation // and just not worth it. DWORD vptr_ofs; if(SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_VIRTUALBASEPOINTEROFFSET, &vptr_ofs)) - return ERR_SYM_UNSUPPORTED; // NOWARN + return ERR::SYM_UNSUPPORTED; // NOWARN return dump_sym(base_class_type_id, p, state); @@ -1199,7 +1199,7 @@ static LibError dump_sym_data(DWORD id, const u8* p, DumpState state) // display name (of variable/member) const wchar_t* name; if(!SymGetTypeInfo(hProcess, mod_base, id, TI_GET_SYMNAME, &name)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); out(L"%s = ", name); LocalFree((HLOCAL)name); @@ -1208,7 +1208,7 @@ static LibError dump_sym_data(DWORD id, const u8* p, DumpState state) // get type_id and address DWORD type_id; if(!SymGetTypeInfo(hProcess, mod_base, id, TI_GET_TYPEID, &type_id)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); RETURN_ERR(determine_symbol_address(id, type_id, &p)); // display value recursively @@ -1216,7 +1216,7 @@ static LibError dump_sym_data(DWORD id, const u8* p, DumpState state) } __except(EXCEPTION_EXECUTE_HANDLER) { - return ERR_SYM_INTERNAL_ERROR; // NOWARN + return ERR::SYM_INTERNAL_ERROR; // NOWARN } } @@ -1227,7 +1227,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state { ULONG64 size_ = 0; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); const size_t size = (size_t)size_; const i64 enum_value = movsx_64le(p, size); @@ -1235,10 +1235,10 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state // get array of child symbols (enumerants). DWORD num_children; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_CHILDRENCOUNT, &num_children)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); TI_FINDCHILDREN_PARAMS2 fcp(num_children); if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_FINDCHILDREN, &fcp)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); num_children = fcp.p.Count; // was truncated to MAX_CHILDREN const DWORD* children = fcp.p.ChildId; @@ -1254,7 +1254,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state // already pulled in by e.g. OpenGL anyway. VARIANT v; if(!SymGetTypeInfo(hProcess, mod_base, child_data_id, TI_GET_VALUE, &v)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); if(VariantChangeType(&v, &v, 0, VT_I8) != S_OK) continue; @@ -1263,10 +1263,10 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state { const wchar_t* name; if(!SymGetTypeInfo(hProcess, mod_base, child_data_id, TI_GET_SYMNAME, &name)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); out(L"%s", name); LocalFree((HLOCAL)name); - return INFO_OK; + return INFO::OK; } } @@ -1275,7 +1275,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state // note: could goto here after a SGTI fails, but we fail instead // to make sure those errors are noticed. out(L"%I64d", enum_value); - return INFO_OK; + return INFO::OK; } @@ -1284,7 +1284,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state static LibError dump_sym_function(DWORD UNUSED(type_id), const u8* UNUSED(p), DumpState UNUSED(state)) { - return INFO_SYM_SUPPRESS_OUTPUT; + return INFO::SYM_SUPPRESS_OUTPUT; } @@ -1300,9 +1300,9 @@ static LibError dump_sym_function_type(DWORD UNUSED(type_id), const u8* p, DumpS LibError err = debug_resolve_symbol_lk((void*)p, name, 0, 0); out(L"0x%p", p); - if(err == INFO_OK) + if(err == INFO::OK) out(L" (%hs)", name); - return INFO_OK; + return INFO::OK; } @@ -1340,7 +1340,7 @@ static LibError dump_sym_pointer(DWORD type_id, const u8* p, DumpState state) { ULONG64 size_ = 0; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); const size_t size = (size_t)size_; // read+output pointer's value. @@ -1350,13 +1350,13 @@ static LibError dump_sym_pointer(DWORD type_id, const u8* p, DumpState state) // bail if it's obvious the pointer is bogus // (=> can't display what it's pointing to) if(debug_is_pointer_bogus(p)) - return INFO_OK; + return INFO::OK; // avoid duplicates and circular references if(ptr_already_visited(p)) { out(L" (see above)"); - return INFO_OK; + return INFO::OK; } // display what the pointer is pointing to. @@ -1366,11 +1366,11 @@ static LibError dump_sym_pointer(DWORD type_id, const u8* p, DumpState state) // the responsible dump_sym* will erase "->", leaving only address. out(L" -> "); if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &type_id)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); // prevent infinite recursion just to be safe (shouldn't happen) if(state.indirection >= MAX_INDIRECTION) - WARN_RETURN(ERR_SYM_NESTING_LIMIT); + WARN_RETURN(ERR::SYM_NESTING_LIMIT); state.indirection++; return dump_sym(type_id, p, state); } @@ -1382,7 +1382,7 @@ static LibError dump_sym_pointer(DWORD type_id, const u8* p, DumpState state) static LibError dump_sym_typedef(DWORD type_id, const u8* p, DumpState state) { if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &type_id)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); return dump_sym(type_id, p, state); } @@ -1416,19 +1416,19 @@ static LibError udt_get_child_type(const wchar_t* child_name, // .. its type information is what we want. DWORD type_id; if(!SymGetTypeInfo(hProcess, mod_base, child_id, TI_GET_TYPEID, &type_id)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); ULONG64 size; if(!SymGetTypeInfo(hProcess, mod_base, child_id, TI_GET_LENGTH, &size)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); *el_type_id = type_id; *el_size = (size_t)size; - return INFO_OK; + return INFO::OK; } // (happens if called for containers that are treated as STL but are not) - return ERR_SYM_CHILD_NOT_FOUND; // NOWARN + return ERR::SYM_CHILD_NOT_FOUND; // NOWARN } @@ -1439,13 +1439,13 @@ static LibError udt_dump_std(const wchar_t* wtype_name, const u8* p, size_t size // not a C++ standard library object; can't handle it. if(wcsncmp(wtype_name, L"std::", 5) != 0) - return INFO_CANNOT_HANDLE; + return INFO::CANNOT_HANDLE; // check for C++ objects that should be displayed via udt_dump_normal. // STL containers are special-cased and the rest (apart from those here) // are ignored, because for the most part they are spew. if(!wcsncmp(wtype_name, L"std::pair", 9)) - return INFO_CANNOT_HANDLE; + return INFO::CANNOT_HANDLE; // convert to char since debug_stl doesn't support wchar_t. char ctype_name[DBG_SYMBOL_LEN]; @@ -1456,14 +1456,14 @@ static LibError udt_dump_std(const wchar_t* wtype_name, const u8* p, size_t size DWORD el_type_id; size_t el_size; err = udt_get_child_type(L"value_type", num_children, children, &el_type_id, &el_size); - if(err != INFO_OK) + if(err != INFO::OK) goto not_valid_container; // .. get iterator and # elements size_t el_count; DebugIterator el_iterator; u8 it_mem[DEBUG_STL_MAX_ITERATOR_SIZE]; err = debug_stl_get_container_info(ctype_name, p, size, el_size, &el_count, &el_iterator, it_mem); - if(err != INFO_OK) + if(err != INFO::OK) goto not_valid_container; return dump_sequence(el_iterator, it_mem, el_count, el_type_id, el_size, state); not_valid_container: @@ -1475,13 +1475,13 @@ not_valid_container: // it's a non-STL C++ stdlib object. wasn't handled by the // special case above, so we just display its simplified type name // (the contents are usually spew). - if(err == ERR_SYM_CHILD_NOT_FOUND) + if(err == ERR::SYM_CHILD_NOT_FOUND) text = ""; // .. not one of the containers we can analyse. - if(err == ERR_STL_CNT_UNKNOWN) + if(err == ERR::STL_CNT_UNKNOWN) text = "unsupported "; // .. container of a known type but contents are invalid. - if(err == ERR_STL_CNT_INVALID) + if(err == ERR::STL_CNT_INVALID) text = "uninitialized/invalid "; // .. some other error encountered else @@ -1490,7 +1490,7 @@ not_valid_container: text = buf; } out(L"(%hs%hs)", text, debug_stl_simplify_name(ctype_name)); - return INFO_OK; + return INFO::OK; } @@ -1547,7 +1547,7 @@ static LibError udt_dump_suppressed(const wchar_t* type_name, const u8* UNUSED(p DumpState state, ULONG UNUSED(num_children), const DWORD* UNUSED(children)) { if(!udt_should_suppress(type_name)) - return INFO_CANNOT_HANDLE; + return INFO::CANNOT_HANDLE; // the data symbol is pointer-to-UDT. since we won't display its // contents, leave only the pointer's value. @@ -1558,7 +1558,7 @@ static LibError udt_dump_suppressed(const wchar_t* type_name, const u8* UNUSED(p // (otherwise, lack of output may be taken for an error) out(L" (..)"); - return INFO_OK; + return INFO::OK; } @@ -1603,7 +1603,7 @@ static LibError udt_dump_normal(const wchar_t* type_name, const u8* p, size_t si // prevent infinite recursion just to be safe (shouldn't happen) if(state.level >= MAX_LEVEL) - WARN_RETURN(ERR_SYM_NESTING_LIMIT); + WARN_RETURN(ERR::SYM_NESTING_LIMIT); state.level++; out(fits_on_one_line? L"{ " : L"\r\n"); @@ -1628,7 +1628,7 @@ static LibError udt_dump_normal(const wchar_t* type_name, const u8* p, size_t si // there was no output for this child; undo its indentation (if any), // skip everything below and proceed with the next child. - if(err == INFO_SYM_SUPPRESS_OUTPUT) + if(err == INFO::SYM_SUPPRESS_OUTPUT) { if(!fits_on_one_line) UNINDENT; @@ -1636,10 +1636,10 @@ static LibError udt_dump_normal(const wchar_t* type_name, const u8* p, size_t si } displayed_anything = true; - dump_error(err, el_p); // nop if err == INFO_OK + dump_error(err, el_p); // nop if err == INFO::OK out(fits_on_one_line? L", " : L"\r\n"); - if(err == ERR_SYM_SINGLE_SYMBOL_LIMIT) + if(err == ERR::SYM_SINGLE_SYMBOL_LIMIT) break; } // for each child @@ -1649,7 +1649,7 @@ static LibError udt_dump_normal(const wchar_t* type_name, const u8* p, size_t si { out_erase(2); // "{ " or "\r\n" out(L"(%s)", type_name); - return INFO_OK; + return INFO::OK; } // remove trailing comma separator @@ -1661,7 +1661,7 @@ static LibError udt_dump_normal(const wchar_t* type_name, const u8* p, size_t si out(L" }"); } - return INFO_OK; + return INFO::OK; } @@ -1669,37 +1669,37 @@ static LibError dump_sym_udt(DWORD type_id, const u8* p, DumpState state) { ULONG64 size_ = 0; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); const size_t size = (size_t)size_; // get array of child symbols (members/functions/base classes). DWORD num_children; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_CHILDRENCOUNT, &num_children)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); TI_FINDCHILDREN_PARAMS2 fcp(num_children); if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_FINDCHILDREN, &fcp)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); num_children = fcp.p.Count; // was truncated to MAX_CHILDREN const DWORD* children = fcp.p.ChildId; const wchar_t* type_name; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMNAME, &type_name)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); LibError ret; // note: order is important (e.g. STL special-case must come before // suppressing UDTs, which tosses out most other C++ stdlib classes) ret = udt_dump_std (type_name, p, size, state, num_children, children); - if(ret != INFO_CANNOT_HANDLE) + if(ret != INFO::CANNOT_HANDLE) goto done; ret = udt_dump_suppressed(type_name, p, size, state, num_children, children); - if(ret != INFO_CANNOT_HANDLE) + if(ret != INFO::CANNOT_HANDLE) goto done; ret = udt_dump_normal (type_name, p, size, state, num_children, children); - if(ret != INFO_CANNOT_HANDLE) + if(ret != INFO::CANNOT_HANDLE) goto done; done: @@ -1714,7 +1714,7 @@ done: static LibError dump_sym_vtable(DWORD UNUSED(type_id), const u8* UNUSED(p), DumpState UNUSED(state)) { // unsupported (vtable internals are undocumented; too much work). - return INFO_SYM_SUPPRESS_OUTPUT; + return INFO::SYM_SUPPRESS_OUTPUT; } @@ -1726,11 +1726,11 @@ static LibError dump_sym_unknown(DWORD type_id, const u8* UNUSED(p), DumpState U // redundant (already done in dump_sym), but this is rare. DWORD type_tag; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMTAG, &type_tag)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); debug_printf("SYM| unknown tag: %d\n", type_tag); out(L"(unknown symbol type)"); - return INFO_OK; + return INFO::OK; } @@ -1745,7 +1745,7 @@ static LibError dump_sym(DWORD type_id, const u8* p, DumpState state) DWORD type_tag; if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMTAG, &type_tag)) - WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE); + WARN_RETURN(ERR::SYM_TYPE_INFO_UNAVAILABLE); switch(type_tag) { case SymTagArrayType: @@ -1794,7 +1794,7 @@ static BOOL CALLBACK dump_sym_cb(SYMBOL_INFO* sym, ULONG UNUSED(size), void* UNU INDENT; LibError err = dump_sym(sym->Index, p, state); dump_error(err, p); - if(err == INFO_SYM_SUPPRESS_OUTPUT) + if(err == INFO::SYM_SUPPRESS_OUTPUT) UNINDENT; else out(L"\r\n"); @@ -1834,7 +1834,7 @@ static LibError dump_frame_cb(const STACKFRAME64* sf, void* UNUSED(user_arg)) char func_name[DBG_SYMBOL_LEN]; char file[DBG_FILE_LEN]; int line; LibError ret = debug_resolve_symbol_lk(func, func_name, file, &line); - if(ret == INFO_OK) + if(ret == INFO::OK) { // don't trace back further than the app's entry point // (no one wants to see this frame). checking for the @@ -1842,7 +1842,7 @@ static LibError dump_frame_cb(const STACKFRAME64* sf, void* UNUSED(user_arg)) // an alternative would be to check if module=kernel32, but // that would cut off callbacks as well. if(!strcmp(func_name, "_BaseProcessStart@4")) - return INFO_OK; + return INFO::OK; out(L"%hs (%hs:%d)\r\n", func_name, file, line); } @@ -1862,7 +1862,7 @@ static LibError dump_frame_cb(const STACKFRAME64* sf, void* UNUSED(user_arg)) // should be used. out(L"\r\n"); - return INFO_CB_CONTINUE; + return INFO::CB_CONTINUE; } @@ -1870,7 +1870,7 @@ LibError debug_dump_stack(wchar_t* buf, size_t max_chars, uint skip, void* pcont { static uintptr_t already_in_progress; if(!CAS(&already_in_progress, 0, 1)) - return ERR_REENTERED; // NOWARN + return ERR::REENTERED; // NOWARN lock(); out_init(buf, max_chars); @@ -1940,7 +1940,7 @@ static LibError wdbg_sym_init() HMODULE hKernel32Dll = GetModuleHandle("kernel32.dll"); *(void**)&pRtlCaptureContext = GetProcAddress(hKernel32Dll, "RtlCaptureContext"); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wdir_watch.cpp b/source/lib/sysdep/win/wdir_watch.cpp index 8022bb0ffa..8c71fe208d 100644 --- a/source/lib/sysdep/win/wdir_watch.cpp +++ b/source/lib/sysdep/win/wdir_watch.cpp @@ -168,7 +168,7 @@ static LibError wdir_watch_shutdown() delete it->second; watches.clear(); - return INFO_OK; + return INFO::OK; } @@ -185,7 +185,7 @@ static Watch* find_watch(intptr_t reqnum) // better to use a cached string from rel_chdir - secure LibError dir_add_watch(const char* dir, intptr_t* _reqnum) { - LibError err = ERR_FAIL; + LibError err = ERR::FAIL; WIN_SAVE_LAST_ERROR; // Create* intptr_t reqnum; @@ -268,7 +268,7 @@ LibError dir_add_watch(const char* dir, intptr_t* _reqnum) } done: - err = INFO_OK; + err = INFO::OK; *_reqnum = reqnum; fail: @@ -280,17 +280,17 @@ fail: LibError dir_cancel_watch(const intptr_t reqnum) { if(reqnum <= 0) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); Watch* w = find_watch(reqnum); // watches[reqnum] is invalid - big trouble if(!w) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); // we're freeing a reference - done. debug_assert(w->refs >= 1); if(--w->refs != 0) - return INFO_OK; + return INFO::OK; // contrary to dox, the RDC IOs do not issue a completion notification. // no packet was received on the IOCP while or after cancelling in a test. @@ -375,7 +375,7 @@ static void get_packet() // if a file change notification is pending, store its filename in and -// return INFO_OK; otherwise, return ERR_AGAIN ('none currently pending') or +// return INFO::OK; otherwise, return ERR::AGAIN ('none currently pending') or // a negative error code. // must hold at least PATH_MAX chars. LibError dir_get_changed_file(char* fn) @@ -385,11 +385,11 @@ LibError dir_get_changed_file(char* fn) // nothing to return; call again later. if(pending_events.empty()) - return ERR_AGAIN; // NOWARN + return ERR::AGAIN; // NOWARN const std::string& fn_s = pending_events.front(); strcpy_s(fn, PATH_MAX, fn_s.c_str()); pending_events.pop_front(); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wgfx.cpp b/source/lib/sysdep/win/wgfx.cpp index ebb6dc8f97..16a7e0e04e 100644 --- a/source/lib/sysdep/win/wgfx.cpp +++ b/source/lib/sysdep/win/wgfx.cpp @@ -45,7 +45,7 @@ LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq) // dm.dmDriverExtra already set to 0 by memset if(!EnumDisplaySettingsA(0, ENUM_CURRENT_SETTINGS, &dm)) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); if(dm.dmFields & (DWORD)DM_PELSWIDTH && xres) *xres = (int)dm.dmPelsWidth; @@ -56,7 +56,7 @@ LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq) if(dm.dmFields & (DWORD)DM_DISPLAYFREQUENCY && freq) *freq = (int)dm.dmDisplayFrequency; - return INFO_OK; + return INFO::OK; } @@ -69,7 +69,7 @@ LibError gfx_get_monitor_size(int& width_mm, int& height_mm) width_mm = GetDeviceCaps(dc, HORZSIZE); height_mm = GetDeviceCaps(dc, VERTSIZE); ReleaseDC(0, dc); - return INFO_OK; + return INFO::OK; } @@ -93,7 +93,7 @@ static LibError import_EnumDisplayDevices() // so this resource leak is unavoidable. } - return pEnumDisplayDevicesA? INFO_OK : ERR_FAIL; + return pEnumDisplayDevicesA? INFO::OK : ERR::FAIL; } @@ -120,12 +120,12 @@ static LibError win_get_gfx_card() if(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { strcpy_s(gfx_card, ARRAY_SIZE(gfx_card), (const char*)dd.DeviceString); - return INFO_OK; + return INFO::OK; } } } - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); } @@ -134,7 +134,7 @@ static LibError win_get_gfx_drv_ver() { // don't overwrite existing information if(gfx_drv_ver[0] != '\0') - return INFO_SKIPPED; + return INFO::SKIPPED; // rationale: // - we could easily determine the 2d driver via EnumDisplaySettings, @@ -153,7 +153,7 @@ static LibError win_get_gfx_drv_ver() // gfx_card which one is correct; we thus avoid driver-specific // name checks and reporting incorrectly. - LibError ret = ERR_FAIL; // single point of exit (for RegCloseKey) + LibError ret = ERR::FAIL; // single point of exit (for RegCloseKey) DWORD i; char drv_name[MAX_PATH+1]; @@ -162,7 +162,7 @@ static LibError win_get_gfx_drv_ver() HKEY hkOglDrivers; const char* key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers"; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hkOglDrivers) != 0) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); // for each subkey (i.e. set of installed OpenGL drivers): for(i = 0; ; i++) @@ -214,5 +214,5 @@ LibError win_get_gfx_info() // don't exit before trying both RETURN_ERR(err1); RETURN_ERR(err2); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/win.cpp b/source/lib/sysdep/win/win.cpp index bad4b423e9..0aa8e20814 100644 --- a/source/lib/sysdep/win/win.cpp +++ b/source/lib/sysdep/win/win.cpp @@ -45,21 +45,22 @@ static LibError LibError_from_GLE(bool warn_if_failed = true) switch(GetLastError()) { case ERROR_OUTOFMEMORY: - err = ERR_NO_MEM; break; + err = ERR::NO_MEM; break; case ERROR_INVALID_PARAMETER: - err = ERR_INVALID_PARAM; break; + err = ERR::INVALID_PARAM; break; case ERROR_INSUFFICIENT_BUFFER: - err = ERR_BUF_SIZE; break; + err = ERR::BUF_SIZE; break; +/*/* case ERROR_ACCESS_DENIED: - err = ERR_FILE_ACCESS; break; + err = ERR::FILE_ACCESS; break; case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: - err = ERR_TNODE_NOT_FOUND; break; - + err = ERR::TNODE_NOT_FOUND; break; +*/ default: - err = ERR_FAIL; break; + err = ERR::FAIL; break; } if(warn_if_failed) @@ -68,14 +69,14 @@ static LibError LibError_from_GLE(bool warn_if_failed = true) } -// return the LibError equivalent of GetLastError(), or ERR_FAIL if +// return the LibError equivalent of GetLastError(), or ERR::FAIL if // there's no equal. // you should SetLastError(0) before calling whatever will set ret // to make sure we do not return any stale errors. LibError LibError_from_win32(DWORD ret, bool warn_if_failed) { if(ret != FALSE) - return INFO_OK; + return INFO::OK; return LibError_from_GLE(warn_if_failed); } diff --git a/source/lib/sysdep/win/win_internal.h b/source/lib/sysdep/win/win_internal.h index a153b6dc34..4d0b1e8d2a 100644 --- a/source/lib/sysdep/win/win_internal.h +++ b/source/lib/sysdep/win/win_internal.h @@ -452,7 +452,7 @@ extern void win_free(void* p); #define WIN_RESTORE_LAST_ERROR STMT(if(last_err__ != 0 && GetLastError() == 0) SetLastError(last_err__);); -// return the LibError equivalent of GetLastError(), or ERR_FAIL if +// return the LibError equivalent of GetLastError(), or ERR::FAIL if // there's no equal. // you should SetLastError(0) before calling whatever will set ret // to make sure we do not return any stale errors. diff --git a/source/lib/sysdep/win/wposix.cpp b/source/lib/sysdep/win/wposix.cpp index dc89a76617..4ca46a14c8 100644 --- a/source/lib/sysdep/win/wposix.cpp +++ b/source/lib/sysdep/win/wposix.cpp @@ -99,7 +99,7 @@ no_aio: // warn now, so that we notice why so many are open. #ifndef NDEBUG if(fd > 256) - WARN_ERR(ERR_LIMIT); + WARN_ERR(ERR::LIMIT); #endif return fd; @@ -626,7 +626,7 @@ static LibError mmap_mem(void* start, size_t len, int prot, int flags, int fd, v *pp = 0; // make sure *pp won't be misinterpreted as an error cassert(MAP_FAILED != 0); - return INFO_OK; + return INFO::OK; } } @@ -634,9 +634,9 @@ static LibError mmap_mem(void* start, size_t len, int prot, int flags, int fd, v DWORD flProtect = win32_prot(prot); void* p = VirtualAlloc(start, len, flAllocationType, flProtect); if(!p) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); *pp = p; - return INFO_OK; + return INFO::OK; } @@ -669,11 +669,11 @@ static LibError mmap_file_access(int prot, int flags, DWORD& flProtect, DWORD& d // definitely illegal according to POSIX and some man pages // say exactly one must be set, so abort. default: - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); } } - return INFO_OK; + return INFO::OK; } @@ -686,7 +686,7 @@ static LibError mmap_file(void* start, size_t len, int prot, int flags, HANDLE hFile = HANDLE_from_intptr(_get_osfhandle(fd)); if(hFile == INVALID_HANDLE_VALUE) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); // MapViewOfFileEx will fail if the "suggested" base address is // nonzero but cannot be honored, so wipe out unless MAP_FIXED. @@ -703,7 +703,7 @@ static LibError mmap_file(void* start, size_t len, int prot, int flags, const HANDLE hMap = CreateFileMapping(hFile, 0, flProtect, 0, 0, (LPCSTR)0); // .. create failed; bail now to avoid overwriting the last error value. if(!hMap) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); const DWORD ofs_hi = u64_hi(ofs), ofs_lo = u64_lo(ofs); void* p = MapViewOfFileEx(hMap, dwAccess, ofs_hi, ofs_lo, (SIZE_T)len, start); // .. make sure we got the requested address if MAP_FIXED was passed. @@ -714,14 +714,14 @@ static LibError mmap_file(void* start, size_t len, int prot, int flags, CloseHandle(hMap); // .. map failed; bail now to avoid "restoring" the last error value. if(!p) - WARN_RETURN(ERR_NO_MEM); + WARN_RETURN(ERR::NO_MEM); // slap on correct (more restrictive) permissions. (void)mprotect(p, len, prot); WIN_RESTORE_LAST_ERROR; *pp = p; - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wpthread.cpp b/source/lib/sysdep/win/wpthread.cpp index a9ea25e363..8a67d6a598 100644 --- a/source/lib/sysdep/win/wpthread.cpp +++ b/source/lib/sysdep/win/wpthread.cpp @@ -143,7 +143,7 @@ int pthread_key_create(pthread_key_t* key, void (*dtor)(void*)) } // not enough slots; we have a valid key, but its dtor won't be called. - WARN_ERR(ERR_LIMIT); + WARN_ERR(ERR::LIMIT); return -1; have_slot: @@ -183,7 +183,7 @@ void* pthread_getspecific(pthread_key_t key) SetLastError(last_err); } else - WARN_ERR(ERR_FAIL); + WARN_ERR(ERR::FAIL); return data; } @@ -382,7 +382,7 @@ static DWORD calc_timeout_length_ms(const struct timespec* abs_timeout, // that's the Win32 INFINITE value. if(length_ms >= 0xffffffff) { - WARN_ERR(ERR_LIMIT); + WARN_ERR(ERR::LIMIT); length_ms = 0xfffffffe; } return (DWORD)(length_ms & 0xffffffff); @@ -441,7 +441,7 @@ int sem_msgwait_np(sem_t* sem) else { errno = EINVAL; - WARN_ERR(ERR_FAIL); + WARN_ERR(ERR::FAIL); } return -1; } @@ -517,7 +517,7 @@ int pthread_create(pthread_t* thread_id, const void* UNUSED(attr), void* (*func) const uintptr_t id = _beginthreadex(0, 0, thread_start, (void*)&func_and_arg, 0, 0); if(!id) { - WARN_ERR(ERR_FAIL); + WARN_ERR(ERR::FAIL); return -1; } @@ -552,7 +552,7 @@ int pthread_join(pthread_t thread, void** value_ptr) DWORD ret = WaitForSingleObject(hThread, INFINITE); if(ret != WAIT_OBJECT_0) { - WARN_ERR(ERR_FAIL); + WARN_ERR(ERR::FAIL); return -1; } @@ -572,12 +572,12 @@ static LibError wpthread_init() { int err = sem_init(&sem_thread_create, 0, 0); debug_assert(err == 0); - return INFO_OK; + return INFO::OK; } static LibError wpthread_shutdown() { int err = sem_destroy(&sem_thread_create); debug_assert(err == 0); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wsdl.cpp b/source/lib/sysdep/win/wsdl.cpp index 96eb648412..72451a534e 100644 --- a/source/lib/sysdep/win/wsdl.cpp +++ b/source/lib/sysdep/win/wsdl.cpp @@ -97,7 +97,7 @@ static LibError calc_gamma_ramp(float gamma, u16* ramp) { for(u16 i = 0; i < 256; i++) ramp[i] = (i << 8); - return INFO_OK; + return INFO::OK; } const double inv_gamma = 1.0 / gamma; @@ -110,7 +110,7 @@ static LibError calc_gamma_ramp(float gamma, u16* ramp) ramp[i] = fp_to_u16(pow(frac, inv_gamma)); } - return INFO_OK; + return INFO::OK; } @@ -142,7 +142,7 @@ int SDL_SetGamma(float r, float g, float b) LibError err1 = calc_gamma_ramp(r, cur_ramp[0]); LibError err2 = calc_gamma_ramp(g, cur_ramp[1]); LibError err3 = calc_gamma_ramp(b, cur_ramp[2]); - if(err1 != INFO_OK || err2 != INFO_OK || err3 != INFO_OK) + if(err1 != INFO::OK || err2 != INFO::OK || err3 != INFO::OK) return -1; if(!SetDeviceGammaRamp(hDC, cur_ramp)) @@ -1339,7 +1339,7 @@ static LibError wsdl_init() enable_kbd_hook(true); - return INFO_OK; + return INFO::OK; } @@ -1357,7 +1357,7 @@ static LibError wsdl_shutdown() enable_kbd_hook(false); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wsdl.h b/source/lib/sysdep/win/wsdl.h index e126bbfa59..9b1abde398 100644 --- a/source/lib/sysdep/win/wsdl.h +++ b/source/lib/sysdep/win/wsdl.h @@ -26,10 +26,6 @@ #include "lib/types.h" #include "SDL/SDL_keysym.h" -#ifdef __cplusplus -extern "C" { -#endif - typedef u8 Uint8; typedef u16 Uint16; typedef u32 Uint32; @@ -304,9 +300,4 @@ extern Uint8 SDL_GetMouseState(int* x, int* y); extern Uint8 SDL_GetAppState(); - -#ifdef __cplusplus -} -#endif - #endif // #ifndef WSDL_H__ diff --git a/source/lib/sysdep/win/wsnd.cpp b/source/lib/sysdep/win/wsnd.cpp index 52d9c862a1..071ff0e974 100644 --- a/source/lib/sysdep/win/wsnd.cpp +++ b/source/lib/sysdep/win/wsnd.cpp @@ -86,19 +86,19 @@ static LibError add_if_oal_dll(const DirEnt* ent, PathPackage* pp, StringSet* dl // skip non-files. if(!DIRENT_IS_DIR(ent)) - return INFO_OK; + return INFO::OK; // skip if not an OpenAL DLL. const size_t len = strlen(fn); const bool oal = len >= 7 && !stricmp(fn+len-7, "oal.dll"); const bool openal = strstr(fn, "OpenAL") != 0; if(!oal && !openal) - return INFO_OK; + return INFO::OK; // skip if already in StringSet (i.e. has already been dll_list_add-ed) std::pair ret = dlls->insert(fn); if(!ret.second) // insert failed - element already there - return INFO_OK; + return INFO::OK; RETURN_ERR(path_package_append_file(pp, fn)); return dll_list_add(pp->path); @@ -123,13 +123,13 @@ static LibError add_oal_dlls_in_dir(const char* dir, StringSet* dlls) for(;;) // instead of while to avoid warning { LibError err = dir_next_ent(&d, &ent); - if(err != INFO_OK) + if(err != INFO::OK) break; (void)add_if_oal_dll(&ent, &pp, dlls); } (void)dir_close(&d); - return INFO_OK; + return INFO::OK; } @@ -169,7 +169,7 @@ LibError win_get_snd_info() { strcpy_s(snd_card, SND_CARD_LEN, "(none)"); strcpy_s(snd_drv_ver, SND_DRV_VER_LEN, "(none)"); - return INFO_OK; + return INFO::OK; } // find all DLLs related to OpenAL, retrieve their versions, @@ -179,5 +179,5 @@ LibError win_get_snd_info() StringSet dlls; // ensures uniqueness (void)add_oal_dlls_in_dir(win_exe_dir, &dlls); (void)add_oal_dlls_in_dir(win_sys_dir, &dlls); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wsock.cpp b/source/lib/sysdep/win/wsock.cpp index f3c1fd0ede..325a2f266b 100644 --- a/source/lib/sysdep/win/wsock.cpp +++ b/source/lib/sysdep/win/wsock.cpp @@ -45,7 +45,7 @@ WIN_REGISTER_FUNC(wsock_shutdown); // These are included in the linux C libraries and in newer platform SDKs, // so should only be needed in VC++6 or earlier. const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; // :: -const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; // ::1 +const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; // ::_1 static HMODULE hWs2_32Dll; static int dll_refs; @@ -65,7 +65,7 @@ static LibError wsock_actual_init() debug_warn("WSAStartup failed"); } - return INFO_OK; + return INFO::OK; } @@ -74,7 +74,7 @@ static LibError wsock_actual_init() static LibError wsock_init() { WDLL_LOAD_NOTIFY("ws2_32", wsock_actual_init); - return INFO_OK; + return INFO::OK; } static LibError wsock_shutdown() @@ -89,7 +89,7 @@ static LibError wsock_shutdown() while(dll_refs-- > 0) FreeLibrary(hWs2_32Dll); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/sysdep/win/wsock.h b/source/lib/sysdep/win/wsock.h index bfd936f92d..9b9651045a 100644 --- a/source/lib/sysdep/win/wsock.h +++ b/source/lib/sysdep/win/wsock.h @@ -115,7 +115,7 @@ struct ip_mreq #define in6addr_loopback PS_in6addr_loopback extern const struct in6_addr in6addr_any; /* :: */ -extern const struct in6_addr in6addr_loopback; /* ::1 */ +extern const struct in6_addr in6addr_loopback; /* ::_1 */ #define IN6ADDR_ANY_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } #define IN6ADDR_LOOPBACK_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } diff --git a/source/lib/sysdep/win/wsysdep.cpp b/source/lib/sysdep/win/wsysdep.cpp index 91e4bd8166..ee512926d3 100644 --- a/source/lib/sysdep/win/wsysdep.cpp +++ b/source/lib/sysdep/win/wsysdep.cpp @@ -356,17 +356,17 @@ LibError sys_clipboard_set(const wchar_t* text) // MSDN: passing 0 requests the current task be granted ownership; // there's no need to pass our window handle. if(!OpenClipboard(new_owner)) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); EmptyClipboard(); - LibError err = ERR_FAIL; + LibError err = ERR::FAIL; { const size_t len = wcslen(text); HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (len+1) * sizeof(wchar_t)); if(!hMem) { - err = ERR_NO_MEM; + err = ERR::NO_MEM; goto fail; } @@ -378,7 +378,7 @@ LibError sys_clipboard_set(const wchar_t* text) GlobalUnlock(hMem); if(SetClipboardData(CF_UNICODETEXT, hMem) != 0) - err = INFO_OK; + err = INFO::OK; } } @@ -432,7 +432,7 @@ wchar_t* sys_clipboard_get() LibError sys_clipboard_free(wchar_t* copy) { free(copy); - return INFO_OK; + return INFO::OK; } @@ -468,7 +468,7 @@ static HCURSOR HCURSOR_from_ptr(void* p) // it is no longer needed and can be freed after this call returns. // hotspot (hx,hy) is the offset from its upper-left corner to the // position where mouse clicks are registered. -// cursor is only valid when INFO_OK is returned; in that case, it must be +// cursor is only valid when INFO::OK is returned; in that case, it must be // sys_cursor_free-ed when no longer needed. LibError sys_cursor_create(uint w, uint h, void* bgra_img, uint hx, uint hy, void** cursor) @@ -498,10 +498,10 @@ LibError sys_cursor_create(uint w, uint h, void* bgra_img, DeleteObject(hbmColour); if(!hIcon) // not INVALID_HANDLE_VALUE - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); *cursor = ptr_from_HICON(hIcon); - return INFO_OK; + return INFO::OK; } LibError sys_cursor_create_empty(void **cursor) @@ -521,7 +521,7 @@ LibError sys_cursor_set(void* cursor) (void)SetCursor(HCURSOR_from_ptr(cursor)); // return value (previous cursor) is useless. - return INFO_OK; + return INFO::OK; } @@ -531,7 +531,7 @@ LibError sys_cursor_free(void* cursor) { // bail now to prevent potential confusion below; there's nothing to do. if(!cursor) - return INFO_OK; + return INFO::OK; // if the cursor being freed is active, restore the default arrow // (just for safety). @@ -552,7 +552,7 @@ LibError sys_error_description_r(int user_err, char* buf, size_t max_chars) DWORD err = (DWORD)user_err; // not in our range (Win32 error numbers are positive) if(user_err < 0) - return ERR_FAIL; // NOWARN + return ERR::FAIL; // NOWARN // user doesn't know error code; get current error state if(!user_err) err = GetLastError(); @@ -563,9 +563,9 @@ LibError sys_error_description_r(int user_err, char* buf, size_t max_chars) DWORD chars_output = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, source, err, lang_id, buf, (DWORD)max_chars, args); if(!chars_output) - WARN_RETURN(ERR_FAIL); + WARN_RETURN(ERR::FAIL); debug_assert(chars_output < max_chars); - return INFO_OK; + return INFO::OK; } @@ -597,7 +597,7 @@ wchar_t* sys_get_module_filename(void* addr, wchar_t* path) inline LibError sys_get_executable_name(char* n_path, size_t buf_size) { DWORD nbytes = GetModuleFileName(0, n_path, (DWORD)buf_size); - return nbytes? INFO_OK : ERR_FAIL; + return nbytes? INFO::OK : ERR::FAIL; } diff --git a/source/lib/sysdep/win/wtime.cpp b/source/lib/sysdep/win/wtime.cpp index 4f92f0c62a..66b5e54211 100644 --- a/source/lib/sysdep/win/wtime.cpp +++ b/source/lib/sysdep/win/wtime.cpp @@ -52,6 +52,16 @@ WIN_REGISTER_FUNC(wtime_shutdown); #pragma data_seg() +namespace ERR +{ + const LibError TIMER_NO_SAFE_IMPL = -130100; +} + +AT_STARTUP(\ + error_setDescription(ERR::TIMER_NO_SAFE_IMPL, "No safe time source available");\ +) + + // see http://www.gamedev.net/reference/programming/features/timing/ . // rationale: @@ -199,7 +209,7 @@ static LibError choose_impl() hrt_impl = HRT_TSC; hrt_nominal_freq = cpu_freq; hrt_res = (1.0 / hrt_nominal_freq); - return INFO_OK; + return INFO::OK; } } #endif // TSC @@ -258,7 +268,7 @@ static LibError choose_impl() hrt_impl = HRT_QPC; hrt_nominal_freq = (double)qpc_freq; hrt_res = (1.0 / hrt_nominal_freq); - return INFO_OK; + return INFO::OK; } } #endif // QPC @@ -279,12 +289,12 @@ static LibError choose_impl() DWORD timer_period; // [hectonanoseconds] if(GetSystemTimeAdjustment(&adj, &timer_period, &adj_disabled)) hrt_res = (timer_period / 1e7); - return INFO_OK; + return INFO::OK; } hrt_impl = HRT_NONE; hrt_nominal_freq = -1.0; - WARN_RETURN(ERR_TIMER_NO_SAFE_IMPL); + WARN_RETURN(ERR::TIMER_NO_SAFE_IMPL); } @@ -393,7 +403,7 @@ static LibError reset_impl_lk() hrt_cal_ticks = ticks_lk(); } - return INFO_OK; + return INFO::OK; } @@ -462,7 +472,7 @@ static LibError hrt_override_impl(HRTOverride ovr, HRTImpl impl) { if((ovr != HRT_DISABLE && ovr != HRT_FORCE && ovr != HRT_DEFAULT) || (impl != HRT_TSC && impl != HRT_QPC && impl != HRT_GTC && impl != HRT_NONE)) - WARN_RETURN(ERR_INVALID_PARAM); + WARN_RETURN(ERR::INVALID_PARAM); lock(); @@ -597,7 +607,7 @@ static inline LibError init_calibration_thread() { sem_init(&exit_flag, 0, 0); pthread_create(&thread, 0, calibration_thread, 0); - return INFO_OK; + return INFO::OK; } @@ -606,7 +616,7 @@ static inline LibError shutdown_calibration_thread() sem_post(&exit_flag); pthread_join(thread, 0); sem_destroy(&exit_flag); - return INFO_OK; + return INFO::OK; } @@ -741,7 +751,7 @@ static LibError wtime_init() // first call latches start times time_ns(); - return INFO_OK; + return INFO::OK; } diff --git a/source/lib/tests/test_allocators.h b/source/lib/tests/test_allocators.h index 7bce233e3e..3bda16a99a 100644 --- a/source/lib/tests/test_allocators.h +++ b/source/lib/tests/test_allocators.h @@ -2,6 +2,7 @@ #include "lib/allocators.h" #include "lib/byte_order.h" +#include "lib/res/file/file_io.h" class TestAllocators : public CxxTest::TestSuite { @@ -22,7 +23,7 @@ public: u8 buf[4]; TS_ASSERT_OK(da_read(&da, buf, 4)); TS_ASSERT_EQUALS(read_le32(buf), 0x78563412); // read correct value - debug_skip_next_err(ERR_EOF); + debug_skip_next_err(ERR::IO_EOF); TS_ASSERT(da_read(&da, buf, 1) < 0); // no more data left TS_ASSERT_OK(da_free(&da)); } diff --git a/source/lib/tests/test_lib.h b/source/lib/tests/test_lib.h index 2064ed9582..02a0d80ad4 100644 --- a/source/lib/tests/test_lib.h +++ b/source/lib/tests/test_lib.h @@ -203,9 +203,9 @@ public: void test_rand() { // complain if huge interval or min > max - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TS_ASSERT_EQUALS(rand(1, 0), 0); - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TS_ASSERT_EQUALS(rand(2, ~0u), 0); // returned number must be in [min, max) diff --git a/source/lib/tests/test_lockfree.h b/source/lib/tests/test_lockfree.h index de0b1a638a..c376a55136 100644 --- a/source/lib/tests/test_lockfree.h +++ b/source/lib/tests/test_lockfree.h @@ -160,10 +160,10 @@ class TestMultithread : public CxxTest::TestSuite int err; err = lfl_erase(&this_->list, key); - TS_ASSERT(was_in_set == (err == INFO_OK)); + TS_ASSERT(was_in_set == (err == INFO::OK)); err = lfh_erase(&this_->hash, key); - TS_ASSERT(was_in_set == (err == INFO_OK)); + TS_ASSERT(was_in_set == (err == INFO::OK)); } break; diff --git a/source/lib/tests/test_path_util.h b/source/lib/tests/test_path_util.h index c719604354..e9c5784a3c 100644 --- a/source/lib/tests/test_path_util.h +++ b/source/lib/tests/test_path_util.h @@ -12,13 +12,13 @@ class TestPathUtil : public CxxTest::TestSuite TS_ASSERT_STR_EQUALS(dst, correct_result); } - // if correct_ret is ERR_FAIL, ignore correct_result. + // if correct_ret is ERR::FAIL, ignore correct_result. void TEST_REPLACE(const char* src, const char* remove, const char* replace, LibError correct_ret, const char* correct_result) { char dst[PATH_MAX] = {0}; TS_ASSERT_EQUALS(path_replace(dst, src, remove, replace), correct_ret); - if(correct_ret != ERR_FAIL) + if(correct_ret != ERR::FAIL) TS_ASSERT_STR_EQUALS(dst, correct_result); } @@ -108,17 +108,17 @@ public: void test_replace() { // no match - TEST_REPLACE("abc/def", "/def", "xx", ERR_FAIL, 0); + TEST_REPLACE("abc/def", "/def", "xx", ERR::FAIL, 0); // normal case: match and remove - TEST_REPLACE("abc/def", "abc", "ok", INFO_OK, "ok/def"); + TEST_REPLACE("abc/def", "abc", "ok", INFO::OK, "ok/def"); // caller also stripping / - TEST_REPLACE("abc/def", "abc/", "ok", INFO_OK, "ok/def"); + TEST_REPLACE("abc/def", "abc/", "ok", INFO::OK, "ok/def"); // empty remove - TEST_REPLACE("abc/def", "", "ok", INFO_OK, "ok/abc/def"); + TEST_REPLACE("abc/def", "", "ok", INFO::OK, "ok/abc/def"); // empty replace - TEST_REPLACE("abc/def", "abc", "", INFO_OK, "def"); + TEST_REPLACE("abc/def", "abc", "", INFO::OK, "def"); // remove entire string - TEST_REPLACE("abc/def", "abc/def", "", INFO_OK, ""); + TEST_REPLACE("abc/def", "abc/def", "", INFO::OK, ""); } void test_name_only() diff --git a/source/lib/tests/test_string_s.h b/source/lib/tests/test_string_s.h index 162d0b8db2..4399cdf985 100644 --- a/source/lib/tests/test_string_s.h +++ b/source/lib/tests/test_string_s.h @@ -11,7 +11,7 @@ class TestString_s : public CxxTest::TestSuite { - // note: avoid 4-byte strings - they would trigger WARN_IF_PTR_LEN. + // note: avoid 4-byte strings - they would trigger WARN::IF_PTR_LEN. const char* const s0; const char* const s1; @@ -108,64 +108,64 @@ public: void test_param_validation() { #if !HAVE_STRING_S - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CPY(0 ,0,0 , EINVAL,""); // all invalid - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CPY(0 ,0,s1, EINVAL,""); // dst = 0, max = 0 - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CPY(0 ,1,s1, EINVAL,""); // dst = 0, max > 0 - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CPY(d1,1,0 , EINVAL,""); // src = 0 - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CPY(d1,0,s1, ERANGE,""); // max_dst_chars = 0 - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_CPY2(d1,1, s1, ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_CPY2(d1,1, s5, ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_CPY2(d5,5, s5, ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_NCPY(d1,1 ,s1,1, ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_NCPY(d1,1 ,s5,1, ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_NCPY(d5,5 ,s5,5, ERANGE,""); - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CAT(0 ,0,0 , EINVAL,""); // all invalid - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CAT(0 ,0,s1, EINVAL,""); // dst = 0, max = 0 - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CAT(0 ,1,s1, EINVAL,""); // dst = 0, max > 0 - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CAT(d1,1,0 , EINVAL,""); // src = 0 - debug_skip_next_err(ERR_INVALID_PARAM); + debug_skip_next_err(ERR::INVALID_PARAM); TEST_CAT(d1,0,s1, ERANGE,""); // max_dst_chars = 0 - debug_skip_next_err(ERR_STRING_NOT_TERMINATED); + debug_skip_next_err(ERR::STRING_NOT_TERMINATED); TEST_CAT(no_null,5,s1, ERANGE,""); // dst not terminated - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_CAT2(d1,1, s1, "",ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_CAT2(d1,1, s5, "",ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_CAT2(d10,10, s10, "",ERANGE,""); // empty, total overflow - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_CAT2(d10,10, s5, "12345",ERANGE,""); // not empty, overflow - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_CAT2(d10,10, s10, "12345",ERANGE,""); // not empty, total overflow - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_NCAT(d1,1, s1,1, "",ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_NCAT(d1,1, s5,5, "",ERANGE,""); - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_NCAT(d10,10, s10,10, "",ERANGE,""); // empty, total overflow - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_NCAT(d10,10, s5,5, "12345",ERANGE,""); // not empty, overflow - debug_skip_next_err(ERR_BUF_SIZE); + debug_skip_next_err(ERR::BUF_SIZE); TEST_NCAT(d10,10, s10,10, "12345",ERANGE,""); // not empty, total overflow #endif } diff --git a/source/lib/timer.h b/source/lib/timer.h index 9292aadc77..469a628f3f 100644 --- a/source/lib/timer.h +++ b/source/lib/timer.h @@ -28,9 +28,6 @@ #include "debug.h" // debug_printf -#ifdef __cplusplus -extern "C" { -#endif // high resolution (> 1 us) timestamp [s], starting at or near 0 s. extern double get_time(void); @@ -116,11 +113,6 @@ extern void timer_bill_client(TimerClient* tc, TimerUnit dt); // typically called at exit. extern void timer_display_client_totals(); -#ifdef __cplusplus -} -#endif - - // used via TIMER* macros below. diff --git a/source/lib/types.h b/source/lib/types.h index 8916f96862..f9191f5d1e 100644 --- a/source/lib/types.h +++ b/source/lib/types.h @@ -24,7 +24,6 @@ #define __TYPES_H__ #include "posix_types.h" -#include "lib_errors.h" // defines instead of typedefs so we can #undef conflicting decls diff --git a/source/main.cpp b/source/main.cpp index 34687de5e6..74e87c9a89 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -98,13 +98,13 @@ static void PumpEvents() static bool ProgressiveBuildArchive() { int ret = vfs_opt_auto_build("../logs/trace.txt", "mods/official/official%02d.zip", "mods/official/mini%02d.zip"); - if(ret == INFO_ALL_COMPLETE) + if(ret == INFO::ALL_COMPLETE) { // nothing to do; will return false below } else if(ret < 0) DISPLAY_ERROR(L"Archive build failed"); - else if(ret == INFO_OK) + else if(ret == INFO::OK) g_GUI.SendEventToAll("archivebuildercomplete"); // in progress else @@ -127,14 +127,14 @@ static int ProgressiveLoad() switch(ret) { // no load active => no-op (skip code below) - case INFO_OK: + case INFO::OK: return 0; // current task didn't complete. we only care about this insofar as the // load process is therefore not yet finished. - case ERR_TIMED_OUT: + case ERR::TIMED_OUT: break; // just finished loading - case INFO_ALL_COMPLETE: + case INFO::ALL_COMPLETE: g_Game->ReallyStartGame(); wcscpy_s(description, ARRAY_SIZE(description), L"Game is starting.."); // LDR_ProgressiveLoad returns L""; set to valid text to @@ -143,7 +143,7 @@ static int ProgressiveLoad() // error! default: CHECK_ERR(ret); - // can't do this above due to legit ERR_TIMED_OUT + // can't do this above due to legit ERR::TIMED_OUT break; } diff --git a/source/network/Client.cpp b/source/network/Client.cpp index a7ad8e7591..c1a4e0bd36 100644 --- a/source/network/Client.cpp +++ b/source/network/Client.cpp @@ -17,7 +17,7 @@ #define LOG_CAT_NET "net" CNetClient *g_NetClient=NULL; -extern "C" int fps; +extern int fps; extern CConsole *g_Console; CNetClient::CServerSession::CServerSession(int sessionID, const CStrW& name): diff --git a/source/ps/CVFSFile.cpp b/source/ps/CVFSFile.cpp index d51916b7b4..8e8604ba36 100644 --- a/source/ps/CVFSFile.cpp +++ b/source/ps/CVFSFile.cpp @@ -26,7 +26,7 @@ PSRETURN CVFSFile::Load(const char* filename, uint flags /* = 0 */) } LibError ret = vfs_load(filename, m_Buffer, m_BufferSize, flags); - if (ret != INFO_OK) + if (ret != INFO::OK) { LOG(ERROR, LOG_CATEGORY, "CVFSFile: file %s couldn't be opened (vfs_load: %d)", filename, ret); return PSRETURN_CVFSFile_LoadFailed; diff --git a/source/ps/ConfigDB.cpp b/source/ps/ConfigDB.cpp index 89200418e4..6b03c4013e 100644 --- a/source/ps/ConfigDB.cpp +++ b/source/ps/ConfigDB.cpp @@ -251,7 +251,7 @@ bool CConfigDB::Reload(EConfigNamespace ns) { // Open file with VFS ret = vfs_load(m_ConfigFile[ns], buffer, buflen); - if(ret != INFO_OK) + if(ret != INFO::OK) { LOG(ERROR, LOG_CATEGORY, "vfs_load for \"%s\" failed: return was %lld", m_ConfigFile[ns].c_str(), ret); return false; @@ -259,7 +259,7 @@ bool CConfigDB::Reload(EConfigNamespace ns) } else { - if (file_open(m_ConfigFile[ns], 0, &f)!=INFO_OK) + if (file_open(m_ConfigFile[ns], 0, &f)!=INFO::OK) { LOG(ERROR, LOG_CATEGORY, "file_open for \"%s\" failed", m_ConfigFile[ns].c_str()); return false; diff --git a/source/ps/Loader.cpp b/source/ps/Loader.cpp index 07c6e868d0..a0434de674 100644 --- a/source/ps/Loader.cpp +++ b/source/ps/Loader.cpp @@ -88,11 +88,11 @@ struct DurationAdder: public std::binary_function SkyManager::GetSkySets() const skies.push_back(CStr(entry.name)); } - if (err != ERR_DIR_END) + if (err != ERR::DIR_END) { LOG(ERROR, "vfs", "Error reading files from directory '%s' (%d)", dirname, err); return std::vector(1, GetSkySet()); // just return what we currently have diff --git a/source/scripting/ScriptGlue.h b/source/scripting/ScriptGlue.h index 6a7585afe0..b80d459d45 100644 --- a/source/scripting/ScriptGlue.h +++ b/source/scripting/ScriptGlue.h @@ -10,7 +10,7 @@ extern JSPropertySpec ScriptGlobalTable[]; // dependencies (moved to header to avoid L4 warnings) // .. from main.cpp: -extern "C" int fps; +extern int fps; extern void kill_mainloop(); extern CStr g_CursorName; extern void StartGame(); diff --git a/source/scripting/ScriptingHost.cpp b/source/scripting/ScriptingHost.cpp index 116f3dc23d..f93c14116f 100644 --- a/source/scripting/ScriptingHost.cpp +++ b/source/scripting/ScriptingHost.cpp @@ -112,7 +112,7 @@ void ScriptingHost::RunScript(const CStr& filename, JSObject* globalObject) FileIOBuf buf; size_t size; - if(vfs_load(fn, buf, size) != INFO_OK) // ERRTODO: translate/pass it on + if(vfs_load(fn, buf, size) != INFO::OK) // ERRTODO: translate/pass it on throw PSERROR_Scripting_LoadFile_OpenFailed(); const char* script = (const char*)buf; diff --git a/source/sound/CMusicPlayer.cpp b/source/sound/CMusicPlayer.cpp index f6548e5b4d..9b25301f32 100644 --- a/source/sound/CMusicPlayer.cpp +++ b/source/sound/CMusicPlayer.cpp @@ -42,7 +42,7 @@ void CMusicPlayer::open(char* UNUSED(filename)) /* void* p; size_t sizeOfFile; - if(vfs_load(filename, p, sizeOfFile) != INFO_OK) + if(vfs_load(filename, p, sizeOfFile) != INFO::OK) { LOG(ERROR, LOG_CATEGORY, "CMusicPlayer::open(): vfs_load for %s failed!\n", filename); return; diff --git a/source/sound/JSI_Sound.cpp b/source/sound/JSI_Sound.cpp index 166f81912b..ec222830be 100644 --- a/source/sound/JSI_Sound.cpp +++ b/source/sound/JSI_Sound.cpp @@ -14,7 +14,7 @@ JSI_Sound::JSI_Sound( const CStr& Filename ) // special-case to avoid throwing exceptions if quickstart has // disabled sound: set a flag queried by Construct; the object will // then immediately be freed. - if(m_Handle == ERR_AGAIN) + if(m_Handle == ERR::AGAIN) { m_SoundDisabled = true; return;