#include "../tdkpin_object_lifecycle.h" #include static unsigned g_sequence; static Win16FarPtr g_object; static Win16FarPtr g_parent; static Win16FarPtr g_thunk; static Win16FarPtr g_teardown; static bool g_enter_result; static unsigned g_construct_sequence; void win16_call_object_method( Win16FarPtr procedure, Win16FarPtr object) { assert(++g_sequence == 1); assert(procedure == g_teardown && object == g_object); } void object_windows_for_each_child( Win16FarPtr container, Win16FarPtr action) { assert(++g_sequence == 2); assert(container == g_object); assert(action == win16_make_far_pointer(0x6000, 0x03e9)); } void object_windows_remove_child( Win16FarPtr container, Win16FarPtr child) { assert(++g_sequence == 3); assert(container == g_parent && child == g_object); } void object_windows_release_bound_thunk(Win16FarPtr thunk) { assert(++g_sequence == (g_parent == 0 ? 3u : 4u)); assert(thunk == g_thunk); } void borland_default_object_destructor( Win16FarPtr object, uint16_t vmt) { assert(++g_sequence == (g_parent == 0 ? 4u : 5u)); assert(object == g_object && vmt == 0); } void borland_finish_object_destructor( BorlandObjectCallFrame *frame, uint16_t vmt_field_offset) { assert(++g_sequence == (g_parent == 0 ? 5u : 6u)); assert(frame->object == g_object && frame->vmt_argument == 0x0200); assert(vmt_field_offset == 0); } bool borland_enter_object_constructor( BorlandObjectCallFrame *frame, uint16_t vmt_field_offset) { assert(++g_construct_sequence == 1); assert(frame->object == g_object && frame->vmt_argument == 0x0200); assert(vmt_field_offset == 0); return g_enter_result; } Win16FarPtr borland_default_object_constructor( Win16FarPtr object, uint16_t vmt) { assert(++g_construct_sequence == 2); assert(object == g_object && vmt == 0); return object; } void object_windows_append_child( Win16FarPtr container, Win16FarPtr child) { assert(++g_construct_sequence == 3); assert(container == g_parent && child == g_object); } Win16FarPtr object_windows_allocate_bound_thunk(Win16FarPtr object) { unsigned expected = g_parent == 0 ? 3u : 4u; assert(++g_construct_sequence == expected); assert(object == g_object); return g_thunk; } void object_windows_set_flag_4(Win16FarPtr object) { unsigned expected = g_parent == 0 ? 4u : 5u; assert(++g_construct_sequence == expected); assert(object == g_object); Win16FarPtr address = win16_far_add_offset(object, 0x16); win16_write_u8(address, (uint8_t)(win16_read_u8(address) | 4)); } static void write_far(Win16FarPtr object, uint16_t offset, Win16FarPtr value) { win16_write_u16(object, offset, win16_far_offset(value)); win16_write_u16( object, (uint16_t)(offset + 2), win16_far_selector(value)); } static void run_case(bool with_parent) { g_sequence = 0; g_parent = with_parent ? win16_make_far_pointer(0x7100, 2) : 0; write_far(g_object, 6, g_parent); object_windows_object_destruct(g_object, 0x0200); assert(g_sequence == (with_parent ? 6u : 5u)); } static void run_construct_case(bool with_parent) { g_construct_sequence = 0; g_enter_result = true; g_parent = with_parent ? win16_make_far_pointer(0x7100, 2) : 0; assert(object_windows_object_construct(g_object, 0x0200, g_parent) == g_object); assert(g_construct_sequence == (with_parent ? 5u : 4u)); assert(win16_read_u16(win16_far_add_offset(g_object, 2)) == 0); assert(win16_read_u16(win16_far_add_offset(g_object, 4)) == 0); assert(win16_read_far_pointer(g_object, 6) == g_parent); assert(win16_read_far_pointer(g_object, 0x0a) == 0); assert(win16_read_far_pointer(g_object, 0x0e) == 0); assert(win16_read_far_pointer(g_object, 0x12) == g_thunk); assert(win16_read_u8(win16_far_add_offset(g_object, 0x16)) == 4); if (!with_parent) { assert(win16_read_far_pointer(g_object, 0x19) == 0); } } int main(void) { static uint8_t dgroup[0x1000]; static uint8_t code[0x1000]; static uint8_t object_bytes[64]; static uint8_t parent_bytes[64]; win16_reset_segment_bindings(); win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true); win16_set_dgroup_selector(0x5000); win16_bind_ne_segment(4, 0x6000, code, sizeof(code), false); win16_bind_segment(0x7000, object_bytes, sizeof(object_bytes), true); win16_bind_segment(0x7100, parent_bytes, sizeof(parent_bytes), true); g_object = win16_make_far_pointer(0x7000, 2); g_thunk = win16_make_far_pointer(0x6200, 0x1234); g_teardown = win16_make_far_pointer(0x6100, 0x4321); win16_write_u16(g_object, 0, 0x0100); write_far(win16_dgroup_pointer(0x0124), 0, g_teardown); write_far(g_object, 0x12, g_thunk); run_case(true); run_case(false); run_construct_case(true); run_construct_case(false); g_construct_sequence = 0; g_enter_result = false; assert(object_windows_object_construct(g_object, 0x0200, 0) == g_object); assert(g_construct_sequence == 1); return 0; }