//===-- Commands.cpp - Implement various commands for the CLI -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements many builtin user commands.
//
//===----------------------------------------------------------------------===//

#include "CLIDebugger.h"
#include "CLICommand.h"
#include "llvm/Debugger/ProgramInfo.h"
#include "llvm/Debugger/RuntimeInfo.h"
#include "llvm/Debugger/SourceLanguage.h"
#include "llvm/Debugger/SourceFile.h"
#include "llvm/Debugger/InferiorProcess.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/ADT/StringExtras.h"
#include <iostream>
using namespace llvm;

/// getCurrentLanguage - Return the current source language that the user is
/// playing around with.  This is aquired from the current stack frame of a
/// running program if one exists, but this value can be explicitly set by the
/// user as well.
const SourceLanguage &CLIDebugger::getCurrentLanguage() const {
  // If the user explicitly switched languages with 'set language', use what
  // they asked for.
  if (CurrentLanguage) {
    return *CurrentLanguage;
  } else if (Dbg.isProgramRunning()) {
    // Otherwise, if the program is running, infer the current language from it.
    const GlobalVariable *FuncDesc =
      getRuntimeInfo().getCurrentFrame().getFunctionDesc();
    return getProgramInfo().getFunction(FuncDesc).getSourceFile().getLanguage();
  } else {
    // Otherwise, default to C like GDB apparently does.
    return SourceLanguage::getCFamilyInstance();
  }
}

/// startProgramRunning - If the program has been updated, reload it, then
/// start executing the program.
void CLIDebugger::startProgramRunning() {
  eliminateRunInfo();

  // If the program has been modified, reload it!
  sys::PathWithStatus Program(Dbg.getProgramPath());
  std::string Err;
  const sys::FileStatus *Status = Program.getFileStatus(false, &Err);
  if (!Status)
    throw Err;
  if (TheProgramInfo->getProgramTimeStamp() != Status->getTimestamp()) {
    std::cout << "'" << Program << "' has changed; re-reading program.\n";

    // Unload an existing program.  This kills the program if necessary.
    Dbg.unloadProgram();
    delete TheProgramInfo;
    TheProgramInfo = 0;
    CurrentFile = 0;

    Dbg.loadProgram(Program.toString());
    TheProgramInfo = new ProgramInfo(Dbg.getProgram());
  }

  std::cout << "Starting program: " << Dbg.getProgramPath() << "\n";
  Dbg.createProgram();

  // There was no current frame.
  LastCurrentFrame = 0;
}

/// printSourceLine - Print the specified line of the current source file.
/// If the specified line is invalid (the source file could not be loaded or
/// the line number is out of range), don't print anything, but return true.
bool CLIDebugger::printSourceLine(unsigned LineNo) {
  assert(CurrentFile && "There is no current source file to print!");
  const char *LineStart, *LineEnd;
  CurrentFile->getSourceLine(LineNo-1, LineStart, LineEnd);
  if (LineStart == 0) return true;
  std::cout << LineNo;

  // If this is the line the program is currently stopped at, print a marker.
  if (Dbg.isProgramRunning()) {
    unsigned CurLineNo, CurColNo;
    const SourceFileInfo *CurSFI;
    getRuntimeInfo().getCurrentFrame().getSourceLocation(CurLineNo, CurColNo,
                                                         CurSFI);

    if (CurLineNo == LineNo && CurrentFile == &CurSFI->getSourceText())
      std::cout << " ->";
  }

  std::cout << "\t" << std::string(LineStart, LineEnd) << "\n";
  return false;
}

/// printProgramLocation - Print a line of the place where the current stack
/// frame has stopped and the source line it is on.
///
void CLIDebugger::printProgramLocation(bool PrintLocation) {
  assert(Dbg.isProgramLoaded() && Dbg.isProgramRunning() &&
         "Error program is not loaded and running!");

  // Figure out where the program stopped...
  StackFrame &SF = getRuntimeInfo().getCurrentFrame();
  unsigned LineNo, ColNo;
  const SourceFileInfo *FileDesc;
  SF.getSourceLocation(LineNo, ColNo, FileDesc);

  // If requested, print out some program information about WHERE we are.
  if (PrintLocation) {
    // FIXME: print the current function arguments
    if (const GlobalVariable *FuncDesc = SF.getFunctionDesc())
      std::cout << getProgramInfo().getFunction(FuncDesc).getSymbolicName();
    else
      std::cout << "<unknown function>";

    CurrentFile = &FileDesc->getSourceText();

    std::cout << " at " << CurrentFile->getFilename() << ":" << LineNo;
    if (ColNo) std::cout << ":" << ColNo;
    std::cout << "\n";
  }

  if (printSourceLine(LineNo))
    std::cout << "<could not load source file>\n";
  else {
    LineListedStart = LineNo-ListSize/2+1;
    if ((int)LineListedStart < 1) LineListedStart = 1;
    LineListedEnd = LineListedStart+1;
  }
}

