Go to the first, previous, next, last section, table of contents.


Textinterpretation und -Ersetzung

Ersetzung durch Environmentvariablen

$NAME
Die Zeichenkette wird durch den Inhalt der Environmentvariablen NAME ersetzt. Der Bezeichner NAME darf dabei nur aus Buchstaben, Ziffern und Unterstrichen bestehen. Ist die Environmentvariable name nicht gesetzt, wird ein Leerstring eingesetzt.
$(NAME)
Wie oben, mit der Ausnahme, dass der Bezeichner NAME auch Sonderzeichen mit Ausnahme der geschlossenen Klammer enthalten darf.

C-aehnliche Escapesequenzen

\0[0-7]+
Ein Backslashs, gefolgt von einer oktalen Zahl (die mit einer 0 zu beginnen hat) wird durch das ASCII-Zeichen ersetzt, dessen Wertigkeit der Zahl entspricht. \0101 wird durch das Zeichen A ersetzt.
\0x[0-9a-fA-F]+
Ein Backslashs, gefolgt von ieiner 0, einem x und hexadezimalen Zahlen, wird durch das ASCII-Zeichen ersetzt, dessen Wertigkeit der Zahl entspricht. 0\x42 wird durch das Zeichen B ersetzt.
\[1-9][0-9]+
Ein Backslash, gefolgt von einer Ziffer zwischen 1 und 9 einschliesslich, sowie optional weiteren Ziffern von 0 bis 9, wird durch das ASCII-Zeichen ersetzt, dessen Wertigkeit der Zahl entspricht. \67 wird durch das Zeichen C ersetzt.
\\
wird durch einen einzelnen Backslash (\) ersetzt
\a
wird durch das Zeichen ersetzt, bei dessen Ausgabe auf ein Terminal ein Ton erklingt (im Klartext: Dies ist das Glockenzeichen, die Bell).
\b
wird durch ein Backspace ersetzt.
\f
wird durch ein Formfeed ersetzt.
\n
wird durch einen Zeilenvorschub ersetzt.
\r
wird durch ein CR, einen Wagenruecklauf ersetzt.
\t
wird durch einen horizontalen Tabulator ersetzt.
\v
wird durch einen vertikalen Tabulator ersetzt.
\$
wird durch ein Dollarzeichen ($) ersetzt.
\~
wird durch eine Tilde (~) ersetzt.

Ersetzung durch Heimatverzeichnisse

~
wird durch das Heimatverzeichnis des Benutzers ersetzt.
Wenn das Heimatverzeichnis /home/uwe ist, dann wird
~ durch /home/uwe ersetzt.
~name
Der Ausdruck wird durch das Heimatverzeichnis des Benutzers mit dem Namen name ersetzt.
~uwe wird durch /home/uwe ersetzt.
~(name)
Der Ausdruck wird durch das Heimatverzeichnis des Benutzers mit dem Namen name ersetzt. Diese Version ist vorzuziehen, wenn name Sonderzeichen enthaelt oder sich direkt daran weitere Zeichen oder Buchstaben anschliessen.
~(uwe)/tmp wird durch /home/uwe/tmp ersetzt.
~~
wird durch eine Tilde (~) ersetzt.

Bedingte Textersetzung

