From 5a4d38d249074e2b0dee688c06a1c19a90a9c38d Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Thu, 5 Sep 2019 18:42:28 +0200 Subject: [PATCH] project: Fix a massive list of dangerous warnings This is a massive improvement to stability and safety when using the plugin, as all exceptions should now no longer be leaked into C controlled code, which can't actually handle exceptions at all. Warnings fixed: * Potentially throwing exception during library load. * Possibly throwing function passed to C. * Statement does nothing. * Variable is initialized but not referenced. * Variable overloads variable in parent scope. --- source/filters/filter-dynamic-mask.cpp | 7 +- source/filters/filter-dynamic-mask.hpp | 2 +- source/filters/filter-sdf-effects.cpp | 93 ++++++++++++++++---------- source/filters/filter-sdf-effects.hpp | 36 +++++----- source/filters/filter-shader.cpp | 20 +++--- source/filters/filter-transform.cpp | 66 +++++++++++------- source/filters/filter-transform.hpp | 30 ++++----- source/gfx/gfx-effect-source.cpp | 46 ++++++++----- source/gfx/gfx-effect-source.hpp | 4 +- source/obs/gs/gs-effect.cpp | 24 +++---- source/obs/gs/gs-vertexbuffer.cpp | 4 +- source/obs/obs-source-tracker.cpp | 16 +++-- source/obs/obs-source-tracker.hpp | 6 +- source/obs/obs-tools.cpp | 12 ++-- source/plugin.cpp | 71 +++++++++++--------- source/plugin.hpp | 20 +++--- source/sources/source-mirror.cpp | 4 +- source/sources/source-mirror.hpp | 2 +- source/strings.hpp | 2 + source/utility.cpp | 3 +- 20 files changed, 270 insertions(+), 198 deletions(-) diff --git a/source/filters/filter-dynamic-mask.cpp b/source/filters/filter-dynamic-mask.cpp index c0c1b523..8ccf7987 100644 --- a/source/filters/filter-dynamic-mask.cpp +++ b/source/filters/filter-dynamic-mask.cpp @@ -287,6 +287,8 @@ void filter::dynamic_mask::dynamic_mask_instance::update(obs_data_t* settings) case channel::Alpha: ch = &this->_precalc.matrix.t; break; + default: + break; } for (auto kv2 : channel_translations) { @@ -343,7 +345,7 @@ void filter::dynamic_mask::dynamic_mask_instance::input_renamed(obs::source*, st } bool filter::dynamic_mask::dynamic_mask_instance::modified(void*, obs_properties_t* properties, obs_property_t*, - obs_data_t* settings) + obs_data_t* settings) noexcept try { channel mask = static_cast(obs_data_get_int(settings, ST_CHANNEL)); @@ -360,6 +362,9 @@ bool filter::dynamic_mask::dynamic_mask_instance::modified(void*, obs_properties } return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in modified_properties callback."); + return false; } void filter::dynamic_mask::dynamic_mask_instance::video_tick(float) diff --git a/source/filters/filter-dynamic-mask.hpp b/source/filters/filter-dynamic-mask.hpp index 78025b5f..4af55ba5 100644 --- a/source/filters/filter-dynamic-mask.hpp +++ b/source/filters/filter-dynamic-mask.hpp @@ -102,7 +102,7 @@ namespace filter { void input_renamed(obs::source* src, std::string old_name, std::string new_name); static bool modified(void* self, obs_properties_t* properties, obs_property_t* property, - obs_data_t* settings); + obs_data_t* settings) noexcept; void video_tick(float _time); void video_render(gs_effect_t* effect); diff --git a/source/filters/filter-sdf-effects.cpp b/source/filters/filter-sdf-effects.cpp index aac3c948..329ee93d 100644 --- a/source/filters/filter-sdf-effects.cpp +++ b/source/filters/filter-sdf-effects.cpp @@ -135,18 +135,18 @@ void filter::sdf_effects::sdf_effects_factory::on_list_empty() this->_sdf_consumer_effect.reset(); } -void* filter::sdf_effects::sdf_effects_factory::create(obs_data_t* data, obs_source_t* parent) -{ +void* filter::sdf_effects::sdf_effects_factory::create(obs_data_t* data, obs_source_t* parent) noexcept try { if (get()->_sources.empty()) { get()->on_list_fill(); } filter::sdf_effects::sdf_effects_instance* ptr = new filter::sdf_effects::sdf_effects_instance(data, parent); get()->_sources.push_back(ptr); return ptr; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::sdf_effects::sdf_effects_factory::destroy(void* inptr) -{ +void filter::sdf_effects::sdf_effects_factory::destroy(void* inptr) noexcept try { filter::sdf_effects::sdf_effects_instance* ptr = reinterpret_cast(inptr); get()->_sources.remove(ptr); @@ -154,10 +154,11 @@ void filter::sdf_effects::sdf_effects_factory::destroy(void* inptr) get()->on_list_empty(); } delete ptr; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::sdf_effects::sdf_effects_factory::get_defaults(obs_data_t* data) -{ +void filter::sdf_effects::sdf_effects_factory::get_defaults(obs_data_t* data) noexcept try { obs_data_set_default_bool(data, ST_SHADOW_OUTER, false); obs_data_set_default_int(data, ST_SHADOW_OUTER_COLOR, 0x00000000); obs_data_set_default_double(data, ST_SHADOW_OUTER_ALPHA, 100.0); @@ -196,51 +197,62 @@ void filter::sdf_effects::sdf_effects_factory::get_defaults(obs_data_t* data) obs_data_set_default_bool(data, S_ADVANCED, false); obs_data_set_default_double(data, ST_SDF_SCALE, 100.0); obs_data_set_default_double(data, ST_SDF_THRESHOLD, 50.0); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -obs_properties_t* filter::sdf_effects::sdf_effects_factory::get_properties(void* inptr) -{ +obs_properties_t* filter::sdf_effects::sdf_effects_factory::get_properties(void* inptr) noexcept try { return reinterpret_cast(inptr)->get_properties(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::sdf_effects::sdf_effects_factory::update(void* inptr, obs_data_t* settings) -{ +void filter::sdf_effects::sdf_effects_factory::update(void* inptr, obs_data_t* settings) noexcept try { reinterpret_cast(inptr)->update(settings); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -const char* filter::sdf_effects::sdf_effects_factory::get_name(void*) -{ +const char* filter::sdf_effects::sdf_effects_factory::get_name(void*) noexcept try { return D_TRANSLATE(ST); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -uint32_t filter::sdf_effects::sdf_effects_factory::get_width(void* inptr) -{ +uint32_t filter::sdf_effects::sdf_effects_factory::get_width(void* inptr) noexcept try { return reinterpret_cast(inptr)->get_width(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -uint32_t filter::sdf_effects::sdf_effects_factory::get_height(void* inptr) -{ +uint32_t filter::sdf_effects::sdf_effects_factory::get_height(void* inptr) noexcept try { return reinterpret_cast(inptr)->get_height(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::sdf_effects::sdf_effects_factory::activate(void* inptr) -{ +void filter::sdf_effects::sdf_effects_factory::activate(void* inptr) noexcept try { reinterpret_cast(inptr)->activate(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::sdf_effects::sdf_effects_factory::deactivate(void* inptr) -{ +void filter::sdf_effects::sdf_effects_factory::deactivate(void* inptr) noexcept try { reinterpret_cast(inptr)->deactivate(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::sdf_effects::sdf_effects_factory::video_tick(void* inptr, float delta) -{ +void filter::sdf_effects::sdf_effects_factory::video_tick(void* inptr, float delta) noexcept try { reinterpret_cast(inptr)->video_tick(delta); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::sdf_effects::sdf_effects_factory::video_render(void* inptr, gs_effect_t* effect) -{ +void filter::sdf_effects::sdf_effects_factory::video_render(void* inptr, gs_effect_t* effect) noexcept try { reinterpret_cast(inptr)->video_render(effect); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } std::shared_ptr filter::sdf_effects::sdf_effects_factory::get_sdf_producer_effect() @@ -254,8 +266,7 @@ std::shared_ptr filter::sdf_effects::sdf_effects_factory::get_sdf_co } bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_inside(void*, obs_properties_t* props, obs_property*, - obs_data_t* settings) -{ + obs_data_t* settings) noexcept try { bool v = obs_data_get_bool(settings, ST_SHADOW_INNER); obs_property_set_visible(obs_properties_get(props, ST_SHADOW_INNER_RANGE_MINIMUM), v); obs_property_set_visible(obs_properties_get(props, ST_SHADOW_INNER_RANGE_MAXIMUM), v); @@ -264,11 +275,13 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_inside(void*, obs_property_set_visible(obs_properties_get(props, ST_SHADOW_INNER_COLOR), v); obs_property_set_visible(obs_properties_get(props, ST_SHADOW_INNER_ALPHA), v); return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_outside(void*, obs_properties_t* props, - obs_property*, obs_data_t* settings) -{ +bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_outside(void*, obs_properties_t* props, + obs_property*, + obs_data_t* settings) noexcept try { bool v = obs_data_get_bool(settings, ST_SHADOW_OUTER); obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_RANGE_MINIMUM), v); obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_RANGE_MAXIMUM), v); @@ -277,33 +290,36 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_shadow_outside(void* obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_COLOR), v); obs_property_set_visible(obs_properties_get(props, ST_SHADOW_OUTER_ALPHA), v); return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } bool filter::sdf_effects::sdf_effects_instance::cb_modified_glow_inside(void*, obs_properties_t* props, obs_property*, - obs_data_t* settings) -{ + obs_data_t* settings) noexcept try { bool v = obs_data_get_bool(settings, ST_GLOW_INNER); obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_COLOR), v); obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_ALPHA), v); obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_WIDTH), v); obs_property_set_visible(obs_properties_get(props, ST_GLOW_INNER_SHARPNESS), v); return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } bool filter::sdf_effects::sdf_effects_instance::cb_modified_glow_outside(void*, obs_properties_t* props, obs_property*, - obs_data_t* settings) -{ + obs_data_t* settings) noexcept try { bool v = obs_data_get_bool(settings, ST_GLOW_OUTER); obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_COLOR), v); obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_ALPHA), v); obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_WIDTH), v); obs_property_set_visible(obs_properties_get(props, ST_GLOW_OUTER_SHARPNESS), v); return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } bool filter::sdf_effects::sdf_effects_instance::cb_modified_outline(void*, obs_properties_t* props, obs_property*, - obs_data_t* settings) -{ + obs_data_t* settings) noexcept try { bool v = obs_data_get_bool(settings, ST_OUTLINE); obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_COLOR), v); obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_ALPHA), v); @@ -311,15 +327,18 @@ bool filter::sdf_effects::sdf_effects_instance::cb_modified_outline(void*, obs_p obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_OFFSET), v); obs_property_set_visible(obs_properties_get(props, ST_OUTLINE_SHARPNESS), v); return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } bool filter::sdf_effects::sdf_effects_instance::cb_modified_advanced(void*, obs_properties_t* props, obs_property*, - obs_data_t* settings) -{ + obs_data_t* settings) noexcept try { bool show_advanced = obs_data_get_bool(settings, S_ADVANCED); obs_property_set_visible(obs_properties_get(props, ST_SDF_SCALE), show_advanced); obs_property_set_visible(obs_properties_get(props, ST_SDF_THRESHOLD), show_advanced); return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } filter::sdf_effects::sdf_effects_instance::sdf_effects_instance(obs_data_t* settings, obs_source_t* self) diff --git a/source/filters/filter-sdf-effects.hpp b/source/filters/filter-sdf-effects.hpp index cbe01978..52f4f3b9 100644 --- a/source/filters/filter-sdf-effects.hpp +++ b/source/filters/filter-sdf-effects.hpp @@ -60,22 +60,22 @@ namespace filter { void on_list_fill(); void on_list_empty(); - static void* create(obs_data_t* settings, obs_source_t* self); - static void destroy(void* source); + static void* create(obs_data_t* settings, obs_source_t* self) noexcept; + static void destroy(void* source) noexcept; - static void get_defaults(obs_data_t* settings); - static obs_properties_t* get_properties(void* source); - static void update(void* source, obs_data_t* settings); + static void get_defaults(obs_data_t* settings) noexcept; + static obs_properties_t* get_properties(void* source) noexcept; + static void update(void* source, obs_data_t* settings) noexcept; - static const char* get_name(void* source); - static uint32_t get_width(void* source); - static uint32_t get_height(void* source); + static const char* get_name(void* source) noexcept; + static uint32_t get_width(void* source) noexcept; + static uint32_t get_height(void* source) noexcept; - static void activate(void* source); - static void deactivate(void* source); + static void activate(void* source) noexcept; + static void deactivate(void* source) noexcept; - static void video_tick(void* source, float delta); - static void video_render(void* source, gs_effect_t* effect); + static void video_tick(void* source, float delta) noexcept; + static void video_render(void* source, gs_effect_t* effect) noexcept; public: std::shared_ptr get_sdf_producer_effect(); @@ -136,22 +136,22 @@ namespace filter { float_t _outline_sharpness_inv; static bool cb_modified_shadow_inside(void* ptr, obs_properties_t* props, obs_property* prop, - obs_data_t* settings); + obs_data_t* settings) noexcept; static bool cb_modified_shadow_outside(void* ptr, obs_properties_t* props, obs_property* prop, - obs_data_t* settings); + obs_data_t* settings) noexcept; static bool cb_modified_glow_inside(void* ptr, obs_properties_t* props, obs_property* prop, - obs_data_t* settings); + obs_data_t* settings) noexcept; static bool cb_modified_glow_outside(void* ptr, obs_properties_t* props, obs_property* prop, - obs_data_t* settings); + obs_data_t* settings) noexcept; static bool cb_modified_outline(void* ptr, obs_properties_t* props, obs_property* prop, - obs_data_t* settings); + obs_data_t* settings) noexcept; static bool cb_modified_advanced(void* ptr, obs_properties_t* props, obs_property* prop, - obs_data_t* settings); + obs_data_t* settings) noexcept; public: sdf_effects_instance(obs_data_t* settings, obs_source_t* self); diff --git a/source/filters/filter-shader.cpp b/source/filters/filter-shader.cpp index d90443e5..a52d5ce3 100644 --- a/source/filters/filter-shader.cpp +++ b/source/filters/filter-shader.cpp @@ -218,18 +218,20 @@ uint32_t filter::shader::shader_instance::height() return _sheight; } +bool modifiedcb3(obs_properties_t* props, obs_property_t* property, obs_data_t* settings) noexcept try { + obs_property_set_visible(obs_properties_get(props, ST_SCALE_SCALE), obs_data_get_bool(settings, ST_SCALE_LOCKED)); + obs_property_set_visible(obs_properties_get(props, ST_SCALE_WIDTH), !obs_data_get_bool(settings, ST_SCALE_LOCKED)); + obs_property_set_visible(obs_properties_get(props, ST_SCALE_HEIGHT), !obs_data_get_bool(settings, ST_SCALE_LOCKED)); + return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return false; +} + void filter::shader::shader_instance::properties(obs_properties_t* props) { auto p = obs_properties_add_bool(props, ST_SCALE_LOCKED, D_TRANSLATE(ST_SCALE_LOCKED)); - obs_property_set_modified_callback(p, [](obs_properties_t* props, obs_property_t* property, obs_data_t* settings) { - obs_property_set_visible(obs_properties_get(props, ST_SCALE_SCALE), - obs_data_get_bool(settings, ST_SCALE_LOCKED)); - obs_property_set_visible(obs_properties_get(props, ST_SCALE_WIDTH), - !obs_data_get_bool(settings, ST_SCALE_LOCKED)); - obs_property_set_visible(obs_properties_get(props, ST_SCALE_HEIGHT), - !obs_data_get_bool(settings, ST_SCALE_LOCKED)); - return true; - }); + obs_property_set_modified_callback(p, modifiedcb3); obs_properties_add_float(props, ST_SCALE_SCALE, D_TRANSLATE(ST_SCALE_SCALE), 0.01, 5.0, 0.01); obs_properties_add_float(props, ST_SCALE_WIDTH, D_TRANSLATE(ST_SCALE_WIDTH), 0.01, 5.0, 0.01); obs_properties_add_float(props, ST_SCALE_HEIGHT, D_TRANSLATE(ST_SCALE_HEIGHT), 0.01, 5.0, 0.01); diff --git a/source/filters/filter-transform.cpp b/source/filters/filter-transform.cpp index dcace777..5bd5bd2f 100644 --- a/source/filters/filter-transform.cpp +++ b/source/filters/filter-transform.cpp @@ -116,13 +116,13 @@ filter::transform::transform_factory::transform_factory() filter::transform::transform_factory::~transform_factory() {} -const char* filter::transform::transform_factory::get_name(void*) -{ +const char* filter::transform::transform_factory::get_name(void*) noexcept try { return D_TRANSLATE(ST); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::transform::transform_factory::get_defaults(obs_data_t* data) -{ +void filter::transform::transform_factory::get_defaults(obs_data_t* data) noexcept try { obs_data_set_default_int(data, ST_CAMERA, (int64_t)CameraMode::Orthographic); obs_data_set_default_double(data, ST_CAMERA_FIELDOFVIEW, 90.0); obs_data_set_default_double(data, ST_POSITION_X, 0); @@ -137,10 +137,11 @@ void filter::transform::transform_factory::get_defaults(obs_data_t* data) obs_data_set_default_double(data, ST_SHEAR_Y, 0); obs_data_set_default_bool(data, S_ADVANCED, false); obs_data_set_default_int(data, ST_ROTATION_ORDER, RotationOrder::ZXY); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -obs_properties_t* filter::transform::transform_factory::get_properties(void*) -{ +obs_properties_t* filter::transform::transform_factory::get_properties(void*) noexcept try { obs_properties_t* pr = obs_properties_create(); obs_property_t* p = NULL; @@ -237,10 +238,12 @@ obs_properties_t* filter::transform::transform_factory::get_properties(void*) obs_property_set_long_description(p, D_TRANSLATE(D_DESC(S_MIPGENERATOR_INTENSITY))); return pr; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -bool filter::transform::transform_factory::modified_properties(obs_properties_t* pr, obs_property_t*, obs_data_t* d) -{ +bool filter::transform::transform_factory::modified_properties(obs_properties_t* pr, obs_property_t*, + obs_data_t* d) noexcept try { switch ((CameraMode)obs_data_get_int(d, ST_CAMERA)) { case CameraMode::Orthographic: obs_property_set_visible(obs_properties_get(pr, ST_CAMERA_FIELDOFVIEW), false); @@ -261,51 +264,62 @@ bool filter::transform::transform_factory::modified_properties(obs_properties_t* obs_property_set_visible(obs_properties_get(pr, S_MIPGENERATOR_INTENSITY), mipmappingVisible); return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void* filter::transform::transform_factory::create(obs_data_t* data, obs_source_t* source) -{ +void* filter::transform::transform_factory::create(obs_data_t* data, obs_source_t* source) noexcept try { return new transform_instance(data, source); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::transform::transform_factory::destroy(void* ptr) -{ +void filter::transform::transform_factory::destroy(void* ptr) noexcept try { delete reinterpret_cast(ptr); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -uint32_t filter::transform::transform_factory::get_width(void* ptr) -{ +uint32_t filter::transform::transform_factory::get_width(void* ptr) noexcept try { return reinterpret_cast(ptr)->get_width(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -uint32_t filter::transform::transform_factory::get_height(void* ptr) -{ +uint32_t filter::transform::transform_factory::get_height(void* ptr) noexcept try { return reinterpret_cast(ptr)->get_height(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::transform::transform_factory::update(void* ptr, obs_data_t* data) -{ +void filter::transform::transform_factory::update(void* ptr, obs_data_t* data) noexcept try { reinterpret_cast(ptr)->update(data); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::transform::transform_factory::activate(void* ptr) -{ +void filter::transform::transform_factory::activate(void* ptr) noexcept try { reinterpret_cast(ptr)->activate(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::transform::transform_factory::deactivate(void* ptr) -{ +void filter::transform::transform_factory::deactivate(void* ptr) noexcept try { reinterpret_cast(ptr)->deactivate(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::transform::transform_factory::video_tick(void* ptr, float time) -{ +void filter::transform::transform_factory::video_tick(void* ptr, float time) noexcept try { reinterpret_cast(ptr)->video_tick(time); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void filter::transform::transform_factory::video_render(void* ptr, gs_effect_t* effect) -{ +void filter::transform::transform_factory::video_render(void* ptr, gs_effect_t* effect) noexcept try { reinterpret_cast(ptr)->video_render(effect); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } filter::transform::transform_instance::~transform_instance() diff --git a/source/filters/filter-transform.hpp b/source/filters/filter-transform.hpp index 0fc70efe..8dcb8314 100644 --- a/source/filters/filter-transform.hpp +++ b/source/filters/filter-transform.hpp @@ -40,22 +40,22 @@ namespace filter { transform_factory(); ~transform_factory(); - static const char* get_name(void*); - static void get_defaults(obs_data_t*); - static obs_properties_t* get_properties(void*); - static bool modified_properties(obs_properties_t*, obs_property_t*, obs_data_t*); + static const char* get_name(void*) noexcept; + static void get_defaults(obs_data_t*) noexcept; + static obs_properties_t* get_properties(void*) noexcept; + static bool modified_properties(obs_properties_t*, obs_property_t*, obs_data_t*) noexcept; - static void* create(obs_data_t*, obs_source_t*); - static void destroy(void*); - static uint32_t get_width(void*); - static uint32_t get_height(void*); - static void update(void*, obs_data_t*); - static void activate(void*); - static void deactivate(void*); - static void show(void*); - static void hide(void*); - static void video_tick(void*, float); - static void video_render(void*, gs_effect_t*); + static void* create(obs_data_t*, obs_source_t*) noexcept; + static void destroy(void*) noexcept; + static uint32_t get_width(void*) noexcept; + static uint32_t get_height(void*) noexcept; + static void update(void*, obs_data_t*) noexcept; + static void activate(void*) noexcept; + static void deactivate(void*) noexcept; + static void show(void*) noexcept; + static void hide(void*) noexcept; + static void video_tick(void*, float) noexcept; + static void video_render(void*, gs_effect_t*) noexcept; }; class transform_instance { diff --git a/source/gfx/gfx-effect-source.cpp b/source/gfx/gfx-effect-source.cpp index 0d41e5e7..f978fdda 100644 --- a/source/gfx/gfx-effect-source.cpp +++ b/source/gfx/gfx-effect-source.cpp @@ -121,6 +121,8 @@ std::shared_ptr return std::make_shared(parent, effect, param); case gs::effect_parameter::type::Texture: return std::make_shared(parent, effect, param); + default: + return nullptr; } return nullptr; @@ -402,6 +404,8 @@ void gfx::effect_source::value_parameter::properties(obs_properties_t* props) is_int = false; limit = 4; break; + default: + break; } for (size_t idx = 0; idx < limit; idx++) { @@ -468,6 +472,8 @@ void gfx::effect_source::value_parameter::remove_properties(obs_properties_t* pr is_int = false; limit = 4; break; + default: + break; } for (size_t idx = 0; idx < limit; idx++) { @@ -513,6 +519,8 @@ void gfx::effect_source::value_parameter::update(obs_data_t* data) is_int = false; limit = 4; break; + default: + break; } for (size_t idx = 0; idx < limit; idx++) { @@ -555,6 +563,8 @@ void gfx::effect_source::value_parameter::assign() case gs::effect_parameter::type::Float4: _param->set_float4(_value.f[0], _value.f[1], _value.f[2], _value.f[3]); break; + default: + break; } } @@ -699,13 +709,13 @@ void gfx::effect_source::matrix_parameter::update(obs_data_t* data) for (size_t x = 0; x < 4; x++) { vec4& v_ref = _value.x; if (x == 0) { - vec4& v_ref = _value.x; + v_ref = _value.x; } else if (x == 1) { - vec4& v_ref = _value.y; + v_ref = _value.y; } else if (x == 2) { - vec4& v_ref = _value.z; + v_ref = _value.z; } else { - vec4& v_ref = _value.t; + v_ref = _value.t; } for (size_t y = 0; y < 4; y++) { @@ -799,6 +809,13 @@ void gfx::effect_source::texture_parameter::defaults(obs_properties_t* props, ob obs_data_set_default_string(data, _cache.name[2].c_str(), _source_name.c_str()); } +bool modifiedcb(void* priv, obs_properties_t* props, obs_property_t* property, obs_data_t* settings) noexcept try { + return reinterpret_cast(priv)->modified2(props, property, settings); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return false; +} + void gfx::effect_source::texture_parameter::properties(obs_properties_t* props) { auto grp = props; @@ -812,12 +829,7 @@ void gfx::effect_source::texture_parameter::properties(obs_properties_t* props) { auto p = obs_properties_add_list(grp, _cache.name[0].c_str(), _cache.visible_name[0].c_str(), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_set_modified_callback2( - p, - [](void* priv, obs_properties_t* props, obs_property_t* property, obs_data_t* settings) { - return reinterpret_cast(priv)->modified2(props, property, settings); - }, - this); + obs_property_set_modified_callback2(p, modifiedcb, this); obs_property_set_long_description(p, D_TRANSLATE(D_DESC(ST_TEXTURE_TYPE))); obs_property_list_add_int(p, D_TRANSLATE(ST_TEXTURE_FILE), static_cast(texture_mode::FILE)); obs_property_list_add_int(p, D_TRANSLATE(ST_TEXTURE_SOURCE), static_cast(texture_mode::SOURCE)); @@ -1017,16 +1029,18 @@ gfx::effect_source::effect_source::effect_source(obs_source_t* self) gfx::effect_source::effect_source::~effect_source() {} +bool modifiedcb2(void* priv, obs_properties_t* props, obs_property_t* property, obs_data_t* settings) noexcept try { + return reinterpret_cast(priv)->modified2(props, property, settings); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return false; +} + void gfx::effect_source::effect_source::properties(obs_properties_t* props) { auto p = obs_properties_add_path(props, ST_FILE, D_TRANSLATE(ST_FILE), OBS_PATH_FILE, "Effects (*.effect);;*.*", nullptr); - obs_property_set_modified_callback2( - p, - [](void* priv, obs_properties_t* props, obs_property_t* property, obs_data_t* settings) { - return reinterpret_cast(priv)->modified2(props, property, settings); - }, - this); + obs_property_set_modified_callback2(p, modifiedcb2, this); obs_properties_add_text(props, ST_TECHNIQUE, D_TRANSLATE(ST_TECHNIQUE), OBS_TEXT_DEFAULT); for (auto& kv : _params) { diff --git a/source/gfx/gfx-effect-source.hpp b/source/gfx/gfx-effect-source.hpp index 5471cc25..a8be48f7 100644 --- a/source/gfx/gfx-effect-source.hpp +++ b/source/gfx/gfx-effect-source.hpp @@ -300,8 +300,6 @@ namespace gfx { valid_property_cb_t _cb_valid; param_override_cb_t _cb_override; - bool modified2(obs_properties_t* props, obs_property_t* property, obs_data_t* settings); - void load_file(std::string file); public: @@ -324,6 +322,8 @@ namespace gfx { void set_valid_property_cb(valid_property_cb_t cb); void set_override_cb(param_override_cb_t cb); + + bool modified2(obs_properties_t* props, obs_property_t* property, obs_data_t* settings); }; } // namespace effect_source } // namespace gfx diff --git a/source/obs/gs/gs-effect.cpp b/source/obs/gs/gs-effect.cpp index 6b11fdf4..4f0ef1cc 100644 --- a/source/obs/gs/gs-effect.cpp +++ b/source/obs/gs/gs-effect.cpp @@ -322,7 +322,7 @@ void gs::effect_parameter::get_float2(float_t& x, float_t& y) y = *reinterpret_cast(ptr + sizeof(float_t)); bfree(ptr); } else { - x, y = 0; + x = y = 0; } } @@ -336,7 +336,7 @@ void gs::effect_parameter::get_default_float2(float_t& x, float_t& y) y = *reinterpret_cast(ptr + sizeof(float_t)); bfree(ptr); } else { - x, y = 0; + x = y = 0; } } @@ -376,7 +376,7 @@ void gs::effect_parameter::get_float3(float_t& x, float_t& y, float_t& z) z = *reinterpret_cast(ptr + sizeof(float_t) * 2); bfree(ptr); } else { - x, y, z = 0; + x = y = z = 0; } } @@ -391,7 +391,7 @@ void gs::effect_parameter::get_default_float3(float_t& x, float_t& y, float_t& z z = *reinterpret_cast(ptr + sizeof(float_t) * 2); bfree(ptr); } else { - x, y, z = 0; + x = y = z = 0; } } @@ -432,7 +432,7 @@ void gs::effect_parameter::get_float4(float_t& x, float_t& y, float_t& z, float_ w = *reinterpret_cast(ptr + sizeof(float_t) * 3); bfree(ptr); } else { - x, y, z, w = 0; + x = y = z = w = 0; } } @@ -448,7 +448,7 @@ void gs::effect_parameter::get_default_float4(float_t& x, float_t& y, float_t& z w = *reinterpret_cast(ptr + sizeof(float_t) * 3); bfree(ptr); } else { - x, y, z, w = 0; + x = y = z = w = 0; } } @@ -511,7 +511,7 @@ void gs::effect_parameter::get_int2(int32_t& x, int32_t& y) y = *reinterpret_cast(ptr + sizeof(int32_t)); bfree(ptr); } else { - x, y = 0; + x = y = 0; } } @@ -525,7 +525,7 @@ void gs::effect_parameter::get_default_int2(int32_t& x, int32_t& y) y = *reinterpret_cast(ptr + sizeof(int32_t)); bfree(ptr); } else { - x, y = 0; + x = y = 0; } } @@ -548,7 +548,7 @@ void gs::effect_parameter::get_int3(int32_t& x, int32_t& y, int32_t& z) z = *reinterpret_cast(ptr + sizeof(int32_t) * 2); bfree(ptr); } else { - x, y, z = 0; + x = y = z = 0; } } @@ -563,7 +563,7 @@ void gs::effect_parameter::get_default_int3(int32_t& x, int32_t& y, int32_t& z) z = *reinterpret_cast(ptr + sizeof(int32_t) * 2); bfree(ptr); } else { - x, y, z = 0; + x = y = z = 0; } } @@ -587,7 +587,7 @@ void gs::effect_parameter::get_int4(int32_t& x, int32_t& y, int32_t& z, int32_t& w = *reinterpret_cast(ptr + sizeof(int32_t) * 3); bfree(ptr); } else { - x, y, z, w = 0; + x = y = z = w = 0; } } @@ -603,7 +603,7 @@ void gs::effect_parameter::get_default_int4(int32_t& x, int32_t& y, int32_t& z, w = *reinterpret_cast(ptr + sizeof(int32_t) * 3); bfree(ptr); } else { - x, y, z, w = 0; + x = y = z = w = 0; } } diff --git a/source/obs/gs/gs-vertexbuffer.cpp b/source/obs/gs/gs-vertexbuffer.cpp index 87640cd8..28112528 100644 --- a/source/obs/gs/gs-vertexbuffer.cpp +++ b/source/obs/gs/gs-vertexbuffer.cpp @@ -273,7 +273,7 @@ bool gs::vertex_buffer::empty() const gs::vertex gs::vertex_buffer::at(uint32_t idx) { - if ((idx < 0) || (idx >= _size)) { + if (idx >= _size) { throw std::out_of_range("idx out of range"); } @@ -321,7 +321,7 @@ uint32_t* gs::vertex_buffer::get_colors() vec4* gs::vertex_buffer::get_uv_layer(size_t idx) { - if ((idx < 0) || (idx >= _layers)) { + if (idx >= _layers) { throw std::out_of_range("idx out of range"); } return _uvs[idx]; diff --git a/source/obs/obs-source-tracker.cpp b/source/obs/obs-source-tracker.cpp index 1cdd44bf..d0df6ba1 100644 --- a/source/obs/obs-source-tracker.cpp +++ b/source/obs/obs-source-tracker.cpp @@ -19,11 +19,11 @@ #include "obs-source-tracker.hpp" #include +#include "plugin.hpp" static std::shared_ptr source_tracker_instance; -void obs::source_tracker::source_create_handler(void* ptr, calldata_t* data) -{ +void obs::source_tracker::source_create_handler(void* ptr, calldata_t* data) noexcept try { obs::source_tracker* self = reinterpret_cast(ptr); obs_source_t* target = nullptr; @@ -45,10 +45,11 @@ void obs::source_tracker::source_create_handler(void* ptr, calldata_t* data) } self->_source_map.insert({std::string(name), weak}); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void obs::source_tracker::source_destroy_handler(void* ptr, calldata_t* data) -{ +void obs::source_tracker::source_destroy_handler(void* ptr, calldata_t* data) noexcept try { obs::source_tracker* self = reinterpret_cast(ptr); obs_source_t* target = nullptr; @@ -71,10 +72,11 @@ void obs::source_tracker::source_destroy_handler(void* ptr, calldata_t* data) obs_weak_source_release(found->second); self->_source_map.erase(found); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -void obs::source_tracker::source_rename_handler(void* ptr, calldata_t* data) -{ +void obs::source_tracker::source_rename_handler(void* ptr, calldata_t* data) noexcept try { obs::source_tracker* self = reinterpret_cast(ptr); obs_source_t* target = nullptr; @@ -103,6 +105,8 @@ void obs::source_tracker::source_rename_handler(void* ptr, calldata_t* data) // Insert at new key, remove old pair. self->_source_map.insert({new_name, found->second}); self->_source_map.erase(found); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } void obs::source_tracker::initialize() diff --git a/source/obs/obs-source-tracker.hpp b/source/obs/obs-source-tracker.hpp index 67881bbf..38bf6124 100644 --- a/source/obs/obs-source-tracker.hpp +++ b/source/obs/obs-source-tracker.hpp @@ -36,9 +36,9 @@ namespace obs { class source_tracker { std::map _source_map; - static void source_create_handler(void* ptr, calldata_t* data); - static void source_destroy_handler(void* ptr, calldata_t* data); - static void source_rename_handler(void* ptr, calldata_t* data); + static void source_create_handler(void* ptr, calldata_t* data) noexcept; + static void source_destroy_handler(void* ptr, calldata_t* data) noexcept; + static void source_rename_handler(void* ptr, calldata_t* data) noexcept; public: // Singleton static void initialize(); diff --git a/source/obs/obs-tools.cpp b/source/obs/obs-tools.cpp index 5909c0c0..a705b3a8 100644 --- a/source/obs/obs-tools.cpp +++ b/source/obs/obs-tools.cpp @@ -20,6 +20,7 @@ #include "obs-tools.hpp" #include #include +#include "plugin.hpp" struct scs_searchdata { obs_source_t* source; @@ -29,17 +30,20 @@ struct scs_searchdata { static bool scs_contains(scs_searchdata& sd, obs_source_t* source); -static void scs_enum_active_cb(obs_source_t*, obs_source_t* child, void* searchdata) -{ +static void scs_enum_active_cb(obs_source_t*, obs_source_t* child, void* searchdata) noexcept try { scs_searchdata& sd = reinterpret_cast(*reinterpret_cast(searchdata)); scs_contains(sd, child); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } -static bool scs_enum_items_cb(obs_scene_t*, obs_sceneitem_t* item, void* searchdata) -{ +static bool scs_enum_items_cb(obs_scene_t*, obs_sceneitem_t* item, void* searchdata) noexcept try { scs_searchdata& sd = reinterpret_cast(*reinterpret_cast(searchdata)); obs_source_t* source = obs_sceneitem_get_source(item); return scs_contains(sd, source); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return false; } static bool scs_contains(scs_searchdata& sd, obs_source_t* source) diff --git a/source/plugin.cpp b/source/plugin.cpp index cda60636..fb73b6b0 100644 --- a/source/plugin.cpp +++ b/source/plugin.cpp @@ -30,48 +30,53 @@ #include "sources/source-mirror.hpp" #include "sources/source-shader.hpp" -std::list> initializer_functions; -std::list> finalizer_functions; - -MODULE_EXPORT bool obs_module_load(void) -{ - // Previously through P_INITIALIZER. - initializer_functions.push_back([] { filter::blur::blur_factory::initialize(); }); - finalizer_functions.push_back([] { filter::blur::blur_factory::finalize(); }); - initializer_functions.push_back([] { filter::color_grade::color_grade_factory::initialize(); }); - finalizer_functions.push_back([] { filter::color_grade::color_grade_factory::finalize(); }); - initializer_functions.push_back([] { filter::displacement::displacement_factory::initialize(); }); - finalizer_functions.push_back([] { filter::displacement::displacement_factory::finalize(); }); - initializer_functions.push_back([] { filter::dynamic_mask::dynamic_mask_factory::initialize(); }); - finalizer_functions.push_back([] { filter::dynamic_mask::dynamic_mask_factory::finalize(); }); - initializer_functions.push_back([] { filter::sdf_effects::sdf_effects_factory::initialize(); }); - finalizer_functions.push_back([] { filter::sdf_effects::sdf_effects_factory::finalize(); }); - initializer_functions.push_back([] { filter::shader::shader_factory::initialize(); }); - finalizer_functions.push_back([] { filter::shader::shader_factory::finalize(); }); - initializer_functions.push_back([] { filter::transform::transform_factory::initialize(); }); - finalizer_functions.push_back([] { filter::transform::transform_factory::finalize(); }); - initializer_functions.push_back([] { source::mirror::mirror_factory::initialize(); }); - finalizer_functions.push_back([] { source::mirror::mirror_factory::finalize(); }); - initializer_functions.push_back([] { source::shader::shader_factory::initialize(); }); - finalizer_functions.push_back([] { source::shader::shader_factory::finalize(); }); - +MODULE_EXPORT bool obs_module_load(void) try { P_LOG_INFO("Loading Version %u.%u.%u (Build %u)", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH, PROJECT_VERSION_TWEAK); + + // Initialize Source Tracker obs::source_tracker::initialize(); - for (auto func : initializer_functions) { - func(); - } + + // Initialize Filters + filter::blur::blur_factory::initialize(); + filter::color_grade::color_grade_factory::initialize(); + filter::displacement::displacement_factory::initialize(); + filter::dynamic_mask::dynamic_mask_factory::initialize(); + filter::sdf_effects::sdf_effects_factory::initialize(); + filter::shader::shader_factory::initialize(); + filter::transform::transform_factory::initialize(); + + // Initialize Sources + source::mirror::mirror_factory::initialize(); + source::shader::shader_factory::initialize(); + return true; +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); + return false; } -MODULE_EXPORT void obs_module_unload(void) -{ +MODULE_EXPORT void obs_module_unload(void) try { P_LOG_INFO("Unloading Version %u.%u.%u (Build %u)", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH, PROJECT_VERSION_TWEAK); - for (auto func : finalizer_functions) { - func(); - } + + // Clean up Sources + source::mirror::mirror_factory::finalize(); + source::shader::shader_factory::finalize(); + + // Clean up Filters + filter::blur::blur_factory::finalize(); + filter::color_grade::color_grade_factory::finalize(); + filter::displacement::displacement_factory::finalize(); + filter::dynamic_mask::dynamic_mask_factory::finalize(); + filter::sdf_effects::sdf_effects_factory::finalize(); + filter::shader::shader_factory::finalize(); + filter::transform::transform_factory::finalize(); + + // Clean up Source Tracker obs::source_tracker::finalize(); +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } #ifdef _WIN32 diff --git a/source/plugin.hpp b/source/plugin.hpp index bb96ff46..3cea3d6a 100644 --- a/source/plugin.hpp +++ b/source/plugin.hpp @@ -18,9 +18,8 @@ */ #pragma once -#include -#include -#include +#include "strings.hpp" +#include "version.hpp" // OBS #ifdef _MSC_VER @@ -33,16 +32,17 @@ #pragma warning(pop) #endif -// Plugin -#define PLUGIN_NAME "Stream Effects" -#include "version.hpp" - +// Logging #define P_LOG(level, ...) blog(level, "[" PLUGIN_NAME "] " __VA_ARGS__) #define P_LOG_ERROR(...) P_LOG(LOG_ERROR, __VA_ARGS__) #define P_LOG_WARNING(...) P_LOG(LOG_WARNING, __VA_ARGS__) #define P_LOG_INFO(...) P_LOG(LOG_INFO, __VA_ARGS__) #define P_LOG_DEBUG(...) P_LOG(LOG_DEBUG, __VA_ARGS__) -// Initializer & Finalizer -extern std::list> initializer_functions; -extern std::list> finalizer_functions; +#ifndef __FUNCTION_NAME__ +#ifdef WIN32 //WINDOWS +#define __FUNCTION_NAME__ __FUNCTION__ +#else //*NIX +#define __FUNCTION_NAME__ __func__ +#endif +#endif diff --git a/source/sources/source-mirror.cpp b/source/sources/source-mirror.cpp index ccdc2b37..55d74755 100644 --- a/source/sources/source-mirror.cpp +++ b/source/sources/source-mirror.cpp @@ -654,7 +654,7 @@ void source::mirror::mirror_instance::video_render(gs_effect_t* effect) } } -void source::mirror::mirror_instance::audio_output_cb() +void source::mirror::mirror_instance::audio_output_cb() noexcept try { std::unique_lock ulock(this->_audio_lock_outputter); @@ -686,6 +686,8 @@ void source::mirror::mirror_instance::audio_output_cb() } } } +} catch (...) { + P_LOG_ERROR("Unexpected exception in function '%s'.", __FUNCTION_NAME__); } void source::mirror::mirror_instance::enum_active_sources(obs_source_enum_proc_t enum_callback, void* param) diff --git a/source/sources/source-mirror.hpp b/source/sources/source-mirror.hpp index f3c73133..e1834754 100644 --- a/source/sources/source-mirror.hpp +++ b/source/sources/source-mirror.hpp @@ -133,7 +133,7 @@ namespace source { void deactivate(); void video_tick(float); void video_render(gs_effect_t*); - void audio_output_cb(); + void audio_output_cb() noexcept; void enum_active_sources(obs_source_enum_proc_t, void*); void load(obs_data_t*); void save(obs_data_t*); diff --git a/source/strings.hpp b/source/strings.hpp index 1f31bff1..2a6ec2a3 100644 --- a/source/strings.hpp +++ b/source/strings.hpp @@ -20,6 +20,8 @@ #pragma once #include "plugin.hpp" +#define PLUGIN_NAME "Stream Effects" + #define D_TRANSLATE(x) obs_module_text(x) #define D_DESC(x) x ".Description" diff --git a/source/utility.cpp b/source/utility.cpp index ac6f845f..117d015e 100644 --- a/source/utility.cpp +++ b/source/utility.cpp @@ -21,6 +21,7 @@ #include #include #include "plugin.hpp" +#include // OBS #ifdef _MSC_VER @@ -49,7 +50,7 @@ const char* obs_module_recursive_text(const char* to_translate, size_t depth) std::stringstream out; { - size_t seq_start, seq_end = 0; + size_t seq_start = 0, seq_end = 0; bool seq_got = false; for (size_t pos = 0; pos <= orig.length(); pos++) {