Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Einleitung
2 Die Installation
3 Erste Schritte
4 Linux als Workstation für Einsteiger
5 Der Kernel
6 Die Grundlagen aus Anwendersicht
7 Die Shell
8 Reguläre Ausdrücke
9 Konsolentools
10 Die Editoren
11 Shellskriptprogrammierung mit der bash
12 Die C-Shell
13 Benutzerverwaltung
14 Grundlegende Verwaltungsaufgaben
15 Netzwerkgrundlagen
16 Anwendersoftware für das Netzwerk
17 Netzwerkdienste
18 Mailserver unter Linux
19 LAMP
20 DNS-Server
21 Secure Shell
22 Die grafische Oberfläche
23 Window-Manager und Desktops
24 X11-Programme
25 Multimedia und Spiele
26 Prozesse und IPC
27 Bootstrap und Shutdown
28 Dateisysteme
29 Virtualisierung und Emulatoren
30 Softwareentwicklung
31 Crashkurs in C und Perl
32 Einführung in die Sicherheit
33 Netzwerksicherheit überwachen
A Lösungen zu den einzelnen Aufgaben
B Kommandoreferenz
C X11-InputDevices
D MBR
E Die Buch-DVDs
F Glossar
G Literatur
Stichwort

Download:
- ZIP, ca. 15,7 MB
Buch bestellen
Ihre Meinung?

Spacer
 <<   zurück
Linux von Johannes Pl&ouml;tner, Steffen Wendzel
Das umfassende Handbuch
Buch: Linux

Linux
geb., mit 2 DVDs
1302 S., 39,90 Euro
Galileo Computing
ISBN 978-3-8362-1704-0
Pfeil 30 Softwareentwicklung
  Pfeil 30.1 Interpreter und Compiler
    Pfeil 30.1.1 C und C++
    Pfeil 30.1.2 Perl
    Pfeil 30.1.3 Java
    Pfeil 30.1.4 Tcl
    Pfeil 30.1.5 Was es sonst noch gibt
  Pfeil 30.2 Shared Libraries
    Pfeil 30.2.1 Vorteile der Shared Libraries
    Pfeil 30.2.2 Statisches Linken
    Pfeil 30.2.3 Die Dateien
  Pfeil 30.3 Debugging
    Pfeil 30.3.1 Vorbereitung
    Pfeil 30.3.2 Konsolenarbeit
    Pfeil 30.3.3 ddd
  Pfeil 30.4 Profiling
    Pfeil 30.4.1 Compiler-Option
    Pfeil 30.4.2 gprof verwenden
    Pfeil 30.4.3 Profiling-Daten lesen
  Pfeil 30.5 Tracing
  Pfeil 30.6 Hilfe beim Finden von Bugs
    Pfeil 30.6.1 ProPolice
    Pfeil 30.6.2 flawfinder und RATS
    Pfeil 30.6.3 Electric Fence
  Pfeil 30.7 Integrierte Entwicklungsumgebungen
  Pfeil 30.8 make
    Pfeil 30.8.1 Makefile
    Pfeil 30.8.2 Makefile-Makros
    Pfeil 30.8.3 Shellvariablen in Makefiles
    Pfeil 30.8.4 Einzelne Targets übersetzen
    Pfeil 30.8.5 Spezielle Targets
    Pfeil 30.8.6 Tipps im Umgang mit make
  Pfeil 30.9 Die GNU Autotools
  Pfeil 30.10 lex/flex und yacc/bison
    Pfeil 30.10.1 flex grundlegend anwenden
    Pfeil 30.10.2 bison/yacc grundlegend anwenden
  Pfeil 30.11 Unix-Software veröffentlichen
    Pfeil 30.11.1 Wichtige Dateien
  Pfeil 30.12 Manpages erstellen
    Pfeil 30.12.1 groff nutzen
    Pfeil 30.12.2 Die Manpage installieren
  Pfeil 30.13 Versionsmanagement
    Pfeil 30.13.1 CVS
    Pfeil 30.13.2 Subversion
  Pfeil 30.14 Wichtige Bibliotheken
    Pfeil 30.14.1 Entwicklung grafischer Oberflächen
    Pfeil 30.14.2 Weitere Bibliotheken
  Pfeil 30.15 Zusammenfassung
  Pfeil 30.16 Aufgaben


Galileo Computing - Zum Seitenanfang

30.10 lex/flex und yacc/bison  Zur nächsten ÜberschriftZur vorigen Überschrift

Für den anspruchsvollen angehenden Profi-Programmierer seien in diesem Kapitel auch noch einige Sätze zu den Tools flex und yacc gesagt. lex (unter Linux in der Regel flex) ist ein Tool zur lexikalischen Analyse, yacc und das ähnliche Tool bison sind zur syntaktischen Analyse gedacht.

