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
13static 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
38static 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
67static 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
75int 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
93typedef struct thread_info {
94 int argc;
95 const char **argv;
96 int result;
97} thread_info;
98void 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
103static 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
110int 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