diff --git a/en/tutorials/Makefile b/en/tutorials/Makefile index 40a10bc3f1..e414259fe1 100644 --- a/en/tutorials/Makefile +++ b/en/tutorials/Makefile @@ -1,5 +1,5 @@ DOCS= index.sgml -SUBDIR= disklessx newuser -DOCSUBDIR= ddwg devel fonts mh multios ppp +SUBDIR= devel disklessx newuser +DOCSUBDIR= ddwg fonts mh multios ppp .include "../web.mk" diff --git a/en/tutorials/devel/Makefile b/en/tutorials/devel/Makefile index 6cc882035c..9429f7790d 100644 --- a/en/tutorials/devel/Makefile +++ b/en/tutorials/devel/Makefile @@ -1,5 +1,5 @@ -DOC= devel -SRCS= devel.sgml +DOCS= devel.docb +INDEXLINK= devel.html -.include <bsd.sgml.mk> +.include "../../web.mk" diff --git a/en/tutorials/devel/devel.docb b/en/tutorials/devel/devel.docb new file mode 100644 index 0000000000..524d8730f3 --- /dev/null +++ b/en/tutorials/devel/devel.docb @@ -0,0 +1,1835 @@ +<!-- $FreeBSD$ --> +<!-- The FreeBSD Documentation Project --> + +<!DOCTYPE BOOK PUBLIC "-//Davenport//DTD DocBook V3.0//EN"> +<book> +<bookinfo> +<bookbiblio> +<title>A User's Guide to FreeBSD Programming Tools</title> + +<authorgroup> +<author> +<firstname>James</firstname> +<surname>Raynard</surname> +<affiliation> +<address> +<email>jraynard@freebsd.org</email> +</address> +</affiliation> +</author></authorgroup> + +<pubdate>January 19, 1997</pubdate> + +<copyright> +<year>1997</year> +<holder>James Raynard</holder> +</copyright> + +<abstract><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></abstract> +</bookbiblio> +</bookinfo> + +<chapter> +<title>Introduction<anchor id=foo></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</> and <command>awk</>. 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</> and +<acronym>ANSI</> 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> + +</chapter> + +<chapter> +<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</>, the other a +<firstterm>compiler</>. 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> + + + +<sect1> +<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>csh</>) is itself an interpreter, and many people do in fact +write shell <quote>scripts</quote> to help with various +<quote>housekeeping</> 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> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>pkg_add <replaceable>package name</></userinput></screen> +</para> + +<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> + +<para> +<variablelist> +<varlistentry><term><acronym>BASIC</></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</> has been the first programming language +for many programmers. It's also the foundation for <trademark>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</> +scripts.</para> + +<para>Version 4, which is probably still the most widely-used +version, comes with FreeBSD; the newer <ulink +URL="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/perl-5.001.tgz">Perl +Version 5</ulink> is available as a package.</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> +</para> + +</sect1> + +<sect1> +<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</> as such; however +it is possible to use Emacs for this purpose. This is discussed in +<xref linkend="emacs">.</para> + +</sect1> +</chapter> + +<chapter> +<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</> or <command>gcc</>. 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</> converts the source code into its own, +machine-independent <firstterm>p-code</> 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</> is often used to refer to just +steps 1 to 4—the others are referred to as +<firstterm>linking</>. Sometimes step 1 is referred to as +<firstterm>pre-processing</> and steps 3-4 as +<firstterm>assembling</>.</para> + +<para>Fortunately, almost all this detail is hidden from you, as +<command>cc</> is a front end that manages calling all these programs +with the right arguments for you; simply typing +<screen>$ <userinput>cc foobar.c</></screen></para> + +<para>will cause <filename>foobar.c</> to be compiled by all the +steps above. If you have more than one file to compile, just do +something like +<screen>$ <userinput>cc foo.c bar.c</></screen> +</para> + +<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</>, 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></></term> + +<listitem><para>The output name of the file. If you do not use this +option, <command>cc</> will produce an executable called +<filename>a.out</>.<footnote><para>The reasons for this are buried in +the mists of history.</para></footnote></para> + +<informalexample> +<screen>$ <userinput>cc foobar.c</> <lineannotation>executable is <filename>a.out</></> +$ <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>$ <userinput>cc -c foobar.c</userinput></screen> +</informalexample> + +<para>This will produce an <firstterm>object file</> (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>$ <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>$ <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</> 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</> 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>$ <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>$ <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>$ <userinput>cc -o foobar foobar.cc -lg++</userinput> <lineannotation>For FreeBSD 2.1.6 and earlier</> +$ <userinput>cc -o foobar foobar.cc -lstdc++</userinput> <lineannotation>For FreeBSD 2.2 and later</> +$ <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 <trademark>MS-DOS</trademark> 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> + +<sect1> +<title>Common <command>cc</command> Queries and Problems</title> + +<para>Q. 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? +<informalexample> +<screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment</screen> +</informalexample> +</para> + +<para>A. When using mathematical functions like +<function>sin()</function>, you have to tell <command>cc</command> to +link in the math library, like so: +<informalexample> +<screen>$ <userinput>cc -o foobar foobar.c -lm</userinput></screen> +</informalexample></para> + +<para>Q. 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. +<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> +and I compiled it as: +<informalexample> +<screen>$ <userinput>cc temp.c -lm</userinput></screen> +</informalexample> +like you said I should, but I get this when I run it: +<informalexample> +<screen>$ <userinput>./a.out</userinput> +2.1 ^ 6 = 1023.000000</screen> +</informalexample> +</para> + +<para>This is <emphasis>not</emphasis> the right answer! What is +going on?</para> + +<para>A. 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> + +<para>Q. So how do I fix this?</para> + +<para>A. 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! +<informalexample> +<programlisting>#include <math.h> +#include <stdio.h> + +int main() { +...</programlisting> +</informalexample> +</para> + +<para>After recompiling it as you did before, run it: +<informalexample> +<screen>$ <userinput>./a.out</userinput> +2.1 ^ 6 = 85.766121</screen> +</informalexample> +</para> + +<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> + +<para>Q. I compiled a file called <filename>foobar.c</filename> and I +cannot find an executable called <filename>foobar</filename>. Where's +it gone?</para> + +<para>A. 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: +<informalexample> +<screen>$ <userinput>cc -o foobar foobar.c</userinput></screen> +</informalexample> +</para> + +<para>Q. 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> + +<para>A. Unlike <trademark>MS-DOS</trademark>, 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 +<informalexample> +<screen>bin:/usr/bin:/usr/local/bin:.</screen> +</informalexample> +The dot at the end means <quote>look in the current directory if it is not in +any of the others</quote>.</para> + +<para>Q. I called my executable <filename>test</filename>, but +nothing happens when I run it. What is going on?</para> + +<para>A. 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: +<informalexample> +<screen>$ <userinput>./test</userinput></screen> +</informalexample> +or choose a better name for your program!</para> + +<para>Q. 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> + +<para>A. 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> + +<para>Q. Fascinating stuff, but what I am supposed to do now?</para> + +<para>A. Use <command>gdb</command> to analyse the core (see <xref +linkend="debugging">).</para> + +<para>Q. When my program dumped core, it said something about a +<errorname>segmentation fault</errorname>. What's that?</para> + +<para>A. 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: +<itemizedlist> +<listitem><para>Trying to write to a <symbol>NULL</symbol> pointer, eg +<programlisting>char *foo = NULL; +strcpy(foo, "bang!");</programlisting> +</para></listitem> + +<listitem><para>Using a pointer that hasn't been initialised, eg +<programlisting>char *foo; +strcpy(foo, "bang!");</programlisting> +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 +<programlisting>int bar[20]; +bar[27] = 6;</programlisting></para></listitem> + +<listitem><para> Trying to store something in read-only memory, eg +<programlisting>char *foo = "My string"; +strcpy(foo, "bang!");</programlisting> +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 +<programlisting>char bar[80]; +free(bar);</programlisting> +or +<programlisting>char *foo = malloc(27); +free(foo); +free(foo);</programlisting> +</para></listitem> + +</itemizedlist></para> + +<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> + +<para>Q. 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> + +<para>A. 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> + +<para>Q. 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> + +<para>A. Yes, just go to another console or xterm, do +<screen>$ <userinput>ps</userinput></screen> +to find out the process ID of your program, and do +<screen>$ <userinput>kill -ABRT <replaceable>pid</replaceable></userinput></screen> +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> + +</sect1> +</chapter> + + +<chapter> +<title>Make</title> + +<sect1> +<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 +<screen>$ <userinput>cc file1.c file2.c</userinput></screen> +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: +<screen>$ <userinput>cc file1.o file2.o</userinput> … <userinput>file37.c</userinput> &hellip</screen> +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> + +</sect1> + +<sect1> +<title>Example of using <command>make</command></title> + +<para>Here's a very simple make file: +<programlisting>foo: foo.c + cc -o foo foo.c</programlisting> +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: +<programlisting>foo: foo.c + cc -o foo foo.c + +install: + cp foo /home/me</programlisting></para> + +<para>We can tell make which target we want to make by typing: +<screen>$ <userinput>make <replaceable>target</replaceable></userinput></screen> +<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> + +</sect1> + +<sect1> +<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>: +<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> + +<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> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>zmore paper.ascii.gz</userinput></screen> +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 +<programlisting> * Make: (make). The GNU Make utility.</programlisting> +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> + +</sect1> +</chapter> + +<chapter id="debugging"> +<title>Debugging</title> + +<sect1> +<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 +<screen>$ <userinput>gdb <replaceable>progname</replaceable></userinput></screen> +although most people prefer to run it inside +<application>Emacs</application>. You can do this by: +<screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput></screen></para> + +<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="http://www.freebsd.org/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> + +</sect1> + +<sect1> +<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: +<screen>… (no debugging symbols found) …</screen>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): +<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> + +<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 +<screen>$ <userinput>cc -g -o temp temp.c</userinput> +$ <userinput>./temp</userinput> +This is my program +anint = 4231</screen></para> + +<para>That wasn't what we expected! Time to see what's going +on!<screen>$ <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> + + +<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> + +<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> +Oh dear! Looking at the code, we forgot to initialise +<symbol>i</symbol>. We meant to put +<programlisting><lineannotation>…</> +main() { + int i; + + i = 5; + printf("This is my program\n"); +<lineannotation>&hellip</></programlisting> +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> + +</sect1> + +<sect1> +<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</>.core</> 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 +<screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput></screen> +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: +<screen>$ <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> + +<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: +<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>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> + +</sect1> + +<sect1> +<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<screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput></screen> +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): +<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> +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> + +</sect1> +</chapter> + +<chapter id="emacs"> +<title>Using Emacs as a Development Environment</title> + +<sect1> +<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: +<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>And doubtless many more that I've overlooked.</para> + +<para>Emacs can be installed on FreeBSD using <ulink +URL="http://www.freebsd.org/ports/editors">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-c C-x</command> +(that means hold down the <keysym>control</keysym> key, press +<keysym>c</keysym>, press <keysym>x</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> + +</sect1> + +<sect1> +<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> + +</sect1> + +<sect1> +<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> + +<para> +<itemizedlist> + +<listitem><para>Everything beginning with a <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 +<screen>$ <userinput>emacsclient <replaceable>filename</replaceable></userinput></screen> +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> +</para> + +<example> +<title>A sample <filename>.emacs</filename> file</title> +<screen>;; -*-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") </screen> + +<screen>(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)))</screen> + +<screen>;; 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) ".") +</screen> +</example> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>find /usr/ports/lang/whizbang -name "*.el" -print</userinput></screen> +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 +<screen>/usr/ports/lang/whizbang/work/misc/whizbang.el</screen> +we would do +<screen>$ <userinput>cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp</userinput></screen> +</para> + +<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: +<programlisting><lineannotation>…</> +("\\.lsp$" . lisp-mode) +("\\.wiz$" . whizbang-mode) +("\\.scm$" . scheme-mode) +<lineannotation>…</></programlisting> +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: +<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> +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> + +</sect1> +</chapter> + +<chapter> +<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> + +</chapter> +</book> diff --git a/en/tutorials/devel/devel.sgml b/en/tutorials/devel/devel.sgml deleted file mode 100644 index 0fde023afd..0000000000 --- a/en/tutorials/devel/devel.sgml +++ /dev/null @@ -1,1739 +0,0 @@ -<!DOCTYPE linuxdoc PUBLIC "-//FreeBSD//DTD linuxdoc//EN"> -<!-- $Id: devel.sgml,v 1.2 1996-10-06 20:17:10 jfieber Exp $ --> - -<!-- - ++++++++++++++++++++++++++++++++++++++++++++++++++ - ++ file: /home/james/docs/devel.sgml - ++ - ++ Copyright James Raynard, Thursday 30th May 1996 - ++ - ++ Sgml doc for programming under FreeBSD. - --> - -<article> - -<title>A User's Guide to FreeBSD Programming Tools -<author>James Raynard, <tt /jraynard@freebsd.org/ -<date>30th May 1996 - -<abstract> - -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 <it /not/ 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 - -</abstract> - -<sect><heading>Introduction</heading> -<p> - -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 sed and awk. -If that isn't enough, there are many more compilers and interpreters -in the Ports collection. FreeBSD is very compatible with standards -such as POSIX and ANSI 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. -<p> -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. -<p> -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! - -<sect><heading>Introduction to Programming</heading> -<p> -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 ``commands'' as they're usually called. One way uses -an interpreter, the other a compiler. 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. - -<sect1><heading>Interpreters</heading> -<p> -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. -<P> -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. -<p> -In my opinion, interpreted languages are the best way to start if you -haven't 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 (sh, csh) is itself -an interpreter, and many people do in fact write shell `scripts' to -help with various ``housekeeping'' 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. -<p> -<sect1><heading>Interpreters available with FreeBSD</heading> -<p> -Here is a list of interpreters that are available as <htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/" name="FreeBSD -packages">, with a brief discussion of some of the more popular -interpreted languages. -<p> -To get one of these packages, all you need to do is to click on the -hotlink for the package, then run - -<tscreen><verb> - pkg_add <package name> -</verb></tscreen> - -as root. Obviously, you'll need to have a fully-functional FreeBSD -2.1.0 system for the package to work! - -<descrip> -<tag>Basic</tag> - -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, BASIC has -been the first programming language for many programmers. It's also -the foundation for Visual Basic. - -The <htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/bwbasic-2.10.tgz" -name="Bywater Basic Interpreter"> and the <htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/pbasic-2.0.tgz" -name="Phil Cockroft's Basic Interpreter"> (formerly Rabbit Basic) are -available as FreeBSD <htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/" name="FreeBSD -packages"> - -<tag>Lisp</tag> - -A language that was developed in the late 1950s as an alternative to -the ``number-crunching'' 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 "List Processing". Very popular in AI -(Artificial Intelligence) circles. - -Lisp is an extremely powerful and sophisticated language, but can be -rather large and unwieldy. - -FreeBSD has <htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/gcl-2.0.tgz" name="GNU -Common Lisp"> available as a package. - -<tag>Perl</tag> - -Very popular with system administrators for writing scripts; also -often used on World Wide Web servers for writing CGI scripts. - -Version 4, which is probably still the most widely-used version, comes -with FreeBSD; the newer -<htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/perl-5.001.tgz" -name="Perl Version 5"> is available as a package. - -<tag>Scheme</tag> - -A dialect of Lisp that is rather more compact and cleaner than Common -Lisp. Popular in Universities as it's 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. - -FreeBSD has packages of the -<htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/elk-3.0.tgz" -name="Elk Scheme Interpreter">, the -<htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/mit-scheme-7.3.tgz" -name="MIT Scheme Interpreter"> and the -<htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/scm-4e1.tgz" -name="SCM Scheme Interpreter">. -<!-- -<tag>TCL and Tk</tag> - -Programming with the X windowing system can best be described as -rather character-forming. As someone once said, if they designed cars -the way X was designed, each car would have five steering wheels, all -following completely different conventions, but you can use the -radio-cassette player to change gears, which is a really useful -feature when you think about it. Or perhaps not. -<p> -Fortunately, it doesn't have to be like that. A number of people have -written "toolkits" for X, where all the interaction with X is hidden -inside toolkit routines and you can just say, in effect, ``pop up a -window and draw a line from point A to point B''. Many of these are -`libraries' that have to be called from inside a C program, but one of -the best known toolkits, John Ousterhout's Tk, provides a -straightforward way to write GUI programs using a scripted -language. And by one of those remarkable coincidences, he also happens -to have written an embeddable language, TCL (Tool Command Language) -which is very suitable for the purpose, although it is possible to use -other interpreted languages such as Perl or Scheme to send commands to -Tk. - -FreeBSD has a <htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/tcl-7.4.2.tgz" -name="Tool Command Language"> package. ---> -<tag>Icon</tag> - -<htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/icon-9.0.tgz" -name="The Icon Programming Language">. - -<tag>Logo</tag> - -<htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/ucblogo-3.3.tgz" -name="Brian Harvey's LOGO Interpreter">. - -<tag>Python</tag> -<htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/python-1.2" -name="The Python Object-Oriented Programming Language"> - -</descrip> - -<sect1><heading>Compilers</heading> -<p> -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 didn't 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. (If you run it in the shell, you may get a core dump). -<p> -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 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 -wouldn't 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). -<p> -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. -<p> -As the edit-compile-run-debug cycle is rather tedious when using -separate programs, many commercial compiler makers have produced -Integrated Development Environments (IDEs for short). FreeBSD doesn't -have an IDE as such; however it's possible to use Emacs for this -purpose. This is discussed under Emacs. - -<sect><heading>Compiling with cc</heading> -<p> -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 -`cc' or `gcc'. 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. -<p> -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. - -<enum> - -<item> Pre-process your source code to remove comments and do other -tricks like expanding `macros' in C. - -<item> Check the syntax of your code to see if you have obeyed the -rules of the language. If you haven't, it will complain! - -<item> Convert the source code into assembler - this is very close to -machine code, but still understandable by humans. Allegedly. (To be -strictly accurate, cc converts the source code into its own, -machine-independent p-code instead of assembler at this stage). - -<item> Convert the assembler into machine code - yep, we're talking -bits and bytes, ones and zeros here. - -<item> Check that you've used things like functions and global -variables in a consistent way (eg if you've called a non-existent -function, it'll complain). - -<item> If you're trying to produce an executable from several source -code files, work out how to fit them all together. - -<item> Work out how to produce something that the system's run-time -loader will be able to load into memory and run. - -<item> (Finally!) Write the executable on the file system. -</enum> - -The word ``compiling'' is often used to refer to just steps 1 to 4 - -the others are referred to as ``linking''. Sometimes step 1 is -referred to as ``pre-processing'' and steps 3-4 as ``assembling''. -<p> -Fortunately, almost all this detail is hidden from you, as cc is a -front end that manages calling all these programs with the right -arguments for you; simply typing - -<tscreen><verb> - cc foobar.c -</verb></tscreen> - -will cause foobar.c to be compiled by all the steps above. If you have -more than one file to compile, just do something like - -<tscreen><verb> - cc foo.c bar.c -</verb></tscreen> - -Note that the syntax checking is just that - checking the syntax. It -won't 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. {In case you didn't know, a -binary sort is an efficient way of sorting things into order and a -bubble sort isn't.} -<p> -There are lots and lots of options for cc, which are all in the man -page. Here are a few of the most important ones, with examples of how -to use them. - -<descrip> -<tag/-o/ - The output name of the file. If you don't use this option, cc will - produce an executable called `a.out' (the reasons for this are buried - in the mists of history). - - Example:- -<tscreen><verb> - cc foobar.c executable is a.out - cc -o foobar foobar.c executable is foobar -</verb></tscreen> - -<tag/-c/ - Just compile the file, don't link it. Useful for toy programs where - you just want to check the syntax, or if you're using a Make file. - - Example:- - -<tscreen><verb> - cc -c foobar.c -</verb></tscreen> - - This will produce an ``object file'' (not an executable) called - `foobar.o'. This can be linked together with other object files - into an executable. - -<tag/-g/ - - 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 <it /very/ useful; the disadvantage is that all - this extra information makes the program much bigger. Normally, - you compile with -g while you're developing a program and then - compile a ``release version'' without -g when you're satisfied it - works properly. - - Example:- - -<tscreen><verb> - cc -g foobar.c -</verb></tscreen> - - This will produce a debug version of the program. (Note, we didn't use - the -o flag to specify the executable name, so we'll get an executable - called `a.out'. Producing a debug version called `foobar' is left as an - exercise for the reader!) - -<tag/-O/ - 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 `O' to specify a higher - level of optimisation, but this often exposes bugs in the compiler's - optimiser. For instance, the version of cc that comes with the 2.1.0 - release of FreeBSD is known to produce bad code with the `-O2' - option in some circumstances. - - Optimisation is usually only turned on when compiling a release version. - - Example:- - -<tscreen><verb> - cc -O -o foobar foobar.c -</verb></tscreen> - - This will produce an optimised version of `foobar'. -<p> - The following three flags will force cc to check that your code - complies to the relevant international standard (often referred to - as the ``ANSI'' standard, though strictly speaking it's an ISO - standard). - -<tag/-Wall/ - Enable all the warnings which the authors of cc believe are - worthwhile. Despite the name, it will not enable all the warnings - cc is capable of. - -<tag/-ansi/ - Turn off most (but not all) of the non-standard features provided - by cc. Despite the name, it does not guarantee strictly that your - code will comply to the standard. - -<tag/-pedantic/ - Turn off <it /all/ cc's non-standard features. -<p> - Without these flags, cc 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 - ``portable code''). -<p> - 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? - - Example:- -<tscreen><verb> - cc -Wall -ansi -pedantic -o foobar foobar.c -</verb></tscreen> - will produce an executable `foobar' after checking foobar.c for standard - compliance. - -<tag/-l/ - Specify a library to be used during when linking. -<p> - 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. -<p> - The rule is that if the library is called `libsomething.a', you - give cc the argument `-lsomething'. For example, the maths library - is `libm.a', so you give cc the argument `-lm'. A common - ``gotcha'' with the maths library is that it has to be the last - library on the command line. -<p> - Example:- -<tscreen><verb> - cc -o foobar foobar.c -lm -</verb></tscreen> - will link the maths library functions into `foobar'. -<p> - If you're compiling C++ code, you need to add `-lg++' to the - command line argument, to link the C++ library functions. - Alternatively, you can run c++ instead of cc, which does this for - you. -<p> - Example:- -<tscreen><verb> - cc -o foobar foobar.cc -lg++ - c++ -o foobar foobar.cc -</verb></tscreen> - will both produce an executable `foobar' from the C++ source file - `foobar.cc'. Note that, on Unix systems, C++ source files - traditionally end in `.C', `.cxx' or `.cc', rather than the - DOS-style `.cpp' (which was already used for something else). gcc - 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 `.cpp' with impunity! - {c++ can also be invoked as g++ on FreeBSD.} -</descrip> - -<sect1><heading>Common cc Queries and Problems</heading> -<p> -Q. I'm trying to write a program which uses the sin() function and I get - an error like this. What does it mean? - -<tscreen><verb> - /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment -</verb></tscreen> - -A. When using mathematical functions like sin(), you have to tell cc to link - in the maths library, like so:- -<tscreen><verb> - cc -o foobar foobar.c -lm -</verb></tscreen> -Q. All right, I wrote this simple program to practice using -lm. All -it does is raise 2.1 to the power of 6. -<code> -#include <stdio.h> - -int main() { - float f; - - f = pow(2.1, 6); - printf("2.1 ^ 6 = %f\n", f); - return 0; -} -</code> -and I compiled it as - -<tscreen><verb> -gcc temp.c -lm -</verb></tscreen> - -like you said I should, but I get this when I run it:- -<tscreen><verb> -$ ./a.out -2.1 ^ 6 = 1023.000000 -</verb></tscreen> - -This is <it /not/ the right answer! What the %$&#'s going on? -<p> -A. When the compiler sees you call a function, it checks if it's -already seen a prototype for it. If it hasn't, it assumes the function -returns an int, which is definitely not what you want here. -<p> -Q. So how do I fix this? -<p> -A. The prototypes for the mathematical functions are in math.h. If you -include this file, the compiler will be able to find the prototype and -it'll stop doing strange things to your calculation! - -<code> -#include <math.h> -#include <stdio.h> - -int main() { -... -</code> -<p> -<tscreen><verb> -$ ./a.out -2.1 ^ 6 = 85.766121 -</verb></tscreen> - -Morale: if you're using any of the mathematical functions, always -include math.h and remember to link in the maths library. - -Q. I've compiled a file called `foobar.c' and I can't find an executable - called `foobar'. Where's it gone? -<p> -A. cc will call the executable `a.out' unless you tell it differently. Use - the -o option, eg -<tscreen><verb> - cc -o foobar foobar.c -</verb></tscreen> -Q. OK, I've got an executable called `foobar', I can see it when I do - `ls', but when I type in 'foobar' at the command prompt it tells me - there's no such file. Why can't it find it? -<p> -A. Unlike DOS, Unix won't look in the current directory when it's - trying to find out which executable you want it to run, unless you - tell it to. Either type `./foobar', which means ``run the file - called `foobar' in the current directory'', or change your PATH - environment variable so that it looks something like -<tscreen><verb> - bin:/usr/bin:/usr/local/bin:. -</verb></tscreen> - (The dot at the end means ``look in the current directory if it's not in - any of the others'') -<p> -Q. I called my executable `test', but nothing happens when I run - it. What's going on? -<p> -A. Most Unix systems have a program called `test' in /usr/bin and the - shell's picking that one up before it gets to checking the current - directory. Either type - -<tscreen><verb> - ./test -</verb></tscreen> - - or choose a better name for your program! -<p> -Q. I compiled my program and it seemed to run all right at first, then - there was an error and it said something about ``core - dumped''. What does that mean? -<p> -A. The name ``core dump'' 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 ``core'', - which the programmer could then pore over to find out what went - wrong. -<p> -Q. Fascinating stuff, but what I am supposed to do now? -<p> -A. Use gdb to analyse the core (see Debugging). -<p> -Q. When my program dumped core, it said something about a segmentation - fault. What's that? -<p> -A. 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. -<p> - Common causes for this are:- -<itemize> - <item> Trying to write to a NULL pointer, eg -<code> - char *foo = NULL; - strcpy(foo, "bang!"); -</code> - <item> Using a pointer that hasn't been initialised, eg -<code> - char *foo; - strcpy(foo, "bang!"); -</code> - 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. -<p> - <item> Trying to access past the end of an array, eg -<code> - int bar[20]; - bar[27] = 6; -</code> - <item> Trying to store something in read-only memory, eg -<code> - char *foo = "My string"; - strcpy(foo, "bang!"); -</code> - (Unix compilers often put string literals like ``My string'' into - read-only areas of memory). - - <item> Doing naughty things with malloc() and free(), eg -<code> - char bar[80]; - free(bar); -</code> - or -<code> - char *foo = malloc(27); - free(foo); - free(foo); -</code> -</itemize> - (Note 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) -<p> -Q. Sometimes when I get a core dump it says ``bus error''. It says in - my Unix book that this means a hardware problem, but the computer - still seems to be working. Is this true? -<p> -A. 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. -<p> -Q. 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? -<p> -A. Yes, just go to another console or xterm, do - -<tscreen><verb> - ps -</verb></tscreen> - -to find out the process ID of your program, and do - -<tscreen><verb> - kill -ABRT <pid> -</verb></tscreen> - - This is useful if your program has got stuck in an infinite loop, - for instance. (If your program traps SIGABRT, there are several - other signals which have a similar effect). - -<sect><heading>Make</heading> -<p> -<sect1><heading>What is make?</heading> -<p> -When you're working on a simple program with only one or two source -files, typing in - -<tscreen><verb> - cc file1.c file2.c -</verb></tscreen> - -is not too bad, but it quickly becomes very tedious when there are -several files - and it can take a while to compile, too. -<p> -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:- - -<tscreen><verb> - cc file1.o file2.o ... file37.c ... -</verb></tscreen> - -if we'd changed file37.c, but not any of the others, since the last -time we compiled. -<p> -This may speed up the compilation quite a bit, but doesn't solve the -typing problem. -<p> -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. -<p> -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? -<p> -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. -<p> -This program is called <tt /make/. It reads in a file, called a make -file, 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 ``if fromboz.o is older than -fromboz.c, that means someone must have changed fromboz.c, so it needs -to be re-compiled.'' The make file also has rules telling make <it -/how/ to re-compile the source file, making it a much more powerful -tool. -<p> -Make files are typically kept in the same directory as the source they -apply to, and can be called `makefile', `Makefile' or `MAKEFILE'. Most -programmers use the name 'Makefile', as this puts it near the top of a -directory listing, where it can easily be seen (they don't use the -`MAKEFILE' form as block capitals are often used for documentation -files like `README'). - -<sect1><heading>Example of using make</heading> -<p> -Here's a very simple make file:- -<tscreen><verb> -foo: foo.c - cc -o foo foo.c -</verb></tscreen> -It consists of two lines, a dependency line and a creation line. -<p> -The dependency line here consists of the name of the program (known as -``the target''), followed by a colon, then a gap, then the name of the -source file. When make reads this line, it looks to see if `foo' -exists; if it exists, it compares the time 'foo' was last modified to -the time `foo.c' was last modified. If 'foo' does not exist, or is -older than `foo.c', it then looks at the creation line to find out -what to do. In other words, this is the rule for working out when -foo.c needs to be re-compiled. -<p> -The creation line starts with a tab (press the tab key) and then the -command you would type to create `foo' if you were doing it at a -command prompt. If `foo' is out of date, or does not exist, `make' -then executes this command to create it. In other words, this is the -rule which tells make how to re-compile foo.c. -<p> -So, when you type `make', it will make sure that `foo' is up to date -with respect to your latest changes to `foo.c'. This principle can be -extended to Makefiles with hundreds of targets - in fact, on FreeBSD, -it is possible to compile the entire operating system just by typing -`make world' in the appropriate directory! -<p> -Another useful property of make files is that the targets don't have -to be programs. For instance, we could have a make file that looks -like this:- - -<tscreen><verb> -foo: foo.c - cc -o foo foo.c - -install: - cp foo /home/me -</verb></tscreen> - -We can tell make which target we want to make by typing - -<tscreen><verb> - make <target> -</verb></tscreen> - -make will then only look at that target and ignore any -others. For example, if we type `make foo' with the make file above, -make will ignore the 'install' target. -<p> -If we just type `make' on its own, make will always look at the first -target and then stop without looking at any others. So if we typed -`make' here, it will just go to the `foo' target, re-compile `foo' if -necessary, and then stop without going on to the `install' target. -<p> -Notice that the `install' 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 `make install'. In this -case, it will copy `foo' into the user's home directory. This is often -used by application make files, so that the application can be -installed in the correct directory when it has been correctly -compiled. -<p> -This is a slightly confusing subject to try and explain. If you don't -quite understand how make works, the best thing to do is to write a -simple program like ``hello world'' 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 `touch' command is -very useful here - it changes the date on a file without you having to -edit it). - -<sect1><heading>FreeBSD Make Files</heading> -<p> -Make files can be rather complicated to write. Fortunately, BSD-based -systems like FreeBSD come with some very powerful ones as part of the -system. -<p> -One very good example of this is the FreeBSD ports system. Here's the -essential part of a typical ports Makefile:- - -<code> -MASTER_SITES= ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/ -DISTFILES= scheme-microcode+dist-7.3-freebsd.tgz - -.include <bsd.port.mk> -</code> - -Now, if we go to the directory for this port and type make, the -following happens:- - -<enum> - -<item> A check is made to see if the source code for this port is -already on the system. - -<item> If it isn't, an FTP connection to the URL in ``MASTER_SITES'' -is set up to download the source. - -<item> 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. - -<item> Any changes required to make the source work on FreeBSD are -applied - this is known as ``patching''. - -<item> 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). - -<item> The source code for the program is compiled. In effect, we -change to the directory where the source was unpacked and do 'make' - -the program's own make file has the necessary information to build the -program. - -<item> 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 -'make install'. 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 ``package database'', so that the port can easily be -uninstalled later if we change our mind about it. - -</enum> - -Now I think you'll agree that's rather impressive for a four line -script! -<p> -The secret lies in the last line, which tells make to look in the -system make file called `bsd.port.mk'. It's easy to overlook this -line, but this is where all the clever stuff comes from - someone has -written a make file that tells make to do all the things above (plus a -couple of other things I didn't mention, not to mention handling any -errors that may occur) and anyone can get access to that just by -putting a single line in their own make file! -<p> -If you want to have a look at these system make files, they're in -/usr/share/mk, but it's probably best to wait until you've had a bit -of practice with make files, as they are very complicated (and if you -do look at them, make sure you have a flask of strong coffee handy!) - -<sect1><heading>More advanced uses of make</heading> -<p> -Make is a very powerful tool, and can do much more than the simple -example above shows. Unfortunately, there are several different -versions of make, 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. -<p> -The version of make that comes with FreeBSD is the Berkeley make; -there is a tutorial for it in /usr/share/doc/psd/12.make. To view it, -do - -<tscreen><verb> - zmore paper.ascii.gz -</verb></tscreen> - -in that directory. -<p> -Many applications in the ports use GNU make, which has a very good set -of `info' pages. If you have installed any of these ports, GNU make -will automatically have been installed as `gmake'. It's also available -as a port and package in it's own right. -<p> -To view the info pages for GNU make, you will have to edit the `dir' -file in the /usr/local/info directory to add an entry for it. This -involves adding a line like - -<tscreen><verb> - * Make: (make). The GNU Make utility. - </verb></tscreen> - -to the file. Once you have done this, you can type `info' and then -select make from the menu (or in Emacs, do C-h i). - -<sect><heading>Debugging</heading> -<p> -<sect1><heading>The Debugger</heading> -<p> -The debugger that comes with FreeBSD is called `gdb' (GNU debugger). You -start it up by typing - -<tscreen><verb> - gdb <progname> -</verb></tscreen> - -although most people prefer to run it inside Emacs. You can do this by - -<tscreen><verb> - M-x gdb RET <progname> RET. -</verb></tscreen> - -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. -<p> -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. -<p> -gdb 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. -<p> -Finally, if you find its text-based command-prompt style off-putting, -there's a graphical front-end for it <htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/ports/devel/xxgdb.tgz" -name="xxgdb"> in the ports. -<p> -This section is intended to be an introduction to using gdb and does -not cover specialised topics such as debugging the kernel. - -<sect1><heading>Running a program in the debugger</heading> -<p> -You'll need to have compiled the program with the `-g' option to get the -most out of using gdb. 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 - -<tscreen><verb> - ...(no debugging symbols found)... -</verb></tscreen> - -when gdb starts up, you'll know that the program wasn't compiled with -the `-g' option. -<p> -At the gdb prompt, type `break main'. 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 `run' 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 main(). (If you've ever wondered where main() -gets called from, now you know!). -<p> -You can now step through the program, a line at a time, by pressing -`n'. If you get to a function call, you can step into it by pressing -`s'. Once you're in a function call, you can return from stepping into -a function call by pressing `f'. You can also use `up' and `down' to -take a quick look at the caller. -<p> -Here's a simple example of how to spot a mistake in a program with -gdb. This is our program (with a deliberate mistake):- - -<code> -#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; -} -</code> - -This program sets i to be 5 and passes it to a function bazz() which prints -out the number we gave it. -<p> -When we compile and run the program we get - -<tscreen><verb> - cc -g -o temp temp.c - ./temp - This is my program - anint = 4231 -</verb></tscreen> - -That wasn't what we expected! Time to see what's going on! - -<tscreen><verb> -Current directory is ~/tmp/ -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) break main # Skip the set-up code -Breakpoint 1 at 0x160f: file temp.c, line 9. # gdb puts breakpoint at main() -(gdb) run # Run as far as main() -Starting program: /home/james/tmp/temp # Program starts running - -Breakpoint 1, main () at temp.c:9 # gdb stops at main() -(gdb) n # Go to next line -This is my program # Program prints out "This .." -(gdb) s # step into bazz() -bazz (anint=4231) at temp.c:17 # gdb displays stack frame -</verb></tscreen> - -Hang on a minute! How did anint get to be 4231? Didn't we set it to be 5 -in main()? Let's move up to main() and have a look. - -<tscreen><verb> -(gdb) up # Move up call stack -#1 0x1625 in main () at temp.c:11 # gdb displays stack frame -(gdb) p i # Show us the value of i -$1 = 4231 # gdb displays 4231 -</verb></tscreen> - -Oh dear! Looking at the code, we forgot to initialise i. We meant to put - -<code> -... -main() { - int i; - - i = 5; - printf("This is my program\n"); -... -</code> - -but we missed the `i=5;' line out. As we didn't initialise i, it had -whatever number happened to be in that area of memory when the program -ran, which in this case happened to be 4231. -<p> -Note that gdb displays the stack frame every time we go into or out of -a function, even if we're using `up' and `down' 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). - -<sect1><heading>Examining a core file</heading> -<p> -A core file is basically a file which contains the complete state of -the process when it crashed. In ``the good old days'', 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 ``progname.core'' instead -of just core, to make it clearer which program a core file belongs to. -<p> -To examine a core file, start up gdb in the usual way. Instead of -typing `break' or `run', type - -<tscreen><verb> - core progname.core -</verb></tscreen> - -(if you're not in the same directory as the core file, you'll have to -do `dir /path/to/core/file' first). -<p> -You should see something like this:- - -<tscreen><verb> -Current directory is ~/tmp/ -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) core a.out.core -Core was generated by `a.out'. -Program terminated with signal 11, Segmentation fault. -Cannot access memory at address 0x7020796d. -#0 0x164a in foobar (some_arg=0x5) at temp.c:17 -</verb></tscreen> - -In this case, the program was called `a.out', so the core file is -called `a.out.core'. 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 `bazz'. -<p> -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 `bt' command causes gdb to print out a back-trace -of the call stack:- - -<tscreen><verb> -(gdb) bt -#0 0x164a in bazz (anint=0x5) at temp.c:17 -#1 0xefbfd888 in end () -#2 0x162c in main () at temp.c:11 -</verb></tscreen> - -The end() function is called when a program crashes; in this case, the -bazz() function was called from main(). - -<sect1><heading>Attaching to a running program</heading> -<p> -One of the neatest features about gdb 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. -<p> -What you do is start up another gdb, use `ps' to find the process ID -for the child, and do - -<tscreen><verb> - attach <pid> -</verb></tscreen> - -in gdb, and then debug as usual. -<p> -``That's all very well,'' you're probably thinking, ``but by the time -I've done that, the child process will be over the hill and far -away''. Fear not, gentle reader, here's how to do it (courtesy of the -gdb info pages):- - -<tscreen><verb> -... -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 */ - ... -} else { /* parent */ - ... -</verb></tscreen> - -Now all you have to do is attach to the child, set PauseMode to 0, and -wait for the sleep() call to return! - -<sect><heading>Using Emacs as a Development Environment</heading> -<p> -<sect1><heading>Emacs</heading> -<p> -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 (at least, -not unless you pay out very large sums of money). 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. -<p> -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. -<p> -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). -<p> -It's impossible even to summarise everything Emacs can do here, but -here are some of the features of interest to developers:- - -<itemize> -<item> Very powerful editor, allowing search-and-replace on both - strings and regular expressions (patterns), jumping to start/end of - block expression, etc, etc. - -<item> Pull-down menus and online help. - -<item> Language-dependent syntax highlighting and indentation. - -<item> Completely customisable. - -<item> You can compile and debug programs within Emacs. - -<item> On a compilation error, you can jump to the offending line of source - code. - -<item> Friendly-ish front-end to the `info' program used for reading GNU - hypertext documentation (including the documentation on Emacs). - -<item> Friendly front-end to GDB, allowing you to look at the source code - as you step through your program. - -<item> You can read Usenet news and mail while your program is compiling ;-) -</itemize> - -And doubtless many more that I've overlooked. -<p> -Emacs can be installed on FreeBSD using <htmlurl -url="ftp://ftp.freebsd.org:pub/FreeBSD/packages/editors/emacs" -name="the Emacs package">. -<p> -Once it's installed, start it up and do C-h t to read an Emacs -tutorial - that means hold down the control key, press `h', let go of -the control key, and then press t. (Alternatively, you can you use -the mouse to select ``Emacs Tutorial'' from the ``Help'' menu). -<p> -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 - -<tscreen><verb> - M-x replace-s RET foo RET bar RET -</verb></tscreen> - -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. -<p> -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). -<p> -If you can't remember what a particular combination of keys does, -select ``Describe Key'' from the ``Help'' menu and type it in - Emacs -will tell you what it does. You can also use the ``Command Apropos'' -menu item to find out all the commands which contain a particular word -in them, with the key binding next to it. -<p> -By the way, the expression above means hold down the Meta key, press -`x', release the Meta key, type replace-s (short for ``replace-string'' -- another feature of Emacs is that you can abbreviate commands), press -the return key, type foo (the string you want replaced), press the -return key, type bar (the string you want to replace ``foo'' with) and -press return again. Emacs will then do the search-and-replace -operation you've just requested. -<p> -If you're wondering what on earth the Meta key is, it's a special key -that many Unix workstations have. Unfortunately, PC's don't have one, -so it's usually the ``alt'' key (or if you're unlucky, the ``escape'' -key). -<p> -Oh, and to get out of Emacs, do C-c C-x (that means hold down the -control key, press `c', press `x' and release the control 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 C-z 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). - -<sect1><heading>Configuring Emacs</heading> -<p> -Emacs does many wonderful things, some of them are built in, some of -them need to be configured. -<p> -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!). -<p> -The best way to learn Emacs Lisp is to download the <htmlurl -url="ftp://prep.ai.mit.edu:pub/gnu/elisp-manual-19-2.4.tar.gz" -name="Emacs Tutorial"> -<p> -However, there's no need to actually know any Lisp to get started with -configuring Emacs, as I've included a sample ``.emacs'' 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. - -<sect1><heading>A sample .emacs file</heading> -<p> -Unfortunately, there's far too much here to explain it in detail; -however there are one or two points worth mentioning. - -<itemize> -<item> Everything beginning with a `;' is a comment and is ignored by Emacs. - -<item> In the first line, the -*- Emacs-Lisp -*- is so that we can edit -the .emacs 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 .emacs). - -<item> The `tab' 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 tab character in whatever you're writing, -hold the control key down while you're pressing the tab key. - -<item> This file supports syntax highlighting for C, C++, Perl, Lisp and -Scheme (by guessing the language from the filename). - -<item> Emacs already has a pre-defined function called ``next-error''. -In a compilation output window, this allows you to move from one -compilation error to the next by doing M-n; we define a complementary -function, ``previous-error'', that allows you to go to a previous -error by doing M-p. The nicest feature of all is that C-c C-c will -open up the source file in which the error occurred and jump to the -appropriate line. - -<item> 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 -<tscreen><verb> - emacsclient <filename> -</verb></tscreen> - -and then you can edit the file in your Emacs! (Many Emacs users set -their EDITOR environment to `emacsclient' so this happens every time -they need to edit a file). -</itemize> - -<tscreen><verb> -;; -*-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") -</verb></tscreen> -<tscreen><verb> -(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))) -</verb></tscreen> -<tscreen><verb> -;; 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) ".") - -</verb></tscreen> - -<sect1><heading>Extending the Range of Languages Emacs Understands</heading> -<p> -Now, this is all very well if you only want to program in the -languages already catered for in the .emacs file (C, C++, Perl, Lisp -and Scheme), but what happens if a new language called "whizbang" -comes out, full of exciting features? -<p> -The first thing to do is find out if "whizbang" comes with any files -that tell Emacs about the language. These usually end in ".el", short -for "Emacs Lisp". For example, if "whizbang" is a FreeBSD port, we can -locate these files by doing - -<tscreen><verb> - find /usr/ports/lang/whizbang -name *.el -print -</verb></tscreen> - -and install them by copying them into the Emacs site Lisp directory. On -FreeBSD 2.1.0-RELEASE, this is /usr/local/share/emacs/site-lisp. - -So for example, if the output from the find command was - -<tscreen><verb> - /usr/ports/lang/whizbang/work/misc/whizbang.el -</verb></tscreen> - -we would do - -<tscreen><verb> - cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp -</verb></tscreen> - -Next, we need to decide what extension whizbang source files -have. Let's say for the sake of argument that they all end in -`.wiz'. We need to add an entry to our .emacs file to make sure Emacs -will be able to use the information in whizbang.el. -<p> -Find the auto-mode-alist entry in .emacs and add a line for whizbang, -such as:- - -<tscreen><verb> - ... - ("\\.lsp$" . lisp-mode) - ("\\.wiz$" . whizbang-mode) - ("\\.scm$" . scheme-mode) - ... -</verb></tscreen> - -This means that Emacs will automatically go into whizbang-mode when -you edit a file ending in .wiz. -<p> -Just below this, you'll find the font-lock-auto-mode-list entry. Add -whizbang-mode to it like so:- - -<tscreen><verb> -;; 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") -</verb></tscreen> - -This means that Emacs will always enable font-lock-mode (ie syntax -highlighting) when editing a .wiz file. -<p> -And that's all that's needed. If there's anything else you want done -automatically when you open up a .wiz file, you can add a -whizbang-mode hook (see my-scheme-mode-hook for a simple example that -adds auto-indent). - -<sect><heading>Further Reading</heading> -<sect1><heading>Bibliography</heading> -<p> -<itemize> -<item> -Brian Harvey and Matthew Wright -<em>Simply Scheme</em> -MIT 1994. -<newline>ISBN 0-262-08226-8 -</item> - -<item> -Randall Schwartz -<em>Learning Perl</em> -O'Reilly 1993 -<newline>ISBN 1-56592-042-2 -</item> - -<item> -Patrick Henry Winston and Berthold Klaus Paul Horn -<em>Lisp (3rd Edition)</em> -Addison-Wesley 1989 -<newline>ISBN 0-201-08319-1 -</item> - -<item> -Brian W. Kernighan and Rob Pike -<em>The Unix Programming Environment</em> -Prentice-Hall 1984 -<newline>ISBN 0-13-937681-X -</item> - -<item> -Brian W. Kernighan and Dennis M. Ritchie -<em>The C Programming Language (2nd Edition)</em> -Prentice-Hall 1988 -<newline>ISBN 0-13-110362-8 -</item> - -<item> -Bjarne Stroustrup -<em>The C++ Programming Language</em> -Addison-Wesley 1991 -<newline>ISBN 0-201-53992-6 -</item> - -<item> -W. Richard Stevens -<em>Advanced Programming in the Unix Environment</em> -Addison-Wesley 1992 -<newline>ISBN 0-201-56317-7 -</item> - -<item> -W. Richard Stevens -<em>Unix Network Programming</em> -Prentice-Hall 1990 -<newline>ISBN 0-13-949876-1 -</item> -</itemize> -</article> diff --git a/en/tutorials/index.sgml b/en/tutorials/index.sgml index ebbc838f65..0f785a2caf 100644 --- a/en/tutorials/index.sgml +++ b/en/tutorials/index.sgml @@ -1,6 +1,6 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN" [ <!ENTITY base CDATA ".."> -<!ENTITY date "$Date: 1997-01-18 02:24:07 $"> +<!ENTITY date "$Date: 1997-01-19 15:29:57 $"> <!ENTITY title "FreeBSD Tutorials"> <!ENTITY % includes SYSTEM "../includes.sgml"> %includes; ]> @@ -19,9 +19,8 @@ (<a href="mh/mh.ps">postscript</a>, <a href="mh/mh-html.tar.gz">gzipd tar file</a>)</li> - <li><a href="devel/devel.html">A User's Guide to FreeBSD Programming Tools</a> - (<a href="devel/devel.ps">postscript</a>, - <a href="devel/devel-html.tar.gz">gzipd tar file</a>)</li> + <li><a href="devel/devel.html">A User's Guide to FreeBSD Programming + Tools</a></li> <li><a href="ddwg/ddwg.html">Writing device drivers for FreeBSD</a> (<a href="ddwg/ddwg.ps">postscript</a>, diff --git a/en_US.ISO8859-1/articles/programming-tools/Makefile b/en_US.ISO8859-1/articles/programming-tools/Makefile index 6cc882035c..9429f7790d 100644 --- a/en_US.ISO8859-1/articles/programming-tools/Makefile +++ b/en_US.ISO8859-1/articles/programming-tools/Makefile @@ -1,5 +1,5 @@ -DOC= devel -SRCS= devel.sgml +DOCS= devel.docb +INDEXLINK= devel.html -.include <bsd.sgml.mk> +.include "../../web.mk" diff --git a/en_US.ISO8859-1/articles/programming-tools/article.sgml b/en_US.ISO8859-1/articles/programming-tools/article.sgml new file mode 100644 index 0000000000..524d8730f3 --- /dev/null +++ b/en_US.ISO8859-1/articles/programming-tools/article.sgml @@ -0,0 +1,1835 @@ +<!-- $FreeBSD$ --> +<!-- The FreeBSD Documentation Project --> + +<!DOCTYPE BOOK PUBLIC "-//Davenport//DTD DocBook V3.0//EN"> +<book> +<bookinfo> +<bookbiblio> +<title>A User's Guide to FreeBSD Programming Tools</title> + +<authorgroup> +<author> +<firstname>James</firstname> +<surname>Raynard</surname> +<affiliation> +<address> +<email>jraynard@freebsd.org</email> +</address> +</affiliation> +</author></authorgroup> + +<pubdate>January 19, 1997</pubdate> + +<copyright> +<year>1997</year> +<holder>James Raynard</holder> +</copyright> + +<abstract><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></abstract> +</bookbiblio> +</bookinfo> + +<chapter> +<title>Introduction<anchor id=foo></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</> and <command>awk</>. 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</> and +<acronym>ANSI</> 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> + +</chapter> + +<chapter> +<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</>, the other a +<firstterm>compiler</>. 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> + + + +<sect1> +<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>csh</>) is itself an interpreter, and many people do in fact +write shell <quote>scripts</quote> to help with various +<quote>housekeeping</> 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> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>pkg_add <replaceable>package name</></userinput></screen> +</para> + +<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> + +<para> +<variablelist> +<varlistentry><term><acronym>BASIC</></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</> has been the first programming language +for many programmers. It's also the foundation for <trademark>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</> +scripts.</para> + +<para>Version 4, which is probably still the most widely-used +version, comes with FreeBSD; the newer <ulink +URL="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/perl-5.001.tgz">Perl +Version 5</ulink> is available as a package.</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> +</para> + +</sect1> + +<sect1> +<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</> as such; however +it is possible to use Emacs for this purpose. This is discussed in +<xref linkend="emacs">.</para> + +</sect1> +</chapter> + +<chapter> +<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</> or <command>gcc</>. 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</> converts the source code into its own, +machine-independent <firstterm>p-code</> 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</> is often used to refer to just +steps 1 to 4—the others are referred to as +<firstterm>linking</>. Sometimes step 1 is referred to as +<firstterm>pre-processing</> and steps 3-4 as +<firstterm>assembling</>.</para> + +<para>Fortunately, almost all this detail is hidden from you, as +<command>cc</> is a front end that manages calling all these programs +with the right arguments for you; simply typing +<screen>$ <userinput>cc foobar.c</></screen></para> + +<para>will cause <filename>foobar.c</> to be compiled by all the +steps above. If you have more than one file to compile, just do +something like +<screen>$ <userinput>cc foo.c bar.c</></screen> +</para> + +<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</>, 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></></term> + +<listitem><para>The output name of the file. If you do not use this +option, <command>cc</> will produce an executable called +<filename>a.out</>.<footnote><para>The reasons for this are buried in +the mists of history.</para></footnote></para> + +<informalexample> +<screen>$ <userinput>cc foobar.c</> <lineannotation>executable is <filename>a.out</></> +$ <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>$ <userinput>cc -c foobar.c</userinput></screen> +</informalexample> + +<para>This will produce an <firstterm>object file</> (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>$ <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>$ <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</> 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</> 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>$ <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>$ <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>$ <userinput>cc -o foobar foobar.cc -lg++</userinput> <lineannotation>For FreeBSD 2.1.6 and earlier</> +$ <userinput>cc -o foobar foobar.cc -lstdc++</userinput> <lineannotation>For FreeBSD 2.2 and later</> +$ <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 <trademark>MS-DOS</trademark> 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> + +<sect1> +<title>Common <command>cc</command> Queries and Problems</title> + +<para>Q. 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? +<informalexample> +<screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment</screen> +</informalexample> +</para> + +<para>A. When using mathematical functions like +<function>sin()</function>, you have to tell <command>cc</command> to +link in the math library, like so: +<informalexample> +<screen>$ <userinput>cc -o foobar foobar.c -lm</userinput></screen> +</informalexample></para> + +<para>Q. 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. +<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> +and I compiled it as: +<informalexample> +<screen>$ <userinput>cc temp.c -lm</userinput></screen> +</informalexample> +like you said I should, but I get this when I run it: +<informalexample> +<screen>$ <userinput>./a.out</userinput> +2.1 ^ 6 = 1023.000000</screen> +</informalexample> +</para> + +<para>This is <emphasis>not</emphasis> the right answer! What is +going on?</para> + +<para>A. 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> + +<para>Q. So how do I fix this?</para> + +<para>A. 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! +<informalexample> +<programlisting>#include <math.h> +#include <stdio.h> + +int main() { +...</programlisting> +</informalexample> +</para> + +<para>After recompiling it as you did before, run it: +<informalexample> +<screen>$ <userinput>./a.out</userinput> +2.1 ^ 6 = 85.766121</screen> +</informalexample> +</para> + +<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> + +<para>Q. I compiled a file called <filename>foobar.c</filename> and I +cannot find an executable called <filename>foobar</filename>. Where's +it gone?</para> + +<para>A. 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: +<informalexample> +<screen>$ <userinput>cc -o foobar foobar.c</userinput></screen> +</informalexample> +</para> + +<para>Q. 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> + +<para>A. Unlike <trademark>MS-DOS</trademark>, 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 +<informalexample> +<screen>bin:/usr/bin:/usr/local/bin:.</screen> +</informalexample> +The dot at the end means <quote>look in the current directory if it is not in +any of the others</quote>.</para> + +<para>Q. I called my executable <filename>test</filename>, but +nothing happens when I run it. What is going on?</para> + +<para>A. 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: +<informalexample> +<screen>$ <userinput>./test</userinput></screen> +</informalexample> +or choose a better name for your program!</para> + +<para>Q. 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> + +<para>A. 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> + +<para>Q. Fascinating stuff, but what I am supposed to do now?</para> + +<para>A. Use <command>gdb</command> to analyse the core (see <xref +linkend="debugging">).</para> + +<para>Q. When my program dumped core, it said something about a +<errorname>segmentation fault</errorname>. What's that?</para> + +<para>A. 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: +<itemizedlist> +<listitem><para>Trying to write to a <symbol>NULL</symbol> pointer, eg +<programlisting>char *foo = NULL; +strcpy(foo, "bang!");</programlisting> +</para></listitem> + +<listitem><para>Using a pointer that hasn't been initialised, eg +<programlisting>char *foo; +strcpy(foo, "bang!");</programlisting> +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 +<programlisting>int bar[20]; +bar[27] = 6;</programlisting></para></listitem> + +<listitem><para> Trying to store something in read-only memory, eg +<programlisting>char *foo = "My string"; +strcpy(foo, "bang!");</programlisting> +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 +<programlisting>char bar[80]; +free(bar);</programlisting> +or +<programlisting>char *foo = malloc(27); +free(foo); +free(foo);</programlisting> +</para></listitem> + +</itemizedlist></para> + +<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> + +<para>Q. 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> + +<para>A. 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> + +<para>Q. 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> + +<para>A. Yes, just go to another console or xterm, do +<screen>$ <userinput>ps</userinput></screen> +to find out the process ID of your program, and do +<screen>$ <userinput>kill -ABRT <replaceable>pid</replaceable></userinput></screen> +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> + +</sect1> +</chapter> + + +<chapter> +<title>Make</title> + +<sect1> +<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 +<screen>$ <userinput>cc file1.c file2.c</userinput></screen> +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: +<screen>$ <userinput>cc file1.o file2.o</userinput> … <userinput>file37.c</userinput> &hellip</screen> +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> + +</sect1> + +<sect1> +<title>Example of using <command>make</command></title> + +<para>Here's a very simple make file: +<programlisting>foo: foo.c + cc -o foo foo.c</programlisting> +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: +<programlisting>foo: foo.c + cc -o foo foo.c + +install: + cp foo /home/me</programlisting></para> + +<para>We can tell make which target we want to make by typing: +<screen>$ <userinput>make <replaceable>target</replaceable></userinput></screen> +<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> + +</sect1> + +<sect1> +<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>: +<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> + +<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> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>zmore paper.ascii.gz</userinput></screen> +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 +<programlisting> * Make: (make). The GNU Make utility.</programlisting> +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> + +</sect1> +</chapter> + +<chapter id="debugging"> +<title>Debugging</title> + +<sect1> +<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 +<screen>$ <userinput>gdb <replaceable>progname</replaceable></userinput></screen> +although most people prefer to run it inside +<application>Emacs</application>. You can do this by: +<screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput></screen></para> + +<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="http://www.freebsd.org/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> + +</sect1> + +<sect1> +<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: +<screen>… (no debugging symbols found) …</screen>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): +<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> + +<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 +<screen>$ <userinput>cc -g -o temp temp.c</userinput> +$ <userinput>./temp</userinput> +This is my program +anint = 4231</screen></para> + +<para>That wasn't what we expected! Time to see what's going +on!<screen>$ <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> + + +<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> + +<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> +Oh dear! Looking at the code, we forgot to initialise +<symbol>i</symbol>. We meant to put +<programlisting><lineannotation>…</> +main() { + int i; + + i = 5; + printf("This is my program\n"); +<lineannotation>&hellip</></programlisting> +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> + +</sect1> + +<sect1> +<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</>.core</> 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 +<screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput></screen> +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: +<screen>$ <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> + +<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: +<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>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> + +</sect1> + +<sect1> +<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<screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput></screen> +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): +<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> +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> + +</sect1> +</chapter> + +<chapter id="emacs"> +<title>Using Emacs as a Development Environment</title> + +<sect1> +<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: +<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>And doubtless many more that I've overlooked.</para> + +<para>Emacs can be installed on FreeBSD using <ulink +URL="http://www.freebsd.org/ports/editors">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-c C-x</command> +(that means hold down the <keysym>control</keysym> key, press +<keysym>c</keysym>, press <keysym>x</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> + +</sect1> + +<sect1> +<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> + +</sect1> + +<sect1> +<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> + +<para> +<itemizedlist> + +<listitem><para>Everything beginning with a <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 +<screen>$ <userinput>emacsclient <replaceable>filename</replaceable></userinput></screen> +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> +</para> + +<example> +<title>A sample <filename>.emacs</filename> file</title> +<screen>;; -*-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") </screen> + +<screen>(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)))</screen> + +<screen>;; 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) ".") +</screen> +</example> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>find /usr/ports/lang/whizbang -name "*.el" -print</userinput></screen> +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 +<screen>/usr/ports/lang/whizbang/work/misc/whizbang.el</screen> +we would do +<screen>$ <userinput>cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp</userinput></screen> +</para> + +<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: +<programlisting><lineannotation>…</> +("\\.lsp$" . lisp-mode) +("\\.wiz$" . whizbang-mode) +("\\.scm$" . scheme-mode) +<lineannotation>…</></programlisting> +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: +<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> +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> + +</sect1> +</chapter> + +<chapter> +<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> + +</chapter> +</book> diff --git a/en_US.ISO_8859-1/articles/programming-tools/Makefile b/en_US.ISO_8859-1/articles/programming-tools/Makefile index 6cc882035c..9429f7790d 100644 --- a/en_US.ISO_8859-1/articles/programming-tools/Makefile +++ b/en_US.ISO_8859-1/articles/programming-tools/Makefile @@ -1,5 +1,5 @@ -DOC= devel -SRCS= devel.sgml +DOCS= devel.docb +INDEXLINK= devel.html -.include <bsd.sgml.mk> +.include "../../web.mk" diff --git a/en_US.ISO_8859-1/articles/programming-tools/article.sgml b/en_US.ISO_8859-1/articles/programming-tools/article.sgml new file mode 100644 index 0000000000..524d8730f3 --- /dev/null +++ b/en_US.ISO_8859-1/articles/programming-tools/article.sgml @@ -0,0 +1,1835 @@ +<!-- $FreeBSD$ --> +<!-- The FreeBSD Documentation Project --> + +<!DOCTYPE BOOK PUBLIC "-//Davenport//DTD DocBook V3.0//EN"> +<book> +<bookinfo> +<bookbiblio> +<title>A User's Guide to FreeBSD Programming Tools</title> + +<authorgroup> +<author> +<firstname>James</firstname> +<surname>Raynard</surname> +<affiliation> +<address> +<email>jraynard@freebsd.org</email> +</address> +</affiliation> +</author></authorgroup> + +<pubdate>January 19, 1997</pubdate> + +<copyright> +<year>1997</year> +<holder>James Raynard</holder> +</copyright> + +<abstract><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></abstract> +</bookbiblio> +</bookinfo> + +<chapter> +<title>Introduction<anchor id=foo></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</> and <command>awk</>. 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</> and +<acronym>ANSI</> 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> + +</chapter> + +<chapter> +<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</>, the other a +<firstterm>compiler</>. 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> + + + +<sect1> +<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>csh</>) is itself an interpreter, and many people do in fact +write shell <quote>scripts</quote> to help with various +<quote>housekeeping</> 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> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>pkg_add <replaceable>package name</></userinput></screen> +</para> + +<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> + +<para> +<variablelist> +<varlistentry><term><acronym>BASIC</></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</> has been the first programming language +for many programmers. It's also the foundation for <trademark>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</> +scripts.</para> + +<para>Version 4, which is probably still the most widely-used +version, comes with FreeBSD; the newer <ulink +URL="ftp://ftp.freebsd.org:pub/FreeBSD/packages/lang/perl-5.001.tgz">Perl +Version 5</ulink> is available as a package.</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> +</para> + +</sect1> + +<sect1> +<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</> as such; however +it is possible to use Emacs for this purpose. This is discussed in +<xref linkend="emacs">.</para> + +</sect1> +</chapter> + +<chapter> +<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</> or <command>gcc</>. 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</> converts the source code into its own, +machine-independent <firstterm>p-code</> 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</> is often used to refer to just +steps 1 to 4—the others are referred to as +<firstterm>linking</>. Sometimes step 1 is referred to as +<firstterm>pre-processing</> and steps 3-4 as +<firstterm>assembling</>.</para> + +<para>Fortunately, almost all this detail is hidden from you, as +<command>cc</> is a front end that manages calling all these programs +with the right arguments for you; simply typing +<screen>$ <userinput>cc foobar.c</></screen></para> + +<para>will cause <filename>foobar.c</> to be compiled by all the +steps above. If you have more than one file to compile, just do +something like +<screen>$ <userinput>cc foo.c bar.c</></screen> +</para> + +<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</>, 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></></term> + +<listitem><para>The output name of the file. If you do not use this +option, <command>cc</> will produce an executable called +<filename>a.out</>.<footnote><para>The reasons for this are buried in +the mists of history.</para></footnote></para> + +<informalexample> +<screen>$ <userinput>cc foobar.c</> <lineannotation>executable is <filename>a.out</></> +$ <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>$ <userinput>cc -c foobar.c</userinput></screen> +</informalexample> + +<para>This will produce an <firstterm>object file</> (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>$ <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>$ <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</> 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</> 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>$ <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>$ <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>$ <userinput>cc -o foobar foobar.cc -lg++</userinput> <lineannotation>For FreeBSD 2.1.6 and earlier</> +$ <userinput>cc -o foobar foobar.cc -lstdc++</userinput> <lineannotation>For FreeBSD 2.2 and later</> +$ <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 <trademark>MS-DOS</trademark> 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> + +<sect1> +<title>Common <command>cc</command> Queries and Problems</title> + +<para>Q. 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? +<informalexample> +<screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment</screen> +</informalexample> +</para> + +<para>A. When using mathematical functions like +<function>sin()</function>, you have to tell <command>cc</command> to +link in the math library, like so: +<informalexample> +<screen>$ <userinput>cc -o foobar foobar.c -lm</userinput></screen> +</informalexample></para> + +<para>Q. 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. +<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> +and I compiled it as: +<informalexample> +<screen>$ <userinput>cc temp.c -lm</userinput></screen> +</informalexample> +like you said I should, but I get this when I run it: +<informalexample> +<screen>$ <userinput>./a.out</userinput> +2.1 ^ 6 = 1023.000000</screen> +</informalexample> +</para> + +<para>This is <emphasis>not</emphasis> the right answer! What is +going on?</para> + +<para>A. 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> + +<para>Q. So how do I fix this?</para> + +<para>A. 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! +<informalexample> +<programlisting>#include <math.h> +#include <stdio.h> + +int main() { +...</programlisting> +</informalexample> +</para> + +<para>After recompiling it as you did before, run it: +<informalexample> +<screen>$ <userinput>./a.out</userinput> +2.1 ^ 6 = 85.766121</screen> +</informalexample> +</para> + +<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> + +<para>Q. I compiled a file called <filename>foobar.c</filename> and I +cannot find an executable called <filename>foobar</filename>. Where's +it gone?</para> + +<para>A. 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: +<informalexample> +<screen>$ <userinput>cc -o foobar foobar.c</userinput></screen> +</informalexample> +</para> + +<para>Q. 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> + +<para>A. Unlike <trademark>MS-DOS</trademark>, 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 +<informalexample> +<screen>bin:/usr/bin:/usr/local/bin:.</screen> +</informalexample> +The dot at the end means <quote>look in the current directory if it is not in +any of the others</quote>.</para> + +<para>Q. I called my executable <filename>test</filename>, but +nothing happens when I run it. What is going on?</para> + +<para>A. 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: +<informalexample> +<screen>$ <userinput>./test</userinput></screen> +</informalexample> +or choose a better name for your program!</para> + +<para>Q. 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> + +<para>A. 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> + +<para>Q. Fascinating stuff, but what I am supposed to do now?</para> + +<para>A. Use <command>gdb</command> to analyse the core (see <xref +linkend="debugging">).</para> + +<para>Q. When my program dumped core, it said something about a +<errorname>segmentation fault</errorname>. What's that?</para> + +<para>A. 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: +<itemizedlist> +<listitem><para>Trying to write to a <symbol>NULL</symbol> pointer, eg +<programlisting>char *foo = NULL; +strcpy(foo, "bang!");</programlisting> +</para></listitem> + +<listitem><para>Using a pointer that hasn't been initialised, eg +<programlisting>char *foo; +strcpy(foo, "bang!");</programlisting> +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 +<programlisting>int bar[20]; +bar[27] = 6;</programlisting></para></listitem> + +<listitem><para> Trying to store something in read-only memory, eg +<programlisting>char *foo = "My string"; +strcpy(foo, "bang!");</programlisting> +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 +<programlisting>char bar[80]; +free(bar);</programlisting> +or +<programlisting>char *foo = malloc(27); +free(foo); +free(foo);</programlisting> +</para></listitem> + +</itemizedlist></para> + +<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> + +<para>Q. 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> + +<para>A. 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> + +<para>Q. 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> + +<para>A. Yes, just go to another console or xterm, do +<screen>$ <userinput>ps</userinput></screen> +to find out the process ID of your program, and do +<screen>$ <userinput>kill -ABRT <replaceable>pid</replaceable></userinput></screen> +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> + +</sect1> +</chapter> + + +<chapter> +<title>Make</title> + +<sect1> +<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 +<screen>$ <userinput>cc file1.c file2.c</userinput></screen> +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: +<screen>$ <userinput>cc file1.o file2.o</userinput> … <userinput>file37.c</userinput> &hellip</screen> +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> + +</sect1> + +<sect1> +<title>Example of using <command>make</command></title> + +<para>Here's a very simple make file: +<programlisting>foo: foo.c + cc -o foo foo.c</programlisting> +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: +<programlisting>foo: foo.c + cc -o foo foo.c + +install: + cp foo /home/me</programlisting></para> + +<para>We can tell make which target we want to make by typing: +<screen>$ <userinput>make <replaceable>target</replaceable></userinput></screen> +<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> + +</sect1> + +<sect1> +<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>: +<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> + +<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> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>zmore paper.ascii.gz</userinput></screen> +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 +<programlisting> * Make: (make). The GNU Make utility.</programlisting> +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> + +</sect1> +</chapter> + +<chapter id="debugging"> +<title>Debugging</title> + +<sect1> +<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 +<screen>$ <userinput>gdb <replaceable>progname</replaceable></userinput></screen> +although most people prefer to run it inside +<application>Emacs</application>. You can do this by: +<screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput></screen></para> + +<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="http://www.freebsd.org/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> + +</sect1> + +<sect1> +<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: +<screen>… (no debugging symbols found) …</screen>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): +<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> + +<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 +<screen>$ <userinput>cc -g -o temp temp.c</userinput> +$ <userinput>./temp</userinput> +This is my program +anint = 4231</screen></para> + +<para>That wasn't what we expected! Time to see what's going +on!<screen>$ <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> + + +<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> + +<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> +Oh dear! Looking at the code, we forgot to initialise +<symbol>i</symbol>. We meant to put +<programlisting><lineannotation>…</> +main() { + int i; + + i = 5; + printf("This is my program\n"); +<lineannotation>&hellip</></programlisting> +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> + +</sect1> + +<sect1> +<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</>.core</> 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 +<screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput></screen> +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: +<screen>$ <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> + +<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: +<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>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> + +</sect1> + +<sect1> +<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<screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput></screen> +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): +<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> +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> + +</sect1> +</chapter> + +<chapter id="emacs"> +<title>Using Emacs as a Development Environment</title> + +<sect1> +<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: +<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>And doubtless many more that I've overlooked.</para> + +<para>Emacs can be installed on FreeBSD using <ulink +URL="http://www.freebsd.org/ports/editors">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-c C-x</command> +(that means hold down the <keysym>control</keysym> key, press +<keysym>c</keysym>, press <keysym>x</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> + +</sect1> + +<sect1> +<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> + +</sect1> + +<sect1> +<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> + +<para> +<itemizedlist> + +<listitem><para>Everything beginning with a <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 +<screen>$ <userinput>emacsclient <replaceable>filename</replaceable></userinput></screen> +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> +</para> + +<example> +<title>A sample <filename>.emacs</filename> file</title> +<screen>;; -*-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") </screen> + +<screen>(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)))</screen> + +<screen>;; 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) ".") +</screen> +</example> + +</sect1> + +<sect1> +<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 +<screen>$ <userinput>find /usr/ports/lang/whizbang -name "*.el" -print</userinput></screen> +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 +<screen>/usr/ports/lang/whizbang/work/misc/whizbang.el</screen> +we would do +<screen>$ <userinput>cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp</userinput></screen> +</para> + +<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: +<programlisting><lineannotation>…</> +("\\.lsp$" . lisp-mode) +("\\.wiz$" . whizbang-mode) +("\\.scm$" . scheme-mode) +<lineannotation>…</></programlisting> +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: +<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> +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> + +</sect1> +</chapter> + +<chapter> +<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> + +</chapter> +</book> diff --git a/en_US.ISO_8859-1/tutorials/Makefile b/en_US.ISO_8859-1/tutorials/Makefile index 40a10bc3f1..e414259fe1 100644 --- a/en_US.ISO_8859-1/tutorials/Makefile +++ b/en_US.ISO_8859-1/tutorials/Makefile @@ -1,5 +1,5 @@ DOCS= index.sgml -SUBDIR= disklessx newuser -DOCSUBDIR= ddwg devel fonts mh multios ppp +SUBDIR= devel disklessx newuser +DOCSUBDIR= ddwg fonts mh multios ppp .include "../web.mk" diff --git a/en_US.ISO_8859-1/tutorials/index.sgml b/en_US.ISO_8859-1/tutorials/index.sgml index ebbc838f65..0f785a2caf 100644 --- a/en_US.ISO_8859-1/tutorials/index.sgml +++ b/en_US.ISO_8859-1/tutorials/index.sgml @@ -1,6 +1,6 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN" [ <!ENTITY base CDATA ".."> -<!ENTITY date "$Date: 1997-01-18 02:24:07 $"> +<!ENTITY date "$Date: 1997-01-19 15:29:57 $"> <!ENTITY title "FreeBSD Tutorials"> <!ENTITY % includes SYSTEM "../includes.sgml"> %includes; ]> @@ -19,9 +19,8 @@ (<a href="mh/mh.ps">postscript</a>, <a href="mh/mh-html.tar.gz">gzipd tar file</a>)</li> - <li><a href="devel/devel.html">A User's Guide to FreeBSD Programming Tools</a> - (<a href="devel/devel.ps">postscript</a>, - <a href="devel/devel-html.tar.gz">gzipd tar file</a>)</li> + <li><a href="devel/devel.html">A User's Guide to FreeBSD Programming + Tools</a></li> <li><a href="ddwg/ddwg.html">Writing device drivers for FreeBSD</a> (<a href="ddwg/ddwg.ps">postscript</a>,