Learn how to use emacs -q and version control to manage your.emacs.d. That way you can experiment safe in the knowledge that you can always roll it back to a previous, stable state. Get familiar with emacs internal documentation system: M-x info, M-x org-info, and all the C-h commands will make you feel less frustrated and lost.
Emacs has many capabilities that making it useful for creating,editing, compiling and debugging programs. This tutorial discusses:
- C++ Mode
- Debugging (with Gdb) inside Emacs
- Color-coding:Emacs can display C++ source code files in a color-coded manner.This means that:
- comments
- preprocessor directives(like
#include
and#define
) - types (like
int
) - keyword (like
if
,while
) - string literals (like
'Here is a string'
) - etc.
will be displayed using different colors.This can be useful in helping you understand a program and to findtypos. For example, suppose you had the following:when it is color-coded:it displays the entire line afterAs another example, suppose you are doing a science project on theproperties of materials. You are writing a program that keeps track ofproperties of test objects, for example:cout << (
in thecolor used for a string literal. Since the variablesum
and the manipulatorendl
are obviously not intended to bepart of the string literal, it's easy to see there is an error, amissingquote ( .'
)With color-coding:you can see that you accidentally used a reserved word floatfor the name of a variable.In conclusion, color-coding can be useful in finding certain kinds ofmistakes. Emacs' color-coding is not, however, all-powerful, and thereare many problems it will not help you find.If you need to set up your account so that Emacs will color-code your Cand C++ programs, follow these instructions. - C++ Mode:Now let's see how else Emacs can help us with writing/editing C++code.Download the program
sum1.cpp
into your current directory.Now, start up Emacs:To load the file, choose Open File... from the Emacs Filemenu. When it prompts you with:(where curr-dir is your current directory), type in the name ofthe file, giving:and press<Return>
.Aside:The tilde (~
) is shorthand for your home directory in manyprograms and at the UNIX prompt. Thus, tilde (~
) willappear at the beginning of what Emacs lists as your currentdirectory if it is under your home directory.You should now see the source code in Emacs. Note that since we haveloaded C++ code, Emacs has gone into C++ mode. Emacs knows it isediting C++ code because the filename ends inAside:It may also recognize other common C++ file extensions like.cpp
..cc
.For files ending in.c
or.h
, Emacs will gointo a similar C mode. Even though a header file (.h
)might have either C or C++ code, Emacs cannot tell the difference.C++ Menu
Note that when you are in C++ mode in Emacs, there is an additionalmenu named C++, with commands for navigating and editing C++programs.Aside:A very similar C menu will appear in C mode.Let's use one of the C++ menu's commands. In the Emacs window,put the cursor at the end of the first line that usescout
:If you now choose Forward Statement from the C++ menu, itwill go to the next statement, which is the one usingAside: Roughly, a statement is something that ends in asemi-colon (cin
:;
), which is a simple statement.There are also compound statements--all of the stuff in a block(i.e., between braces,{
and}
) forms asingle compound statement.You might use the Forward Statement command to advance throughstatements in a program when you cannot easily tell where statementsbegin and end.Automatic Indentation
Another feature you can use when Emacs is in C++ mode is automaticindentation. You can use this before or after the fact. In otherwords, you can press the<Tab>
key before you type aline of code for it to indent to the proper place. Or, you can pressthe<Tab>
key while on a line, to fix itsindentation after the fact.Look at the loop inNow, go to each line of the loop and presssum1.cpp
, whose indentation is messedup:<Tab>
, itshould fix the indentation for each line, producing something like:You'll want to explore the other features that Emacs gives you in C++mode.Don't forget to save your changes when you are done by using SaveBuffer from the Emacs Files menu. Shut down Emacs by choosingExit Emacs from the Emacs Files menu. - Using multiple buffers inside Emacs:While working on a program, we may need to edit some source code,compile and run it, edit other files and so on. There is no needto start up and shut down Emacs each time we need to go back to the UNIXprompt or need to load a different file. Instead, using features ofUNIX and Emacs, we can leave Emacs up during our entire login session.First, we should take care to start up Emacs as:By using the ampersand (Note:Use
&
) at the end of thecommand, we'll get a UNIX prompt back right away, where we can typemore UNIX commands. Without the&
, the UNIX windowwaits for Emacs to exit before it will let us type more commands.&
at the end of any UNIX command that brings up its ownwindow and runs for a while.Suppose, we need to work with 2 files in Emacs, likesum1.cpp
andavg1.cpp
.(If you don't already have those files, download them into your currentdirectory now.)Now, let's load them into Emacs. Choose Open File... from theEmacs Files menu. At the bottom of the Emacs screen, it willprompt your for a file name:(where curr-dir is your current directory), type in the name ofthe file, giving:and press<Return>
. It should load the file intothe window.Now, let's split the Emacs window into 2 by choosing SplitWindow from the Emacs Files menu.Note that Emacs has split its window into 2 parts (or subwindows),each with the same file in it:Then, click in the lower window, and use the Open File...command (again, from the Files menu) to loadavg1.cpp
in the lower window.We can now click in the 2 subwindows to edit either one.Suppose we want to spent some time onsum1.cpp
, so we wantit to be the only window. We can do so by clicking in the upper window(wheresum1.cpp
is loaded) and the choosing One Windowfrom the Emacs Files menu.Finally, suppose we needavg1.cpp
back. Just click in theEmacs subwindow where you want it (there is only one now) and chooseavg1.cpp from the Buffers menu.Until we exit Emacs, we can switch between loaded files in this way. - Compiling inside Emacs:Not only can we compile programs at the UNIX prompt, but we can alsocompile them inside of Emacs. Compiling programs while inside Emacsmakes it very easy to go through the source code and look at whatcaused the errors and warnings reported by the compiler.For this example, we'll use a program that sums numbers,
sum1.cpp
.(If you don't already have that file, download it into your currentdirectory now.)If you are not already running Emacs, start it up:To compile while in Emacs, use the Emacs command:<Esc> x compile
At the bottom of the Emacs screen, it will ask you what UNIX commandto use for compilation. The default ismake -k
(make is a separate topic), so erase that and type whatevercompilation command you'd use at the UNIX prompt:Note that we toldAside:The code you are compiling should be in the same directory as the one inwhich you started up Emacs.g++
to name the executabletotal
.Note that Emacs has split its window into 2 parts (or subwindows),one of which contains the output of the attempt to compile the program:This compilation window contains all the usual output fromthe compilation process, including some compiler warnings/errors:We could search through the source code in an another Emacs subwindow toexamine and fix the errors, but there is an easier way:- Click in the compilation window (this is the one where thecompilation errors appeared). Note that a new menu appears, labeledCompile.
- Pull down the menu to look at its contents...Remember, Emacs has special modes depending on what it isdoing. This menu appears when you are in a compilation window.
- Choose
First Error from theCompile menu. Note that it automatically loads thesource code containing the error in the other Emacs subwindow (if itwasn't already there) and places the cursor on the right line.
What is the error? Fix it. - Now, click in the compilation window again to get theCompile menu back and choose
NextError from the menu this time.
Once it is at the next error, determine the error and fixit. - Since we fixed the first 2 errors, let's recompile the program and seeif what we fixed was causing the other error messages (i.e., errorsoften cause other errors).Bring up the Compile menu again, and chooseRecompile. Note that Emacs knows that you should savethe file you are about to recompile, and asks you to do so (chooseYes). Emacs will use the same command we typed originally torecompile.
- If you corrected the first 2 errors properly, the program shouldrecompile successfully.
Since we are done with the compilation window for now, let's get rid ofit. Click in the Emacs subwindow that has the source codesum1.cpp
and then chooseOne Window from the Emacs Files menu. We can bring back thecompilation window when needed (during this session withEmacs), by choosing it from the Buffers menu.Go to the UNIX prompt and run the executable total that wascreated if you like. - Debugging inside Emacs:For this example, we'll use a program that calculates an average,
avg1.cpp
.(If you don't already have that file, download it into your currentdirectory now.)If you are not already running Emacs, start it up:Then, compile the program under Emacs. Remember to:- Use
<Esc> x compile - Erase the default,
make -k
- Type in the proper compilation command (we'll give it an executablename other than
a.out
):Note: We've added a new flag -g. If you want to beable to debug a program, you'll have to add this -g option whenyou compile it.
The program should compile without any errors or warnings.Since we will be running the executable several times to debug it,download this data fileAside:The data file tells the program that there are 4 numbers toaverage, which are:numdata
.10
,20
,30
,and40
.Now, run the executable on the data file from the UNIX prompt:You'll notice that the program produces a nice Segmentationfault. This calls for using the debugger, Gdb! We could run Gdbfrom the UNIX prompt, but it is more useful to run it under Emacs.Running Gdb under Emacs:
Let's start up Gdb under Emacs:- Select the compilation window by clicking in it(we'll reuse this window for Gdb)
- Type
<Esc> x gdb - When it prompts you for the command to use to start Gdb:complete the command with the name of the executable, as in:
avg
under Gdb.If we just wanted to run the executable without using a data file(i.e., the user types in needed input), we could just type 'run'.However, since we want to use our data file,numdata
, weshould use input redirection, as in:The output of the program is shown, just like when the program was runat the UNIX prompt. In fact, we still get the Segmentationfault. What's really nice about Gdb, however, is that it gives usadditional information, telling us where the Segmentationfault occurred.What may happen, as in this case, is that the Seg fault occurs not incode you wrote, but in some library you used. (Note that it may haveloaded that nasty library code in the other Emacs subwindow.)Examining the calling chain:
Although the Seg fault occurred in library code, it was most likelystill caused by an error on your part. We need to know how theprogram got to that library function. To display the callingchain, i.e., the sequence of function calls that lead to thecurrent point in the program, use:Aha! Now we see that the problem was caused by the code at line 44 inavg1.cpp
(i.e., inmain()
).We could load the source code into Emacs and go to line 44 (use<Esc> x goto-line perhaps) and see what is there.Instead, however, we can go back up the calling chain until weare in our code. To do so, use the Gdb up command until we'reinmain()
:Conveniently, Emacs has loaded the source code (avg1.cpp
)in the other subwindow and is pointing (with an arrow,=>
)to the offending line, i.e., where the program stopped because of theSeg fault.Since the line contains an array access, perhaps the problem is anout of range array index? We can display the value of index variablei
by using the Gdb print command:It's now obvious thati
has an incorrect value. Findthe source of this problem and then fix it.With that error fixed, we should recompile. While the cursor is in thesource code subwindow, call up the compilation window...Do thisby bringing back its buffer, i.e., choose the *compilation*buffer from the Buffers menu:Aside: Note the *gud-avg* listing forgdb
running onavg
.After bringing up the compilation window, chooseRecompile from the Compile menu. Note that it willprompt you to save the edited source code, which you want to do. Makesure that everything compiles ok.Now, let's debug this new version of the executable. To get back toGdb, click in Emacs' gdb window after the (gdb) prompt:We need to re-run the executable; however, we don't want to have totype the redirection stuff every time. So, first do:This tells Gdb to use '< numdata' as the argument to the runcommand.Then, run the program:It will ask you if you want to restart the program (remember, we werealready running it and it Seg faulted). Just say y.Notice that Gdb automatically notices that there is a new version(i.e., we just recompiled it) of the executable. Once it loads in thenew version of the executable, it will run it on the data file.What's nice is that the Segmentation fault is now gone,and the 'Program exited normally.' However, we now seem to havea logic error since the average shouldn't be zero.Stopping the program while it is running:
A main feature of a debugger is that we can tell it to stop a programwhile it is running so that we can examine variables, etc.The first thing we might check to find this error is to make sure thenumbers are read into our program properly.Bring the source code back:- Click in the compilation window
- Choose avg1.cpp from the Buffers menu
Now scroll to the line just after when the numbers are read in,i.e., go to:Note this statement's line number (listed at the bottom of the Emacssubwindow with the source code). It should be line 47, but might besomething else if you added blank lines, etc. This line would be agood place to stop the program and then check all the numbers. We cantell Gdb to stop the program at this line by setting abreakpoint.Go back to the Gdb window (i.e., click in it after the prompt) andtype:Aside: Gdb assumes the line number refers to a line in thesource code file from which it last performed a statement. Since,right now, our executable is only made up of one source code file, thisdoesn't matter.However, if you needed to refer to a line in another source code file,you'd use the form 'filename:line' as in:Now, re-run the program:The program should stop at the designated line. Also, notice thatEmacs is following the source code (with an arrow,Note: When Gdb stops at a line, it hasn't performed that lineyet. For example, line 47 has not been done in this case.=>
)in the other subwindow.Now, we can display the elements of thenumbers
array with theprint command (you can use print to display the result ofany expression). Do:These seem to be ok, so we won't really need this breakpoint (noticeit's breakpoint #1) anymore. Remove it with:The next place we might look is in the function that calculates theaverage,Aside: When setting a breakpoint for a member function (method)of a class, you'll need to specify the function in the form'Class::member-function-name' as in:avgNumbers()
. To set a breakpoint that will stopthe program when it gets in that function, we can do:Continuing program once it has been stopped:
What we want to do now is to have the program continue to rununtil it hits another breakpoint. Do:The program continued and then should have stopped inNote:It displays the values of the parameters of the functionavgNumbers()
like we asked it to.avgNumbers()
in which it stopped. Sincenumbers
is an array, it displays its address.As usual, it is following the code in the source code window.We may want to see what happens after it performs the statement:To just perform this statement and have the program stop again, use thenext command. Then, we can examine the sum with print:A sum of zero is clearly wrong. This implies that functionsumNumbers()
is probably not calculating the sum correctly.Let's explore this theory...Start by re-running the program under Gdb:We again stop at our breakpoint inavgNumbers()
. This time,instead of using next to perform the call tosumNumbers()
, let's use step, so that we stepinto that function:Now that we are insumNumbers()
, we see that the variablewe'll want to examine issum
. Rather than usingprint to view its value as we go through the function, we canuse the display command:which will display the value of that variable every time the programstops.We'll want to go through the loop statement by statement and see howsum
changes. First, go to the loop with:Now, start the loop with:Since this is a for loop, it has done what part(s) of the loop?Now, let's do the assignment statement in the loop body:Hmmm...The sum did not change (we want it to!)Let's continue the loop for another iteration:What part(s) of the loop did it just do?Do the assignment in the body of the loop one more time:Again,sum
does not change. Aha! We think we know whatis causing the error.Changing variables while program is running:
What we can do now is correct the value ofsum
and see ifthe rest of the program doesn't mess it up. Let's give thesum
variable the value it should have:(i.e.,10+20+30+40
).And, we'll let the program continue to run:You can see that we get the correct average, based on the value wejust gavesum
. So, the error insumNumbers()
is probably the only place needing to be fixed.Fix the problem, recompile, and see if the program runs properly now.Getting help in Gdb:
Note that the Gdb commands we've learned (plus others) are described bythe Gdb help command. Use:to look up categories of help topics. Use help category,e.g.:to list the commands in that category. And, use help command,e.g.:to look up a specific command.The End:
Finally, don't forget to quit the debugger:before exiting Emacs. - Use
Copyright © 1993-2000 byRobert I. Pitts<rip at bu dot edu>.All Rights Reserved.
You can use the Desktop library to save the state of Emacs from onesession to another. Saving the state means that Emacs starts up withthe same set of buffers, major modes, buffer positions, and so on thatthe previous Emacs session had.
To use Desktop, you should use the Customization buffer (Section 32.2.2) to set desktop-enable to a non-nil value,or add these lines at the end of your .emacs file:
The first time you save the state of the Emacs session, you must do itmanually, with the command M-x desktop-save. Once you have donethat, exiting Emacs will save the state again--not only the presentEmacs session, but also subsequent sessions. You can also save thestate at any time, without exiting Emacs, by typing M-xdesktop-save again.
In order for Emacs to recover the state from a previous session, youmust start it with the same current directory as you used when youstarted the previous session. This is because desktop-read looksin the current directory for the file to read. This means that you canhave separate saved sessions in different directories; the directory inwhich you start Emacs will control which saved session to use.
The variable desktop-files-not-to-save controls which files areexcluded from state saving. Its value is a regular expression thatmatches the files to exclude. By default, remote (ftp-accessed) filesare excluded; this is because visiting them again in the subsequentsession would be slow. If you want to include these files in statesaving, set desktop-files-not-to-save to '^$'.Section 16.12.
The Saveplace library provides a simpler feature that records yourposition in each file when you kill its buffer (or kill Emacs), andjumps to the same position when you visit the file again (even inanother Emacs session). Use M-x toggle-save-place to turn onplace-saving in a given file. Customize the option save-placeto turn it on for all files in each session.