flex, lex

Bei der lexikalischen Analyse wird eine Eingabe, wie zum Beispiel eine Quellcode- oder Konfigurationsdatei, in einzelne Bestandteile, sogenannte Tokens zerlegt. Dabei werden Muster erkannt und als Token X identifiziert. Diese Muster werden bei flex und lex in Form von regulären Ausdrücken angegeben. Der Input-String sqrt(2); beispielsweise würde in einen Funktionsnamen (sqrt), eine geöffnete Klammer, einen Integerwert (2), eine geschlossene Klammer und ein Semikolon zerlegt werden.

yacc, Bison

Bei der Syntax-Analyse hingegen werden die einzelnen Token in ihrer Anwendungsreihenfolge (Syntax-Regel) einer Prüfung unterzogen. Die Syntax kann beispielsweise regeln, dass hinter einem Funktionsnamen beim Aufruf eine geöffnete Klammer stehen soll, auf die dann die Funktionsparameter durch Kommas separiert folgen sollen usw.

Wir können leider nicht bis ins letzte Detail auf die Anwendung beider Tools eingehen – dazu wäre ein eigenes Buch notwendig –, sondern legen nur die wichtigsten Grundlagen für das Arbeiten mit flex und bison. Als hervorragende weiterführende Literatur empfiehlt sich [Herold03B]. Dieses Buch behandelt zwar nicht bison, aber dafür yacc in aller Ausführlichkeit.


Galileo Computing - Zum Seitenanfang

30.10.1 flex grundlegend anwenden  Zur nächsten ÜberschriftZur vorigen Überschrift

Ein flex-Skript gliedert sich in drei Teile, die jeweils durch eine Zeile, in der nur die Zeichen %% stehen, unterteilt werden. Im oberen Teil wird C-Code definiert, der Variablen, Funktionsprototypen und Ähnliches enthält, die später zur Verfügung stehen sollen. Im mittleren Teil werden die Muster für Tokens definiert und im unteren Teil werden C-Funktionen implementiert. Die Verwendung des oberen und unteren Skriptteils ist optional.

Soll zum Beispiel mithilfe von flex ein simpler Taschenrechner realisiert werden, der Addition und Subtraktion durchführen kann, so würde man ein Token für die Addition, eines für die Subtraktion und eines für die Zahlen benötigen. In flex umgesetzt, könnte dies wie folgt aussehen:

%{
#include <stdio.h>
#define TOK_ADD 0x01
#define TOK_SUB 0x02
#define TOK_NUM 0x03
int tmpv=0;
int token;
%}
%%
\+       { return TOK_ADD; }
-        { return TOK_SUB; }
[0-9]+   { tmpv=atoi(yytext); }
[\n\t ]+       {}
%%
int main ()
{
int value=0;
  while(token=yylex()) {
switch(token) {
case TOK_ADD:
value+=tmpv;
break;
case TOK_SUB:
value-=tmpv;
break;
}
tmpv=0;
printf("\t -> %i\n", value);
}
}

Listing 30.57  calc.l

Zunächst haben wir, eingebettet in %{ und %}, den C-Code für den oberen Teil des flex-Programms festgelegt. Dort binden wir für die spätere Nutzung die Datei stdio.h ein und vergeben mit der Präprozessor-Anweisung define drei Token-Werte.

Im Muster-Teil des Programms wird festgelegt, welche Aktionen durchgeführt werden sollen, wenn ein bestimmtes Muster auftritt. Beachten Sie, dass wir das Plus-Zeichen escaped haben, damit es nicht als »mindestens ein Vorkommen eines Zeichens« im regulären Ausdruck interpretiert wird. Falls Sie das Kapitel 8 zu regulären Ausdrücken nur überflogen oder bereits vergessen haben, sollten Sie es vor der Nutzung von flex nochmals durchlesen.

Die jeweilige Anweisung, die durchzuführen ist, wird durch Leerzeichen vom Muster getrennt und im Optimalfall in geschweifte Klammern eingebettet. Verwendet man nur eine einzelne Anweisung, kann man diese geschweiften Klammern jedoch auch weglassen.


Um keine Probleme mit der Eingabe einer neuen Zeile zu bekommen, fangen wir durch die Regel »\n { }« das Newline-Zeichen ab und führen einfach gar keine Anweisung dafür aus.


Im Schlussteil holen wir uns über die Funktion yylex() das jeweilige Token und verarbeiten es in einer Schleife.

Übersetzen

Um aus diesem Code nun ein ausführbares Programm zu generieren, muss flex (bzw. lex) zunächst den entsprechenden Quellcode für das Parsen der Texteingabe generieren. Dazu ruft man flex mit der jeweiligen Quelldatei auf – in unserem Fall heißt sie calc.l.

$ flex calc.l

