ScratchBuffer.cpp revision 226633
1243789Sdim//===--- ScratchBuffer.cpp - Scratch space for forming tokens -------------===//
2243789Sdim//
3243789Sdim//                     The LLVM Compiler Infrastructure
4243789Sdim//
5243789Sdim// This file is distributed under the University of Illinois Open Source
6243789Sdim// License. See LICENSE.TXT for details.
7243789Sdim//
8243789Sdim//===----------------------------------------------------------------------===//
9243789Sdim//
10243789Sdim//  This file implements the ScratchBuffer interface.
11251662Sdim//
12251662Sdim//===----------------------------------------------------------------------===//
13251662Sdim
14243789Sdim#include "clang/Lex/ScratchBuffer.h"
15249423Sdim#include "clang/Basic/SourceManager.h"
16243789Sdim#include "llvm/Support/MemoryBuffer.h"
17243789Sdim#include <cstring>
18243789Sdimusing namespace clang;
19243789Sdim
20243789Sdim// ScratchBufSize - The size of each chunk of scratch memory.  Slightly less
21243789Sdim//than a page, almost certainly enough for anything. :)
22243789Sdimstatic const unsigned ScratchBufSize = 4060;
23249423Sdim
24243789SdimScratchBuffer::ScratchBuffer(SourceManager &SM) : SourceMgr(SM), CurBuffer(0) {
25243789Sdim  // Set BytesUsed so that the first call to getToken will require an alloc.
26243789Sdim  BytesUsed = ScratchBufSize;
27243789Sdim}
28249423Sdim
29243789Sdim/// getToken - Splat the specified text into a temporary MemoryBuffer and
30243789Sdim/// return a SourceLocation that refers to the token.  This is just like the
31243789Sdim/// method below, but returns a location that indicates the physloc of the
32243789Sdim/// token.
33243789SdimSourceLocation ScratchBuffer::getToken(const char *Buf, unsigned Len,
34243789Sdim                                       const char *&DestPtr) {
35249423Sdim  if (BytesUsed+Len+2 > ScratchBufSize)
36243789Sdim    AllocScratchBuffer(Len+2);
37288943Sdim
38288943Sdim  // Prefix the token with a \n, so that it looks like it is the first thing on
39288943Sdim  // its own virtual line in caret diagnostics.
40288943Sdim  CurBuffer[BytesUsed++] = '\n';
41243789Sdim
42243789Sdim  // Return a pointer to the character data.
43243789Sdim  DestPtr = CurBuffer+BytesUsed;
44249423Sdim
45249423Sdim  // Copy the token data into the buffer.
46249423Sdim  memcpy(CurBuffer+BytesUsed, Buf, Len);
47243789Sdim
48249423Sdim  // Remember that we used these bytes.
49249423Sdim  BytesUsed += Len+1;
50249423Sdim
51261991Sdim  // Add a NUL terminator to the token.  This keeps the tokens separated, in
52249423Sdim  // case they get relexed, and puts them on their own virtual lines in case a
53261991Sdim  // diagnostic points to one.
54249423Sdim  CurBuffer[BytesUsed-1] = '\0';
55249423Sdim
56243789Sdim  return BufferStartLoc.getLocWithOffset(BytesUsed-Len-1);
57276479Sdim}
58243789Sdim
59243789Sdimvoid ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
60296417Sdim  // Only pay attention to the requested length if it is larger than our default
61276479Sdim  // page size.  If it is, we allocate an entire chunk for it.  This is to
62280031Sdim  // support gigantic tokens, which almost certainly won't happen. :)
63276479Sdim  if (RequestLen < ScratchBufSize)
64280031Sdim    RequestLen = ScratchBufSize;
65296417Sdim
66296417Sdim  llvm::MemoryBuffer *Buf =
67288943Sdim    llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
68249423Sdim  FileID FID = SourceMgr.createFileIDForMemBuffer(Buf);
69249423Sdim  BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
70249423Sdim  CurBuffer = const_cast<char*>(Buf->getBufferStart());
71243789Sdim  BytesUsed = 1;
72249423Sdim  CurBuffer[0] = '0';  // Start out with a \0 for cleanliness.
73243789Sdim}
74249423Sdim