%% LyX 2.0.0 created this file.  For more info, see http://www.lyx.org/.
%% Do not edit unless you really know what you are doing.
\documentclass[ngerman]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8x]{inputenc}
\usepackage{multicol}
\usepackage{babel}
%\begin{document}

\vspace*{2em}

\title{Xchars im Microcontroller}


\author{Bernd Paysan}
\maketitle
\begin{abstract}
\emph{Matthias Trute fragte im IRC, was er denn tun müsse, um das Xchar--Wordset
in seinem amForth zu implementieren. Ich nutze die freie Seite in
der VD, das mal kurz zu erklären. Das Xchar--Wordset ist ein Modul
des Forth200x--Standards, mit dem ASCII--kompatible Erweiterungen
von Zeichensätzen, auch solche mit variablen Zeichenlängen, verarbeitet
werden können. Das ist vor allem das populäre UTF--8, aber auch GBK
(VR China), Big5 (Taiwan) oder JIS X 0213 (Japan) haben variable Länge
und sind ASCII--kompatibel.}
\end{abstract}
\begin{multicols}{2}


\section{Einleitung}

Die Motivation zu der Xchar--Erweiterung kommt aus der Anforderung
der ISO, zu Forth doch bitte auch ein Internationalization--Konzept
hinzuzufügen. Xchars lösen nur einen Teil davon, nämlich die Zeichensätze
--- ANS--Forth selbst war ein reines ASCII--System. Anders als etwa
Python, das zwischen Strings und Byte--Arrays unterscheidet, und Strings
bei der Ein/Ausgabe recodieren muss, wollte ich keine solch gravierenden
Eingriffe in das Forth--System vornehmen. Xchar ist also so gebaut,
dass man mit wenig Aufwand ein vorhandenes System fit für UTF--8 oder
andere Encodings mit variabler Länge machen kann.

So ein Standard--Text ist nicht unbedingt leicht zu lesen, weil Standards
immer viel mit Politik zu tun haben, und man das dann so formuliert,
dass auch verschiedene Implementierungsoptionen möglich sind. In der
Praxis kommen diese Optionen selten in Frage. So definiert Xchar ein
,,pchar{};`` in den meisten Implementierungen nennt man das einfach
,,Byte{}.`` Ein Xchar (extended character) besteht halt aus einem
oder mehreren Bytes.

String--Befehle selbst funktionieren ohne Änderungen mit Xchars, weil
Strings nach wie vor einfach Byte--Arrays sind. Natürlich muss man
darauf achten, dass alles 8--Bit--clean ist, auch das Wörterbuch.
Dann hat man schon ein System, das weitgehend funktioniert, wenn man
ihm UTF--8--Quelltext vorlegt. Gforth 0.6.2, die letzte Version ohne
Xchars, schluckt das, ohne zu murren. Nur der Zeileneditor hakt, wenn
man Xchars eingibt, und mit dem Cursor darüber hinweglaufen will ---
weil der eben nichts über die variable Zeichenlänge weiß. amForth,
das hat Matthias gleich ausprobiert, verschluckt sich im Wörterbuch,
wenn man UTF--8--Zeichen benutzt. Aber das ist sicher ein Problem,
das leicht zu beheben ist. Damit ist das Forth--System dann schon
mal 8--Bit--clean, das ist die halbe Miete.

Was das Xchar--Wordset nicht macht: Es unterstützt nicht das Umwandeln
von einem Encoding in ein anderes. Man kann also nicht mal ein
UTF--8--Terminal, mal ein Latin--1--Terminal verwenden, und sich
darauf verlassen, dass das dann alles geht. Wenn man solche Features
haben möchte, kann man die außerhalb des Standards implementieren, wie
es einem gerade gefällt.


\section{Minimaler Befehlssatz}

Man muss nicht viel implementieren, um das Xchar--Wordset auf einen
Controller zu bringen. Die Erweiterungen (XCHAR EXT) sind nicht Pflicht,
und auch nicht nötig, um einfache Operationen auszuführen. Viel mehr
wird man auf dem Controller auch nicht machen, nur XCHAR-- ist interessant.
Ich definiere die Wörter so, dass man sie auf einem Controller einfach
implementieren kann.
\begin{description}
\item [{X--SIZE}] ( xc--addr u1 --- u2 ) 


Liefert die Länge des ersten Xchars im String --- maximal u1. Kann
man sehr einfach implementieren:
\begin{small}
\begin{verbatim}
: x-size ( xc-addr u1 -- u2 )
  >r dup xc@+ drop - r> min ;
\end{verbatim}
\end{small}
\item [{XC--SIZE}] ( xchar --- u )