/// eliminateRunInfo - We are about to run the program.  Forget any state
/// about how the program used to be stopped.
void CLIDebugger::eliminateRunInfo() {
  delete TheRuntimeInfo;
  TheRuntimeInfo = 0;
}

/// programStoppedSuccessfully - This method updates internal data
/// structures to reflect the fact that the program just executed a while,
/// and has successfully stopped.
void CLIDebugger::programStoppedSuccessfully() {
  assert(TheRuntimeInfo==0 && "Someone forgot to release the old RuntimeInfo!");

  TheRuntimeInfo = new RuntimeInfo(TheProgramInfo, Dbg.getRunningProcess());

  // FIXME: if there are any breakpoints at the current location, print them as
  // well.

  // Since the program as successfully stopped, print its location.
  void *CurrentFrame = getRuntimeInfo().getCurrentFrame().getFrameID();
  printProgramLocation(CurrentFrame != LastCurrentFrame);
  LastCurrentFrame = CurrentFrame;
}



/// getUnsignedIntegerOption - Get an unsigned integer number from the Val
/// string.  Check to make sure that the string contains an unsigned integer
/// token, and if not, throw an exception.  If isOnlyOption is set, also throw
/// an exception if there is extra junk at the end of the string.
static unsigned getUnsignedIntegerOption(const char *Msg, std::string &Val,
                                         bool isOnlyOption = true) {
  std::string Tok = getToken(Val);
  if (Tok.empty() || (isOnlyOption && !getToken(Val).empty()))
    throw std::string(Msg) + " expects an unsigned integer argument.";

  char *EndPtr;
  unsigned Result = strtoul(Tok.c_str(), &EndPtr, 0);
  if (EndPtr != Tok.c_str()+Tok.size())
    throw std::string(Msg) + " expects an unsigned integer argument.";

  return Result;
}

/// getOptionalUnsignedIntegerOption - This method is just like
/// getUnsignedIntegerOption, but if the argument value is not specified, a
/// default is returned instead of causing an error.
static unsigned
getOptionalUnsignedIntegerOption(const char *Msg, unsigned Default,
                                 std::string &Val, bool isOnlyOption = true) {
  // Check to see if the value was specified...
  std::string TokVal = getToken(Val);
  if (TokVal.empty()) return Default;

  // If it was specified, add it back to the value we are parsing...
  Val = TokVal+Val;

  // And parse normally.
  return getUnsignedIntegerOption(Msg, Val, isOnlyOption);
}


/// parseProgramOptions - This method parses the Options string and loads it
/// as options to be passed to the program.  This is used by the run command
/// and by 'set args'.
void CLIDebugger::parseProgramOptions(std::string &Options) {
  // FIXME: tokenizing by whitespace is clearly incorrect.  Instead we should
  // honor quotes and other things that a shell would.  Also in the future we
  // should support redirection of standard IO.

  std::vector<std::string> Arguments;
  for (std::string A = getToken(Options); !A.empty(); A = getToken(Options))
    Arguments.push_back(A);
  Dbg.setProgramArguments(Arguments.begin(), Arguments.end());
}


//===----------------------------------------------------------------------===//
//                   Program startup and shutdown options
//===----------------------------------------------------------------------===//


/// file command - If the user specifies an option, search the PATH for the
/// specified program/bytecode file and load it.  If the user does not specify
/// an option, unload the current program.
void CLIDebugger::fileCommand(std::string &Options) {
  std::string Prog = getToken(Options);
  if (!getToken(Options).empty())
    throw "file command takes at most one argument.";

  // Check to make sure the user knows what they are doing
  if (Dbg.isProgramRunning() &&
      !askYesNo("A program is already loaded.  Kill it?"))
    return;

  // Unload an existing program.  This kills the program if necessary.
  eliminateRunInfo();
  delete TheProgramInfo;
  TheProgramInfo = 0;
  Dbg.unloadProgram();
  CurrentFile = 0;

  // If requested, start the new program.
  if (Prog.empty()) {
    std::cout << "Unloaded program.\n";
  } else {
    std::cout << "Loading program... " << std::flush;
    Dbg.loadProgram(Prog);
    assert(Dbg.isProgramLoaded() &&
           "loadProgram succeeded, but not program loaded!");
    TheProgramInfo = new ProgramInfo(Dbg.getProgram());
    std::cout << "successfully loaded '" << Dbg.getProgramPath() << "'!\n";
  }
}


