<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<!--
     The FreeBSD Documentation Project
     The FreeBSD German Documentation Project

     $FreeBSD$
     $FreeBSDde: de-docproj/books/developers-handbook/tools/chapter.sgml,v 1.11 2011/05/12 17:36:17 bcr Exp $
     basiert auf: 1.52
-->

<chapter id="tools">
  <chapterinfo>
    <authorgroup>
      <author>
	<firstname>James</firstname>
	<surname>Raynard</surname>
	<contrib>Contributed by </contrib>
      </author>
      <author>
	<firstname>Murray</firstname>
	<surname>Stokely</surname>
      </author>
    </authorgroup>
    <authorgroup>
      <author>
	<firstname>Dirk</firstname>
	<surname>Arlt</surname>
	<contrib>Übersetzt von </contrib>
      </author>
      <author>
	<firstname>Fabian</firstname>
	<surname>Borschel</surname>
      </author>
    </authorgroup>
  </chapterinfo>

  <title>Werkzeuge zur Programmierung</title>

  <sect1 id="tools-synopsis">
    <title>Überblick</title>

    <para>Dieses Kapitel ist eine Einführung in die Benutzung
      einiger der Werkzeuge zur Programmierung die mit FreeBSD
      ausgeliefert werden. Trotzdem ist vieles auch auf verschiedene
      andere Versionen von &unix; übertragbar. Dieses Kapitel
      soll <emphasis>kein</emphasis> Versuch sein Programmierung
      detailliert zu beschreiben. Der größte Teil dieses
      Kapitels setzt wenige oder gar keine Programmierkenntnisse
      voraus, dennoch sollten die meisten Programmierer etwas
      Sinnvolles darin finden.</para>
  </sect1>

  <sect1 id="tools-intro">
    <title>Zusammenfassung</title>

    <para>FreeBSD bietet eine exzellente Entwicklungsumgebung.
      Compiler für C und C++, sowie ein Assembler sind im
      Basissystem enthalten. Natürlich finden
      sich auch klassische &unix;-Werkzeuge wie <command>sed</command>
      und <command>awk</command>.  Sollte das nicht genug sein, finden sich
      zahlreiche weitere Compiler und Interpreter in der Ports-Sammlung.
      Der folgende Abschnitt, <link
      linkend="tools-programming">Einführung in die Programmierung</link>,
      zählt ein paar der verfügbaren Optionen auf.  FreeBSD ist
      kompatibel zu vielen Standards wie <acronym>&posix;</acronym>
      und <acronym>ANSI</acronym> C, sowie zu seinem eigenen BSD Erbe. So
      ist es möglich Anwendungen zu schreiben, welche ohne oder
      zumindest ohne wesentliche Änderungen auf einer
      großen Zahl an Plattformen kompilieren und laufen
      werden.</para>

    <para>Allerdings können all diese Möglichkeiten
      anfangs etwas überwältigend sein, wenn Sie vorher nie
      Programme auf einem &unix;-System geschrieben haben. Dieses
      Dokument hat die Zielsetzung ihnen beim Einstieg zu helfen ohne
      allzu weit in fortgeschrittene Themen vorzudringen. Die
      Intention ist, daß dieses Dokument ihnen ausreichend
      Basiswissen vermittelt und die weitergehende Dokumentation
      sinnvoll nutzen zu können.</para>

    <para>Der größte Teil dieses Dokuments erfordert wenige
      oder gar keine Kenntnisse in der Programmierung, es werden
      trotzdem Basiswissen im Umgang mit &unix; und die Bereitschaft
      zu lernen vorausgesetzt!</para>
  </sect1>

  <sect1 id="tools-programming">
    <title>Einführung in die Programmierung</title>

    <para>Ein Programm ist eine Zusammenstellung von Anweisungen, die
      den Computer auffordern verschiedenste Dinge zu tun. Dieser
      Abschnitt gibt ihnen einen Überblick über die beiden
      wesentlichen Methoden diese Anweisungen oder
      <quote>Befehle</quote>, wie man diese Anweisungen
      üblicherweise nennt, zu geben. Die eine Methode nutzt einen
      <firstterm>Interpreter</firstterm>, die andere einen
      <firstterm>Compiler</firstterm>. Da menschliche Sprachen
      für einen Computer nicht unmissverständlich sind,
      werden diese Befehle in einer Sprache geschrieben die speziell
      für diesen Zweck gedacht ist.</para>

    <sect2>
      <title>Interpreter</title>

      <para>Mit einem Interpreter ist die Sprache vielmehr eine
	Umgebung, in der Sie ein Kommando an der Kommandozeile
	eingeben welches dann von der Umgebung ausgeführt wird.
	Für kompliziertere Programme können Sie die Befehle
	in eine Datei schreiben und den Interpreter dazu bringen diese
	Datei zu laden und die enthaltenen Befehle auszuführen.
	Falls etwas schief geht werden viele Interpreter Sie an einen
	Debugger weiterleiten.</para>

      <para>Der Vorteil hierbei ist, das Sie das Ergebnis ihres
	Befehls direkt sehen und Fehler sofort korrigiert werden
	können. Der größte Nachteil bei dieser Methode
	entsteht, wenn Sie ihr Programm mit jemandem teilen wollen.
	Diese Person muss den selben Interpreter nutzen wie Sie es tun
	und Sie muss wissen wie dieser zu bedienen ist.
	Zudem werden Benutzer es nicht begrüßen sich in
	einem Debugger wiederzufinden, wenn Sie einmal die falsche
	Taste drücken! Bei einem Blick auf die
	Leistungsfähigkeit brauchen Interpreter oftmals viel
	Speicher und erzeugen den Code nicht so effizient wie
	Compiler.</para>

      <para>Meiner Meinung nach sind interpretierte Sprachen der beste
	Anfang, wenn Sie bisher noch nicht programmiert haben. Diese
	Art von Umgebung findet man typischerweise bei Sprachen wie
	Lisp, Smalltalk, Perl und Basic. Man könnte auch sagen,
	dass die &unix; Shell (<command>sh</command>,
	<command>csh</command>) für sich bereits einen
	Interpreter darstellt und viele Leute schreiben
	tatsächlich Shell <quote>Scripten</quote> um sich bei
	einigen <quote>Haushaltsaufgaben</quote> auf ihren Maschinen
	helfen zu lassen. Tatsächlich war es ein wesentlicher
	Teil der originalen &unix; Philosophie eine große Zahl
	an kleinen Hilfsprogrammen zur Verfügung zu stellen,
	welche mittels eines Shellskripts miteinander kombiniert werden
	um bestimmte Aufgaben zu übernehmen.</para>
    </sect2>

    <sect2>
      <title>Für FreeBSD verfügbare Interpreter</title>

      <para>Im folgenden eine Liste der über die &os;
	Ports-Sammlung verfügbaren Interpreter
	einschließlich einer kurzen Erörterung der
	populären interpretierten Sprachen.</para>

      <para>Anleitungen wie man Anwendungen aus der Ports-Sammlung
	erhält und installiert können Sie dem Kapitel <ulink
	url="&url.books.handbook;/ports-using.html">Benutzen der
	Ports-Sammlung</ulink> aus dem FreeBSD Handbuch
	entnehmen.</para>

      <variablelist>
	<varlistentry>
	  <term><acronym>BASIC</acronym></term>

	  <listitem>
	    <para>Kurz für Beginner's All-purpose Symbolic
	      Instruction Code. Entwickelt in den 50er Jahren um
	      Studenten in Programmierung zu unterrichten, wurde
	      <acronym>BASIC</acronym> in den 80er Jahren mit jedem
	      anständigen Personal Computer ausgeliefert und war
	      für viele Programmierer die erste
	      Programmiersprache. <acronym>BASIC</acronym> ist auch
	      die Grundlage für Visual Basic.</para>

	    <para>Der Bywater Basic Interpreter findet sich in der
	      Ports-Sammlung unter <filename
	      role="package">lang/bwbasic</filename> und Phil
	      Cockroft's Basic Interpreter (auch bekannt als Rabbit
	      Basic) findet sich unter <filename
	      role="package">lang/pbasic</filename>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Lisp</term>

	  <listitem>
	    <para>Diese Sprache wurde in den späten 50er Jahren
	      als Alternative zu den, zu dieser Zeit populären,
	      <quote>zahlenverarbeitenden</quote> Sprachen entwickelt.
	      Anstelle auf Zahlen basiert Lisp auf Listen;
	      tatsächlich ist der Name Lisp eine Kurzform
	      für <quote>List Processing</quote> (Listen
	      abarbeiten). Sehr populär fü
	      <acronym>AI</acronym> (Artificial Intelligence/
	      künstliche Intelligez) (Fach-) Kreisen.</para>

	    <para>Lisp ist eine extrem kraftvolle und durchdachte
	      Sprache, kann aber auch recht groß und unhandlich
	      sein.</para>

	    <para>Zahlreiche Ausformungen von Lisp, die auf &unix;
	      Systemen laufen sind über die Ports-Sammlung
	      verfügbar. GNU Common Lisp befindet sich in
	      <filename role="package">lang/gcl</filename>. CLISP von
	      Bruno Haible und Michael Stoll ist in <filename
	      role="package">lang/clisp</filename> zu finden. Für
	      CMUCL, welches auch einen hoch-optimierten Compiler
	      enthält, oder einfachere Ausformungen wie SLisp,
	      das die meisten gängigen Lisp Konstrukte in wenigen
	      hundert Zeilen C Code enthält sind in <filename
	      role="package">lang/cmucl</filename> und <filename
	      role="package">lang/slisp</filename> ebenfalls
	      enthalten.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Perl</term>

	  <listitem>
	    <para>Unter Systemadministratoren zum Schreiben von
	      Skripten sehr beliebt; wird häufig auch auf World
	      Wide Web Servern verwendet, um
	      <acronym>CGI</acronym>-Skripte zu schreiben.</para>

	    <para>Perl ist in der Ports-Sammlung unter <filename
	      role="package">lang/perl5.8</filename> für alle
	      &os;-Versionen verfügbar, und wird im Basissystem
	      von 4.x als <command>/usr/bin/perl</command>
	      installiert.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Scheme</term>

	  <listitem>
	    <para>Ein Dialekt von Lisp, der kompakter und sauberer
	      als Common Lisp ist. Dieser Dialekt ist an
	      Universitäten sehr beliebt, da er zum einen
	      für den Unterricht im Grundstudium einfach genug
	      ist, und zum anderen ein ausreichend hohes
	      Abstraktionsniveau für den Einsatz in der Forschung
	      bietet.</para>

	    <para>Scheme ist in der Ports-Sammlung in Form des Elk
	      Scheme Interpreters als <filename
	      role="package">lang/elk</filename> verfügbar. Den
	      MIT Scheme Interpreter findet man unter <filename
	      role="package">lang/mit-scheme</filename>, und den SCM
	      Scheme Interpreter unter <filename
	      role="package">lang/scm</filename>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Icon</term>

	  <listitem>
	    <para>Icon ist eine Hochsprache mit ausgereiften
	      Möglichkeiten zur Verarbeitung von Zeichenketten
	      und Strukturen. Die unter &os; verfügbare Version
	      von Icon steht in der Ports-Sammlung unter <filename
	      role="package">lang/icon</filename> zur
	      Verfügung.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Logo</term>

	  <listitem>
	    <para>Logo ist eine leicht zu erlernende
	      Programmiersprache, welche in vielen Kursen als
	      einführende Programmiersprache gewählt wird.
	      Sie ist ein ideales Arbeitswerkzeug beim Unterricht mit
	      jungen Menschen, da mit ihr die Erstellung komplizierter
	      geometrischer Oberflächen selbst für kleine
	      Kinder einfach ist.</para>

	    <para>Die für &os; aktuellste, verfügbare
	      Version findet man in der Ports-Sammlung unter <filename
	      role="package">lang/logo</filename>.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Python</term>

	  <listitem>
	    <para>Python ist eine objektorientierte, interpretierte
	      Programmiersprache. Die Verfechter von Python
	      argumentieren, daß sie eine der besten
	      Programmiersprachen für Programmieranfänger
	      sei, da sie einfach zu erlernen ist, und anderen
	      populären interpretierten Programmiersprachen,
	      welche zur Entwicklung großer und komplexer
	      Anwendungen verwendet werden, in nichts nachsteht (Perl
	      und Tcl sind zwei solcher bekannten
	      Programmiersprachen).</para>

	    <para>Die aktuellste Version von Python ist in der
	      Ports-Sammlung unter <filename
	      role="package">lang/python</filename>
	      verfügbar.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Ruby</term>

	  <listitem>
	    <para>Ruby ist eine interpretierte und rein
	      objektorientierte Programmiersprache. Sie wurde wegen
	      ihrer leicht verständlichen Syntax, ihrer
	      Flexibilität und der Möglichkeit, große und
	      komplexe Programme einfach zu entwickeln und zu pflegen,
	      populär.</para>

	    <para>Ruby ist in der Ports-Sammlung unter <filename
	      role="package">lang/ruby18</filename>
	      verfügbar.</para>
	  </listitem>
	</varlistentry>

	<varlistentry>
	  <term>Tcl und Tk</term>

	  <listitem>
	    <para>Tcl ist eine einbettbare, interpretierte
	      Programmiersprache, welche aufgrund ihrer Portierbarkeit
	      auf viele unterschiedliche Plattformen eine weite
	      Verbreitung erfahren hat. Sie kann sowohl für die
	      schnelle Entwicklung kleinerer Prototypen, als auch (in
	      Verbindung mit Tk, einem GUI Toolkit) vollwertiger,
	      ausgereifter Programme verwendet werden.</para>

	    <para>Es sind mehrere Versionen von Tcl als Ports
	      für &os; verfügbar. Die aktuellste Version,
	      Tcl 8.5, ist unter <filename
	      role="package">lang/tcl85</filename>
	      verfügbar.</para>
	  </listitem>
	</varlistentry>
      </variablelist>
    </sect2>

    <sect2>
      <title>Compiler</title>

      <para>Compiler sind eher anders. Zuerst schreibt man seinen
	Code unter Verwendung eines Editors in eine Datei (oder
	mehrere Dateien). Anschließend ruft man den Compiler auf
	um zu sehen, ob dieser das Programm annimmt. Wenn das Programm
	nicht kompiliert werden konnte, muß man die Zähne
	zusammenbeissen und wieder zum Editor zurückkehren; falls
	das Programm kompiliert und eine ausführbare Anwendung
	erzeugt wurde, kann man diese über eine
	Eingabeaufforderung oder über einen Debugger aufrufen um
	zu sehen, ob sie auch funktioniert.

	<footnote>
	  <para>Wenn die Anwendung über eine Eingabeaufforderung
	    gestartet wird könnte bei Auftreten eines
	    Programmfehlers dieses abgebrochen und ein Speicherabbild
	    erzeugt werden.</para>
	</footnote>
      </para>

      <para>Offensichtlich ist diese Art der Programmierung nicht
	so direkt wie die Verwendung eines Interpreters. Jedoch sind
	auf diese Weise viele Dinge möglich, die mit einem
	Interpreter nur sehr schwer oder überhaupt nicht
	realisierbar wären, wie z.B. das Schreiben von Code, der
	sehr eng mit dem Betriebsystem zusammen arbeitet&mdash;oder
	das Schreiben eines eigenen Betriebsystems selbst! Des
	weiteren ist so das Erzeugen von sehr effizientem Code
	möglich, da sich der Compiler für die Optimierung
	Zeit nehmen kann, was bei einem Interpreter inakzeptabel
	wäre. Ferner ist das Verbreiten von Programmen, welche
	für einen Compiler geschrieben wurden, einfacher als
	welche, die für einen Interpreter geschrieben
	wurden&mdash;man muss in ersterem Fall nur die
	ausführbare Datei verbreiten, vorausgesetzt, daß das
	gleiche Betriebssystem verwendet wird.</para>

      <para>Programmiersprachen, die kompiliert werden, sind unter
	anderem Pascal, C und C++. C und C++ sind eher unbarmherzige
	Programmiersprachen und daher eher für erfahrene
	Programmierer gedacht; Pascal auf der anderen Seite wurde zu
	Ausbildungszwecken entworfen, und stellt daher eine
	einsteigerfreundliche Programmiersprache dar. FreeBSD
	beinhaltet im Basissystem keine Unterstützung für
	Pascal, stellt jedoch über die Ports-Sammlung den
	Free Pascal Compiler unter <filename
	role="package">lang/fpc</filename> zur Verfügung.</para>

      <para>Da der editier-kompilier-ausführ-debug-Kreislauf
	unter Verwendung mehrerer Programme eher mühsam ist haben
	viele Hersteller von Compilern integrierte
	Entwicklungsumgebungen (Integrated Development Environment;
	auch kurz <acronym>IDE</acronym>) entwickelt. FreeBSD bietet
	zwar im Basissystem keine IDE an, stellt jedoch über die
	Ports-Sammlung IDEs wie <filename
	role="package">devel/kdevelop</filename> oder
	<application>Emacs</application> zur Verfügung, wobei
	letztere weit verbreitet ist. Die Verwendung von
	<application>Emacs</application> als IDE wird unter <xref
	linkend="emacs"/> diskutiert.</para>
    </sect2>
  </sect1>

  <sect1 id="tools-compiling">
    <title>Kompilieren mit dem <command>cc</command></title>

    <para>Dieser Abschnitt behandelt ausschließlich den GNU
      Compiler für C und C++, da dieser bereits im Basissystem
      von FreeBSD enthalten ist. Er kann mittels <command>cc</command>
      oder <command>gcc</command> aufgerufen werden. Die Details zur
      Erstellung einer Anwendung mit einem Interpreter variieren
      zwischen verschiedenen Interpretern mehr oder weniger stark, und
      werden meist ausführlich in der zugehörigen
      Dokumentation oder Online-Hilfe beschrieben.</para> <para>Sobald
      Sie Ihr Meisterwerk fertig geschrieben haben besteht der
      nächste Schritt darin, dieses (hoffentlich!) unter FreeBSD
      zum Laufen zu bekommen. Dies beinhaltet üblicherweise
      mehrere Schritte, wobei jeder einzelne Schritt von einem
      separaten Programm durchgeführt wird.</para>

    <procedure>
      <step>
	<para>Aufbereiten Ihres Quelltextes durch Entfernen von
	  Kommentaren, sowie weiteren Tricks wie das Ersetzen von
	  Macros in C.</para>
      </step>

      <step>
	<para>Überprüfen der Syntax Ihres Quelltextes, um
	  die Einhaltung der Sprachregeln sicherzustellen. Wenn Sie
	  diese verletzt haben werden entsprechende Fehlermeldungen
	  Ihnen dies mitteilen!</para>
      </step>

      <step>
	<para>Übersetzen des Quelltextes in Assemblersprache
	  &mdash;diese ist dem eigentlichen Maschinencode schon sehr
	  nahe, jedoch immer noch für Menschen lesbar.
	  Angeblich.

	  <footnote>
	    <para>Um genau zu sein übersetzt der
	      <command>cc</command> den Quelltext an dieser Stelle
	      nicht in Assemblersprache, sondern in seine eigene,
	      maschinenunabhängige Sprache namens
	      <firstterm>p-code</firstterm>.</para>
	  </footnote>
	</para>
      </step>

      <step>
	<para>Übersetzen der Assemblersprache in
	  Maschinencode&mdash;genau, wir sprechen hier von Bits und
	  Bytes, Einsen und Nullen.</para>
      </step>

      <step>
	<para>Überprüfen, ob Sie Dinge wie Funktionen und
	  globale Variablen in einheitlicher Weise verwendet haben.
	  Wenn Sie z.B. eine nicht existierende Funktion aufgerufen
	  haben, wird eine entsprechende Fehlermeldung Ihnen dies
	  mitteilen.</para>
      </step>

      <step>
	<para>Wenn aus mehreren Quelltextdateien eine
	  ausführbare Datei erstellt werden soll wird
	  herausgefunden, wie die einzelnen Codeteile
	  zusammengefügt werden müssen.</para>
      </step>

      <step>
	<para>Ausarbeiten, wie das Programm aussehen muss, damit
	  der Lader zur Laufzeit des Systems dieses in den Speicher
	  laden und ausführen kann.</para>
      </step>

      <step>
	<para>Endgültiges Schreiben der ausführbaren Datei
	  in das Dateisystem.</para>
      </step>
    </procedure>

    <para>Das Wort <firstterm>kompilieren</firstterm> wird häufig
      für die Schritte 1 bis 4 verwendet&mdash;die anderen werden
      mit dem Wort <firstterm>verlinken</firstterm> zusammengefasst.
      Manchmal wird Schritt 1 auch als
      <firstterm>Pre-Processing</firstterm> und die Schritte 3-4 als
      <firstterm>assemblieren</firstterm> bezeichnet.</para>

    <para>Glücklicherweise werden alle diese Details vor Ihnen
      verborgen, da <command>cc</command> ein Frontend ist, welches
      sich um die Ausführung all dieser Programme mit den
      richtigen Argumenten für Sie kümmert; einfaches
      eingeben von</para>

    <screen>&prompt.user; <userinput>cc foobar.c</userinput></screen>

    <para>führt zur Übersetzung von
      <filename>foobar.c</filename> durch alle bereits erwähnten
      Schritte. Wenn Sie mehr als eine Datei übersetzen wollen
      müssen Sie etwas wie folgt eingeben</para>

    <screen>&prompt.user; <userinput>cc foo.c bar.c</userinput></screen>

    <para>Beachten Sie, daß die Überprüfung der Syntax
      genau dies tut&mdash;das reine Überprüfen der Syntax.
      Es findet keine Überprüfung bzgl. logischer Fehler
      statt, die Sie vielleicht gemacht haben, wie z.B. das Programm
      in eine Endlosschleife zu versetzen, oder Bubble Sort zu
      verwenden, wenn Sie eigentlich Binary Sort benutzen wollten.

      <footnote>
	<para>Falls Sie es nicht wußten, Binary Sort ist, im
	  Gegensatz zu Bubble Sort, eine effektive Möglichkeit,
	  Dinge zu sortieren.</para>
      </footnote>
    </para>

    <para>Es gibt haufenweise Optionen für <command>cc</command>,
      die alle in der zugehörigen Manualpage beschrieben werden.
      Im Folgenden werden ein paar der wichtigsten Optionen mit
      Beispielen ihrer Anwendung gezeigt.</para>

    <variablelist>
      <varlistentry>
	<term><option>-o <replaceable>filename</replaceable></option></term>

	<listitem>
	  <para>Die Name der Ausgabedatei. Wenn Sie diese Option nicht
	    verwenden erstellt <command>cc</command> eine Datei mit
	    dem Namen <filename>a.out</filename>.

	    <footnote>
	      <para>Der Grund dafür ist im Haufen der Geschichte
		begraben.</para>
	    </footnote>
	  </para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc foobar.c</userinput>               <lineannotation>executable is <filename>a.out</filename></lineannotation>
