1 /* c-arcmt-test.c */ 2 3 #include "clang-c/Index.h" 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <string.h> 7 #if defined(_WIN32) 8 #include <io.h> 9 #include <fcntl.h> 10 #endif 11 12 static int print_remappings(const char *path) { 13 CXRemapping remap; 14 unsigned i, N; 15 CXString origFname; 16 CXString transFname; 17 18 remap = clang_getRemappings(path); 19 if (!remap) 20 return 1; 21 22 N = clang_remap_getNumFiles(remap); 23 for (i = 0; i != N; ++i) { 24 clang_remap_getFilenames(remap, i, &origFname, &transFname); 25 26 fprintf(stdout, "%s\n", clang_getCString(origFname)); 27 fprintf(stdout, "%s\n", clang_getCString(transFname)); 28 29 clang_disposeString(origFname); 30 clang_disposeString(transFname); 31 } 32 33 clang_remap_dispose(remap); 34 return 0; 35 } 36 37 static int print_remappings_filelist(const char **files, unsigned numFiles) { 38 CXRemapping remap; 39 unsigned i, N; 40 CXString origFname; 41 CXString transFname; 42 43 remap = clang_getRemappingsFromFileList(files, numFiles); 44 if (!remap) 45 return 1; 46 47 N = clang_remap_getNumFiles(remap); 48 for (i = 0; i != N; ++i) { 49 clang_remap_getFilenames(remap, i, &origFname, &transFname); 50 51 fprintf(stdout, "%s\n", clang_getCString(origFname)); 52 fprintf(stdout, "%s\n", clang_getCString(transFname)); 53 54 clang_disposeString(origFname); 55 clang_disposeString(transFname); 56 } 57 58 clang_remap_dispose(remap); 59 return 0; 60 } 61 62 /******************************************************************************/ 63 /* Command line processing. */ 64 /******************************************************************************/ 65 66 static void print_usage(void) { 67 fprintf(stderr, 68 "usage: c-arcmt-test -mt-migrate-directory <path>\n" 69 " c-arcmt-test <remap-file-path1> <remap-file-path2> ...\n\n\n"); 70 } 71 72 /***/ 73 74 int carcmttest_main(int argc, const char **argv) { 75 clang_enableStackTraces(); 76 if (argc == 3 && strncmp(argv[1], "-mt-migrate-directory", 21) == 0) 77 return print_remappings(argv[2]); 78 79 if (argc > 1) 80 return print_remappings_filelist(argv+1, argc-1); 81 82 print_usage(); 83 return 1; 84 } 85 86 /***/ 87 88 /* We intentionally run in a separate thread to ensure we at least minimal 89 * testing of a multithreaded environment (for example, having a reduced stack 90 * size). */ 91 92 typedef struct thread_info { 93 int argc; 94 const char **argv; 95 int result; 96 } thread_info; 97 void thread_runner(void *client_data_v) { 98 thread_info *client_data = client_data_v; 99 client_data->result = carcmttest_main(client_data->argc, client_data->argv); 100 } 101 102 static void flush_atexit(void) { 103 /* stdout, and surprisingly even stderr, are not always flushed on process 104 * and thread exit, particularly when the system is under heavy load. */ 105 fflush(stdout); 106 fflush(stderr); 107 } 108 109 int main(int argc, const char **argv) { 110 thread_info client_data; 111 112 atexit(flush_atexit); 113 114 #if defined(_WIN32) 115 if (getenv("LIBCLANG_LOGGING") == NULL) 116 putenv("LIBCLANG_LOGGING=1"); 117 _setmode( _fileno(stdout), _O_BINARY ); 118 #else 119 setenv("LIBCLANG_LOGGING", "1", /*overwrite=*/0); 120 #endif 121 122 if (getenv("CINDEXTEST_NOTHREADS")) 123 return carcmttest_main(argc, argv); 124 125 client_data.argc = argc; 126 client_data.argv = argv; 127 clang_executeOnThread(thread_runner, &client_data, 0); 128 return client_data.result; 129 } 130