#include "tdkpin_numeric.h" static uint8_t digit_character(uint8_t digit) { return (uint8_t)(digit + (digit < 10 ? '0' : 'A' - 10)); } BorlandFormattedSlice borland_format_u32_backward( Win16FarPtr end, uint32_t value, uint16_t base) { Win16FarPtr cursor = end; do { uint8_t digit = (uint8_t)(value % base); value /= base; cursor = win16_far_add_offset(cursor, 0xffff); win16_write_u8(cursor, digit_character(digit)); } while (value != 0); return (BorlandFormattedSlice){ cursor, (uint16_t)(win16_far_offset(end) - win16_far_offset(cursor)), }; } BorlandFormattedSlice borland_format_i32_decimal_backward( Win16FarPtr end, int32_t value) { bool negative = value < 0; uint32_t magnitude = negative ? (uint32_t)(0u - (uint32_t)value) : (uint32_t)value; BorlandFormattedSlice result = borland_format_u32_backward(end, magnitude, 10); if (negative) { result.start = win16_far_add_offset(result.start, 0xffff); win16_write_u8(result.start, '-'); result.length++; } return result; } /* * 1020:1629 — format an int32_t into a Pascal ShortString with a signed field * width, left space padding, and a caller-supplied maximum length. If the * decimal representation is truncated, the target copies its leading bytes. */ void borland_format_i32_short_string( int16_t maximum_length, Win16FarPtr destination, int16_t field_width, int32_t value) { uint8_t workspace[32]; Win16FarPtr end = win16_stack_pointer(workspace + sizeof(workspace)); BorlandFormattedSlice formatted = borland_format_i32_decimal_backward(end, value); int16_t copy_length = (int16_t)formatted.length; if (field_width > maximum_length) { field_width = maximum_length; } if (copy_length > maximum_length) { copy_length = maximum_length; } if (field_width < copy_length) { field_width = copy_length; } win16_write_u8(destination, (uint8_t)field_width); Win16FarPtr output = win16_far_add_offset(destination, 1); uint16_t padding = (uint16_t)(field_width - copy_length); for (uint16_t index = 0; index < padding; index++) { win16_write_u8(win16_far_add_offset(output, index), ' '); } output = win16_far_add_offset(output, padding); for (uint16_t index = 0; index < (uint16_t)copy_length; index++) { win16_write_u8( win16_far_add_offset(output, index), win16_read_u8(win16_far_add_offset(formatted.start, index))); } } static BorlandParseI32Result parse_finish( uint32_t magnitude, bool negative, Win16FarPtr cursor, uint16_t remaining, bool validate_signed_range) { uint32_t result = negative ? 0u - magnitude : magnitude; if (validate_signed_range && magnitude != 0 && negative != ((result & 0x80000000u) != 0)) { return (BorlandParseI32Result){0, cursor, remaining, true}; } return (BorlandParseI32Result){(int32_t)result, cursor, remaining, false}; } BorlandParseI32Result borland_parse_i32_span( Win16FarPtr text, uint16_t length) { Win16FarPtr cursor = text; uint16_t remaining = length; bool negative = false; if (remaining == 0) { return (BorlandParseI32Result){0, cursor, 0, true}; } uint8_t current = win16_read_u8(cursor); if (current == '+' || current == '-') { negative = current == '-'; cursor = win16_far_add_offset(cursor, 1); remaining--; if (remaining == 0) { return (BorlandParseI32Result){0, cursor, 0, true}; } current = win16_read_u8(cursor); } uint32_t magnitude = 0; if (current == '$') { cursor = win16_far_add_offset(cursor, 1); remaining--; if (remaining == 0) { return (BorlandParseI32Result){0, cursor, 0, true}; } while (remaining != 0) { uint8_t value = win16_read_u8(cursor); if (value > 0x60) { value = (uint8_t)(value - 0x20); } uint8_t digit; if (value >= '0' && value <= '9') { digit = (uint8_t)(value - '0'); } else if (value >= 'A' && value <= 'F') { digit = (uint8_t)(value - 'A' + 10); } else { return parse_finish( magnitude, negative, cursor, remaining, true); } if ((magnitude & 0xf0000000u) != 0) { return (BorlandParseI32Result){0, cursor, remaining, true}; } magnitude = (magnitude << 4) | digit; cursor = win16_far_add_offset(cursor, 1); remaining--; } return parse_finish(magnitude, negative, cursor, 0, false); } while (remaining != 0) { uint8_t value = win16_read_u8(cursor); if (value < '0' || value > '9') { break; } if ((magnitude & 0xf0000000u) != 0) { return (BorlandParseI32Result){0, cursor, remaining, true}; } magnitude = magnitude * 10u + (uint8_t)(value - '0'); cursor = win16_far_add_offset(cursor, 1); remaining--; } return parse_finish(magnitude, negative, cursor, remaining, true); } BorlandValI32Result borland_val_i32_short_string(Win16FarPtr string) { uint16_t remaining = win16_read_u8(string); Win16FarPtr cursor = win16_far_add_offset(string, 1); while (remaining != 0 && win16_read_u8(cursor) == ' ') { cursor = win16_far_add_offset(cursor, 1); remaining--; } BorlandParseI32Result parsed = borland_parse_i32_span(cursor, remaining); if (parsed.failed || parsed.remaining != 0) { return (BorlandValI32Result){ 0, (uint16_t)( win16_far_offset(parsed.cursor) - win16_far_offset(string)), }; } return (BorlandValI32Result){parsed.value, 0}; }