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