1//===- ARCMigrate.cpp - Clang-C ARC Migration Library ---------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the main API hooks in the Clang-C ARC Migration library.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang-c/Index.h"
15#include "CXString.h"
16#include "clang/ARCMigrate/ARCMT.h"
17#include "clang/Frontend/TextDiagnosticBuffer.h"
18#include "llvm/Support/FileSystem.h"
19
20using namespace clang;
21using namespace arcmt;
22
23namespace {
24
25struct Remap {
26  std::vector<std::pair<std::string, std::string> > Vec;
27};
28
29} // anonymous namespace.
30
31//===----------------------------------------------------------------------===//
32// libClang public APIs.
33//===----------------------------------------------------------------------===//
34
35extern "C" {
36
37CXRemapping clang_getRemappings(const char *migrate_dir_path) {
38  bool Logging = ::getenv("LIBCLANG_LOGGING");
39
40  if (!migrate_dir_path) {
41    if (Logging)
42      llvm::errs() << "clang_getRemappings was called with NULL parameter\n";
43    return nullptr;
44  }
45
46  bool exists = false;
47  llvm::sys::fs::exists(migrate_dir_path, exists);
48  if (!exists) {
49    if (Logging) {
50      llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path
51                   << "\")\n";
52      llvm::errs() << "\"" << migrate_dir_path << "\" does not exist\n";
53    }
54    return nullptr;
55  }
56
57  TextDiagnosticBuffer diagBuffer;
58  std::unique_ptr<Remap> remap(new Remap());
59
60  bool err = arcmt::getFileRemappings(remap->Vec, migrate_dir_path,&diagBuffer);
61
62  if (err) {
63    if (Logging) {
64      llvm::errs() << "Error by clang_getRemappings(\"" << migrate_dir_path
65                   << "\")\n";
66      for (TextDiagnosticBuffer::const_iterator
67             I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I)
68        llvm::errs() << I->second << '\n';
69    }
70    return nullptr;
71  }
72
73  return remap.release();
74}
75
76CXRemapping clang_getRemappingsFromFileList(const char **filePaths,
77                                            unsigned numFiles) {
78  bool Logging = ::getenv("LIBCLANG_LOGGING");
79
80  std::unique_ptr<Remap> remap(new Remap());
81
82  if (numFiles == 0) {
83    if (Logging)
84      llvm::errs() << "clang_getRemappingsFromFileList was called with "
85                      "numFiles=0\n";
86    return remap.release();
87  }
88
89  if (!filePaths) {
90    if (Logging)
91      llvm::errs() << "clang_getRemappingsFromFileList was called with "
92                      "NULL filePaths\n";
93    return nullptr;
94  }
95
96  TextDiagnosticBuffer diagBuffer;
97  SmallVector<StringRef, 32> Files;
98  for (unsigned i = 0; i != numFiles; ++i)
99    Files.push_back(filePaths[i]);
100
101  bool err = arcmt::getFileRemappingsFromFileList(remap->Vec, Files,
102                                                  &diagBuffer);
103
104  if (err) {
105    if (Logging) {
106      llvm::errs() << "Error by clang_getRemappingsFromFileList\n";
107      for (TextDiagnosticBuffer::const_iterator
108             I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I)
109        llvm::errs() << I->second << '\n';
110    }
111    return remap.release();
112  }
113
114  return remap.release();
115}
116
117unsigned clang_remap_getNumFiles(CXRemapping map) {
118  return static_cast<Remap *>(map)->Vec.size();
119
120}
121
122void clang_remap_getFilenames(CXRemapping map, unsigned index,
123                              CXString *original, CXString *transformed) {
124  if (original)
125    *original = cxstring::createDup(
126                    static_cast<Remap *>(map)->Vec[index].first);
127  if (transformed)
128    *transformed = cxstring::createDup(
129                    static_cast<Remap *>(map)->Vec[index].second);
130}
131
132void clang_remap_dispose(CXRemapping map) {
133  delete static_cast<Remap *>(map);
134}
135
136} // end: extern "C"
137