119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===//
219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//                     The LLVM Compiler Infrastructure
419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file is distributed under the University of Illinois Open Source
619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// License. See LICENSE.TXT for details.
719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===//
919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
1019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This header provides the interface to read and write coverage files that
1119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// use 'gcov' format.
1219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
1319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===//
1419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifndef LLVM_GCOV_H
1619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#define LLVM_GCOV_H
1719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/SmallVector.h"
1919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/StringMap.h"
2019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/MemoryBuffer.h"
2119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/raw_ostream.h"
2219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
2319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace llvm {
2419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
2519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass GCOVFunction;
2619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass GCOVBlock;
2719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass GCOVLines;
2819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass FileInfo;
2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
3019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanenum GCOVFormat {
3119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  InvalidGCOV,
3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  GCNO_402,
3319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  GCNO_404,
3419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  GCDA_402,
3519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  GCDA_404
3619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman};
3719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
3819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
3919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// read operations.
4019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass GCOVBuffer {
4119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanpublic:
4219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
4319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
4419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// readGCOVFormat - Read GCOV signature at the beginning of buffer.
4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  enum GCOVFormat readGCOVFormat() {
4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef Magic = Buffer->getBuffer().slice(0, 12);
4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor = 12;
4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Magic == "oncg*404MVLL")
4919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return GCNO_404;
5019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    else if (Magic == "oncg*204MVLL")
5119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return GCNO_402;
5219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    else if (Magic == "adcg*404MVLL")
5319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return GCDA_404;
5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    else if (Magic == "adcg*204MVLL")
5519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return GCDA_402;
5619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
5719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor = 0;
5819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return InvalidGCOV;
5919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
6019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
6119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// readFunctionTag - If cursor points to a function tag then increment the
6219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// cursor and return true otherwise return false.
6319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool readFunctionTag() {
6419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Tag.empty() ||
6619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[0] != '\0' || Tag[1] != '\0' ||
6719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[2] != '\0' || Tag[3] != '\1') {
6819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return false;
6919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
7019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor += 4;
7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true;
7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
7319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
7419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// readBlockTag - If cursor points to a block tag then increment the
7519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// cursor and return true otherwise return false.
7619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool readBlockTag() {
7719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
7819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Tag.empty() ||
7919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[0] != '\0' || Tag[1] != '\0' ||
8019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[2] != '\x41' || Tag[3] != '\x01') {
8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return false;
8219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor += 4;
8419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true;
8519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
8619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// readEdgeTag - If cursor points to an edge tag then increment the
8819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// cursor and return true otherwise return false.
8919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool readEdgeTag() {
9019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
9119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Tag.empty() ||
9219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[0] != '\0' || Tag[1] != '\0' ||
9319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[2] != '\x43' || Tag[3] != '\x01') {
9419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return false;
9519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
9619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor += 4;
9719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true;
9819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
9919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
10019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// readLineTag - If cursor points to a line tag then increment the
10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// cursor and return true otherwise return false.
10219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool readLineTag() {
10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
10419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Tag.empty() ||
10519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[0] != '\0' || Tag[1] != '\0' ||
10619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[2] != '\x45' || Tag[3] != '\x01') {
10719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return false;
10819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
10919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor += 4;
11019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true;
11119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// readArcTag - If cursor points to an gcda arc tag then increment the
11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  /// cursor and return true otherwise return false.
11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool readArcTag() {
11619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4);
11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Tag.empty() ||
11819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[0] != '\0' || Tag[1] != '\0' ||
11919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman	Tag[2] != '\xa1' || Tag[3] != '\1') {
12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return false;
12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor += 4;
12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true;
12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint32_t readInt() {
12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    uint32_t Result;
12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4);
12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    assert (Str.empty() == false && "Unexpected memory buffer end!");
13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor += 4;
13119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Result = *(uint32_t *)(Str.data());
13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return Result;
13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint64_t readInt64() {
13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    uint64_t Lo = readInt();
13719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    uint64_t Hi = readInt();
13819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    uint64_t Result = Lo | (Hi << 32);
13919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return Result;
14019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef readString() {
14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    uint32_t Len = readInt() * 4;
14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+Len);
14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Cursor += Len;
14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return Str;
14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint64_t getCursor() const { return Cursor; }
15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanprivate:
15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MemoryBuffer *Buffer;
15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint64_t Cursor;
15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman};
15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// GCOVFile - Collects coverage information for one pair of coverage file
15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// (.gcno and .gcda).
15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass GCOVFile {
15819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanpublic:
15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  GCOVFile() {}
16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  ~GCOVFile();
16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool read(GCOVBuffer &Buffer);
16219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void dump();
16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void collectLineCounts(FileInfo &FI);
16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanprivate:
16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallVector<GCOVFunction *, 16> Functions;
16619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman};
16719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
16819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// GCOVFunction - Collects function information.
16919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass GCOVFunction {
17019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanpublic:
17119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  GCOVFunction() : Ident(0), LineNumber(0) {}
17219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  ~GCOVFunction();
17319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool read(GCOVBuffer &Buffer, GCOVFormat Format);
17419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void dump();
17519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void collectLineCounts(FileInfo &FI);
17619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanprivate:
17719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint32_t Ident;
17819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint32_t LineNumber;
17919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef Name;
18019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef Filename;
18119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallVector<GCOVBlock *, 16> Blocks;
18219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman};
18319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
18419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// GCOVBlock - Collects block information.
18519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass GCOVBlock {
18619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanpublic:
18719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  GCOVBlock(uint32_t N) : Number(N), Counter(0) {}
18819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  ~GCOVBlock();
18919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void addEdge(uint32_t N) { Edges.push_back(N); }
19019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void addLine(StringRef Filename, uint32_t LineNo);
19119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void addCount(uint64_t N) { Counter = N; }
19219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void dump();
19319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void collectLineCounts(FileInfo &FI);
19419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanprivate:
19519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint32_t Number;
19619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint64_t Counter;
19719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallVector<uint32_t, 16> Edges;
19819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringMap<GCOVLines *> Lines;
19919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman};
20019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
20119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// GCOVLines - A wrapper around a vector of int to keep track of line nos.
20219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass GCOVLines {
20319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanpublic:
20419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  ~GCOVLines() { Lines.clear(); }
20519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void add(uint32_t N) { Lines.push_back(N); }
20619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void collectLineCounts(FileInfo &FI, StringRef Filename, uint32_t Count);
20719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void dump();
20819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
20919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanprivate:
21019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallVector<uint32_t, 4> Lines;
21119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman};
21219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
21319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumantypedef SmallVector<uint32_t, 16> LineCounts;
21419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanclass FileInfo {
21519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanpublic:
21619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void addLineCount(StringRef Filename, uint32_t Line, uint32_t Count);
21719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  void print();
21819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanprivate:
21919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringMap<LineCounts> LineInfo;
22019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman};
22119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
22219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
22319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
22419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
225