| /* 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; |
| } |