Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ Release notes:

1c/04, Lib 1.2.4:

Compiler: improved dictionary word matching accuracy.

Compiler: Improved ordering of strings in WRIT chunk, which
improves performance on slow platforms like 6502.

Expand Down
61 changes: 42 additions & 19 deletions src/backend_aa.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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() {
Expand Down
Loading