Sams Teach Yourself Emacs in 24 Hours

ContentsIndex

Hour 19: Programming Utilities

Previous HourNext Hour

Sections in this Hour:

 

Debugging Programs

After your program has been compiled, you might find runtime errors or anomalies and turn immediately to the debugger. All traditional UNIX debuggers are command-line-based; this makes them difficult to learn at first, but ideal for running under Emacs. This section assumes that you have at least a basic understanding of your system's debugger and the language you are attempting to debug.

Emacs has extensive knowledge of debuggers and the languages with which they work. To accommodate the vast array of debuggers for everything from C to Perl, a base called the Grand Unified Debugger was written. This provides the baseline for working with a debugger in Emacs. After you learn the basics of the Grand Unified Debugger, almost any language or system debugging tool can be used with ease.

To simplify this hour, I'll give examples that use gdb, the GNU Debugger. This debugger is widely available for almost any platform, and even has features that were designed especially for use under the Grand Unified Debugger.

First, make sure that you know where the program you want to debug is. Next, you might want to load a source file for the program so that the Grand Unified Debugger has a starting point, and so that you can be ready to put in a few break points. After you're ready, run one of the many debugger programs. For this example, the command is M-x gdb. On some commercial UNIX systems, you might be running dbx, sdb, or some other debugger. For Java, you run jdb, and for Perl, you run perldb.

After you choose your debugger, you are queried for a command line. You can pass any arguments to the debugger, but usually you just want to enter the name of the program that you want to debug. Pretend that you're working on a program called twiddle, the purpose of which is to adjust bits in a file. Therefore, you'll type in twiddle at the gdb prompt.

As soon as you press Enter, Emacs runs gdb in a subprocess. This mode is probably familiar to you because it is closely related to Shell mode, which is introduced in Hour 16. In this case, however, you have a (gdb) prompt, and gdb will have reported its success in loading the program and its symbol table.

You probably know that there are usually several ways to do any one thing. To begin, assume that there is a problem in the function twiddle_file, which loops over the file and twiddles its bits. At the (gdb) prompt you can type in break twi, where break is the command for setting a break point and twi is the first few characters of the function name. You can now use Tab completion to fill out the rest of the function name. This is true for any command in gdb that accesses a symbol of any kind, including print.

Note - In dbx, you can set a break point with the stop in command.


Now you have a break point in your function. You can now type run, followed by any needed parameters, to start your program under the debugger. When the program reaches twiddle_file it stops in the debugger; Emacs shows you file.c, which contains the twiddle_file function, and an overlay arrow appears next to the beginning of your functions.

You can now step through your program using some simple keys, instead of typing in debugger commands. Emacs knows which command is for which debugger, so you only have to remember the Emacs key sequence--not the more archaic commands. In almost all cases, a command has some keystroke associated with it, such as C-n. When the current buffer is the GUD buffer, prefix it with C-c to run it. If you are in a source file, prefix it with C-x C-a.

To use the next command, which walks over one command, press C-c C-n. To use the step command to step into a function, use C-c C-s. In either case, the overlay arrow is updated to the new location regardless of the file to which you moved. Another big advantage to using these keybindings is that the gdb buffer is not filled up with useless status messages. Instead, that information is filtered out completely, and the overlay arrow shows you the current state of the debugger. If your current buffer is the source code and not the debugger buffer, you can still use the next and step commands by using the C-x C-a prefix that was mentioned earlier. Therefore, C-x C-a C-n executes next, and C-x C-a C-s executes step.

You might find that you must step too much in the main loop of this function. If the bug in which you are interested is after this loop, move the cursor to a line of interest, and type C-x SPC; a break point is registered for that location. Now type C-x C-a C-r to cause the debugger to continue throughout the loop. When the debugger hits the new break point, it stops and updates the source buffers. If you want to get rid of this break point, you can use the C-x C-a C-d command to remove it.

Now that you are here, you might be interested to know what the values of some variables are. Did the file pointer get cleared correctly? How many characters have been scanned? Position the cursor over a variable name, and type C-x C-a C-p. This prints out the value of the item under the cursor. In C, it is even smart enough to pick up full structure elements or function call parameters.

In Figure 19.1, you can see that the cursor is on the variable unchanged. The resulting output of C-x C-a C-p, which prints the value under the cursor, is prefixed with $1 =, which simply indicates the first item you've printed.

Figure 19.1
Debugging twiddle_file in twiddle.c.

Are other stack layers at fault here? You can navigate up and down the stack with some quick keystrokes. In the gdb buffer, use C-c < to go up the stack and C-c > to go down. If you are still in the source buffer, use C-x C-a < and C-x C-a > to move up and down, respectively. After you've switched to that new stack frame, you can use the print command that you learned earlier to examine the variables in this stack frame as well.

It is obvious that all the basics of the debugger are covered with simple keystrokes. Any additional functionality that is provided by a debugger can still be accessed by just typing in the desired command as if you were on the command line, and not in Emacs at all. If any command you enter changes the current state of the stack, Emacs picks up on it and adjusts the currently displayed buffers to make sure that the area of interest is visible.

Because the commands you've just learned all work by sending a command string to the debugger and interpreting its output, it's possible to add new commands of your own creation if something is not covered by the basics. Doing so involves the same programmatic features that are used by the individual debugging modes such as gdb.

For example, say it is common for you to set watch points in gdb so that you can track changes in variable values. You can do this easily enough by just typing watch <variable> at the command line. Because you are in the mood to impress your friends, however, say you want to bind this to a key sequence. This requires some modification to your .emacs file. First, you know that you want to add a hook for gdb to add this binding. Next, you need to understand the Lisp function gud-def. This function takes four arguments, starting with the name that you want to give the Lisp function, followed by the string that is sent to the debugger, the keybinding, and some documentation. Call your function my-watch; the command is watch <variable>; and the key binding is C-w.

When you specify C-w as your key sequence, it really means that in the gud buffer, your new function is accessible through C-c C-w and from a source buffer as C-x C-a C-w.

When you are specifying the command to send to the debugger, specify that your preference is for the <variable> part of your command to be automatically filled in with the symbol under the cursor. To do this, replace <variable> with %e. %e is automatically replaced by GUD with the expression found under the cursor. Some other symbols that you can add to your string include %f for the filename, and %l for the current line number.

Now put all this information together to customize the gdb mode for all future sessions. Your .emacs now contains the following information:


(add-hook 'gdb-mode-hook 
                 (lambda () 
                  (gud-def my-watch "watch %e" 
                           "\C-w" "Watch my variables.") 
                   ) 
 ) 

After this is set up and gdb is restarted, you can use C-x C-a C-w.in your source buffer to set watch points on the expression on which the cursor sits.

Sams Teach Yourself Emacs in 24 Hours

ContentsIndex

Hour 19: Programming Utilities

Previous HourNext Hour

Sections in this Hour: