+proc preamble_trie {ofilehandle ifiles ofile} {
+ set f $ofilehandle
+
+ set totype {unsigned }
+
+ puts $f "/** \\file $ofile"
+ puts $f " \\brief Character conversion, generated from [lindex $ifiles 0]"
+ puts $f ""
+ puts $f " Generated automatically by charconv.tcl"
+ puts $f "*/"
+ puts $f "\#include <string.h>"
+
+ puts $f "\#if HAVE_CONFIG_H"
+ puts $f "\#include <config.h>"
+ puts $f "\#endif"
+
+ puts $f "
+ struct yaz_iconv_trie_flat {
+ char from\[6\];
+ unsigned combining : 1;
+ $totype to : 24;
+ };
+ struct yaz_iconv_trie_dir {
+ int ptr : 15;
+ unsigned combining : 1;
+ $totype to : 24;
+ };
+
+ struct yaz_iconv_trie {
+ struct yaz_iconv_trie_flat *flat;
+ struct yaz_iconv_trie_dir *dir;
+ };
+ "
+ puts $f {
+ static unsigned long lookup(struct yaz_iconv_trie **ptrs, int ptr, unsigned char *inp,
+ size_t inbytesleft, size_t *no_read, int *combining, unsigned mask, unsigned int boffset)
+ {
+ struct yaz_iconv_trie *t = ptrs[ptr-1];
+ if (inbytesleft < 1)
+ return 0;
+ if (t->dir)
+ {
+ size_t ch = (inp[0] & mask) + boffset;
+ unsigned long code;
+ if (t->dir[ch].ptr)
+ {
+ code = lookup(ptrs, t->dir[ch].ptr, inp+1, inbytesleft-1, no_read, combining, mask, boffset);
+ if (code)
+ {
+ (*no_read)++;
+ return code;
+ }
+ }
+ if (t->dir[ch].to)
+ {
+ code = t->dir[ch].to;
+ *combining = t->dir[ch].combining;
+ *no_read = 1;
+ return code;
+ }
+ }
+ else
+ {
+ struct yaz_iconv_trie_flat *flat = t->flat;
+ while (flat->to)
+ {
+ size_t len = strlen(flat->from);
+ if (len <= inbytesleft)
+ {
+ size_t i;
+ for (i = 0; i < len; i++)
+ {
+ if (((unsigned char *) flat->from)[i] != (inp[i] & mask) + boffset)
+ break;
+ }
+ if (i == len)
+ {
+ *no_read = len;
+ *combining = flat->combining;
+ return flat->to;
+ }
+ }
+ flat++;
+ }
+ }
+ return 0;
+ }
+ }
+}
+
+proc reset_trie {} {
+ global trie
+
+ foreach x [array names trie] {
+ unset trie($x)
+ }
+
+ set trie(no) 1
+ set trie(size) 0
+ set trie(max) 0
+ set trie(split) 50
+ set trie(prefix) {}
+}
+
+proc ins_trie {from to combining codename} {