1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2004-2016. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 *
20 */
21
22 /*
23 * A compiler wrapper that translate (some) gcc command line arguments
24 * to the Visual C++ compiler and (of course) the gcc compiler. It also
25 * makes some changes in the command line arguments when debug compiling.
26 */
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdarg.h>
32
33
34 #if !defined(__WIN32__)
35 #define USE_EXEC
36 #include <unistd.h>
37 #endif
38
39
40 #ifdef __WIN32__
41 #define EOL "\r\n"
42 #else
43 #define EOL "\n"
44 #endif
45
46 #define ARGS_INCR 20
47
48 static char *prog;
49
50 typedef struct {
51 char **vec;
52 int no;
53 int ix;
54 int chars;
55 } args_t;
56
57 static void
enomem(void)58 enomem(void)
59 {
60 fprintf(stderr, "%s: Out of memory%s", prog, EOL);
61 exit(1);
62 }
63
64 static void
save_arg(args_t * args,char * arg1,...)65 save_arg(args_t *args, char *arg1, ...)
66 {
67 char *carg;
68 va_list argp;
69
70 va_start(argp, arg1);
71 carg = arg1;
72 while (carg) {
73 if (args->no <= args->ix) {
74 args->vec = (char **) (args->no
75 ? realloc((void *) args->vec,
76 (sizeof(char *)
77 *(args->no + ARGS_INCR + 2)))
78 : malloc((sizeof(char *)
79 *(args->no + ARGS_INCR + 2))));
80 if (!args->vec)
81 enomem();
82 args->no += ARGS_INCR;
83 }
84 if (carg == arg1) {
85 args->vec[args->ix++] = "\"";
86 args->chars++;
87 }
88 args->vec[args->ix++] = carg;
89 args->chars += strlen(carg);
90 carg = va_arg(argp, char *);
91 }
92 args->vec[args->ix++] = "\"";
93 args->chars++;
94 args->vec[args->ix++] = " ";
95 args->chars++;
96 va_end(argp);
97 }
98
99 static int
is_prefix(char * prfx,char ** str)100 is_prefix(char *prfx, char **str)
101 {
102 int i;
103 for (i = 0; prfx[i] && (*str)[i]; i++) {
104 if (prfx[i] != (*str)[i])
105 return 0;
106 }
107 if (!prfx[i]) {
108 *str = &(*str)[i];
109 return 1;
110 }
111 return 0;
112 }
113
114 static void
cpy(char ** dst,char * src)115 cpy(char **dst, char *src)
116 {
117 int i;
118 for (i = 0; src[i]; i++)
119 (*dst)[i] = src[i];
120 *dst = &(*dst)[i];
121 }
122
123 typedef enum {
124 STDLIB_NONE,
125 STDLIB_MD,
126 STDLIB_ML,
127 STDLIB_MT
128 } stdlib_t;
129
130 int
main(int argc,char * argv[])131 main(int argc, char *argv[])
132 {
133 int res;
134 int i;
135 size_t cmd_len;
136 char *cmd;
137 char *cmd_end;
138 char *cc = NULL;
139 args_t args = {0};
140 int is_debug = 0;
141 int is_purify = 0;
142 int is_quantify = 0;
143 int is_purecov = 0;
144 #ifdef __WIN32__
145 int is_shared = 0;
146 stdlib_t stdlib = STDLIB_NONE;
147 char *shared_flag = "";
148 char *stdlib_flag = "";
149 int have_link_args = 0;
150 args_t link_args = {0};
151
152 #define CHECK_FIRST_LINK_ARG \
153 if (!have_link_args) { \
154 save_arg(&link_args, "-link", NULL); \
155 have_link_args = 1; \
156 }
157 #else /* #ifdef __WIN32__ */
158 #define CHECK_FIRST_LINK_ARG
159 #endif /* #ifdef __WIN32__ */
160
161 prog = argv[0];
162
163
164 for (i = 1; i < argc; i++) {
165 char *arg = argv[i];
166 if (is_prefix("-CC", &arg)) {
167 cc = arg;
168 }
169 else if (is_prefix("-O", &arg)) {
170 if (!is_debug)
171 save_arg(&args, argv[i], NULL);
172 }
173 else if (strcmp("-DDEBUG", arg) == 0) {
174 save_arg(&args, arg, NULL);
175 #ifdef __WIN32__
176 set_debug:
177 #endif
178 if (!is_debug) {
179 int j;
180 is_debug = 1;
181 #ifdef __WIN32__
182 save_arg(&args, "-Z7", NULL);
183 CHECK_FIRST_LINK_ARG;
184 save_arg(&link_args, "-debug", NULL);
185 save_arg(&link_args, "-pdb:none", NULL);
186 #endif
187 for (j = 0; j < args.ix; j++) {
188 char *tmp_arg = args.vec[j];
189 if (is_prefix("-O", &tmp_arg))
190 args.vec[j] = "";
191 }
192 }
193 }
194 else if (strcmp("-DPURIFY", arg) == 0) {
195 save_arg(&args, arg, NULL);
196 is_purify = 1;
197 }
198 else if (strcmp("-DQUANTIFY", arg) == 0) {
199 save_arg(&args, arg, NULL);
200 is_quantify = 1;
201 }
202 else if (strcmp("-DPURECOV", arg) == 0) {
203 save_arg(&args, arg, NULL);
204 is_purecov = 1;
205 }
206 #ifdef __WIN32__
207 else if (strcmp("-g", arg) == 0) {
208 goto set_debug;
209 }
210 else if (strcmp("-MD", arg) == 0)
211 stdlib = STDLIB_MD;
212 else if (strcmp("-MDd", arg) == 0) {
213 stdlib = STDLIB_MD;
214 goto set_debug;
215 }
216 else if (strcmp("-ML", arg) == 0)
217 stdlib = STDLIB_ML;
218 else if (strcmp("-MLd", arg) == 0) {
219 stdlib = STDLIB_ML;
220 goto set_debug;
221 }
222 else if (strcmp("-MT", arg) == 0)
223 stdlib = STDLIB_MT;
224 else if (strcmp("-MTd", arg) == 0) {
225 stdlib = STDLIB_MT;
226 goto set_debug;
227 }
228 else if (strcmp("-shared", arg) == 0 || strcmp("-LD", arg) == 0)
229 is_shared = 1;
230 else if (strcmp("-LDd", arg) == 0) {
231 is_shared = 1;
232 goto set_debug;
233 }
234 else if (strcmp("-Wall", arg) == 0) {
235 save_arg(&args, "-W3", NULL);
236 }
237 else if (is_prefix("-L", &arg)) {
238 CHECK_FIRST_LINK_ARG;
239 save_arg(&link_args, "-libpath:", arg, NULL);
240 }
241 else if (strcmp("-link",arg) == 0) {
242 CHECK_FIRST_LINK_ARG;
243 }
244 #endif /* #ifdef __WIN32__ */
245 else if (is_prefix("-l", &arg)) {
246 CHECK_FIRST_LINK_ARG;
247 if (is_debug && strcmp("ethread", arg) == 0)
248 arg = "ethread.debug";
249 else if (is_purify && strcmp("ethread", arg) == 0)
250 arg = "ethread.purify";
251 else if (is_quantify && strcmp("ethread", arg) == 0)
252 arg = "ethread.quantify";
253 else if (is_purecov && strcmp("ethread", arg) == 0)
254 arg = "ethread.purecov";
255 #ifdef __WIN32__
256 else if (strcmp("socket", arg) == 0)
257 arg = "ws2_32";
258 save_arg(&link_args, arg, ".lib", NULL);
259 #else
260 save_arg(&args, "-l", arg, NULL);
261 #endif
262 }
263 else
264 save_arg(&args, argv[i], NULL);
265 }
266
267 if (!cc || !cc[0]) {
268 fprintf(stderr, "%s: Missing compulsory -CC flag%s", prog, EOL);
269 exit(1);
270 }
271
272 cmd_len = strlen(cc) + 1 + args.chars + 1;
273
274 #ifdef __WIN32__
275 if (is_shared)
276 shared_flag = is_debug ? "-LDd " : "-LD ";
277 switch (stdlib) {
278 case STDLIB_MD: stdlib_flag = is_debug ? "-MDd " : "-MD "; break;
279 case STDLIB_ML: stdlib_flag = is_debug ? "-MLd " : "-ML "; break;
280 case STDLIB_MT: stdlib_flag = is_debug ? "-MTd " : "-MT "; break;
281 case STDLIB_NONE: break;
282 }
283
284 cmd_len += strlen(shared_flag) + strlen(stdlib_flag) + link_args.chars;
285 #endif
286
287 cmd = (char *) malloc(sizeof(char) * cmd_len);
288
289 if (!cmd)
290 enomem();
291 cmd_end = cmd;
292 cpy(&cmd_end, cc);
293 cpy(&cmd_end, " ");
294 #ifdef __WIN32__
295 cpy(&cmd_end, stdlib_flag);
296 cpy(&cmd_end, shared_flag);
297 #endif
298 for (i = 0; i < args.ix; i++)
299 cpy(&cmd_end, args.vec[i]);
300 #ifdef __WIN32__
301 for (i = 0; i < link_args.ix; i++)
302 cpy(&cmd_end, link_args.vec[i]);
303 #endif
304 *cmd_end = '\0';
305
306 printf("==> %s%s", cmd, EOL);
307 fflush(stdout);
308
309 #ifdef USE_EXEC
310 (void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
311 perror(NULL);
312 res = 1;
313 #else
314 res = system(cmd);
315 #endif
316
317 free((void *) args.vec);
318 #ifdef __WIN32__
319 free((void *) link_args.vec);
320 #endif
321 free((void *) cmd);
322
323 if (res < 0)
324 res = 1;
325 return res;
326 }
327