&prompt.user; <userinput>cc -o foobar foobar.c</userinput>     <lineannotation>executable is <filename>foobar</filename></lineannotation>
	    </screen>
	  </informalexample>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-c</option></term>

	<listitem>
	  <para>Dies kompiliert die Datei nur, verlinkt sie jedoch
	    nicht. Nützlich für Spielereien, um die Syntax
	    auf Korrektheit zu überprüfen, oder falls Sie
	    ein <filename>Makefile</filename> verwenden.</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -c foobar.c</userinput>
	    </screen>
	  </informalexample>

	  <para>Dieser Befehl erzeugt eine
	    <firstterm>Objektdatei</firstterm> (nicht ausführbar)
	    mit den Namen <filename>foobar.o</filename>. Diese kann
	    mit anderen Objektdateien zusammen zu einer
	    ausführbaren Datei verlinkt werden.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-g</option></term>

	<listitem>
	  <para>Diese Option erzeugt die Debug-Version einer
	    ausführbaren Datei. Dabei fügt der Compiler
	    zusätzliche Informationen darüber, welcher
	    Funktionsaufruf zu welcher Zeile im Quelltext gehört,
	    der ausführbaren Datei hinzu. Ein Debugger kann Ihnen
	    mit Hilfe dieser Information den zugehörigen
	    Quelltext anzeigen, während Sie den Programmverlauf
	    schrittweise verfolgen, was <emphasis>sehr</emphasis>
	    hilfreich sein kann; der Nachteil dabei ist, daß
	    durch die zusätzlichen Informationen das Programm
	    viel größer wird. Normalerweise verwendet man
	    die Option <option>-g</option> während der
	    Entwicklung eines Programms, und für die
	    <quote>Release-Version</quote>, wenn man von der
	    Korrektheit des Programms überzeugt ist, kompiliert
	    man das Programm dann ohne diese Option.</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -g foobar.c</userinput>
	    </screen>
	  </informalexample>

	  <para>Mit diesem Befehl wird eine Debug-Version des
	    Programms erzeugt.

	    <footnote>
	      <para>Beachten Sie, daß an dieser Stelle die
		Option <option>-o</option> zum Festlegen des Namens
		der ausführbaren Datei nicht verwendet wurde,
		weswegen an dieser Stelle die erzeugte Datei
		<filename>a.out</filename> heißt. Die Erzeugung
		einer Debug-Version namens <filename>foobar</filename>
		ist als Übung dem Leser überlassen!</para>
	    </footnote>
	  </para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-O</option></term>

	<listitem>
	  <para>Diese Option erzeugt eine optimierte Version der
	    ausführbaren Datei. Der Compiler verwendet einige
	    clevere Tricks, um das erzeugte Programm schneller zu
	    machen. Sie können hinter der Option
	    <option>-O</option> eine Zahl angeben, um eine
	    höheres Level der Optimierung festzulegen. Dadurch
	    wird jedoch häufig eine fehlerhafte Optimierung
	    seitens des Compilers aufgedeckt. Zum Beispiel erzeugte
	    die Version des <command>cc</command>, welche mit dem
	    FreeBSD Release 2.1.0 mitgeliefert wurde, bei Verwendung
	    der Option <option>-O2</option> unter bestimmten
	    Umständen falschen Code.</para>

	  <para>Optimierungen werden normalerweise nur beim
	    Kompilieren von Release-Versionen aktiviert.</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -O -o foobar foobar.c</userinput>
	    </screen>
	  </informalexample>

	  <para>Durch diesen Befehl wird eine optimierte Version von
	    <filename>foobar</filename> erzeugt.</para>
	</listitem>
      </varlistentry>
    </variablelist>

    <para>Die folgenden drei Flags zwingen den <command>cc</command>
      dazu, Ihren Code auf die Einhaltung der internationalen
      Standards hin zu überprüfen, welche häufig als
      <acronym>ANSI</acronym> Standards bezeichnet werden, obwohl sie
      streng genommen zum <acronym>ISO</acronym> Standard
      gehören.</para>

    <variablelist>
      <varlistentry>
	<term><option>-Wall</option></term>

	<listitem>
	  <para>Aktivieren aller Warnmeldungen, die die Autoren des
	    <command>cc</command> für wichtig halten. Trotz des
	    Namens dieser Option werden dadurch nicht sämtliche
	    Warnungen ausgegeben, die der <command>cc</command>
	    ausgeben könnte.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-ansi</option></term>

	<listitem>
	  <para>Deaktivieren der meisten, jedoch nicht aller,
	    nicht-<acronym>ANSI</acronym>&nbsp;C Eigenschaften, die
	    der <command>cc</command> bietet. Trotz des Namens ist
	    durch diese Option nicht sichergestellt, daß Ihr
	    Code diese Standards auch vollständig
	    einhält.</para>
	</listitem>
      </varlistentry>

      <varlistentry>
	<term><option>-pedantic</option></term>

	<listitem>
	  <para>Deaktivieren <emphasis>aller</emphasis> Eigenschaften
	    des <command>cc</command>, welche nicht konform zu
	    <acronym>ANSI</acronym>&nbsp;C sind.</para>
	</listitem>
      </varlistentry>
    </variablelist>

    <para>Ohne diese Flags wird Ihnen der <command>cc</command> die
      Verwendung eigener Erweiterungen des Standards erlauben. Einige
      dieser Erweiterungen sind zwar sehr nützlich, werden jedoch
      nicht von anderen Compilern unterstützt&mdash;eigentlich
      ist eines der Hauptziele des Standards, das Leute Code so
      schreiben können, daß dieser mit jedem Compiler auf
      beliebigen Systemen funktioniert. Dies wird häufig als
      <firstterm>portabler Code</firstterm> bezeichnet.</para>

    <para>Im Allgemeinen sollten Sie versuchen, Ihren Code so portabel
      wie möglich zu schreiben, da Sie ansonsten eventuell das
      gesamte Programm noch einmal neu schreiben müssen, falls
      dieser in einer anderen Umgebung laufen soll&mdash;und wer
      weiß schon was er in ein paar Jahren verwenden
      wird?</para>

    <informalexample>
      <screen>&prompt.user; <userinput>cc -Wall -ansi -pedantic -o foobar foobar.c</userinput></screen>
    </informalexample>

    <para>Durch diesen Befehl wird eine ausführbare Datei namens
      <filename>foobar</filename> erzeugt, nachdem
      <filename>foobar.c</filename> auf die Einhaltung der Standards
      überprüft wurde.</para>

    <variablelist>
      <varlistentry>
	<term><option>-l<replaceable>library</replaceable></option></term>

	<listitem>
	  <para>Mit dieser Option kann eine Bibliothek mit Funktionen
	    angegeben werden, die während des Verlinkens
	    verwendet wird.</para>

	  <para>Das am häufigsten auftretende Beispiel dieser
	    Option ist die Übersetzung eines Programmes, welches
	    einige der mathematischen Funktionen in C verwendet. Im
	    Gegensatz zu den meisten anderen Plattformen befinden sich
	    diese Funktionen in einer separaten Bibliothek, deren
	    Verwendung Sie dem Compiler explizit mitteilen
	    müssen.</para>

	  <para>Angenommen eine Bibliothek heißt
	    <filename>lib<replaceable>irgendwas</replaceable>.a</filename>,
	    dann müssen Sie dem <command>cc</command> als
	    Argument
	    <option>-l<replaceable>irgendwas</replaceable></option>
	    übergeben. Zum Beispiel heißt die
	    Mathematik-Bibliothek <filename>libm.a</filename>, und
	    daher müssen Sie dem <command>cc</command> als
	    Argument <option>-lm</option> übergeben. Ein
	    typisches <quote>Manko</quote> der Mathematik-Bibliothek
	    ist, daß diese immer die letzte Bibliothek auf der
	    Kommandozeile sein muß.</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput>
	    </screen>
	  </informalexample>

	  <para>Durch diesen Befehl werden die Funktionen aus der
	    Mathematik-Bibliothek in <filename>foobar</filename>
	    gelinkt.</para>

	  <para>Wenn Sie C++-Code kompilieren wollen, müssen Sie
	    <option>-lg++</option>, bzw. <option>-lstdc++</option>
	    falls Sie FreeBSD 2.2 oder neuer verwenden, zu Ihrer
	    Kommandozeile hinzufügen, um Ihr Programm gegen die
	    Funktionen der C++ Bibliothek zu linken. Alternativ
	    können Sie anstatt <command>cc</command> auch
	    <command>c++</command> aufrufen, welcher dies für Sie
	    erledigt. <command>c++</command> kann unter FreeBSD auch
	    als <command>g++</command> aufgerufen werden.</para>

	  <informalexample>
	    <screen>&prompt.user; <userinput>cc -o foobar foobar.cc -lg++</userinput>     <lineannotation>Bei FreeBSD 2.1.6 oder älter</lineannotation>
