/* c-arcmt-test.c */ #include "clang-c/Index.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #if defined(_WIN32) #include <io.h> #include <fcntl.h> #endif static int print_remappings(const char *path) { CXRemapping remap; unsigned i, N; CXString origFname; CXString transFname; remap = clang_getRemappings(path); if (!remap) return 1; N = clang_remap_getNumFiles(remap); for (i = 0; i != N; ++i) { clang_remap_getFilenames(remap, i, &origFname, &transFname); fprintf(stdout, "%s\n", clang_getCString(origFname)); fprintf(stdout, "%s\n", clang_getCString(transFname)); clang_disposeString(origFname); clang_disposeString(transFname); } clang_remap_dispose(remap); return 0; } static int print_remappings_filelist(const char **files, unsigned numFiles) { CXRemapping remap; unsigned i, N; CXString origFname; CXString transFname; remap = clang_getRemappingsFromFileList(files, numFiles); if (!remap) return 1; N = clang_remap_getNumFiles(remap); for (i = 0; i != N; ++i) { clang_remap_getFilenames(remap, i, &origFname, &transFname); fprintf(stdout, "%s\n", clang_getCString(origFname)); fprintf(stdout, "%s\n", clang_getCString(transFname)); clang_disposeString(origFname); clang_disposeString(transFname); } clang_remap_dispose(remap); return 0; } /******************************************************************************/ /* Command line processing. */ /******************************************************************************/ static void print_usage(void) { fprintf(stderr, "usage: c-arcmt-test -mt-migrate-directory <path>\n" " c-arcmt-test <remap-file-path1> <remap-file-path2> ...\n\n\n"); } /***/ int carcmttest_main(int argc, const char **argv) { clang_enableStackTraces(); if (argc == 3 && strncmp(argv[1], "-mt-migrate-directory", 21) == 0) return print_remappings(argv[2]); if (argc > 1) return print_remappings_filelist(argv+1, argc-1); print_usage(); return 1; } /***/ /* We intentionally run in a separate thread to ensure we at least minimal * testing of a multithreaded environment (for example, having a reduced stack * size). */ typedef struct thread_info { int argc; const char **argv; int result; } thread_info; void thread_runner(void *client_data_v) { thread_info *client_data = client_data_v; client_data->result = carcmttest_main(client_data->argc, client_data->argv); } static void flush_atexit(void) { /* stdout, and surprisingly even stderr, are not always flushed on process * and thread exit, particularly when the system is under heavy load. */ fflush(stdout); fflush(stderr); } int main(int argc, const char **argv) { thread_info client_data; atexit(flush_atexit); #if defined(_WIN32) if (getenv("LIBCLANG_LOGGING") == NULL) putenv("LIBCLANG_LOGGING=1"); _setmode( _fileno(stdout), _O_BINARY ); #else setenv("LIBCLANG_LOGGING", "1", /*overwrite=*/0); #endif if (getenv("CINDEXTEST_NOTHREADS")) return carcmttest_main(argc, argv); client_data.argc = argc; client_data.argv = argv; clang_executeOnThread(thread_runner, &client_data, 0); return client_data.result; }