fix "\x{100}..." =~ tr/.../.../cd
authorDavid Mitchell <davem@iabyn.com>
Thu, 11 Jan 2018 11:45:49 +0000 (11:45 +0000)
committerDavid Mitchell <davem@iabyn.com>
Fri, 19 Jan 2018 13:45:19 +0000 (13:45 +0000)
commitf146bab680e5a22cf4657df42193385ddd2b538c
tree233f1c84d32d3195bf371fce30a72ceb7d44098a
parentea088e559c9bca8e7337d3d6236f06deb5afda32
fix "\x{100}..." =~ tr/.../.../cd

In transliterations where the search and replacement charlists are
non-utf8, but where the string being modified contains codepoints >=
0x100, then tr/.../.../cd would always delete all such codepoints, rather
than potentially mapping some of them.

In more detail: in the presence of /c (complement), an implicit
0x100..0x7fffffff is added to a non-utf8 search charlist. If the
replacement list is longer than the < 0x100 part of the search list, then
the last few replacement chars should in principle be paired off against
the first few of (\x100, \x101, ...). However, this wasn't happening. For
example,

    tr/\x00-\xfd/ABCD/cd

should be equivalent to

    tr/\xfe-\x{7fffffff}/ABCD/d

which should
    map:
        \xfe    => A,
        \xff    => B,
        \x{100} => C,
        \x{101} => D,
    and delete \x{102} onwards.

But instead, it behaved like

    tr/\xfe-\x{7fffffff}/AB/d

and deleted all codepoints >= 0x100.

This commit fixes that by using the extended mapping table format
for all /c variants (formerly it excluded /cd).

I also changed a variable holding the mapped char from being I32 to UV:
principally to avoid a casting mess in the fixed code. This may (or may
not), as a side-effect, have fixed possible issues with very large
codepoints.
doop.c
op.c
t/op/tr.t