Avoid temporary construction and potential for corrupted data access.
[oota-llvm.git] / tools / llvm-db / Commands.cpp
1 //===-- Commands.cpp - Implement various commands for the CLI -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements many builtin user commands.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "CLIDebugger.h"
15 #include "CLICommand.h"
16 #include "llvm/Debugger/ProgramInfo.h"
17 #include "llvm/Debugger/RuntimeInfo.h"
18 #include "llvm/Debugger/SourceLanguage.h"
19 #include "llvm/Debugger/SourceFile.h"
20 #include "llvm/Debugger/InferiorProcess.h"
21 #include "llvm/Support/FileUtilities.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include <iostream>
24 using namespace llvm;
25
26 /// getCurrentLanguage - Return the current source language that the user is
27 /// playing around with.  This is aquired from the current stack frame of a
28 /// running program if one exists, but this value can be explicitly set by the
29 /// user as well.
30 const SourceLanguage &CLIDebugger::getCurrentLanguage() const {
31   // If the user explicitly switched languages with 'set language', use what
32   // they asked for.
33   if (CurrentLanguage) {
34     return *CurrentLanguage;
35   } else if (Dbg.isProgramRunning()) {
36     // Otherwise, if the program is running, infer the current language from it.
37     const GlobalVariable *FuncDesc =
38       getRuntimeInfo().getCurrentFrame().getFunctionDesc();
39     return getProgramInfo().getFunction(FuncDesc).getSourceFile().getLanguage();
40   } else {
41     // Otherwise, default to C like GDB apparently does.
42     return SourceLanguage::getCFamilyInstance();
43   }
44 }
45
46 /// startProgramRunning - If the program has been updated, reload it, then
47 /// start executing the program.
48 void CLIDebugger::startProgramRunning() {
49   eliminateRunInfo();
50
51   // If the program has been modified, reload it!
52   sys::PathWithStatus Program(Dbg.getProgramPath());
53   std::string Err;
54   const sys::FileStatus *Status = Program.getFileStatus(false, &Err);
55   if (!Status)
56     throw Err;
57   if (TheProgramInfo->getProgramTimeStamp() != Status->getTimestamp()) {
58     std::cout << "'" << Program << "' has changed; re-reading program.\n";
59
60     // Unload an existing program.  This kills the program if necessary.
61     Dbg.unloadProgram();
62     delete TheProgramInfo;
63     TheProgramInfo = 0;
64     CurrentFile = 0;
65
66     Dbg.loadProgram(Program.toString());
67     TheProgramInfo = new ProgramInfo(Dbg.getProgram());
68   }
69
70   std::cout << "Starting program: " << Dbg.getProgramPath() << "\n";
71   Dbg.createProgram();
72
73   // There was no current frame.
74   LastCurrentFrame = 0;
75 }
76
77 /// printSourceLine - Print the specified line of the current source file.
78 /// If the specified line is invalid (the source file could not be loaded or
79 /// the line number is out of range), don't print anything, but return true.
80 bool CLIDebugger::printSourceLine(unsigned LineNo) {
81   assert(CurrentFile && "There is no current source file to print!");
82   const char *LineStart, *LineEnd;
83   CurrentFile->getSourceLine(LineNo-1, LineStart, LineEnd);
84   if (LineStart == 0) return true;
85   std::cout << LineNo;
86
87   // If this is the line the program is currently stopped at, print a marker.
88   if (Dbg.isProgramRunning()) {
89     unsigned CurLineNo, CurColNo;
90     const SourceFileInfo *CurSFI;
91     getRuntimeInfo().getCurrentFrame().getSourceLocation(CurLineNo, CurColNo,
92                                                          CurSFI);
93
94     if (CurLineNo == LineNo && CurrentFile == &CurSFI->getSourceText())
95       std::cout << " ->";
96   }
97
98   std::cout << "\t" << std::string(LineStart, LineEnd) << "\n";
99   return false;
100 }
101
102 /// printProgramLocation - Print a line of the place where the current stack
103 /// frame has stopped and the source line it is on.
104 ///
105 void CLIDebugger::printProgramLocation(bool PrintLocation) {
106   assert(Dbg.isProgramLoaded() && Dbg.isProgramRunning() &&
107          "Error program is not loaded and running!");
108
109   // Figure out where the program stopped...
110   StackFrame &SF = getRuntimeInfo().getCurrentFrame();
111   unsigned LineNo, ColNo;
112   const SourceFileInfo *FileDesc;
113   SF.getSourceLocation(LineNo, ColNo, FileDesc);
114
115   // If requested, print out some program information about WHERE we are.
116   if (PrintLocation) {
117     // FIXME: print the current function arguments
118     if (const GlobalVariable *FuncDesc = SF.getFunctionDesc())
119       std::cout << getProgramInfo().getFunction(FuncDesc).getSymbolicName();
120     else
121       std::cout << "<unknown function>";
122
123     CurrentFile = &FileDesc->getSourceText();
124
125     std::cout << " at " << CurrentFile->getFilename() << ":" << LineNo;
126     if (ColNo) std::cout << ":" << ColNo;
127     std::cout << "\n";
128   }
129
130   if (printSourceLine(LineNo))
131     std::cout << "<could not load source file>\n";
132   else {
133     LineListedStart = LineNo-ListSize/2+1;
134     if ((int)LineListedStart < 1) LineListedStart = 1;
135     LineListedEnd = LineListedStart+1;
136   }
137 }
138
139 /// eliminateRunInfo - We are about to run the program.  Forget any state
140 /// about how the program used to be stopped.
141 void CLIDebugger::eliminateRunInfo() {
142   delete TheRuntimeInfo;
143   TheRuntimeInfo = 0;
144 }
145
146 /// programStoppedSuccessfully - This method updates internal data
147 /// structures to reflect the fact that the program just executed a while,
148 /// and has successfully stopped.
149 void CLIDebugger::programStoppedSuccessfully() {
150   assert(TheRuntimeInfo==0 && "Someone forgot to release the old RuntimeInfo!");
151
152   TheRuntimeInfo = new RuntimeInfo(TheProgramInfo, Dbg.getRunningProcess());
153
154   // FIXME: if there are any breakpoints at the current location, print them as
155   // well.
156
157   // Since the program as successfully stopped, print its location.
158   void *CurrentFrame = getRuntimeInfo().getCurrentFrame().getFrameID();
159   printProgramLocation(CurrentFrame != LastCurrentFrame);
160   LastCurrentFrame = CurrentFrame;
161 }
162
163
164
165 /// getUnsignedIntegerOption - Get an unsigned integer number from the Val
166 /// string.  Check to make sure that the string contains an unsigned integer
167 /// token, and if not, throw an exception.  If isOnlyOption is set, also throw
168 /// an exception if there is extra junk at the end of the string.
169 static unsigned getUnsignedIntegerOption(const char *Msg, std::string &Val,
170                                          bool isOnlyOption = true) {
171   std::string Tok = getToken(Val);
172   if (Tok.empty() || (isOnlyOption && !getToken(Val).empty()))
173     throw std::string(Msg) + " expects an unsigned integer argument.";
174
175   char *EndPtr;
176   unsigned Result = strtoul(Tok.c_str(), &EndPtr, 0);
177   if (EndPtr != Tok.c_str()+Tok.size())
178     throw std::string(Msg) + " expects an unsigned integer argument.";
179
180   return Result;
181 }
182
183 /// getOptionalUnsignedIntegerOption - This method is just like
184 /// getUnsignedIntegerOption, but if the argument value is not specified, a
185 /// default is returned instead of causing an error.
186 static unsigned
187 getOptionalUnsignedIntegerOption(const char *Msg, unsigned Default,
188                                  std::string &Val, bool isOnlyOption = true) {
189   // Check to see if the value was specified...
190   std::string TokVal = getToken(Val);
191   if (TokVal.empty()) return Default;
192
193   // If it was specified, add it back to the value we are parsing...
194   Val = TokVal+Val;
195
196   // And parse normally.
197   return getUnsignedIntegerOption(Msg, Val, isOnlyOption);
198 }
199
200
201 /// parseProgramOptions - This method parses the Options string and loads it
202 /// as options to be passed to the program.  This is used by the run command
203 /// and by 'set args'.
204 void CLIDebugger::parseProgramOptions(std::string &Options) {
205   // FIXME: tokenizing by whitespace is clearly incorrect.  Instead we should
206   // honor quotes and other things that a shell would.  Also in the future we
207   // should support redirection of standard IO.
208
209   std::vector<std::string> Arguments;
210   for (std::string A = getToken(Options); !A.empty(); A = getToken(Options))
211     Arguments.push_back(A);
212   Dbg.setProgramArguments(Arguments.begin(), Arguments.end());
213 }
214
215
216 //===----------------------------------------------------------------------===//
217 //                   Program startup and shutdown options
218 //===----------------------------------------------------------------------===//
219
220
221 /// file command - If the user specifies an option, search the PATH for the
222 /// specified program/bytecode file and load it.  If the user does not specify
223 /// an option, unload the current program.
224 void CLIDebugger::fileCommand(std::string &Options) {
225   std::string Prog = getToken(Options);
226   if (!getToken(Options).empty())
227     throw "file command takes at most one argument.";
228
229   // Check to make sure the user knows what they are doing
230   if (Dbg.isProgramRunning() &&
231       !askYesNo("A program is already loaded.  Kill it?"))
232     return;
233
234   // Unload an existing program.  This kills the program if necessary.
235   eliminateRunInfo();
236   delete TheProgramInfo;
237   TheProgramInfo = 0;
238   Dbg.unloadProgram();
239   CurrentFile = 0;
240
241   // If requested, start the new program.
242   if (Prog.empty()) {
243     std::cout << "Unloaded program.\n";
244   } else {
245     std::cout << "Loading program... " << std::flush;
246     Dbg.loadProgram(Prog);
247     assert(Dbg.isProgramLoaded() &&
248            "loadProgram succeeded, but not program loaded!");
249     TheProgramInfo = new ProgramInfo(Dbg.getProgram());
250     std::cout << "successfully loaded '" << Dbg.getProgramPath() << "'!\n";
251   }
252 }
253
254
255 void CLIDebugger::createCommand(std::string &Options) {
256   if (!getToken(Options).empty())
257     throw "create command does not take any arguments.";
258   if (!Dbg.isProgramLoaded()) throw "No program loaded.";
259   if (Dbg.isProgramRunning() &&
260       !askYesNo("The program is already running.  Restart from the beginning?"))
261     return;
262
263   // Start the program running.
264   startProgramRunning();
265
266   // The program stopped!
267   programStoppedSuccessfully();
268 }
269
270 void CLIDebugger::killCommand(std::string &Options) {
271   if (!getToken(Options).empty())
272     throw "kill command does not take any arguments.";
273   if (!Dbg.isProgramRunning())
274     throw "No program is currently being run.";
275
276   if (askYesNo("Kill the program being debugged?"))
277     Dbg.killProgram();
278   eliminateRunInfo();
279 }
280
281 void CLIDebugger::quitCommand(std::string &Options) {
282   if (!getToken(Options).empty())
283     throw "quit command does not take any arguments.";
284
285   if (Dbg.isProgramRunning() &&
286       !askYesNo("The program is running.  Exit anyway?"))
287     return;
288
289   // Throw exception to get out of the user-input loop.
290   throw 0;
291 }
292
293
294 //===----------------------------------------------------------------------===//
295 //                        Program execution commands
296 //===----------------------------------------------------------------------===//
297
298 void CLIDebugger::runCommand(std::string &Options) {
299   if (!Dbg.isProgramLoaded()) throw "No program loaded.";
300   if (Dbg.isProgramRunning() &&
301       !askYesNo("The program is already running.  Restart from the beginning?"))
302     return;
303
304   // Parse all of the options to the run command, which specify program
305   // arguments to run with.
306   parseProgramOptions(Options);
307
308   eliminateRunInfo();
309
310   // Start the program running.
311   startProgramRunning();
312
313   // Start the program running...
314   Options = "";
315   contCommand(Options);
316 }
317
318 void CLIDebugger::contCommand(std::string &Options) {
319   if (!getToken(Options).empty()) throw "cont argument not supported yet.";
320   if (!Dbg.isProgramRunning()) throw "Program is not running.";
321
322   eliminateRunInfo();
323
324   Dbg.contProgram();
325
326   // The program stopped!
327   programStoppedSuccessfully();
328 }
329
330 void CLIDebugger::stepCommand(std::string &Options) {
331   if (!Dbg.isProgramRunning()) throw "Program is not running.";
332
333   // Figure out how many times to step.
334   unsigned Amount =
335     getOptionalUnsignedIntegerOption("'step' command", 1, Options);
336
337   eliminateRunInfo();
338
339   // Step the specified number of times.
340   for (; Amount; --Amount)
341     Dbg.stepProgram();
342
343   // The program stopped!
344   programStoppedSuccessfully();
345 }
346
347 void CLIDebugger::nextCommand(std::string &Options) {
348   if (!Dbg.isProgramRunning()) throw "Program is not running.";
349   unsigned Amount =
350     getOptionalUnsignedIntegerOption("'next' command", 1, Options);
351
352   eliminateRunInfo();
353
354   for (; Amount; --Amount)
355     Dbg.nextProgram();
356
357   // The program stopped!
358   programStoppedSuccessfully();
359 }
360
361 void CLIDebugger::finishCommand(std::string &Options) {
362   if (!getToken(Options).empty())
363     throw "finish command does not take any arguments.";
364   if (!Dbg.isProgramRunning()) throw "Program is not running.";
365
366   // Figure out where we are exactly.  If the user requests that we return from
367   // a frame that is not the top frame, make sure we get it.
368   void *CurrentFrame = getRuntimeInfo().getCurrentFrame().getFrameID();
369
370   eliminateRunInfo();
371
372   Dbg.finishProgram(CurrentFrame);
373
374   // The program stopped!
375   programStoppedSuccessfully();
376 }
377
378 //===----------------------------------------------------------------------===//
379 //                           Stack frame commands
380 //===----------------------------------------------------------------------===//
381
382 void CLIDebugger::backtraceCommand(std::string &Options) {
383   // Accepts "full", n, -n
384   if (!getToken(Options).empty())
385     throw "FIXME: bt command argument not implemented yet!";
386
387   RuntimeInfo &RI = getRuntimeInfo();
388   ProgramInfo &PI = getProgramInfo();
389
390   try {
391     for (unsigned i = 0; ; ++i) {
392       StackFrame &SF = RI.getStackFrame(i);
393       std::cout << "#" << i;
394       if (i == RI.getCurrentFrameIdx())
395         std::cout << " ->";
396       std::cout << "\t" << SF.getFrameID() << " in ";
397       if (const GlobalVariable *G = SF.getFunctionDesc())
398         std::cout << PI.getFunction(G).getSymbolicName();
399
400       unsigned LineNo, ColNo;
401       const SourceFileInfo *SFI;
402       SF.getSourceLocation(LineNo, ColNo, SFI);
403       if (!SFI->getBaseName().empty()) {
404         std::cout << " at " << SFI->getBaseName();
405         if (LineNo) {
406           std::cout << ":" << LineNo;
407           if (ColNo)
408             std::cout << ":" << ColNo;
409         }
410       }
411
412       // FIXME: when we support shared libraries, we should print ' from foo.so'
413       // if the stack frame is from a different object than the current one.
414
415       std::cout << "\n";
416     }
417   } catch (...) {
418     // Stop automatically when we run off the bottom of the stack.
419   }
420 }
421
422 void CLIDebugger::upCommand(std::string &Options) {
423   unsigned Num =
424     getOptionalUnsignedIntegerOption("'up' command", 1, Options);
425
426   RuntimeInfo &RI = getRuntimeInfo();
427   unsigned CurFrame = RI.getCurrentFrameIdx();
428
429   // Check to see if we go can up the specified number of frames.
430   try {
431     RI.getStackFrame(CurFrame+Num);
432   } catch (...) {
433     if (Num == 1)
434       throw "Initial frame selected; you cannot go up.";
435     else
436       throw "Cannot go up " + utostr(Num) + " frames!";
437   }
438
439   RI.setCurrentFrameIdx(CurFrame+Num);
440   printProgramLocation();
441 }
442
443 void CLIDebugger::downCommand(std::string &Options) {
444   unsigned Num =
445     getOptionalUnsignedIntegerOption("'down' command", 1, Options);
446
447   RuntimeInfo &RI = getRuntimeInfo();
448   unsigned CurFrame = RI.getCurrentFrameIdx();
449
450   // Check to see if we can go up the specified number of frames.
451   if (CurFrame < Num)
452     if (Num == 1)
453       throw "Bottom (i.e., innermost) frame selected; you cannot go down.";
454     else
455       throw "Cannot go down " + utostr(Num) + " frames!";
456
457   RI.setCurrentFrameIdx(CurFrame-Num);
458   printProgramLocation();
459 }
460
461 void CLIDebugger::frameCommand(std::string &Options) {
462   RuntimeInfo &RI = getRuntimeInfo();
463   unsigned CurFrame = RI.getCurrentFrameIdx();
464
465   unsigned Num =
466     getOptionalUnsignedIntegerOption("'frame' command", CurFrame, Options);
467
468   // Check to see if we go to the specified frame.
469   RI.getStackFrame(Num);
470
471   RI.setCurrentFrameIdx(Num);
472   printProgramLocation();
473 }
474
475
476 //===----------------------------------------------------------------------===//
477 //                        Breakpoint related commands
478 //===----------------------------------------------------------------------===//
479
480 void CLIDebugger::breakCommand(std::string &Options) {
481   // Figure out where the user wants a breakpoint.
482   const SourceFile *File;
483   unsigned LineNo;
484
485   // Check to see if the user specified a line specifier.
486   std::string Option = getToken(Options);  // strip whitespace
487   if (!Option.empty()) {
488     Options = Option + Options;  // reconstruct string
489
490     // Parse the line specifier.
491     parseLineSpec(Options, File, LineNo);
492   } else {
493     // Build a line specifier for the current stack frame.
494     throw "FIXME: breaking at the current location is not implemented yet!";
495   }
496
497   if (!File) File = CurrentFile;
498   if (File == 0)
499     throw "Unknown file to place breakpoint!";
500
501   std::cerr << "Break: " << File->getFilename() << ":" << LineNo << "\n";
502
503   throw "breakpoints not implemented yet!";
504 }
505
506 //===----------------------------------------------------------------------===//
507 //                          Miscellaneous commands
508 //===----------------------------------------------------------------------===//
509
510 void CLIDebugger::infoCommand(std::string &Options) {
511   std::string What = getToken(Options);
512
513   if (What.empty() || !getToken(Options).empty()){
514     std::string infoStr("info");
515     helpCommand(infoStr);
516     return;
517   }
518
519   if (What == "frame") {
520   } else if (What == "functions") {
521     const std::map<const GlobalVariable*, SourceFunctionInfo*> &Functions
522       = getProgramInfo().getSourceFunctions();
523     std::cout << "All defined functions:\n";
524     // FIXME: GDB groups these by source file.  We could do that I guess.
525     for (std::map<const GlobalVariable*, SourceFunctionInfo*>::const_iterator
526            I = Functions.begin(), E = Functions.end(); I != E; ++I) {
527       std::cout << I->second->getSymbolicName() << "\n";
528     }
529
530   } else if (What == "source") {
531     if (CurrentFile == 0)
532       throw "No current source file.";
533
534     // Get the SourceFile information for the current file.
535     const SourceFileInfo &SF =
536       getProgramInfo().getSourceFile(CurrentFile->getDescriptor());
537
538     std::cout << "Current source file is: " << SF.getBaseName() << "\n"
539               << "Compilation directory is: " << SF.getDirectory() << "\n";
540     if (unsigned NL = CurrentFile->getNumLines())
541       std::cout << "Located in: " << CurrentFile->getFilename() << "\n"
542                 << "Contains " << NL << " lines\n";
543     else
544       std::cout << "Could not find source file.\n";
545     std::cout << "Source language is "
546               << SF.getLanguage().getSourceLanguageName() << "\n";
547
548   } else if (What == "sources") {
549     const std::map<const GlobalVariable*, SourceFileInfo*> &SourceFiles =
550       getProgramInfo().getSourceFiles();
551     std::cout << "Source files for the program:\n";
552     for (std::map<const GlobalVariable*, SourceFileInfo*>::const_iterator I =
553            SourceFiles.begin(), E = SourceFiles.end(); I != E;) {
554       std::cout << I->second->getDirectory() << "/"
555                 << I->second->getBaseName();
556       ++I;
557       if (I != E) std::cout << ", ";
558     }
559     std::cout << "\n";
560   } else if (What == "target") {
561     std::cout << Dbg.getRunningProcess().getStatus();
562   } else {
563     // See if this is something handled by the current language.
564     if (getCurrentLanguage().printInfo(What))
565       return;
566
567     throw "Unknown info command '" + What + "'.  Try 'help info'.";
568   }
569 }
570
571 /// parseLineSpec - Parses a line specifier, for use by the 'list' command.
572 /// If SourceFile is returned as a void pointer, then it was not specified.
573 /// If the line specifier is invalid, an exception is thrown.
574 void CLIDebugger::parseLineSpec(std::string &LineSpec,
575                                 const SourceFile *&SourceFile,
576                                 unsigned &LineNo) {
577   SourceFile = 0;
578   LineNo = 0;
579
580   // First, check to see if we have a : separator.
581   std::string FirstPart = getToken(LineSpec, ":");
582   std::string SecondPart = getToken(LineSpec, ":");
583   if (!getToken(LineSpec).empty()) throw "Malformed line specification!";
584
585   // If there is no second part, we must have either "function", "number",
586   // "+offset", or "-offset".
587   if (SecondPart.empty()) {
588     if (FirstPart.empty()) throw "Malformed line specification!";
589     if (FirstPart[0] == '+') {
590       FirstPart.erase(FirstPart.begin(), FirstPart.begin()+1);
591       // For +n, return LineListedEnd+n
592       LineNo = LineListedEnd +
593                getUnsignedIntegerOption("Line specifier '+'", FirstPart);
594
595     } else if (FirstPart[0] == '-') {
596       FirstPart.erase(FirstPart.begin(), FirstPart.begin()+1);
597       // For -n, return LineListedEnd-n
598       LineNo = LineListedEnd -
599                getUnsignedIntegerOption("Line specifier '-'", FirstPart);
600       if ((int)LineNo < 1) LineNo = 1;
601     } else if (FirstPart[0] == '*') {
602       throw "Address expressions not supported as source locations!";
603     } else {
604       // Ok, check to see if this is just a line number.
605       std::string Saved = FirstPart;
606       try {
607         LineNo = getUnsignedIntegerOption("", Saved);
608       } catch (...) {
609         // Ok, it's not a valid line number.  It must be a source-language
610         // entity name.
611         std::string Name = getToken(FirstPart);
612         if (!getToken(FirstPart).empty())
613           throw "Extra junk in line specifier after '" + Name + "'.";
614         SourceFunctionInfo *SFI =
615           getCurrentLanguage().lookupFunction(Name, getProgramInfo(),
616                                               TheRuntimeInfo);
617         if (SFI == 0)
618           throw "Unknown identifier '" + Name + "'.";
619
620         unsigned L, C;
621         SFI->getSourceLocation(L, C);
622         if (L == 0) throw "Could not locate '" + Name + "'!";
623         LineNo = L;
624         SourceFile = &SFI->getSourceFile().getSourceText();
625         return;
626       }
627     }
628
629   } else {
630     // Ok, this must be a filename qualified line number or function name.
631     // First, figure out the source filename.
632     std::string SourceFilename = getToken(FirstPart);
633     if (!getToken(FirstPart).empty())
634       throw "Invalid filename qualified source location!";
635
636     // Next, check to see if this is just a line number.
637     std::string Saved = SecondPart;
638     try {
639       LineNo = getUnsignedIntegerOption("", Saved);
640     } catch (...) {
641       // Ok, it's not a valid line number.  It must be a function name.
642       throw "FIXME: Filename qualified function names are not support "
643             "as line specifiers yet!";
644     }
645
646     // Ok, we got the line number.  Now check out the source file name to make
647     // sure it's all good.  If it is, return it.  If not, throw exception.
648     SourceFile =&getProgramInfo().getSourceFile(SourceFilename).getSourceText();
649   }
650 }
651
652 void CLIDebugger::listCommand(std::string &Options) {
653   if (!Dbg.isProgramLoaded())
654     throw "No program is loaded.  Use the 'file' command.";
655
656   // Handle "list foo," correctly, by returning " " as the second token
657   Options += " ";
658
659   std::string FirstLineSpec = getToken(Options, ",");
660   std::string SecondLineSpec = getToken(Options, ",");
661   if (!getToken(Options, ",").empty())
662     throw "list command only expects two source location specifiers!";
663
664   // StartLine, EndLine - The starting and ending line numbers to print.
665   unsigned StartLine = 0, EndLine = 0;
666
667   if (SecondLineSpec.empty()) {    // No second line specifier provided?
668     // Handle special forms like "", "+", "-", etc.
669     std::string TmpSpec = FirstLineSpec;
670     std::string Tok = getToken(TmpSpec);
671     if (getToken(TmpSpec).empty() && (Tok == "" || Tok == "+" || Tok == "-")) {
672       if (Tok == "+" || Tok == "") {
673         StartLine = LineListedEnd;
674         EndLine = StartLine + ListSize;
675       } else {
676         assert(Tok == "-");
677         StartLine = LineListedStart-ListSize;
678         EndLine = LineListedStart;
679         if ((int)StartLine <= 0) StartLine = 1;
680       }
681     } else {
682       // Must be a normal line specifier.
683       const SourceFile *File;
684       unsigned LineNo;
685       parseLineSpec(FirstLineSpec, File, LineNo);
686
687       // If the user only specified one file specifier, we should display
688       // ListSize lines centered at the specified line.
689       if (File != 0) CurrentFile = File;
690       StartLine = LineNo - (ListSize+1)/2;
691       if ((int)StartLine <= 0) StartLine = 1;
692       EndLine = StartLine + ListSize;
693     }
694
695   } else {
696     // Parse two line specifiers...
697     const SourceFile *StartFile, *EndFile;
698     unsigned StartLineNo, EndLineNo;
699     parseLineSpec(FirstLineSpec, StartFile, StartLineNo);
700     unsigned SavedLLE = LineListedEnd;
701     LineListedEnd = StartLineNo;
702     try {
703       parseLineSpec(SecondLineSpec, EndFile, EndLineNo);
704     } catch (...) {
705       LineListedEnd = SavedLLE;
706       throw;
707     }
708
709     // Inherit file specified by the first line spec if there was one.
710     if (EndFile == 0) EndFile = StartFile;
711
712     if (StartFile != EndFile)
713       throw "Start and end line specifiers are in different files!";
714     CurrentFile = StartFile;
715     StartLine = StartLineNo;
716     EndLine = EndLineNo+1;
717   }
718
719   assert((int)StartLine > 0 && (int)EndLine > 0 && StartLine <= EndLine &&
720          "Error reading line specifiers!");
721
722   // If there was no current file, and the user didn't specify one to list, we
723   // have an error.
724   if (CurrentFile == 0)
725     throw "There is no current file to list.";
726
727   // Remember for next time.
728   LineListedStart = StartLine;
729   LineListedEnd = StartLine;
730
731   for (unsigned LineNo = StartLine; LineNo != EndLine; ++LineNo) {
732     // Print the source line, unless it is invalid.
733     if (printSourceLine(LineNo))
734       break;
735     LineListedEnd = LineNo+1;
736   }
737
738   // If we didn't print any lines, find out why.
739   if (LineListedEnd == StartLine) {
740     // See if we can read line #0 from the file, if not, we couldn't load the
741     // file.
742     const char *LineStart, *LineEnd;
743     CurrentFile->getSourceLine(0, LineStart, LineEnd);
744     if (LineStart == 0)
745       throw "Could not load source file '" + CurrentFile->getFilename() + "'!";
746     else
747       std::cout << "<end of file>\n";
748   }
749 }
750
751 void CLIDebugger::setCommand(std::string &Options) {
752   std::string What = getToken(Options);
753
754   if (What.empty())
755     throw "set command expects at least two arguments.";
756   if (What == "args") {
757     parseProgramOptions(Options);
758   } else if (What == "language") {
759     std::string Lang = getToken(Options);
760     if (!getToken(Options).empty())
761       throw "set language expects one argument at most.";
762     if (Lang == "") {
763       std::cout << "The currently understood settings are:\n\n"
764                 << "local or auto  Automatic setting based on source file\n"
765                 << "c              Use the C language\n"
766                 << "c++            Use the C++ language\n"
767                 << "unknown        Use when source language is not supported\n";
768     } else if (Lang == "local" || Lang == "auto") {
769       CurrentLanguage = 0;
770     } else if (Lang == "c") {
771       CurrentLanguage = &SourceLanguage::getCFamilyInstance();
772     } else if (Lang == "c++") {
773       CurrentLanguage = &SourceLanguage::getCPlusPlusInstance();
774     } else if (Lang == "unknown") {
775       CurrentLanguage = &SourceLanguage::getUnknownLanguageInstance();
776     } else {
777       throw "Unknown language '" + Lang + "'.";
778     }
779
780   } else if (What == "listsize") {
781     ListSize = getUnsignedIntegerOption("'set prompt' command", Options);
782   } else if (What == "prompt") {
783     // Include any trailing whitespace or other tokens, but not leading
784     // whitespace.
785     Prompt = getToken(Options);  // Strip leading whitespace
786     Prompt += Options;           // Keep trailing whitespace or other stuff
787   } else {
788     // FIXME: Try to parse this as a source-language program expression.
789     throw "Don't know how to set '" + What + "'!";
790   }
791 }
792
793 void CLIDebugger::showCommand(std::string &Options) {
794   std::string What = getToken(Options);
795
796   if (What.empty() || !getToken(Options).empty())
797     throw "show command expects one argument.";
798
799   if (What == "args") {
800     std::cout << "Argument list to give program when started is \"";
801     // FIXME: This doesn't print stuff correctly if the arguments have spaces in
802     // them, but currently the only way to get that is to use the --args command
803     // line argument.  This should really handle escaping all hard characters as
804     // needed.
805     for (unsigned i = 0, e = Dbg.getNumProgramArguments(); i != e; ++i)
806       std::cout << (i ? " " : "") << Dbg.getProgramArgument(i);
807     std::cout << "\"\n";
808
809   } else if (What == "language") {
810     std::cout << "The current source language is '";
811     if (CurrentLanguage)
812       std::cout << CurrentLanguage->getSourceLanguageName();
813     else
814       std::cout << "auto; currently "
815                 << getCurrentLanguage().getSourceLanguageName();
816     std::cout << "'.\n";
817   } else if (What == "listsize") {
818     std::cout << "Number of source lines llvm-db will list by default is "
819               << ListSize << ".\n";
820   } else if (What == "prompt") {
821     std::cout << "llvm-db's prompt is \"" << Prompt << "\".\n";
822   } else {
823     throw "Unknown show command '" + What + "'.  Try 'help show'.";
824   }
825 }
826
827 void CLIDebugger::helpCommand(std::string &Options) {
828   // Print out all of the commands in the CommandTable
829   std::string Command = getToken(Options);
830   if (!getToken(Options).empty())
831     throw "help command takes at most one argument.";
832
833   // Getting detailed help on a particular command?
834   if (!Command.empty()) {
835     CLICommand *C = getCommand(Command);
836     std::cout << C->getShortHelp() << ".\n" << C->getLongHelp();
837
838     // If there are aliases for this option, print them out.
839     const std::vector<std::string> &Names = C->getOptionNames();
840     if (Names.size() > 1) {
841       std::cout << "The '" << Command << "' command is known as: '"
842                 << Names[0] << "'";
843       for (unsigned i = 1, e = Names.size(); i != e; ++i)
844         std::cout << ", '" << Names[i] << "'";
845       std::cout << "\n";
846     }
847
848   } else {
849     unsigned MaxSize = 0;
850     for (std::map<std::string, CLICommand*>::iterator I = CommandTable.begin(),
851            E = CommandTable.end(); I != E; ++I)
852       if (I->first.size() > MaxSize &&
853           I->first == I->second->getPrimaryOptionName())
854         MaxSize = I->first.size();
855
856     // Loop over all of the commands, printing the short help version
857     for (std::map<std::string, CLICommand*>::iterator I = CommandTable.begin(),
858            E = CommandTable.end(); I != E; ++I)
859       if (I->first == I->second->getPrimaryOptionName())
860         std::cout << I->first << std::string(MaxSize - I->first.size(), ' ')
861                   << " - " << I->second->getShortHelp() << "\n";
862   }
863 }