From 5d844ae6cb34130083517a06a0097af9bd1e08a7 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Mon, 7 Sep 2026 11:17:34 +0200 Subject: [PATCH 1/2] fixed binary search in find_dict_prefix() --- src/backend_aa.c | 61 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/src/backend_aa.c b/src/backend_aa.c index 4c6cbb2d..2dafb547 100644 --- a/src/backend_aa.c +++ b/src/backend_aa.c @@ -75,6 +75,7 @@ static int n_decodetable; static struct dictentry *dictionary; static int ndict; +static int dict_maxlen; // length of the longest dictionary word static int first_sel_byte; static int first_gvar; @@ -295,6 +296,12 @@ void prepare_dictionary_aa(struct program *prg) { } } } + + dict_maxlen = 0; + for(i = 0; i < ndict; i++) { + n = strlen((char *) dictionary[i].chars); + if(n > dict_maxlen) dict_maxlen = n; + } } static void putbyte_crc(uint8_t b, FILE *f, uint32_t *crc) { @@ -3039,32 +3046,48 @@ static void build_decoder_tree(struct decodernode *node, int i, uint32_t prefix, } } +// Compare the first len characters of chars (which must be at least that +// long) to a complete, nul-terminated dictionary word. +static int cmp_dict_word(const uint8_t *chars, int len, const uint8_t *word) { + int i; + + for(i = 0; i < len; i++) { + if(!word[i]) return 1; + if(chars[i] != word[i]) return (int) chars[i] - (int) word[i]; + } + + return word[len] ? -1 : 0; +} + +// Find the longest dictionary word (longer than two characters) that appears +// right after a space at the beginning of aastr. Such a word can be encoded +// as a single escape, replacing the space and the word itself. static int find_dict_prefix(uint8_t *aastr) { - int i, best = 2, argbest = -1; - int begin, end, mid; - struct dictentry *de; + int len, begin, end, mid, diff; if(*aastr++ != ' ') return -1; - begin = 0; - end = ndict; - while(begin < end) { - mid = (begin + end) / 2; - de = &dictionary[mid]; - for(i = 0; de->chars[i] && aastr[i] == de->chars[i]; i++); - if(!de->chars[i]) { - if(i > best) { - best = i; - argbest = mid; + + for(len = 0; len < dict_maxlen && aastr[len]; len++); + + // do the binary search on strings of the same length + // starting with the longest + while(len > 2) { + begin = 0; + end = ndict - 1; + while(begin <= end) { + mid = (begin + end) / 2; + diff = cmp_dict_word(aastr, len, dictionary[mid].chars); + if(!diff) return mid; + if(diff < 0) { + end = mid - 1; + } else { + begin = mid + 1; } - begin = mid + 1; - } else if(de->chars[i] > aastr[i]) { - end = mid - 1; - } else { - begin = mid + 1; } + len--; } - return argbest; + return -1; } static void analyze_chars() { From 17da7251b9849927908524d777c2cf15b4b06fe9 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Fri, 11 Sep 2026 04:00:32 +0200 Subject: [PATCH 2/2] updated readme --- readme.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.txt b/readme.txt index c1be6c8e..47777cc5 100644 --- a/readme.txt +++ b/readme.txt @@ -48,6 +48,10 @@ Project website: Release notes: + 1c/04, Lib 1.2.4: + + Compiler: improved dictionary word matching accuracy. + 1c/03, Lib 1.2.4: Language: CSS text-decoration: reverse has been replaced with