Listing 30.58  C-Quellcode erstellen

Die nun erstellte Datei nennt sich – sofern man das Programm nicht explizit zu einer anderen Benennung anweist – lex.yy.c, ist in unserem Fall 36 KB groß und besteht aus 1550 Zeilen Quellcode. Es ist nicht sonderlich wichtig zu wissen, was flex dort im Detail generiert, wichtig ist nur, dass es den Code für Sie generiert, ohne dass Sie es selbst tun müssen, und dass es funktioniert. In diesem Fall muss dies tatsächlich nicht als schlampige Programmierung gelten. Bei großen Projekten generiert flex nämlich durchaus mal einige Zehntausend Zeilen an Quellcode, die sich bei jeder Übersetzung verändern – viel Spaß bei der Fehlersuche.

$ du -h lex.yy.c
36.0K   lex.yy.c
$ wc -l lex.yy.c
1550 lex.yy.c

Listing 30.59  lex.yy.c

Nun muss der Quellcode mit dem C-Compiler übersetzt werden, und anschließend können wir das fertige Programm testen. Dazu muss die Flex-Library eingelinkt werden. Unter Linux geschieht dies mit -lfl, unter BSD mit -ll:

$ gcc -o calc lex.yy.c -lfl
$ ./calc
100
+
-> 100
3
-
-> 97
96
-
-> 1
99
+
-> 100
^D

Listing 30.60  Übersetzen und Linken


Galileo Computing - Zum Seitenanfang

30.10.2 bison/yacc grundlegend anwenden  topZur vorigen Überschrift

Kommen wir nach diesem kleinen Einblick in flex/lex zur syntaktischen Analyse mittels bison. Dabei wird der Quellcode des Beispiels, das wir an dieser Stelle einbringen werden, auch für yacc anwendbar sein.

Ein bison-Programm ist ähnlich aufgebaut wie ein flex-Programm. Die von flex generierten Tokens werden dabei im Mittelteil über das Keyword %token eingebunden:

%token TOK_ADD
%token TOK_SUM
%token TOK_NUM

Listing 30.61  %token

Im unteren Programmteil werden die syntaktischen Möglichkeiten definiert. Zunächst kümmert man sich darum, dass mehrere Kommandos hintereinander stehen können. Anschließend wird definiert, welche möglichen Syntaxkombinationen es gibt. Bei uns heißen die Kombinationen add und sub.

commands: /**/ | commands command;
command:  add | sub;

Listing 30.62  commands

Nun wird jedes einzelne Kommando genau definiert. Dies beinhaltet die Aneinanderreihung von Tokens, die diesem Kommando entsprechen, und die entsprechend auszuführenden Aktionen.

add:
TOK_NUM TOK_ADD TOK_NUM
{
printf("\t->%i\n", vtmp1+vtmp2);
};
sub:
TOK_NUM TOK_SUB TOK_NUM
{
printf("\t->%i\n", vtmp1-vtmp2);
};

Listing 30.63  add und sub

Mit diesem Quellcode wird definiert, dass wir die Token-Reihenfolgen Zahl + Zahl und Zahl – Zahl abdecken.

Wie Sie vielleicht bemerkt haben, verwenden wir die Variablen vtmp1 und vtmp2. In diesen müssen jeweils die letzten zwei vom Benutzer eingegebenen Zahlenwerte hinterlegt sein, was sich beispielsweise folgendermaßen lösen lässt:

%%
[0-9]+   { vtmp1=vtmp2;
vtmp2=atoi(yytext);
return TOK_NUM;
}

Listing 30.64  An vtmp1 und vtmp2 kommen

Des Weiteren muss nun in der Main-Funktion im flex-Code der bison-Mainloop aufgerufen werden, was durch einen einfachen Aufruf von yyparse(); geschieht.

Übersetzen

Nun muss zunächst mit lex die Datei calc.l und anschließend mit bison die calc.y in C-Code umgewandelt werden. Daraufhin kann mit dem gcc alles zusammengelinkt werden.

$ flex calc.l
$ bison calc.y --output-file=calc.tab.c
$ gcc -o lex.yy.c calc.tab.c -ll

Listing 30.65  Code erzeugen und compilieren



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






 <<   zurück
  Zum Katalog
Zum Katalog: Linux, Ausgabe 2011






Linux, Ausgabe 2011
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Linux-Server






 Linux-Server


Zum Katalog: Linux Hochverfügbarkeit






 Linux Hoch-
 verfügbarkeit


Zum Katalog: LPIC-1






 LPIC-1


Zum Katalog: Debian GNU/Linux






 Debian GNU/Linux


Zum Katalog: openSUSE 11.2






 openSUSE 11.2


Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Ubuntu GNU/Linux






 Ubuntu GNU/Linux


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 2011
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de