void CLIDebugger::createCommand(std::string &Options) {
  if (!getToken(Options).empty())
    throw "create command does not take any arguments.";
  if (!Dbg.isProgramLoaded()) throw "No program loaded.";
  if (Dbg.isProgramRunning() &&
      !askYesNo("The program is already running.  Restart from the beginning?"))
    return;

  // Start the program running.
  startProgramRunning();

  // The program stopped!
  programStoppedSuccessfully();
}

void CLIDebugger::killCommand(std::string &Options) {
  if (!getToken(Options).empty())
    throw "kill command does not take any arguments.";
  if (!Dbg.isProgramRunning())
    throw "No program is currently being run.";

  if (askYesNo("Kill the program being debugged?"))
    Dbg.killProgram();
  eliminateRunInfo();
}

void CLIDebugger::quitCommand(std::string &Options) {
  if (!getToken(Options).empty())
    throw "quit command does not take any arguments.";

  if (Dbg.isProgramRunning() &&
      !askYesNo("The program is running.  Exit anyway?"))
    return;

  // Throw exception to get out of the user-input loop.
  throw 0;
}


//===----------------------------------------------------------------------===//
//                        Program execution commands
//===----------------------------------------------------------------------===//

void CLIDebugger::runCommand(std::string &Options) {
  if (!Dbg.isProgramLoaded()) throw "No program loaded.";
  if (Dbg.isProgramRunning() &&
      !askYesNo("The program is already running.  Restart from the beginning?"))
    return;

  // Parse all of the options to the run command, which specify program
  // arguments to run with.
  parseProgramOptions(Options);

  eliminateRunInfo();

  // Start the program running.
  startProgramRunning();

  // Start the program running...
  Options = "";
  contCommand(Options);
}

void CLIDebugger::contCommand(std::string &Options) {
  if (!getToken(Options).empty()) throw "cont argument not supported yet.";
  if (!Dbg.isProgramRunning()) throw "Program is not running.";

  eliminateRunInfo();

  Dbg.contProgram();

  // The program stopped!
  programStoppedSuccessfully();
}

void CLIDebugger::stepCommand(std::string &Options) {
  if (!Dbg.isProgramRunning()) throw "Program is not running.";

  // Figure out how many times to step.
  unsigned Amount =
    getOptionalUnsignedIntegerOption("'step' command", 1, Options);

  eliminateRunInfo();

  // Step the specified number of times.
  for (; Amount; --Amount)
    Dbg.stepProgram();

  // The program stopped!
  programStoppedSuccessfully();
}

void CLIDebugger::nextCommand(std::string &Options) {
  if (!Dbg.isProgramRunning()) throw "Program is not running.";
  unsigned Amount =
    getOptionalUnsignedIntegerOption("'next' command", 1, Options);

  eliminateRunInfo();

  for (; Amount; --Amount)
    Dbg.nextProgram();

  // The program stopped!
  programStoppedSuccessfully();
}

void CLIDebugger::finishCommand(std::string &Options) {
  if (!getToken(Options).empty())
    throw "finish command does not take any arguments.";
  if (!Dbg.isProgramRunning()) throw "Program is not running.";

  // Figure out where we are exactly.  If the user requests that we return from
  // a frame that is not the top frame, make sure we get it.
  void *CurrentFrame = getRuntimeInfo().getCurrentFrame().getFrameID();

  eliminateRunInfo();

  Dbg.finishProgram(CurrentFrame);

  // The program stopped!
  programStoppedSuccessfully();
}

//===----------------------------------------------------------------------===//
//                           Stack frame commands
//===----------------------------------------------------------------------===//

