LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

SourceFile.cpp

Go to the documentation of this file.
00001 //===-- SourceFile.cpp - SourceFile implementation for the debugger -------===//
00002 // 
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 // 
00008 //===----------------------------------------------------------------------===//
00009 // 
00010 // This file implements the SourceFile class for the LLVM debugger.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Debugger/SourceFile.h"
00015 #include "llvm/Support/SlowOperationInformer.h"
00016 #include "llvm/Support/FileUtilities.h"
00017 #include <iostream>
00018 #include <cerrno>
00019 #include <fcntl.h>
00020 #include <unistd.h>
00021 using namespace llvm;
00022 
00023 /// readFile - Load Filename into FileStart and FileEnd.
00024 ///
00025 void SourceFile::readFile() {
00026   ssize_t FileSize = getFileSize(Filename);
00027   if (FileSize != -1) {
00028     FDHandle FD(open(Filename.c_str(), O_RDONLY));
00029     if (FD != -1) {
00030       char *FilePos = new char[FileSize];
00031       FileStart = FilePos;
00032 
00033       // If this takes a long time, inform the user what we are doing.
00034       SlowOperationInformer SOI("loading source file '" + Filename + "'");
00035 
00036       try {
00037         // Read in the whole buffer.
00038         unsigned Amount = FileSize;
00039         while (Amount) {
00040           unsigned AmountToRead = 512*1024;
00041           if (Amount < AmountToRead) AmountToRead = Amount;
00042           ssize_t ReadAmount = read(FD, FilePos, AmountToRead);
00043           if (ReadAmount < 0 && errno == EINTR)
00044             continue;
00045           else if (ReadAmount <= 0) {
00046             // Couldn't read whole file just free memory and continue.
00047             throw "Error reading file '" + Filename + "'!";
00048           }
00049           Amount -= ReadAmount;
00050           FilePos += ReadAmount;
00051           
00052           SOI.progress(FileSize-Amount, FileSize);
00053         }
00054 
00055       } catch (const std::string &Msg) {
00056         std::cout << Msg << "\n";
00057         // If the user cancels the operation, clean up after ourselves.
00058         delete [] FileStart;
00059         FileStart = 0;
00060         return;
00061       }
00062       
00063       FileEnd = FileStart+FileSize;
00064     }
00065   }
00066 }
00067 
00068 /// calculateLineOffsets - Compute the LineOffset vector for the current file.
00069 ///
00070 void SourceFile::calculateLineOffsets() const {
00071   assert(LineOffset.empty() && "Line offsets already computed!");
00072   const char *BufPtr = FileStart;
00073   do {
00074     LineOffset.push_back(BufPtr-FileStart);
00075 
00076     // Scan until we get to a newline.
00077     while (BufPtr != FileEnd && *BufPtr != '\n' && *BufPtr != '\r')
00078       ++BufPtr;
00079 
00080     if (BufPtr != FileEnd) {
00081       ++BufPtr;               // Skip over the \n or \r
00082       if (BufPtr[-1] == '\r' && BufPtr != FileEnd && BufPtr[0] == '\n')
00083         ++BufPtr;   // Skip over dos/windows style \r\n's
00084     }
00085   } while (BufPtr != FileEnd);
00086 }
00087 
00088 
00089 /// getSourceLine - Given a line number, return the start and end of the line
00090 /// in the file.  If the line number is invalid, or if the file could not be
00091 /// loaded, null pointers are returned for the start and end of the file. Note
00092 /// that line numbers start with 0, not 1.
00093 void SourceFile::getSourceLine(unsigned LineNo, const char *&LineStart,
00094                                const char *&LineEnd) const {
00095   LineStart = LineEnd = 0;
00096   if (FileStart == 0) return;  // Couldn't load file, return null pointers
00097   if (LineOffset.empty()) calculateLineOffsets();
00098 
00099   // Asking for an out-of-range line number?
00100   if (LineNo >= LineOffset.size()) return;
00101 
00102   // Otherwise, they are asking for a valid line, which we can fulfill.
00103   LineStart = FileStart+LineOffset[LineNo];
00104 
00105   if (LineNo+1 < LineOffset.size())
00106     LineEnd = FileStart+LineOffset[LineNo+1];
00107   else
00108     LineEnd = FileEnd;
00109 
00110   // If the line ended with a newline, strip it off.
00111   while (LineEnd != LineStart && (LineEnd[-1] == '\n' || LineEnd[-1] == '\r'))
00112     --LineEnd;
00113 
00114   assert(LineEnd >= LineStart && "We somehow got our pointers swizzled!");
00115 }
00116