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 #ifdef __CYGWIN__
101   fflush(stdout);  /* stdout is not flushed on Cygwin. */
102 #endif
103 }
104 
105 int main(int argc, const char **argv) {
106   thread_info client_data;
107 
108 #if defined(_WIN32)
109   if (getenv("LIBCLANG_LOGGING") == NULL)
110     putenv("LIBCLANG_LOGGING=1");
111   _setmode( _fileno(stdout), _O_BINARY );
112 #else
113   setenv("LIBCLANG_LOGGING", "1", /*overwrite=*/0);
114 #endif
115 
116   if (getenv("CINDEXTEST_NOTHREADS"))
117     return carcmttest_main(argc, argv);
118 
119   client_data.argc = argc;
120   client_data.argv = argv;
121   clang_executeOnThread(thread_runner, &client_data, 0);
122   return client_data.result;
123 }
124