diff options
Diffstat (limited to 'en_US.ISO8859-1/books')
-rw-r--r-- | en_US.ISO8859-1/books/arch-handbook/book.sgml | 2257 | ||||
-rw-r--r-- | en_US.ISO8859-1/books/developers-handbook/book.sgml | 2257 |
2 files changed, 4498 insertions, 16 deletions
diff --git a/en_US.ISO8859-1/books/arch-handbook/book.sgml b/en_US.ISO8859-1/books/arch-handbook/book.sgml index 8aacd1d42a..bd58d4a25a 100644 --- a/en_US.ISO8859-1/books/arch-handbook/book.sgml +++ b/en_US.ISO8859-1/books/arch-handbook/book.sgml @@ -1,7 +1,7 @@ <!-- The FreeBSD Documentation Project - $FreeBSD: doc/en_US.ISO_8859-1/books/developers-handbook/book.sgml,v 1.4 2000/11/06 10:22:11 murray Exp $ + $FreeBSD: doc/en_US.ISO_8859-1/books/developers-handbook/book.sgml,v 1.5 2000/11/06 13:52:26 murray Exp $ --> <!DOCTYPE BOOK PUBLIC "-//FreeBSD//DTD DocBook V3.1-Based Extension//EN" [ @@ -205,14 +205,2255 @@ <part id="Basics"> <title>Basics</title> - <chapter id="compilation"> - <title>Compilation</title> + <chapter id="programming-tools"> + <title>Programming Tools</title> - <para>This will include things like: compilation, makefiles, .mk - files, basic debugging, linking, secure programming - guidelines, style(9), CVS, diff, patch, etc.</para> + <para><emphasis>This chapter was written by James Raynard. + Modifications for the Developer's Handbook by Murray Stokely. + </emphasis></para> + + <sect1><title>Synopsis</title> + + <para>This document is an introduction to using some of the + programming tools supplied with FreeBSD, although much of it + will be applicable to many other versions of Unix. It does + <emphasis>not</emphasis> attempt to describe coding in any + detail. Most of the document assumes little or no previous + programming knowledge, although it is hoped that most + programmers will find something of value in it</para> + + </sect1> + + <sect1><title>Introduction</title> + + <para>FreeBSD offers an excellent development environment. + Compilers for C, C++, and Fortran and an assembler come with the + basic system, not to mention a Perl interpreter and classic Unix + tools such as <command>sed</command> and <command>awk</command>. + If that is not enough, there are many more compilers and + interpreters in the Ports collection. FreeBSD is very + compatible with standards such as <acronym>POSIX</acronym> and + <acronym>ANSI</acronym> C, as well with its own BSD heritage, so + it is possible to write applications that will compile and run + with little or no modification on a wide range of + platforms.</para> + + <para>However, all this power can be rather overwhelming at + first if you've never written programs on a Unix platform + before. This document aims to help you get up and running, + without getting too deeply into more advanced topics. The + intention is that this document should give you enough of the + basics to be able to make some sense of the + documentation.</para> + + <para>Most of the document requires little or no knowledge of + programming, although it does assume a basic competence with + using Unix and a willingness to learn!</para> + + </sect1> + + <sect1> + <title>Introduction to Programming</title> + + <para>A program is a set of instructions that tell the computer + to do various things; sometimes the instruction it has to + perform depends on what happened when it performed a previous + instruction. This section gives an overview of the two main + ways in which you can give these instructions, or + <quote>commands</quote> as they are usually called. One way + uses an <firstterm>interpreter</firstterm>, the other a + <firstterm>compiler</firstterm>. As human languages are too + difficult for a computer to understand in an unambiguous way, + commands are usually written in one or other languages specially + designed for the purpose.</para> + + <sect2> + <title>Interpreters</title> + + <para>With an interpreter, the language comes as an environment, + where you type in commands at a prompt and the environment + executes them for you. For more complicated programs, you can + type the commands into a file and get the interpreter to load + the file and execute the commands in it. If anything goes + wrong, many interpreters will drop you into a debugger to help + you track down the problem.</para> + + <para>The advantage of this is that you can see the results of + your commands immediately, and mistakes can be corrected + readily. The biggest disadvantage comes when you want to + share your programs with someone. They must have the same + interpreter, or you must have some way of giving it to them, + and they need to understand how to use it. Also users may not + appreciate being thrown into a debugger if they press the + wrong key! From a performance point of view, interpreters can + use up a lot of memory, and generally do not generate code as + efficiently as compilers.</para> + + <para>In my opinion, interpreted languages are the best way to + start if you have not done any programming before. This kind + of environment is typically found with languages like Lisp, + Smalltalk, Perl and Basic. It could also be argued that the + Unix shell (<command>sh</command>, <command>csh</command>) is itself an + interpreter, and many people do in fact write shell + <quote>scripts</quote> to help with various + <quote>housekeeping</quote> tasks on their machine. Indeed, part + of the original Unix philosophy was to provide lots of small + utility programs that could be linked together in shell + scripts to perform useful tasks.</para> + </sect2> + + <sect2> + <title>Interpreters available with FreeBSD</title> + + <para>Here is a list of interpreters that are available as + <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/">FreeBSD + packages</ulink>, with a brief discussion of some of the + more popular interpreted languages.</para> + + <para>To get one of these packages, all you need to do is to + click on the hotlink for the package, then run</para> + + <screen>&prompt.root; <userinput>pkg_add <replaceable>package name</></userinput> + </screen> + + <para>as root. Obviously, you will need to have a fully + functional FreeBSD 2.1.0 or later system for the package to + work!</para> + + <variablelist> + <varlistentry> + <term><acronym>BASIC</acronym></term> + + <listitem> + <para>Short for Beginner's All-purpose Symbolic + Instruction Code. Developed in the 1950s for teaching + University students to program and provided with every + self-respecting personal computer in the 1980s, + <acronym>BASIC</acronym> has been the first programming + language for many programmers. It's also the foundation + for Visual Basic.</para> + + <para>The <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/bwbasic-2.10.tgz">Bywater + Basic Interpreter</ulink> and the <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/pbasic-2.0.tgz">Phil + Cockroft's Basic Interpreter</ulink> (formerly Rabbit + Basic) are available as FreeBSD <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/">FreeBSD + packages</ulink></para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Lisp</term> + + <listitem> + <para>A language that was developed in the late 1950s as + an alternative to the <quote>number-crunching</quote> + languages that were popular at the time. Instead of + being based on numbers, Lisp is based on lists; in fact + the name is short for <quote>List Processing</quote>. + Very popular in AI (Artificial Intelligence) + circles.</para> + + <para>Lisp is an extremely powerful and sophisticated + language, but can be rather large and unwieldy.</para> + + <para>FreeBSD has <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/gcl-2.0.tgz">GNU + Common Lisp</ulink> available as a package.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Perl</term> + + <listitem> + <para>Very popular with system administrators for writing + scripts; also often used on World Wide Web servers for + writing <acronym>CGI</acronym> scripts.</para> + + <para>The latest version (version 5) comes with FreeBSD.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Scheme</term> + + <listitem> + <para>A dialect of Lisp that is rather more compact and + cleaner than Common Lisp. Popular in Universities as it + is simple enough to teach to undergraduates as a first + language, while it has a high enough level of + abstraction to be used in research work.</para> + + <para>FreeBSD has packages of the <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/elk-3.0.tgz">Elk + Scheme Interpreter</ulink>, the <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/mit-scheme-7.3.tgz">MIT + Scheme Interpreter</ulink> and the <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/scm-4e1.tgz">SCM + Scheme Interpreter</ulink>.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Icon</term> + + <listitem> + <para><ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/icon-9.0.tgz">The + Icon Programming Language</ulink>.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Logo</term> + + <listitem> + <para><ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/ucblogo-3.3.tgz">Brian + Harvey's LOGO Interpreter</ulink>.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Python</term> + + <listitem> + <para><ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/python-1.2">The + Python Object-Oriented Programming + Language</ulink></para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + + <sect2> + <title>Compilers</title> + + <para>Compilers are rather different. First of all, you write + your code in a file (or files) using an editor. You then run + the compiler and see if it accepts your program. If it did + not compile, grit your teeth and go back to the editor; if it + did compile and gave you a program, you can run it either at a + shell command prompt or in a debugger to see if it works + properly. + + <footnote> + <para>If you run it in the shell, you may get a core + dump.</para> + </footnote></para> + + <para>Obviously, this is not quite as direct as using an + interpreter. However it allows you to do a lot of things + which are very difficult or even impossible with an + interpreter, such as writing code which interacts closely with + the operating system—or even writing your own operating + system! It's also useful if you need to write very efficient + code, as the compiler can take its time and optimise the code, + which would not be acceptable in an interpreter. And + distributing a program written for a compiler is usually more + straightforward than one written for an interpreter—you + can just give them a copy of the executable, assuming they + have the same operating system as you.</para> + + <para>Compiled languages include Pascal, C and C++. C and C++ + are rather unforgiving languages, and best suited to more + experienced programmers; Pascal, on the other hand, was + designed as an educational language, and is quite a good + language to start with. Unfortunately, FreeBSD doesn't have + any Pascal support, except for a Pascal-to-C converter in the + ports.</para> + + <para>As the edit-compile-run-debug cycle is rather tedious when + using separate programs, many commercial compiler makers have + produced Integrated Development Environments + + (<acronym>IDE</acronym>s for short). FreeBSD does not have an + <acronym>IDE</acronym> as such; however it is possible to use Emacs + for this purpose. This is discussed in <xref + linkend="emacs">.</para> + </sect2> + + + </sect1> + + + <sect1> + <title>Compiling with <command>cc</command></title> + + <para>This section deals only with the GNU compiler for C and C++, + since that comes with the base FreeBSD system. It can be + invoked by either <command>cc</command> or <command>gcc</command>. The + details of producing a program with an interpreter vary + considerably between interpreters, and are usually well covered + in the documentation and on-line help for the + interpreter.</para> + + <para>Once you've written your masterpiece, the next step is to + convert it into something that will (hopefully!) run on FreeBSD. + This usually involves several steps, each of which is done by a + separate program.</para> + + <procedure> + <step> + <para>Pre-process your source code to remove comments and do + other tricks like expanding macros in C.</para> + </step> + + <step> + <para>Check the syntax of your code to see if you have obeyed + the rules of the language. If you have not, it will + complain!</para> + </step> + + <step> + <para>Convert the source code into assembly + language—this is very close to machine code, but still + understandable by humans. Allegedly. + + <footnote> + <para>To be strictly accurate, <command>cc</command> converts the + source code into its own, machine-independent + <firstterm>p-code</firstterm> instead of assembly language at + this stage.</para> + </footnote></para> + </step> + + <step> + <para>Convert the assembly language into machine + code—yep, we are talking bits and bytes, ones and + zeros here.</para> + </step> + + <step> + <para>Check that you have used things like functions and + global variables in a consistent way. For example, if you + have called a non-existent function, it will + complain.</para> + </step> + + <step> + <para>If you are trying to produce an executable from several + source code files, work out how to fit them all + together.</para> + </step> + + <step> + <para>Work out how to produce something that the system's + run-time loader will be able to load into memory and + run.</para> + </step> + + <step> + <para>Finally, write the executable on the file system.</para> + </step> + </procedure> + + <para>The word <firstterm>compiling</firstterm> is often used to refer to + just steps 1 to 4—the others are referred to as + <firstterm>linking</firstterm>. Sometimes step 1 is referred to as + <firstterm>pre-processing</firstterm> and steps 3-4 as + <firstterm>assembling</firstterm>.</para> + + <para>Fortunately, almost all this detail is hidden from you, as + <command>cc</command> is a front end that manages calling all these + programs with the right arguments for you; simply typing</para> + + <screen>&prompt.user; <userinput>cc foobar.c</> + </screen> + + <para>will cause <filename>foobar.c</filename> to be compiled by all the + steps above. If you have more than one file to compile, just do + something like</para> + + <screen>&prompt.user; <userinput>cc foo.c bar.c</> + </screen> + + <para>Note that the syntax checking is just that—checking + the syntax. It will not check for any logical mistakes you may + have made, like putting the program into an infinite loop, or + using a bubble sort when you meant to use a binary + sort. + + <footnote> + <para>In case you didn't know, a binary sort is an efficient + way of sorting things into order and a bubble sort + isn't.</para> + </footnote></para> + + <para>There are lots and lots of options for <command>cc</command>, which + are all in the man page. Here are a few of the most important + ones, with examples of how to use them.</para> + + <variablelist> + <varlistentry> + <term><option>-o <replaceable>filename</replaceable></option></term> + + <listitem> + <para>The output name of the file. If you do not use this + option, <command>cc</command> will produce an executable called + <filename>a.out</filename>. + + <footnote> + <para>The reasons for this are buried in the mists of + history.</para> + </footnote></para> + + <informalexample> + <screen>&prompt.user; <userinput>cc foobar.c</> <lineannotation>executable is <filename>a.out</></> +&prompt.user; <userinput>cc -o foobar foobar.c</> <lineannotation>executable is <filename>foobar</></> + </screen> + </informalexample> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-c</option></term> + + <listitem> + <para>Just compile the file, do not link it. Useful for toy + programs where you just want to check the syntax, or if + you are using a <filename>Makefile</filename>.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -c foobar.c</userinput> + </screen> + </informalexample> + + <para>This will produce an <firstterm>object file</firstterm> (not an + executable) called <filename>foobar.o</filename>. This + can be linked together with other object files into an + executable.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-g</option></term> + + <listitem> + <para>Create a debug version of the executable. This makes + the compiler put information into the executable about + which line of which source file corresponds to which + function call. A debugger can use this information to show + the source code as you step through the program, which is + <emphasis>very</emphasis> useful; the disadvantage is that + all this extra information makes the program much bigger. + Normally, you compile with <option>-g</option> while you + are developing a program and then compile a <quote>release + version</quote> without <option>-g</option> when you're + satisfied it works properly.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -g foobar.c</userinput> + </screen> + </informalexample> + + <para>This will produce a debug version of the + program. + + <footnote> + <para>Note, we didn't use the <option>-o</option> flag + to specify the executable name, so we will get an + executable called <filename>a.out</filename>. + Producing a debug version called + <filename>foobar</filename> is left as an exercise for + the reader!</para> + </footnote></para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-O</option></term> + + <listitem> + <para>Create an optimised version of the executable. The + compiler performs various clever tricks to try and produce + an executable that runs faster than normal. You can add a + number after the <option>-O</option> to specify a higher + level of optimisation, but this often exposes bugs in the + compiler's optimiser. For instance, the version of + <command>cc</command> that comes with the 2.1.0 release of + FreeBSD is known to produce bad code with the + <option>-O2</option> option in some circumstances.</para> + + <para>Optimisation is usually only turned on when compiling + a release version.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -O -o foobar foobar.c</userinput> + </screen> + </informalexample> + + <para>This will produce an optimised version of + <filename>foobar</filename>.</para> + </listitem> + </varlistentry> + </variablelist> + + <para>The following three flags will force <command>cc</command> + to check that your code complies to the relevant international + standard, often referred to as the <acronym>ANSI</acronym> + standard, though strictly speaking it is an + <acronym>ISO</acronym> standard.</para> + + <variablelist> + <varlistentry> + <term><option>-Wall</option></term> + + <listitem> + <para>Enable all the warnings which the authors of + <command>cc</command> believe are worthwhile. Despite the + name, it will not enable all the warnings + <command>cc</command> is capable of.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-ansi</option></term> + + <listitem> + <para>Turn off most, but not all, of the + non-<acronym>ANSI</acronym> C features provided by + <command>cc</command>. Despite the name, it does not + guarantee strictly that your code will comply to the + standard.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-pedantic</option></term> + + <listitem> + <para>Turn off <emphasis>all</emphasis> + <command>cc</command>'s non-<acronym>ANSI</acronym> C + features.</para> + </listitem> + </varlistentry> + </variablelist> + + <para>Without these flags, <command>cc</command> will allow you to + use some of its non-standard extensions to the standard. Some + of these are very useful, but will not work with other + compilers—in fact, one of the main aims of the standard is + to allow people to write code that will work with any compiler + on any system. This is known as <firstterm>portable + code</firstterm>.</para> + + <para>Generally, you should try to make your code as portable as + possible, as otherwise you may have to completely re-write the + program later to get it to work somewhere else—and who + knows what you may be using in a few years time?</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -Wall -ansi -pedantic -o foobar foobar.c</userinput> + </screen> + </informalexample> + + <para>This will produce an executable <filename>foobar</filename> + after checking <filename>foobar.c</filename> for standard + compliance.</para> + + <variablelist> + <varlistentry> + <term><option>-l<replaceable>library</replaceable></option></term> + + <listitem> + <para>Specify a function library to be used during when + linking.</para> + + <para>The most common example of this is when compiling a + program that uses some of the mathematical functions in C. + Unlike most other platforms, these are in a separate + library from the standard C one and you have to tell the + compiler to add it.</para> + + <para>The rule is that if the library is called + <filename>lib<replaceable>something</replaceable>.a</filename>, + you give <command>cc</command> the argument + <option>-l<replaceable>something</replaceable></option>. + For example, the math library is + <filename>libm.a</filename>, so you give + <command>cc</command> the argument <option>-lm</option>. + A common <quote>gotcha</quote> with the math library is + that it has to be the last library on the command + line.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput> + </screen> + </informalexample> + + <para>This will link the math library functions into + <filename>foobar</filename>.</para> + + <para>If you are compiling C++ code, you need to add + <option>-lg++</option>, or <option>-lstdc++</option> if + you are using FreeBSD 2.2 or later, to the command line + argument to link the C++ library functions. + Alternatively, you can run <command>c++</command> instead + of <command>cc</command>, which does this for you. + <command>c++</command> can also be invoked as + <command>g++</command> on FreeBSD.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -o foobar foobar.cc -lg++</userinput> <lineannotation>For FreeBSD 2.1.6 and earlier</> +&prompt.user; <userinput>cc -o foobar foobar.cc -lstdc++</userinput> <lineannotation>For FreeBSD 2.2 and later</> +&prompt.user; <userinput>c++ -o foobar foobar.cc</userinput> + </screen> + </informalexample> + + <para>Each of these will both produce an executable + <filename>foobar</filename> from the C++ source file + <filename>foobar.cc</filename>. Note that, on Unix + systems, C++ source files traditionally end in + <filename>.C</filename>, <filename>.cxx</filename> or + <filename>.cc</filename>, rather than the + MS-DOS style + <filename>.cpp</filename> (which was already used for + something else). <command>gcc</command> used to rely on + this to work out what kind of compiler to use on the + source file; however, this restriction no longer applies, + so you may now call your C++ files + <filename>.cpp</filename> with impunity!</para> + </listitem> + </varlistentry> + </variablelist> + + <sect2> + <title>Common <command>cc</command> Queries and Problems</title> + + <qandaset> + <qandaentry> + <question> + <para>I am trying to write a program which uses the + <function>sin()</function> function and I get an error + like this. What does it mean?</para> + + <informalexample> + <screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment + </screen> + </informalexample> + </question> + + <answer> + <para>When using mathematical functions like + <function>sin()</function>, you have to tell + <command>cc</command> to link in the math library, like + so:</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput> + </screen> + </informalexample> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>All right, I wrote this simple program to practice + using <option>-lm</option>. All it does is raise 2.1 to + the power of 6.</para> + + <informalexample> + <programlisting>#include <stdio.h> + +int main() { + float f; + + f = pow(2.1, 6); + printf("2.1 ^ 6 = %f\n", f); + return 0; +} + </programlisting> + </informalexample> + + <para>and I compiled it as:</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc temp.c -lm</userinput> + </screen> + </informalexample> + + <para>like you said I should, but I get this when I run + it:</para> + + <informalexample> + <screen>&prompt.user; <userinput>./a.out</userinput> +2.1 ^ 6 = 1023.000000 + </screen> + </informalexample> + + <para>This is <emphasis>not</emphasis> the right answer! + What is going on?</para> + </question> + + <answer> + <para>When the compiler sees you call a function, it + checks if it has already seen a prototype for it. If it + has not, it assumes the function returns an + <type>int</type>, which is definitely not what you want + here.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>So how do I fix this?</para> + </question> + + <answer> + <para>The prototypes for the mathematical functions are in + <filename>math.h</filename>. If you include this file, + the compiler will be able to find the prototype and it + will stop doing strange things to your + calculation!</para> + + <informalexample> + <programlisting>#include <math.h> +#include <stdio.h> + +int main() { +... + </programlisting> + </informalexample> + + <para>After recompiling it as you did before, run + it:</para> + + <informalexample> + <screen>&prompt.user; <userinput>./a.out</userinput> +2.1 ^ 6 = 85.766121 + </screen> + </informalexample> + + <para>If you are using any of the mathematical functions, + <emphasis>always</emphasis> include + <filename>math.h</filename> and remember to link in the + math library.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>I compiled a file called + <filename>foobar.c</filename> and I cannot find an + executable called <filename>foobar</filename>. Where's + it gone?</para> + </question> + + <answer> + <para>Remember, <command>cc</command> will call the + executable <filename>a.out</filename> unless you tell it + differently. Use the + <option>-o <replaceable>filename</replaceable></option> + option:</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -o foobar foobar.c</userinput> + </screen> + </informalexample> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>OK, I have an executable called + <filename>foobar</filename>, I can see it when I run + <command>ls</command>, but when I type in + <command>foobar</command> at the command prompt it tells + me there is no such file. Why can it not find + it?</para> + </question> + + <answer> + <para>Unlike MS-DOS, Unix does not + look in the current directory when it is trying to find + out which executable you want it to run, unless you tell + it to. Either type <command>./foobar</command>, which + means <quote>run the file called + <filename>foobar</filename> in the current + directory</quote>, or change your <systemitem + class=environvar>PATH</systemitem> environment + variable so that it looks something like</para> + + <informalexample> + <screen>bin:/usr/bin:/usr/local/bin:. + </screen> + </informalexample> + + <para>The dot at the end means <quote>look in the current + directory if it is not in any of the + others</quote>.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>I called my executable <filename>test</filename>, + but nothing happens when I run it. What is going + on?</para> + </question> + + <answer> + <para>Most Unix systems have a program called + <command>test</command> in <filename>/usr/bin</filename> + and the shell is picking that one up before it gets to + checking the current directory. Either type:</para> + + <informalexample> + <screen>&prompt.user; <userinput>./test</userinput> + </screen> + </informalexample> + + <para>or choose a better name for your program!</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>I compiled my program and it seemed to run all right + at first, then there was an error and it said something + about <errorname>core dumped</errorname>. What does that + mean?</para> + </question> + + <answer> + <para>The name <firstterm>core dump</firstterm> dates back + to the very early days of Unix, when the machines used + core memory for storing data. Basically, if the program + failed under certain conditions, the system would write + the contents of core memory to disk in a file called + <filename>core</filename>, which the programmer could + then pore over to find out what went wrong.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>Fascinating stuff, but what I am supposed to do + now?</para> + </question> + + <answer> + <para>Use <command>gdb</command> to analyse the core (see + <xref linkend="debugging">).</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>When my program dumped core, it said something about + a <errorname>segmentation fault</errorname>. What's + that?</para> + </question> + + <answer> + <para>This basically means that your program tried to + perform some sort of illegal operation on memory; Unix + is designed to protect the operating system and other + programs from rogue programs.</para> + + <para>Common causes for this are:</para> + + <itemizedlist> + <listitem> + <para>Trying to write to a <symbol>NULL</symbol> + pointer, eg</para> + + <programlisting>char *foo = NULL; +strcpy(foo, "bang!"); + </programlisting> + </listitem> + + <listitem> + <para>Using a pointer that hasn't been initialised, + eg</para> + + <programlisting>char *foo; +strcpy(foo, "bang!"); + </programlisting> + + <para>The pointer will have some random value that, + with luck, will point into an area of memory that + isn't available to your program and the kernel will + kill your program before it can do any damage. If + you're unlucky, it'll point somewhere inside your + own program and corrupt one of your data structures, + causing the program to fail mysteriously.</para> + </listitem> + + <listitem> + <para>Trying to access past the end of an array, + eg</para> + + <programlisting>int bar[20]; +bar[27] = 6; + </programlisting> + </listitem> + + <listitem> + <para>Trying to store something in read-only memory, + eg</para> + + <programlisting>char *foo = "My string"; +strcpy(foo, "bang!"); + </programlisting> + + <para>Unix compilers often put string literals like + <literal>"My string"</literal> into read-only areas + of memory.</para> + </listitem> + + <listitem> + <para>Doing naughty things with + <function>malloc()</function> and + <function>free()</function>, eg</para> + + <programlisting>char bar[80]; +free(bar); + </programlisting> + + <para>or</para> + + <programlisting>char *foo = malloc(27); +free(foo); +free(foo); + </programlisting> + </listitem> + </itemizedlist> + + <para>Making one of these mistakes will not always lead to + an error, but they are always bad practice. Some + systems and compilers are more tolerant than others, + which is why programs that ran well on one system can + crash when you try them on an another.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>Sometimes when I get a core dump it says + <errorname>bus error</errorname>. It says in my Unix + book that this means a hardware problem, but the + computer still seems to be working. Is this + true?</para> + </question> + + <answer> + <para>No, fortunately not (unless of course you really do + have a hardware problem…). This is usually + another way of saying that you accessed memory in a way + you shouldn't have.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>This dumping core business sounds as though it could + be quite useful, if I can make it happen when I want to. + Can I do this, or do I have to wait until there's an + error?</para> + </question> + + <answer> + <para>Yes, just go to another console or xterm, do</para> + + <screen>&prompt.user; <userinput>ps</userinput> + </screen> + + <para>to find out the process ID of your program, and + do</para> + + <screen>&prompt.user; <userinput>kill -ABRT <replaceable>pid</replaceable></userinput> + </screen> + + <para>where + <parameter><replaceable>pid</replaceable></parameter> is + the process ID you looked up.</para> + + <para>This is useful if your program has got stuck in an + infinite loop, for instance. If your program happens to + trap <symbol>SIGABRT</symbol>, there are several other + signals which have a similar effect.</para> + </answer> + </qandaentry> + </qandaset> + </sect2> + </sect1> + + <sect1> + <title>Make</title> + + <sect2> + <title>What is <command>make</command>?</title> + + <para>When you're working on a simple program with only one or + two source files, typing in</para> + + <screen>&prompt.user; <userinput>cc file1.c file2.c</userinput> + </screen> + + <para>is not too bad, but it quickly becomes very tedious when + there are several files—and it can take a while to + compile, too.</para> + + <para>One way to get around this is to use object files and only + recompile the source file if the source code has changed. So + we could have something like:</para> + + <screen>&prompt.user; <userinput>cc file1.o file2.o</userinput> … <userinput>file37.c</userinput> &hellip + </screen> + + <para>if we'd changed <filename>file37.c</filename>, but not any + of the others, since the last time we compiled. This may + speed up the compilation quite a bit, but doesn't solve the + typing problem.</para> + + <para>Or we could write a shell script to solve the typing + problem, but it would have to re-compile everything, making it + very inefficient on a large project.</para> + + <para>What happens if we have hundreds of source files lying + about? What if we're working in a team with other people who + forget to tell us when they've changed one of their source + files that we use?</para> + + <para>Perhaps we could put the two solutions together and write + something like a shell script that would contain some kind of + magic rule saying when a source file needs compiling. Now all + we need now is a program that can understand these rules, as + it's a bit too complicated for the shell.</para> + + <para>This program is called <command>make</command>. It reads + in a file, called a <firstterm>makefile</firstterm>, that + tells it how different files depend on each other, and works + out which files need to be re-compiled and which ones don't. + For example, a rule could say something like <quote>if + <filename>fromboz.o</filename> is older than + <filename>fromboz.c</filename>, that means someone must have + changed <filename>fromboz.c</filename>, so it needs to be + re-compiled.</quote> The makefile also has rules telling + make <emphasis>how</emphasis> to re-compile the source file, + making it a much more powerful tool.</para> + + <para>Makefiles are typically kept in the same directory as the + source they apply to, and can be called + <filename>makefile</filename>, <filename>Makefile</filename> + or <filename>MAKEFILE</filename>. Most programmers use the + name <filename>Makefile</filename>, as this puts it near the + top of a directory listing, where it can easily be + seen. + + <footnote> + <para>They don't use the <filename>MAKEFILE</filename> form + as block capitals are often used for documentation files + like <filename>README</filename>.</para> + </footnote></para> + </sect2> + + <sect2> + <title>Example of using <command>make</command></title> + + <para>Here's a very simple make file:</para> + + <programlisting>foo: foo.c + cc -o foo foo.c + </programlisting> + + <para>It consists of two lines, a dependency line and a creation + line.</para> + + <para>The dependency line here consists of the name of the + program (known as the <firstterm>target</firstterm>), followed + by a colon, then whitespace, then the name of the source file. + When <command>make</command> reads this line, it looks to see + if <filename>foo</filename> exists; if it exists, it compares + the time <filename>foo</filename> was last modified to the + time <filename>foo.c</filename> was last modified. If + <filename>foo</filename> does not exist, or is older than + <filename>foo.c</filename>, it then looks at the creation line + to find out what to do. In other words, this is the rule for + working out when <filename>foo.c</filename> needs to be + re-compiled.</para> + + <para>The creation line starts with a <token>tab</token> (press + the <keycap>tab</keycap> key) and then the command you would + type to create <filename>foo</filename> if you were doing it + at a command prompt. If <filename>foo</filename> is out of + date, or does not exist, <command>make</command> then executes + this command to create it. In other words, this is the rule + which tells make how to re-compile + <filename>foo.c</filename>.</para> + + <para>So, when you type <userinput>make</userinput>, it will + make sure that <filename>foo</filename> is up to date with + respect to your latest changes to <filename>foo.c</filename>. + This principle can be extended to + <filename>Makefile</filename>s with hundreds of + targets—in fact, on FreeBSD, it is possible to compile + the entire operating system just by typing <userinput>make + world</userinput> in the appropriate directory!</para> + + <para>Another useful property of makefiles is that the targets + don't have to be programs. For instance, we could have a make + file that looks like this:</para> + + <programlisting>foo: foo.c + cc -o foo foo.c + +install: + cp foo /home/me + </programlisting> + + <para>We can tell make which target we want to make by + typing:</para> + + <screen>&prompt.user; <userinput>make <replaceable>target</replaceable></userinput> + </screen> + + <para><command>make</command> will then only look at that target + and ignore any others. For example, if we type + <userinput>make foo</userinput> with the makefile above, make + will ignore the <action>install</action> target.</para> + + <para>If we just type <userinput>make</userinput> on its own, + make will always look at the first target and then stop + without looking at any others. So if we typed + <userinput>make</userinput> here, it will just go to the + <action>foo</action> target, re-compile + <filename>foo</filename> if necessary, and then stop without + going on to the <action>install</action> target.</para> + + <para>Notice that the <action>install</action> target doesn't + actually depend on anything! This means that the command on + the following line is always executed when we try to make that + target by typing <userinput>make install</userinput>. In this + case, it will copy <filename>foo</filename> into the user's + home directory. This is often used by application makefiles, + so that the application can be installed in the correct + directory when it has been correctly compiled.</para> + + <para>This is a slightly confusing subject to try and explain. + If you don't quite understand how <command>make</command> + works, the best thing to do is to write a simple program like + <quote>hello world</quote> and a make file like the one above + and experiment. Then progress to using more than one source + file, or having the source file include a header file. The + <command>touch</command> command is very useful here—it + changes the date on a file without you having to edit + it.</para> + </sect2> + + <sect2> + <title>FreeBSD Makefiles</title> + + <para>Makefiles can be rather complicated to write. Fortunately, + BSD-based systems like FreeBSD come with some very powerful + ones as part of the system. One very good example of this is + the FreeBSD ports system. Here's the essential part of a + typical ports <filename>Makefile</filename>:</para> + + <programlisting>MASTER_SITES= ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/ +DISTFILES= scheme-microcode+dist-7.3-freebsd.tgz + +.include <bsd.port.mk> + </programlisting> + + <para>Now, if we go to the directory for this port and type + <userinput>make</userinput>, the following happens:</para> + + <procedure> + <step> + <para>A check is made to see if the source code for this + port is already on the system.</para> + </step> + + <step> + <para>If it isn't, an FTP connection to the URL in + <symbol>MASTER_SITES</symbol> is set up to download the + source.</para> + </step> + + <step> + <para>The checksum for the source is calculated and compared + it with one for a known, good, copy of the source. This + is to make sure that the source was not corrupted while in + transit.</para> + </step> + + <step> + <para>Any changes required to make the source work on + FreeBSD are applied—this is known as + <firstterm>patching</firstterm>.</para> + </step> + + <step> + <para>Any special configuration needed for the source is + done. (Many Unix program distributions try to work out + which version of Unix they are being compiled on and which + optional Unix features are present—this is where + they are given the information in the FreeBSD ports + scenario).</para> + </step> + + <step> + <para>The source code for the program is compiled. In + effect, we change to the directory where the source was + unpacked and do <command>make</command>—the + program's own make file has the necessary information to + build the program.</para> + </step> + + <step> + <para>We now have a compiled version of the program. If we + wish, we can test it now; when we feel confident about the + program, we can type <userinput>make install</userinput>. + This will cause the program and any supporting files it + needs to be copied into the correct location; an entry is + also made into a <database>package database</database>, so + that the port can easily be uninstalled later if we change + our mind about it.</para> + </step> + </procedure> + + <para>Now I think you'll agree that's rather impressive for a + four line script!</para> + + <para>The secret lies in the last line, which tells + <command>make</command> to look in the system makefile called + <filename>bsd.port.mk</filename>. It's easy to overlook this + line, but this is where all the clever stuff comes + from—someone has written a makefile that tells + <command>make</command> to do all the things above (plus a + couple of other things I didn't mention, including handling + any errors that may occur) and anyone can get access to that + just by putting a single line in their own make file!</para> + + <para>If you want to have a look at these system makefiles, + they're in <filename>/usr/share/mk</filename>, but it's + probably best to wait until you've had a bit of practice with + makefiles, as they are very complicated (and if you do look at + them, make sure you have a flask of strong coffee + handy!)</para> + </sect2> + + <sect2> + <title>More advanced uses of <command>make</command></title> + + <para><command>Make</command> is a very powerful tool, and can + do much more than the simple example above shows. + Unfortunately, there are several different versions of + <command>make</command>, and they all differ considerably. + The best way to learn what they can do is probably to read the + documentation—hopefully this introduction will have + given you a base from which you can do this.</para> + + <para>The version of make that comes with FreeBSD is the + <application>Berkeley make</application>; there is a tutorial + for it in <filename>/usr/share/doc/psd/12.make</filename>. To + view it, do</para> + + <screen>&prompt.user; <userinput>zmore paper.ascii.gz</userinput> + </screen> + + <para>in that directory.</para> + + <para>Many applications in the ports use <application>GNU + make</application>, which has a very good set of + <quote>info</quote> pages. If you have installed any of these + ports, <application>GNU make</application> will automatically + have been installed as <command>gmake</command>. It's also + available as a port and package in its own right.</para> + + <para>To view the info pages for <application>GNU + make</application>, you will have to edit the + <filename>dir</filename> file in the + <filename>/usr/local/info</filename> directory to add an entry + for it. This involves adding a line like</para> + + <programlisting> * Make: (make). The GNU Make utility. + </programlisting> + + <para>to the file. Once you have done this, you can type + <userinput>info</userinput> and then select + <guimenuitem>make</guimenuitem> from the menu (or in + <application>Emacs</application>, do <userinput>C-h + i</userinput>).</para> + </sect2> + </sect1> + + <sect1 id="debugging"> + <title>Debugging</title> + + <sect2> + <title>The Debugger</title> + + <para>The debugger that comes with FreeBSD is called + <command>gdb</command> (<application>GNU + debugger</application>). You start it up by typing</para> + + <screen>&prompt.user; <userinput>gdb <replaceable>progname</replaceable></userinput> + </screen> + + <para>although most people prefer to run it inside + <application>Emacs</application>. You can do this by:</para> + + <screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput> + </screen> + + <para>Using a debugger allows you to run the program under more + controlled circumstances. Typically, you can step through the + program a line at a time, inspect the value of variables, + change them, tell the debugger to run up to a certain point + and then stop, and so on. You can even attach to a program + that's already running, or load a core file to investigate why + the program crashed. It's even possible to debug the kernel, + though that's a little trickier than the user applications + we'll be discussing in this section.</para> + + <para><command>gdb</command> has quite good on-line help, as + well as a set of info pages, so this section will concentrate + on a few of the basic commands.</para> + + <para>Finally, if you find its text-based command-prompt style + off-putting, there's a graphical front-end for it <ulink + URL="../../ports/devel.html">xxgdb</ulink> in the ports + collection.</para> + + <para>This section is intended to be an introduction to using + <command>gdb</command> and does not cover specialised topics + such as debugging the kernel.</para> + </sect2> + + <sect2> + <title>Running a program in the debugger</title> + + <para>You'll need to have compiled the program with the + <option>-g</option> option to get the most out of using + <command>gdb</command>. It will work without, but you'll only + see the name of the function you're in, instead of the source + code. If you see a line like:</para> + + <screen>… (no debugging symbols found) … + </screen> + + <para>when <command>gdb</command> starts up, you'll know that + the program wasn't compiled with the <option>-g</option> + option.</para> + + <para>At the <command>gdb</command> prompt, type + <userinput>break main</userinput>. This will tell the + debugger to skip over the preliminary set-up code in the + program and start at the beginning of your code. Now type + <userinput>run</userinput> to start the program—it will + start at the beginning of the set-up code and then get stopped + by the debugger when it calls <function>main()</function>. + (If you've ever wondered where <function>main()</function> + gets called from, now you know!).</para> + + <para>You can now step through the program, a line at a time, by + pressing <command>n</command>. If you get to a function call, + you can step into it by pressing <command>s</command>. Once + you're in a function call, you can return from stepping into a + function call by pressing <command>f</command>. You can also + use <command>up</command> and <command>down</command> to take + a quick look at the caller.</para> + + <para>Here's a simple example of how to spot a mistake in a + program with <command>gdb</command>. This is our program + (with a deliberate mistake):</para> + + <programlisting>#include <stdio.h> + +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>This program sets <symbol>i</symbol> to be + <literal>5</literal> and passes it to a function + <function>bazz()</function> which prints out the number we + gave it.</para> + + <para>When we compile and run the program we get</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>That wasn't what we expected! Time to see what's going + on!</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</> <lineannotation>Skip the set-up code</> +Breakpoint 1 at 0x160f: file temp.c, line 9. <lineannotation><command>gdb</command> puts breakpoint at <function>main()</></> +(gdb) <userinput>run</> <lineannotation>Run as far as <function>main()</></> +Starting program: /home/james/tmp/temp <lineannotation>Program starts running</> + +Breakpoint 1, main () at temp.c:9 <lineannotation><command>gdb</command> stops at <function>main()</></> +(gdb) <userinput>n</> <lineannotation>Go to next line</> +This is my program <lineannotation>Program prints out</> +(gdb) <userinput>s</> <lineannotation>step into <function>bazz()</></> +bazz (anint=4231) at temp.c:17 <lineannotation><command>gdb</command> displays stack frame</> +(gdb) + </screen> + + <para>Hang on a minute! How did <symbol>anint</symbol> get to be + <literal>4231</literal>? Didn't we set it to be + <literal>5</literal> in <function>main()</function>? Let's + move up to <function>main()</function> and have a look.</para> + + <screen>(gdb) <userinput>up</> <lineannotation>Move up call stack</> +#1 0x1625 in main () at temp.c:11 <lineannotation><command>gdb</command> displays stack frame</> +(gdb) <userinput>p i</> <lineannotation>Show us the value of <symbol>i</></> +$1 = 4231 <lineannotation><command>gdb</command> displays <literal>4231</></> + </screen> + + <para>Oh dear! Looking at the code, we forgot to initialise + <symbol>i</symbol>. We meant to put</para> + + <programlisting><lineannotation>…</> +main() { + int i; + + i = 5; + printf("This is my program\n"); +<lineannotation>&hellip</> + </programlisting> + + <para>but we left the <literal>i=5;</literal> line out. As we + didn't initialise <symbol>i</symbol>, it had whatever number + happened to be in that area of memory when the program ran, + which in this case happened to be + <literal>4231</literal>.</para> + + <note> + <para><command>gdb</command> displays the stack frame every + time we go into or out of a function, even if we're using + <command>up</command> and <command>down</command> to move + around the call stack. This shows the name of the function + and the values of its arguments, which helps us keep track + of where we are and what's going on. (The stack is a + storage area where the program stores information about the + arguments passed to functions and where to go when it + returns from a function call).</para> + </note> + </sect2> + + <sect2> + <title>Examining a core file</title> + + <para>A core file is basically a file which contains the + complete state of the process when it crashed. In <quote>the + good old days</quote>, programmers had to print out hex + listings of core files and sweat over machine code manuals, + but now life is a bit easier. Incidentally, under FreeBSD and + other 4.4BSD systems, a core file is called + <filename><replaceable>progname</replaceable>.core</filename> instead of just + <filename>core</filename>, to make it clearer which program a + core file belongs to.</para> + + <para>To examine a core file, start up <command>gdb</command> in + the usual way. Instead of typing <command>break</command> or + <command>run</command>, type</para> + + <screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput> + </screen> + + <para>If you're not in the same directory as the core file, + you'll have to do <userinput>dir + /path/to/core/file</userinput> first.</para> + + <para>You should see something like this:</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 this case, the program was called + <filename>a.out</filename>, so the core file is called + <filename>a.out.core</filename>. We can see that the program + crashed due to trying to access an area in memory that was not + available to it in a function called + <function>bazz</function>.</para> + + <para>Sometimes it's useful to be able to see how a function was + called, as the problem could have occurred a long way up the + call stack in a complex program. The <command>bt</command> + command causes <command>gdb</command> to print out a + back-trace of the call stack:</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>The <function>end()</function> function is called when a + program crashes; in this case, the <function>bazz()</function> + function was called from <function>main()</function>.</para> + </sect2> + + <sect2> + <title>Attaching to a running program</title> + + <para>One of the neatest features about <command>gdb</command> + is that it can attach to a program that's already running. Of + course, that assumes you have sufficient permissions to do so. + A common problem is when you are stepping through a program + that forks, and you want to trace the child, but the debugger + will only let you trace the parent.</para> + + <para>What you do is start up another <command>gdb</command>, + use <command>ps</command> to find the process ID for the + child, and do</para> + + <screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput> + </screen> + + <para>in <command>gdb</command>, and then debug as usual.</para> + + <para><quote>That's all very well,</quote> you're probably + thinking, <quote>but by the time I've done that, the child + process will be over the hill and far away</quote>. Fear + not, gentle reader, here's how to do it (courtesy of the + <command>gdb</command> info pages):</para> + + <screen><lineannotation>&hellip</lineannotation> +if ((pid = fork()) < 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>Now all you have to do is attach to the child, set + <symbol>PauseMode</symbol> to <literal>0</literal>, and wait + for the <function>sleep()</function> call to return!</para> + </sect2> + </sect1> + + <sect1 id="emacs"> + <title>Using Emacs as a Development Environment</title> + + <sect2> + <title>Emacs</title> + + <para>Unfortunately, Unix systems don't come with the kind of + everything-you-ever-wanted-and-lots-more-you-didn't-in-one-gigantic-package + integrated development environments that other systems + have. + + <footnote> + <para>At least, not unless you pay out very large sums of + money.</para> + </footnote> + + However, it is possible to set up your own environment. It + may not be as pretty, and it may not be quite as integrated, + but you can set it up the way you want it. And it's free. + And you have the source to it.</para> + + <para>The key to it all is Emacs. Now there are some people who + loathe it, but many who love it. If you're one of the former, + I'm afraid this section will hold little of interest to you. + Also, you'll need a fair amount of memory to run it—I'd + recommend 8MB in text mode and 16MB in X as the bare minimum + to get reasonable performance.</para> + + <para>Emacs is basically a highly customisable + editor—indeed, it has been customised to the point where + it's more like an operating system than an editor! Many + developers and sysadmins do in fact spend practically all + their time working inside Emacs, leaving it only to log + out.</para> + + <para>It's impossible even to summarise everything Emacs can do + here, but here are some of the features of interest to + developers:</para> + + <itemizedlist> + <listitem> + <para>Very powerful editor, allowing search-and-replace on + both strings and regular expressions (patterns), jumping + to start/end of block expression, etc, etc.</para> + </listitem> + + <listitem> + <para>Pull-down menus and online help.</para> + </listitem> + + <listitem> + <para>Language-dependent syntax highlighting and + indentation.</para> + </listitem> + + <listitem> + <para>Completely customisable.</para> + </listitem> + + <listitem> + <para>You can compile and debug programs within + Emacs.</para> + </listitem> + + <listitem> + <para>On a compilation error, you can jump to the offending + line of source code.</para> + </listitem> + + <listitem> + <para>Friendly-ish front-end to the <command>info</command> + program used for reading GNU hypertext documentation, + including the documentation on Emacs itself.</para> + </listitem> + + <listitem> + <para>Friendly front-end to <command>gdb</command>, allowing + you to look at the source code as you step through your + program.</para> + </listitem> + + <listitem> + <para>You can read Usenet news and mail while your program + is compiling.</para> + </listitem> + </itemizedlist> + + <para>And doubtless many more that I've overlooked.</para> + + <para>Emacs can be installed on FreeBSD using <ulink + URL="../../ports/editors.html">the Emacs + port</ulink>.</para> + + <para>Once it's installed, start it up and do <userinput>C-h + t</userinput> to read an Emacs tutorial—that means + hold down the <keycap>control</keycap> key, press + <keycap>h</keycap>, let go of the <keycap>control</keycap> + key, and then press <keycap>t</keycap>. (Alternatively, you + can you use the mouse to select <guimenuitem>Emacs + Tutorial</guimenuitem> from the <guimenu>Help</guimenu> + menu).</para> + + <para>Although Emacs does have menus, it's well worth learning + the key bindings, as it's much quicker when you're editing + something to press a couple of keys than to try and find the + mouse and then click on the right place. And, when you're + talking to seasoned Emacs users, you'll find they often + casually throw around expressions like <quote><literal>M-x + replace-s RET foo RET bar RET</literal></quote> so it's + useful to know what they mean. And in any case, Emacs has far + too many useful functions for them to all fit on the menu + bars.</para> + + <para>Fortunately, it's quite easy to pick up the key-bindings, + as they're displayed next to the menu item. My advice is to + use the menu item for, say, opening a file until you + understand how it works and feel confident with it, then try + doing C-x C-f. When you're happy with that, move on to + another menu command.</para> + + <para>If you can't remember what a particular combination of + keys does, select <guimenuitem>Describe Key</guimenuitem> from + the <guimenu>Help</guimenu> menu and type it in—Emacs + will tell you what it does. You can also use the + <guimenuitem>Command Apropos</guimenuitem> menu item to find + out all the commands which contain a particular word in them, + with the key binding next to it.</para> + + <para>By the way, the expression above means hold down the + <keysym>Meta</keysym> key, press <keysym>x</keysym>, release + the <keysym>Meta</keysym> key, type + <userinput>replace-s</userinput> (short for + <literal>replace-string</literal>—another feature of + Emacs is that you can abbreviate commands), press the + <keysym>return</keysym> key, type <userinput>foo</userinput> + (the string you want replaced), press the + <keysym>return</keysym> key, type bar (the string you want to + replace <literal>foo</literal> with) and press + <keysym>return</keysym> again. Emacs will then do the + search-and-replace operation you've just requested.</para> + + <para>If you're wondering what on earth the + <keysym>Meta</keysym> key is, it's a special key that many + Unix workstations have. Unfortunately, PC's don't have one, + so it's usually the <keycap>alt</keycap> key (or if you're + unlucky, the <keysym>escape</keysym> key).</para> + + <para>Oh, and to get out of Emacs, do <command>C-x C-c</command> + (that means hold down the <keysym>control</keysym> key, press + <keysym>x</keysym>, press <keysym>c</keysym> and release the + <keysym>control</keysym> key). If you have any unsaved files + open, Emacs will ask you if you want to save them. (Ignore + the bit in the documentation where it says + <command>C-z</command> is the usual way to leave + Emacs—that leaves Emacs hanging around in the + background, and is only really useful if you're on a system + which doesn't have virtual terminals).</para> + </sect2> + + <sect2> + <title>Configuring Emacs</title> + + <para>Emacs does many wonderful things; some of them are built + in, some of them need to be configured.</para> + + <para>Instead of using a proprietary macro language for + configuration, Emacs uses a version of Lisp specially adapted + for editors, known as Emacs Lisp. This can be quite useful if + you want to go on and learn something like Common Lisp, as + it's considerably smaller than Common Lisp (although still + quite big!).</para> + + <para>The best way to learn Emacs Lisp is to download the <ulink + URL="ftp://prep.ai.mit.edu:pub/gnu/elisp-manual-19-2.4.tar.gz">Emacs + Tutorial</ulink></para> + + <para>However, there's no need to actually know any Lisp to get + started with configuring Emacs, as I've included a sample + <filename>.emacs</filename> file, which should be enough to + get you started. Just copy it into your home directory and + restart Emacs if it's already running; it will read the + commands from the file and (hopefully) give you a useful basic + setup.</para> + </sect2> + + <sect2> + <title>A sample <filename>.emacs</filename> file</title> + + <para>Unfortunately, there's far too much here to explain it in + detail; however there are one or two points worth + mentioning.</para> + + <itemizedlist> + <listitem> + <para>Everything beginning with a <literal>;</literal> is a comment + and is ignored by Emacs.</para> + </listitem> + + <listitem> + <para>In the first line, the + <literal>-*- Emacs-Lisp -*-</literal> is so that + we can edit the <filename>.emacs</filename> file itself + within Emacs and get all the fancy features for editing + Emacs Lisp. Emacs usually tries to guess this based on + the filename, and may not get it right for + <filename>.emacs</filename>.</para> + </listitem> + + <listitem> + <para>The <keysym>tab</keysym> key is bound to an + indentation function in some modes, so when you press the + tab key, it will indent the current line of code. If you + want to put a <token>tab</token> character in whatever + you're writing, hold the <keysym>control</keysym> key down + while you're pressing the <keysym>tab</keysym> key.</para> + </listitem> + + <listitem> + <para>This file supports syntax highlighting for C, C++, + Perl, Lisp and Scheme, by guessing the language from the + filename.</para> + </listitem> + + <listitem> + <para>Emacs already has a pre-defined function called + <function>next-error</function>. In a compilation output + window, this allows you to move from one compilation error + to the next by doing <command>M-n</command>; we define a + complementary function, + <function>previous-error</function>, that allows you to go + to a previous error by doing <command>M-p</command>. The + nicest feature of all is that <command>C-c C-c</command> + will open up the source file in which the error occurred + and jump to the appropriate line.</para> + </listitem> + + <listitem> + <para>We enable Emacs's ability to act as a server, so that + if you're doing something outside Emacs and you want to + edit a file, you can just type in</para> + + <screen>&prompt.user; <userinput>emacsclient <replaceable>filename</replaceable></userinput> + </screen> + + <para>and then you can edit the file in your + Emacs! + + <footnote> + <para>Many Emacs users set their <systemitem + class=environvar>EDITOR</systemitem> environment to + <literal>emacsclient</literal> so this happens every + time they need to edit a file.</para> + </footnote></para> + </listitem> + </itemizedlist> + + <example> + <title>A sample <filename>.emacs</filename> file</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-<") +(global-set-key [C-end] "\M->") +(global-set-key [C-prior] "\M-<") +(global-set-key [C-next] "\M->") + +;; 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 <CR> 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) + +;; 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 colour &optional bold) + "Create a face from a colour and optionally make it bold" + (make-face face) + (copy-face 'default face) + (set-face-foreground face colour) + (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>Extending the Range of Languages Emacs Understands</title> + + <para>Now, this is all very well if you only want to program in + the languages already catered for in the + <filename>.emacs</filename> file (C, C++, Perl, Lisp and + Scheme), but what happens if a new language called + <quote>whizbang</quote> comes out, full of exciting + features?</para> + + <para>The first thing to do is find out if whizbang comes with + any files that tell Emacs about the language. These usually + end in <filename>.el</filename>, short for <quote>Emacs + Lisp</quote>. For example, if whizbang is a FreeBSD port, we + can locate these files by doing</para> + + <screen>&prompt.user; <userinput>find /usr/ports/lang/whizbang -name "*.el" -print</userinput> + </screen> + + <para>and install them by copying them into the Emacs site Lisp + directory. On FreeBSD 2.1.0-RELEASE, this is + <filename>/usr/local/share/emacs/site-lisp</filename>.</para> + + <para>So for example, if the output from the find command + was</para> + + <screen>/usr/ports/lang/whizbang/work/misc/whizbang.el + </screen> + + <para>we would do</para> + + <screen>&prompt.root; <userinput>cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp</userinput> + </screen> + + <para>Next, we need to decide what extension whizbang source + files have. Let's say for the sake of argument that they all + end in <filename>.wiz</filename>. We need to add an entry to + our <filename>.emacs</filename> file to make sure Emacs will + be able to use the information in + <filename>whizbang.el</filename>.</para> + + <para>Find the <symbol>auto-mode-alist entry</symbol> in + <filename>.emacs</filename> and add a line for whizbang, such + as:</para> + + <programlisting><lineannotation>…</> +("\\.lsp$" . lisp-mode) +("\\.wiz$" . whizbang-mode) +("\\.scm$" . scheme-mode) +<lineannotation>…</> + </programlisting> + + <para>This means that Emacs will automatically go into + <function>whizbang-mode</function> when you edit a file ending + in <filename>.wiz</filename>.</para> + + <para>Just below this, you'll find the + <symbol>font-lock-auto-mode-list</symbol> entry. Add + <function>whizbang-mode</function> to it like so:</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>This means that Emacs will always enable + <function>font-lock-mode</function> (ie syntax highlighting) + when editing a <filename>.wiz</filename> file.</para> + + <para>And that's all that's needed. If there's anything else + you want done automatically when you open up a + <filename>.wiz</filename> file, you can add a + <function>whizbang-mode hook</function> (see + <function>my-scheme-mode-hook</function> for a simple example + that adds <function>auto-indent</function>).</para> + </sect2> + </sect1> + + <sect1> + <title>Further Reading</title> + + <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> - <para></para> </chapter> <chapter id="secure-programming"> @@ -1357,7 +3598,7 @@ DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0); </chapter> </part> - <part id="debugging"> + <part id="debuggingpart"> <title>Debugging</title> <chapter id="truss"> diff --git a/en_US.ISO8859-1/books/developers-handbook/book.sgml b/en_US.ISO8859-1/books/developers-handbook/book.sgml index 8aacd1d42a..bd58d4a25a 100644 --- a/en_US.ISO8859-1/books/developers-handbook/book.sgml +++ b/en_US.ISO8859-1/books/developers-handbook/book.sgml @@ -1,7 +1,7 @@ <!-- The FreeBSD Documentation Project - $FreeBSD: doc/en_US.ISO_8859-1/books/developers-handbook/book.sgml,v 1.4 2000/11/06 10:22:11 murray Exp $ + $FreeBSD: doc/en_US.ISO_8859-1/books/developers-handbook/book.sgml,v 1.5 2000/11/06 13:52:26 murray Exp $ --> <!DOCTYPE BOOK PUBLIC "-//FreeBSD//DTD DocBook V3.1-Based Extension//EN" [ @@ -205,14 +205,2255 @@ <part id="Basics"> <title>Basics</title> - <chapter id="compilation"> - <title>Compilation</title> + <chapter id="programming-tools"> + <title>Programming Tools</title> - <para>This will include things like: compilation, makefiles, .mk - files, basic debugging, linking, secure programming - guidelines, style(9), CVS, diff, patch, etc.</para> + <para><emphasis>This chapter was written by James Raynard. + Modifications for the Developer's Handbook by Murray Stokely. + </emphasis></para> + + <sect1><title>Synopsis</title> + + <para>This document is an introduction to using some of the + programming tools supplied with FreeBSD, although much of it + will be applicable to many other versions of Unix. It does + <emphasis>not</emphasis> attempt to describe coding in any + detail. Most of the document assumes little or no previous + programming knowledge, although it is hoped that most + programmers will find something of value in it</para> + + </sect1> + + <sect1><title>Introduction</title> + + <para>FreeBSD offers an excellent development environment. + Compilers for C, C++, and Fortran and an assembler come with the + basic system, not to mention a Perl interpreter and classic Unix + tools such as <command>sed</command> and <command>awk</command>. + If that is not enough, there are many more compilers and + interpreters in the Ports collection. FreeBSD is very + compatible with standards such as <acronym>POSIX</acronym> and + <acronym>ANSI</acronym> C, as well with its own BSD heritage, so + it is possible to write applications that will compile and run + with little or no modification on a wide range of + platforms.</para> + + <para>However, all this power can be rather overwhelming at + first if you've never written programs on a Unix platform + before. This document aims to help you get up and running, + without getting too deeply into more advanced topics. The + intention is that this document should give you enough of the + basics to be able to make some sense of the + documentation.</para> + + <para>Most of the document requires little or no knowledge of + programming, although it does assume a basic competence with + using Unix and a willingness to learn!</para> + + </sect1> + + <sect1> + <title>Introduction to Programming</title> + + <para>A program is a set of instructions that tell the computer + to do various things; sometimes the instruction it has to + perform depends on what happened when it performed a previous + instruction. This section gives an overview of the two main + ways in which you can give these instructions, or + <quote>commands</quote> as they are usually called. One way + uses an <firstterm>interpreter</firstterm>, the other a + <firstterm>compiler</firstterm>. As human languages are too + difficult for a computer to understand in an unambiguous way, + commands are usually written in one or other languages specially + designed for the purpose.</para> + + <sect2> + <title>Interpreters</title> + + <para>With an interpreter, the language comes as an environment, + where you type in commands at a prompt and the environment + executes them for you. For more complicated programs, you can + type the commands into a file and get the interpreter to load + the file and execute the commands in it. If anything goes + wrong, many interpreters will drop you into a debugger to help + you track down the problem.</para> + + <para>The advantage of this is that you can see the results of + your commands immediately, and mistakes can be corrected + readily. The biggest disadvantage comes when you want to + share your programs with someone. They must have the same + interpreter, or you must have some way of giving it to them, + and they need to understand how to use it. Also users may not + appreciate being thrown into a debugger if they press the + wrong key! From a performance point of view, interpreters can + use up a lot of memory, and generally do not generate code as + efficiently as compilers.</para> + + <para>In my opinion, interpreted languages are the best way to + start if you have not done any programming before. This kind + of environment is typically found with languages like Lisp, + Smalltalk, Perl and Basic. It could also be argued that the + Unix shell (<command>sh</command>, <command>csh</command>) is itself an + interpreter, and many people do in fact write shell + <quote>scripts</quote> to help with various + <quote>housekeeping</quote> tasks on their machine. Indeed, part + of the original Unix philosophy was to provide lots of small + utility programs that could be linked together in shell + scripts to perform useful tasks.</para> + </sect2> + + <sect2> + <title>Interpreters available with FreeBSD</title> + + <para>Here is a list of interpreters that are available as + <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/">FreeBSD + packages</ulink>, with a brief discussion of some of the + more popular interpreted languages.</para> + + <para>To get one of these packages, all you need to do is to + click on the hotlink for the package, then run</para> + + <screen>&prompt.root; <userinput>pkg_add <replaceable>package name</></userinput> + </screen> + + <para>as root. Obviously, you will need to have a fully + functional FreeBSD 2.1.0 or later system for the package to + work!</para> + + <variablelist> + <varlistentry> + <term><acronym>BASIC</acronym></term> + + <listitem> + <para>Short for Beginner's All-purpose Symbolic + Instruction Code. Developed in the 1950s for teaching + University students to program and provided with every + self-respecting personal computer in the 1980s, + <acronym>BASIC</acronym> has been the first programming + language for many programmers. It's also the foundation + for Visual Basic.</para> + + <para>The <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/bwbasic-2.10.tgz">Bywater + Basic Interpreter</ulink> and the <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/pbasic-2.0.tgz">Phil + Cockroft's Basic Interpreter</ulink> (formerly Rabbit + Basic) are available as FreeBSD <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/">FreeBSD + packages</ulink></para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Lisp</term> + + <listitem> + <para>A language that was developed in the late 1950s as + an alternative to the <quote>number-crunching</quote> + languages that were popular at the time. Instead of + being based on numbers, Lisp is based on lists; in fact + the name is short for <quote>List Processing</quote>. + Very popular in AI (Artificial Intelligence) + circles.</para> + + <para>Lisp is an extremely powerful and sophisticated + language, but can be rather large and unwieldy.</para> + + <para>FreeBSD has <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/gcl-2.0.tgz">GNU + Common Lisp</ulink> available as a package.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Perl</term> + + <listitem> + <para>Very popular with system administrators for writing + scripts; also often used on World Wide Web servers for + writing <acronym>CGI</acronym> scripts.</para> + + <para>The latest version (version 5) comes with FreeBSD.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Scheme</term> + + <listitem> + <para>A dialect of Lisp that is rather more compact and + cleaner than Common Lisp. Popular in Universities as it + is simple enough to teach to undergraduates as a first + language, while it has a high enough level of + abstraction to be used in research work.</para> + + <para>FreeBSD has packages of the <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/elk-3.0.tgz">Elk + Scheme Interpreter</ulink>, the <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/mit-scheme-7.3.tgz">MIT + Scheme Interpreter</ulink> and the <ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/scm-4e1.tgz">SCM + Scheme Interpreter</ulink>.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Icon</term> + + <listitem> + <para><ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/icon-9.0.tgz">The + Icon Programming Language</ulink>.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Logo</term> + + <listitem> + <para><ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/ucblogo-3.3.tgz">Brian + Harvey's LOGO Interpreter</ulink>.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term>Python</term> + + <listitem> + <para><ulink + URL="ftp://ftp.FreeBSD.org:pub/FreeBSD/packages/lang/python-1.2">The + Python Object-Oriented Programming + Language</ulink></para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + + <sect2> + <title>Compilers</title> + + <para>Compilers are rather different. First of all, you write + your code in a file (or files) using an editor. You then run + the compiler and see if it accepts your program. If it did + not compile, grit your teeth and go back to the editor; if it + did compile and gave you a program, you can run it either at a + shell command prompt or in a debugger to see if it works + properly. + + <footnote> + <para>If you run it in the shell, you may get a core + dump.</para> + </footnote></para> + + <para>Obviously, this is not quite as direct as using an + interpreter. However it allows you to do a lot of things + which are very difficult or even impossible with an + interpreter, such as writing code which interacts closely with + the operating system—or even writing your own operating + system! It's also useful if you need to write very efficient + code, as the compiler can take its time and optimise the code, + which would not be acceptable in an interpreter. And + distributing a program written for a compiler is usually more + straightforward than one written for an interpreter—you + can just give them a copy of the executable, assuming they + have the same operating system as you.</para> + + <para>Compiled languages include Pascal, C and C++. C and C++ + are rather unforgiving languages, and best suited to more + experienced programmers; Pascal, on the other hand, was + designed as an educational language, and is quite a good + language to start with. Unfortunately, FreeBSD doesn't have + any Pascal support, except for a Pascal-to-C converter in the + ports.</para> + + <para>As the edit-compile-run-debug cycle is rather tedious when + using separate programs, many commercial compiler makers have + produced Integrated Development Environments + + (<acronym>IDE</acronym>s for short). FreeBSD does not have an + <acronym>IDE</acronym> as such; however it is possible to use Emacs + for this purpose. This is discussed in <xref + linkend="emacs">.</para> + </sect2> + + + </sect1> + + + <sect1> + <title>Compiling with <command>cc</command></title> + + <para>This section deals only with the GNU compiler for C and C++, + since that comes with the base FreeBSD system. It can be + invoked by either <command>cc</command> or <command>gcc</command>. The + details of producing a program with an interpreter vary + considerably between interpreters, and are usually well covered + in the documentation and on-line help for the + interpreter.</para> + + <para>Once you've written your masterpiece, the next step is to + convert it into something that will (hopefully!) run on FreeBSD. + This usually involves several steps, each of which is done by a + separate program.</para> + + <procedure> + <step> + <para>Pre-process your source code to remove comments and do + other tricks like expanding macros in C.</para> + </step> + + <step> + <para>Check the syntax of your code to see if you have obeyed + the rules of the language. If you have not, it will + complain!</para> + </step> + + <step> + <para>Convert the source code into assembly + language—this is very close to machine code, but still + understandable by humans. Allegedly. + + <footnote> + <para>To be strictly accurate, <command>cc</command> converts the + source code into its own, machine-independent + <firstterm>p-code</firstterm> instead of assembly language at + this stage.</para> + </footnote></para> + </step> + + <step> + <para>Convert the assembly language into machine + code—yep, we are talking bits and bytes, ones and + zeros here.</para> + </step> + + <step> + <para>Check that you have used things like functions and + global variables in a consistent way. For example, if you + have called a non-existent function, it will + complain.</para> + </step> + + <step> + <para>If you are trying to produce an executable from several + source code files, work out how to fit them all + together.</para> + </step> + + <step> + <para>Work out how to produce something that the system's + run-time loader will be able to load into memory and + run.</para> + </step> + + <step> + <para>Finally, write the executable on the file system.</para> + </step> + </procedure> + + <para>The word <firstterm>compiling</firstterm> is often used to refer to + just steps 1 to 4—the others are referred to as + <firstterm>linking</firstterm>. Sometimes step 1 is referred to as + <firstterm>pre-processing</firstterm> and steps 3-4 as + <firstterm>assembling</firstterm>.</para> + + <para>Fortunately, almost all this detail is hidden from you, as + <command>cc</command> is a front end that manages calling all these + programs with the right arguments for you; simply typing</para> + + <screen>&prompt.user; <userinput>cc foobar.c</> + </screen> + + <para>will cause <filename>foobar.c</filename> to be compiled by all the + steps above. If you have more than one file to compile, just do + something like</para> + + <screen>&prompt.user; <userinput>cc foo.c bar.c</> + </screen> + + <para>Note that the syntax checking is just that—checking + the syntax. It will not check for any logical mistakes you may + have made, like putting the program into an infinite loop, or + using a bubble sort when you meant to use a binary + sort. + + <footnote> + <para>In case you didn't know, a binary sort is an efficient + way of sorting things into order and a bubble sort + isn't.</para> + </footnote></para> + + <para>There are lots and lots of options for <command>cc</command>, which + are all in the man page. Here are a few of the most important + ones, with examples of how to use them.</para> + + <variablelist> + <varlistentry> + <term><option>-o <replaceable>filename</replaceable></option></term> + + <listitem> + <para>The output name of the file. If you do not use this + option, <command>cc</command> will produce an executable called + <filename>a.out</filename>. + + <footnote> + <para>The reasons for this are buried in the mists of + history.</para> + </footnote></para> + + <informalexample> + <screen>&prompt.user; <userinput>cc foobar.c</> <lineannotation>executable is <filename>a.out</></> +&prompt.user; <userinput>cc -o foobar foobar.c</> <lineannotation>executable is <filename>foobar</></> + </screen> + </informalexample> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-c</option></term> + + <listitem> + <para>Just compile the file, do not link it. Useful for toy + programs where you just want to check the syntax, or if + you are using a <filename>Makefile</filename>.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -c foobar.c</userinput> + </screen> + </informalexample> + + <para>This will produce an <firstterm>object file</firstterm> (not an + executable) called <filename>foobar.o</filename>. This + can be linked together with other object files into an + executable.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-g</option></term> + + <listitem> + <para>Create a debug version of the executable. This makes + the compiler put information into the executable about + which line of which source file corresponds to which + function call. A debugger can use this information to show + the source code as you step through the program, which is + <emphasis>very</emphasis> useful; the disadvantage is that + all this extra information makes the program much bigger. + Normally, you compile with <option>-g</option> while you + are developing a program and then compile a <quote>release + version</quote> without <option>-g</option> when you're + satisfied it works properly.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -g foobar.c</userinput> + </screen> + </informalexample> + + <para>This will produce a debug version of the + program. + + <footnote> + <para>Note, we didn't use the <option>-o</option> flag + to specify the executable name, so we will get an + executable called <filename>a.out</filename>. + Producing a debug version called + <filename>foobar</filename> is left as an exercise for + the reader!</para> + </footnote></para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-O</option></term> + + <listitem> + <para>Create an optimised version of the executable. The + compiler performs various clever tricks to try and produce + an executable that runs faster than normal. You can add a + number after the <option>-O</option> to specify a higher + level of optimisation, but this often exposes bugs in the + compiler's optimiser. For instance, the version of + <command>cc</command> that comes with the 2.1.0 release of + FreeBSD is known to produce bad code with the + <option>-O2</option> option in some circumstances.</para> + + <para>Optimisation is usually only turned on when compiling + a release version.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -O -o foobar foobar.c</userinput> + </screen> + </informalexample> + + <para>This will produce an optimised version of + <filename>foobar</filename>.</para> + </listitem> + </varlistentry> + </variablelist> + + <para>The following three flags will force <command>cc</command> + to check that your code complies to the relevant international + standard, often referred to as the <acronym>ANSI</acronym> + standard, though strictly speaking it is an + <acronym>ISO</acronym> standard.</para> + + <variablelist> + <varlistentry> + <term><option>-Wall</option></term> + + <listitem> + <para>Enable all the warnings which the authors of + <command>cc</command> believe are worthwhile. Despite the + name, it will not enable all the warnings + <command>cc</command> is capable of.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-ansi</option></term> + + <listitem> + <para>Turn off most, but not all, of the + non-<acronym>ANSI</acronym> C features provided by + <command>cc</command>. Despite the name, it does not + guarantee strictly that your code will comply to the + standard.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><option>-pedantic</option></term> + + <listitem> + <para>Turn off <emphasis>all</emphasis> + <command>cc</command>'s non-<acronym>ANSI</acronym> C + features.</para> + </listitem> + </varlistentry> + </variablelist> + + <para>Without these flags, <command>cc</command> will allow you to + use some of its non-standard extensions to the standard. Some + of these are very useful, but will not work with other + compilers—in fact, one of the main aims of the standard is + to allow people to write code that will work with any compiler + on any system. This is known as <firstterm>portable + code</firstterm>.</para> + + <para>Generally, you should try to make your code as portable as + possible, as otherwise you may have to completely re-write the + program later to get it to work somewhere else—and who + knows what you may be using in a few years time?</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -Wall -ansi -pedantic -o foobar foobar.c</userinput> + </screen> + </informalexample> + + <para>This will produce an executable <filename>foobar</filename> + after checking <filename>foobar.c</filename> for standard + compliance.</para> + + <variablelist> + <varlistentry> + <term><option>-l<replaceable>library</replaceable></option></term> + + <listitem> + <para>Specify a function library to be used during when + linking.</para> + + <para>The most common example of this is when compiling a + program that uses some of the mathematical functions in C. + Unlike most other platforms, these are in a separate + library from the standard C one and you have to tell the + compiler to add it.</para> + + <para>The rule is that if the library is called + <filename>lib<replaceable>something</replaceable>.a</filename>, + you give <command>cc</command> the argument + <option>-l<replaceable>something</replaceable></option>. + For example, the math library is + <filename>libm.a</filename>, so you give + <command>cc</command> the argument <option>-lm</option>. + A common <quote>gotcha</quote> with the math library is + that it has to be the last library on the command + line.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput> + </screen> + </informalexample> + + <para>This will link the math library functions into + <filename>foobar</filename>.</para> + + <para>If you are compiling C++ code, you need to add + <option>-lg++</option>, or <option>-lstdc++</option> if + you are using FreeBSD 2.2 or later, to the command line + argument to link the C++ library functions. + Alternatively, you can run <command>c++</command> instead + of <command>cc</command>, which does this for you. + <command>c++</command> can also be invoked as + <command>g++</command> on FreeBSD.</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -o foobar foobar.cc -lg++</userinput> <lineannotation>For FreeBSD 2.1.6 and earlier</> +&prompt.user; <userinput>cc -o foobar foobar.cc -lstdc++</userinput> <lineannotation>For FreeBSD 2.2 and later</> +&prompt.user; <userinput>c++ -o foobar foobar.cc</userinput> + </screen> + </informalexample> + + <para>Each of these will both produce an executable + <filename>foobar</filename> from the C++ source file + <filename>foobar.cc</filename>. Note that, on Unix + systems, C++ source files traditionally end in + <filename>.C</filename>, <filename>.cxx</filename> or + <filename>.cc</filename>, rather than the + MS-DOS style + <filename>.cpp</filename> (which was already used for + something else). <command>gcc</command> used to rely on + this to work out what kind of compiler to use on the + source file; however, this restriction no longer applies, + so you may now call your C++ files + <filename>.cpp</filename> with impunity!</para> + </listitem> + </varlistentry> + </variablelist> + + <sect2> + <title>Common <command>cc</command> Queries and Problems</title> + + <qandaset> + <qandaentry> + <question> + <para>I am trying to write a program which uses the + <function>sin()</function> function and I get an error + like this. What does it mean?</para> + + <informalexample> + <screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment + </screen> + </informalexample> + </question> + + <answer> + <para>When using mathematical functions like + <function>sin()</function>, you have to tell + <command>cc</command> to link in the math library, like + so:</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput> + </screen> + </informalexample> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>All right, I wrote this simple program to practice + using <option>-lm</option>. All it does is raise 2.1 to + the power of 6.</para> + + <informalexample> + <programlisting>#include <stdio.h> + +int main() { + float f; + + f = pow(2.1, 6); + printf("2.1 ^ 6 = %f\n", f); + return 0; +} + </programlisting> + </informalexample> + + <para>and I compiled it as:</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc temp.c -lm</userinput> + </screen> + </informalexample> + + <para>like you said I should, but I get this when I run + it:</para> + + <informalexample> + <screen>&prompt.user; <userinput>./a.out</userinput> +2.1 ^ 6 = 1023.000000 + </screen> + </informalexample> + + <para>This is <emphasis>not</emphasis> the right answer! + What is going on?</para> + </question> + + <answer> + <para>When the compiler sees you call a function, it + checks if it has already seen a prototype for it. If it + has not, it assumes the function returns an + <type>int</type>, which is definitely not what you want + here.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>So how do I fix this?</para> + </question> + + <answer> + <para>The prototypes for the mathematical functions are in + <filename>math.h</filename>. If you include this file, + the compiler will be able to find the prototype and it + will stop doing strange things to your + calculation!</para> + + <informalexample> + <programlisting>#include <math.h> +#include <stdio.h> + +int main() { +... + </programlisting> + </informalexample> + + <para>After recompiling it as you did before, run + it:</para> + + <informalexample> + <screen>&prompt.user; <userinput>./a.out</userinput> +2.1 ^ 6 = 85.766121 + </screen> + </informalexample> + + <para>If you are using any of the mathematical functions, + <emphasis>always</emphasis> include + <filename>math.h</filename> and remember to link in the + math library.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>I compiled a file called + <filename>foobar.c</filename> and I cannot find an + executable called <filename>foobar</filename>. Where's + it gone?</para> + </question> + + <answer> + <para>Remember, <command>cc</command> will call the + executable <filename>a.out</filename> unless you tell it + differently. Use the + <option>-o <replaceable>filename</replaceable></option> + option:</para> + + <informalexample> + <screen>&prompt.user; <userinput>cc -o foobar foobar.c</userinput> + </screen> + </informalexample> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>OK, I have an executable called + <filename>foobar</filename>, I can see it when I run + <command>ls</command>, but when I type in + <command>foobar</command> at the command prompt it tells + me there is no such file. Why can it not find + it?</para> + </question> + + <answer> + <para>Unlike MS-DOS, Unix does not + look in the current directory when it is trying to find + out which executable you want it to run, unless you tell + it to. Either type <command>./foobar</command>, which + means <quote>run the file called + <filename>foobar</filename> in the current + directory</quote>, or change your <systemitem + class=environvar>PATH</systemitem> environment + variable so that it looks something like</para> + + <informalexample> + <screen>bin:/usr/bin:/usr/local/bin:. + </screen> + </informalexample> + + <para>The dot at the end means <quote>look in the current + directory if it is not in any of the + others</quote>.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>I called my executable <filename>test</filename>, + but nothing happens when I run it. What is going + on?</para> + </question> + + <answer> + <para>Most Unix systems have a program called + <command>test</command> in <filename>/usr/bin</filename> + and the shell is picking that one up before it gets to + checking the current directory. Either type:</para> + + <informalexample> + <screen>&prompt.user; <userinput>./test</userinput> + </screen> + </informalexample> + + <para>or choose a better name for your program!</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>I compiled my program and it seemed to run all right + at first, then there was an error and it said something + about <errorname>core dumped</errorname>. What does that + mean?</para> + </question> + + <answer> + <para>The name <firstterm>core dump</firstterm> dates back + to the very early days of Unix, when the machines used + core memory for storing data. Basically, if the program + failed under certain conditions, the system would write + the contents of core memory to disk in a file called + <filename>core</filename>, which the programmer could + then pore over to find out what went wrong.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>Fascinating stuff, but what I am supposed to do + now?</para> + </question> + + <answer> + <para>Use <command>gdb</command> to analyse the core (see + <xref linkend="debugging">).</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>When my program dumped core, it said something about + a <errorname>segmentation fault</errorname>. What's + that?</para> + </question> + + <answer> + <para>This basically means that your program tried to + perform some sort of illegal operation on memory; Unix + is designed to protect the operating system and other + programs from rogue programs.</para> + + <para>Common causes for this are:</para> + + <itemizedlist> + <listitem> + <para>Trying to write to a <symbol>NULL</symbol> + pointer, eg</para> + + <programlisting>char *foo = NULL; +strcpy(foo, "bang!"); + </programlisting> + </listitem> + + <listitem> + <para>Using a pointer that hasn't been initialised, + eg</para> + + <programlisting>char *foo; +strcpy(foo, "bang!"); + </programlisting> + + <para>The pointer will have some random value that, + with luck, will point into an area of memory that + isn't available to your program and the kernel will + kill your program before it can do any damage. If + you're unlucky, it'll point somewhere inside your + own program and corrupt one of your data structures, + causing the program to fail mysteriously.</para> + </listitem> + + <listitem> + <para>Trying to access past the end of an array, + eg</para> + + <programlisting>int bar[20]; +bar[27] = 6; + </programlisting> + </listitem> + + <listitem> + <para>Trying to store something in read-only memory, + eg</para> + + <programlisting>char *foo = "My string"; +strcpy(foo, "bang!"); + </programlisting> + + <para>Unix compilers often put string literals like + <literal>"My string"</literal> into read-only areas + of memory.</para> + </listitem> + + <listitem> + <para>Doing naughty things with + <function>malloc()</function> and + <function>free()</function>, eg</para> + + <programlisting>char bar[80]; +free(bar); + </programlisting> + + <para>or</para> + + <programlisting>char *foo = malloc(27); +free(foo); +free(foo); + </programlisting> + </listitem> + </itemizedlist> + + <para>Making one of these mistakes will not always lead to + an error, but they are always bad practice. Some + systems and compilers are more tolerant than others, + which is why programs that ran well on one system can + crash when you try them on an another.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>Sometimes when I get a core dump it says + <errorname>bus error</errorname>. It says in my Unix + book that this means a hardware problem, but the + computer still seems to be working. Is this + true?</para> + </question> + + <answer> + <para>No, fortunately not (unless of course you really do + have a hardware problem…). This is usually + another way of saying that you accessed memory in a way + you shouldn't have.</para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para>This dumping core business sounds as though it could + be quite useful, if I can make it happen when I want to. + Can I do this, or do I have to wait until there's an + error?</para> + </question> + + <answer> + <para>Yes, just go to another console or xterm, do</para> + + <screen>&prompt.user; <userinput>ps</userinput> + </screen> + + <para>to find out the process ID of your program, and + do</para> + + <screen>&prompt.user; <userinput>kill -ABRT <replaceable>pid</replaceable></userinput> + </screen> + + <para>where + <parameter><replaceable>pid</replaceable></parameter> is + the process ID you looked up.</para> + + <para>This is useful if your program has got stuck in an + infinite loop, for instance. If your program happens to + trap <symbol>SIGABRT</symbol>, there are several other + signals which have a similar effect.</para> + </answer> + </qandaentry> + </qandaset> + </sect2> + </sect1> + + <sect1> + <title>Make</title> + + <sect2> + <title>What is <command>make</command>?</title> + + <para>When you're working on a simple program with only one or + two source files, typing in</para> + + <screen>&prompt.user; <userinput>cc file1.c file2.c</userinput> + </screen> + + <para>is not too bad, but it quickly becomes very tedious when + there are several files—and it can take a while to + compile, too.</para> + + <para>One way to get around this is to use object files and only + recompile the source file if the source code has changed. So + we could have something like:</para> + + <screen>&prompt.user; <userinput>cc file1.o file2.o</userinput> … <userinput>file37.c</userinput> &hellip + </screen> + + <para>if we'd changed <filename>file37.c</filename>, but not any + of the others, since the last time we compiled. This may + speed up the compilation quite a bit, but doesn't solve the + typing problem.</para> + + <para>Or we could write a shell script to solve the typing + problem, but it would have to re-compile everything, making it + very inefficient on a large project.</para> + + <para>What happens if we have hundreds of source files lying + about? What if we're working in a team with other people who + forget to tell us when they've changed one of their source + files that we use?</para> + + <para>Perhaps we could put the two solutions together and write + something like a shell script that would contain some kind of + magic rule saying when a source file needs compiling. Now all + we need now is a program that can understand these rules, as + it's a bit too complicated for the shell.</para> + + <para>This program is called <command>make</command>. It reads + in a file, called a <firstterm>makefile</firstterm>, that + tells it how different files depend on each other, and works + out which files need to be re-compiled and which ones don't. + For example, a rule could say something like <quote>if + <filename>fromboz.o</filename> is older than + <filename>fromboz.c</filename>, that means someone must have + changed <filename>fromboz.c</filename>, so it needs to be + re-compiled.</quote> The makefile also has rules telling + make <emphasis>how</emphasis> to re-compile the source file, + making it a much more powerful tool.</para> + + <para>Makefiles are typically kept in the same directory as the + source they apply to, and can be called + <filename>makefile</filename>, <filename>Makefile</filename> + or <filename>MAKEFILE</filename>. Most programmers use the + name <filename>Makefile</filename>, as this puts it near the + top of a directory listing, where it can easily be + seen. + + <footnote> + <para>They don't use the <filename>MAKEFILE</filename> form + as block capitals are often used for documentation files + like <filename>README</filename>.</para> + </footnote></para> + </sect2> + + <sect2> + <title>Example of using <command>make</command></title> + + <para>Here's a very simple make file:</para> + + <programlisting>foo: foo.c + cc -o foo foo.c + </programlisting> + + <para>It consists of two lines, a dependency line and a creation + line.</para> + + <para>The dependency line here consists of the name of the + program (known as the <firstterm>target</firstterm>), followed + by a colon, then whitespace, then the name of the source file. + When <command>make</command> reads this line, it looks to see + if <filename>foo</filename> exists; if it exists, it compares + the time <filename>foo</filename> was last modified to the + time <filename>foo.c</filename> was last modified. If + <filename>foo</filename> does not exist, or is older than + <filename>foo.c</filename>, it then looks at the creation line + to find out what to do. In other words, this is the rule for + working out when <filename>foo.c</filename> needs to be + re-compiled.</para> + + <para>The creation line starts with a <token>tab</token> (press + the <keycap>tab</keycap> key) and then the command you would + type to create <filename>foo</filename> if you were doing it + at a command prompt. If <filename>foo</filename> is out of + date, or does not exist, <command>make</command> then executes + this command to create it. In other words, this is the rule + which tells make how to re-compile + <filename>foo.c</filename>.</para> + + <para>So, when you type <userinput>make</userinput>, it will + make sure that <filename>foo</filename> is up to date with + respect to your latest changes to <filename>foo.c</filename>. + This principle can be extended to + <filename>Makefile</filename>s with hundreds of + targets—in fact, on FreeBSD, it is possible to compile + the entire operating system just by typing <userinput>make + world</userinput> in the appropriate directory!</para> + + <para>Another useful property of makefiles is that the targets + don't have to be programs. For instance, we could have a make + file that looks like this:</para> + + <programlisting>foo: foo.c + cc -o foo foo.c + +install: + cp foo /home/me + </programlisting> + + <para>We can tell make which target we want to make by + typing:</para> + + <screen>&prompt.user; <userinput>make <replaceable>target</replaceable></userinput> + </screen> + + <para><command>make</command> will then only look at that target + and ignore any others. For example, if we type + <userinput>make foo</userinput> with the makefile above, make + will ignore the <action>install</action> target.</para> + + <para>If we just type <userinput>make</userinput> on its own, + make will always look at the first target and then stop + without looking at any others. So if we typed + <userinput>make</userinput> here, it will just go to the + <action>foo</action> target, re-compile + <filename>foo</filename> if necessary, and then stop without + going on to the <action>install</action> target.</para> + + <para>Notice that the <action>install</action> target doesn't + actually depend on anything! This means that the command on + the following line is always executed when we try to make that + target by typing <userinput>make install</userinput>. In this + case, it will copy <filename>foo</filename> into the user's + home directory. This is often used by application makefiles, + so that the application can be installed in the correct + directory when it has been correctly compiled.</para> + + <para>This is a slightly confusing subject to try and explain. + If you don't quite understand how <command>make</command> + works, the best thing to do is to write a simple program like + <quote>hello world</quote> and a make file like the one above + and experiment. Then progress to using more than one source + file, or having the source file include a header file. The + <command>touch</command> command is very useful here—it + changes the date on a file without you having to edit + it.</para> + </sect2> + + <sect2> + <title>FreeBSD Makefiles</title> + + <para>Makefiles can be rather complicated to write. Fortunately, + BSD-based systems like FreeBSD come with some very powerful + ones as part of the system. One very good example of this is + the FreeBSD ports system. Here's the essential part of a + typical ports <filename>Makefile</filename>:</para> + + <programlisting>MASTER_SITES= ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/ +DISTFILES= scheme-microcode+dist-7.3-freebsd.tgz + +.include <bsd.port.mk> + </programlisting> + + <para>Now, if we go to the directory for this port and type + <userinput>make</userinput>, the following happens:</para> + + <procedure> + <step> + <para>A check is made to see if the source code for this + port is already on the system.</para> + </step> + + <step> + <para>If it isn't, an FTP connection to the URL in + <symbol>MASTER_SITES</symbol> is set up to download the + source.</para> + </step> + + <step> + <para>The checksum for the source is calculated and compared + it with one for a known, good, copy of the source. This + is to make sure that the source was not corrupted while in + transit.</para> + </step> + + <step> + <para>Any changes required to make the source work on + FreeBSD are applied—this is known as + <firstterm>patching</firstterm>.</para> + </step> + + <step> + <para>Any special configuration needed for the source is + done. (Many Unix program distributions try to work out + which version of Unix they are being compiled on and which + optional Unix features are present—this is where + they are given the information in the FreeBSD ports + scenario).</para> + </step> + + <step> + <para>The source code for the program is compiled. In + effect, we change to the directory where the source was + unpacked and do <command>make</command>—the + program's own make file has the necessary information to + build the program.</para> + </step> + + <step> + <para>We now have a compiled version of the program. If we + wish, we can test it now; when we feel confident about the + program, we can type <userinput>make install</userinput>. + This will cause the program and any supporting files it + needs to be copied into the correct location; an entry is + also made into a <database>package database</database>, so + that the port can easily be uninstalled later if we change + our mind about it.</para> + </step> + </procedure> + + <para>Now I think you'll agree that's rather impressive for a + four line script!</para> + + <para>The secret lies in the last line, which tells + <command>make</command> to look in the system makefile called + <filename>bsd.port.mk</filename>. It's easy to overlook this + line, but this is where all the clever stuff comes + from—someone has written a makefile that tells + <command>make</command> to do all the things above (plus a + couple of other things I didn't mention, including handling + any errors that may occur) and anyone can get access to that + just by putting a single line in their own make file!</para> + + <para>If you want to have a look at these system makefiles, + they're in <filename>/usr/share/mk</filename>, but it's + probably best to wait until you've had a bit of practice with + makefiles, as they are very complicated (and if you do look at + them, make sure you have a flask of strong coffee + handy!)</para> + </sect2> + + <sect2> + <title>More advanced uses of <command>make</command></title> + + <para><command>Make</command> is a very powerful tool, and can + do much more than the simple example above shows. + Unfortunately, there are several different versions of + <command>make</command>, and they all differ considerably. + The best way to learn what they can do is probably to read the + documentation—hopefully this introduction will have + given you a base from which you can do this.</para> + + <para>The version of make that comes with FreeBSD is the + <application>Berkeley make</application>; there is a tutorial + for it in <filename>/usr/share/doc/psd/12.make</filename>. To + view it, do</para> + + <screen>&prompt.user; <userinput>zmore paper.ascii.gz</userinput> + </screen> + + <para>in that directory.</para> + + <para>Many applications in the ports use <application>GNU + make</application>, which has a very good set of + <quote>info</quote> pages. If you have installed any of these + ports, <application>GNU make</application> will automatically + have been installed as <command>gmake</command>. It's also + available as a port and package in its own right.</para> + + <para>To view the info pages for <application>GNU + make</application>, you will have to edit the + <filename>dir</filename> file in the + <filename>/usr/local/info</filename> directory to add an entry + for it. This involves adding a line like</para> + + <programlisting> * Make: (make). The GNU Make utility. + </programlisting> + + <para>to the file. Once you have done this, you can type + <userinput>info</userinput> and then select + <guimenuitem>make</guimenuitem> from the menu (or in + <application>Emacs</application>, do <userinput>C-h + i</userinput>).</para> + </sect2> + </sect1> + + <sect1 id="debugging"> + <title>Debugging</title> + + <sect2> + <title>The Debugger</title> + + <para>The debugger that comes with FreeBSD is called + <command>gdb</command> (<application>GNU + debugger</application>). You start it up by typing</para> + + <screen>&prompt.user; <userinput>gdb <replaceable>progname</replaceable></userinput> + </screen> + + <para>although most people prefer to run it inside + <application>Emacs</application>. You can do this by:</para> + + <screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput> + </screen> + + <para>Using a debugger allows you to run the program under more + controlled circumstances. Typically, you can step through the + program a line at a time, inspect the value of variables, + change them, tell the debugger to run up to a certain point + and then stop, and so on. You can even attach to a program + that's already running, or load a core file to investigate why + the program crashed. It's even possible to debug the kernel, + though that's a little trickier than the user applications + we'll be discussing in this section.</para> + + <para><command>gdb</command> has quite good on-line help, as + well as a set of info pages, so this section will concentrate + on a few of the basic commands.</para> + + <para>Finally, if you find its text-based command-prompt style + off-putting, there's a graphical front-end for it <ulink + URL="../../ports/devel.html">xxgdb</ulink> in the ports + collection.</para> + + <para>This section is intended to be an introduction to using + <command>gdb</command> and does not cover specialised topics + such as debugging the kernel.</para> + </sect2> + + <sect2> + <title>Running a program in the debugger</title> + + <para>You'll need to have compiled the program with the + <option>-g</option> option to get the most out of using + <command>gdb</command>. It will work without, but you'll only + see the name of the function you're in, instead of the source + code. If you see a line like:</para> + + <screen>… (no debugging symbols found) … + </screen> + + <para>when <command>gdb</command> starts up, you'll know that + the program wasn't compiled with the <option>-g</option> + option.</para> + + <para>At the <command>gdb</command> prompt, type + <userinput>break main</userinput>. This will tell the + debugger to skip over the preliminary set-up code in the + program and start at the beginning of your code. Now type + <userinput>run</userinput> to start the program—it will + start at the beginning of the set-up code and then get stopped + by the debugger when it calls <function>main()</function>. + (If you've ever wondered where <function>main()</function> + gets called from, now you know!).</para> + + <para>You can now step through the program, a line at a time, by + pressing <command>n</command>. If you get to a function call, + you can step into it by pressing <command>s</command>. Once + you're in a function call, you can return from stepping into a + function call by pressing <command>f</command>. You can also + use <command>up</command> and <command>down</command> to take + a quick look at the caller.</para> + + <para>Here's a simple example of how to spot a mistake in a + program with <command>gdb</command>. This is our program + (with a deliberate mistake):</para> + + <programlisting>#include <stdio.h> + +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>This program sets <symbol>i</symbol> to be + <literal>5</literal> and passes it to a function + <function>bazz()</function> which prints out the number we + gave it.</para> + + <para>When we compile and run the program we get</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>That wasn't what we expected! Time to see what's going + on!</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</> <lineannotation>Skip the set-up code</> +Breakpoint 1 at 0x160f: file temp.c, line 9. <lineannotation><command>gdb</command> puts breakpoint at <function>main()</></> +(gdb) <userinput>run</> <lineannotation>Run as far as <function>main()</></> +Starting program: /home/james/tmp/temp <lineannotation>Program starts running</> + +Breakpoint 1, main () at temp.c:9 <lineannotation><command>gdb</command> stops at <function>main()</></> +(gdb) <userinput>n</> <lineannotation>Go to next line</> +This is my program <lineannotation>Program prints out</> +(gdb) <userinput>s</> <lineannotation>step into <function>bazz()</></> +bazz (anint=4231) at temp.c:17 <lineannotation><command>gdb</command> displays stack frame</> +(gdb) + </screen> + + <para>Hang on a minute! How did <symbol>anint</symbol> get to be + <literal>4231</literal>? Didn't we set it to be + <literal>5</literal> in <function>main()</function>? Let's + move up to <function>main()</function> and have a look.</para> + + <screen>(gdb) <userinput>up</> <lineannotation>Move up call stack</> +#1 0x1625 in main () at temp.c:11 <lineannotation><command>gdb</command> displays stack frame</> +(gdb) <userinput>p i</> <lineannotation>Show us the value of <symbol>i</></> +$1 = 4231 <lineannotation><command>gdb</command> displays <literal>4231</></> + </screen> + + <para>Oh dear! Looking at the code, we forgot to initialise + <symbol>i</symbol>. We meant to put</para> + + <programlisting><lineannotation>…</> +main() { + int i; + + i = 5; + printf("This is my program\n"); +<lineannotation>&hellip</> + </programlisting> + + <para>but we left the <literal>i=5;</literal> line out. As we + didn't initialise <symbol>i</symbol>, it had whatever number + happened to be in that area of memory when the program ran, + which in this case happened to be + <literal>4231</literal>.</para> + + <note> + <para><command>gdb</command> displays the stack frame every + time we go into or out of a function, even if we're using + <command>up</command> and <command>down</command> to move + around the call stack. This shows the name of the function + and the values of its arguments, which helps us keep track + of where we are and what's going on. (The stack is a + storage area where the program stores information about the + arguments passed to functions and where to go when it + returns from a function call).</para> + </note> + </sect2> + + <sect2> + <title>Examining a core file</title> + + <para>A core file is basically a file which contains the + complete state of the process when it crashed. In <quote>the + good old days</quote>, programmers had to print out hex + listings of core files and sweat over machine code manuals, + but now life is a bit easier. Incidentally, under FreeBSD and + other 4.4BSD systems, a core file is called + <filename><replaceable>progname</replaceable>.core</filename> instead of just + <filename>core</filename>, to make it clearer which program a + core file belongs to.</para> + + <para>To examine a core file, start up <command>gdb</command> in + the usual way. Instead of typing <command>break</command> or + <command>run</command>, type</para> + + <screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput> + </screen> + + <para>If you're not in the same directory as the core file, + you'll have to do <userinput>dir + /path/to/core/file</userinput> first.</para> + + <para>You should see something like this:</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 this case, the program was called + <filename>a.out</filename>, so the core file is called + <filename>a.out.core</filename>. We can see that the program + crashed due to trying to access an area in memory that was not + available to it in a function called + <function>bazz</function>.</para> + + <para>Sometimes it's useful to be able to see how a function was + called, as the problem could have occurred a long way up the + call stack in a complex program. The <command>bt</command> + command causes <command>gdb</command> to print out a + back-trace of the call stack:</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>The <function>end()</function> function is called when a + program crashes; in this case, the <function>bazz()</function> + function was called from <function>main()</function>.</para> + </sect2> + + <sect2> + <title>Attaching to a running program</title> + + <para>One of the neatest features about <command>gdb</command> + is that it can attach to a program that's already running. Of + course, that assumes you have sufficient permissions to do so. + A common problem is when you are stepping through a program + that forks, and you want to trace the child, but the debugger + will only let you trace the parent.</para> + + <para>What you do is start up another <command>gdb</command>, + use <command>ps</command> to find the process ID for the + child, and do</para> + + <screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput> + </screen> + + <para>in <command>gdb</command>, and then debug as usual.</para> + + <para><quote>That's all very well,</quote> you're probably + thinking, <quote>but by the time I've done that, the child + process will be over the hill and far away</quote>. Fear + not, gentle reader, here's how to do it (courtesy of the + <command>gdb</command> info pages):</para> + + <screen><lineannotation>&hellip</lineannotation> +if ((pid = fork()) < 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>Now all you have to do is attach to the child, set + <symbol>PauseMode</symbol> to <literal>0</literal>, and wait + for the <function>sleep()</function> call to return!</para> + </sect2> + </sect1> + + <sect1 id="emacs"> + <title>Using Emacs as a Development Environment</title> + + <sect2> + <title>Emacs</title> + + <para>Unfortunately, Unix systems don't come with the kind of + everything-you-ever-wanted-and-lots-more-you-didn't-in-one-gigantic-package + integrated development environments that other systems + have. + + <footnote> + <para>At least, not unless you pay out very large sums of + money.</para> + </footnote> + + However, it is possible to set up your own environment. It + may not be as pretty, and it may not be quite as integrated, + but you can set it up the way you want it. And it's free. + And you have the source to it.</para> + + <para>The key to it all is Emacs. Now there are some people who + loathe it, but many who love it. If you're one of the former, + I'm afraid this section will hold little of interest to you. + Also, you'll need a fair amount of memory to run it—I'd + recommend 8MB in text mode and 16MB in X as the bare minimum + to get reasonable performance.</para> + + <para>Emacs is basically a highly customisable + editor—indeed, it has been customised to the point where + it's more like an operating system than an editor! Many + developers and sysadmins do in fact spend practically all + their time working inside Emacs, leaving it only to log + out.</para> + + <para>It's impossible even to summarise everything Emacs can do + here, but here are some of the features of interest to + developers:</para> + + <itemizedlist> + <listitem> + <para>Very powerful editor, allowing search-and-replace on + both strings and regular expressions (patterns), jumping + to start/end of block expression, etc, etc.</para> + </listitem> + + <listitem> + <para>Pull-down menus and online help.</para> + </listitem> + + <listitem> + <para>Language-dependent syntax highlighting and + indentation.</para> + </listitem> + + <listitem> + <para>Completely customisable.</para> + </listitem> + + <listitem> + <para>You can compile and debug programs within + Emacs.</para> + </listitem> + + <listitem> + <para>On a compilation error, you can jump to the offending + line of source code.</para> + </listitem> + + <listitem> + <para>Friendly-ish front-end to the <command>info</command> + program used for reading GNU hypertext documentation, + including the documentation on Emacs itself.</para> + </listitem> + + <listitem> + <para>Friendly front-end to <command>gdb</command>, allowing + you to look at the source code as you step through your + program.</para> + </listitem> + + <listitem> + <para>You can read Usenet news and mail while your program + is compiling.</para> + </listitem> + </itemizedlist> + + <para>And doubtless many more that I've overlooked.</para> + + <para>Emacs can be installed on FreeBSD using <ulink + URL="../../ports/editors.html">the Emacs + port</ulink>.</para> + + <para>Once it's installed, start it up and do <userinput>C-h + t</userinput> to read an Emacs tutorial—that means + hold down the <keycap>control</keycap> key, press + <keycap>h</keycap>, let go of the <keycap>control</keycap> + key, and then press <keycap>t</keycap>. (Alternatively, you + can you use the mouse to select <guimenuitem>Emacs + Tutorial</guimenuitem> from the <guimenu>Help</guimenu> + menu).</para> + + <para>Although Emacs does have menus, it's well worth learning + the key bindings, as it's much quicker when you're editing + something to press a couple of keys than to try and find the + mouse and then click on the right place. And, when you're + talking to seasoned Emacs users, you'll find they often + casually throw around expressions like <quote><literal>M-x + replace-s RET foo RET bar RET</literal></quote> so it's + useful to know what they mean. And in any case, Emacs has far + too many useful functions for them to all fit on the menu + bars.</para> + + <para>Fortunately, it's quite easy to pick up the key-bindings, + as they're displayed next to the menu item. My advice is to + use the menu item for, say, opening a file until you + understand how it works and feel confident with it, then try + doing C-x C-f. When you're happy with that, move on to + another menu command.</para> + + <para>If you can't remember what a particular combination of + keys does, select <guimenuitem>Describe Key</guimenuitem> from + the <guimenu>Help</guimenu> menu and type it in—Emacs + will tell you what it does. You can also use the + <guimenuitem>Command Apropos</guimenuitem> menu item to find + out all the commands which contain a particular word in them, + with the key binding next to it.</para> + + <para>By the way, the expression above means hold down the + <keysym>Meta</keysym> key, press <keysym>x</keysym>, release + the <keysym>Meta</keysym> key, type + <userinput>replace-s</userinput> (short for + <literal>replace-string</literal>—another feature of + Emacs is that you can abbreviate commands), press the + <keysym>return</keysym> key, type <userinput>foo</userinput> + (the string you want replaced), press the + <keysym>return</keysym> key, type bar (the string you want to + replace <literal>foo</literal> with) and press + <keysym>return</keysym> again. Emacs will then do the + search-and-replace operation you've just requested.</para> + + <para>If you're wondering what on earth the + <keysym>Meta</keysym> key is, it's a special key that many + Unix workstations have. Unfortunately, PC's don't have one, + so it's usually the <keycap>alt</keycap> key (or if you're + unlucky, the <keysym>escape</keysym> key).</para> + + <para>Oh, and to get out of Emacs, do <command>C-x C-c</command> + (that means hold down the <keysym>control</keysym> key, press + <keysym>x</keysym>, press <keysym>c</keysym> and release the + <keysym>control</keysym> key). If you have any unsaved files + open, Emacs will ask you if you want to save them. (Ignore + the bit in the documentation where it says + <command>C-z</command> is the usual way to leave + Emacs—that leaves Emacs hanging around in the + background, and is only really useful if you're on a system + which doesn't have virtual terminals).</para> + </sect2> + + <sect2> + <title>Configuring Emacs</title> + + <para>Emacs does many wonderful things; some of them are built + in, some of them need to be configured.</para> + + <para>Instead of using a proprietary macro language for + configuration, Emacs uses a version of Lisp specially adapted + for editors, known as Emacs Lisp. This can be quite useful if + you want to go on and learn something like Common Lisp, as + it's considerably smaller than Common Lisp (although still + quite big!).</para> + + <para>The best way to learn Emacs Lisp is to download the <ulink + URL="ftp://prep.ai.mit.edu:pub/gnu/elisp-manual-19-2.4.tar.gz">Emacs + Tutorial</ulink></para> + + <para>However, there's no need to actually know any Lisp to get + started with configuring Emacs, as I've included a sample + <filename>.emacs</filename> file, which should be enough to + get you started. Just copy it into your home directory and + restart Emacs if it's already running; it will read the + commands from the file and (hopefully) give you a useful basic + setup.</para> + </sect2> + + <sect2> + <title>A sample <filename>.emacs</filename> file</title> + + <para>Unfortunately, there's far too much here to explain it in + detail; however there are one or two points worth + mentioning.</para> + + <itemizedlist> + <listitem> + <para>Everything beginning with a <literal>;</literal> is a comment + and is ignored by Emacs.</para> + </listitem> + + <listitem> + <para>In the first line, the + <literal>-*- Emacs-Lisp -*-</literal> is so that + we can edit the <filename>.emacs</filename> file itself + within Emacs and get all the fancy features for editing + Emacs Lisp. Emacs usually tries to guess this based on + the filename, and may not get it right for + <filename>.emacs</filename>.</para> + </listitem> + + <listitem> + <para>The <keysym>tab</keysym> key is bound to an + indentation function in some modes, so when you press the + tab key, it will indent the current line of code. If you + want to put a <token>tab</token> character in whatever + you're writing, hold the <keysym>control</keysym> key down + while you're pressing the <keysym>tab</keysym> key.</para> + </listitem> + + <listitem> + <para>This file supports syntax highlighting for C, C++, + Perl, Lisp and Scheme, by guessing the language from the + filename.</para> + </listitem> + + <listitem> + <para>Emacs already has a pre-defined function called + <function>next-error</function>. In a compilation output + window, this allows you to move from one compilation error + to the next by doing <command>M-n</command>; we define a + complementary function, + <function>previous-error</function>, that allows you to go + to a previous error by doing <command>M-p</command>. The + nicest feature of all is that <command>C-c C-c</command> + will open up the source file in which the error occurred + and jump to the appropriate line.</para> + </listitem> + + <listitem> + <para>We enable Emacs's ability to act as a server, so that + if you're doing something outside Emacs and you want to + edit a file, you can just type in</para> + + <screen>&prompt.user; <userinput>emacsclient <replaceable>filename</replaceable></userinput> + </screen> + + <para>and then you can edit the file in your + Emacs! + + <footnote> + <para>Many Emacs users set their <systemitem + class=environvar>EDITOR</systemitem> environment to + <literal>emacsclient</literal> so this happens every + time they need to edit a file.</para> + </footnote></para> + </listitem> + </itemizedlist> + + <example> + <title>A sample <filename>.emacs</filename> file</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-<") +(global-set-key [C-end] "\M->") +(global-set-key [C-prior] "\M-<") +(global-set-key [C-next] "\M->") + +;; 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 <CR> 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) + +;; 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 colour &optional bold) + "Create a face from a colour and optionally make it bold" + (make-face face) + (copy-face 'default face) + (set-face-foreground face colour) + (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>Extending the Range of Languages Emacs Understands</title> + + <para>Now, this is all very well if you only want to program in + the languages already catered for in the + <filename>.emacs</filename> file (C, C++, Perl, Lisp and + Scheme), but what happens if a new language called + <quote>whizbang</quote> comes out, full of exciting + features?</para> + + <para>The first thing to do is find out if whizbang comes with + any files that tell Emacs about the language. These usually + end in <filename>.el</filename>, short for <quote>Emacs + Lisp</quote>. For example, if whizbang is a FreeBSD port, we + can locate these files by doing</para> + + <screen>&prompt.user; <userinput>find /usr/ports/lang/whizbang -name "*.el" -print</userinput> + </screen> + + <para>and install them by copying them into the Emacs site Lisp + directory. On FreeBSD 2.1.0-RELEASE, this is + <filename>/usr/local/share/emacs/site-lisp</filename>.</para> + + <para>So for example, if the output from the find command + was</para> + + <screen>/usr/ports/lang/whizbang/work/misc/whizbang.el + </screen> + + <para>we would do</para> + + <screen>&prompt.root; <userinput>cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp</userinput> + </screen> + + <para>Next, we need to decide what extension whizbang source + files have. Let's say for the sake of argument that they all + end in <filename>.wiz</filename>. We need to add an entry to + our <filename>.emacs</filename> file to make sure Emacs will + be able to use the information in + <filename>whizbang.el</filename>.</para> + + <para>Find the <symbol>auto-mode-alist entry</symbol> in + <filename>.emacs</filename> and add a line for whizbang, such + as:</para> + + <programlisting><lineannotation>…</> +("\\.lsp$" . lisp-mode) +("\\.wiz$" . whizbang-mode) +("\\.scm$" . scheme-mode) +<lineannotation>…</> + </programlisting> + + <para>This means that Emacs will automatically go into + <function>whizbang-mode</function> when you edit a file ending + in <filename>.wiz</filename>.</para> + + <para>Just below this, you'll find the + <symbol>font-lock-auto-mode-list</symbol> entry. Add + <function>whizbang-mode</function> to it like so:</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>This means that Emacs will always enable + <function>font-lock-mode</function> (ie syntax highlighting) + when editing a <filename>.wiz</filename> file.</para> + + <para>And that's all that's needed. If there's anything else + you want done automatically when you open up a + <filename>.wiz</filename> file, you can add a + <function>whizbang-mode hook</function> (see + <function>my-scheme-mode-hook</function> for a simple example + that adds <function>auto-indent</function>).</para> + </sect2> + </sect1> + + <sect1> + <title>Further Reading</title> + + <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> - <para></para> </chapter> <chapter id="secure-programming"> @@ -1357,7 +3598,7 @@ DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0); </chapter> </part> - <part id="debugging"> + <part id="debuggingpart"> <title>Debugging</title> <chapter id="truss"> |