&prompt.user; <userinput>cc -o foobar foobar.cc -lstdc++</userinput>  <lineannotation>Bei FreeBSD 2.2 und neuer</lineannotation>
&prompt.user; <userinput>c++ -o foobar foobar.cc</userinput>
	    </screen>
	  </informalexample>

	  <para>Beide Varianten erzeugen eine ausführbare
	    <filename>foobar</filename> aus der C++ Quelltextdatei
	    <filename>foobar.cc</filename>. Beachten Sie bitte,
	    daß auf &unix; Systemen C++ Quelltextdateien
	    üblicherweise auf <filename>.C</filename>,
	    <filename>.cxx</filename> oder <filename>.cc</filename>
	    enden, und nicht wie bei &ms-dos; auf
	    <filename>.cpp</filename> (welche schon anderweitig
	    benutzt wurde). Der <command>gcc</command> hat
	    normalerweise anhand dieser Information entschieden,
	    welcher Compiler für die Quelltextdatei zum Einsatz
	    kommen soll; allerdings gilt diese Einschränkung
	    jetzt nicht mehr, und Sie können Ihre C++-Dateien
	    ungestraft auf <filename>.cpp</filename> enden
	    lassen!</para>
	</listitem>
      </varlistentry>
    </variablelist>

    <sect2>
      <title>Häufig auftretende <command>cc</command>-Fragen und
	-Probleme</title>

      <qandaset>
	<qandaentry>
	  <question>
	    <para>Ich versuche ein Programm zu schreiben, welches die
	      Funktion <function>sin()</function> verwendet, erhalte
	      jedoch eine Fehlermeldung. Was bedeutet diese?</para>

	    <informalexample>
	      <screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment
	      </screen>
	    </informalexample>
	  </question>

	  <answer>
	    <para>Wenn Sie mathematische Funktionen wie
	      <function>sin()</function> verwenden wollen, müssen
	      Sie den <command>cc</command> anweisen, die
	      Mathematik-Bibliothek wie folgt zu verlinken:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput>
	      </screen>
	    </informalexample>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>So, ich habe jetzt dieses einfache Programm als
	      Übung für <option>-lm</option> geschrieben.
	      Alles was es macht ist, 2.1 hoch 6 zu berechnen.</para>

	    <informalexample>
	      <programlisting>#include &lt;stdio.h&gt;

int main() {
	float f;

	f = pow(2.1, 6);
	printf("2.1 ^ 6 = %f\n", f);
	return 0;
}
	      </programlisting>
	    </informalexample>

	    <para>und ich habe es wie folgt kompiliert:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>cc temp.c -lm</userinput>
	      </screen>
	    </informalexample>

	    <para>wie mir gesagt wurde. Allerdings bekomme ich jetzt
	      bei der Ausführung die folgende Ausgabe:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>./a.out</userinput>
2.1 ^ 6 = 1023.000000
	      </screen>
	    </informalexample>

	    <para>Das ist <emphasis>nicht</emphasis> die richtige
	      Antwort! Was ist hier los?</para>
	  </question>

	  <answer>
	    <para>Wenn der Compiler Ihren Funktionsaufruf sieht,
	      überprüft er, ob er schon einmal einen
	      Prototypen für diese gesehen hat. Wenn nicht nimmt
	      er als Rückgabewert den Typ <type>int</type> an,
	      was sicherlich nicht das ist, was Sie an dieser Stelle
	      wollen.</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Wie kann ich das korrigieren?</para>
	  </question>

	  <answer>
	    <para>Die Prototypen der mathematischen Funktionen
	      befinden sich in der Datei <filename>math.h</filename>.
	      Wenn Sie diese Datei in Ihrem Quelltext includen ist der
	      Compiler in der Lage, den Prototypen zu finden, und wird
	      aufhören, seltsame Dinge mit Ihrer Berechnung zu
	      machen!</para>

	    <informalexample>
	      <programlisting>#include &lt;math.h&gt;
#include &lt;stdio.h&gt;

