Podcast #128: We chat with Kent C Dodds about why he loves React and discuss what life was like in the dark days before Git. Listen now.
1 of 6

As I understand it, there are two parts to doing what the question desires:

  • Converting a Unicode code point to its UTF-8 encoding, e.g. U+20AC to the sequence of bytes E2 82 AC.
  • Injecting those bytes, or the equivalent of typing those bytes, into the input stream.

I still don't understand how to do the second part, but just for fun I wrote the first part (UTF-8 encoder). I know it's already implemented in utf8ienc.dtx / utf8.def, but found it interesting to write one afresh (having written the inverse—a UTF-8 decoder—recently).

The following requires eTeX (uses \numexpr) but otherwise works in both plain TeX and LaTeX (for plain TeX, comment out the first three lines):

\documentclass{article}
\begin{document}
\def\bye{\end{document}}

\input binhex  % Used for hex output (E2 instead of 226)
\def\byte#1{\nhex{2}{\number#1}}

% Division and remainder. Based on https://tex.stackexchange.com/a/34449/48 but with bugs fixed. Note: assumes #2 positive
\def\moduloop#1#2{\ifnum \numexpr(#1 - (#1/#2)*(#2))\relax < 0 (#1 - (#1/#2)*(#2) + #2) \else (#1 - (#1/#2)*(#2)) \fi}
\def\truncdiv#1#2{((#1 - \moduloop{#1}{#2})/(#2))}
% The hypothetical continuation bytes: last byte, the one before that, etc.
\def\utfByteLastOne  #1{\numexpr(128 + \moduloop{#1}{64})\relax}
\def\utfByteLastTwo  #1{\numexpr(128 + \moduloop{\truncdiv{#1}{64}}{64})\relax}
\def\utfByteLastThree#1{\numexpr(128 + \moduloop{\truncdiv{#1}{(64*64)}}{64})\relax}
\def\utfByteLastFour #1{\numexpr(128 + \moduloop{\truncdiv{#1}{(64*64*64)}}{64})\relax}
% The actual individual bytes in the stream, for lengths 1 to 4.
\def\utfStreamOneByteOne    #1{#1}
\def\utfStreamTwoByteOne    #1{\numexpr(\utfByteLastTwo{#1} + 64)\relax}
\def\utfStreamTwoByteTwo    #1{\utfByteLastOne{#1}}
\def\utfStreamThreeByteOne  #1{\numexpr(\utfByteLastThree{#1} + 96)\relax}
\def\utfStreamThreeByteTwo  #1{\utfByteLastTwo{#1}}
\def\utfStreamThreeByteThree#1{\utfByteLastOne{#1}}
\def\utfStreamFourByteOne   #1{\numexpr(\utfByteLastFour{#1} + 112)\relax}
\def\utfStreamFourByteTwo   #1{\utfByteLastThree{#1}}
\def\utfStreamFourByteThree #1{\utfByteLastTwo{#1}}
\def\utfStreamFourByteFour  #1{\utfByteLastOne{#1}}
% The full byte stream -- here, do whatever you want with the individual bytes (e.g. convert to hex).
\def\utfStreamOne  #1{\byte{\utfStreamOneByteOne{#1}}}
\def\utfStreamTwo  #1{\byte{\utfStreamTwoByteOne{#1}}, then \byte{\utfStreamTwoByteTwo{#1}}}
\def\utfStreamThree#1{\byte{\utfStreamThreeByteOne{#1}}, then \byte{\utfStreamThreeByteTwo{#1}}, then \byte{\utfStreamThreeByteThree{#1}}}
\def\utfStreamFour #1{\byte{\utfStreamFourByteOne{#1}}, then \byte{\utfStreamFourByteTwo{#1}}, then \byte{\utfStreamFourByteThree{#1}}, then \byte{\utfStreamFourByteFour{#1}}}
% Converting Unicode code point to UTF-8, by using one of the above.
\def\utfStreamFromNumber#1{%
    \ifnum #1 < 128
        \utfStreamOne{#1}%
    \else \ifnum #1 < 2048  % 2^11
              \utfStreamTwo{#1}%
          \else \ifnum #1 < 65536  % 2^16
                    \utfStreamThree{#1}%
                \else
                    \utfStreamFour{#1}%
                \fi
          \fi
    \fi
}
\def\utfStream#1{\utfStreamFromNumber{"#1}}

Examples:
\tt

\def\example#1{U+#1 is encoded as: \utfStream{#1}.\par}
\example{0000}
\example{007F}
\example{0080}
\example{07FF}
\example{0800}
\example{20AC}
\example{FFFF}
\example{10000}
\example{10FFFF}

\bye

output