void CLIDebugger::backtraceCommand(std::string &Options) {
  // Accepts "full", n, -n
  if (!getToken(Options).empty())
    throw "FIXME: bt command argument not implemented yet!";

  RuntimeInfo &RI = getRuntimeInfo();
  ProgramInfo &PI = getProgramInfo();

  try {
    for (unsigned i = 0; ; ++i) {
      StackFrame &SF = RI.getStackFrame(i);
      std::cout << "#" << i;
      if (i == RI.getCurrentFrameIdx())
        std::cout << " ->";
      std::cout << "\t" << SF.getFrameID() << " in ";
      if (const GlobalVariable *G = SF.getFunctionDesc())
        std::cout << PI.getFunction(G).getSymbolicName();

      unsigned LineNo, ColNo;
      const SourceFileInfo *SFI;
      SF.getSourceLocation(LineNo, ColNo, SFI);
      if (!SFI->getBaseName().empty()) {
        std::cout << " at " << SFI->getBaseName();
        if (LineNo) {
          std::cout << ":" << LineNo;
          if (ColNo)
            std::cout << ":" << ColNo;
        }
      }

      // FIXME: when we support shared libraries, we should print ' from foo.so'
      // if the stack frame is from a different object than the current one.

      std::cout << "\n";
    }
  } catch (...) {
    // Stop automatically when we run off the bottom of the stack.
  }
}

void CLIDebugger::upCommand(std::string &Options) {
  unsigned Num =
    getOptionalUnsignedIntegerOption("'up' command", 1, Options);

  RuntimeInfo &RI = getRuntimeInfo();
  unsigned CurFrame = RI.getCurrentFrameIdx();

  // Check to see if we go can up the specified number of frames.
  try {
    RI.getStackFrame(CurFrame+Num);
  } catch (...) {
    if (Num == 1)
      throw "Initial frame selected; you cannot go up.";
    else
      throw "Cannot go up " + utostr(Num) + " frames!";
  }

  RI.setCurrentFrameIdx(CurFrame+Num);
  printProgramLocation();
}

void CLIDebugger::downCommand(std::string &Options) {
  unsigned Num =
    getOptionalUnsignedIntegerOption("'down' command", 1, Options);

  RuntimeInfo &RI = getRuntimeInfo();
  unsigned CurFrame = RI.getCurrentFrameIdx();

  // Check to see if we can go up the specified number of frames.
  if (CurFrame < Num)
    if (Num == 1)
      throw "Bottom (i.e., innermost) frame selected; you cannot go down.";
    else
      throw "Cannot go down " + utostr(Num) + " frames!";

  RI.setCurrentFrameIdx(CurFrame-Num);
  printProgramLocation();
}

void CLIDebugger::frameCommand(std::string &Options) {
  RuntimeInfo &RI = getRuntimeInfo();
  unsigned CurFrame = RI.getCurrentFrameIdx();

  unsigned Num =
    getOptionalUnsignedIntegerOption("'frame' command", CurFrame, Options);

  // Check to see if we go to the specified frame.
  RI.getStackFrame(Num);

  RI.setCurrentFrameIdx(Num);
  printProgramLocation();
}


//===----------------------------------------------------------------------===//
//                        Breakpoint related commands
//===----------------------------------------------------------------------===//

void CLIDebugger::breakCommand(std::string &Options) {
  // Figure out where the user wants a breakpoint.
  const SourceFile *File;
  unsigned LineNo;

  // Check to see if the user specified a line specifier.
  std::string Option = getToken(Options);  // strip whitespace
  if (!Option.empty()) {
    Options = Option + Options;  // reconstruct string

    // Parse the line specifier.
    parseLineSpec(Options, File, LineNo);
  } else {
    // Build a line specifier for the current stack frame.
    throw "FIXME: breaking at the current location is not implemented yet!";
  }

  if (!File) File = CurrentFile;
  if (File == 0)
    throw "Unknown file to place breakpoint!";

  std::cerr << "Break: " << File->getFilename() << ":" << LineNo << "\n";

  throw "breakpoints not implemented yet!";
}

//===----------------------------------------------------------------------===//
//                          Miscellaneous commands
//===----------------------------------------------------------------------===//

