Word Unperfect
public
Read
Owner: themaster
Branch: main
Commits: 0
Git CLI clone URL
git clone https://www.xt-emporium.com/git/word-unperfect.git
Fullscreen desktop URL
Code
Commits
History
Branches
Bug Reports
Discussions
Compare
Settings
word-unperfect
/
rev
/
wp_scanner_logic.c
File editor
#include "wp_scanner_logic.h" #include "wp_fixed_codes.h" #include "wp_control_codes.h" #include "wp_record_parser.h" #include "wp_variable_codes.h" #include "wp_nested_stream.h" #include <string.h> static bool wp_scanner_write_byte(uint8_t *out, size_t out_capacity, size_t *count, uint8_t value, WpScannerStats *stats) { if (count == NULL) { return false; } if (out == NULL || *count >= out_capacity) { if (stats != NULL) { stats->output_truncated = true; } return false; } out[(*count)++] = value; if (stats != NULL) { stats->bytes_written++; } return true; } static bool wp_scanner_write_record_bytes(uint8_t lead, const WpRecord *rec, uint8_t *out, size_t out_capacity, size_t *count, WpScannerStats *stats) { size_t i; if (!wp_scanner_write_byte(out, out_capacity, count, lead, stats)) { return false; } if (rec != NULL && rec->type == WP_CODE_VARIABLE_LENGTH) { uint16_t len = rec->declared_length; if (!wp_scanner_write_byte(out, out_capacity, count, rec->sub_code, stats) || !wp_scanner_write_byte(out, out_capacity, count, (uint8_t)(len & 0xFFU), stats) || !wp_scanner_write_byte(out, out_capacity, count, (uint8_t)(len >> 8), stats)) { return false; } } for (i = 0; rec != NULL && i < rec->data_length; ++i) { if (!wp_scanner_write_byte(out, out_capacity, count, rec->data[i], stats)) { return false; } } if (rec != NULL && rec->trailer_present) { if (rec->type == WP_CODE_VARIABLE_LENGTH) { uint16_t len = rec->declared_length; if (!wp_scanner_write_byte(out, out_capacity, count, (uint8_t)(len & 0xFFU), stats) || !wp_scanner_write_byte(out, out_capacity, count, (uint8_t)(len >> 8), stats) || !wp_scanner_write_byte(out, out_capacity, count, rec->sub_code, stats) || !wp_scanner_write_byte(out, out_capacity, count, rec->code, stats)) { return false; } } else if (!wp_scanner_write_byte(out, out_capacity, count, rec->code, stats)) { return false; } } return true; } void wp_scanner_default_options(WpScannerOptions *options) { if (options == NULL) { return; } options->copy_text_bytes = true; options->copy_format_packets = false; options->normalize_space_hyphen = true; options->emit_line_controls = true; } void wp_scanner_stats_clear(WpScannerStats *stats) { if (stats != NULL) { memset(stats, 0, sizeof(*stats)); } } static void wp_scanner_count_record_status(const WpRecord *rec, WpScannerStats *stats) { if (rec == NULL || stats == NULL) { return; } if (!rec->is_complete && !rec->trailer_present) { stats->incomplete_records++; } if (rec->trailer_present && !rec->trailer_matches) { stats->mismatched_trailers++; } } static bool wp_scanner_emit_single_code(const WpRecord *rec, uint8_t *out, size_t out_capacity, size_t *count, const WpScannerOptions *options, WpScannerStats *stats) { WpControlInfo control; if (rec == NULL || options == NULL) { return true; } wp_control_decode_byte(rec->code, &control); if (stats != NULL) { stats->control_codes_seen++; if ((control.effects & WP_CONTROL_EFFECT_DORMANT) != 0UL) { stats->dormant_controls_seen++; } if ((control.effects & WP_CONTROL_EFFECT_WHITESPACE_GATE) != 0UL) { stats->whitespace_gate_controls++; } if ((control.effects & WP_CONTROL_EFFECT_RENDER_DIRTY_GATE) != 0UL) { stats->render_dirty_gate_controls++; } if ((control.effects & WP_CONTROL_EFFECT_DIRTY_NEUTRAL) != 0UL) { stats->dirty_neutral_controls++; } if ((control.effects & WP_CONTROL_EFFECT_EXTENSION_SCAN_STOP) != 0UL) { stats->extension_scan_stop_controls++; } } if (options->normalize_space_hyphen && (control.effects & WP_CONTROL_EFFECT_NORMALIZED_SPACE) != 0UL) { if (stats != NULL) { stats->scanner_normalized_space++; } return wp_scanner_write_byte(out, out_capacity, count, (uint8_t)' ', stats); } if (options->normalize_space_hyphen && (control.effects & WP_CONTROL_EFFECT_NORMALIZED_HYPHEN) != 0UL) { if (stats != NULL) { stats->scanner_normalized_hyphen++; } return wp_scanner_write_byte(out, out_capacity, count, (uint8_t)'-', stats); } if (options->emit_line_controls && (control.effects & WP_CONTROL_EFFECT_DORMANT) == 0UL) { if ((control.effects & WP_CONTROL_EFFECT_LINE_BREAK) != 0UL) { if (stats != NULL) stats->line_controls_emitted++; return wp_scanner_write_byte(out, out_capacity, count, (uint8_t)'\n', stats); } if ((control.effects & WP_CONTROL_EFFECT_PAGE_BREAK) != 0UL) { if (stats != NULL) stats->line_controls_emitted++; return wp_scanner_write_byte(out, out_capacity, count, (uint8_t)'\f', stats); } if ((control.effects & WP_CONTROL_EFFECT_TAB_STOP) != 0UL && (rec->code == 0x84U || rec->code == 0x8DU)) { if (stats != NULL) stats->line_controls_emitted++; return wp_scanner_write_byte(out, out_capacity, count, (uint8_t)'\t', stats); } } if (options->copy_format_packets) { return wp_scanner_write_byte(out, out_capacity, count, rec->code, stats); } return true; } bool wp_scanner_run_stream(WpLayoutGlobals *wl, uint8_t *out, size_t out_capacity, size_t *out_len, const WpScannerOptions *options, WpScannerStats *stats) { WpScannerOptions local_options; WpScannerStats local_stats; WpLayoutGlobals cursor; size_t count = 0; bool ok = true; if (out_len != NULL) { *out_len = 0; } if (wl == NULL || out_len == NULL || (out_capacity > 0U && out == NULL)) { return false; } if (options == NULL) { wp_scanner_default_options(&local_options); options = &local_options; } wp_scanner_stats_clear(&local_stats); cursor = *wl; while (cursor.record_used_bytes > 0) { WpRecord rec; wp_parser_consume_record(&cursor, &rec); if (rec.length == 0U) { wp_record_free(&rec); break; } local_stats.records_seen++; local_stats.bytes_consumed += rec.length; wp_scanner_count_record_status(&rec, &local_stats); if (rec.type == WP_CODE_CHAR) { local_stats.text_bytes_seen++; if (options->copy_text_bytes) { if ((rec.code >= 0x20U && rec.code < 0x7FU) || rec.code == '\n' || rec.code == '\r' || rec.code == '\t' || rec.code == '\f') { if (!wp_scanner_write_byte(out, out_capacity, &count, rec.code, &local_stats)) { ok = false; } else { local_stats.text_bytes_copied++; } } } } else if (rec.type == WP_CODE_SINGLE_BYTE) { if (!wp_scanner_emit_single_code(&rec, out, out_capacity, &count, options, &local_stats)) { ok = false; } } else if (rec.type == WP_CODE_FIXED_LENGTH) { switch (rec.code) { case 0xC0U: local_stats.c0_extended_packets++; break; case 0xC1U: local_stats.c1_fixed_packets++; break; case 0xC2U: local_stats.c2_fixed_packets++; break; case 0xC3U: local_stats.c3_fixed_packets++; break; case 0xC4U: local_stats.c4_fixed_packets++; break; case 0xC5U: local_stats.c5_fixed_packets++; break; case 0xC6U: local_stats.c6_fixed_packets++; break; default: local_stats.other_fixed_packets++; break; } if (options->copy_format_packets) { local_stats.fixed_packets_copied++; if (!wp_scanner_write_record_bytes(rec.code, &rec, out, out_capacity, &count, &local_stats)) { ok = false; } } else { local_stats.fixed_packets_skipped++; } } else if (rec.type == WP_CODE_VARIABLE_LENGTH) { WpVariableCommandInfo command_info; bool have_command_info; local_stats.variable_packets_seen++; have_command_info = wp_variable_classify_record(&rec, &command_info); if (have_command_info && command_info.has_initial_format_table) { local_stats.d0_initial_format_tables++; local_stats.d0_format_table_words += command_info.initial_table.word_count; local_stats.d0_format_table_groups += command_info.initial_table.group_count; local_stats.d0_format_table_sentinels += command_info.initial_table.sentinel_word_count; local_stats.d0_format_table_nonmonotonic_steps += command_info.initial_table.nonmonotonic_step_count; if (command_info.initial_table.has_positive_step && local_stats.d0_format_table_first_step == 0U) { local_stats.d0_format_table_first_step = command_info.initial_table.first_positive_step; } if (command_info.initial_table.max_value > local_stats.d0_format_table_max_value) { local_stats.d0_format_table_max_value = command_info.initial_table.max_value; } } if (rec.code == 0xD4U) local_stats.d4_command_packets++; if (rec.code == 0xD5U) local_stats.d5_repeat_packets++; if (rec.code == 0xD6U) local_stats.d6_repeat_packets++; if (have_command_info && command_info.has_layout_state) { local_stats.d4_layout_state_packets++; local_stats.d4_layout_state_payload_bytes += rec.data_length; if (command_info.layout_state.carry_width > local_stats.d4_layout_state_max_carry_width) { local_stats.d4_layout_state_max_carry_width = command_info.layout_state.carry_width; } if (command_info.layout_state.wrap_value > local_stats.d4_layout_state_max_wrap_value) { local_stats.d4_layout_state_max_wrap_value = command_info.layout_state.wrap_value; } if (command_info.layout_state.has_variant_snapshot) { local_stats.d4_variant_snapshot_packets++; } if (command_info.layout_state.has_extension_blocks) { local_stats.d4_extension_block_packets++; local_stats.d4_extension_blocks += command_info.layout_state.extension_block_count; local_stats.d4_extension_bytes += command_info.layout_state.extension_block_bytes; } } if (have_command_info && command_info.has_pending_span) { local_stats.d4_pending_span_packets++; local_stats.d4_pending_span_payload_bytes += rec.data_length; if (command_info.pending_span.span_a > local_stats.d4_pending_span_max_span_a) { local_stats.d4_pending_span_max_span_a = command_info.pending_span.span_a; } if (command_info.pending_span.span_b > local_stats.d4_pending_span_max_span_b) { local_stats.d4_pending_span_max_span_b = command_info.pending_span.span_b; } if (command_info.pending_span.carry_width > local_stats.d4_pending_span_max_carry_width) { local_stats.d4_pending_span_max_carry_width = command_info.pending_span.carry_width; } } if (have_command_info && command_info.has_line_window) { local_stats.d4_line_window_packets++; local_stats.d4_line_window_payload_bytes += rec.data_length; if (command_info.line_window.has_extension_payload) { local_stats.d4_line_window_extension_packets++; local_stats.d4_line_window_extension_bytes += command_info.line_window.extension_payload_bytes; } if (command_info.line_window.old_line_extent > local_stats.d4_line_window_max_old_extent) { local_stats.d4_line_window_max_old_extent = command_info.line_window.old_line_extent; } if (command_info.line_window.new_line_extent > local_stats.d4_line_window_max_new_extent) { local_stats.d4_line_window_max_new_extent = command_info.line_window.new_line_extent; } } if (have_command_info && command_info.has_line_metric) { local_stats.d4_line_metric_packets++; local_stats.d4_line_metric_payload_bytes += rec.data_length; if (command_info.line_metric.position_word > local_stats.d4_line_metric_max_position) { local_stats.d4_line_metric_max_position = command_info.line_metric.position_word; } if (command_info.line_metric.extent_word_a > local_stats.d4_line_metric_max_extent) { local_stats.d4_line_metric_max_extent = command_info.line_metric.extent_word_a; } if (command_info.line_metric.extent_word_b > local_stats.d4_line_metric_max_extent) { local_stats.d4_line_metric_max_extent = command_info.line_metric.extent_word_b; } if (command_info.line_metric.has_extension_payload) { local_stats.d4_line_metric_extension_packets++; local_stats.d4_line_metric_extension_bytes += command_info.line_metric.extension.extension_payload_bytes; } } if (have_command_info && command_info.has_extension_fragment) { local_stats.d4_extension_fragment_packets++; local_stats.d4_extension_fragment_bytes += command_info.extension_fragment.extension_payload_bytes; if (command_info.extension_fragment.is_block_list) { local_stats.d4_extension_fragment_block_records++; local_stats.d4_extension_fragment_block_bytes += command_info.extension_fragment.block_bytes; } } if (have_command_info && command_info.has_line_build_checkpoint) { local_stats.d4_line_build_checkpoint_packets++; if (command_info.line_build_checkpoint.line_build_word_51f3 > local_stats.d4_line_build_checkpoint_max_word) { local_stats.d4_line_build_checkpoint_max_word = command_info.line_build_checkpoint.line_build_word_51f3; } } if (have_command_info && command_info.has_nested_stream_hint) { WpNestedStreamStats nested; local_stats.variable_nested_stream_hints++; if (wp_nested_stream_analyze_record(&rec, NULL, &nested)) { local_stats.nested_streams_analyzed += nested.streams_seen; local_stats.nested_stream_records += nested.records_seen; local_stats.nested_stream_bytes += nested.bytes_consumed; local_stats.nested_stream_fixed_codes += nested.fixed_length_codes; local_stats.nested_stream_variable_codes += nested.variable_length_codes; local_stats.nested_stream_char_records += nested.char_records; local_stats.nested_stream_d4_layout_states += nested.d4_layout_state_records; local_stats.nested_stream_post_compare_packets += nested.variable_repeat_dispatch_packets + nested.variable_extension_scan_packets + nested.variable_refcount_increment_packets + nested.variable_refcount_decrement_packets; local_stats.nested_stream_repeat_total += nested.variable_repeat_total; if (nested.max_depth_seen > local_stats.nested_stream_max_depth) { local_stats.nested_stream_max_depth = nested.max_depth_seen; } local_stats.nested_stream_recursion_limit_hit = local_stats.nested_stream_recursion_limit_hit || nested.recursion_limit_hit; local_stats.nested_stream_parse_gap = local_stats.nested_stream_parse_gap || nested.stopped_on_parse_gap || nested.allocation_failed; } } if (have_command_info && command_info.has_post_compare_plan) { if ((command_info.post_compare.flags & WP_VARIABLE_POST_REPEAT_DISPATCH) != 0U) { local_stats.variable_repeat_dispatch_packets++; if (command_info.post_compare.has_repeat_count) { local_stats.variable_repeat_total += command_info.post_compare.repeat_count; } } if (command_info.post_compare.extension_scan) { local_stats.variable_extension_scan_packets++; } if (command_info.post_compare.refcount_increment) { local_stats.variable_refcount_increment_packets++; } if (command_info.post_compare.refcount_decrement) { local_stats.variable_refcount_decrement_packets++; } } if (have_command_info && command_info.scanner_bypass) { local_stats.de31_scanner_bypass_packets++; } if (options->copy_format_packets) { local_stats.variable_packets_copied++; if (!wp_scanner_write_record_bytes(rec.code, &rec, out, out_capacity, &count, &local_stats)) { ok = false; } } else { local_stats.variable_packets_skipped++; } } wp_record_free(&rec); if (!ok) { break; } } *out_len = count; if (stats != NULL) { *stats = local_stats; } return ok && !local_stats.output_truncated; } bool wp_scanner_run_loaded_file(WpLoadedFile *file, uint8_t *out, size_t out_capacity, size_t *out_len, const WpScannerOptions *options, WpScannerStats *stats) { WpLayoutGlobals wl; if (file == NULL) { return false; } memset(&wl, 0, sizeof(wl)); if (!wp_file_bind_primary_stream(file, &wl, 4096U)) { return false; } return wp_scanner_run_stream(&wl, out, out_capacity, out_len, options, stats); } bool wp_scanner_run_file(const char *filename, uint8_t *out, size_t out_capacity, size_t *out_len, const WpScannerOptions *options, WpScannerStats *stats) { WpLoadedFile file; bool ok; if (filename == NULL) { return false; } if (!wp_file_load_body(filename, &file)) { return false; } ok = wp_scanner_run_loaded_file(&file, out, out_capacity, out_len, options, stats); wp_file_free(&file); return ok; } /* Ported Segment 3000 utility functions */ void __cdecl16near layout_clear_firmware_flag_b113_bit1(WpLayoutGlobals *wl) { if (wl != NULL) { wl->firmware_flag_b113 &= (uint8_t)~0x02; } } void __cdecl16near layout_flip_dos_char_sign_and_dos_service_hooks(WpLayoutGlobals *wl) { if (wl != NULL && wl->dos_char_01f5 >= 0) { wl->dos_char_01f5 = (char)-wl->dos_char_01f5; /* Note: Original assembly dispatches far calls here; host build uses modular logic. */ } } void __cdecl16near firmware_io_prepare_then_transfer_step(WpLayoutGlobals *wl, uint16_t *unaff_DI) { /* 32-bit negation and increment on memory pointed by DI */ uint16_t *p_lo = unaff_DI; uint16_t *p_hi = unaff_DI + 1; uint32_t val = (uint32_t)*p_lo | ((uint32_t)*p_hi << 16); val = (uint32_t)(-(int32_t)val) + 1; *p_lo = (uint16_t)(val & 0xFFFFU); *p_hi = (uint16_t)(val >> 16); } uint16_t __cdecl16near firmware_io_word_transfer_step(WpLayoutGlobals *wl, uint16_t *unaff_DI, int in_CX) { firmware_io_prepare_then_transfer_step(wl, unaff_DI); if (in_CX < 0) { /* Toggle high bit of byte at DI + 4 */ uint8_t *p_ctrl = (uint8_t *)unaff_DI + 4; *p_ctrl ^= 0x80; } return 0; }
Commit message
This repository is read-only for this account.
Repository snapshot
Current branch
main
Visibility
public
Your access
Read
Remote
None
File activity
View file history