#include "../tdkpin_borland_objects.h" #include #include #include static BorlandAllocationAttempt g_allocation; static Win16FarPtr g_freed_object; static uint16_t g_freed_size; static bool g_free_failed; static jmp_buf g_runtime_error_jump; static uint16_t g_runtime_error_code; static Win16FarPtr g_called_destructor; static Win16FarPtr g_destructor_object; static uint16_t g_dispose_mode; BorlandAllocationAttempt borland_try_get_mem(uint16_t bytes) { assert(bytes == 16); return g_allocation; } bool borland_try_free_mem(Win16FarPtr object, uint16_t bytes) { g_freed_object = object; g_freed_size = bytes; return g_free_failed; } _Noreturn void borland_runtime_error(uint16_t code) { g_runtime_error_code = code; longjmp(g_runtime_error_jump, 1); } void win16_call_object_destructor( Win16FarPtr procedure, Win16FarPtr object, uint16_t dispose_mode) { g_called_destructor = procedure; g_destructor_object = object; g_dispose_mode = dispose_mode; } int main(void) { static uint8_t dgroup[0x1000]; static uint8_t existing_bytes[64]; static uint8_t allocated_bytes[64]; win16_reset_segment_bindings(); win16_bind_segment(0x5000, dgroup, sizeof(dgroup), true); win16_set_dgroup_selector(0x5000); win16_bind_segment( 0x7000, existing_bytes, sizeof(existing_bytes), true); win16_bind_segment( 0x7100, allocated_bytes, sizeof(allocated_bytes), true); win16_write_u16(win16_make_far_pointer(0x5000, 0x0200), 0, 16); BorlandObjectCallFrame existing = { win16_make_far_pointer(0x7000, 4), 0x0200}; borland_enter_object_constructor(&existing, 2); assert(existing.object == win16_make_far_pointer(0x7000, 4)); assert(existing.vmt_argument == 0); assert(win16_read_u16(win16_make_far_pointer(0x7000, 6)) == 0x0200); g_allocation = (BorlandAllocationAttempt){ win16_make_far_pointer(0x7100, 8), false}; BorlandObjectCallFrame allocated = {0, 0x0200}; borland_enter_object_constructor(&allocated, 2); assert(allocated.object == win16_make_far_pointer(0x7100, 8)); assert(allocated.vmt_argument == 0x0200); assert(win16_read_u16(win16_make_far_pointer(0x7100, 10)) == 0x0200); BorlandObjectCallFrame inactive = { win16_make_far_pointer(0x7000, 20), 0}; borland_enter_object_constructor(&inactive, 0); assert(inactive.object == win16_make_far_pointer(0x7000, 20)); g_allocation = (BorlandAllocationAttempt){0, false}; BorlandObjectCallFrame suppressed = {0, 0x0200}; borland_enter_object_constructor(&suppressed, 0); assert(suppressed.object == 0 && suppressed.vmt_argument == 0x0200); g_allocation = (BorlandAllocationAttempt){0, true}; if (setjmp(g_runtime_error_jump) == 0) { borland_enter_object_constructor(&suppressed, 0); assert(false); } assert(g_runtime_error_code == 203); win16_write_u16(win16_make_far_pointer(0x7000, 4), 0, 0x0200); BorlandObjectCallFrame destroyed = { win16_make_far_pointer(0x7000, 4), 1}; g_free_failed = false; borland_finish_object_destructor(&destroyed, 0); assert(destroyed.object == 0); assert(g_freed_object == win16_make_far_pointer(0x7000, 4)); assert(g_freed_size == 16); BorlandObjectCallFrame borrowed = { win16_make_far_pointer(0x7000, 4), 0}; g_freed_object = 0; borland_finish_object_destructor(&borrowed, 0); assert(borrowed.object == win16_make_far_pointer(0x7000, 4)); assert(g_freed_object == 0); g_free_failed = true; destroyed.object = win16_make_far_pointer(0x7000, 4); if (setjmp(g_runtime_error_jump) == 0) { borland_finish_object_destructor(&destroyed, 0); assert(false); } assert(g_runtime_error_code == 204); g_allocation = (BorlandAllocationAttempt){ win16_make_far_pointer(0x7100, 8), false}; assert(borland_default_object_constructor(0, 0x0200) == win16_make_far_pointer(0x7100, 8)); g_free_failed = false; g_freed_object = 0; borland_default_object_destructor( win16_make_far_pointer(0x7000, 4), 1); assert(g_freed_object == win16_make_far_pointer(0x7000, 4)); assert(g_freed_size == 16); Win16FarPtr destructor = win16_make_far_pointer(0x6000, 0x1234); win16_write_u16(win16_make_far_pointer(0x5000, 0x0208), 0, win16_far_offset(destructor)); win16_write_u16(win16_make_far_pointer(0x5000, 0x020a), 0, win16_far_selector(destructor)); borland_dispose_object(win16_make_far_pointer(0x7000, 4)); assert(g_called_destructor == destructor); assert(g_destructor_object == win16_make_far_pointer(0x7000, 4)); assert(g_dispose_mode == 1); if (setjmp(g_runtime_error_jump) == 0) { borland_abstract_method_error(); assert(false); } assert(g_runtime_error_code == 211); if (setjmp(g_runtime_error_jump) == 0) { object_windows_abstract_method(); assert(false); } assert(g_runtime_error_code == 211); return 0; }