diff --git a/en_US.ISO8859-1/books/arch-handbook/book.sgml b/en_US.ISO8859-1/books/arch-handbook/book.sgml index 8aacd1d42a..bd58d4a25a 100644 --- a/en_US.ISO8859-1/books/arch-handbook/book.sgml +++ b/en_US.ISO8859-1/books/arch-handbook/book.sgml @@ -1,7 +1,7 @@ Basics - - Compilation + + Programming Tools - This will include things like: compilation, makefiles, .mk - files, basic debugging, linking, secure programming - guidelines, style(9), CVS, diff, patch, etc. + This chapter was written by James Raynard. + Modifications for the Developer's Handbook by Murray Stokely. + + + Synopsis + + 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 + 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 + + + + Introduction + + 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 is not 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. + + 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. + + 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! + + + + + Introduction to Programming + + 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 are 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. + + + Interpreters + + 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. + + 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. + + 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 (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. + + + + Interpreters available with FreeBSD + + Here is a list of interpreters that are available as + FreeBSD + packages, with a brief discussion of some of the + more popular interpreted languages. + + To get one of these packages, all you need to do is to + click on the hotlink for the package, then run + + &prompt.root; pkg_add package name + + + as root. Obviously, you will need to have a fully + functional FreeBSD 2.1.0 or later system for the package to + work! + + + + BASIC + + + 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 Bywater + Basic Interpreter and the Phil + Cockroft's Basic Interpreter (formerly Rabbit + Basic) are available as FreeBSD FreeBSD + packages + + + + + Lisp + + + 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 GNU + Common Lisp available as a package. + + + + + Perl + + + Very popular with system administrators for writing + scripts; also often used on World Wide Web servers for + writing CGI scripts. + + The latest version (version 5) comes with FreeBSD. + + + + + Scheme + + + 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. + + FreeBSD has packages of the Elk + Scheme Interpreter, the MIT + Scheme Interpreter and the SCM + Scheme Interpreter. + + + + + Icon + + + The + Icon Programming Language. + + + + + Logo + + + Brian + Harvey's LOGO Interpreter. + + + + + Python + + + The + Python Object-Oriented Programming + Language + + + + + + + Compilers + + 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. + + + If you run it in the shell, you may get a core + dump. + + + 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. + + 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. + + 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 does not have an + IDE as such; however it is possible to use Emacs + for this purpose. This is discussed in . + + + + + + + + Compiling with <command>cc</command> + + 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. + + 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. + + + + Pre-process your source code to remove comments and do + other tricks like expanding macros in C. + + + + Check the syntax of your code to see if you have obeyed + the rules of the language. If you have not, it will + complain! + + + + Convert the source code into assembly + language—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 assembly language at + this stage. + + + + + Convert the assembly language into machine + code—yep, we are talking bits and bytes, ones and + zeros here. + + + + 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. + + + + If you are trying to produce an executable from several + source code files, work out how to fit them all + together. + + + + Work out how to produce something that the system's + run-time loader will be able to load into memory and + run. + + + + Finally, write the executable on the file system. + + + + 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. + + 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 + + &prompt.user; cc foobar.c + + + 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 + + &prompt.user; cc foo.c bar.c + + + 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. + + + In case you didn't know, a binary sort is an efficient + way of sorting things into order and a bubble sort + isn't. + + + 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. + + + + + + + The output name of the file. If you do not use this + option, cc will produce an executable called + a.out. + + + The reasons for this are buried in the mists of + history. + + + + &prompt.user; cc foobar.c executable is a.out +&prompt.user; cc -o foobar foobar.c executable is foobar + + + + + + + + + + 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 Makefile. + + + &prompt.user; cc -c foobar.c + + + + This will produce an object file (not an + executable) called foobar.o. This + can be linked together with other object files into an + executable. + + + + + + + + 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 + very useful; the disadvantage is that + all this extra information makes the program much bigger. + Normally, you compile with while you + are developing a program and then compile a release + version without when you're + satisfied it works properly. + + + &prompt.user; cc -g foobar.c + + + + This will produce a debug version of the + program. + + + Note, we didn't use the flag + to specify the executable name, so we will get an + executable called a.out. + Producing a debug version called + foobar is left as an exercise for + the reader! + + + + + + + + + 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 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 + option in some circumstances. + + Optimisation is usually only turned on when compiling + a release version. + + + &prompt.user; cc -O -o foobar foobar.c + + + + This will produce an optimised version of + foobar. + + + + + 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 is an + ISO standard. + + + + + + + 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. + + + + + + + + Turn off most, but not all, of the + non-ANSI C features provided by + cc. Despite the name, it does not + guarantee strictly that your code will comply to the + standard. + + + + + + + + Turn off all + cc's non-ANSI C + features. + + + + + 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. + + 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? + + + &prompt.user; cc -Wall -ansi -pedantic -o foobar foobar.c + + + + This will produce an executable foobar + after checking foobar.c for standard + compliance. + + + + + + + Specify a function library to be used during when + linking. + + 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. + + The rule is that if the library is called + libsomething.a, + you give cc the argument + . + For example, the math library is + libm.a, so you give + cc the argument . + A common gotcha with the math library is + that it has to be the last library on the command + line. + + + &prompt.user; cc -o foobar foobar.c -lm + + + + This will link the math library functions into + foobar. + + If you are compiling C++ code, you need to add + , or if + you are using FreeBSD 2.2 or later, to the command line + argument to link the C++ library functions. + Alternatively, you can run c++ instead + of cc, which does this for you. + c++ can also be invoked as + g++ on FreeBSD. + + + &prompt.user; cc -o foobar foobar.cc -lg++ For FreeBSD 2.1.6 and earlier +&prompt.user; cc -o foobar foobar.cc -lstdc++ For FreeBSD 2.2 and later +&prompt.user; c++ -o foobar foobar.cc + + + + Each of these 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 + MS-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! + + + + + + Common <command>cc</command> Queries and Problems + + + + + I am trying to write a program which uses the + sin() function and I get an error + like this. What does it mean? + + + /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment + + + + + + When using mathematical functions like + sin(), you have to tell + cc to link in the math library, like + so: + + + &prompt.user; cc -o foobar foobar.c -lm + + + + + + + + All right, I wrote this simple program to practice + using . All it does is raise 2.1 to + the power of 6. + + + #include <stdio.h> + +int main() { + float f; + + f = pow(2.1, 6); + printf("2.1 ^ 6 = %f\n", f); + return 0; +} + + + + and I compiled it as: + + + &prompt.user; cc temp.c -lm + + + + like you said I should, but I get this when I run + it: + + + &prompt.user; ./a.out +2.1 ^ 6 = 1023.000000 + + + + This is not the right answer! + What is going on? + + + + 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 + int, which is definitely not what you want + here. + + + + + + So how do I fix this? + + + + 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 + will stop doing strange things to your + calculation! + + + #include <math.h> +#include <stdio.h> + +int main() { +... + + + + After recompiling it as you did before, run + it: + + + &prompt.user; ./a.out +2.1 ^ 6 = 85.766121 + + + + If you are using any of the mathematical functions, + always include + math.h and remember to link in the + math library. + + + + + + I compiled a file called + foobar.c and I cannot find an + executable called foobar. Where's + it gone? + + + + Remember, cc will call the + executable a.out unless you tell it + differently. Use the + + option: + + + &prompt.user; cc -o foobar foobar.c + + + + + + + + OK, I have an executable called + foobar, I can see it when I run + ls, but when I type in + foobar at the command prompt it tells + me there is no such file. Why can it not find + it? + + + + Unlike MS-DOS, Unix does not + look in the current directory when it is trying to find + out which executable you want it to run, unless you tell + it to. Either type ./foobar, which + means run the file called + foobar in the current + directory, or change your PATH environment + variable so that it looks something like + + + bin:/usr/bin:/usr/local/bin:. + + + + The dot at the end means look in the current + directory if it is not in any of the + others. + + + + + + I called my executable test, + but nothing happens when I run it. What is going + on? + + + + Most Unix systems have a program called + test in /usr/bin + and the shell is picking that one up before it gets to + checking the current directory. Either type: + + + &prompt.user; ./test + + + + or choose a better name for your program! + + + + + + 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? + + + + 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. + + + + + + Fascinating stuff, but what I am supposed to do + now? + + + + Use gdb to analyse the core (see + ). + + + + + + When my program dumped core, it said something about + a segmentation fault. What's + that? + + + + 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. + + Common causes for this are: + + + + Trying to write to a NULL + pointer, eg + + char *foo = NULL; +strcpy(foo, "bang!"); + + + + + Using a pointer that hasn't been initialised, + eg + + char *foo; +strcpy(foo, "bang!"); + + + 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. + + + + Trying to access past the end of an array, + eg + + int bar[20]; +bar[27] = 6; + + + + + Trying to store something in read-only memory, + eg + + char *foo = "My string"; +strcpy(foo, "bang!"); + + + Unix compilers often put string literals like + "My string" into read-only areas + of memory. + + + + Doing naughty things with + malloc() and + free(), eg + + char bar[80]; +free(bar); + + + or + + char *foo = malloc(27); +free(foo); +free(foo); + + + + + 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. + + + + + + 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? + + + + 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. + + + + + + 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? + + + + Yes, just go to another console or xterm, do + + &prompt.user; ps + + + to find out the process ID of your program, and + do + + &prompt.user; kill -ABRT pid + + + where + pid is + the process ID you looked up. + + This is useful if your program has got stuck in an + infinite loop, for instance. If your program happens to + trap SIGABRT, there are several other + signals which have a similar effect. + + + + + + + + Make + + + What is <command>make</command>? + + When you're working on a simple program with only one or + two source files, typing in + + &prompt.user; cc file1.c file2.c + + + is not too bad, but it quickly becomes very tedious when + there are several files—and it can take a while to + compile, too. + + 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: + + &prompt.user; cc file1.o file2.ofile37.c &hellip + + + if we'd changed file37.c, 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. + + 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. + + 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? + + 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. + + This program is called make. It reads + in a file, called a makefile, 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 makefile also has rules telling + make how to re-compile the source file, + making it a much more powerful tool. + + Makefiles 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. + + + + + Example of using <command>make</command> + + Here's a very simple make file: + + foo: foo.c + cc -o foo foo.c + + + It consists of two lines, a dependency line and a creation + line. + + The dependency line here consists of the name of the + program (known as the target), followed + by a colon, then whitespace, 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. + + 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. + + 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! + + 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: + + foo: foo.c + cc -o foo foo.c + +install: + cp foo /home/me + + + We can tell make which target we want to make by + typing: + + &prompt.user; make target + + + make will then only look at that target + and ignore any others. For example, if we type + make foo with the makefile above, make + will ignore the install target. + + 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. + + 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 makefiles, + so that the application can be installed in the correct + directory when it has been correctly compiled. + + 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. + + + + FreeBSD Makefiles + + 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 Makefile: + + MASTER_SITES= ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/ +DISTFILES= scheme-microcode+dist-7.3-freebsd.tgz + +.include <bsd.port.mk> + + + Now, if we go to the directory for this port and type + make, the following happens: + + + + A check is made to see if the source code for this + port is already on the system. + + + + If it isn't, an FTP connection to the URL in + MASTER_SITES is set up to download the + source. + + + + 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. + + + + Any changes required to make the source work on + FreeBSD are applied—this is known as + patching. + + + + 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). + + + + 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. + + + + 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. + + + + Now I think you'll agree that's rather impressive for a + four line script! + + The secret lies in the last line, which tells + make to look in the system makefile 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 makefile that tells + make 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! + + If you want to have a look at these system makefiles, + they're in /usr/share/mk, 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!) + + + + More advanced uses of <command>make</command> + + 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. + + 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 + + &prompt.user; zmore paper.ascii.gz + + + in that directory. + + 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 its own right. + + 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 + + * Make: (make). The GNU Make utility. + + + 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). + + + + + Debugging + + + The Debugger + + The debugger that comes with FreeBSD is called + gdb (GNU + debugger). You start it up by typing + + &prompt.user; gdb progname + + + although most people prefer to run it inside + Emacs. You can do this by: + + M-x gdb RET progname RET + + + 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. + + 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. + + Finally, if you find its text-based command-prompt style + off-putting, there's a graphical front-end for it xxgdb in the ports + collection. + + This section is intended to be an introduction to using + gdb and does not cover specialised topics + such as debugging the kernel. + + + + Running a program in the debugger + + You'll need to have compiled the program with the + 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: + + … (no debugging symbols found) … + + + when gdb starts up, you'll know that + the program wasn't compiled with the + option. + + 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!). + + 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. + + Here's a simple example of how to spot a mistake in a + program with gdb. This is our program + (with a deliberate mistake): + + #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; +} + + + This program sets i to be + 5 and passes it to a function + bazz() which prints out the number we + gave it. + + When we compile and run the program we get + + &prompt.user; cc -g -o temp temp.c +&prompt.user; ./temp +This is my program +anint = 4231 + + + That wasn't what we expected! Time to see what's going + on! + + &prompt.user; gdb temp +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 +(gdb) s step into bazz() +bazz (anint=4231) at temp.c:17 gdb displays stack frame +(gdb) + + + 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. + + (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 + + + Oh dear! Looking at the code, we forgot to initialise + i. We meant to put + + … +main() { + int i; + + i = 5; + printf("This is my program\n"); +&hellip + + + but we left 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. + + + 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). + + + + + Examining a core file + + 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. + + To examine a core file, start up gdb in + the usual way. Instead of typing break or + run, type + + (gdb) core progname.core + + + If you're not in the same directory as the core file, + you'll have to do dir + /path/to/core/file first. + + You should see something like this: + + &prompt.user; gdb a.out +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 bazz (anint=0x5) at temp.c:17 +(gdb) + + + 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. + + 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: + + (gdb) bt +#0 0x164a in bazz (anint=0x5) at temp.c:17 +#1 0xefbfd888 in end () +#2 0x162c in main () at temp.c:11 +(gdb) + + + The end() function is called when a + program crashes; in this case, the bazz() + function was called from main(). + + + + Attaching to a running program + + 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. + + What you do is start up another gdb, + use ps to find the process ID for the + child, and do + + (gdb) attach pid + + + in gdb, and then debug as usual. + + 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): + + &hellip +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 */ + &hellip +} else { /* parent */ + &hellip + + + Now all you have to do is attach to the child, set + PauseMode to 0, and wait + for the sleep() call to return! + + + + + Using Emacs as a Development Environment + + + Emacs + + 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. + + 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. + + 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. + + It's impossible even to summarise everything Emacs can do + here, but here are some of the features of interest to + developers: + + + + Very powerful editor, allowing search-and-replace on + both strings and regular expressions (patterns), jumping + to start/end of block expression, etc, etc. + + + + Pull-down menus and online help. + + + + Language-dependent syntax highlighting and + indentation. + + + + Completely customisable. + + + + You can compile and debug programs within + Emacs. + + + + On a compilation error, you can jump to the offending + line of source code. + + + + Friendly-ish front-end to the info + program used for reading GNU hypertext documentation, + including the documentation on Emacs itself. + + + + Friendly front-end to gdb, allowing + you to look at the source code as you step through your + program. + + + + You can read Usenet news and mail while your program + is compiling. + + + + And doubtless many more that I've overlooked. + + Emacs can be installed on FreeBSD using the Emacs + port. + + 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). + + 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 M-x + replace-s RET foo RET bar RET 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. + + 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. + + 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. + + 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. + + 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). + + Oh, and to get out of Emacs, do C-x C-c + (that means hold down the control key, press + x, press c 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). + + + + Configuring Emacs + + Emacs does many wonderful things; some of them are built + in, some of them need to be configured. + + 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!). + + The best way to learn Emacs Lisp is to download the Emacs + Tutorial + + 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. + + + + A sample <filename>.emacs</filename> file + + Unfortunately, there's far too much here to explain it in + detail; however there are one or two points worth + mentioning. + + + + Everything beginning with a ; is a comment + and is ignored by Emacs. + + + + 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. + + + + 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. + + + + This file supports syntax highlighting for C, C++, + Perl, Lisp and Scheme, by guessing the language from the + filename. + + + + 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. + + + + 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 + + &prompt.user; emacsclient filename + + + 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. + + + + + + A sample <filename>.emacs</filename> file + + ;; -*-Emacs-Lisp-*- + +;; This file is designed to be re-evaled; use the variable first-time +;; to avoid any problems with this. +(defvar first-time t + "Flag signifying this is the first time that .emacs has been evaled") + +;; Meta +(global-set-key "\M- " 'set-mark-command) +(global-set-key "\M-\C-h" 'backward-kill-word) +(global-set-key "\M-\C-r" 'query-replace) +(global-set-key "\M-r" 'replace-string) +(global-set-key "\M-g" 'goto-line) +(global-set-key "\M-h" 'help-command) + +;; Function keys +(global-set-key [f1] 'manual-entry) +(global-set-key [f2] 'info) +(global-set-key [f3] 'repeat-complex-command) +(global-set-key [f4] 'advertised-undo) +(global-set-key [f5] 'eval-current-buffer) +(global-set-key [f6] 'buffer-menu) +(global-set-key [f7] 'other-window) +(global-set-key [f8] 'find-file) +(global-set-key [f9] 'save-buffer) +(global-set-key [f10] 'next-error) +(global-set-key [f11] 'compile) +(global-set-key [f12] 'grep) +(global-set-key [C-f1] 'compile) +(global-set-key [C-f2] 'grep) +(global-set-key [C-f3] 'next-error) +(global-set-key [C-f4] 'previous-error) +(global-set-key [C-f5] 'display-faces) +(global-set-key [C-f8] 'dired) +(global-set-key [C-f10] 'kill-compilation) + +;; Keypad bindings +(global-set-key [up] "\C-p") +(global-set-key [down] "\C-n") +(global-set-key [left] "\C-b") +(global-set-key [right] "\C-f") +(global-set-key [home] "\C-a") +(global-set-key [end] "\C-e") +(global-set-key [prior] "\M-v") +(global-set-key [next] "\C-v") +(global-set-key [C-up] "\M-\C-b") +(global-set-key [C-down] "\M-\C-f") +(global-set-key [C-left] "\M-b") +(global-set-key [C-right] "\M-f") +(global-set-key [C-home] "\M-<") +(global-set-key [C-end] "\M->") +(global-set-key [C-prior] "\M-<") +(global-set-key [C-next] "\M->") + +;; Mouse +(global-set-key [mouse-3] 'imenu) + +;; Misc +(global-set-key [C-tab] "\C-q\t") ; Control tab quotes a tab. +(setq backup-by-copying-when-mismatch t) + +;; Treat 'y' or <CR> as yes, 'n' as no. +(fset 'yes-or-no-p 'y-or-n-p) + (define-key query-replace-map [return] 'act) + (define-key query-replace-map [?\C-m] 'act) + +;; Load packages +(require 'desktop) +(require 'tar-mode) + +;; Pretty diff mode +(autoload 'ediff-buffers "ediff" "Intelligent Emacs interface to diff" t) +(autoload 'ediff-files "ediff" "Intelligent Emacs interface to diff" t) +(autoload 'ediff-files-remote "ediff" + "Intelligent Emacs interface to diff") + +(if first-time + (setq auto-mode-alist + (append '(("\\.cpp$" . c++-mode) + ("\\.hpp$" . c++-mode) + ("\\.lsp$" . lisp-mode) + ("\\.scm$" . scheme-mode) + ("\\.pl$" . perl-mode) + ) auto-mode-alist))) + +;; Auto font lock mode +(defvar font-lock-auto-mode-list + (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode 'perl-mode 'scheme-mode) + "List of modes to always start in font-lock-mode") + +(defvar font-lock-mode-keyword-alist + '((c++-c-mode . c-font-lock-keywords) + (perl-mode . perl-font-lock-keywords)) + "Associations between modes and keywords") + +(defun font-lock-auto-mode-select () + "Automatically select font-lock-mode if the current major mode is +in font-lock-auto-mode-list" + (if (memq major-mode font-lock-auto-mode-list) + (progn + (font-lock-mode t)) + ) + ) + +(global-set-key [M-f1] 'font-lock-fontify-buffer) + +;; New dabbrev stuff +;(require 'new-dabbrev) +(setq dabbrev-always-check-other-buffers t) +(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_") +(add-hook 'emacs-lisp-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) nil) + (set (make-local-variable 'dabbrev-case-replace) nil))) +(add-hook 'c-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) nil) + (set (make-local-variable 'dabbrev-case-replace) nil))) +(add-hook 'text-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) t) + (set (make-local-variable 'dabbrev-case-replace) t))) + +;; C++ and C mode... +(defun my-c++-mode-hook () + (setq tab-width 4) + (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key c++-mode-map "\C-ce" 'c-comment-edit) + (setq c++-auto-hungry-initial-state 'none) + (setq c++-delete-function 'backward-delete-char) + (setq c++-tab-always-indent t) + (setq c-indent-level 4) + (setq c-continued-statement-offset 4) + (setq c++-empty-arglist-indent 4)) + +(defun my-c-mode-hook () + (setq tab-width 4) + (define-key c-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key c-mode-map "\C-ce" 'c-comment-edit) + (setq c-auto-hungry-initial-state 'none) + (setq c-delete-function 'backward-delete-char) + (setq c-tab-always-indent t) +;; BSD-ish indentation style + (setq c-indent-level 4) + (setq c-continued-statement-offset 4) + (setq c-brace-offset -4) + (setq c-argdecl-indent 0) + (setq c-label-offset -4)) + +;; Perl mode +(defun my-perl-mode-hook () + (setq tab-width 4) + (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent) + (setq perl-indent-level 4) + (setq perl-continued-statement-offset 4)) + +;; Scheme mode... +(defun my-scheme-mode-hook () + (define-key scheme-mode-map "\C-m" 'reindent-then-newline-and-indent)) + +;; Emacs-Lisp mode... +(defun my-lisp-mode-hook () + (define-key lisp-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key lisp-mode-map "\C-i" 'lisp-indent-line) + (define-key lisp-mode-map "\C-j" 'eval-print-last-sexp)) + +;; Add all of the hooks... +(add-hook 'c++-mode-hook 'my-c++-mode-hook) +(add-hook 'c-mode-hook 'my-c-mode-hook) +(add-hook 'scheme-mode-hook 'my-scheme-mode-hook) +(add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook) +(add-hook 'lisp-mode-hook 'my-lisp-mode-hook) +(add-hook 'perl-mode-hook 'my-perl-mode-hook) + +;; Complement to next-error +(defun previous-error (n) + "Visit previous compilation error message and corresponding source code." + (interactive "p") + (next-error (- n))) + +;; Misc... +(transient-mark-mode 1) +(setq mark-even-if-inactive t) +(setq visible-bell nil) +(setq next-line-add-newlines nil) +(setq compile-command "make") +(setq suggest-key-bindings nil) +(put 'eval-expression 'disabled nil) +(put 'narrow-to-region 'disabled nil) +(put 'set-goal-column 'disabled nil) + +;; Elisp archive searching +(autoload 'format-lisp-code-directory "lispdir" nil t) +(autoload 'lisp-dir-apropos "lispdir" nil t) +(autoload 'lisp-dir-retrieve "lispdir" nil t) +(autoload 'lisp-dir-verify "lispdir" nil t) + +;; Font lock mode +(defun my-make-face (face colour &optional bold) + "Create a face from a colour and optionally make it bold" + (make-face face) + (copy-face 'default face) + (set-face-foreground face colour) + (if bold (make-face-bold face)) + ) + +(if (eq window-system 'x) + (progn + (my-make-face 'blue "blue") + (my-make-face 'red "red") + (my-make-face 'green "dark green") + (setq font-lock-comment-face 'blue) + (setq font-lock-string-face 'bold) + (setq font-lock-type-face 'bold) + (setq font-lock-keyword-face 'bold) + (setq font-lock-function-name-face 'red) + (setq font-lock-doc-string-face 'green) + (add-hook 'find-file-hooks 'font-lock-auto-mode-select) + + (setq baud-rate 1000000) + (global-set-key "\C-cmm" 'menu-bar-mode) + (global-set-key "\C-cms" 'scroll-bar-mode) + (global-set-key [backspace] 'backward-delete-char) + ; (global-set-key [delete] 'delete-char) + (standard-display-european t) + (load-library "iso-transl"))) + +;; X11 or PC using direct screen writes +(if window-system + (progn + ;; (global-set-key [M-f1] 'hilit-repaint-command) + ;; (global-set-key [M-f2] [?\C-u M-f1]) + (setq hilit-mode-enable-list + '(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode + scheme-mode) + hilit-auto-highlight nil + hilit-auto-rehighlight 'visible + hilit-inhibit-hooks nil + hilit-inhibit-rebinding t) + (require 'hilit19) + (require 'paren)) + (setq baud-rate 2400) ; For slow serial connections + ) + +;; TTY type terminal +(if (and (not window-system) + (not (equal system-type 'ms-dos))) + (progn + (if first-time + (progn + (keyboard-translate ?\C-h ?\C-?) + (keyboard-translate ?\C-? ?\C-h))))) + +;; Under UNIX +(if (not (equal system-type 'ms-dos)) + (progn + (if first-time + (server-start)))) + +;; Add any face changes here +(add-hook 'term-setup-hook 'my-term-setup-hook) +(defun my-term-setup-hook () + (if (eq window-system 'pc) + (progn +;; (set-face-background 'default "red") + ))) + +;; Restore the "desktop" - do this as late as possible +(if first-time + (progn + (desktop-load-default) + (desktop-read))) + +;; Indicate that this file has been read at least once +(setq first-time nil) + +;; No need to debug anything now +(setq debug-on-error nil) + +;; All done +(message "All done, %s%s" (user-login-name) ".") + + + + + + Extending the Range of Languages Emacs Understands + + 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? + + 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 + + &prompt.user; find /usr/ports/lang/whizbang -name "*.el" -print + + + 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 + + /usr/ports/lang/whizbang/work/misc/whizbang.el + + + we would do + + &prompt.root; cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp + + + 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. + + Find the auto-mode-alist entry in + .emacs and add a line for whizbang, such + as: + + … +("\\.lsp$" . lisp-mode) +("\\.wiz$" . whizbang-mode) +("\\.scm$" . scheme-mode) +… + + + This means that Emacs will automatically go into + whizbang-mode when you edit a file ending + in .wiz. + + Just below this, you'll find the + font-lock-auto-mode-list entry. Add + whizbang-mode to it like so: + + ;; 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") + + + This means that Emacs will always enable + font-lock-mode (ie syntax highlighting) + when editing a .wiz file. + + 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). + + + + + Further Reading + + + + Brian Harvey and Matthew Wright + Simply Scheme + MIT 1994. + ISBN 0-262-08226-8 + + + + Randall Schwartz + Learning Perl + O'Reilly 1993 + ISBN 1-56592-042-2 + + + + Patrick Henry Winston and Berthold Klaus Paul Horn + Lisp (3rd Edition) + Addison-Wesley 1989 + ISBN 0-201-08319-1 + + + + Brian W. Kernighan and Rob Pike + The Unix Programming Environment + Prentice-Hall 1984 + ISBN 0-13-937681-X + + + + Brian W. Kernighan and Dennis M. Ritchie + The C Programming Language (2nd Edition) + Prentice-Hall 1988 + ISBN 0-13-110362-8 + + + + Bjarne Stroustrup + The C++ Programming Language + Addison-Wesley 1991 + ISBN 0-201-53992-6 + + + + W. Richard Stevens + Advanced Programming in the Unix Environment + Addison-Wesley 1992 + ISBN 0-201-56317-7 + + + + W. Richard Stevens + Unix Network Programming + Prentice-Hall 1990 + ISBN 0-13-949876-1 + + + - @@ -1357,7 +3598,7 @@ DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0); - + Debugging diff --git a/en_US.ISO8859-1/books/developers-handbook/book.sgml b/en_US.ISO8859-1/books/developers-handbook/book.sgml index 8aacd1d42a..bd58d4a25a 100644 --- a/en_US.ISO8859-1/books/developers-handbook/book.sgml +++ b/en_US.ISO8859-1/books/developers-handbook/book.sgml @@ -1,7 +1,7 @@ Basics - - Compilation + + Programming Tools - This will include things like: compilation, makefiles, .mk - files, basic debugging, linking, secure programming - guidelines, style(9), CVS, diff, patch, etc. + This chapter was written by James Raynard. + Modifications for the Developer's Handbook by Murray Stokely. + + + Synopsis + + 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 + 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 + + + + Introduction + + 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 is not 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. + + 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. + + 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! + + + + + Introduction to Programming + + 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 are 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. + + + Interpreters + + 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. + + 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. + + 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 (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. + + + + Interpreters available with FreeBSD + + Here is a list of interpreters that are available as + FreeBSD + packages, with a brief discussion of some of the + more popular interpreted languages. + + To get one of these packages, all you need to do is to + click on the hotlink for the package, then run + + &prompt.root; pkg_add package name + + + as root. Obviously, you will need to have a fully + functional FreeBSD 2.1.0 or later system for the package to + work! + + + + BASIC + + + 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 Bywater + Basic Interpreter and the Phil + Cockroft's Basic Interpreter (formerly Rabbit + Basic) are available as FreeBSD FreeBSD + packages + + + + + Lisp + + + 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 GNU + Common Lisp available as a package. + + + + + Perl + + + Very popular with system administrators for writing + scripts; also often used on World Wide Web servers for + writing CGI scripts. + + The latest version (version 5) comes with FreeBSD. + + + + + Scheme + + + 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. + + FreeBSD has packages of the Elk + Scheme Interpreter, the MIT + Scheme Interpreter and the SCM + Scheme Interpreter. + + + + + Icon + + + The + Icon Programming Language. + + + + + Logo + + + Brian + Harvey's LOGO Interpreter. + + + + + Python + + + The + Python Object-Oriented Programming + Language + + + + + + + Compilers + + 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. + + + If you run it in the shell, you may get a core + dump. + + + 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. + + 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. + + 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 does not have an + IDE as such; however it is possible to use Emacs + for this purpose. This is discussed in . + + + + + + + + Compiling with <command>cc</command> + + 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. + + 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. + + + + Pre-process your source code to remove comments and do + other tricks like expanding macros in C. + + + + Check the syntax of your code to see if you have obeyed + the rules of the language. If you have not, it will + complain! + + + + Convert the source code into assembly + language—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 assembly language at + this stage. + + + + + Convert the assembly language into machine + code—yep, we are talking bits and bytes, ones and + zeros here. + + + + 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. + + + + If you are trying to produce an executable from several + source code files, work out how to fit them all + together. + + + + Work out how to produce something that the system's + run-time loader will be able to load into memory and + run. + + + + Finally, write the executable on the file system. + + + + 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. + + 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 + + &prompt.user; cc foobar.c + + + 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 + + &prompt.user; cc foo.c bar.c + + + 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. + + + In case you didn't know, a binary sort is an efficient + way of sorting things into order and a bubble sort + isn't. + + + 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. + + + + + + + The output name of the file. If you do not use this + option, cc will produce an executable called + a.out. + + + The reasons for this are buried in the mists of + history. + + + + &prompt.user; cc foobar.c executable is a.out +&prompt.user; cc -o foobar foobar.c executable is foobar + + + + + + + + + + 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 Makefile. + + + &prompt.user; cc -c foobar.c + + + + This will produce an object file (not an + executable) called foobar.o. This + can be linked together with other object files into an + executable. + + + + + + + + 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 + very useful; the disadvantage is that + all this extra information makes the program much bigger. + Normally, you compile with while you + are developing a program and then compile a release + version without when you're + satisfied it works properly. + + + &prompt.user; cc -g foobar.c + + + + This will produce a debug version of the + program. + + + Note, we didn't use the flag + to specify the executable name, so we will get an + executable called a.out. + Producing a debug version called + foobar is left as an exercise for + the reader! + + + + + + + + + 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 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 + option in some circumstances. + + Optimisation is usually only turned on when compiling + a release version. + + + &prompt.user; cc -O -o foobar foobar.c + + + + This will produce an optimised version of + foobar. + + + + + 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 is an + ISO standard. + + + + + + + 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. + + + + + + + + Turn off most, but not all, of the + non-ANSI C features provided by + cc. Despite the name, it does not + guarantee strictly that your code will comply to the + standard. + + + + + + + + Turn off all + cc's non-ANSI C + features. + + + + + 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. + + 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? + + + &prompt.user; cc -Wall -ansi -pedantic -o foobar foobar.c + + + + This will produce an executable foobar + after checking foobar.c for standard + compliance. + + + + + + + Specify a function library to be used during when + linking. + + 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. + + The rule is that if the library is called + libsomething.a, + you give cc the argument + . + For example, the math library is + libm.a, so you give + cc the argument . + A common gotcha with the math library is + that it has to be the last library on the command + line. + + + &prompt.user; cc -o foobar foobar.c -lm + + + + This will link the math library functions into + foobar. + + If you are compiling C++ code, you need to add + , or if + you are using FreeBSD 2.2 or later, to the command line + argument to link the C++ library functions. + Alternatively, you can run c++ instead + of cc, which does this for you. + c++ can also be invoked as + g++ on FreeBSD. + + + &prompt.user; cc -o foobar foobar.cc -lg++ For FreeBSD 2.1.6 and earlier +&prompt.user; cc -o foobar foobar.cc -lstdc++ For FreeBSD 2.2 and later +&prompt.user; c++ -o foobar foobar.cc + + + + Each of these 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 + MS-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! + + + + + + Common <command>cc</command> Queries and Problems + + + + + I am trying to write a program which uses the + sin() function and I get an error + like this. What does it mean? + + + /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment + + + + + + When using mathematical functions like + sin(), you have to tell + cc to link in the math library, like + so: + + + &prompt.user; cc -o foobar foobar.c -lm + + + + + + + + All right, I wrote this simple program to practice + using . All it does is raise 2.1 to + the power of 6. + + + #include <stdio.h> + +int main() { + float f; + + f = pow(2.1, 6); + printf("2.1 ^ 6 = %f\n", f); + return 0; +} + + + + and I compiled it as: + + + &prompt.user; cc temp.c -lm + + + + like you said I should, but I get this when I run + it: + + + &prompt.user; ./a.out +2.1 ^ 6 = 1023.000000 + + + + This is not the right answer! + What is going on? + + + + 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 + int, which is definitely not what you want + here. + + + + + + So how do I fix this? + + + + 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 + will stop doing strange things to your + calculation! + + + #include <math.h> +#include <stdio.h> + +int main() { +... + + + + After recompiling it as you did before, run + it: + + + &prompt.user; ./a.out +2.1 ^ 6 = 85.766121 + + + + If you are using any of the mathematical functions, + always include + math.h and remember to link in the + math library. + + + + + + I compiled a file called + foobar.c and I cannot find an + executable called foobar. Where's + it gone? + + + + Remember, cc will call the + executable a.out unless you tell it + differently. Use the + + option: + + + &prompt.user; cc -o foobar foobar.c + + + + + + + + OK, I have an executable called + foobar, I can see it when I run + ls, but when I type in + foobar at the command prompt it tells + me there is no such file. Why can it not find + it? + + + + Unlike MS-DOS, Unix does not + look in the current directory when it is trying to find + out which executable you want it to run, unless you tell + it to. Either type ./foobar, which + means run the file called + foobar in the current + directory, or change your PATH environment + variable so that it looks something like + + + bin:/usr/bin:/usr/local/bin:. + + + + The dot at the end means look in the current + directory if it is not in any of the + others. + + + + + + I called my executable test, + but nothing happens when I run it. What is going + on? + + + + Most Unix systems have a program called + test in /usr/bin + and the shell is picking that one up before it gets to + checking the current directory. Either type: + + + &prompt.user; ./test + + + + or choose a better name for your program! + + + + + + 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? + + + + 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. + + + + + + Fascinating stuff, but what I am supposed to do + now? + + + + Use gdb to analyse the core (see + ). + + + + + + When my program dumped core, it said something about + a segmentation fault. What's + that? + + + + 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. + + Common causes for this are: + + + + Trying to write to a NULL + pointer, eg + + char *foo = NULL; +strcpy(foo, "bang!"); + + + + + Using a pointer that hasn't been initialised, + eg + + char *foo; +strcpy(foo, "bang!"); + + + 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. + + + + Trying to access past the end of an array, + eg + + int bar[20]; +bar[27] = 6; + + + + + Trying to store something in read-only memory, + eg + + char *foo = "My string"; +strcpy(foo, "bang!"); + + + Unix compilers often put string literals like + "My string" into read-only areas + of memory. + + + + Doing naughty things with + malloc() and + free(), eg + + char bar[80]; +free(bar); + + + or + + char *foo = malloc(27); +free(foo); +free(foo); + + + + + 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. + + + + + + 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? + + + + 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. + + + + + + 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? + + + + Yes, just go to another console or xterm, do + + &prompt.user; ps + + + to find out the process ID of your program, and + do + + &prompt.user; kill -ABRT pid + + + where + pid is + the process ID you looked up. + + This is useful if your program has got stuck in an + infinite loop, for instance. If your program happens to + trap SIGABRT, there are several other + signals which have a similar effect. + + + + + + + + Make + + + What is <command>make</command>? + + When you're working on a simple program with only one or + two source files, typing in + + &prompt.user; cc file1.c file2.c + + + is not too bad, but it quickly becomes very tedious when + there are several files—and it can take a while to + compile, too. + + 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: + + &prompt.user; cc file1.o file2.ofile37.c &hellip + + + if we'd changed file37.c, 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. + + 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. + + 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? + + 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. + + This program is called make. It reads + in a file, called a makefile, 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 makefile also has rules telling + make how to re-compile the source file, + making it a much more powerful tool. + + Makefiles 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. + + + + + Example of using <command>make</command> + + Here's a very simple make file: + + foo: foo.c + cc -o foo foo.c + + + It consists of two lines, a dependency line and a creation + line. + + The dependency line here consists of the name of the + program (known as the target), followed + by a colon, then whitespace, 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. + + 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. + + 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! + + 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: + + foo: foo.c + cc -o foo foo.c + +install: + cp foo /home/me + + + We can tell make which target we want to make by + typing: + + &prompt.user; make target + + + make will then only look at that target + and ignore any others. For example, if we type + make foo with the makefile above, make + will ignore the install target. + + 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. + + 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 makefiles, + so that the application can be installed in the correct + directory when it has been correctly compiled. + + 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. + + + + FreeBSD Makefiles + + 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 Makefile: + + MASTER_SITES= ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/ +DISTFILES= scheme-microcode+dist-7.3-freebsd.tgz + +.include <bsd.port.mk> + + + Now, if we go to the directory for this port and type + make, the following happens: + + + + A check is made to see if the source code for this + port is already on the system. + + + + If it isn't, an FTP connection to the URL in + MASTER_SITES is set up to download the + source. + + + + 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. + + + + Any changes required to make the source work on + FreeBSD are applied—this is known as + patching. + + + + 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). + + + + 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. + + + + 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. + + + + Now I think you'll agree that's rather impressive for a + four line script! + + The secret lies in the last line, which tells + make to look in the system makefile 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 makefile that tells + make 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! + + If you want to have a look at these system makefiles, + they're in /usr/share/mk, 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!) + + + + More advanced uses of <command>make</command> + + 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. + + 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 + + &prompt.user; zmore paper.ascii.gz + + + in that directory. + + 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 its own right. + + 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 + + * Make: (make). The GNU Make utility. + + + 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). + + + + + Debugging + + + The Debugger + + The debugger that comes with FreeBSD is called + gdb (GNU + debugger). You start it up by typing + + &prompt.user; gdb progname + + + although most people prefer to run it inside + Emacs. You can do this by: + + M-x gdb RET progname RET + + + 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. + + 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. + + Finally, if you find its text-based command-prompt style + off-putting, there's a graphical front-end for it xxgdb in the ports + collection. + + This section is intended to be an introduction to using + gdb and does not cover specialised topics + such as debugging the kernel. + + + + Running a program in the debugger + + You'll need to have compiled the program with the + 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: + + … (no debugging symbols found) … + + + when gdb starts up, you'll know that + the program wasn't compiled with the + option. + + 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!). + + 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. + + Here's a simple example of how to spot a mistake in a + program with gdb. This is our program + (with a deliberate mistake): + + #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; +} + + + This program sets i to be + 5 and passes it to a function + bazz() which prints out the number we + gave it. + + When we compile and run the program we get + + &prompt.user; cc -g -o temp temp.c +&prompt.user; ./temp +This is my program +anint = 4231 + + + That wasn't what we expected! Time to see what's going + on! + + &prompt.user; gdb temp +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 +(gdb) s step into bazz() +bazz (anint=4231) at temp.c:17 gdb displays stack frame +(gdb) + + + 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. + + (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 + + + Oh dear! Looking at the code, we forgot to initialise + i. We meant to put + + … +main() { + int i; + + i = 5; + printf("This is my program\n"); +&hellip + + + but we left 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. + + + 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). + + + + + Examining a core file + + 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. + + To examine a core file, start up gdb in + the usual way. Instead of typing break or + run, type + + (gdb) core progname.core + + + If you're not in the same directory as the core file, + you'll have to do dir + /path/to/core/file first. + + You should see something like this: + + &prompt.user; gdb a.out +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 bazz (anint=0x5) at temp.c:17 +(gdb) + + + 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. + + 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: + + (gdb) bt +#0 0x164a in bazz (anint=0x5) at temp.c:17 +#1 0xefbfd888 in end () +#2 0x162c in main () at temp.c:11 +(gdb) + + + The end() function is called when a + program crashes; in this case, the bazz() + function was called from main(). + + + + Attaching to a running program + + 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. + + What you do is start up another gdb, + use ps to find the process ID for the + child, and do + + (gdb) attach pid + + + in gdb, and then debug as usual. + + 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): + + &hellip +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 */ + &hellip +} else { /* parent */ + &hellip + + + Now all you have to do is attach to the child, set + PauseMode to 0, and wait + for the sleep() call to return! + + + + + Using Emacs as a Development Environment + + + Emacs + + 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. + + 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. + + 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. + + It's impossible even to summarise everything Emacs can do + here, but here are some of the features of interest to + developers: + + + + Very powerful editor, allowing search-and-replace on + both strings and regular expressions (patterns), jumping + to start/end of block expression, etc, etc. + + + + Pull-down menus and online help. + + + + Language-dependent syntax highlighting and + indentation. + + + + Completely customisable. + + + + You can compile and debug programs within + Emacs. + + + + On a compilation error, you can jump to the offending + line of source code. + + + + Friendly-ish front-end to the info + program used for reading GNU hypertext documentation, + including the documentation on Emacs itself. + + + + Friendly front-end to gdb, allowing + you to look at the source code as you step through your + program. + + + + You can read Usenet news and mail while your program + is compiling. + + + + And doubtless many more that I've overlooked. + + Emacs can be installed on FreeBSD using the Emacs + port. + + 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). + + 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 M-x + replace-s RET foo RET bar RET 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. + + 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. + + 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. + + 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. + + 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). + + Oh, and to get out of Emacs, do C-x C-c + (that means hold down the control key, press + x, press c 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). + + + + Configuring Emacs + + Emacs does many wonderful things; some of them are built + in, some of them need to be configured. + + 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!). + + The best way to learn Emacs Lisp is to download the Emacs + Tutorial + + 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. + + + + A sample <filename>.emacs</filename> file + + Unfortunately, there's far too much here to explain it in + detail; however there are one or two points worth + mentioning. + + + + Everything beginning with a ; is a comment + and is ignored by Emacs. + + + + 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. + + + + 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. + + + + This file supports syntax highlighting for C, C++, + Perl, Lisp and Scheme, by guessing the language from the + filename. + + + + 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. + + + + 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 + + &prompt.user; emacsclient filename + + + 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. + + + + + + A sample <filename>.emacs</filename> file + + ;; -*-Emacs-Lisp-*- + +;; This file is designed to be re-evaled; use the variable first-time +;; to avoid any problems with this. +(defvar first-time t + "Flag signifying this is the first time that .emacs has been evaled") + +;; Meta +(global-set-key "\M- " 'set-mark-command) +(global-set-key "\M-\C-h" 'backward-kill-word) +(global-set-key "\M-\C-r" 'query-replace) +(global-set-key "\M-r" 'replace-string) +(global-set-key "\M-g" 'goto-line) +(global-set-key "\M-h" 'help-command) + +;; Function keys +(global-set-key [f1] 'manual-entry) +(global-set-key [f2] 'info) +(global-set-key [f3] 'repeat-complex-command) +(global-set-key [f4] 'advertised-undo) +(global-set-key [f5] 'eval-current-buffer) +(global-set-key [f6] 'buffer-menu) +(global-set-key [f7] 'other-window) +(global-set-key [f8] 'find-file) +(global-set-key [f9] 'save-buffer) +(global-set-key [f10] 'next-error) +(global-set-key [f11] 'compile) +(global-set-key [f12] 'grep) +(global-set-key [C-f1] 'compile) +(global-set-key [C-f2] 'grep) +(global-set-key [C-f3] 'next-error) +(global-set-key [C-f4] 'previous-error) +(global-set-key [C-f5] 'display-faces) +(global-set-key [C-f8] 'dired) +(global-set-key [C-f10] 'kill-compilation) + +;; Keypad bindings +(global-set-key [up] "\C-p") +(global-set-key [down] "\C-n") +(global-set-key [left] "\C-b") +(global-set-key [right] "\C-f") +(global-set-key [home] "\C-a") +(global-set-key [end] "\C-e") +(global-set-key [prior] "\M-v") +(global-set-key [next] "\C-v") +(global-set-key [C-up] "\M-\C-b") +(global-set-key [C-down] "\M-\C-f") +(global-set-key [C-left] "\M-b") +(global-set-key [C-right] "\M-f") +(global-set-key [C-home] "\M-<") +(global-set-key [C-end] "\M->") +(global-set-key [C-prior] "\M-<") +(global-set-key [C-next] "\M->") + +;; Mouse +(global-set-key [mouse-3] 'imenu) + +;; Misc +(global-set-key [C-tab] "\C-q\t") ; Control tab quotes a tab. +(setq backup-by-copying-when-mismatch t) + +;; Treat 'y' or <CR> as yes, 'n' as no. +(fset 'yes-or-no-p 'y-or-n-p) + (define-key query-replace-map [return] 'act) + (define-key query-replace-map [?\C-m] 'act) + +;; Load packages +(require 'desktop) +(require 'tar-mode) + +;; Pretty diff mode +(autoload 'ediff-buffers "ediff" "Intelligent Emacs interface to diff" t) +(autoload 'ediff-files "ediff" "Intelligent Emacs interface to diff" t) +(autoload 'ediff-files-remote "ediff" + "Intelligent Emacs interface to diff") + +(if first-time + (setq auto-mode-alist + (append '(("\\.cpp$" . c++-mode) + ("\\.hpp$" . c++-mode) + ("\\.lsp$" . lisp-mode) + ("\\.scm$" . scheme-mode) + ("\\.pl$" . perl-mode) + ) auto-mode-alist))) + +;; Auto font lock mode +(defvar font-lock-auto-mode-list + (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode 'perl-mode 'scheme-mode) + "List of modes to always start in font-lock-mode") + +(defvar font-lock-mode-keyword-alist + '((c++-c-mode . c-font-lock-keywords) + (perl-mode . perl-font-lock-keywords)) + "Associations between modes and keywords") + +(defun font-lock-auto-mode-select () + "Automatically select font-lock-mode if the current major mode is +in font-lock-auto-mode-list" + (if (memq major-mode font-lock-auto-mode-list) + (progn + (font-lock-mode t)) + ) + ) + +(global-set-key [M-f1] 'font-lock-fontify-buffer) + +;; New dabbrev stuff +;(require 'new-dabbrev) +(setq dabbrev-always-check-other-buffers t) +(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_") +(add-hook 'emacs-lisp-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) nil) + (set (make-local-variable 'dabbrev-case-replace) nil))) +(add-hook 'c-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) nil) + (set (make-local-variable 'dabbrev-case-replace) nil))) +(add-hook 'text-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) t) + (set (make-local-variable 'dabbrev-case-replace) t))) + +;; C++ and C mode... +(defun my-c++-mode-hook () + (setq tab-width 4) + (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key c++-mode-map "\C-ce" 'c-comment-edit) + (setq c++-auto-hungry-initial-state 'none) + (setq c++-delete-function 'backward-delete-char) + (setq c++-tab-always-indent t) + (setq c-indent-level 4) + (setq c-continued-statement-offset 4) + (setq c++-empty-arglist-indent 4)) + +(defun my-c-mode-hook () + (setq tab-width 4) + (define-key c-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key c-mode-map "\C-ce" 'c-comment-edit) + (setq c-auto-hungry-initial-state 'none) + (setq c-delete-function 'backward-delete-char) + (setq c-tab-always-indent t) +;; BSD-ish indentation style + (setq c-indent-level 4) + (setq c-continued-statement-offset 4) + (setq c-brace-offset -4) + (setq c-argdecl-indent 0) + (setq c-label-offset -4)) + +;; Perl mode +(defun my-perl-mode-hook () + (setq tab-width 4) + (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent) + (setq perl-indent-level 4) + (setq perl-continued-statement-offset 4)) + +;; Scheme mode... +(defun my-scheme-mode-hook () + (define-key scheme-mode-map "\C-m" 'reindent-then-newline-and-indent)) + +;; Emacs-Lisp mode... +(defun my-lisp-mode-hook () + (define-key lisp-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key lisp-mode-map "\C-i" 'lisp-indent-line) + (define-key lisp-mode-map "\C-j" 'eval-print-last-sexp)) + +;; Add all of the hooks... +(add-hook 'c++-mode-hook 'my-c++-mode-hook) +(add-hook 'c-mode-hook 'my-c-mode-hook) +(add-hook 'scheme-mode-hook 'my-scheme-mode-hook) +(add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook) +(add-hook 'lisp-mode-hook 'my-lisp-mode-hook) +(add-hook 'perl-mode-hook 'my-perl-mode-hook) + +;; Complement to next-error +(defun previous-error (n) + "Visit previous compilation error message and corresponding source code." + (interactive "p") + (next-error (- n))) + +;; Misc... +(transient-mark-mode 1) +(setq mark-even-if-inactive t) +(setq visible-bell nil) +(setq next-line-add-newlines nil) +(setq compile-command "make") +(setq suggest-key-bindings nil) +(put 'eval-expression 'disabled nil) +(put 'narrow-to-region 'disabled nil) +(put 'set-goal-column 'disabled nil) + +;; Elisp archive searching +(autoload 'format-lisp-code-directory "lispdir" nil t) +(autoload 'lisp-dir-apropos "lispdir" nil t) +(autoload 'lisp-dir-retrieve "lispdir" nil t) +(autoload 'lisp-dir-verify "lispdir" nil t) + +;; Font lock mode +(defun my-make-face (face colour &optional bold) + "Create a face from a colour and optionally make it bold" + (make-face face) + (copy-face 'default face) + (set-face-foreground face colour) + (if bold (make-face-bold face)) + ) + +(if (eq window-system 'x) + (progn + (my-make-face 'blue "blue") + (my-make-face 'red "red") + (my-make-face 'green "dark green") + (setq font-lock-comment-face 'blue) + (setq font-lock-string-face 'bold) + (setq font-lock-type-face 'bold) + (setq font-lock-keyword-face 'bold) + (setq font-lock-function-name-face 'red) + (setq font-lock-doc-string-face 'green) + (add-hook 'find-file-hooks 'font-lock-auto-mode-select) + + (setq baud-rate 1000000) + (global-set-key "\C-cmm" 'menu-bar-mode) + (global-set-key "\C-cms" 'scroll-bar-mode) + (global-set-key [backspace] 'backward-delete-char) + ; (global-set-key [delete] 'delete-char) + (standard-display-european t) + (load-library "iso-transl"))) + +;; X11 or PC using direct screen writes +(if window-system + (progn + ;; (global-set-key [M-f1] 'hilit-repaint-command) + ;; (global-set-key [M-f2] [?\C-u M-f1]) + (setq hilit-mode-enable-list + '(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode + scheme-mode) + hilit-auto-highlight nil + hilit-auto-rehighlight 'visible + hilit-inhibit-hooks nil + hilit-inhibit-rebinding t) + (require 'hilit19) + (require 'paren)) + (setq baud-rate 2400) ; For slow serial connections + ) + +;; TTY type terminal +(if (and (not window-system) + (not (equal system-type 'ms-dos))) + (progn + (if first-time + (progn + (keyboard-translate ?\C-h ?\C-?) + (keyboard-translate ?\C-? ?\C-h))))) + +;; Under UNIX +(if (not (equal system-type 'ms-dos)) + (progn + (if first-time + (server-start)))) + +;; Add any face changes here +(add-hook 'term-setup-hook 'my-term-setup-hook) +(defun my-term-setup-hook () + (if (eq window-system 'pc) + (progn +;; (set-face-background 'default "red") + ))) + +;; Restore the "desktop" - do this as late as possible +(if first-time + (progn + (desktop-load-default) + (desktop-read))) + +;; Indicate that this file has been read at least once +(setq first-time nil) + +;; No need to debug anything now +(setq debug-on-error nil) + +;; All done +(message "All done, %s%s" (user-login-name) ".") + + + + + + Extending the Range of Languages Emacs Understands + + 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? + + 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 + + &prompt.user; find /usr/ports/lang/whizbang -name "*.el" -print + + + 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 + + /usr/ports/lang/whizbang/work/misc/whizbang.el + + + we would do + + &prompt.root; cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp + + + 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. + + Find the auto-mode-alist entry in + .emacs and add a line for whizbang, such + as: + + … +("\\.lsp$" . lisp-mode) +("\\.wiz$" . whizbang-mode) +("\\.scm$" . scheme-mode) +… + + + This means that Emacs will automatically go into + whizbang-mode when you edit a file ending + in .wiz. + + Just below this, you'll find the + font-lock-auto-mode-list entry. Add + whizbang-mode to it like so: + + ;; 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") + + + This means that Emacs will always enable + font-lock-mode (ie syntax highlighting) + when editing a .wiz file. + + 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). + + + + + Further Reading + + + + Brian Harvey and Matthew Wright + Simply Scheme + MIT 1994. + ISBN 0-262-08226-8 + + + + Randall Schwartz + Learning Perl + O'Reilly 1993 + ISBN 1-56592-042-2 + + + + Patrick Henry Winston and Berthold Klaus Paul Horn + Lisp (3rd Edition) + Addison-Wesley 1989 + ISBN 0-201-08319-1 + + + + Brian W. Kernighan and Rob Pike + The Unix Programming Environment + Prentice-Hall 1984 + ISBN 0-13-937681-X + + + + Brian W. Kernighan and Dennis M. Ritchie + The C Programming Language (2nd Edition) + Prentice-Hall 1988 + ISBN 0-13-110362-8 + + + + Bjarne Stroustrup + The C++ Programming Language + Addison-Wesley 1991 + ISBN 0-201-53992-6 + + + + W. Richard Stevens + Advanced Programming in the Unix Environment + Addison-Wesley 1992 + ISBN 0-201-56317-7 + + + + W. Richard Stevens + Unix Network Programming + Prentice-Hall 1990 + ISBN 0-13-949876-1 + + + - @@ -1357,7 +3598,7 @@ DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0); - + Debugging diff --git a/en_US.ISO_8859-1/books/developers-handbook/book.sgml b/en_US.ISO_8859-1/books/developers-handbook/book.sgml index 8aacd1d42a..bd58d4a25a 100644 --- a/en_US.ISO_8859-1/books/developers-handbook/book.sgml +++ b/en_US.ISO_8859-1/books/developers-handbook/book.sgml @@ -1,7 +1,7 @@ Basics - - Compilation + + Programming Tools - This will include things like: compilation, makefiles, .mk - files, basic debugging, linking, secure programming - guidelines, style(9), CVS, diff, patch, etc. + This chapter was written by James Raynard. + Modifications for the Developer's Handbook by Murray Stokely. + + + Synopsis + + 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 + 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 + + + + Introduction + + 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 is not 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. + + 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. + + 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! + + + + + Introduction to Programming + + 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 are 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. + + + Interpreters + + 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. + + 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. + + 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 (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. + + + + Interpreters available with FreeBSD + + Here is a list of interpreters that are available as + FreeBSD + packages, with a brief discussion of some of the + more popular interpreted languages. + + To get one of these packages, all you need to do is to + click on the hotlink for the package, then run + + &prompt.root; pkg_add package name + + + as root. Obviously, you will need to have a fully + functional FreeBSD 2.1.0 or later system for the package to + work! + + + + BASIC + + + 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 Bywater + Basic Interpreter and the Phil + Cockroft's Basic Interpreter (formerly Rabbit + Basic) are available as FreeBSD FreeBSD + packages + + + + + Lisp + + + 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 GNU + Common Lisp available as a package. + + + + + Perl + + + Very popular with system administrators for writing + scripts; also often used on World Wide Web servers for + writing CGI scripts. + + The latest version (version 5) comes with FreeBSD. + + + + + Scheme + + + 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. + + FreeBSD has packages of the Elk + Scheme Interpreter, the MIT + Scheme Interpreter and the SCM + Scheme Interpreter. + + + + + Icon + + + The + Icon Programming Language. + + + + + Logo + + + Brian + Harvey's LOGO Interpreter. + + + + + Python + + + The + Python Object-Oriented Programming + Language + + + + + + + Compilers + + 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. + + + If you run it in the shell, you may get a core + dump. + + + 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. + + 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. + + 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 does not have an + IDE as such; however it is possible to use Emacs + for this purpose. This is discussed in . + + + + + + + + Compiling with <command>cc</command> + + 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. + + 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. + + + + Pre-process your source code to remove comments and do + other tricks like expanding macros in C. + + + + Check the syntax of your code to see if you have obeyed + the rules of the language. If you have not, it will + complain! + + + + Convert the source code into assembly + language—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 assembly language at + this stage. + + + + + Convert the assembly language into machine + code—yep, we are talking bits and bytes, ones and + zeros here. + + + + 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. + + + + If you are trying to produce an executable from several + source code files, work out how to fit them all + together. + + + + Work out how to produce something that the system's + run-time loader will be able to load into memory and + run. + + + + Finally, write the executable on the file system. + + + + 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. + + 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 + + &prompt.user; cc foobar.c + + + 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 + + &prompt.user; cc foo.c bar.c + + + 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. + + + In case you didn't know, a binary sort is an efficient + way of sorting things into order and a bubble sort + isn't. + + + 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. + + + + + + + The output name of the file. If you do not use this + option, cc will produce an executable called + a.out. + + + The reasons for this are buried in the mists of + history. + + + + &prompt.user; cc foobar.c executable is a.out +&prompt.user; cc -o foobar foobar.c executable is foobar + + + + + + + + + + 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 Makefile. + + + &prompt.user; cc -c foobar.c + + + + This will produce an object file (not an + executable) called foobar.o. This + can be linked together with other object files into an + executable. + + + + + + + + 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 + very useful; the disadvantage is that + all this extra information makes the program much bigger. + Normally, you compile with while you + are developing a program and then compile a release + version without when you're + satisfied it works properly. + + + &prompt.user; cc -g foobar.c + + + + This will produce a debug version of the + program. + + + Note, we didn't use the flag + to specify the executable name, so we will get an + executable called a.out. + Producing a debug version called + foobar is left as an exercise for + the reader! + + + + + + + + + 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 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 + option in some circumstances. + + Optimisation is usually only turned on when compiling + a release version. + + + &prompt.user; cc -O -o foobar foobar.c + + + + This will produce an optimised version of + foobar. + + + + + 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 is an + ISO standard. + + + + + + + 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. + + + + + + + + Turn off most, but not all, of the + non-ANSI C features provided by + cc. Despite the name, it does not + guarantee strictly that your code will comply to the + standard. + + + + + + + + Turn off all + cc's non-ANSI C + features. + + + + + 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. + + 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? + + + &prompt.user; cc -Wall -ansi -pedantic -o foobar foobar.c + + + + This will produce an executable foobar + after checking foobar.c for standard + compliance. + + + + + + + Specify a function library to be used during when + linking. + + 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. + + The rule is that if the library is called + libsomething.a, + you give cc the argument + . + For example, the math library is + libm.a, so you give + cc the argument . + A common gotcha with the math library is + that it has to be the last library on the command + line. + + + &prompt.user; cc -o foobar foobar.c -lm + + + + This will link the math library functions into + foobar. + + If you are compiling C++ code, you need to add + , or if + you are using FreeBSD 2.2 or later, to the command line + argument to link the C++ library functions. + Alternatively, you can run c++ instead + of cc, which does this for you. + c++ can also be invoked as + g++ on FreeBSD. + + + &prompt.user; cc -o foobar foobar.cc -lg++ For FreeBSD 2.1.6 and earlier +&prompt.user; cc -o foobar foobar.cc -lstdc++ For FreeBSD 2.2 and later +&prompt.user; c++ -o foobar foobar.cc + + + + Each of these 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 + MS-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! + + + + + + Common <command>cc</command> Queries and Problems + + + + + I am trying to write a program which uses the + sin() function and I get an error + like this. What does it mean? + + + /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment + + + + + + When using mathematical functions like + sin(), you have to tell + cc to link in the math library, like + so: + + + &prompt.user; cc -o foobar foobar.c -lm + + + + + + + + All right, I wrote this simple program to practice + using . All it does is raise 2.1 to + the power of 6. + + + #include <stdio.h> + +int main() { + float f; + + f = pow(2.1, 6); + printf("2.1 ^ 6 = %f\n", f); + return 0; +} + + + + and I compiled it as: + + + &prompt.user; cc temp.c -lm + + + + like you said I should, but I get this when I run + it: + + + &prompt.user; ./a.out +2.1 ^ 6 = 1023.000000 + + + + This is not the right answer! + What is going on? + + + + 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 + int, which is definitely not what you want + here. + + + + + + So how do I fix this? + + + + 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 + will stop doing strange things to your + calculation! + + + #include <math.h> +#include <stdio.h> + +int main() { +... + + + + After recompiling it as you did before, run + it: + + + &prompt.user; ./a.out +2.1 ^ 6 = 85.766121 + + + + If you are using any of the mathematical functions, + always include + math.h and remember to link in the + math library. + + + + + + I compiled a file called + foobar.c and I cannot find an + executable called foobar. Where's + it gone? + + + + Remember, cc will call the + executable a.out unless you tell it + differently. Use the + + option: + + + &prompt.user; cc -o foobar foobar.c + + + + + + + + OK, I have an executable called + foobar, I can see it when I run + ls, but when I type in + foobar at the command prompt it tells + me there is no such file. Why can it not find + it? + + + + Unlike MS-DOS, Unix does not + look in the current directory when it is trying to find + out which executable you want it to run, unless you tell + it to. Either type ./foobar, which + means run the file called + foobar in the current + directory, or change your PATH environment + variable so that it looks something like + + + bin:/usr/bin:/usr/local/bin:. + + + + The dot at the end means look in the current + directory if it is not in any of the + others. + + + + + + I called my executable test, + but nothing happens when I run it. What is going + on? + + + + Most Unix systems have a program called + test in /usr/bin + and the shell is picking that one up before it gets to + checking the current directory. Either type: + + + &prompt.user; ./test + + + + or choose a better name for your program! + + + + + + 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? + + + + 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. + + + + + + Fascinating stuff, but what I am supposed to do + now? + + + + Use gdb to analyse the core (see + ). + + + + + + When my program dumped core, it said something about + a segmentation fault. What's + that? + + + + 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. + + Common causes for this are: + + + + Trying to write to a NULL + pointer, eg + + char *foo = NULL; +strcpy(foo, "bang!"); + + + + + Using a pointer that hasn't been initialised, + eg + + char *foo; +strcpy(foo, "bang!"); + + + 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. + + + + Trying to access past the end of an array, + eg + + int bar[20]; +bar[27] = 6; + + + + + Trying to store something in read-only memory, + eg + + char *foo = "My string"; +strcpy(foo, "bang!"); + + + Unix compilers often put string literals like + "My string" into read-only areas + of memory. + + + + Doing naughty things with + malloc() and + free(), eg + + char bar[80]; +free(bar); + + + or + + char *foo = malloc(27); +free(foo); +free(foo); + + + + + 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. + + + + + + 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? + + + + 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. + + + + + + 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? + + + + Yes, just go to another console or xterm, do + + &prompt.user; ps + + + to find out the process ID of your program, and + do + + &prompt.user; kill -ABRT pid + + + where + pid is + the process ID you looked up. + + This is useful if your program has got stuck in an + infinite loop, for instance. If your program happens to + trap SIGABRT, there are several other + signals which have a similar effect. + + + + + + + + Make + + + What is <command>make</command>? + + When you're working on a simple program with only one or + two source files, typing in + + &prompt.user; cc file1.c file2.c + + + is not too bad, but it quickly becomes very tedious when + there are several files—and it can take a while to + compile, too. + + 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: + + &prompt.user; cc file1.o file2.ofile37.c &hellip + + + if we'd changed file37.c, 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. + + 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. + + 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? + + 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. + + This program is called make. It reads + in a file, called a makefile, 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 makefile also has rules telling + make how to re-compile the source file, + making it a much more powerful tool. + + Makefiles 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. + + + + + Example of using <command>make</command> + + Here's a very simple make file: + + foo: foo.c + cc -o foo foo.c + + + It consists of two lines, a dependency line and a creation + line. + + The dependency line here consists of the name of the + program (known as the target), followed + by a colon, then whitespace, 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. + + 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. + + 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! + + 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: + + foo: foo.c + cc -o foo foo.c + +install: + cp foo /home/me + + + We can tell make which target we want to make by + typing: + + &prompt.user; make target + + + make will then only look at that target + and ignore any others. For example, if we type + make foo with the makefile above, make + will ignore the install target. + + 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. + + 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 makefiles, + so that the application can be installed in the correct + directory when it has been correctly compiled. + + 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. + + + + FreeBSD Makefiles + + 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 Makefile: + + MASTER_SITES= ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/ +DISTFILES= scheme-microcode+dist-7.3-freebsd.tgz + +.include <bsd.port.mk> + + + Now, if we go to the directory for this port and type + make, the following happens: + + + + A check is made to see if the source code for this + port is already on the system. + + + + If it isn't, an FTP connection to the URL in + MASTER_SITES is set up to download the + source. + + + + 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. + + + + Any changes required to make the source work on + FreeBSD are applied—this is known as + patching. + + + + 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). + + + + 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. + + + + 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. + + + + Now I think you'll agree that's rather impressive for a + four line script! + + The secret lies in the last line, which tells + make to look in the system makefile 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 makefile that tells + make 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! + + If you want to have a look at these system makefiles, + they're in /usr/share/mk, 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!) + + + + More advanced uses of <command>make</command> + + 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. + + 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 + + &prompt.user; zmore paper.ascii.gz + + + in that directory. + + 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 its own right. + + 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 + + * Make: (make). The GNU Make utility. + + + 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). + + + + + Debugging + + + The Debugger + + The debugger that comes with FreeBSD is called + gdb (GNU + debugger). You start it up by typing + + &prompt.user; gdb progname + + + although most people prefer to run it inside + Emacs. You can do this by: + + M-x gdb RET progname RET + + + 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. + + 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. + + Finally, if you find its text-based command-prompt style + off-putting, there's a graphical front-end for it xxgdb in the ports + collection. + + This section is intended to be an introduction to using + gdb and does not cover specialised topics + such as debugging the kernel. + + + + Running a program in the debugger + + You'll need to have compiled the program with the + 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: + + … (no debugging symbols found) … + + + when gdb starts up, you'll know that + the program wasn't compiled with the + option. + + 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!). + + 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. + + Here's a simple example of how to spot a mistake in a + program with gdb. This is our program + (with a deliberate mistake): + + #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; +} + + + This program sets i to be + 5 and passes it to a function + bazz() which prints out the number we + gave it. + + When we compile and run the program we get + + &prompt.user; cc -g -o temp temp.c +&prompt.user; ./temp +This is my program +anint = 4231 + + + That wasn't what we expected! Time to see what's going + on! + + &prompt.user; gdb temp +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 +(gdb) s step into bazz() +bazz (anint=4231) at temp.c:17 gdb displays stack frame +(gdb) + + + 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. + + (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 + + + Oh dear! Looking at the code, we forgot to initialise + i. We meant to put + + … +main() { + int i; + + i = 5; + printf("This is my program\n"); +&hellip + + + but we left 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. + + + 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). + + + + + Examining a core file + + 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. + + To examine a core file, start up gdb in + the usual way. Instead of typing break or + run, type + + (gdb) core progname.core + + + If you're not in the same directory as the core file, + you'll have to do dir + /path/to/core/file first. + + You should see something like this: + + &prompt.user; gdb a.out +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 bazz (anint=0x5) at temp.c:17 +(gdb) + + + 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. + + 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: + + (gdb) bt +#0 0x164a in bazz (anint=0x5) at temp.c:17 +#1 0xefbfd888 in end () +#2 0x162c in main () at temp.c:11 +(gdb) + + + The end() function is called when a + program crashes; in this case, the bazz() + function was called from main(). + + + + Attaching to a running program + + 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. + + What you do is start up another gdb, + use ps to find the process ID for the + child, and do + + (gdb) attach pid + + + in gdb, and then debug as usual. + + 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): + + &hellip +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 */ + &hellip +} else { /* parent */ + &hellip + + + Now all you have to do is attach to the child, set + PauseMode to 0, and wait + for the sleep() call to return! + + + + + Using Emacs as a Development Environment + + + Emacs + + 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. + + 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. + + 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. + + It's impossible even to summarise everything Emacs can do + here, but here are some of the features of interest to + developers: + + + + Very powerful editor, allowing search-and-replace on + both strings and regular expressions (patterns), jumping + to start/end of block expression, etc, etc. + + + + Pull-down menus and online help. + + + + Language-dependent syntax highlighting and + indentation. + + + + Completely customisable. + + + + You can compile and debug programs within + Emacs. + + + + On a compilation error, you can jump to the offending + line of source code. + + + + Friendly-ish front-end to the info + program used for reading GNU hypertext documentation, + including the documentation on Emacs itself. + + + + Friendly front-end to gdb, allowing + you to look at the source code as you step through your + program. + + + + You can read Usenet news and mail while your program + is compiling. + + + + And doubtless many more that I've overlooked. + + Emacs can be installed on FreeBSD using the Emacs + port. + + 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). + + 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 M-x + replace-s RET foo RET bar RET 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. + + 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. + + 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. + + 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. + + 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). + + Oh, and to get out of Emacs, do C-x C-c + (that means hold down the control key, press + x, press c 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). + + + + Configuring Emacs + + Emacs does many wonderful things; some of them are built + in, some of them need to be configured. + + 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!). + + The best way to learn Emacs Lisp is to download the Emacs + Tutorial + + 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. + + + + A sample <filename>.emacs</filename> file + + Unfortunately, there's far too much here to explain it in + detail; however there are one or two points worth + mentioning. + + + + Everything beginning with a ; is a comment + and is ignored by Emacs. + + + + 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. + + + + 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. + + + + This file supports syntax highlighting for C, C++, + Perl, Lisp and Scheme, by guessing the language from the + filename. + + + + 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. + + + + 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 + + &prompt.user; emacsclient filename + + + 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. + + + + + + A sample <filename>.emacs</filename> file + + ;; -*-Emacs-Lisp-*- + +;; This file is designed to be re-evaled; use the variable first-time +;; to avoid any problems with this. +(defvar first-time t + "Flag signifying this is the first time that .emacs has been evaled") + +;; Meta +(global-set-key "\M- " 'set-mark-command) +(global-set-key "\M-\C-h" 'backward-kill-word) +(global-set-key "\M-\C-r" 'query-replace) +(global-set-key "\M-r" 'replace-string) +(global-set-key "\M-g" 'goto-line) +(global-set-key "\M-h" 'help-command) + +;; Function keys +(global-set-key [f1] 'manual-entry) +(global-set-key [f2] 'info) +(global-set-key [f3] 'repeat-complex-command) +(global-set-key [f4] 'advertised-undo) +(global-set-key [f5] 'eval-current-buffer) +(global-set-key [f6] 'buffer-menu) +(global-set-key [f7] 'other-window) +(global-set-key [f8] 'find-file) +(global-set-key [f9] 'save-buffer) +(global-set-key [f10] 'next-error) +(global-set-key [f11] 'compile) +(global-set-key [f12] 'grep) +(global-set-key [C-f1] 'compile) +(global-set-key [C-f2] 'grep) +(global-set-key [C-f3] 'next-error) +(global-set-key [C-f4] 'previous-error) +(global-set-key [C-f5] 'display-faces) +(global-set-key [C-f8] 'dired) +(global-set-key [C-f10] 'kill-compilation) + +;; Keypad bindings +(global-set-key [up] "\C-p") +(global-set-key [down] "\C-n") +(global-set-key [left] "\C-b") +(global-set-key [right] "\C-f") +(global-set-key [home] "\C-a") +(global-set-key [end] "\C-e") +(global-set-key [prior] "\M-v") +(global-set-key [next] "\C-v") +(global-set-key [C-up] "\M-\C-b") +(global-set-key [C-down] "\M-\C-f") +(global-set-key [C-left] "\M-b") +(global-set-key [C-right] "\M-f") +(global-set-key [C-home] "\M-<") +(global-set-key [C-end] "\M->") +(global-set-key [C-prior] "\M-<") +(global-set-key [C-next] "\M->") + +;; Mouse +(global-set-key [mouse-3] 'imenu) + +;; Misc +(global-set-key [C-tab] "\C-q\t") ; Control tab quotes a tab. +(setq backup-by-copying-when-mismatch t) + +;; Treat 'y' or <CR> as yes, 'n' as no. +(fset 'yes-or-no-p 'y-or-n-p) + (define-key query-replace-map [return] 'act) + (define-key query-replace-map [?\C-m] 'act) + +;; Load packages +(require 'desktop) +(require 'tar-mode) + +;; Pretty diff mode +(autoload 'ediff-buffers "ediff" "Intelligent Emacs interface to diff" t) +(autoload 'ediff-files "ediff" "Intelligent Emacs interface to diff" t) +(autoload 'ediff-files-remote "ediff" + "Intelligent Emacs interface to diff") + +(if first-time + (setq auto-mode-alist + (append '(("\\.cpp$" . c++-mode) + ("\\.hpp$" . c++-mode) + ("\\.lsp$" . lisp-mode) + ("\\.scm$" . scheme-mode) + ("\\.pl$" . perl-mode) + ) auto-mode-alist))) + +;; Auto font lock mode +(defvar font-lock-auto-mode-list + (list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode 'perl-mode 'scheme-mode) + "List of modes to always start in font-lock-mode") + +(defvar font-lock-mode-keyword-alist + '((c++-c-mode . c-font-lock-keywords) + (perl-mode . perl-font-lock-keywords)) + "Associations between modes and keywords") + +(defun font-lock-auto-mode-select () + "Automatically select font-lock-mode if the current major mode is +in font-lock-auto-mode-list" + (if (memq major-mode font-lock-auto-mode-list) + (progn + (font-lock-mode t)) + ) + ) + +(global-set-key [M-f1] 'font-lock-fontify-buffer) + +;; New dabbrev stuff +;(require 'new-dabbrev) +(setq dabbrev-always-check-other-buffers t) +(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_") +(add-hook 'emacs-lisp-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) nil) + (set (make-local-variable 'dabbrev-case-replace) nil))) +(add-hook 'c-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) nil) + (set (make-local-variable 'dabbrev-case-replace) nil))) +(add-hook 'text-mode-hook + '(lambda () + (set (make-local-variable 'dabbrev-case-fold-search) t) + (set (make-local-variable 'dabbrev-case-replace) t))) + +;; C++ and C mode... +(defun my-c++-mode-hook () + (setq tab-width 4) + (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key c++-mode-map "\C-ce" 'c-comment-edit) + (setq c++-auto-hungry-initial-state 'none) + (setq c++-delete-function 'backward-delete-char) + (setq c++-tab-always-indent t) + (setq c-indent-level 4) + (setq c-continued-statement-offset 4) + (setq c++-empty-arglist-indent 4)) + +(defun my-c-mode-hook () + (setq tab-width 4) + (define-key c-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key c-mode-map "\C-ce" 'c-comment-edit) + (setq c-auto-hungry-initial-state 'none) + (setq c-delete-function 'backward-delete-char) + (setq c-tab-always-indent t) +;; BSD-ish indentation style + (setq c-indent-level 4) + (setq c-continued-statement-offset 4) + (setq c-brace-offset -4) + (setq c-argdecl-indent 0) + (setq c-label-offset -4)) + +;; Perl mode +(defun my-perl-mode-hook () + (setq tab-width 4) + (define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent) + (setq perl-indent-level 4) + (setq perl-continued-statement-offset 4)) + +;; Scheme mode... +(defun my-scheme-mode-hook () + (define-key scheme-mode-map "\C-m" 'reindent-then-newline-and-indent)) + +;; Emacs-Lisp mode... +(defun my-lisp-mode-hook () + (define-key lisp-mode-map "\C-m" 'reindent-then-newline-and-indent) + (define-key lisp-mode-map "\C-i" 'lisp-indent-line) + (define-key lisp-mode-map "\C-j" 'eval-print-last-sexp)) + +;; Add all of the hooks... +(add-hook 'c++-mode-hook 'my-c++-mode-hook) +(add-hook 'c-mode-hook 'my-c-mode-hook) +(add-hook 'scheme-mode-hook 'my-scheme-mode-hook) +(add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook) +(add-hook 'lisp-mode-hook 'my-lisp-mode-hook) +(add-hook 'perl-mode-hook 'my-perl-mode-hook) + +;; Complement to next-error +(defun previous-error (n) + "Visit previous compilation error message and corresponding source code." + (interactive "p") + (next-error (- n))) + +;; Misc... +(transient-mark-mode 1) +(setq mark-even-if-inactive t) +(setq visible-bell nil) +(setq next-line-add-newlines nil) +(setq compile-command "make") +(setq suggest-key-bindings nil) +(put 'eval-expression 'disabled nil) +(put 'narrow-to-region 'disabled nil) +(put 'set-goal-column 'disabled nil) + +;; Elisp archive searching +(autoload 'format-lisp-code-directory "lispdir" nil t) +(autoload 'lisp-dir-apropos "lispdir" nil t) +(autoload 'lisp-dir-retrieve "lispdir" nil t) +(autoload 'lisp-dir-verify "lispdir" nil t) + +;; Font lock mode +(defun my-make-face (face colour &optional bold) + "Create a face from a colour and optionally make it bold" + (make-face face) + (copy-face 'default face) + (set-face-foreground face colour) + (if bold (make-face-bold face)) + ) + +(if (eq window-system 'x) + (progn + (my-make-face 'blue "blue") + (my-make-face 'red "red") + (my-make-face 'green "dark green") + (setq font-lock-comment-face 'blue) + (setq font-lock-string-face 'bold) + (setq font-lock-type-face 'bold) + (setq font-lock-keyword-face 'bold) + (setq font-lock-function-name-face 'red) + (setq font-lock-doc-string-face 'green) + (add-hook 'find-file-hooks 'font-lock-auto-mode-select) + + (setq baud-rate 1000000) + (global-set-key "\C-cmm" 'menu-bar-mode) + (global-set-key "\C-cms" 'scroll-bar-mode) + (global-set-key [backspace] 'backward-delete-char) + ; (global-set-key [delete] 'delete-char) + (standard-display-european t) + (load-library "iso-transl"))) + +;; X11 or PC using direct screen writes +(if window-system + (progn + ;; (global-set-key [M-f1] 'hilit-repaint-command) + ;; (global-set-key [M-f2] [?\C-u M-f1]) + (setq hilit-mode-enable-list + '(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode + scheme-mode) + hilit-auto-highlight nil + hilit-auto-rehighlight 'visible + hilit-inhibit-hooks nil + hilit-inhibit-rebinding t) + (require 'hilit19) + (require 'paren)) + (setq baud-rate 2400) ; For slow serial connections + ) + +;; TTY type terminal +(if (and (not window-system) + (not (equal system-type 'ms-dos))) + (progn + (if first-time + (progn + (keyboard-translate ?\C-h ?\C-?) + (keyboard-translate ?\C-? ?\C-h))))) + +;; Under UNIX +(if (not (equal system-type 'ms-dos)) + (progn + (if first-time + (server-start)))) + +;; Add any face changes here +(add-hook 'term-setup-hook 'my-term-setup-hook) +(defun my-term-setup-hook () + (if (eq window-system 'pc) + (progn +;; (set-face-background 'default "red") + ))) + +;; Restore the "desktop" - do this as late as possible +(if first-time + (progn + (desktop-load-default) + (desktop-read))) + +;; Indicate that this file has been read at least once +(setq first-time nil) + +;; No need to debug anything now +(setq debug-on-error nil) + +;; All done +(message "All done, %s%s" (user-login-name) ".") + + + + + + Extending the Range of Languages Emacs Understands + + 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? + + 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 + + &prompt.user; find /usr/ports/lang/whizbang -name "*.el" -print + + + 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 + + /usr/ports/lang/whizbang/work/misc/whizbang.el + + + we would do + + &prompt.root; cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp + + + 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. + + Find the auto-mode-alist entry in + .emacs and add a line for whizbang, such + as: + + … +("\\.lsp$" . lisp-mode) +("\\.wiz$" . whizbang-mode) +("\\.scm$" . scheme-mode) +… + + + This means that Emacs will automatically go into + whizbang-mode when you edit a file ending + in .wiz. + + Just below this, you'll find the + font-lock-auto-mode-list entry. Add + whizbang-mode to it like so: + + ;; 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") + + + This means that Emacs will always enable + font-lock-mode (ie syntax highlighting) + when editing a .wiz file. + + 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). + + + + + Further Reading + + + + Brian Harvey and Matthew Wright + Simply Scheme + MIT 1994. + ISBN 0-262-08226-8 + + + + Randall Schwartz + Learning Perl + O'Reilly 1993 + ISBN 1-56592-042-2 + + + + Patrick Henry Winston and Berthold Klaus Paul Horn + Lisp (3rd Edition) + Addison-Wesley 1989 + ISBN 0-201-08319-1 + + + + Brian W. Kernighan and Rob Pike + The Unix Programming Environment + Prentice-Hall 1984 + ISBN 0-13-937681-X + + + + Brian W. Kernighan and Dennis M. Ritchie + The C Programming Language (2nd Edition) + Prentice-Hall 1988 + ISBN 0-13-110362-8 + + + + Bjarne Stroustrup + The C++ Programming Language + Addison-Wesley 1991 + ISBN 0-201-53992-6 + + + + W. Richard Stevens + Advanced Programming in the Unix Environment + Addison-Wesley 1992 + ISBN 0-201-56317-7 + + + + W. Richard Stevens + Unix Network Programming + Prentice-Hall 1990 + ISBN 0-13-949876-1 + + + - @@ -1357,7 +3598,7 @@ DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0); - + Debugging