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, index: i, original: &origFname, transformed: &transFname); |
26 | |
27 | fprintf(stdout, format: "%s\n" , clang_getCString(string: origFname)); |
28 | fprintf(stdout, format: "%s\n" , clang_getCString(string: transFname)); |
29 | |
30 | clang_disposeString(string: origFname); |
31 | clang_disposeString(string: 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(filePaths: 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, index: i, original: &origFname, transformed: &transFname); |
51 | |
52 | fprintf(stdout, format: "%s\n" , clang_getCString(string: origFname)); |
53 | fprintf(stdout, format: "%s\n" , clang_getCString(string: transFname)); |
54 | |
55 | clang_disposeString(string: origFname); |
56 | clang_disposeString(string: 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 | format: "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(s1: argv[1], s2: "-mt-migrate-directory" , n: 21) == 0) |
78 | return print_remappings(path: argv[2]); |
79 | |
80 | if (argc > 1) |
81 | return print_remappings_filelist(files: argv+1, numFiles: 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(argc: client_data->argc, argv: 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 (enableAutoConversion(fileno(stdout)) == -1) |
113 | fprintf(stderr, "Setting conversion on stdout failed\n" ); |
114 | |
115 | if (enableAutoConversion(fileno(stderr)) == -1) |
116 | fprintf(stderr, "Setting conversion on stderr failed\n" ); |
117 | #endif |
118 | |
119 | thread_info client_data; |
120 | |
121 | atexit(func: 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(name: "LIBCLANG_LOGGING" , value: "1" , /*overwrite=*/replace: 0); |
129 | #endif |
130 | |
131 | if (getenv(name: "CINDEXTEST_NOTHREADS" )) |
132 | return carcmttest_main(argc, argv); |
133 | |
134 | client_data.argc = argc; |
135 | client_data.argv = argv; |
136 | clang_executeOnThread(fn: thread_runner, user_data: &client_data, stack_size: 0); |
137 | return client_data.result; |
138 | } |
139 | |