forked from 0ad/0ad
# SwEng (reduce full recompiles by splitting up master error header)
- error codes now accessed as ERR::NO_MEM, INFO::OK etc. - no more X-macros => the above are now recognized by visual assist - error codes are defined by the module originating them (lib_errors has some generic ones) => no full rebuild when adding some - error descriptions are now in C++ files => can be changed without full rebuild added AT_STARTUP in lib.h. This was SVN commit r4374.
This commit is contained in:
parent
05aadf1f12
commit
871cdb6ef9
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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__
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -34,20 +34,44 @@
|
||||
#include <stdlib.h> // abs
|
||||
#include <errno.h>
|
||||
|
||||
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<LibError, LibErrorAssociation> 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())
|
||||
{
|
||||
// <err> 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 <err>. 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);\
|
||||
)
|
||||
|
@ -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__
|
||||
|
@ -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
|
||||
// <num_entries>; 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
// <num_entries>; 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.
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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__
|
||||
|
@ -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 <remove> from the start of <src>, prepend <replace>,
|
||||
// and write to <dst>.
|
||||
// returns ERR_FAIL (without warning!) if the beginning of <src> doesn't
|
||||
// returns ERR::FAIL (without warning!) if the beginning of <src> doesn't
|
||||
// match <remove>.
|
||||
LibError path_replace(char* dst, const char* src, const char* remove, const char* replace)
|
||||
{
|
||||
// remove doesn't match start of <src>
|
||||
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;
|
||||
}
|
||||
|
@ -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 <remove>.
|
||||
* @return LibError; ERR_FAIL (without warning!) if <src> doesn't
|
||||
* @return LibError; ERR::FAIL (without warning!) if <src> doesn't
|
||||
* match <remove>.
|
||||
**/
|
||||
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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
// <ctx> and <max_output_size> 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);
|
||||
|
@ -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 <user>.
|
||||
// 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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,13 @@
|
||||
#ifndef COMPRESSION_H__
|
||||
#define COMPRESSION_H__
|
||||
|
||||
|
||||
namespace ERR
|
||||
{
|
||||
const LibError COMPRESSION_UNKNOWN_METHOD = -110300;
|
||||
}
|
||||
|
||||
|
||||
enum ContextType
|
||||
{
|
||||
CT_COMPRESSION,
|
||||
|
@ -36,6 +36,14 @@
|
||||
#include <string>
|
||||
|
||||
|
||||
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<PathPackage> pp_allocator;
|
||||
|
||||
|
||||
// prepare to iterate (once) over entries in the given directory.
|
||||
// if INFO_OK is returned, <d> is ready for subsequent dir_next_ent calls and
|
||||
// if INFO::OK is returned, <d> 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 <ent>
|
||||
// return ERR::DIR_END if all entries have already been returned once,
|
||||
// another negative error code, or INFO::OK on success, in which case <ent>
|
||||
// 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 <N_fn> 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;
|
||||
}
|
||||
|
@ -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, <d> is ready for subsequent dir_next_ent calls and
|
||||
// if INFO::OK is returned, <d> 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 <ent>
|
||||
// return ERR::DIR_END if all entries have already been returned once,
|
||||
// another negative error code, or INFO::OK on success, in which case <ent>
|
||||
// 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 <size> bytes (possibly more due to internal
|
||||
// fragmentation). never returns 0.
|
||||
// <atom_fn>: 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 <buf> 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 <size> bytes, starting at <ofs>, to/from the given file.
|
||||
// (read or write access was chosen at file-open time).
|
||||
//
|
||||
// if non-NULL, <cb> is called for each block transferred, passing <ctx>.
|
||||
// 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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 <filter>.
|
||||
// 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,
|
||||
// - <pattern>: 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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 <size> bytes (possibly more due to internal
|
||||
// fragmentation). never returns 0.
|
||||
// <atom_fn>: 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 <buf> 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 <size> bytes, starting at <ofs>, to/from the given file.
|
||||
// (read or write access was chosen at file-open time).
|
||||
//
|
||||
// if non-NULL, <cb> is called for each block transferred, passing <ctx>.
|
||||
// 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);
|
||||
|
||||
|
@ -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 <filter>.
|
||||
// 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)
|
||||
// - <pattern>: 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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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: <di> 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 <filter>.
|
||||
// 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)
|
||||
// - <pattern>: 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)
|
||||
{
|
||||
// <ofs> 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);
|
||||
// <size> 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 <filter>.
|
||||
// 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);
|
||||
// - <pattern>: 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.
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
|
||||
|
||||
// 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<Handle> 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: <name> 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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 <path> and pass back information
|
||||
@ -87,7 +94,7 @@ extern LibError tree_lookup(const char* path, TFile** ptf, uint flags = 0);
|
||||
// <path> 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);
|
||||
|
||||
|
||||
|
@ -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 <max_scan_amount> bytes of the file.
|
||||
// if found, fill <dst_ecdr> 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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
// <LineSpacing> and <Height> 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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 <filename> 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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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__
|
||||
|
30
source/lib/res/res.cpp
Normal file
30
source/lib/res/res.cpp
Normal file
@ -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");\
|
||||
)
|
@ -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
|
||||
|
@ -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);
|
||||
// <last_buf> 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 <pos>
|
||||
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);
|
||||
// <static_pri> and <cur_pri> 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 - <vs> has been freed.
|
||||
return INFO::OK; // don't continue - <vs> 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
|
||||
}
|
||||
|
||||
|
||||
|
@ -186,7 +186,7 @@ extern bool self_test_active;
|
||||
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#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__
|
||||
|
@ -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 <dst> 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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 <location> against
|
||||
// <expected>; if not equal, return false; otherwise, overwrite it with
|
||||
// <new_value> 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 <location> 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__
|
||||
|
@ -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()
|
||||
|
@ -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__
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
|
@ -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__
|
||||
|
@ -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 <cmath> 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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -601,7 +601,7 @@ static LibError wdll_shutdown()
|
||||
// changes __puiHead!
|
||||
}
|
||||
|
||||
return INFO_OK;
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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__
|
||||
|
@ -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 <user_arg>.
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 <fn> 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.
|
||||
// <fn> 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 <start> 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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__
|
||||
|
@ -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<StringSet::iterator, bool> 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 } }
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user