Will man Daten aus einer Datenbank in ansprechender Form
mit \TeX{} setzen (z.B. ein Telefonverzeichnis), so steht
man vor der Wahl, diese Daten entweder manuell mit einem
Texteditor mit den notwendigen \TeX-Kommandos zu versehen,
oder ein Programm zu schreiben, welches die Daten liest und
die Kommandos einf"ugt (eine besonders empfehlenswerte
Programmiersprache f"ur solche Zwecke ist AWK, vgl. E.
Neuwirth, Quick and Dirty Databases with Nice Output: AWK
and \TeX, TUGboat 11(1990), No.~3 -- 1990 Conference
Proceedings).
W"ahrend die erste Methode bei gr"o"seren Datenmenge wohl sofort
ausscheidet, hat auch die zweite einen gravierenden Nachteil: das Layout des
Dokuments liegt quasi im Programm-Sourcecode verborgen. Sowohl
die Erstellung des Layouts (in der Regel eine Reihe von
Trial-and-Error-Zyklen von Editor, \TeX{} und Previewer bzw.
Ausdruck) als auch sp"ater eventuell notwendige "Anderungen
werden dadurch erschwert.
Mit db\TeX{} wird ein dritter Weg vorgeschlagen. Ausgangspunkt
ist ein Skript, welches seinerseits ein normales \TeX-Inputfile
darstellt. Dieses Skript ist das Resultat der Layouterstellung
und wird daher in der Regel auch einige Testdatens"atze enthalten.
Innerhalb von \TeX-Kommentaren werden nun spezielle
db\TeX-Befehle eingestreut, die unter anderem das Auskommentieren
der urspr"unglichen Testdatens"atze und das Inkludieren der echten
Datens"atze betreffen.
Dieses Skript wird anschlie"send vom db\TeX-Pr"aprozessor
abgearbeitet; dabei werden die speziellen db\TeX-Befehle
interpretiert (also Musterdaten auskommentiert und echte Daten
eingef"ugt), der Rest des Skriptfiles jedoch nicht ver"andert.
Das Resultat ist die endg"ultige \TeX-Eingabedatei.
Das Einf"ugen der Datens"atze geschieht unter Zuhilfenahme
von "`Templates"', so da"s je nach Wunsch auch nur einzelne
Datenfelder verwendet oder zus"atzliche Informationen
innerhalb der Daten (z.B. \TeX-Makroaufrufe) eingef"ugt
werden k"onnen.
Ein kurzes db\TeX-Skript k"onnte etwa folgenderma"sen aussehen:
\begin{verbatim}
\documentstyle[12pt,german,a4]{article}
\begin{document}
normaler Text und TeX-Definitionen ...
%! template %2%: %1% %2%, Tel. %3% %4% %5% %6% %7%\\
%! examples
Bauer: Fritz Bauer, Tel. 12 34 55\\
Brown: Charly Brown, Tel. 34 55 66\\
Becker: Biggy Becker, Tel. 56 77 88\\
%! include adr.dat
ev.weiterer Text hier ...
\end{document}
\end{verbatim}
Nach Bearbeitung durch den db\TeX-Pr"aprozessor sieht die Datei
dann so aus:
Das hier gezeigte Beispiel ist etwas vereinfacht, da man in
der Praxis noch weitere db\TeX-Befehle ben"otigen wird.
Die inkludierte Datei hat f"ur dieses Beispiel folgendes Aussehen:
\begin{verbatim}
Richi Alteisen 99 80 70
Robby Artmann 12 12 22
Conny Brown 14 14 09
Fritz Lang 77 66 55
Rudi Mayer 88 99 00
\end{verbatim}
F"ur die Realisierung einer ersten Version von db\TeX{} wurde die
Sprache AWK verwendet, die sowohl f"ur einfache
Datenmanipulationen als auch f"ur die Implementation von einfachen
Interpretersprachen wie dem vorgestellten Pr"aprozessor ein sehr
gut geeignetes Werkzeug ist. Im speziellen Fall wurde unter MS-DOS auf
PolyAWK (von Sage Software, vormals Polytron)
zur"uckgegriffen; da es f"ur diesen Implementation auch einen
Compiler gibt, konnte das Programm auch problemlos als
Stand-Alone-Version aufbereitet werden. Es sollte ohne
wesentliche "Anderungen m"oglich sein, das Programm auch mit anderen
AWK-Versionen zum Laufen zu bringen (z.B. mit GNU-AWK, das
im Rahmen der Free Software Foundation erh"altlich ist).
{\sl F"ur das vorliegende Programm und seine Dokumentation
wird kein Copyright beansprucht; es soll im Gegenteil als
Ausgangspunkt f"ur eigene Verbesserungen, Erg"anzungen,
Erweiterungen und Experimente betrachtet werden. Aus diesem
Grunde werden allerdings auch keine Verpflichtungen (zur
Wartung, Fehlerbehebung oder Weiterentwicklung) "ubernommen.
Der Autor ist allerdings sehr an Verbesserungsvorschl"agen
oder Weiterentwicklungen interessiert und entweder
schriftlich (unter der im Titel angegebenen Adresse) oder
mit E-Mail (EARN: {\tt A7511daa @ awiuni11}) erreichbar.}
\newpage
\section{db\TeX -Aufruf}
Der Programmaufruf ist davon abh"angig, ob der
AWK-Interpreter aufgerufen wird oder eine kompilierte Form
des Programms. Im ersten Fall lautet der Aufruf so:
\begin{syntax}{awk -fdbtex.awk {\it input-file} > {\it output-file}}
\item[{\it input-file}] Die Eingabedatei (db\TeX -Skript)
\item[{\it output-file}] Die Ausgabedatei (sollte die Extension
tex aufweisen. da diese Datei mit \TeX{} gesetzt wird)
\end{list}
\end{syntax}
Der Aufruf der kompilierten Form sieht folgenderma"sen aus:
\begin{syntax}{dbtex {\it input-file} > {\it output-file}}
\item[{\it input-file}] Die Eingabedatei (db\TeX -Skript)
\item[{\it output-file}] Die Ausgabedatei (sollte die Extension
tex aufweisen, da diese Datei mit \TeX{} gesetzt wird)
\end{list}
\end{syntax}
\newpage
\section{db\TeX -Befehle}
Jeder db\TeX -Befehl beginnt mit der Sequenz {\tt \%!};
diese mu"s am Zeilenanfang stehen. Anschlie"send steht ein
Schl"usselwort, das auch durch ein oder mehrere Blanks von
der Anfangssequenz getrennt sein kann. In weiterer Folge
k"onnen noch Argumente zu stehen kommen, die ebenfalls durch
Blanks getrennt sind.
Alle db\TeX -Befehle mit einer Ausnahme k"onnen nur eine Zeile lang
sein; die Ausnahme ist der {\tt \%! template}-Befehl, bei
dem auch Fortsetzungszeilen erlaubt sind. Diese
Fortsetzungszeilen beginnen mit der Sequenz {\tt \%\_}.
Da die db\TeX -Anfangssequenzen mit einem Prozentzeichen
beginnen, wird eine solche Zeile von \TeX{} als Kommentar
behandelt; es sind also sowohl das db\TeX-Skript als auch
der von db\TeX{} erzeugte Output g"ultige \TeX-Eingabedateien.
\eintrag{\%! break}
Befehl zum Einf"ugen von Daten anl"a"slich eines
Gruppenwechsels ("Anderung des Inhalts eines Feldes der zu
inkludierenden Datei).
\begin{syntax}{\%! break <num> <template-name> [<flag>]}
\item[<num>] Eine Zahl, die auch in der Form {\tt \%n\%}
geschrieben sein kann. Sie bezieht sich auf das Feld {\tt <num>}
des zu inkludierenden Datenfiles.
\item[<template-name>] Name des Templates, das in die
Ausgabe eingef"ugt werden soll, wenn sich der Inhalt von
Feld {\tt <num>} "andert.
\item[<flag>] Beliebiges Symbol bzw. beliebige Zeichenkette; wenn dieses Flag
vorhanden ist, wird schon {\em vor} dem ersten einzuf"ugenden Datensatz
das Template eingef"ugt (z.B. als "Uberschrift etc.).
\end{list}
\beispiel
\begin{programm}
\%! break 2 tabellenende
\end{programm}
Falls sich der Inhalt des zweiten Feldes "andert, soll das
Template {\tt tabellenende} benutzt werden (da kein Flag vorhanden ist,
wird vor dem ersten Datensatz kein Template eingef"ugt).
\siehe clearbreaks, record, template
\end{syntax}
\eintrag{\%! change}
Dieser Befehl dient zur Spezifikation einer
Zeichenkettenersetzung. Es ist damit m"oglich, bestimmte
Zeichenketten der Eingabedatei durch andere Zeichenketten
zu ersetzen. Es k"onnen auf diese Weise z.B. bestimmte
Zeichen, die in \TeX{} eigens kodiert werden m"ussen,
"ubersetzt werden.
\begin{syntax}{\%! change <string1> <string2>}
\item[<string1>] Der zu ersetzende String. Er mu"s zwischen
zwei Zeichen, die sonst nicht im String vorkommen und nicht
Blank sein d"urfen, begrenzt werden.
\item[<string2>] Der String, womit ersetzt werden soll. Die
formalen Regeln sind analog zum vorhergehenden.
\end{list}
\beispiel
\begin{programm}
\%! change /TeX/ /$\backslash$TeX\{\}/
\end{programm}
Die Zeichenkette TeX in der Datenbankdatei soll durch das
entsprechende \TeX -Makro ersetzt werden
\siehe translate; Abschnitt \ref{idio}
\end{syntax}
\eintrag{\%! clearbreaks}
Mit diesem Befehl werden die bisher spezifizierten
Gruppenwechsel wieder gel"oscht.
\begin{syntax}{\%! clearbreaks}
\item (Dieser Befehl verwendet keine Argumente.)
\end{list}
\siehe break
\end{syntax}
\eintrag{\%! examples}
Mit diesem Befehl wird db\TeX{} angezeigt, da"s die folgenden
Zeilen im Skript als Beispielrecords zu verstehen sind: bei
der Bearbeitung durch den Pr"aprozessor werden die folgenden
Zeilen solange (durch ein Prozentzeichen am Zeilenanfang)
auskommentiert, bis wieder ein db\TeX
-Kommando erkannt wird. Dies wird in der Praxis meist ein
{\tt \%!~include}-Kommando sein.
\begin{syntax}{\%! examples}
\item (Dieser Befehl verwendet keine Argumente.)
\end{list}
\siehe include
\end{syntax}
\eintrag{\%! include}
Dieser Befehl veranla"st db\TeX{}, Datens"atze aus einer
Datendatei zu lesen und in die Outputdatei einzuf"ugen.
Dabei werden die einzelnen Felder der Datens"atze
entsprechend einem Template eingef"ugt, dessen Name in einem
{\tt \%! record}-Befehl angegeben und das in einem {\tt \%!
template}-Befehl definiert wurde. Au"serdem werden eventuell
Zeichenkettenersetzungen durchgef"uhrt, wenn mittels des
{\tt \%! translate}-Befehls eine Ersetzungstabelle geladen
wurde und/oder einzelne Ersetzungen in einem {\tt \%!
change}-Befehl verlangt wurden. Der Wechsel im Inhalt eines
Datenfeldes f"uhrt zur Ausgabe eines eigenen Templates, wenn
dieses Datenfeld in einem {\tt \%! break}-Befehl
referenziert wurde; damit lassen sich spezielle Aktionen
anl"a"slich eines Gruppenwechsels steuern.
\begin{syntax}{\%! include <filename>}
\item[<filename>] Die Datei namens {\tt <filename>} enth"alt
die zu inkludierenden Datens"atze.
\end{list}
\beispiel
Im ersten Beispiel wird f"ur jeden Datensatz das Template
{\tt t1} verwendet und die Datei {\tt xyz.dat} verwendet:
\begin{programm}
\%! record t1
\%! template t1 $\backslash$datensatz\{Name: \%1\% \%3\%\}\{\%2\%\}
\%! include xyz.dat
\end{programm}
Das zweite Beispiel zeigt, wie die Auswahl des Templates
auch durch den Inhalt der Datei selbst bestimmt werden kann:
\begin{programm}
\%! record \%4\%
\%! template name $\backslash$inclname\{\%1\%\}\{\%2\% \%3\%\}
\%! template adr $\backslash$incladr\{\%3\% \%2\% \%1\%\}
\%\_ \{\%4\% (Firma)\}
\%! include adressen.dat
\end{programm}
\siehe record, template, translate, change, break
\end{syntax}
\eintrag{\%! record}
Der {\tt \%! record}-Befehl spezifiziert, wie die S"atze aus
der Datendatei einzulesen und in die Ausgabedatei zu
inkludieren sind. Es wird damit festgelegt, welches
Template und welcher Field-
bzw. Record-Separator (entsprechend den AWK-Variablen
FS und RS) zu verwenden ist.
Das erste Argument ist entweder ein Name (der Name eines
Templates oder eine Zahl n zwischen Prozentzeichen; in
letzterem Fall wird erwartet, da"s in dem Feld n der
Datendatei (vgl. AWK's {\tt \$n}) ein Name
eines Templates steht. Damit ist es m"oglich, das zu verwendende
Template durch die Daten zu definieren.
\begin{syntax}{\%! record <id> [<field-sep> [<record-sep>]]}
\item[<id>] Dies ist entweder ein Name, der einem
Template-Namen entspricht, oder ein Verweis auf ein
Datenfeld in der Form {\tt \%n\%}. In diesem Fall wird der
Name des Templates f"ur den aktuellen Datensatz aus der
Datei selbst, und zwar durch den Inhalt von Feld Nr. {\tt
n} bestimmt.
\item[<field-sep>] Dies ist ein String, der zwischen zwei
Zeichen eingeschlossen sein mu"s, die nicht im String selbst
enthalten sein und nicht Blank sein d"urfen. Er dient zur
Festlegung jener Zeichen, die als Feldseparatoren dienen.
Der Defaultwert ist (wie in AWK) Blank und Tab.
\item[<record-sep>] Dieser String, f"ur den bez"uglich seines
Aufbaus dasselbe gilt wie im vorigen Absatz, definiert den
Recordseparator. Defaultwert ist Newline.
\end{list}
\beispiel
Im folgenden Beispiel wird ein Feld der Datendatei
spezifiziert, welches den Namen des Templates zu enthalten
hat, und ein vom Default abweichender Feldseparator.
\begin{programm}
\%! record \%1\% /:::/
\end{programm}
\siehe include
\end{syntax}
\eintrag{\%! template}
Mit diesem Befehl kann eine beliebige Anzahl von Templates
definiert werden, die entweder als Schema zum Einf"ugen von
Datens"atzen dienen oder anl"a"slich eines Gruppenwechsels
verwendet werden. Die Positionen, an denen Daten aus dem
aktuellen Satz der Datendatei stehen sollen, werden durch
Platzhalter der Form {\tt \%n\%} markiert; es wird dort das
Feld Nr. {\tt n} eingef"ugt.
\begin{syntax}{\%! template <name> [<template>]}
\item[<name>] Ein Name, "uber welchen das betreffende
Template identifiziert wird.
\item[<template>] Das Textmuster, welches Platzhalter
der Form {\tt \%n\%} enthalten kann, und das f"ur jeden
gelesenen Datensatz in die Ausgabedatei geschrieben wird,
wobei die Platzhalter durch die aktuellen Werte aus der
Datendatei ersetzt werden. Dieses Template kann auch
mithilfe von Fortsetzungszeilen "uber mehrere Zeilen gehen.
\end{list}
\end{syntax}
Die Fortsetzungszeilen haben folgende Struktur:
\begin{syntax}{\%\_ <template>}
\item[<template>] Textmuster mit Platzhaltern, siehe oben.
\end{list}
\beispiel
Der im folgende Beispiel vorkommende Platzhalter {\tt
\%0\%} bezieht sich auf den ganzen Datensatz (analog zu den
Konventionen f"ur \$0 in AWK):
\begin{programm}
\%! template adresse Adresse: \%0\%
\%\_ $\backslash$hline
\end{programm}
\siehe break, record, include
\end{syntax}
\eintrag{\%! translate}
Mit diesem Befehl wird eine "Ubersetzungstabelle geladen,
mit deren Hilfe Zeichenkettenersetzungen beim Einlesen des
Datenfiles durchgef"uhrt werden. Zus"atzlich k"onnen einzelne
Ersetzungen durch den {\tt \%! change}-Befehl spezifiziert
werden.
\begin{syntax}{\%! translate <tr-filename>}
\item[<tr-filename>] Der Name der Datei, die die
Ersetzungstabelle enth"alt. Diese Datei enth"alt Eintr"age
entsprechend der Syntax des {\tt \%! change}-Befehls,
allerdings ohne das Befehlswort selbst (die einzelnen
Zeilen haben also die Struktur\\
{\tt <string1> <string2>}\\
wobei der erste String die zu ersetzende Kette und der
zweite die Ersatzzeichenkette repr"asentiert). Wird anstelle eines
Dateinamens das Schl"usselwort {\tt OFF} bzw. {\tt off}
verwendet, so werden alle bisher geladenen
"Ubersetzungstabellen gel"oscht.
\end{list}
\beispiel
Das folgende Beispiel spezifiziert, da"s die Datei {\tt
ascii.tbl} als "Ubersetzungstabelle verwendet werden soll.
\begin{programm}
\%! translate ascii.tbl
\end{programm}
\siehe change, include; Abschnitt \ref{idio}
\end{syntax}
\newpage
\section{Besonderheiten, Probleme und Fehler}\label{idio}
\subsection{AWK's Erbe}
Die zur Implementation benutzte Sprache AWK liegt vielen
Besonderheiten zugrunde; dies sind vor allem:
\begin{itemize}
\item Die Angabe von Feldern der einzuf"ugenden Datens"atze
ist "ahnlich wie bei AWK: \%0\% bezieht sich auf den
vollst"andigen Datensatz, \%1\%, \%2\% usw. beziehen sich
auf die Felder 1, 2 etc. Dies ist mit den AWK-Konstrukten
\$0, \$1, \$2 usw. zu vergleichen.
\item Die Definitionen von "`Fieldseparator"' und
"`Recordseparator"' entsprechen denen von AWK; dies hei"st
insbesondere, da"s diese Zeichen(ketten) als (dynamische)
regul"are Ausdr"ucke interpretiert werden.
\item Das zuvor gesagte bezieht sich auch auf die
Zeichenkettenersetzungen; die zu ersetzende Zeichenkette
ist als regul"arer Ausdruck aufzufassen, und das Zeichen \&
hat im Ersetzungtext die Funktion eines Platzhalters f"ur
den gesamten Teilstring, der durch diesen regul"aren
Ausdruck repr"asentiert wird, und ist deshalb als
$\backslash$\& zu schreiben, wenn das \&-Zeichen selbst
gemeint ist.
\end{itemize}
Diese "`ererbten Features"' sind allerdings keineswegs
negativ zu verstehen; regul"are Ausdr"ucke etwa sind so
m"achtige Formulierungsmechanismen, da"s man nur ungern auf
sie verzichten will, wenn man sich einmal mit ihrer etwas
willk"urlichen Syntax vertraut gemacht hat (und es liegt
eben in der Natur von metasprachlichen Beschreibungen, da"s
sie manchmal etwa kryptisch anmuten).
\subsection{Zeichenkettenersetzungen}
Die Ersetzungen werden als globales Suchen und Ersetzen
hintereinander durchgef"uhrt; das hei"st, das das Ergebnis
einer Ersetzung m"oglicherweise durch eine nachfolgende
Ersetzung weiter ver"andert wird. Vor allem beim Ersetzen
von ganzen Zeichenketten ist entsprechende Vorsicht geboten und
aus diesem Grund k"onnen derzeit keine Backslashes ersetzt werden!
Es werden zuerst die Ersetzungen aus den geladenen
Tabellen und anschlie"send die des {\tt \%! change}-Befehls
durchgef"uhrt.
\subsection{Gruppenwechsel}
Der derzeit vorhandene Mechanismus zur speziellen
Behandlung von Gruppenwechsel ist ziemlich ad hoc
entstanden; so wird z.B. nicht zwischen "`break before"'
und "`break after"' unterschieden. Auch gibt es keine
Mechanismen zur Erzeugung von Zwischensummen und "ahnlichem.
\subsection{Robustheit}
Der vorliegenden Version mangelt es sicherlich noch an
Robustheit; so sind auch die Fehlermeldungen eher sp"arlich
und vielleicht nicht immer sehr hilfreich. Manche Fehler
werden "uberhaupt stillschweigend ignoriert, so z.B. Strings
mit falschen oder fehlenden Delimitern, die zu h"ochst
merkw"urdigen Resultaten f"uhren k"onnen.
In der derzeitigen Form ist db\TeX{} "uberhaupt mehr als
Prototyp zu verstehen; auch in bezug auf
die eingebauten Features bzw. auf die Syntax sind mit
Sicherheit Verbesserungen und Erweiterungen m"oglich bzw.
w"unschenswert. db\TeX{} (bzw. seine Implementierung in AWK)
l"adt zu Experimenten geradezu ein!
\subsection{Bugs und ernste Probleme}
Die mithilfe des PolyAWK Compilers Version 1.0 (von
Sage-Polytron) "ubersetzte Version des Programms hat
Probleme beim Inkludieren von etwas umfangreicheren
Datenfiles (Fehlermeldung: "`out of memory"'); dies d"urfte
an einer mangelhaften Implementierung der Garbage
Collection in der Runtime-Library liegen, bei der
Interpreter-Version wurde dieser Fehler nicht beobachtet.
\subsection{Desiderata}
Der Mechanismus zur Zeichenersetzung und derjenige f"ur den
Gruppenwechsel sollte einer eingehenden Revision unterzogen
werden!
Eventuell sollte die Syntax etwas anders aussehen; es w"are
z.B. durchaus m"oglich, den {\tt \%!~record}- und den {\tt
\%!~include}-Befehl in einen einzigen Befehl zu integrieren!
Umfassendere und genauere Fehlermeldungen!
Es gibt derzeit keine M"oglichkeit, Suchpfade f"ur Daten-
oder Tabellenfiles anzugeben; dies k"onnte eventuell "uber
das Environment gesteuert werden oder "uber einen Aufrufparameter!
\newpage
\section{db\TeX -Fehlermeldungen}
Alle Fehlermeldungen wie auch informative Meldungen werden
sowohl direkt auf der Konsole ausgegeben als auch an der
betreffenden Stelle als
Kommentar in die Ausgabedatei "ubernommen.
\subsubsection{Error: FILE \dots\ NOT FOUND OR NOT ACCESSIBLE!}
Es wurde die in einem {\tt \%! include}-Befehl angegebene Datei
entweder nicht gefunden oder sie konnte nicht zum Lesen
ge"offnet werden.
\subsubsection{Error: INVALID CONTINUATION}
Es wurde eine Fortsetzungszeile ({\tt \%\_ \dots}) angetroffen, die nicht {\em
unmittelbar nach} einem {\tt \%! template}-Befehl steht.
\subsubsection{Error: TRANSLATION TABLE \dots\ NOT FOUND}
Die spezifizierte Ersetzungstabelle wurde nicht gefunden
und konnte daher nicht geladen werden.
\subsubsection{Error: UNKNOWN COMMAND}
Nach der db\TeX -Startsequenz {\tt \%!} steht ein
unbekanntes Befehlswort.
\newpage
\section{Ein kurzes db\TeX-Tutorial}
\subsection{Aufgabenstellung}
Ausgehend von einer Adressendatei soll ein Adre"sbuch mit
\TeX{} gesetzt werden; die Adressen kommen aus einer
Datenbank und liegen im ASCII-Format vor, wobei jeder
Datensatz aus mehreren Zeilen besteht und die einzelnen
Datens"atze durch Leerzeilen getrennt sind. Die Datens"atze
sind bereits richtig sortiert und haben folgende Struktur:
\begin{verse}\tt
Initialbuchstabe\\
Sortierbegriff\\
Name\\
Adresse\\
Postleitzahl und Ort\\
Land\\
Telefonnummer(n)
\end{verse}
Die ersten Datens"atze dieser Datei k"onnten etwa so aussehen:
\begin{verbatim}
A
Alpen-Treuhand
KPMG Alpen-Treuhand Ges.m.b.H
Kolingasse 19
1090 Wien
Oesterreich
34 36 45
A
Andersen
Bente Gaarder Andersen
The Norwegian Institute of Technology
N-7034 Trondheim
Norwegen
+47 7 59 26 95
\end{verbatim}
Das Adressenverzeichnis soll dann etwa folgenderma"sen aussehen:
\newcommand{\aeintrag}[5]{\begin{minipage}{10cm}\begin{flushleft}
{\bf #1}\\
{#2}\\
{#3 (#4)}\\
{\small Tel:} #5\\\vspace{4mm}\end{flushleft}\end{minipage}\par}
\pagebreak[3]\vspace{5mm plus 4mm}{\Huge $\cal A$}%
\nopagebreak\par\vspace{5mm plus 2mm}\nopagebreak
\aeintrag{KPMG Alpen-Treuhand Ges.m.b.H}{Kolingasse 19}%
{1090 Wien}{"Osterreich}{34 36 45}
\aeintrag{Bente Gaarder Andersen}{The Norwegian Institute of Technology}%
{N-7034 Trondheim}{Norwegen}{+47 7 59 26 95}
\subsection{1. Schritt: Entwurf des Layouts in \TeX}
Mithilfe von einigen Testdaten wird zuerst ein
\TeX-Dokument erzeugt und das endg"ultige Layout festgelegt.
Dies k"onnte in unserem einfachen Fall etwa so aussehen:
Dieses File wird nun gesetzt und eventuell so lange
ge"andert, bis das Layout den W"unschen entspricht.
\subsection{2. Schritt: db\TeX-Kommandos einf"ugen}
db\TeX-Kommandos beginnen immer mit einem Prozentzeichen in
der ersten Zeile, gefolgt von einem Ausrufzeichen (oder
einem Underline im Falle von Fortsetzungszeilen). Damit
sind sie f"ur \TeX{} nur gew"ohnliche Kommentare; jedes
db\TeX-Skript ist daher auch ein syntaktisch korrektes
\TeX-Inputfile.
\subsubsection{Musterdaten wegkommentieren}
Zuerst wollen wir angeben, welche Datens"atze nur als Muster
in unserem Skript stehen; dazu f"ugen wir vor diesen den
Befehl {\tt \%!~examples} ein.
\subsubsection{Festlegen der Dateistruktur}
db\TeX{} mu"s wissen, wie die einzulesende Datei in
Datens"atze und jeder Datensatz wiederum in einzelne Felder
aufzugliedern ist. Diese Angaben werden mit dem {\tt
\%!~record}-Befehl gemacht, wobei ein Name f"ur den
Datensatz definiert wird und weiters Zeichenketten, die als
Trennung f"ur Datenfelder (in unserem Fall {\tt \dq$\backslash$n\dq} f"ur
Newline) und Datens"atze dienen. Der vorliegende (Sonder-)Fall von
Datens"atzen, die durch eine Leerzeile getrennt sind, wird
durch den "`leeren"' String {\tt \dq\dq} festgelegt.
Ganz allgemein gilt, da"s f"ur die Definition von Feld- und
Record-Separatoren die selben Konventionen wie in der
Sprache AWK gelten; es handelt sich dabei also jeweils um
dynamische regul"are Ausdr"ucke, so da"s auch ziemlich
komplexe Trennangaben definiert werden k"onnen. F"ur beide
Delimiter gibt es auch Defaultwerte, und zwar {\tt
\dq$\backslash$n\dq} (Zeilenende) f"ur den Recorddelimiter und
{\tt \dq\ \dq} (Leerzeichen oder Tab) f"ur den
Felddelimiter.
\subsubsection{Erstellung eines Templates (Einf"ugeschablone)}
Nun wei"s db\TeX{} zwar, wie die einzulesende Datei zu
gliedern ist, aber noch nicht, in welcher Form diese Daten
in die Ausgabedatei zu stellen sind. Daf"ur mu"s nun eine
Schablone definiert werden, wozu der {\tt
\%!~template}-Befehl dient. Dies ist eine beliebige
Zeichenkette, die f"ur jeden Datensatz in die Ausgabedatei
gestellt wird. Innerhalb dieses Templates k"onnen nun
Platzhalter der Form {\tt \%\it n\tt\%} stehen. Diese
Platzhalter werden durch die entsprechenden Datenfelder
ersetzt, wobei {\it n} der Nummer des Datenfeldes
entspricht. Ein Sonderfall ist die Nummer 0, die f"ur den
{\it gesamten} Datensatz (inkl. der Feldtrennzeichen)
steht. Diese Feldnumerierungskonventionen entsprechen
wiederum der Sprache AWK (dort wird mit {\tt \$\it n} auf
die Felder zugegriffen).
Da Einf"ugemuster unter Umst"anden l"anger sein k"onnen und
mehrere Zeilen beanspruchen k"onnen, sind daf"ur in db\TeX{}
auch Fortsetzungszeilen vorgesehen, die mit der Sequenz
{\tt \%\_} beginnen m"ussen.
\subsubsection{Angabe der zu inkludierenden Datei}
An der richtigen Stelle im Skript (meist nach den
Musterdaten) ist nun anzugeben, welche Datei die zu
inkludierenden Daten enth"alt, wobei hierf"ur der {\tt
\%!~include}-Befehl verwendet wird.
\subsubsection{Der Stand der Dinge bis hierher}
Unser Skript sieht nun nach dem Einf"ugen der bisher
besprochenen Kommandos folgenderma"sen aus:
{\small\begin{verbatim}
\documentstyle[12pt,german]{article}
\title{Meine wichtigsten Adressen von $\cal A-\cal Z$}
\author{}\date{}
\newcommand{\eintrag}[5]{\begin{minipage}{10cm}\begin{flushleft}
{\bf #1}\\
{#2}\\
{#3 (#4)}\\
{\small Tel:} #5\\\vspace{4mm}\end{flushleft}\end{minipage}\par}
\begin{document}\parindent 0pt\raggedbottom
\maketitle
% Struktur von Datei "`adressen": 7 Zeilen pro Record
% 1. Initiale
% 2. Sortierwort
% 3. Name
% 4. Adresse
% 5. PLZ und Ort
% 6. Land
% 7. Telefon
%! record adresse ''\n'' ''''
%! template adresse \eintrag{%3%}{%4%}%
%_ {%5%}{%6%}{%7%}
%! examples
\vspace{5mm}{\Huge A}\par\vspace{5mm}
\eintrag{Name}{Adresse}%
{Ort}{Land}{Telefon}
\eintrag{KPMG Alpen-Treuhand Ges.m.b.H}{Kolingasse 19}%
{1090 Wien}{"Osterreich}{34 36 45}
%! include adressen
\end{document}
\end{verbatim}
}
Wird diese Datei mit db\TeX{} bearbeitet, so werden wir als
Resultat folgende Datei erhalten:
{\small\begin{verbatim}
% dbTeX (1.1.beta) Output generated Tue Feb 12 12:27:11 1991
% dbTeX Input file: adrex1.tex
\documentstyle[12pt,german]{article}
\title{Meine wichtigsten Adressen von $\cal A-\cal Z$}
\author{}\date{}
\newcommand{\eintrag}[5]{\begin{minipage}{10cm}\begin{flushleft}
{\bf #1}\\
{#2}\\
{#3 (#4)}\\
{\small Tel:} #5\\\vspace{4mm}\end{flushleft}\end{minipage}\par}
\begin{document}\parindent 0pt\raggedbottom
\maketitle
% Struktur von Datei "`adressen": 7 Zeilen pro Record
% 1. Initiale
% 2. Sortierwort
% 3. Name
% 4. Adresse
% 5. PLZ und Ort
% 6. Land
% 7. Telefon
%! record adresse ''\n'' ''''
%! template adresse \eintrag{%3%}{%4%}%
%_ {%5%}{%6%}{%7%}
%! examples
%\vspace{5mm}{\Huge A}\par\vspace{5mm}
%\eintrag{Name}{Adresse}%
%{Ort}{Land}{Telefon}
%\eintrag{KPMG Alpen-Treuhand Ges.m.b.H}{Kolingasse 19}%
%{1090 Wien}{"Osterreich}{34 36 45}
%! include adressen
\eintrag{KPMG Alpen-Treuhand Ges.m.b.H}{Kolingasse 19}%
{1090 Wien}{"Osterreich}{34 36 45}
\eintrag{Bente Gaarder Andersen}{The Norwegian Institute of Technology}%
{N-7034 Trondheim}{Norwegen}{+47 7 59 26 95}
\end{verbatim}
\dots
\begin{verbatim}
% (dbTeX) Info: 17 record(s) included from adressen.
\end{document}
% (dbTeX) Info: 29 line(s) input, 17 record(s) included, 0 error(s).
\end{verbatim}
}
\subsection{3. Schritt: Weitere db\TeX-Kommandos einf"ugen}
\subsubsection{Gruppenwechsel bzw. "Uberschriften}
In unserem Beispiel soll vor jedem neuen Anfangsbuchstaben
eine Initiale gedruckt werden. Dies k"onnen wir mit dem in
db\TeX{} vorhandenen Mechanismus zur Behandlung eines
Gruppenwechsels bewerkstelligen. Falls ein {\tt
\%!~break}-Kommando spezifiziert wurde, "uberpr"uft
db\TeX{}, ob sich der Inhalt des dabei spezifizierten
Feldes ge"andert hat. Wenn ja, dann wird dieses Template in
die Ausgabedatei gestellt, wobei Ersetzungen wie bei
gew"ohnlichen Datensatztemplates vorgenommen werden. Bei
diesem Befehl gibt es auch ein optionales Argument; wenn es
(mit einem beliebigen Zeichen) vorhanden ist, dann wird das
"`Breaktemplate"' in jedem Fall auch schon vor dem ersten
Datensatz eingef"ugt (wie es f"ur "Uberschriften auch richtig
ist). Sollen damit aber nur zwischen verschiedenen Gruppen
von Datens"atzen spezielle Einsch"ube erzeugt werden, wird
dieser optionale Parameter einfach ausgelassen.
Im {\tt \%!~break}-Befehl wird neben der Nummer des zu
beobachtenden Datenfeldes auch der Name des zu verwendenden
Templates spezifiziert; es ist daher auch dieses
entsprechende Template im Skript zu definieren.
Die entsprechenden Befehlszeilen, die vor dem {\tt
\%!~include}-Kommando stehen m"ussen, lauten f"ur unser Beispiel:
{\small\begin{verbatim}
%! break 1 initiale +
%! template initiale \pagebreak[3]\vspace{5mm plus 4mm}{\Huge $\cal %1%$}%
%_ \nopagebreak\par\vspace{5mm plus 2mm}\nopagebreak
\end{verbatim}
}
\subsubsection{Zeichenersetzungen}
Ein letztes Problem soll im Rahmen unseres Beispiels noch
behandelt werden: \TeX{} verlangt, da"s gewisse
Sonderzeichen mit einer speziellen Kodierung eingegeben
werden, da diese Zeichen sonst als spezielle Kommandos
interpretiert werden. Dies gilt z.B. f"ur das Dollarzeichen
(Mathematikmodus), das Prozentzeichen (Kommentarbeginn),
Zirkumflex und Unterstreichungsstrich (Hoch- bzw.
Tiefstellung) und so weiter.
Kommen solche Zeichen in den einzuf"ugenden Daten vor,
ergeben sich nat"urlich alle m"oglichen Fehlerquellen. Aus
diesem Grund sind in db\TeX{}
Zeichenersetzungsm"oglichkeiten vorgesehen, und zwar auf
zweierlei Art: zum einen gibt es den {\tt
\%!~change}-Befehl, der ein Zeichen (oder auch eine ganze
Zeichenkette) durch eine andere Zeichenkette ersetzt. Zum
anderen ist es m"oglich, mehrere solcher Ersetzungen in eine
Datei zu schreiben und dann mit dem {\tt
\%!~translate}-Befehl zu veranlassen, da"s eine solche
Ersetzungstabelle geladen wird.
Mit demselben Mechanismus kann man auch 8-bit-ASCII-Zeichen
in die entsprechende \TeX-Konventionen "ubersetzen (also
etwa die deutschen Sonderzeichen im IBM-PC-Zeichensatz).
F"ur unser Beispiel wollen wir zum Ersatz der deutschen
Sonderzeichen die Tabelle {\tt germtex.tbl} laden, die
folgenden Inhalt hat:
{\small\verbatimfile{germtex.tbl}}
Und weiters laden wir eine Tabelle {\tt tex.tbl} folgenden Inhalts:
{\small\verbatimfile{tex.tbl}}
Man beachte, da"s Zeilen, die mit einem {\tt \#}-Zeichen beginnen, als Kommentar
behandelt werden!
Die (vor dem {\tt \%!~include}-Kommando) noch einzuf"ugenden
Zeilen sind daher:
\begin{verbatim}
%! translate germtex.tbl
%! translate tex.tbl
\end{verbatim}
Nach der Bearbeitung mit db\TeX{} sieht dann die Datei
folgenderma"sen aus (und man erzielt mit ihr das gew"unschte Ergebnis):
{\small\begin{verbatim}
% dbTeX (1.1.beta) Output generated Tue Feb 12 15:59:00 1991
% dbTeX Input file: adrex3.tex
\documentstyle[12pt,german]{article}
\title{Meine wichtigsten Adressen von $\cal A-\cal Z$}
\author{}\date{}
\newcommand{\eintrag}[5]{\begin{minipage}{10cm}\begin{flushleft}
{\bf #1}\\
{#2}\\
{#3 (#4)}\\
{\small Tel:} #5\\\vspace{4mm}\end{flushleft}\end{minipage}\par}
\begin{document}\parindent 0pt\raggedbottom
\maketitle
% Struktur von Datei "adressen": 7 Zeilen pro Record
% 1. Initiale
% 2. Sortierwort
% 3. Name
% 4. Adresse
% 5. PLZ und Ort
% 6. Land
% 7. Telefon
%! record adresse "\n"' "`"'
%! template adresse \eintrag{%3%}{%4%}%
%_ {%5%}{%6%}{%7%}
%! break 1 initiale +
%! template initiale \pagebreak[3]\vspace{5mm plus 4mm}{\Huge $\cal %1%$}%
%_ \nopagebreak\par\vspace{5mm plus 2mm}\nopagebreak
%! examples
%\vspace{5mm}{\Huge A}\par\vspace{5mm}
%\eintrag{Name}{Adresse}%
%{Ort}{Land}{Telefon}
%\eintrag{KPMG Alpen-Treuhand Ges.m.b.H}{Kolingasse 19}%
%{1090 Wien}{"Osterreich}{34 36 45}
%! translate germtex.tbl
%! translate tex.tbl
%! include adressen
\pagebreak[3]\vspace{5mm plus 4mm}{\Huge $\cal A$}%
\nopagebreak\par\vspace{5mm plus 2mm}\nopagebreak
\eintrag{KPMG Alpen-Treuhand Ges.m.b.H}{Kolingasse 19}%
{1090 Wien}{"Osterreich}{34 36 45}
\eintrag{Bente Gaarder Andersen}{The Norwegian Institute of Technology}%
{N-7034 Trondheim}{Norwegen}{+47 7 59 26 95}
\end{verbatim}
\dots
\begin{verbatim}
\eintrag{Atominstitut d. "Ost. Hochsch.}{Sch"uttelstra"se}%
{1020 Wien}{"Osterreich}{72 51 36}
\pagebreak[3]\vspace{5mm plus 4mm}{\Huge $\cal B$}%
\nopagebreak\par\vspace{5mm plus 2mm}\nopagebreak
\eintrag{Gwen Bagshaw}{20 Heatherlands, Vicarage Road}%
{Sunbury-on-Thames, Middx TWI6 7QU}{United Kingdom}{0932 -- 787026 }
\eintrag{Nicola Barr}{The Rectory, Cross Ave.}%
{Blackrock, Co.Dublin}{Irland}{00353-1-88 71 18}
\eintrag{Nicola Barr, A.\&L. Goodbody}{1 Earlsfort Centre, Lr. Hatch Street}%
{Dublin 2}{Irland}{(Fax) 00353-1-61 32 78}
\eintrag{Weinschank Binder}{Speckbachergasse}%
{1160 Wien}{"Osterreich}{46 02 30}
\end{verbatim}
\dots
\begin{verbatim}
% (dbTeX) Info: 17 record(s) included from adressen.
\end{document}
% (dbTeX) Info: 34 line(s) input, 17 record(s) included, 0 error(s).
\end{verbatim}
}
\subsection{In diesem Beispiel nicht behandelte Features}
Neben der M"oglichkeit, Zeichenersetzungen "uber Tabellen zu
spezifizieren, kann man ad hoc zu bestimmten
Anwendungsf"allen einzelne Ersetzungen auch "uber den
{\tt \%!~change}-Befehl veranlassen.
Wird beim {\tt \%!~translate}-Befehl anstelle eines
Dateinamens der Parameter {\tt OFF} angegeben, werden alle
zu diesem Zeitpunkt g"ultigen Ersetzungen gel"oscht; damit
ist es m"oglich, in einem Job mehrere unterschiedliche
Ersetzungen zu verwenden.
Beim {\tt \%! record}-Befehl gibt es auch die M"oglichkeit,
anstelle des Identifiers, der das zu verwendende Template
bestimmt, eine numerische Gr"o"se zwischen Prozentzeichen
anzugeben. Dann wird erwartet, da"s in dem Datenfeld mit der
betreffenden Nummer ein String enthalten ist, welcher das
zu verwendende Template angibt. Man kann damit auf
verh"altnism"a"sig einfache Weise datengesteuert verschiedene
Muster innerhalb einer Datei verwenden.
\newpage
\section{Programmdokumentation}
\subsection{Kurzbeschreibung der einzelnen Funktionen}
\subsubsection{Oberste Ebene -- l. 25-49}
Eingabezeilen werden auf eingestreute db\TeX-Kommandos
hin untersucht und ausgegeben; falls es sich um Zeilen nach
einem {\tt \%!~examples}-Befehl handelt, wird ein
Prozentzeichen vorgesetzt, um diese Zeilen auszukommentieren.
\subsubsection{add\_trtbl() -- l. 171-181}
Ein Eintrag wird in eine der beiden intern vorhandenen
Tabellen f"ur die Zeichenersetzung geschrieben: {\tt
std\_tbl} ist die Tabelle f"ur Ersetzungen mittels
entsprechender Tabellendateien, und {\tt usr\_tbl} enth"alt
die mit dem {\tt \%!~change}-Befehl spezifizierten "Ubersetzungen.
\subsubsection{advance() -- l. 140-170}
Diese Funktion ist der Tokenizer des db\TeX-Interpreters;
ihm wird als Argument der erwartete Tokentyp "ubergeben (ID
f"ur Identifier, TEMPLATE f"ur Muster oder STRING f"ur
Zeichenketten). Falls ein entsprechendes Token als n"achstes
in der Variablen {\tt buffer} steht (f"uhrende Leerzeichen
oder Tabs werden "ubersprungen), wird es daraus
entfernt, der Variablen {\tt tok} zugewiesen und die L"ange
des Tokens als R"uckkehrwert zur"uckgeliefert. Wird kein
passendes Token gefunden, wird 0 zur"uckgeliefert.
\subsubsection{console\_msg() -- l. 59-62}
Diese Funktion gibt ihr Argument auf der Konsole aus.
\subsubsection{dbTeX\_command() -- l. 80-140}
Diese Funktion ist daf"ur zust"andig, die einzelnen
db\TeX-Kommandos auszuf"uhren und ist somit die oberste
Ebene f"ur den Fall, da"s ein db\TeX-Befehl erkannt wurde.
F"ur jeden Befehl existiert ein {\tt if}-Block, der die
zu dem entsprechenden Befehl geh"origen Aktionen enth"alt.
\subsubsection{do\_include() -- l. 200-224}
Diese Funktion sit in gewisser Weise die wichtigste; mit
ihrer Hilfe werden die Datens"atze in den Ausgabestrom
"ubernommen. Dabei wird darauf geachtet, ob eine {\tt
break-}Bedingung eintritt (also die Notwendigkeit f"ur einen
Gruppenwechsel) und gegebenenfalls ein entsprechendes
Gruppenwechselmuster geschrieben. Das eigentliche
Inkludieren der Datens"atze wird von {\tt incl\_()} durchgef"uhrt.
\subsubsection{error\_msg() -- l. 63-69}
Diese Funktion schreibt das ihr "ubergebene Argument als
Fehlermeldung sowohl auf die Konsole als auch in die Ausgabedatei.
\subsubsection{incl\_() -- l. 225-236}
Diese Funktion schreibt den aktuellen Datensatz
entsprechend dem Template, welches ihr als Argument
"ubergeben wurde, in den Ausgabestrom.
\subsubsection{info\_msg() -- l. 71-76}
Eine informative Nachricht wird mit dieser Funktion sowohl
auf die Konsole als auch in die Ausgabedatei geshrieben.
\subsubsection{set\_translation() -- l. 181-200}
Mithilfe dieser Funktion wird eine "Ubersetzungstabellendatei
eingelesen und jede darin spezifizierte Ersetzung in die Tabelle {\tt
std\_tbl} aufgenommen; Zeilen, die mit {\tt \#} beginnen,
werden dabei ignoriert, k"onnen also als Kommentar benutzt werden.
Falls anstelle eines Dateinamens {\tt OFF} spezifiziert
wurde, werden alle derzeit g"ultigen Ersetzungen gel"oscht.
\subsubsection{txlate() -- l. 238-245}
Mit dieser Funktion, die von {\tt incl\_} aus aufgerufen
wird, werden die in den Ersetzungtabellen spezifizierten
Zeichenersetzungen auf den "ubergebenen String ausgef"uhrt,
der in enbtsprechend ver"anderter Form schlie"slich wieder
zur"uckgeliefert wird.
%% source code, formatted with TGRIND
\begin{fullpage}
\subsection{AWK-Source von db\TeX}
%{\scriptsize \verbatimfile{dbtex.awk}}
\tgrindfile{dbtexsrc.tex}
\end{fullpage}
\end{document}