void CLIDebugger::infoCommand(std::string &Options) {
  std::string What = getToken(Options);

  if (What.empty() || !getToken(Options).empty()){
    std::string infoStr("info");
    helpCommand(infoStr);
    return;
  }

  if (What == "frame") {
  } else if (What == "functions") {
    const std::map<const GlobalVariable*, SourceFunctionInfo*> &Functions
      = getProgramInfo().getSourceFunctions();
    std::cout << "All defined functions:\n";
    // FIXME: GDB groups these by source file.  We could do that I guess.
    for (std::map<const GlobalVariable*, SourceFunctionInfo*>::const_iterator
           I = Functions.begin(), E = Functions.end(); I != E; ++I) {
      std::cout << I->second->getSymbolicName() << "\n";
    }

  } else if (What == "source") {
    if (CurrentFile == 0)
      throw "No current source file.";

    // Get the SourceFile information for the current file.
    const SourceFileInfo &SF =
      getProgramInfo().getSourceFile(CurrentFile->getDescriptor());

    std::cout << "Current source file is: " << SF.getBaseName() << "\n"
              << "Compilation directory is: " << SF.getDirectory() << "\n";
    if (unsigned NL = CurrentFile->getNumLines())
      std::cout << "Located in: " << CurrentFile->getFilename() << "\n"
                << "Contains " << NL << " lines\n";
    else
      std::cout << "Could not find source file.\n";
    std::cout << "Source language is "
              << SF.getLanguage().getSourceLanguageName() << "\n";

  } else if (What == "sources") {
    const std::map<const GlobalVariable*, SourceFileInfo*> &SourceFiles =
      getProgramInfo().getSourceFiles();
    std::cout << "Source files for the program:\n";
    for (std::map<const GlobalVariable*, SourceFileInfo*>::const_iterator I =
           SourceFiles.begin(), E = SourceFiles.end(); I != E;) {
      std::cout << I->second->getDirectory() << "/"
                << I->second->getBaseName();
      ++I;
      if (I != E) std::cout << ", ";
    }
    std::cout << "\n";
  } else if (What == "target") {
    std::cout << Dbg.getRunningProcess().getStatus();
  } else {
    // See if this is something handled by the current language.
    if (getCurrentLanguage().printInfo(What))
      return;

    throw "Unknown info command '" + What + "'.  Try 'help info'.";
  }
}

/// parseLineSpec - Parses a line specifier, for use by the 'list' command.
/// If SourceFile is returned as a void pointer, then it was not specified.
/// If the line specifier is invalid, an exception is thrown.
void CLIDebugger::parseLineSpec(std::string &LineSpec,
                                const SourceFile *&SourceFile,
                                unsigned &LineNo) {
  SourceFile = 0;
  LineNo = 0;

  // First, check to see if we have a : separator.
  std::string FirstPart = getToken(LineSpec, ":");
  std::string SecondPart = getToken(LineSpec, ":");
  if (!getToken(LineSpec).empty()) throw "Malformed line specification!";

  // If there is no second part, we must have either "function", "number",
  // "+offset", or "-offset".
  if (SecondPart.empty()) {
    if (FirstPart.empty()) throw "Malformed line specification!";
    if (FirstPart[0] == '+') {
      FirstPart.erase(FirstPart.begin(), FirstPart.begin()+1);
      // For +n, return LineListedEnd+n
      LineNo = LineListedEnd +
               getUnsignedIntegerOption("Line specifier '+'", FirstPart);

    } else if (FirstPart[0] == '-') {
      FirstPart.erase(FirstPart.begin(), FirstPart.begin()+1);
      // For -n, return LineListedEnd-n
      LineNo = LineListedEnd -
               getUnsignedIntegerOption("Line specifier '-'", FirstPart);
      if ((int)LineNo < 1) LineNo = 1;
    } else if (FirstPart[0] == '*') {
      throw "Address expressions not supported as source locations!";
    } else {
      // Ok, check to see if this is just a line number.
      std::string Saved = FirstPart;
      try {
        LineNo = getUnsignedIntegerOption("", Saved);
      } catch (...) {
        // Ok, it's not a valid line number.  It must be a source-language
        // entity name.
        std::string Name = getToken(FirstPart);
        if (!getToken(FirstPart).empty())
          throw "Extra junk in line specifier after '" + Name + "'.";
        SourceFunctionInfo *SFI =
          getCurrentLanguage().lookupFunction(Name, getProgramInfo(),
                                              TheRuntimeInfo);
        if (SFI == 0)
          throw "Unknown identifier '" + Name + "'.";

        unsigned L, C;
        SFI->getSourceLocation(L, C);
        if (L == 0) throw "Could not locate '" + Name + "'!";
        LineNo = L;
        SourceFile = &SFI->getSourceFile().getSourceText();
        return;
      }
    }

  } else {
    // Ok, this must be a filename qualified line number or function name.
    // First, figure out the source filename.
    std::string SourceFilename = getToken(FirstPart);
    if (!getToken(FirstPart).empty())
      throw "Invalid filename qualified source location!";

    // Next, check to see if this is just a line number.
    std::string Saved = SecondPart;
    try {
      LineNo = getUnsignedIntegerOption("", Saved);
    } catch (...) {
      // Ok, it's not a valid line number.  It must be a function name.
      throw "FIXME: Filename qualified function names are not support "
            "as line specifiers yet!";
    }

    // Ok, we got the line number.  Now check out the source file name to make
    // sure it's all good.  If it is, return it.  If not, throw exception.
    SourceFile =&getProgramInfo().getSourceFile(SourceFilename).getSourceText();
  }
}