int main() {
...
	      </programlisting>
	    </informalexample>

	    <para>Nach erneutem Compilieren sollte das Folgende bei
	      der Ausführung ausgegeben werden:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>./a.out</userinput>
2.1 ^ 6 = 85.766121
	      </screen>
	    </informalexample>

	    <para>Wenn Sie irgendwelche mathematischen Funktionen
	      verwenden sollten Sie <emphasis>immer</emphasis> die
	      Datei <filename>math.h</filename> includen und nicht
	      vergessen, Ihr Programm gegen die Mathematik-Bibliothek
	      zu verlinken.</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Ich habe eine Datei mit dem Namen
	      <filename>foobar.c</filename> kompiliert, kann jedoch
	      nirgends eine ausführbare Datei namens
	      <filename>foobar</filename> finden. Wo befindet sich
	      diese?</para>
	  </question>

	  <answer>
	    <para>Denken Sie daran, daß der
	      <command>cc</command> die ausführbare Datei
	      <filename>a.out</filename> nennt, wenn Sie nicht
	      explizit einen Namen angeben. Verwenden Sie in solch
	      einem Fall die Option
	      <option>-o&nbsp;<replaceable>filename</replaceable></option>:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>cc -o foobar foobar.c</userinput>
	      </screen>
	    </informalexample>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>OK, ich habe eine ausführbare Datei namens
	      <filename>foobar</filename>, ich kann sie sehen, wenn
	      ich <command>ls</command> aufrufe. Gebe ich jedoch
	      <command>foobar</command> in die Kommandozeile ein wird
	      mir gesagt, daß eine Datei mit diesem Namen nicht
	      existiert. Warum kann die Datei nicht gefunden
	      werden?</para>
	  </question>

	  <answer>
	    <para>Im Gegensatz zu &ms-dos; sucht &unix; nicht im
	      aktuellen Verzeichnis nach einem ausführbaren
	      Programm, das Sie versuchen auszuführen, solange
	      Sie dies nicht explizit mit angeben. Sie können
	      entweder <command>./foobar</command> eingeben, was
	      soviel bedeutet wie <quote>führe eine Datei namens
	      <filename>foobar</filename> im aktuellen Verzeichnis
	      aus</quote>, oder Sie können Ihre Umgebungsvariable
	      <envar>PATH</envar> so erweitern, daß sie
	      ähnlich wie folgt aussieht</para>

	    <informalexample>
	      <screen>bin:/usr/bin:/usr/local/bin:.
	      </screen>
	    </informalexample>

	    <para>Der Punkt am Ende bedeutet <quote>siehe im aktuellen
	      Verzeichnis nach, wenn es in keinem der anderen zu
	      finden war</quote>.</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Ich habe meine ausführbare Datei
	      <filename>test</filename> genannt, allerdings passiert
	      nichts wenn ich diese aufrufe. Was ist hier los?</para>
	  </question>

	  <answer>
	    <para>Bei den meisten &unix;-Systeme existiert bereits
	      ein Programm mit dem Namen <command>test</command> im
	      Verzeichnis <filename>/usr/bin</filename>, und die Shell
	      nimmt dieses, bevor sie im aktuellen Verzeichnis
	      nachsieht. Sie können entweder den folgenden Befehl
	      eingeben:</para>

	    <informalexample>
	      <screen>&prompt.user; <userinput>./test</userinput>
	      </screen>
	    </informalexample>

	    <para>oder Sie können einen geeigneteren Namen
	      für Ihr Programm wählen!</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Ich habe mein Programm kompiliert und bei dessen
	      Aufruf sah zuerst alles gut aus. Jedoch gab es dann eine
	      Fehlermeldung, welche irgendetwas mit <errorname>core
	      dumped</errorname> lautete. Was bedeutet das?</para>
	  </question>

	  <answer>
	    <para>Der Name <firstterm>core dump</firstterm> stammt
	      noch aus sehr frühen Zeiten von &unix;, als die
	      Maschinen noch Kernspeicher zum Speichern von Daten
	      verwendeten. Einfach ausgedrückt, wenn bei einem
	      Programm unter bestimmen Bedingungen ein Fehler auftrat,
	      hat das System den Inhalt des Kernspeichers auf der
	      Festplatte in eine Datei namens
	      <filename>core</filename> geschrieben, welche der
	      Programmierer dann näher untersuchen konnte, um die
	      Ursache des Fehlers herauszufinden.</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Faszinierendes Zeugs, aber was soll ich jetzt
	      machen?</para>
	  </question>

	  <answer>
	    <para>Verwenden Sie den <command>gdb</command>, um das
	      Speicherabbild zu untersuchen (siehe <xref
	      linkend="debugging"/>).</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Als mein Programm den core dump erzeugt hat, sagte
	      es etwas von einem <errorname>segmentation
	      fault</errorname>. Was ist das?</para>
	  </question>

	  <answer>
	    <para>Diese Meldung heißt im Prinzip, daß Ihr
	      Programm eine illegale Operation mit dem Speicher
	      durchführen wollte; &unix; wurde so entworfen,
	      daß es das andere Programme und das Betriebssystem
	      selbst vor wildgewordenen Programmen
	      schützt.</para>

	    <para>Häufige Ursachen hierfür sind:</para>

	    <itemizedlist>
	      <listitem>
		<para>Der Versuch, einen <symbol>NULL</symbol>-Zeiger
		  zu beschreiben, z.B.</para>

		<programlisting>char *foo = NULL;
strcpy(foo, "bang!");
		</programlisting>
	      </listitem>

	      <listitem>
		<para>Einen Zeiger zu verwenden, welcher noch nicht
		  initialisiert wurde, z.B.</para>

		<programlisting>char *foo;
strcpy(foo, "bang!");
		</programlisting>

		<para>Der Zeiger hat einen zufälligen Wert,
		  welcher mit etwas Glück in einen Bereich des
		  Speichers zeigt, der für Ihr Programm nicht
		  verfügbar ist, und der Kernel bricht Ihr
		  Programm ab, bevor es irgendwelchen Schaden
		  anrichten kann. Wenn Sie Pech haben zeigt der Zeiger
		  irgendwo mitten in Ihr eigenes Programm, und
		  verändert dort ihre eigenen Datenstrukturen,
		  was zu sehr seltsamen Fehlern Ihres Programmes
		  führt.</para>
	      </listitem>

	      <listitem>
		<para>Der Versuch, auf Daten außerhalb eines
		  Arrays zuzugreifen, z.B.</para>

		<programlisting>int bar[20];
bar[27] = 6;
		</programlisting>
	      </listitem>

	      <listitem>
		<para>Der Versuch, Daten in eine Speicherbereich zu
		  schreiben, der nur lesbar ist, z.B.</para>

		<programlisting>char *foo = "My string";
strcpy(foo, "bang!");
		</programlisting>

		<para>&unix;-Compiler speichern häufig feste
		  Zeichenketten wie <literal>"My string"</literal> in
		  nur lesbaren Speicherbereichen ab.</para>
	      </listitem>

	      <listitem>
		<para>Wenn man unerlaubte Operationen mit
		  <function>malloc()</function> und
		  <function>free()</function> ausführt,
		  z.B.</para>

		<programlisting>char bar[80];
free(bar);
		</programlisting>

		<para>oder</para>

		<programlisting>char *foo = malloc(27);
free(foo);
free(foo);
		</programlisting>
	      </listitem>
	    </itemizedlist>

	    <para>Einzelne solcher Fehler führen zwar nicht
	      immer zu einem Fehlverhalten des Programms, stellen
	      jedoch immer eine falsche Verwendung dar. Manche Systeme
	      und Compiler sind toleranter als andere, weshalb
	      Programme auf dem einen System einwandfrei laufen, auf
	      dem anderen System jedoch abstürzen.</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Wenn ich einen core dump erhalte erscheint
	      manchmal die Meldung <errorname>bus error</errorname>.
	      In meinem &unix;-Buch steht, daß die Ursache ein
	      Hardwareproblem sei. Der Computer scheint aber weiterhin
	      zu funktionieren. Ist dies wahr?</para>
	  </question>

	  <answer>
	    <para>Nein, glücklicherweise nicht (es sei denn Sie
	      haben wirklich ein Hardwareproblem&hellip;).
	      Üblicherweise ist dies ein Weg Ihnen mitzuteilen,
	      daß Sie auf Speicher in einer Weise zugegriffen
	      haben, in der Sie dies nicht tun sollten.</para>
	  </answer>
	</qandaentry>

	<qandaentry>
	  <question>
	    <para>Diese Sache mit den core dumps hört sich sehr
	      nützlich an, wenn ich so etwas selber an beliebiger
	      Stelle bewirken könnte. Kann ich das tun, oder
	      muß ich warten bis ein Fehler auftritt?</para>
	  </question>

	  <answer>
	    <para>Ja, nehmen sie einfach eine andere Konsole oder
	      XTerm und führen Sie</para>

	    <screen>&prompt.user; <userinput>ps</userinput>
	    </screen>

	    <para>aus, um die Prozess-ID Ihres Programms
	      herauszufinden. Führen Sie
	      anschließend</para>

	    <screen>&prompt.user; <userinput>kill -ABRT <replaceable>pid</replaceable></userinput>
	    </screen>

	    <para>aus, wobei
	      <parameter><replaceable>pid</replaceable></parameter>
	      die Prozess-ID ist, die Sie vorher ermittelt
	      haben.</para>

	    <para>Dies ist nützlich, wenn sich Ihr Programm z.B.
	      in einer Endlosschleife verfangen hat. Sollte Ihr
	      Programm das Signal <symbol>SIGABRT</symbol> abfangen,
	      gibt es noch andere Möglichkeiten, die denselben
	      Effekt haben.</para>

	    <para>Alternativ können Sie einen core dump aus
	      Ihrem Programm heraus erstellen, indem Sie die Funktion
	      <function>abort()</function> aufrufen. Weitere
	      Informationen darüber können Sie in der
	      Manualpage &man.abort.3; nachlesen.</para>

	    <para>Wenn Sie einen core dump von außerhalb Ihres
	      Programms erzeugen wollen, ohne dabei den Prozess
	      abzubrechen, können Sie das Programm
	      <command>gcore</command> verwenden. Weitere
	      Informationen dazu finden Sie in der zugehörigen
	      Manualpage &man.gcore.1;.</para>

	  </answer>
	</qandaentry>
      </qandaset>
    </sect2>
  </sect1>

  <sect1 id="tools-make">
    <title>Make</title>

    <sect2>
      <title>Was ist <command>make</command>?</title>

      <para>Wenn Sie an einem einfachen Programm mit nur einer oder
	zwei Quelltextdateien arbeiten, ist die Eingabe von</para>

      <screen>&prompt.user; <userinput>cc file1.c file2.c</userinput></screen>

      <para>zwar nicht aufwendig, wird aber mit zunehmender Anzahl
	der Quelltextdateien sehr lästig&mdash;und auch das
	Kompilieren kann eine Weile dauern.</para>

      <para>Eine Möglichkeit dies zu umgehen besteht in der
	Verwendung von Objektdateien, wobei man nur die
	Quelltextdateien neu kompiliert, die verändert wurden. So
	könnten wir etwa folgendes erhalten:</para>

      <screen>&prompt.user; <userinput>cc file1.o file2.o</userinput> &hellip; <userinput>file37.c</userinput> &hellip;</screen>

      <para>falls wir seit dem letzten Kompiliervorgang nur die Datei
	<filename>file37.c</filename> verändert haben. Dadurch
	könnte der Kompiliervorgang um einiges beschleunigt
	werden, es muß jedoch immer noch alles von Hand
	eingegeben werden.</para>

      <para>Oder wir könnten uns ein Shell Skript schreiben.
	Dieses würde jedoch alles immer wieder neu kompilieren,
	was bei einem großen Projekt sehr ineffizient
	wäre.</para>

      <para>Was ist, wenn wir hunderte von Quelltextdateien
	hätten? Was ist, wenn wir in einem Team mit anderen
	Leuten arbeiten würden, die vergessen uns Bescheid zu
	sagen, falls sie eine der Quelltextdateien verändert
	haben, die wir ebenfalls benutzen?</para>

      <para>Vielleicht könnten wir beide Lösungen
	kombinieren und etwas wie ein Shell Skript schreiben, welches
	eine Art magische Regel enthalten würde, die feststellt,
	welche Quelltextdateien neu kompiliert werden müssten.
	Alles was wir bräuchten wäre ein Programm, das diese
	Regeln verstehen könnte, da diese Aufgabe etwas zu
	kompliziert für eine Shell ist.</para>

      <para>Dieses Programm heißt <command>make</command>. Es
	liest eine Datei namens <firstterm>makefile</firstterm>,
	welche ihm sagt, wie unterschiedliche Dateien voneinander
	abhängen, und berechnet, welche Dateien neu kompiliert
	werden müssen und welche nicht. Zum Beispiel könnte
	eine Regel etwas sagen wie <quote>wenn
	<filename>fromboz.o</filename> älter als
	<filename>fromboz.c</filename> ist, bedeutet dies, daß
	jemand die Datei <filename>fromboz.c</filename> verändert
	haben muß, und diese daher neu kompiliert werden
	muß.</quote> Das makefile enthält außerdem
	Regeln die make sagen, <emphasis>wie</emphasis> die
	Quelltextdatei neu kompiliert werden muß, was dieses
	Tool noch sehr viel mächtiger macht.</para>

      <para>Makefiles werden normalerweise im selben Verzeichnis
	wie die Quelltextdateien abgelegt, zu denen sie gehören,
	und kann <filename>makefile</filename>,
	<filename>Makefile</filename> oder
	<filename>MAKEFILE</filename> heißen. Die meisten
	Programmierer verwenden den Namen
	<filename>Makefile</filename>, da diese Schreibweise
	dafür sorgt, daß die Datei gut lesbar ganz oben in
	der Verzeichnisliste aufgeführt wird.

	<footnote>
	  <para>Verwenden Sie nicht <filename>MAKEFILE</filename> mit
	    lauter Großbuchstaben, da diese Schreibweise
	    häufig für Dokumentationsdateien wie
	    <filename>README</filename> benutzt wird.</para>
	</footnote>
      </para>
    </sect2>

    <sect2>
      <title>Beispielhafte Verwendung von <command>make</command></title>

      <para>Hier ist eine sehr einfache make Datei:</para>

      <programlisting>foo: foo.c
	cc -o foo foo.c</programlisting>

      <para>Sie besteht aus zwei Zeilen, einer
	Abhängigkeitszeile und einer Erzeugungszeile.</para>

      <para>Die Abhängigkeitszeile hier besteht aus dem Namen
	des Programms (auch <firstterm>Ziel</firstterm> genannt),
	gefolgt von einem Doppelpunkt und einem Leerzeichen, und
	anschließend dem Namen der Quelltextdatei. Wenn
	<command>make</command> diese Zeile liest überprüft
	es die Existenz von <filename>foo</filename>; falls diese
	Datei existiert vergleicht es das Datum der letzten
	Änderung von <filename>foo</filename> mit der von
	<filename>foo.c</filename>. Falls <filename>foo</filename>
	nicht existiert, oder älter als
	<filename>foo.c</filename> ist, liest es die Erzeugungszeile
	um herauszufinden, was zu tun ist. Mit anderen Worten, dies
	ist die Regel die festlegt, wann <filename>foo.c</filename>
	neu kompiliert werden muß.</para>

      <para>Die Erzeugungszeile beginnt mit einem <token>tab</token>
	(drücken Sie dazu die <keycap>tab</keycap>-Taste) gefolgt
	von dem Befehl, mit dem Sie <filename>foo</filename> manuell
	erzeugen würden. Wenn <filename>foo</filename> veraltet
	ist, oder nicht existiert, führt <command>make</command>
	diesen Befehl aus, um die Datei zu erzeugen. Mit anderen
	Worten, dies ist die Regel die make sagt, wie
	<filename>foo.c</filename> kompiliert werden muß.</para>

      <para>Wenn Sie also <userinput>make</userinput> eingeben wird
	dieses sicherstellen, daß <filename>foo</filename> bzgl.
	Ihrer letzten Änderungen an <filename>foo.c</filename>
	auf dem neuesten Stand ist. Dieses Prinzip kann auf
	<filename>Makefile</filename>s mit hunderten von
	Zielen&mdash;es ist bei FreeBSD praktisch möglich, das
	gesamte Betriebssystem zu kompilieren, indem man nur
	<userinput>make world</userinput> im richtigen Verzeichnis
	eingibt!</para>

      <para>Eine weitere nützliche Eigenschaft der makefiles
	ist, daß die Ziele keine Programme sein müssen. Wir
	könnten zum Beispiel eine make Datei haben, die wie folgt
	aussieht:</para>

      <programlisting>foo: foo.c
	cc -o foo foo.c

install:
	cp foo /home/me</programlisting>

      <para>Wir können make sagen welches Ziel wir erzeugt haben
	wollen, indem wir etwas wie folgt eingeben:</para>

      <screen>&prompt.user; <userinput>make <replaceable>target</replaceable></userinput></screen>

      <para><command>make</command> wird dann nur dieses Ziel
	beachten und alle anderen ignorieren. Wenn wir zum Beispiel
	<userinput>make foo</userinput> mit dem obigen makefile
	eingeben, dann wird make das Ziel
	<maketarget>install</maketarget> ignorieren.</para>

      <para>Wenn wir nur <userinput>make</userinput> eingeben wird
	make immer nur nach dem ersten Ziel suchen und danach mit dem
	Suchen aufhören. Wenn wir hier also nur
	<userinput>make</userinput> eingegeben hätten, würde
	es nur zu dem Ziel <maketarget>foo</maketarget> gehen,
	gegebenenfalls <filename>foo</filename> neu kompilieren, und
	danach einfach aufhören, ohne das Ziel
	<maketarget>install</maketarget> zu beachten.</para>

      <para>Beachten Sie, daß das <maketarget>install</maketarget>-Ziel
	von nichts anderem abhängt! Dies bedeutet, daß der
	Befehl in der nachfolgenden Zeile immer ausgeführt wird,
	wenn wir dieses Ziel mittels <userinput>make
	install</userinput> aufrufen. In diesem Fall wird die Datei
	<filename>foo</filename> in das Heimatverzeichnis des
	Benutzers kopiert. Diese Vorgehensweise wird häufig bei
	makefiles von Anwendungen benutzt, damit die Anwendung nach
	erfolgreicher Kompilierung in das richtige Verzeichnis
	installiert werden kann.</para>

      <para>Dieser Teil ist etwas schwierig zu erklären. Wenn
	Sie immer noch nicht so richtig verstanden haben, wie
	<command>make</command> funktioniert, wäre es das Beste,
	sie erstellen sich selber ein einfaches Programm wie
	<quote>hello world</quote> und eine make Datei wie die weiter
	oben angegebene, und experimentieren damit selber ein bißchen
	herum. Als nächstes könnten Sie mehrere
	Quelltextdateien verwenden, oder in Ihrer Quelltextdatei eine
	Header-Datei includen. Der Befehl <command>touch</command> ist
	an dieser Stelle ganz hilfreich&mdash;er verändert das
	Datum einer Datei, ohne das Sie diese extra editieren
	müssen.</para>
    </sect2>

    <sect2>
      <title>Make und include-Dateien</title>

      <para>C-Code beginnt häufig mit einer Liste von Dateien,
	die included werden sollen, zum Beispiel stdio.h. Manche
	dieser Dateien sind include-Dateien des Systems, andere
	gehören zum aktuellen Projekt, an dem Sie gerade
	arbeiten:</para>

      <programlisting>#include &lt;stdio.h&gt;
#include "foo.h"

int main(....</programlisting>

      <para>Um sicherzustellen, daß diese Datei neu kompiliert
	wird, wenn <filename>foo.h</filename> verändert wurde,
	müssen Sie diese Datei Ihrem
	<filename>Makefile</filename> hinzufügen:</para>

      <programlisting>foo: foo.c foo.h</programlisting>

      <para>Sobald Ihr Projekt größer wird und Sie mehr
	und mehr eigene include-Dateien verwalten müssen wird es
	nur noch sehr schwer möglich sein, die Übersicht
	über alle include-Dateien und Dateien, die von diesen
	abhängen, beizubehalten. Falls Sie eine include-Datei
	verändern, jedoch das erneute Kompilieren aller Dateien,
	die von dieser Datei abhängen, vergessen, werden die
	Folgen verheerend sein. Der <command>gcc</command> besitzt
	eine Option, bei der er Ihre Dateien analysiert und eine Liste
	aller include-Dateien und deren Abhängigkeiten erstellt:
	<option>-MM</option>.</para>

      <para>Wenn Sie das Folgende zu Ihrem Makefile
	hinzufügen:</para>

      <programlisting>depend:
	gcc -E -MM *.c &gt; .depend</programlisting>

      <para>und <userinput>make depend</userinput> ausführen,
	wird die Datei <filename>.depend</filename> mit einer Liste
	von Objekt-Dateien, C-Dateien und den include-Dateien
	auftauchen:</para>

      <programlisting>foo.o: foo.c foo.h</programlisting>

      <para>Falls Sie <filename>foo.h</filename> verändern
	werden beim nächsten Aufruf von <command>make</command>
	alle Dateien, die von <filename>foo.h</filename>
	abhängen, neu kompiliert.</para>

      <para>Vergessen Sie nicht jedes mal
	<command>make depend</command> aufzurufen, wenn Sie eine
	include-Datei zu einer Ihrer Dateien hinzugefügt
	haben.</para>
    </sect2>

    <sect2>
      <title>FreeBSD Makefiles</title>

      <para>Makefiles können eher schwierig zu schreiben sein.
	Glücklicherweise kommen BSD-basierende Systeme wie
	FreeBSD mit einigen sehr mächtigen solcher Dateien als
	Teil des Systems daher. Ein sehr gutes Beispiel dafür ist
	das FreeBSD Portssystem. Hier ist der grundlegende Teil eines
	typischen <filename>Makefile</filename>s des
	Portssystems:</para>

      <programlisting>MASTER_SITES=   ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/
DISTFILES=      scheme-microcode+dist-7.3-freebsd.tgz

.include &lt;bsd.port.mk&gt;</programlisting>

      <para>Wenn wir jetzt in das Verzeichnis dieses Ports wechseln
	und <userinput>make</userinput> aufrufen, passiert das
	Folgende:</para>

      <procedure>
	<step>
	  <para>Es wird überprüft, ob sich der Quelltext
	    für diesen Port bereits auf Ihrem System
	    befindet.</para>
	</step>

	<step>
	  <para>Falls dies nicht der Fall ist wird eine
	    FTP-Verbindung zu der URL in <symbol>MASTER_SITES</symbol>
	    aufgebaut und der Quelltext heruntergeladen.</para>
	</step>

	<step>
	  <para>Die Checksumme für den Quelltext wird berechnet
	    und mit der schon bekannten und für sicher und gut
	    empfundenen verglichen. Damit wird sichergestellt,
	    daß der Quelltext bei der Übertragung nicht
	    beschädigt wurde.</para>
	</step>

	<step>
	  <para>Sämtliche Anpassungen, die nötig sind,
	    damit der Quelltext unter FreeBSD funktioniert, werden
	    vorgenommen&mdash;dieser Vorgang wird auch
	    <firstterm>patchen</firstterm> genannt.</para>
	</step>

	<step>
	  <para>Alle speziellen Konfigurationen, die am Quelltext
	    nötig sind, werden vorgenommen. (Viele &unix;
	    Programmdistributionen versuchen herauszufinden, auf
	    welcher &unix;-Version sie kompiliert werden sollen und
	    welche optionalen &unix;-Features vorhanden sind&mdash;an
	    dieser Stelle erhalten sie die Informationen im FreeBSD
	    Ports Szenario).</para>
	</step>

	<step>
	  <para>Der Quelltext für das Programm wird kompiliert.
	    Im Endeffekt wechseln wir in das Verzeichnis, in das der
	    Quelltext entpackt wurde, und rufen
	    <command>make</command> auf&mdash;die eigene make-Datei
	    des Programms besitzt die nötigen Informationen um
	    dieses zu bauen.</para>
	</step>

	<step>
	  <para>Wir haben jetzt eine kompilierte Version des
	    Programmes. Wenn wir wollen können wir dieses jetzt
	    testen; wenn wir überzeugt vom Programm sind,
	    können wir <userinput>make install</userinput>
	    eingeben. Dadurch werden das Programm sowie alle
	    zugehörigen Dateien an die richtige Stelle kopiert;
	    es wird auch ein Eintrag in der
	    <database>Paketdatenbank</database> erzeugt, sodaß
	    der Port sehr einfach wieder deinstalliert werden kann,
	    falls wir unsere Meinung über dieses geändert
	    haben.</para>
	</step>
      </procedure>

      <para>Ich glaube jetzt werden Sie mit mir übereinstimmen,
	daß dies ziemlich eindrucksvoll für ein Skript mit
	vier Zeilen ist!</para>

      <para>Das Geheimnis liegt in der letzten Zeile, die
	<command>make</command> anweist, in das makefile des Systems
	mit dem Namen <filename>bsd.port.mk</filename> zu sehen. Man
	kann diese Zeile zwar leicht übersehen, aber hierher
	kommt all das klevere Zeugs&mdash;jemand hat ein makefile
	geschrieben, welches <command>make</command> anweist, alle
	weiter oben beschriebenen Schritte durchzuführen (neben
	vielen weiteren Dingen, die ich nicht angesprochen habe,
	einschließlich der Behandlung sämtlicher Fehler,
	die auftreten könnten) und jeder kann darauf
	zurückgreifen, indem er eine einzige Zeile in seine
	eigene make-Datei einfügt!</para>

      <para>Falls Sie einen Blick in die makefiles des Systems werfen
	möchten, finden Sie diese in
	<filename>/usr/share/mk</filename>. Es ist aber wahrscheinlich
	besser, wenn Sie damit noch warten, bis Sie ein bißchen mehr
	Praxiserfahrung mit makefiles gesammelt haben, da die dortigen
	makefiles sehr kompliziert sind (und wenn Sie sich diese
	ansehen sollten Sie besser eine Kanne starken Kaffee
	griffbereit haben!)</para>
    </sect2>

    <sect2>
      <title>Fortgeschrittene Verwendung von
	<command>make</command></title>

      <para><command>Make</command> ist ein sehr mächtiges
	Werkzeug und kann noch sehr viel mehr als die gezeigten
	einfachen Beispiele weiter oben. Bedauerlicherweise gibt es
	mehrere verschiedene Versionen von <command>make</command>,
	und sie alle unterscheiden sich beträchtlich voneinander.
	Der beste Weg herauszufinden was sie können ist
	wahrscheinlich deren Dokumentation zu lesen&mdash;hoffentlich
	hat diese Einführung Ihnen genügend Grundkenntnisse
	vermitteln können, damit Sie dies tun können.</para>

      <para>Die Version von make, die in FreeBSD enthalten ist, ist
	<application>Berkeley make</application>; es gibt eine
	Anleitung dazu in
	<filename>/usr/share/doc/psd/12.make</filename>. Um sich diese
	anzusehen, müssen Sie</para>

      <screen>&prompt.user; <userinput>zmore paper.ascii.gz</userinput></screen>

      <para>in diesem Verzeichnis ausführen.</para>

      <para>Viele Anwendungen in den Ports verwenden
	<application>GNU make</application>, welches einen sehr guten
	Satz an <quote>info</quote>-Seiten mitbringt. Falls Sie
	irgendeinen dieser Ports installiert haben wurde
	<application>GNU make</application> automatisch als
	<command>gmake</command> mit installiert. Es ist auch als
	eigenständiger Port und Paket verfügbar.</para>

      <para>Um sich die Info-Seiten für
	<application>GNU make</application> anzusehen müssen Sie
	die Datei <filename>dir</filename> in
	<filename>/usr/local/info</filename> um einen entsprechenden
	Eintrag erweitern. Dies beinhaltet das Einfügen einer
	Zeile wie</para>

      <programlisting> * Make: (make).                 The GNU Make utility.</programlisting>

      <para>in die Datei. Nachdem Sie dies getan haben können
	Sie <userinput>info</userinput> eingeben und dann den
	Menüeintrag <guimenuitem>make</guimenuitem>
	auswählen (oder Sie können in
	<application>Emacs</application> die Tastenkombination
	<userinput>C-h i</userinput> verwenden).</para>
    </sect2>
  </sect1>

  <sect1 id="debugging">
    <title>Debuggen</title>

    <sect2>
      <title>Der Debugger</title>

      <para>Der Debugger bei FreeBSD heißt
	<command>gdb</command> (<application>GNU
	debugger</application>). Sie können Ihn durch die Eingabe
	von</para>

      <screen>&prompt.user; <userinput>gdb <replaceable>progname</replaceable></userinput></screen>

      <para>starten, wobei viele Leute ihn vorzugsweise
	innerhalb von <application>Emacs</application> aufrufen. Sie
	erreichen dies durch die Eingabe von:</para>

      <screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput></screen>

      <para>Die Verwendung eines Debuggers erlaubt Ihnen Ihr
	Programm unter kontrollierteren Bedingungen ausführen zu
	können. Typischerweise können Sie so Zeile für
	Zeile durch Ihr Programm gehen, die Werte von Variablen
	untersuchen, diese verändern, dem Debugger sagen er soll
	das Programm bis zu einem bestimmten Punkt ausführen und
	dann anhalten, und so weiter und so fort. Sie können
	damit sogar ein schon laufendes Programm untersuchen, oder
	eine Datei mit einem Kernspeicherabbild laden um
	herauszufinden, warum das Programm abgestürzt ist. Es ist
	sogar möglich damit den Kernel zu debuggen, wobei dies
	etwas trickreicher als bei den Benutzeranwendungen ist, welche
	wir in diesem Abschnitt behandeln werden.</para>

      <para>Der <command>gdb</command> besitzt eine recht gute
	Online-Hilfe, sowie einen Satz von Info-Seiten, weshalb sich
	dieser Abschnitt auf ein paar grundlegende Befehle
	beschränken wird.</para>

      <para>Falls Sie den textbasierten Kommandozeilen-Stil
	abstoßend finden gibt es ein graphisches Front-End
	dafür (<filename
	role="package">devel/xxgdb</filename>) in der Ports-Sammlung.</para>

      <para>Dieser Abschnitt ist als Einführung in die
	Verwendung des <command>gdb</command> gedacht und beinhaltet
	nicht spezielle Themen wie das Debuggen des Kernels.</para>
    </sect2>

    <sect2>
      <title>Ein Programm im Debugger ausführen</title>

      <para>Sie müssen das Programm mit der Option
	<option>-g</option> kompiliert haben um den
	<command>gdb</command> effektiv einsetzen zu können. Es
	geht auch ohne diese Option, allerdings werden Sie dann nur
	den Namen der Funktion sehen, in der Sie sich gerade befinden,
	anstatt direkt den zugehörigen Quelltext. Falls Sie eine
	Meldung wie die folgende sehen:</para>

      <screen>&hellip; (no debugging symbols found) &hellip;</screen>

      <para>wenn der <command>gdb</command> gestartet wird, dann
	wissen Sie, daß das Programm nicht mit der Option
	<option>-g</option> kompiliert wurde.</para>

      <para>Geben Sie in der Eingabeaufforderung des
	<command>gdb</command> <userinput>break main</userinput> ein.
	Dies weist den Debugger an, dass Sie nicht daran interessiert sind,
	den einleitenden Schritten beim Programmstart zuzusehen und dass
	am Anfang Ihres Codes die Ausführung beginnen soll.  Geben Sie
	nun <userinput>run</userinput> ein, um das Programm zu starten -
	es wird starten und beim Aufruf von <function>main()</function> vom
	Debugger angehalten werden. (Falls Sie sich jemals gewundert haben von
	welcher Stelle <function>main()</function> aufgerufen wird, dann
	wissen Sie es jetzt!).</para>

      <para>Sie können nun Schritt für Schritt durch Ihr
	Programm gehen, indem Sie <command>n</command> drücken.
	Wenn Sie zu einem Funktionsaufruf kommen können Sie diese
	Funktion durch drücken von <command>s</command> betreten.
	Sobald Sie sich in einem Funktionsaufruf befinden können
	Sie diesen durch drücken von <command>f</command> wieder
	verlassen. Sie können auch <command>up</command> und
	<command>down</command> verwenden, um sich schnell den
	Aufrufer einer Funktion anzusehen.</para>

      <para>Hier ist ein einfaches Beispiel, wie man mit Hilfe des
	<command>gdb</command> einen Fehler in einem Programm findet.
	Dies ist unser eigenes Programm (mit einem absichtlich
	eingebauten Fehler):</para>

      <programlisting>#include &lt;stdio.h&gt;

int bazz(int anint);

main() {
	int i;

	printf("This is my program\n");
	bazz(i);
	return 0;
}

int bazz(int anint) {
	printf("You gave me %d\n", anint);
	return anint;
}</programlisting>

      <para>Dieses Programm setzt <symbol>i</symbol> auf den Wert
	<literal>5</literal> und übergibt dies einer Funktion
	<function>bazz()</function>, welche den Wert ausgibt, den Sie
	von uns erhalten hat.</para>

      <para>Wenn wir das Programm kompilieren und ausführen
	erhalten wir</para>

      <screen>&prompt.user; <userinput>cc -g -o temp temp.c</userinput>
&prompt.user; <userinput>./temp</userinput>
This is my program
anint = 4231</screen>

      <para>Das ist nicht was wir erwartet hatten! Es ist Zeit,
	daß wir sehen was hier passiert!</para>

      <screen>&prompt.user; <userinput>gdb temp</userinput>
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
(gdb) <userinput>break main</userinput>				<lineannotation>Skip the set-up code</lineannotation>
Breakpoint 1 at 0x160f: file temp.c, line 9.	<lineannotation><command>gdb</command> puts breakpoint at <function>main()</function></lineannotation>
(gdb) <userinput>run</userinput>					<lineannotation>Run as far as <function>main()</function></lineannotation>
Starting program: /home/james/tmp/temp		<lineannotation>Program starts running</lineannotation>

Breakpoint 1, main () at temp.c:9		<lineannotation><command>gdb</command> stops at <function>main()</function></lineannotation>
(gdb) <userinput>n</userinput>						<lineannotation>Go to next line</lineannotation>
This is my program				<lineannotation>Program prints out</lineannotation>
(gdb) <userinput>s</userinput>						<lineannotation>step into <function>bazz()</function></lineannotation>
bazz (anint=4231) at temp.c:17			<lineannotation><command>gdb</command> displays stack frame</lineannotation>
(gdb)</screen>

      <para>Halt mal! Wieso hat denn <symbol>anint</symbol> den Wert
	<literal>4231</literal>? Haben wir dieser Variablen nicht in
	<function>main()</function> den Wert <literal>5</literal>
	zugewiesen? Gehen wir mal zurück zu
	<function>main()</function> und schauen dort nach.</para>

      <screen>(gdb) <userinput>up</userinput>					<lineannotation>Move up call stack</lineannotation>
#1  0x1625 in main () at temp.c:11		<lineannotation><command>gdb</command> displays stack frame</lineannotation>
(gdb) <userinput>p i</userinput>					<lineannotation>Show us the value of <symbol>i</symbol></lineannotation>
$1 = 4231					<lineannotation><command>gdb</command> displays <literal>4231</literal></lineannotation></screen>

      <para>Oh! Anscheinend haben wir vergessen <symbol>i</symbol> zu
	initialisieren. Wir wollten eigentlich</para>

      <programlisting><lineannotation>&hellip;</lineannotation>
main() {
	int i;

	i = 5;
	printf("This is my program\n");
<lineannotation>&hellip;</lineannotation></programlisting>

      <para>schreiben, haben aber die Zeile mit
	<literal>i=5;</literal> vergessen. Da wir <symbol>i</symbol>
	nicht initialisiert haben hatte diese Variable gerade den
	Wert, der in dem ihr zugewiesenen Speicherbereich stand als
	wir das Programm gestartet haben, welcher in diesem Fall
	<literal>4231</literal> war.</para>

      <note>
	<para>Der <command>gdb</command> zeigt jedes mal, wenn wir
	  eine Funktion betreten oder verlassen, den Inhalt des
	  Stack-Rahmens an, selbst wenn wir uns mit
	  <command>up</command> und <command>down</command> im
	  Aufruf-Stack umher bewegen. Dabei wird der Name der Funktion
	  sowie der übergebenen Argumente angezeigt, was uns
	  dabei hilft, die Übersicht zu behalten. (Der Stack ist
	  ein Speicherbereich, in dem ein Programm Informationen
	  über die an eine Funktion übergebenen Argumente
	  ablegt, sowie die Rücksprungadresse eines
	  Funktionsaufrufes).</para>
      </note>
    </sect2>

    <sect2>
      <title>Eine Kernspeicherdatei untersuchen</title>

      <para>Eine Kernspeicherdatei ist im Prinzip eine Datei, die den
	vollständigen Zustand eines Prozesses enthält, als
	dieses abgestürzt ist. In <quote>den guten alten
	Zeiten</quote> mußten Programmierer hexadezimale Listen
	der Kernspeicherdatei ausdrucken und über
	Maschinencodehandbüchern schwitzen, aber heutzutage ist
	das Leben etwas einfacher geworden. Zufälligerweise wird
	die Kernspeicherdatei unter FreeBSD und anderen
	4.4BSD-Systemen
	<filename><replaceable>progname</replaceable>.core</filename>
	anstatt einfach nur <filename>core</filename> genannt, um
	deutlich zu machen, zu welchem Programm eine Kernspeicherdatei
	gehört.</para>

      <para>Um eine Kernspeicherdatei zu untersuchen müssen Sie
	den <command>gdb</command> wie gewohnt starten. An Stelle von
	<command>break</command> oder <command>run</command>
	müssen Sie das Folgende eingeben</para>

      <screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput></screen>

      <para>Wenn Sie sich nicht in demselben Verzeichnis befinden wie
	die Kernspeicherdatei müssen Sie zuerst <userinput>dir
	/path/to/core/file</userinput> eingeben.</para>

      <para>Sie sollten dann etwas wie folgt sehen:</para>

      <screen>&prompt.user; <userinput>gdb a.out</userinput>
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
(gdb) <userinput>core a.out.core</userinput>
Core was generated by `a.out'.
Program terminated with signal 11, Segmentation fault.
Cannot access memory at address 0x7020796d.
#0  0x164a in bazz (anint=0x5) at temp.c:17
(gdb)</screen>

      <para>In diesem Fall hieß das Programm
	<filename>a.out</filename>, weshalb die Kernspeicherdatei den
	Namen <filename>a.out.core</filename> trägt. Wie wir
	sehen können stürzte das Programm in einer Funktion
	namens <function>bazz</function> ab, als es versuchte auf
	einen Speicherbereich zuzugreifen, der dem Programm nicht zur
	Verfügung stand.</para>

      <para>Manchmal ist es ganz nützlich zu sehen, wie eine
	Funktion aufgerufen wurde, da bei komplexen Programmen das
	eigentliche Problem schon sehr viel weiter oben auf dem
	Aufruf-Stack aufgetreten sein könnte. Der Befehl
	<command>bt</command> veranlaßt den
	<command>gdb</command> dazu, einen Backtrace des Aufruf-Stacks
	auszugeben:</para>

      <screen>(gdb) <userinput>bt</userinput>
#0  0x164a in bazz (anint=0x5) at temp.c:17
#1  0xefbfd888 in end ()
#2  0x162c in main () at temp.c:11
(gdb)</screen>

      <para>Die Funktion <function>end()</function> wird aufgerufen,
	wenn ein Programm abstürzt; in diesem Fall wurde die
	Funktion <function>bazz()</function> aus der
	<function>main()</function>-Funktion heraus aufgerufen.</para>
    </sect2>

    <sect2>
      <title>Ein bereits laufendes Programm untersuchen</title>

      <para>Eine der tollsten Features des <command>gdb</command>
	ist die Möglichkeit, damit bereits laufende Programme zu
	untersuchen. Dies bedeutet natürlich, daß Sie die
	erforderlichen Rechte dafür besitzen. Ein häufig
	auftretendes Problem ist das Untersuchen eines Programmes,
	welches sich selber forkt. Vielleicht will man den Kindprozess
	untersuchen, aber der Debugger erlaubt einem nur den Zugriff
	auf den Elternprozess.</para>

      <para>Was Sie an solch einer Stelle machen ist, Sie starten
	einen weiteren <command>gdb</command>, ermitteln mit Hilfe von
	<command>ps</command> die Prozess-ID des Kindprozesses, und
	geben</para>

      <screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput></screen>

      <para>im <command>gdb</command> ein, und können dann wie
	üblich mit der Fehlersuche fortfahren.</para>

      <para><quote>Das ist zwar alles sehr schön,</quote> werden
	Sie jetzt vielleicht denken, <quote>aber in der Zeit, in der
	ich diese Schritte durchführe, ist der Kindprozess schon
	längst über alle Berge</quote>. Fürchtet euch
	nicht, edler Leser, denn Ihr müßt wie folgt
	vorgehen (freundlicherweise zur Verfügung gestellt von
	den Info-Seite des <command>gdb</command>):</para>

      <screen><lineannotation>&hellip;</lineannotation>
if ((pid = fork()) &lt; 0)		/* _Always_ check this */
	error();
else if (pid == 0) {		/* child */
	int PauseMode = 1;

	while (PauseMode)
		sleep(10);	/* Wait until someone attaches to us */
	<lineannotation>&hellip;</lineannotation>
} else {			/* parent */
	<lineannotation>&hellip;</lineannotation></screen>

      <para>Alles was Sie jetzt noch tun müssen ist, sich an
	den Kindprozess ranzuhängen, <symbol>PauseMode</symbol>
	auf <literal>0</literal> zu setzen und auf den
	<function>sleep()</function> Funktionsaufruf zu warten, um
	zurückzukehren!</para>
    </sect2>
  </sect1>

  <sect1 id="emacs">
    <title>Emacs als Entwicklungsumgebung verwenden</title>

    <sect2>
      <title>Emacs</title>

      <para>Leider werden &unix;-Systeme nicht mit einem
	alles-was-du-jemals-brauchst-und-vieles-mehr-megapaket an
	integrierten Entwicklungsumgebungen ausgestattet, die bei
	anderen Systemen dabei sind.

	<footnote>
	  <para>Es gibt jetzt einige mächtige und freie IDEs in
	    der Ports-Sammlung wie etwa KDevelop.</para>
	</footnote>

	Trotzdem ist es möglich, seine eigene
	Entwicklungsumgebung aufzusetzen. Diese wird vielleicht nicht
	so hübsch und integriert sein, aber dafür
	können Sie sie Ihren eigenen Wünschen anpassen. Und
	sie ist frei. Und Sie haben die Quelltexte davon.</para>

      <para>Der Schlüssel zu all dem ist Emacs. Es gibt zwar ein
	paar Leute die ihn hassen, es gibt jedoch auch viele die ihn
	lieben. Falls Sie zu ersteren gehören befürchte ich,
	daß dieser Abschnitt Ihnen wenig interessantes zu bieten
	hat. Des weiteren benötigen Sie eine angemessene Menge an
	freiem Speicher, um ihn zu benutzen&mdash;ich würde 8MB
	für den Textmodus und 16MB unter X als absolutes Minimum
	empfehlen, um eine halbwegs brauchbare Performance zu
	erhalten.</para>

      <para>Emacs ist im Prinzip ein extrem anpassbarer Editor&mdash;
	in der Tat ist er so stark veränderbar, daß er eher
	einem Betriebssystem als einem Editor gleicht! Viele
	Entwickler und Systemadministratoren erledigen praktisch ihre
	gesamte Arbeit aus Emacs heraus und beenden ihn nur, um sich
	komplett auszuloggen.</para>

      <para>Es ist nicht einmal möglich alles hier
	zusammenzufassen, was man mit dem Emacs machen kann. Im
	Folgenden werden einige Features aufgelistet, die für
	einen Entwickler interessant sein könnten:</para>

      <itemizedlist>
	<listitem>
	  <para>Sehr mächtiger Editor, der suchen-und-ersetzen
	    mit Zeichenfolgen und regulären Ausdrücken
	    (Pattern) sowie das direkte Anspringen von Anfang/Ende von
	    Blockausdrücken erlaubt, etc, etc.</para>
	</listitem>

	<listitem>
	  <para>Pull-Down Menüs und eine Online-Hilfe.</para>
	</listitem>

	<listitem>
	  <para>Sprachunabhängige Syntaxhervorhebung und
	    automatische Einrückung.</para>
	</listitem>

	<listitem>
	  <para>Vollständig konfigurierbar.</para>
	</listitem>

	<listitem>
	  <para>Sie können Programme im Emacs kompilieren und
	    debuggen.</para>
	</listitem>

	<listitem>
	  <para>Bei Kompilationsfehlern können Sie direkt zu der
	    entsprechenden Zeile im Quelltext springen.</para>
	</listitem>

	<listitem>
	  <para>Benutzerfreundliches Front-End für das
	    <command>info</command>-Programm, um die GNU Hypertext
	    Dokumentation inklusive der Dokumentation des Emacs
	    selber.</para>
	</listitem>

	<listitem>
	  <para>Benutzerfreundliches Front-End für den
	    <command>gdb</command> um sich beim Verfolgen der
	    Programmanweisungen den zugehörigen Quelltext
	    anzeigen zu lassen.</para>
	</listitem>

	<listitem>
	  <para>Sie können E-Mails und News im Usenet lesen,
	    während ihr Programm kompiliert wird.</para>
	</listitem>
      </itemizedlist>

      <para>Und zweifelsfrei viele weitere Punkte, die ich
	übersehen habe.</para>

      <para>Emacs kann unter &os; über den	<filename
        role="package">editors/emacs</filename> Port installiert werden.</para>

      <para>Sobald er installiert ist starten Sie ihn, und geben
	dann <userinput>C-h t</userinput> ein, um die Einführung
	in Emacs zu lesen&mdash;d.h. Sie sollen bei gedrückter
	<keycap>Strg</keycap>-Taste die <keycap>h</keycap>-Taste
	drücken, beide wieder loslassen und anschließend
	<keycap>t</keycap> drücken. (Alternativ können Sie
	mit der Maus den Eintrag <guimenuitem>Emacs
	Tutorial</guimenuitem> aus dem
	<guimenu>Hilfe</guimenu>-Menü auswählen).</para>

      <para>Obwohl der Emacs Menüs besitzt ist das Erlernen der
	Tastaturkombinationen lohnenswert, da man beim Editieren sehr
	viel schneller Tastenkombinationen eingeben kann, als die Maus
	zu finden und mit dieser dann an der richtigen Stelle zu
	klicken. Und wenn Sie sich mit erfahrenen Emacs-Benutzern
	unterhalten werden Sie feststellen, daß diese
	häufig nebenbei Ausdrücke wie <quote><literal>M-x
	replace-s RET foo RET bar RET</literal></quote> verwenden,
	weshalb das Erlernen dieser sehr nützlich ist. Und Emacs
	hat auf jeden Fall weit mehr nützliche Funktionen als das
	diese in der Menüleiste unterzubringen wären.</para>

      <para>Zum Glück ist es sehr einfach die jeweiligen
	Tastaturkombinationen herauszubekommen, da diese direkt neben
	den Menüeinträgen stehen. Meine Empfehlung
	wäre, den Menüeintrag für, sagen wir, das
	Öffnen einer Datei zu verwenden, bis Sie die
	Funktionsweise verstanden haben und sie mit dieser vertraut
	sind, und es dann mit C-x C-f versuchen. Wenn Sie damit
	zufrieden sind, gehen Sie zum nächsten
	Menüeintrag.</para>

      <para>Falls Sie sich nicht daran erinnern können, was eine
	bestimmte Tastenkombination macht, wählen Sie
	<guimenuitem>Describe Key</guimenuitem> aus dem
	<guimenu>Hilfe</guimenu>-Menü aus und geben Sie die
	Tastenkombination ein&mdash;Emacs sagt Ihnen dann was diese
	macht. Sie können ebenfalls den Menüeintrag
	<guimenuitem>Command Apropos</guimenuitem> verwenden, um alle
	Befehle, die ein bestimmtes Wort enthalten, mit den
	zugehörigen Tastenkombinationen aufgelistet zu
	bekommen.</para>

      <para>Übrigends bedeutet der Ausdruck weiter oben, bei
	gedrückter <keysym>Meta</keysym>-Taste <keysym>x</keysym>
	zu drücken, beide wieder loszulassen,
	<userinput>replace-s</userinput> einzugeben (Kurzversion
	für <literal>replace-string</literal>&mdash;ein weiteres
	Feature des Emacs ist, daß Sie Befehle abkürzen
	können), anschließend die
	<keysym>return</keysym>-Taste zu drücken, dann
	<userinput>foo</userinput> einzugeben (die Zeichenkette, die
	Sie ersetzen möchten), dann wieder
	<keysym>return</keysym>, dann die Leertaste zu drücken
	(die Zeichenkette, mit der Sie <literal>foo</literal> ersetzen
	möchten) und anschließend erneut
	<keysym>return</keysym> zu drücken. Emacs wird dann die
	gewünschte suchen-und-ersetzen-Operation
	ausführen.</para>

      <para>Wenn Sie sich fragen was in aller Welt die
	<keysym>Meta</keysym>-Taste ist, das ist eine spezielle Taste
	die viele &unix;-Workstations besitzen. Bedauerlicherweise
	haben PCs keine solche Taste, und daher ist es
	üblicherweise die <keycap>alt</keycap>-Taste (oder falls
	Sie Pech haben die <keycap>Esc</keycap>-Taste).</para>

      <para>Oh, und um den Emacs zu verlassen müssen sie
	<command>C-x C-c</command> (das bedeutet, Sie müssen bei
	gedrückter <keysym>Strg</keysym>-Taste zuerst
	<keysym>x</keysym> und dann <keysym>c</keysym> drücken)
	eingeben. Falls Sie noch irgendwelche ungespeicherten Dateien
	offen haben wird Emacs Sie fragen ob Sie diese speichern
	wollen. (Ignorieren Sie bitte die Stelle der Dokumentation, an
	der gesagt wird, daß <command>C-z</command> der
	übliche Weg ist, Emacs zu verlassen&mdash;dadurch wird
	der Emacs in den Hintergrund geschaltet, was nur nützlich
	ist, wenn Sie an einem System ohne virtuelle Terminals
	arbeiten).</para>
    </sect2>

    <sect2>
      <title>Emacs konfigurieren</title>

      <para>Emacs kann viele wundervolle Dinge; manche dieser Dinge
	sind schon eingebaut, andere müssen erst konfiguriert
	werden.</para>

      <para>Anstelle einer proprietären Macrosprache verwendet
	der Emacs für die Konfiguration eine speziell für
	Editoren angepaßte Version von Lisp, auch bekannt als
	Emacs Lisp. Das Arbeiten mit Emacs Lisp kann sehr hilfreich
	sein, wenn Sie darauf aufbauend etwas wie Common Lisp lernen
	möchten. Emacs Lisp hat viele Features von Common Lisp
	obwohl es beträchtlich kleiner ist (und daher auch
	einfacher zu beherrschen).</para>

      <para>Der beste Weg um Emacs Lisp zu erlernen besteht darin,
	sich das <ulink
	url="ftp://ftp.gnu.org/old-gnu/emacs/elisp-manual-19-2.4.tar.gz">Emacs
	Tutorial</ulink> herunterzuladen.</para>

      <para>Es ist jedoch keine Kenntnis von Lisp erforderlich, um
	mit der Konfiguration von Emacs zu beginnen, da ich eine
	beispielhafte <filename>.emacs</filename>-Datei hier
	eingefügt habe, die für den Anfang ausreichen
	sollte. Kopieren Sie diese einfach in Ihr Heimverzeichnis und
	starten Sie den Emacs neu, falls dieser bereits läuft; er
	wird die Befehle aus der Datei lesen und Ihnen (hoffentlich)
	eine brauchbare Grundeinstellung bieten.</para>
    </sect2>

    <sect2>
      <title>Eine beispielhafte <filename>.emacs</filename>-Datei</title>

      <para>Bedauerlicherweise gibt es hier viel zu viel, um es im
	Detail zu erklären; es gibt jedoch ein oder zwei Punkte,
	die besonders erwähnenswert sind.</para>

      <itemizedlist>
	<listitem>
	  <para>Alles was mit einem <literal>;</literal> anfängt
	    ist ein Kommentar und wird von Emacs ignoriert.</para>
	</listitem>

	<listitem>
	  <para>In der ersten Zeile mit
	    <literal>-*-&nbsp;Emacs-Lisp&nbsp;-*-</literal> sorgt
	    dafür, daß wir die Datei
	    <filename>.emacs</filename> in Emacs selber editieren
	    können und uns damit alle tollen Features zum
	    Editieren von Emacs Lisp zur Verfügung stehen. Emacs
	    versucht dies normalerweise anhand des Dateinamens
	    auszumachen, was vielleicht bei
	    <filename>.emacs</filename> nicht funktionieren
	    könnte.</para>
	</listitem>

	<listitem>
	  <para>Die <keysym>Tab</keysym>-Taste ist in manchen Modi
	    an die Einrückungsfunktion gebunden, so daß
	    beim drücken dieser Taste die aktuelle Zeile
	    eingerückt wird. Wenn Sie ein
	    <token>tab</token>-Zeichen in einen Text, welchen auch
	    immer Sie dabei schreiben, einfügen wollen,
	    müssen Sie bei gedrückter
	    <keysym>Strg</keysym>-Taste die <keysym>Tab</keysym>-Taste
	    drücken.</para>
	</listitem>

	<listitem>
	  <para>Diese Datei unterstützt Syntax Highlighting
	    für C, C++, Perl, Lisp und Scheme, indem die Sprache
	    anhand des Dateinamens erraten wird.</para>
	</listitem>

	<listitem>
	  <para>Emacs hat bereits eine vordefinierte Funktion mit dem
	    Namen <function>next-error</function>. Diese erlaubt es
	    einem, in einem Fenster mit der Kompilierungsausgabe
	    mittels <command>M-n</command> von einem zum nächsten
	    Kompilierungsfehler zu springen; wir definieren eine
	    komplementäre Funktion
	    <function>previous-error</function>, die es uns erlaubt,
	    mittels <command>M-p</command> von einem zum vorherigen
	    Kompilierungsfehler zu springen. Das schönste Feature
	    von allen ist, daß mittels <command>C-c
	    C-c</command> die Quelltextdatei, in der der Fehler
	    aufgetreten ist, geöffnet und die betreffende Zeile
	    direkt angesprungen wird.</para>
	</listitem>

	<listitem>
	  <para>Wir aktivieren die Möglichkeit von Emacs als
	    Server zu agieren, so daß wenn Sie etwas
	    außerhalb von Emacs machen und eine Datei editieren
	    möchten, Sie einfach das folgende eingeben
	    können</para>

	  <screen>&prompt.user; <userinput>emacsclient <replaceable>filename</replaceable></userinput>
	  </screen>

	  <para>und dann die Datei in Ihrem Emacs editieren
	    können!

	    <footnote>
	      <para>Viele Emacs-Benutzer setzen Ihre
	        <envar>EDITOR</envar>-Umgebungsvariable auf
	        <literal>emacsclient</literal>, so daß dies
	        immer passiert, wenn sie eine Datei editieren
	        müssen.</para>
	    </footnote>
	  </para>
	</listitem>
      </itemizedlist>

      <example>
	<title>Eine einfache <filename>.emacs</filename>-Datei</title>

	<programlisting>;; -*-Emacs-Lisp-*-

;; This file is designed to be re-evaled; use the variable first-time
;; to avoid any problems with this.
(defvar first-time t
  "Flag signifying this is the first time that .emacs has been evaled")

;; Meta
(global-set-key "\M- " 'set-mark-command)
(global-set-key "\M-\C-h" 'backward-kill-word)
(global-set-key "\M-\C-r" 'query-replace)
(global-set-key "\M-r" 'replace-string)
(global-set-key "\M-g" 'goto-line)
(global-set-key "\M-h" 'help-command)

;; Function keys
(global-set-key [f1] 'manual-entry)
(global-set-key [f2] 'info)
(global-set-key [f3] 'repeat-complex-command)
(global-set-key [f4] 'advertised-undo)
(global-set-key [f5] 'eval-current-buffer)
(global-set-key [f6] 'buffer-menu)
(global-set-key [f7] 'other-window)
(global-set-key [f8] 'find-file)
(global-set-key [f9] 'save-buffer)
(global-set-key [f10] 'next-error)
(global-set-key [f11] 'compile)
(global-set-key [f12] 'grep)
(global-set-key [C-f1] 'compile)
(global-set-key [C-f2] 'grep)
(global-set-key [C-f3] 'next-error)
(global-set-key [C-f4] 'previous-error)
(global-set-key [C-f5] 'display-faces)
(global-set-key [C-f8] 'dired)
(global-set-key [C-f10] 'kill-compilation)

;; Keypad bindings
(global-set-key [up] "\C-p")
(global-set-key [down] "\C-n")
(global-set-key [left] "\C-b")
(global-set-key [right] "\C-f")
(global-set-key [home] "\C-a")
(global-set-key [end] "\C-e")
(global-set-key [prior] "\M-v")
(global-set-key [next] "\C-v")
(global-set-key [C-up] "\M-\C-b")
(global-set-key [C-down] "\M-\C-f")
(global-set-key [C-left] "\M-b")
(global-set-key [C-right] "\M-f")
(global-set-key [C-home] "\M-&lt;")
(global-set-key [C-end] "\M-&gt;")
(global-set-key [C-prior] "\M-&lt;")
(global-set-key [C-next] "\M-&gt;")

;; Mouse
(global-set-key [mouse-3] 'imenu)

;; Misc
(global-set-key [C-tab] "\C-q\t")	; Control tab quotes a tab.
(setq backup-by-copying-when-mismatch t)

;; Treat 'y' or &lt;CR&gt; as yes, 'n' as no.
(fset 'yes-or-no-p 'y-or-n-p)
(define-key query-replace-map [return] 'act)
(define-key query-replace-map [?\C-m] 'act)

;; Load packages
(require 'desktop)
(require 'tar-mode)

;; Pretty diff mode
(autoload 'ediff-buffers "ediff" "Intelligent Emacs interface to diff" t)
(autoload 'ediff-files "ediff" "Intelligent Emacs interface to diff" t)
(autoload 'ediff-files-remote "ediff"
  "Intelligent Emacs interface to diff")

(if first-time
    (setq auto-mode-alist
	  (append '(("\\.cpp$" . c++-mode)
		    ("\\.hpp$" . c++-mode)
		    ("\\.lsp$" . lisp-mode)
		    ("\\.scm$" . scheme-mode)
		    ("\\.pl$" . perl-mode)
		    ) auto-mode-alist)))

;; Auto font lock mode
(defvar font-lock-auto-mode-list
  (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode 'perl-mode 'scheme-mode)
  "List of modes to always start in font-lock-mode")

(defvar font-lock-mode-keyword-alist
  '((c++-c-mode . c-font-lock-keywords)
    (perl-mode . perl-font-lock-keywords))
  "Associations between modes and keywords")

(defun font-lock-auto-mode-select ()
  "Automatically select font-lock-mode if the current major mode is in font-lock-auto-mode-list"
  (if (memq major-mode font-lock-auto-mode-list)
      (progn
	(font-lock-mode t))
    )
  )

(global-set-key [M-f1] 'font-lock-fontify-buffer)

;; New dabbrev stuff
;(require 'new-dabbrev)
(setq dabbrev-always-check-other-buffers t)
(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
(add-hook 'emacs-lisp-mode-hook
	  '(lambda ()
	     (set (make-local-variable 'dabbrev-case-fold-search) nil)
	     (set (make-local-variable 'dabbrev-case-replace) nil)))
(add-hook 'c-mode-hook
	  '(lambda ()
	     (set (make-local-variable 'dabbrev-case-fold-search) nil)
	     (set (make-local-variable 'dabbrev-case-replace) nil)))
(add-hook 'text-mode-hook
	  '(lambda ()
	     (set (make-local-variable 'dabbrev-case-fold-search) t)
	     (set (make-local-variable 'dabbrev-case-replace) t)))

;; C++ and C mode...
(defun my-c++-mode-hook ()
  (setq tab-width 4)
  (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
  (define-key c++-mode-map "\C-ce" 'c-comment-edit)
  (setq c++-auto-hungry-initial-state 'none)
  (setq c++-delete-function 'backward-delete-char)
  (setq c++-tab-always-indent t)
  (setq c-indent-level 4)
  (setq c-continued-statement-offset 4)
  (setq c++-empty-arglist-indent 4))

(defun my-c-mode-hook ()
  (setq tab-width 4)
  (define-key c-mode-map "\C-m" 'reindent-then-newline-and-indent)
  (define-key c-mode-map "\C-ce" 'c-comment-edit)
  (setq c-auto-hungry-initial-state 'none)
  (setq c-delete-function 'backward-delete-char)
  (setq c-tab-always-indent t)
;; BSD-ish indentation style
  (setq c-indent-level 4)
  (setq c-continued-statement-offset 4)
  (setq c-brace-offset -4)
  (setq c-argdecl-indent 0)
  (setq c-label-offset -4))

;; Perl mode
(defun my-perl-mode-hook ()
  (setq tab-width 4)
  (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
  (setq perl-indent-level 4)
  (setq perl-continued-statement-offset 4))

;; Scheme mode...
(defun my-scheme-mode-hook ()
  (define-key scheme-mode-map "\C-m" 'reindent-then-newline-and-indent))

;; Emacs-Lisp mode...
(defun my-lisp-mode-hook ()
  (define-key lisp-mode-map "\C-m" 'reindent-then-newline-and-indent)
  (define-key lisp-mode-map "\C-i" 'lisp-indent-line)
  (define-key lisp-mode-map "\C-j" 'eval-print-last-sexp))

;; Add all of the hooks...
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
(add-hook 'c-mode-hook 'my-c-mode-hook)
(add-hook 'scheme-mode-hook 'my-scheme-mode-hook)
(add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook)
(add-hook 'lisp-mode-hook 'my-lisp-mode-hook)
(add-hook 'perl-mode-hook 'my-perl-mode-hook)

;; Complement to next-error
(defun previous-error (n)
  "Visit previous compilation error message and corresponding source code."
  (interactive "p")
  (next-error (- n)))

;; Misc...
(transient-mark-mode 1)
(setq mark-even-if-inactive t)
(setq visible-bell nil)
(setq next-line-add-newlines nil)
(setq compile-command "make")
(setq suggest-key-bindings nil)
(put 'eval-expression 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'set-goal-column 'disabled nil)
(if (&gt;= emacs-major-version 21)
	(setq show-trailing-whitespace t))

;; Elisp archive searching
(autoload 'format-lisp-code-directory "lispdir" nil t)
(autoload 'lisp-dir-apropos "lispdir" nil t)
(autoload 'lisp-dir-retrieve "lispdir" nil t)
(autoload 'lisp-dir-verify "lispdir" nil t)

;; Font lock mode
(defun my-make-face (face color &amp;optional bold)
  "Create a face from a color and optionally make it bold"
  (make-face face)
  (copy-face 'default face)
  (set-face-foreground face color)
  (if bold (make-face-bold face))
  )

(if (eq window-system 'x)
    (progn
      (my-make-face 'blue "blue")
      (my-make-face 'red "red")
      (my-make-face 'green "dark green")
      (setq font-lock-comment-face 'blue)
      (setq font-lock-string-face 'bold)
      (setq font-lock-type-face 'bold)
      (setq font-lock-keyword-face 'bold)
      (setq font-lock-function-name-face 'red)
      (setq font-lock-doc-string-face 'green)
      (add-hook 'find-file-hooks 'font-lock-auto-mode-select)

      (setq baud-rate 1000000)
      (global-set-key "\C-cmm" 'menu-bar-mode)
      (global-set-key "\C-cms" 'scroll-bar-mode)
      (global-set-key [backspace] 'backward-delete-char)
					;      (global-set-key [delete] 'delete-char)
      (standard-display-european t)
      (load-library "iso-transl")))

;; X11 or PC using direct screen writes
(if window-system
    (progn
      ;;      (global-set-key [M-f1] 'hilit-repaint-command)
      ;;      (global-set-key [M-f2] [?\C-u M-f1])
      (setq hilit-mode-enable-list
	    '(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode
		  scheme-mode)
	    hilit-auto-highlight nil
	    hilit-auto-rehighlight 'visible
	    hilit-inhibit-hooks nil
	    hilit-inhibit-rebinding t)
      (require 'hilit19)
      (require 'paren))
  (setq baud-rate 2400)			; For slow serial connections
  )

;; TTY type terminal
(if (and (not window-system)
	 (not (equal system-type 'ms-dos)))
    (progn
      (if first-time
	  (progn
	    (keyboard-translate ?\C-h ?\C-?)
	    (keyboard-translate ?\C-? ?\C-h)))))

;; Under UNIX
(if (not (equal system-type 'ms-dos))
    (progn
      (if first-time
	  (server-start))))

;; Add any face changes here
(add-hook 'term-setup-hook 'my-term-setup-hook)
(defun my-term-setup-hook ()
  (if (eq window-system 'pc)
      (progn
;;	(set-face-background 'default "red")
	)))

;; Restore the "desktop" - do this as late as possible
(if first-time
    (progn
      (desktop-load-default)
      (desktop-read)))

;; Indicate that this file has been read at least once
(setq first-time nil)

;; No need to debug anything now

(setq debug-on-error nil)

;; All done
(message "All done, %s%s" (user-login-name) ".")
	</programlisting>
      </example>
    </sect2>

    <sect2>
      <title>Erweitern des von Emacs unterstützten Sprachbereichs</title>

      <para>Das ist jetzt alles sehr schön wenn Sie
	ausschließlich in einer der Sprachen programmieren
	wollen, um die wir uns bereits in der
	<filename>.emacs</filename>-Datei gekümmert haben (C,
	C++, Perl, Lisp und Scheme), aber was passiert wenn eine neue
	Sprache namens <quote>whizbang</quote> herauskommt, mit jeder
	Menge neuen tollen Features?</para>

      <para>Als erstes muß festgestellt werden, ob whizbang mit
	irgendwelchen Dateien daherkommt, die Emacs etwas über
	die Sprache sagen. Diese enden üblicherweise auf
	<filename>.el</filename>, der Kurzform für <quote>Emacs
	Lisp</quote>. Falls whizbang zum Beispiel ein FreeBSD Port
	ist, könnten wir diese Dateien mittels</para>

      <screen>&prompt.user; <userinput>find /usr/ports/lang/whizbang -name "*.el" -print</userinput></screen>

      <para>finden und durch Kopieren in das Emacs-seitige
	Lisp-Verzeichnis installieren. Unter &os; ist dies
	<filename>/usr/local/share/emacs/site-lisp</filename>.</para>

      <para>Wenn zum Beispiel die Ausgabe des find-Befehls wie folgt
	war</para>

      <screen>/usr/ports/lang/whizbang/work/misc/whizbang.el</screen>

      <para>könnten wir das folgende tun</para>

      <screen>&prompt.root; <userinput>cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp</userinput></screen>

      <para>Als nächstes müssen wir festlegen, welche
	Dateiendung Quelltextdateien für whizbang haben. Lassen
	Sie uns um der Argumente Willen annehmen, die Dateiendung sei
	<filename>.wiz</filename>. Wir müssen dann einen Eintrag
	unserer <filename>.emacs</filename>-Datei hinzufügen um
	sicherzustellen, daß Emacs die Informationen in
	<filename>whizbang.el</filename> auch verwenden kann.</para>

      <para>Suchen Sie den <symbol>auto-mode-alist Eintrag</symbol>
	in der <filename>.emacs</filename>-Datei und fügen Sie an
	dieser Stelle eine Zeile wie folgt für whizbang
	hinzu:</para>

      <programlisting><lineannotation>&hellip;</lineannotation>
("\\.lsp$" . lisp-mode)
("\\.wiz$" . whizbang-mode)
("\\.scm$" . scheme-mode)
<lineannotation>&hellip;</lineannotation></programlisting>

      <para>Dies bedeutet das Emacs automatisch in den
	<function>whizbang-mode</function> wechseln wird, wenn Sie
	eine Datei mit der Dateiendung <filename>.wiz</filename>
	editieren.</para>

      <para>Direkt darunter werden Sie den Eintrag
	<symbol>font-lock-auto-mode-list</symbol> finden. Erweitern
	Sie den <function>whizbang-mode</function> um diesen wie
	folgt:</para>

      <programlisting>;; Auto font lock mode
(defvar font-lock-auto-mode-list
  (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'whizbang-mode 'lisp-mode 'perl-mode 'scheme-mode)
  "List of modes to always start in font-lock-mode")</programlisting>

      <para>Dies bedeutet das Emacs immer
	<function>font-lock-mode</function> (z.B. Syntax Highlighting)
	aktiviert, wenn Sie eine <filename>.wiz</filename>-Datei
	editieren.</para>

      <para>Und das ist alles was benötigt wird. Falls es
	weitere Dinge gibt, die automatisch beim Öffnen einer
	<filename>.wiz</filename>-Datei ausgeführt werden sollen,
	können Sie einen <function>whizbang-mode
	hook</function>-Eintrag hinzufügen (für ein
	einfaches Beispiel, welches <function>auto-indent</function>
	hinzufügt, sehen Sie sich bitte
	<function>my-scheme-mode-hook</function> an).</para>
    </sect2>
  </sect1>

  <sect1 id="tools-reading">
    <title>Weiterführende Literatur</title>

    <para>Für Informationen zum Aufsetzen einer
      Entwicklungsumgebung, um Fehlerbehebungen an FreeBSD selber
      beizusteuern sehen Sie sich bitte &man.development.7; an.</para>

    <itemizedlist>
      <listitem>
	<para>Brian Harvey and Matthew Wright
	  <emphasis>Simply Scheme</emphasis>
	  MIT 1994.<!-- <br> -->
	  ISBN 0-262-08226-8</para>
      </listitem>

      <listitem>
	<para>Randall Schwartz
	  <emphasis>Learning Perl</emphasis>
	  O'Reilly 1993<!-- <br> -->
	  ISBN 1-56592-042-2</para>
      </listitem>

      <listitem>
	<para>Patrick Henry Winston and Berthold Klaus Paul Horn
	  <emphasis>Lisp (3rd Edition)</emphasis>
	  Addison-Wesley 1989<!-- <br> -->
	  ISBN 0-201-08319-1</para>
      </listitem>

      <listitem>
	<para>Brian W. Kernighan and Rob Pike
	  <emphasis>The Unix Programming Environment</emphasis>
	  Prentice-Hall 1984<!-- <br> -->
	  ISBN 0-13-937681-X</para>
      </listitem>

      <listitem>
	<para>Brian W. Kernighan and Dennis M. Ritchie
	  <emphasis>The C Programming Language (2nd Edition)</emphasis>
	  Prentice-Hall 1988<!-- <br> -->
	  ISBN 0-13-110362-8</para>
      </listitem>

      <listitem>
	<para>Bjarne Stroustrup
	<emphasis>The C++ Programming Language</emphasis>
	Addison-Wesley 1991<!-- <br> -->
	ISBN 0-201-53992-6</para>
      </listitem>

      <listitem>
	<para>W. Richard Stevens
	  <emphasis>Advanced Programming in the Unix Environment</emphasis>
	  Addison-Wesley 1992<!-- <br> -->
	  ISBN 0-201-56317-7</para>
      </listitem>

      <listitem>
	<para>W. Richard Stevens
	  <emphasis>Unix Network Programming</emphasis>
	  Prentice-Hall 1990<!-- <br> -->
	  ISBN 0-13-949876-1</para>
      </listitem>
    </itemizedlist>
  </sect1>

</chapter>