Das $[-Konstrukt ermoeglicht eine Textersetzung in Abhaengigkeit vom Ergebnis einer Bedingung. Die Syntax ist:

    $[bedingung?was-wenn-wahr:was-wenn-falsch]
Der else-Teil der Bedingung darf weggelassen werden:
    $[bedingung?was-wenn-wahr]

bedingung kann sein:

* something==something-else
Das Ergebnis der Bedingung ist wahr, wenn die Interpretationsergebnisse von something und something-else gleich sind.
* something!=something-else
Das Ergebnis der Bedingung ist wahr, wenn die Interpretationsergebnisse von something und something-else ungleich sind.
* something
In diesem Fall ist die Bedingung wahr, wenn das Interpretationsergebnis von something nicht leer ist.

Der Term in den eckigen Klammern wird erst in seine Einzelteile zerlegt, dann erst werden die notwendigen Interpretationen ausgefuehrt. Nicht notwendige Interpretationen (zum Beispiel der else-Teil einer wahren Bedinungen) werden nicht durchgefuehrt.

Einbindung der Textersetzungsroutinen in eigenen Programmen

Der Einsatz der Library erfordert nur geringe Aenderungen am Programm:

Durchfuehrung der Ersetzung

Die Textersetzung wird durch die Routine tip_interpret durchgefuehrt:

Function: size_t tip_interpret
(tip_t *tab, const char *format, char *to, size_t maxlen)

Die Funktion fuehrt die Ersetzung durch. Sie durchsucht den String format zeichenweise. Falls das Zeichen einem magic der Tabelle entspricht oder die nächsten Zeichen einem der magicstrings in der Tabelle entsprechen, wird die assozierte Routine tab->interp aufgerufen. Falls tab->interp nicht zustaendig ist (TIP_NOTDONE zurueckliefert), wird die Tabelle weiter durchsucht.

tip_interpret liefert die die Anzahl der geschriebenen Zeichen ohne das abschliessende '\0', also strlen(to), oder TIP_ERROR, falls ein Fehler auftrat, zurueck.

Die tip_interpret zu uebergebende Tabelle tab wird durch ein Element beendet, dessen magic '\0' und dessen magicstring NULL ist. Der Datentyp ist definiert als:

Datentyp: tip_t
typedef struct
{
    char magicchar;
    const char *magicstring;
    size_t magiclen;
    tip_fn_t interp;
} tip_t;

Die Routine interp wird aufgerufen, falls:

  1. magicchar ungleich '\0' und das nächste Zeichen im zu interpretierenden Text gleich magicchar ist, oder
  2. magicstring ungleich NULL ist und die nächsten magiclen Zeichen im zu interpretierenden Text gleich magicstring sind.

interp wird unter section Ersetzungsunterroutinen: tip_fn_t beschrieben.

tip_t wird niemals einzeln verwendet, sondern immer nur als Array, dessen letztes Element als magic ein '\0' hat und dessen magicstring NULL ist.

Function: char *tip_ainterpret
(tip_t *tab, const char *format)

Die Funktion arbeitet wie tip_interpret, alloziert aber den Speicherbereich für das Ergebnis selbst. Das verwendete Verfahren führt unter Umständen dazu, daß einzelne Interpretationen mehrfach durchgeführt werden.

Ersetzungsunterroutinen: tip_fn_t

Function: size_t tip_function
(const char *this, const char **next, char *to, size_t maxlen)

Die Funktion wird aufgerufen, wenn tip_interpret (siehe section Durchfuehrung der Ersetzung) im format-String ein oder mehrere Zeichen fand, die der tip_function in der Tabelle tab zugeordnet wurden. Sie erhaelt folgende Parameter:

this
zeigt auf das magic im Formatstring.
next
muss auf das naechste zu verarbeitende Zeichen im Eingabestring gesetzt werden, wenn tip_function eine Ersetzung durchfuehren konnte.
to
Ab dieser Position soll das Ergebnis abgelegt werden.
maxlen
Maximale Groesse des Ergebnisstrings. Bei Ueberschreitung ist TIP_ERROR zurueckzuliefern.

Returncodes:

* TIP_NOTDONE
Die Funktion ist nicht aktiv geworden. tip_interpret soll versuchen, andere Routinen zu finden.
* TIP_ERROR
Ein Fehler ist aufgetreten, tip_interpret soll abbrechen.
* Zahl
Die Laenge des aus der Ersetzung hervorgegangenen Strings ohne die abschliessende 0.

Wird eine Ersetzung durchgefuehrt, ist der String mit einer 0 abzuschliessen.

Standardersatzroutinen der Library

Folgende Ersatzroutinen enthaelt die Library:

* tip_dollar
Ersetzung durch Environmentvariablen, erwartet als magic das Zeichen $. Siehe section Ersetzung durch Environmentvariablen.
* tip_tilde
Ersetzung durch Heimatverzeichnisse. Siehe section Ersetzung durch Heimatverzeichnisse fuer eine Beschreibung der vorgenommenen Ersetzungen. Die Funktion erwartet als magic das Zeichen ~. Bei Einsatz von tip_tilde ist Vorsicht geboten. Die Zugriffe auf die Passwortdatei, die notwendig sind, um das Heimatverzeichnis feststellen zu können, geschehen mit Hilfe der Funktionen getpwuid und getpwnam, und verstellen daher den Dateizeiger saemtlicher `/etc/passwd' mit Hilfe der Routinen aus <pwd.h> lesender oder schreibender Funktionen. Bei Aufruf von tip_deinit wird endpwent aufgerufen, falls tip_tilde vorher aufgerufen worden ist.
* tip_backslash
Ersetzung durch C-aehnliche Escapesequenzen. Siehe section C-aehnliche Escapesequenzen fuer eine Aufstellung der verstandenen Esacpecodes. Die Funktion erwartet als magic das Zeichen \\.
* tip_conditional
Die Bedingungen sind dadurch realisiert. Siehe section Bedingte Textersetzung. Als magicstring wird $[ erwartet. Die Bedinungen muß außerdem mit einem ] abgeschlossen werden.
* tip_strip
Eine Funktion, die ihren Parameterstring von führenden und abschließenden Leerzeichen und Tabs befreit. Der Parameterstring wird vor der Kürzung interpretiert. Als magicstring wird ${strip erwartet. Der Ausdruck muß außerdem mit einem } abgeschlossen werden. Die Funktion kann als Beispiel für eigene Funktionen dienen.
* tip_macro
Die Funktion setzt den Wert des ihr übergebenen Makros ein. Ist das Makro nicht definiert, wird undefined eingesetzt. Der Ausdruck muß mit einem } abgeschlossen werden. Das Beispiel setzt den Inhalt des Makros test ein.
	${macro test}
* tip_defmacro macroname value
Die Funktion setzt value als Wert des Makros macroname ein. Der Ausdruck muß mit einem } abgeschlossen werden. Fehlt value, wird ein leerer String als Wert eingesetzt. Das Beispiel setzt das Makro test auf hallo:
	${defmacro test hallo}
tip_defmacro ist über die Funktion tip_defmacro_intern realisiert, siehe section Definition und Nutzung von Makros.
* tip_undefmacro macroname
löscht den Wert des Makros mit dem Namen macroname. Es ist kein Fehler, wenn macroname gar nicht definiert ist (sprich: man kann ein Makro so oft löschen, wie man will).
* tip_literal
Die Funktion setzt ihre Argumente ein, ohne sie zu interpretieren. Der Ausdruck muß mit einem } abgeschlossen werden. Der Scanner, der nach der abschliessenden Klammer sucht, ist recht empfindlich, und verlangt, daß der Parameterstring der Syntax der Interpretationsroutinen genügt. Das Beispiel setzt einen einzelnen $ ein, ist also eine aufwendigere Schreibweise für \$:
	${literal %}
* tip_force
Die Funktion interpretiert die Parameterstring zweimal. Der Ausdruck muß mit einem } abgeschlossen werden. Das Beispiel zeigt, wie man aus vier Backslashs einen machen kann: Das Beispiel setzt den Inhalt des Makros test ein.
	${force \\\\}

Definition und Nutzung von Makros

Makros dienen als Schreiberleichterung. Sie behalten ihren Inhalt bis sie gelöscht werden oder das Programm endet.

Es gibt zwei Arten, Makros einen Wert zuzuweisen:

  1. tip_defmacro Diese Routine wird von defmacro aufgerufen, kann also benutzt werden, um aus einer interpretierten Datei heraus einen Makrowert zu setzen.
  2. tip_defmacro_intern Diese Funktion kann aus C-Programmen benutzt werden. intern bezieht sich darauf, daß ihr Aufruf in das Programm eincodiert werden muß.

Es gibt zwei Arten, ein Makros zu löschen:

  1. tip_undefmacro Diese Routine wird von der Interpretationsfunktion undefmacro aufgerufen, kann also benutzt werden, um aus einer interpretierten Datei heraus ein Makro zu löschen.
  2. tip_defmacro_intern Erhält diese Funktion als Wert einen Nullpointer übergeben, wird das Makro gelöscht.

Ein Makro kann auch einen leeren Wert haben.

Beide Arten, eine Makro zu definieren oder zu löschen sind identisch und arbeiten auf derselben Datenbasis.

Function: char *tip_defmacro_intern
(const char *varname, const char *value)

Mit dieser Funktion kann man aus einem C-Programm heraus ein Makro auf einen Wert setzen (value != NULL) oder ein Makro löschen (value == NULL).

Initialisierung und Deinitialisierung der Library

Function: int tip_init()
Initialisiert die Library. Zur Zeit Dummyfunktion. Liefert 0 bei Erfolg, sonst einen Wert ungleich 0.

Function: int tip_deinit()
Deinitialisiert die Library. Zur Zeit ruft sie nur endpwent auf, und auch nur, falls tip_tilde eine der Routinen aus <pwd.h> benutzt hat. Liefert 0 bei Erfolg, sonst einen Wert ungleich 0.

Beispiel fuer den Einsatz der Routinen in eigenen Programmen

static size_t my_tip_prozent(const char *this, const char **next,
    char *to, size_t maxlen);

tip_t tab[]=
{
	{'$',tip_dollar},
	{'\\',tip_backslash},
	{'%',my_tip_prozent},
	{0,NULL},
};

static void mylog(const char *format);

static size_t my_tip_prozent(const char *this, const char **next,
    char *to, size_t maxlen)
{
	char buf[128];
	time_t t;
	size_t l;
	switch(this[1])
	{
	case 't': /* %t -> Ausgabe von ctime() ohne \n */
		if (maxlen<25) /* strlen(ctime) */
			return TIP_ERROR;
		time(&t);
		strcpy(to,ctime(&t));
		*strchr(to,'\n')=0;
		return 24;
	case 'p': /* %p -> pid */
		sprintf(buf,"%ld",(long) getpid());
		l=strlen(buf);
		if (l+1>maxlen)
			return TIP_ERROR;
		strcpy(to,buf);
		return l;
	}
	return TIP_NOTDONE;
};

extern FILE *logfile;

static void mylog(const char *format)
{
	char buf[4096];
	if (tip_interpret(tab,format,buf,sizeof(buf))!=TIP_ERROR)
		fprintf(logfile,"%s\n",buf);
}


Go to the first, previous, next, last section, table of contents.