void CLIDebugger::listCommand(std::string &Options) {
  if (!Dbg.isProgramLoaded())
    throw "No program is loaded.  Use the 'file' command.";

  // Handle "list foo," correctly, by returning " " as the second token
  Options += " ";

  std::string FirstLineSpec = getToken(Options, ",");
  std::string SecondLineSpec = getToken(Options, ",");
  if (!getToken(Options, ",").empty())
    throw "list command only expects two source location specifiers!";

  // StartLine, EndLine - The starting and ending line numbers to print.
  unsigned StartLine = 0, EndLine = 0;

  if (SecondLineSpec.empty()) {    // No second line specifier provided?
    // Handle special forms like "", "+", "-", etc.
    std::string TmpSpec = FirstLineSpec;
    std::string Tok = getToken(TmpSpec);
    if (getToken(TmpSpec).empty() && (Tok == "" || Tok == "+" || Tok == "-")) {
      if (Tok == "+" || Tok == "") {
        StartLine = LineListedEnd;
        EndLine = StartLine + ListSize;
      } else {
        assert(Tok == "-");
        StartLine = LineListedStart-ListSize;
        EndLine = LineListedStart;
        if ((int)StartLine <= 0) StartLine = 1;
      }
    } else {
      // Must be a normal line specifier.
      const SourceFile *File;
      unsigned LineNo;
      parseLineSpec(FirstLineSpec, File, LineNo);

      // If the user only specified one file specifier, we should display
      // ListSize lines centered at the specified line.
      if (File != 0) CurrentFile = File;
      StartLine = LineNo - (ListSize+1)/2;
      if ((int)StartLine <= 0) StartLine = 1;
      EndLine = StartLine + ListSize;
    }

  } else {
    // Parse two line specifiers...
    const SourceFile *StartFile, *EndFile;
    unsigned StartLineNo, EndLineNo;
    parseLineSpec(FirstLineSpec, StartFile, StartLineNo);
    unsigned SavedLLE = LineListedEnd;
    LineListedEnd = StartLineNo;
    try {
      parseLineSpec(SecondLineSpec, EndFile, EndLineNo);
    } catch (...) {
      LineListedEnd = SavedLLE;
      throw;
    }

    // Inherit file specified by the first line spec if there was one.
    if (EndFile == 0) EndFile = StartFile;

    if (StartFile != EndFile)
      throw "Start and end line specifiers are in different files!";
    CurrentFile = StartFile;
    StartLine = StartLineNo;
    EndLine = EndLineNo+1;
  }

  assert((int)StartLine > 0 && (int)EndLine > 0 && StartLine <= EndLine &&
         "Error reading line specifiers!");

  // If there was no current file, and the user didn't specify one to list, we
  // have an error.
  if (CurrentFile == 0)
    throw "There is no current file to list.";

  // Remember for next time.
  LineListedStart = StartLine;
  LineListedEnd = StartLine;

  for (unsigned LineNo = StartLine; LineNo != EndLine; ++LineNo) {
    // Print the source line, unless it is invalid.
    if (printSourceLine(LineNo))
      break;
    LineListedEnd = LineNo+1;
  }

  // If we didn't print any lines, find out why.
  if (LineListedEnd == StartLine) {
    // See if we can read line #0 from the file, if not, we couldn't load the
    // file.
    const char *LineStart, *LineEnd;
    CurrentFile->getSourceLine(0, LineStart, LineEnd);
    if (LineStart == 0)
      throw "Could not load source file '" + CurrentFile->getFilename() + "'!";
    else
      std::cout << "<end of file>\n";
  }
}

