25int main(
int argc,
char *argv[]) {
26 auto ErrorOrBuffer = MemoryBuffer::getFile(argv[1],
true);
29 std::unique_ptr<MemoryBuffer> Buffer = std::move(ErrorOrBuffer.get());
30 StringRef Content = Buffer->getBuffer();
31 Content = Content.drop_until([](
char C) {
return C ==
'#'; });
33 SplitString(Content, Lines,
"\r\n");
35 std::vector<ConfusableEntry> Entries;
37 for (
const StringRef Line : Lines) {
38 if (Line.starts_with(
'#'))
42 Line.split(Values,
';');
43 if (Values.size() < 2) {
44 errs() <<
"Failed to parse: " << Line <<
"\n";
48 const StringRef From = Values[0].trim();
49 llvm::UTF32 CodePoint = 0;
50 From.getAsInteger(16, CodePoint);
52 std::string Replacement;
54 Values[1].split(ToN,
' ', -1,
false);
55 for (
const StringRef ToI : ToN) {
56 llvm::UTF32 ToCodePoint = 0;
57 ToI.trim().getAsInteger(16, ToCodePoint);
58 char Encoded[UNI_MAX_UTF8_BYTES_PER_CODE_POINT];
59 char *EncodedEnd = Encoded;
60 if (!ConvertCodePointToUTF8(ToCodePoint, EncodedEnd)) {
61 errs() <<
"Failed to encode code point: " << ToI <<
"\n";
64 Replacement.append(Encoded, EncodedEnd);
67 Entries.push_back({CodePoint, std::move(Replacement)});
70 [](
const ConfusableEntry &LHS,
const ConfusableEntry &RHS) {
71 return LHS.CodePoint < RHS.CodePoint;
74 StringMap<uint16_t> ReplacementOffsets;
75 std::string ReplacementData;
76 for (
const ConfusableEntry &
Entry : Entries) {
77 if (ReplacementOffsets.contains(
Entry.Replacement))
79 if (ReplacementData.size() +
Entry.Replacement.size() >
80 std::numeric_limits<uint16_t>::max()) {
81 errs() <<
"Confusable replacement data exceeds 16-bit offsets\n";
84 ReplacementOffsets.try_emplace(
85 Entry.Replacement,
static_cast<uint16_t
>(ReplacementData.size()));
86 ReplacementData.append(
Entry.Replacement);
90 llvm::raw_fd_ostream Os(argv[2], Ec);
92 static constexpr char HexDigits[] =
"0123456789ABCDEF";
93 Os <<
"constexpr char ConfusableReplacementData[] =\n";
94 for (
size_t I = 0; I < ReplacementData.size(); I += 32) {
96 for (
const unsigned char C : StringRef(ReplacementData).substr(I, 32))
97 Os <<
"\\x" << HexDigits[C >> 4] << HexDigits[C & 0x0F];
102 Os <<
"constexpr ConfusableEntry ConfusableEntries[] = {\n";
103 for (
const ConfusableEntry &
Entry : Entries) {
104 const auto It = ReplacementOffsets.find(
Entry.Replacement);
105 Os <<
" {" <<
Entry.CodePoint <<
", " << It->second <<
", "
106 <<
Entry.Replacement.size() <<
"},\n";