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 #ifdef __WIN32__
142 int is_shared = 0;
143 stdlib_t stdlib = STDLIB_NONE;
144 char *shared_flag = "";
145 char *stdlib_flag = "";
146 int have_link_args = 0;
147 args_t link_args = {0};
148
149 #define CHECK_FIRST_LINK_ARG \
150 if (!have_link_args) { \
151 save_arg(&link_args, "-link", NULL); \
152 have_link_args = 1; \
153 }
154 #else /* #ifdef __WIN32__ */
155 #define CHECK_FIRST_LINK_ARG
156 #endif /* #ifdef __WIN32__ */
157
158 prog = argv[0];
159
160
161 for (i = 1; i < argc; i++) {
162 char *arg = argv[i];
163 if (is_prefix("-CC", &arg)) {
164 cc = arg;
165 }
166 else if (is_prefix("-O", &arg)) {
167 if (!is_debug)
168 save_arg(&args, argv[i], NULL);
169 }
170 else if (strcmp("-DDEBUG", arg) == 0) {
171 save_arg(&args, arg, NULL);
172 #ifdef __WIN32__
173 set_debug:
174 #endif
175 if (!is_debug) {
176 int j;
177 is_debug = 1;
178 #ifdef __WIN32__
179 save_arg(&args, "-Z7", NULL);
180 CHECK_FIRST_LINK_ARG;
181 save_arg(&link_args, "-debug", NULL);
182 save_arg(&link_args, "-pdb:none", NULL);
183 #endif
184 for (j = 0; j < args.ix; j++) {
185 char *tmp_arg = args.vec[j];
186 if (is_prefix("-O", &tmp_arg))
187 args.vec[j] = "";
188 }
189 }
190 }
191 #ifdef __WIN32__
192 else if (strcmp("-g", arg) == 0) {
193 goto set_debug;
194 }
195 else if (strcmp("-MD", arg) == 0)
196 stdlib = STDLIB_MD;
197 else if (strcmp("-MDd", arg) == 0) {
198 stdlib = STDLIB_MD;
199 goto set_debug;
200 }
201 else if (strcmp("-ML", arg) == 0)
202 stdlib = STDLIB_ML;
203 else if (strcmp("-MLd", arg) == 0) {
204 stdlib = STDLIB_ML;
205 goto set_debug;
206 }
207 else if (strcmp("-MT", arg) == 0)
208 stdlib = STDLIB_MT;
209 else if (strcmp("-MTd", arg) == 0) {
210 stdlib = STDLIB_MT;
211 goto set_debug;
212 }
213 else if (strcmp("-shared", arg) == 0 || strcmp("-LD", arg) == 0)
214 is_shared = 1;
215 else if (strcmp("-LDd", arg) == 0) {
216 is_shared = 1;
217 goto set_debug;
218 }
219 else if (strcmp("-Wall", arg) == 0) {
220 save_arg(&args, "-W3", NULL);
221 }
222 else if (is_prefix("-L", &arg)) {
223 CHECK_FIRST_LINK_ARG;
224 save_arg(&link_args, "-libpath:", arg, NULL);
225 }
226 else if (strcmp("-link",arg) == 0) {
227 CHECK_FIRST_LINK_ARG;
228 }
229 #endif /* #ifdef __WIN32__ */
230 else if (is_prefix("-l", &arg)) {
231 CHECK_FIRST_LINK_ARG;
232 if (is_debug && strcmp("ethread", arg) == 0)
233 arg = "ethread.debug";
234 #ifdef __WIN32__
235 else if (strcmp("socket", arg) == 0)
236 arg = "ws2_32";
237 save_arg(&link_args, arg, ".lib", NULL);
238 #else
239 save_arg(&args, "-l", arg, NULL);
240 #endif
241 }
242 else
243 save_arg(&args, argv[i], NULL);
244 }
245
246 if (!cc || !cc[0]) {
247 fprintf(stderr, "%s: Missing compulsory -CC flag%s", prog, EOL);
248 exit(1);
249 }
250
251 cmd_len = strlen(cc) + 1 + args.chars + 1;
252
253 #ifdef __WIN32__
254 if (is_shared)
255 shared_flag = is_debug ? "-LDd " : "-LD ";
256 switch (stdlib) {
257 case STDLIB_MD: stdlib_flag = is_debug ? "-MDd " : "-MD "; break;
258 case STDLIB_ML: stdlib_flag = is_debug ? "-MLd " : "-ML "; break;
259 case STDLIB_MT: stdlib_flag = is_debug ? "-MTd " : "-MT "; break;
260 case STDLIB_NONE: break;
261 }
262
263 cmd_len += strlen(shared_flag) + strlen(stdlib_flag) + link_args.chars;
264 #endif
265
266 cmd = (char *) malloc(sizeof(char) * cmd_len);
267
268 if (!cmd)
269 enomem();
270 cmd_end = cmd;
271 cpy(&cmd_end, cc);
272 cpy(&cmd_end, " ");
273 #ifdef __WIN32__
274 cpy(&cmd_end, stdlib_flag);
275 cpy(&cmd_end, shared_flag);
276 #endif
277 for (i = 0; i < args.ix; i++)
278 cpy(&cmd_end, args.vec[i]);
279 #ifdef __WIN32__
280 for (i = 0; i < link_args.ix; i++)
281 cpy(&cmd_end, link_args.vec[i]);
282 #endif
283 *cmd_end = '\0';
284
285 printf("==> %s%s", cmd, EOL);
286 fflush(stdout);
287
288 #ifdef USE_EXEC
289 (void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
290 perror(NULL);
291 res = 1;
292 #else
293 res = system(cmd);
294 #endif
295
296 free((void *) args.vec);
297 #ifdef __WIN32__
298 free((void *) link_args.vec);
299 #endif
300 free((void *) cmd);
301
302 if (res < 0)
303 res = 1;
304 return res;
305 }
306