void CLIDebugger::setCommand(std::string &Options) {
  std::string What = getToken(Options);

  if (What.empty())
    throw "set command expects at least two arguments.";
  if (What == "args") {
    parseProgramOptions(Options);
  } else if (What == "language") {
    std::string Lang = getToken(Options);
    if (!getToken(Options).empty())
      throw "set language expects one argument at most.";
    if (Lang == "") {
      std::cout << "The currently understood settings are:\n\n"
                << "local or auto  Automatic setting based on source file\n"
                << "c              Use the C language\n"
                << "c++            Use the C++ language\n"
                << "unknown        Use when source language is not supported\n";
    } else if (Lang == "local" || Lang == "auto") {
      CurrentLanguage = 0;
    } else if (Lang == "c") {
      CurrentLanguage = &SourceLanguage::getCFamilyInstance();
    } else if (Lang == "c++") {
      CurrentLanguage = &SourceLanguage::getCPlusPlusInstance();
    } else if (Lang == "unknown") {
      CurrentLanguage = &SourceLanguage::getUnknownLanguageInstance();
    } else {
      throw "Unknown language '" + Lang + "'.";
    }

  } else if (What == "listsize") {
    ListSize = getUnsignedIntegerOption("'set prompt' command", Options);
  } else if (What == "prompt") {
    // Include any trailing whitespace or other tokens, but not leading
    // whitespace.
    Prompt = getToken(Options);  // Strip leading whitespace
    Prompt += Options;           // Keep trailing whitespace or other stuff
  } else {
    // FIXME: Try to parse this as a source-language program expression.
    throw "Don't know how to set '" + What + "'!";
  }
}

void CLIDebugger::showCommand(std::string &Options) {
  std::string What = getToken(Options);

  if (What.empty() || !getToken(Options).empty())
    throw "show command expects one argument.";

  if (What == "args") {
    std::cout << "Argument list to give program when started is \"";
    // FIXME: This doesn't print stuff correctly if the arguments have spaces in
    // them, but currently the only way to get that is to use the --args command
    // line argument.  This should really handle escaping all hard characters as
    // needed.
    for (unsigned i = 0, e = Dbg.getNumProgramArguments(); i != e; ++i)
      std::cout << (i ? " " : "") << Dbg.getProgramArgument(i);
    std::cout << "\"\n";

  } else if (What == "language") {
    std::cout << "The current source language is '";
    if (CurrentLanguage)
      std::cout << CurrentLanguage->getSourceLanguageName();
    else
      std::cout << "auto; currently "
                << getCurrentLanguage().getSourceLanguageName();
    std::cout << "'.\n";
  } else if (What == "listsize") {
    std::cout << "Number of source lines llvm-db will list by default is "
              << ListSize << ".\n";
  } else if (What == "prompt") {
    std::cout << "llvm-db's prompt is \"" << Prompt << "\".\n";
  } else {
    throw "Unknown show command '" + What + "'.  Try 'help show'.";
  }
}

void CLIDebugger::helpCommand(std::string &Options) {
  // Print out all of the commands in the CommandTable
  std::string Command = getToken(Options);
  if (!getToken(Options).empty())
    throw "help command takes at most one argument.";

  // Getting detailed help on a particular command?
  if (!Command.empty()) {
    CLICommand *C = getCommand(Command);
    std::cout << C->getShortHelp() << ".\n" << C->getLongHelp();

    // If there are aliases for this option, print them out.
    const std::vector<std::string> &Names = C->getOptionNames();
    if (Names.size() > 1) {
      std::cout << "The '" << Command << "' command is known as: '"
                << Names[0] << "'";
      for (unsigned i = 1, e = Names.size(); i != e; ++i)
        std::cout << ", '" << Names[i] << "'";
      std::cout << "\n";
    }

  } else {
    unsigned MaxSize = 0;
    for (std::map<std::string, CLICommand*>::iterator I = CommandTable.begin(),
           E = CommandTable.end(); I != E; ++I)
      if (I->first.size() > MaxSize &&
          I->first == I->second->getPrimaryOptionName())
        MaxSize = I->first.size();

    // Loop over all of the commands, printing the short help version
    for (std::map<std::string, CLICommand*>::iterator I = CommandTable.begin(),
           E = CommandTable.end(); I != E; ++I)
      if (I->first == I->second->getPrimaryOptionName())
        std::cout << I->first << std::string(MaxSize - I->first.size(), ' ')
                  << " - " << I->second->getShortHelp() << "\n";
  }
}