Liefert die Länge des Zeichens im Speicher. Auch das sehr einfach
zu implementieren:
\begin{small}
\begin{verbatim}
Create xc-buf 4 allot
: xc-size ( xchar -- u )  xc-buf xc!+ xc-buf - ;
\end{verbatim}
\end{small}
\item [{XC@+}] ( xc--addr1 --- xc--addr2 xchar )


Liest ein Xchar aus dem String, analog zu COUNT. Für UTF--8 kann man
sich an die Referenz--Implementierung halten:
\begin{small}
\begin{verbatim}
: xc@+ ( xc-addr -- xc-addr' u )
    count  dup $80 u< IF  EXIT  THEN
    $7F and  $40 >r
    BEGIN   dup r@ and  WHILE  r@ xor
            6 lshift r> 5 lshift >r >r count
            $3F and r> or
    REPEAT  r> drop ;
\end{verbatim}
\end{small}
\item [{XC!+}] ( xchar xc--addr1 --- xc--addr2 )


Speichert ein Xchar in einem String, und gibt die nächste unbenutzte
Adresse zurück --- also das Gegenstück zu XC@+. Auch hier der Verweis
auf die Referenz--Implementierung für UTF--8:
\begin{small}
\begin{verbatim}
: xc!+ ( xchar xc-addr -- xc-addr' )
  over $80 u< IF  tuck c! char+  EXIT  THEN
  >r 0 swap  $3F
  BEGIN  2dup u>  WHILE
         2/ >r  dup $3F and $80 or
         swap 6 rshift r>
  REPEAT  $7F xor 2* or  r>
  BEGIN   over $80 u< 0= WHILE
          tuck c! char+  REPEAT  nip ; 
\end{verbatim}
\end{small}
\item [{XC!+?}] ( xchar xc--addr1 u1 --- xc--addr2 u2 flag ) 


Diese Variante von XC!+ schützt vor Buffer--Overflows. Man kann das
mit XC--SIZE leicht implementieren:
\begin{small}
\begin{verbatim}
: xc!+? ( xchar xc-addr1 u1 -- xc-addr2 u2 flag )
  >r
  over xc-size r@ u>
  IF  nip r> false  EXIT  THEN
  r> over + >r xc!+ r> over - true ;
\end{verbatim}
\end{small}
\item [{XC,}] ( xchar --- )


Legt ein Xchar im Dictionary ab. Auch das leicht zu implementieren:
\begin{small}
\begin{verbatim}
: xc, ( xchar -- ) here xc!+ dp ! ;
\end{verbatim}
\end{small}
\item [{XCHAR+}] ( xc--addr1 --- xc--addr2 )


Geht zum nächsten Xchar, ebenfalls trivial zu implementieren:
\begin{small}
\begin{verbatim}
: xchar+ ( xc-addr1 -- xc-addr2 )  xc@+ drop ; 
\end{verbatim}
\end{small}

Es gibt da noch ein XCHAR--, das nicht ganz so leicht zu implementieren
ist, aber sehr nützlich für den Zeileneditor. Bei UTF--8 sucht man
rückwärts nach etwas, was entweder ASCII oder größer \$C0 ist.

\item [{XKEY}] ( --- xchar )


Liest ein Xchar vom Terminal. Auch hier ist die Implementierung Encoding--abhängig.
\begin{small}
\begin{verbatim}
: xkey ( -- xchar)
  key dup $80 u< IF  EXIT  THEN
  $7F and  $40 >r
  BEGIN  dup r@ and  WHILE  r@ xor
         6 lshift r> 5 lshift >r >r key
         $3F and r> or
  REPEAT  r> drop ; 
\end{verbatim}
\end{small}
\item [{XKEY?}] ( --- flag )


Liefert true zurück, wenn ein komplettes Xchar im Input--Buffer des
Terminals angelangt ist. Das heißt, man muss Buffering implementieren.
Ich überlasse das als Übung dem Leser, und überlege mir, ob man XKEY?
auf dem Controller wirklich braucht.

\item [{XEMIT}] ( xchar --- )


Gibt ein Xchar auf dem Terminal aus. Das kann man jetzt wieder direkt
implementieren:
\begin{small}
\begin{verbatim}
: xemit ( xchar -- )
  xc-buf xc!+ xc-buf tuck - type ;
\end{verbatim}
\end{small}
\end{description}

\end{multicols}

\vfill

\begin{figure}
  \begin{center}
  \includegraphics[height=5.7cm]{2011-03/2011-05-20_15-34-05}
    
  \end{center}
  \caption{Das Thema Schreibrichtung ist nichts für Microcontroller}
\end{figure}

%\end{document}
