int main(int argc, char **argv) { LogLevel logLevel = LogLevel::Error; Path file; for (int i=1; i<argc; ++i) { if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) { ++logLevel; } else { file = argv[i]; } } setenv("LIBCLANG_NOTHREADS", "1", 0); signal(SIGSEGV, sigHandler); signal(SIGABRT, sigHandler); signal(SIGBUS, sigHandler); Flags<LogMode> logType = LogStderr; std::shared_ptr<SyslogCloser> closer; if (ClangIndexer::serverOpts() & Server::RPLogToSyslog) { logType |= LogSyslog; closer.reset(new SyslogCloser); } initLogging(argv[0], logType, logLevel); (void)closer; RTags::initMessages(); std::shared_ptr<EventLoop> eventLoop(new EventLoop); eventLoop->init(EventLoop::MainEventLoop); String data; if (!file.isEmpty()) { data = file.readAll(); } else { uint32_t size; if (!fread(&size, sizeof(size), 1, stdin)) { error() << "Failed to read from stdin"; return 1; } data.resize(size); if (!fread(&data[0], size, 1, stdin)) { error() << "Failed to read from stdin"; return 2; } // FILE *f = fopen("/tmp/data", "w"); // fwrite(data.constData(), data.size(), 1, f); // fclose(f); } ClangIndexer indexer; if (!indexer.exec(data)) { error() << "ClangIndexer error"; return 3; } return 0; }
void ClangIndexer::inclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack, unsigned includeLen, CXClientData userData) { ClangIndexer *indexer = static_cast<ClangIndexer*>(userData); const Location l = indexer->createLocation(includedFile, 1, 1); const uint32_t fileId = l.fileId(); if (!includeLen) { indexer->mData->dependencies[fileId].insert(fileId); } else { for (unsigned i=0; i<includeLen; ++i) { CXFile originatingFile; clang_getSpellingLocation(includeStack[i], &originatingFile, 0, 0, 0); const Location loc = indexer->createLocation(originatingFile, 1, 1); const uint32_t f = loc.fileId(); if (f) indexer->mData->dependencies[fileId].insert(f); } } }
int main(int argc, char **argv) { setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); LogLevel logLevel = LogLevel::Error; Path file; bool logToSyslog = false; bool daemon = false; for (int i=1; i<argc; ++i) { if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) { ++logLevel; } else if (!strcmp(argv[i], "--priority")) { // ignore, only for wrapping purposes ++i; } else if (!strcmp(argv[i], "--log-to-syslog")) { logToSyslog = true; } else if (!strcmp(argv[i], "--daemon")) { daemon = true; } else { file = argv[i]; } } if (const char *env = getenv("TMPDIR")) { // should really always be set by rdm Path path = Path(env).ensureTrailingSlash(); path += String::number(getpid()); path.mkdir(Path::Recursive); setenv("TMPDIR", path.c_str(), 1); } if (!daemon) setenv("LIBCLANG_NOTHREADS", "1", 0); signal(SIGSEGV, sigHandler); signal(SIGABRT, sigHandler); signal(SIGBUS, sigHandler); signal(SIGALRM, [](int) { ClangIndexer::transition(ClangIndexer::Stopped); }); Flags<LogFlag> logFlags = LogStderr; std::shared_ptr<SyslogCloser> closer; if (logToSyslog & Server::RPLogToSyslog) { logFlags |= LogSyslog; closer.reset(new SyslogCloser); } initLogging(argv[0], logFlags, logLevel); (void)closer; RTags::initMessages(); auto eventLoop = std::make_shared<EventLoop>(); eventLoop->init(EventLoop::MainEventLoop); ClangIndexer indexer; while (true) { String data; if (!file.isEmpty()) { data = file.readAll(); } else { uint32_t size; if (!fread(&size, sizeof(size), 1, stdin)) { error() << "Failed to read from stdin"; return 1; } data.resize(size); if (!fread(&data[0], size, 1, stdin)) { error() << "Failed to read from stdin"; return 2; } // FILE *f = fopen("/tmp/data", "w"); // fwrite(data.constData(), data.size(), 1, f); // fclose(f); } if (!indexer.exec(data)) { error() << "ClangIndexer error"; return 3; } if (daemon) { if (ClangIndexer::state() == ClangIndexer::Running) { printf("@FINISHED@"); fflush(stdout); } ClangIndexer::transition(ClangIndexer::NotStarted); } else { break; } } return 0; }
CXChildVisitResult ClangIndexer::indexVisitor(CXCursor cursor, CXCursor parent, CXClientData data) { ClangIndexer *indexer = static_cast<ClangIndexer*>(data); // error() << "indexVisitor" << cursor; // FILE *f = fopen("/tmp/clangindex.log", "a"); // String str; // Log(&str) << cursor; // fwrite(str.constData(), 1, str.size(), f); // fwrite("\n", 1, 1, f); // fclose(f); const LastCursorUpdater updater(indexer->mLastCursor, cursor); const CXCursorKind kind = clang_getCursorKind(cursor); const RTags::CursorType type = RTags::cursorType(kind); if (type == RTags::Other) return CXChildVisit_Recurse; bool blocked = false; Location loc = indexer->createLocation(cursor, &blocked); if (blocked) { // error() << "blocked" << cursor; ++indexer->mBlocked; return CXChildVisit_Continue; } else if (loc.isNull()) { // error() << "Got null" << cursor; return CXChildVisit_Recurse; } ++indexer->mAllowed; if (indexer->mLogFile) { String out; Log(&out) << cursor; fwrite(out.constData(), 1, out.size(), indexer->mLogFile); fwrite("\n", 1, 1, indexer->mLogFile); } if (testLog(VerboseDebug)) { Log log(VerboseDebug); log << cursor; CXCursor ref = clang_getCursorReferenced(cursor); if (!clang_isInvalid(clang_getCursorKind(ref)) && !clang_equalCursors(ref, cursor)) { log << "refs" << ref; } } switch (type) { case RTags::Cursor: indexer->handleCursor(cursor, kind, loc); break; case RTags::Include: indexer->handleInclude(cursor, kind, loc); break; case RTags::Reference: switch (kind) { case CXCursor_OverloadedDeclRef: { const int count = clang_getNumOverloadedDecls(cursor); for (int i=0; i<count; ++i) { const CXCursor ref = clang_getOverloadedDecl(cursor, i); indexer->handleReference(cursor, kind, loc, ref, parent); } break; } case CXCursor_CXXDeleteExpr: indexer->handleReference(cursor, kind, loc, findDestructorForDelete(cursor), parent); break; case CXCursor_CallExpr: { // uglehack, see rtags/tests/nestedClassConstructorCallUgleHack/ const CXCursor ref = clang_getCursorReferenced(cursor); if (clang_getCursorKind(ref) == CXCursor_Constructor && clang_getCursorKind(indexer->mLastCursor) == CXCursor_TypeRef && clang_getCursorKind(parent) != CXCursor_VarDecl) { loc = indexer->createLocation(indexer->mLastCursor); indexer->handleReference(indexer->mLastCursor, kind, loc, ref, parent); } else { indexer->handleReference(cursor, kind, loc, ref, parent); } break; } default: indexer->handleReference(cursor, kind, loc, clang_getCursorReferenced(cursor), parent); break; } break; case RTags::Other: assert(0); break; } return CXChildVisit_Recurse; }