1193326Sed//===--- ScratchBuffer.cpp - Scratch space for forming tokens -------------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file implements the ScratchBuffer interface.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#include "clang/Lex/ScratchBuffer.h"
15193326Sed#include "clang/Basic/SourceManager.h"
16193326Sed#include "llvm/Support/MemoryBuffer.h"
17193326Sed#include <cstring>
18193326Sedusing namespace clang;
19193326Sed
20193326Sed// ScratchBufSize - The size of each chunk of scratch memory.  Slightly less
21193326Sed//than a page, almost certainly enough for anything. :)
22193326Sedstatic const unsigned ScratchBufSize = 4060;
23193326Sed
24193326SedScratchBuffer::ScratchBuffer(SourceManager &SM) : SourceMgr(SM), CurBuffer(0) {
25193326Sed  // Set BytesUsed so that the first call to getToken will require an alloc.
26193326Sed  BytesUsed = ScratchBufSize;
27193326Sed}
28193326Sed
29193326Sed/// getToken - Splat the specified text into a temporary MemoryBuffer and
30193326Sed/// return a SourceLocation that refers to the token.  This is just like the
31193326Sed/// method below, but returns a location that indicates the physloc of the
32193326Sed/// token.
33193326SedSourceLocation ScratchBuffer::getToken(const char *Buf, unsigned Len,
34193326Sed                                       const char *&DestPtr) {
35193326Sed  if (BytesUsed+Len+2 > ScratchBufSize)
36193326Sed    AllocScratchBuffer(Len+2);
37193326Sed
38193326Sed  // Prefix the token with a \n, so that it looks like it is the first thing on
39193326Sed  // its own virtual line in caret diagnostics.
40193326Sed  CurBuffer[BytesUsed++] = '\n';
41198092Srdivacky
42193326Sed  // Return a pointer to the character data.
43193326Sed  DestPtr = CurBuffer+BytesUsed;
44198092Srdivacky
45193326Sed  // Copy the token data into the buffer.
46193326Sed  memcpy(CurBuffer+BytesUsed, Buf, Len);
47193326Sed
48193326Sed  // Remember that we used these bytes.
49193326Sed  BytesUsed += Len+1;
50198092Srdivacky
51193326Sed  // Add a NUL terminator to the token.  This keeps the tokens separated, in
52193326Sed  // case they get relexed, and puts them on their own virtual lines in case a
53193326Sed  // diagnostic points to one.
54193326Sed  CurBuffer[BytesUsed-1] = '\0';
55193326Sed
56226633Sdim  return BufferStartLoc.getLocWithOffset(BytesUsed-Len-1);
57193326Sed}
58193326Sed
59193326Sedvoid ScratchBuffer::AllocScratchBuffer(unsigned RequestLen) {
60193326Sed  // Only pay attention to the requested length if it is larger than our default
61193326Sed  // page size.  If it is, we allocate an entire chunk for it.  This is to
62193326Sed  // support gigantic tokens, which almost certainly won't happen. :)
63193326Sed  if (RequestLen < ScratchBufSize)
64193326Sed    RequestLen = ScratchBufSize;
65198092Srdivacky
66198092Srdivacky  llvm::MemoryBuffer *Buf =
67193326Sed    llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
68193326Sed  FileID FID = SourceMgr.createFileIDForMemBuffer(Buf);
69193326Sed  BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
70193326Sed  CurBuffer = const_cast<char*>(Buf->getBufferStart());
71193326Sed  BytesUsed = 1;
72193326Sed  CurBuffer[0] = '0';  // Start out with a \0 for cleanliness.
73193326Sed}
74