1 /*
2 * Copyright (c) 2003 - 2010, Nils R. Weller
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Driver for cpp, nasm, ncc and ld
28 */
29 #include "driver.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/wait.h>
36 #include <unistd.h>
37 #include <assert.h>
38 #include "exectools.h"
39 #include "backend.h"
40 #include "misc.h"
41 #include "sysdeps.h"
42 #include "debug.h"
43 #include "cc_main.h"
44 #include "defs.h"
45 #include "n_libc.h"
46
47 /*
48 * Store file path referenced by ``name'' in dynamically allocated variable
49 * *output_names, resize it if necessary (*output_index contains the
50 * number of files in use, it is incremented at each call. The variable keeping
51 * track of allocated members in *output_names is static.)
52 */
53 static int
store_file(char *** output_names,int ** output_del,int needdel,char * name,int * output_index)54 store_file(char ***output_names, int **output_del, int needdel,
55 char *name, int *output_index) {
56
57 static int alloc = 0;
58 static int chunk_size = 8;
59 int tmpi = *output_index;
60
61 if (tmpi >= alloc) {
62 alloc += chunk_size;
63
64 /* Quadratically increase number of allocated slots */
65 chunk_size *= chunk_size;
66
67 *output_names =
68 n_xrealloc(*output_names, alloc * sizeof(char *));
69 *output_del =
70 n_xrealloc(*output_del, alloc * sizeof **output_del);
71
72 }
73 (*output_names)[tmpi] = n_xstrdup(name);
74 (*output_del)[tmpi] = needdel;
75 ++(*output_index);
76 return 0;
77 }
78
79 extern int Sflag; /* XXX */
80
81 int
driver(char ** cpp_flags,char * asm_flags,char * ld_flags,char ** files)82 driver(char **cpp_flags, char *asm_flags, char *ld_flags, char **files) {
83 int i;
84 int rc;
85 int out_index = 0;
86 int ld_cmd_len;
87 int has_errors = 0;
88 int sd_host_sys;
89 char *ld_cmd;
90 char **output_names = NULL;
91 char buf[256];
92 int *output_del = NULL;
93 pid_t pid;
94 FILE *fd;
95 char ld_std_flags[512];
96 char ld_pre_std_flags[128];
97 static struct timeval tv;
98
99 *ld_pre_std_flags = 0;
100
101 sd_host_sys = sysdep_get_host_system();
102
103
104 if (archflag == ARCH_X86) {
105 if (sd_host_sys == OS_FREEBSD) {
106 sprintf(ld_std_flags,
107 "-dynamic-linker /usr/libexec/ld-elf.so.1 "
108 "%s /usr/lib/crti.o /usr/lib/crtbegin.o "
109 "-L/usr/lib -lc /usr/lib/crtend.o /usr/lib/crtn.o ",
110 sharedflag? "-shared": "/usr/lib/crt1.o");
111 } else if (sd_host_sys == OS_DRAGONFLYBSD) {
112 /*
113 * Uses same flags as FreeBSD except for ld-elf.so.2 instead
114 * of ld-elf.so.1
115 */
116 sprintf(ld_pre_std_flags, sharedflag? "-shared": "/usr/lib/crt1.o");
117 sprintf(ld_std_flags,
118 "-dynamic-linker /usr/libexec/ld-elf.so.2 "
119 "/usr/lib/crti.o /usr/lib/crtbegin.o "
120 "-L/usr/lib -lc /usr/lib/crtend.o /usr/lib/crtn.o ");
121 } else if (sd_host_sys == OS_MIRBSD) {
122 /*
123 * 07/25/09: XXX Untested!
124 */
125 sprintf(ld_pre_std_flags, sharedflag? "-shared /usr/lib/crtbeginS.o":
126 "/usr/lib/crt0.o /usr/lib/crtbegin.o");
127 sprintf(ld_std_flags, sharedflag?
128 /* "-shared "*/
129 "/usr/lib/crti.o "
130 "/usr/lib/crtendS.o /usr/lib/crtn.o " :
131 "-e __start -dynamic-linker /usr/libexec/ld.so "
132 "/usr/lib/crti.o "
133 "-lc /usr/lib/crtend.o /usr/lib/crtn.o ");
134 } else if (sd_host_sys == OS_OPENBSD) {
135 sprintf(ld_pre_std_flags, "/usr/lib/crt0.o /usr/lib/crtbegin.o");
136 sprintf(ld_std_flags,
137 "-e __start -Bdynamic -dynamic-linker "
138 "/usr/libexec/ld.so"
139 " -lc /usr/lib/crtend.o ");
140 } else if (sd_host_sys == OS_NETBSD) {
141 sprintf(ld_pre_std_flags, "/usr/lib/crt0.o /usr/lib/crtbegin.o");
142 sprintf(ld_std_flags, "-dc -dp -e __start -dynamic-linker "
143 "/usr/libexec/ld.elf_so /usr/lib/crti.o "
144 "-lc /usr/lib/crtend.o /usr/lib/crtn.o ");
145 } else if (sd_host_sys == OS_LINUX) {
146 #ifndef LIBDIR_32
147 #define LIBDIR_32 "/usr/lib/"
148 #define RTLDDIR_32 "/lib/"
149 #endif
150 sprintf(ld_pre_std_flags, sharedflag? "": LIBDIR_32 "crt1.o");
151 sprintf(ld_std_flags,
152 "-lc %s " LIBDIR_32 "crti.o "
153 LIBDIR_32 "crtn.o " LIBDIR_32 "libc.so "
154 "--dynamic-linker " RTLDDIR_32 "ld-linux.so.2 ",
155 sharedflag? "-shared": ""); /*"/usr/lib/crt1.o");*/
156 #undef LIBDIR_32
157 #undef RTLDDIR_32
158 } else if (sd_host_sys == OS_SOLARIS) {
159 sprintf(ld_pre_std_flags, sharedflag? "-shared": "/usr/lib/crt1.o");
160 sprintf(ld_std_flags,
161 "-L/usr/ccs/lib -L/usr/lib -Qy "
162 "/usr/lib/crti.o -lc /usr/lib/crtn.o ");
163 } else if (sd_host_sys == OS_OSX) {
164 sprintf(ld_std_flags,
165 "-dynamic -arch i386 -macosx_version_min 10.5.0 "
166 "-weak_reference_mismatches non-weak -lcrt1.10.5.o "
167 "-lSystem");
168 } else {
169 /* XXX */
170 (void) fprintf(stderr, "This operating system isn't supported"
171 " on x86\n");
172 }
173 } else if (archflag == ARCH_AMD64) {
174 if (sd_host_sys == OS_LINUX) {
175 /*
176 * 08/08/07: Explicitly use lib64 instead of lib
177 * dirs, since some distributions seem to put 32bit
178 * files into plain lib dirs
179 *
180 * 07/24/12: Some 64bit distributions have moved the
181 * locations of library directories again. Specifically,
182 * KUbuntu AMD64 not only stores 64bit libs in /usr/lib,
183 * but also puts the CRT libs we're interested in into
184 * a sub directory titled "x86_64-linux-gnu".
185 * We use configure to attempt to make sense of this.
186 * XXX This should probably be stored in the config file
187 * instead.
188 */
189 #ifndef LIBDIR_64
190 #define LIBDIR_64 "/usr/lib64/"
191 #endif
192 #ifndef RTLDDIR_64
193 #define RTLDDIR_64 "/lib64/"
194 #endif
195
196 sprintf(ld_pre_std_flags, sharedflag? "-shared": LIBDIR_64 "crt1.o");
197 sprintf(ld_std_flags, "-lc " LIBDIR_64 "crti.o "
198 LIBDIR_64 "crtn.o " LIBDIR_64 "libc.so "
199 "--dynamic-linker " RTLDDIR_64 "ld-linux-x86-64.so.2 ");
200 #undef LIBDIR64
201 #undef RTLDDIR_64
202 } else if (sd_host_sys == OS_DRAGONFLYBSD) {
203 sprintf(ld_pre_std_flags, sharedflag? "-shared": "/usr/lib/crt1.o");
204 sprintf(ld_std_flags,
205 "-dynamic-linker /usr/libexec/ld-elf.so.2 "
206 "/usr/lib/crti.o /usr/lib/crtbegin.o "
207 "-L/usr/lib -lc /usr/lib/crtend.o /usr/lib/crtn.o ");
208 } else if (sd_host_sys == OS_FREEBSD) {
209 sprintf(ld_pre_std_flags, sharedflag? "-shared": "/usr/lib/crt1.o");
210 sprintf(ld_std_flags, "/usr/lib/crti.o "
211 "/usr/lib/crtbegin.o -L/usr/lib -lc /usr/lib/crtend.o "
212 "/usr/lib/crtn.o -dynamic-linker /libexec/ld-elf.so.1 ");
213 } else if (sd_host_sys == OS_OPENBSD) {
214 sprintf(ld_pre_std_flags, "/usr/lib/crt0.o /usr/lib/crtbegin.o");
215 sprintf(ld_std_flags, "-Bdynamic "
216 "-dynamic-linker /usr/libexec/ld.so "
217 "-lc /usr/lib/crtend.o "
218 "-L/usr/lib ");
219 } else if (sd_host_sys == OS_OSX) {
220 sprintf(ld_std_flags,
221 "-dynamic -arch x86_64 -macosx_version_min 10.5.0 "
222 "-weak_reference_mismatches non-weak -lcrt1.10.5.o "
223 "-lSystem");
224 } else {
225 /* XXX */
226 (void) fprintf(stderr, "This operating system isn't supported"
227 " on AMD64\n");
228 }
229 } else if (archflag == ARCH_MIPS) {
230 if (sd_host_sys == OS_IRIX) {
231 if (abiflag == ABI_MIPS_N64) {
232 strcpy(ld_std_flags,
233 "-64 /usr/lib64/mips3/crt1.o -L/usr/lib64/mips3 "
234 "-L/usr/lib64 -lc /usr/lib64/mips3/crtn.o ");
235 } else {
236 strcpy(ld_std_flags,
237 "/usr/lib32/crt1.o /usr/lib32/crtn.o "
238 "/usr/lib32/bpcrt.o -lc ");
239 }
240 } else if (sd_host_sys == OS_LINUX) {
241 if (abiflag == ABI_MIPS_N64) {
242 sprintf(ld_pre_std_flags, sharedflag? "-shared": "/usr/lib64/crt1.o");
243 strcpy(ld_std_flags,
244 "-dynamic-linker /lib64/ld.so.1 -melf64ltsmip "
245 "/usr/lib64/crti.o /usr/lib64/crtn.o "
246 "-L/usr/lib64 -lc ");
247 } else {
248 sprintf(ld_pre_std_flags, sharedflag? "-shared": "/usr/lib64/crt1.o");
249 strcpy(ld_std_flags,
250 "-dynamic-linker /lib64/ld.so.1 -melf64ltsmip "
251 "/usr/lib64/crti.o /usr/lib64/crtn.o "
252 "-L/usr/lib64 -lc ");
253 }
254 } else {
255 /* XXX */
256 (void) fprintf(stderr, "This operating system isn't supported"
257 " on MIPS\n");
258 }
259 } else if (archflag == ARCH_POWER) {
260 if (sd_host_sys == OS_AIX) {
261 if (abiflag == ABI_POWER64) {
262 strcpy(ld_std_flags,
263 "-bpT:0x10000000 -bpD:0x20000000 -btextro -b64 "
264 "/lib/crt0_64.o -L/usr/lib -lc ");
265 } else {
266 strcpy(ld_std_flags,
267 "-bpT:0x10000000 -bpD:0x20000000 -btextro /lib/crt0.o -L/usr/lib -lc ");
268 }
269 } else if (sd_host_sys == OS_LINUX) {
270 /*
271 * Because Linux/PPC64 appallingly does not provide crtbegin.o
272 * and crtend.o in standard places, even though they are needed
273 * by crt1.o, which IS provided in standard places, we have to
274 * use a private copy
275 */
276 struct stat sbuf;
277 char *crtbegin = NULL;
278 char *crtend = NULL;
279
280 if (abiflag == ABI_POWER64) {
281 if (stat(INSTALLDIR "/nwcc/lib/crtbegin-64.o", &sbuf)==0) {
282 crtbegin = INSTALLDIR "/nwcc/lib/crtbegin-64.o";
283 } else if (stat("./crtbegin-64.o", &sbuf) == 0) {
284 crtbegin = "./crtbegin-64.o";
285 }
286 if (stat(INSTALLDIR "/nwcc/lib/crtend-64.o", &sbuf)==0) {
287 crtend = INSTALLDIR "/nwcc/lib/crtend-64.o";
288 } else if (stat("./crtend-64.o", &sbuf) == 0) {
289 crtend = "./crtend-64.o";
290 }
291 } else if (sysflag == OS_LINUX) {
292 (void) fprintf(stderr,
293 "ERROR: 32bit mode not implemented for Linux/PPC! Please \n"
294 " contact the author to donate a 32bit account or a\n"
295 " 64bit account with 32bit gcc and libraries.\n");
296 crtbegin = "";
297 crtend = "";
298
299 #if 0
300 /* 32bit */
301 if (stat(INSTALLDIR "/nwcc/lib/crtbegin-32.o", &sbuf)==0) {
302 crtbegin = INSTALLDIR "/nwcc/lib/crtbegin-32.o";
303 } else if (stat("./crtbegin-32.o", &sbuf) == 0) {
304 crtbegin = "./crtbegin-32.o";
305 }
306 if (stat(INSTALLDIR "/nwcc/lib/crtend-32.o", &sbuf)==0) {
307 crtend = INSTALLDIR "/nwcc/lib/crtend-32.o";
308 } else if (stat("./crtend-32.o", &sbuf) == 0) {
309 crtend = "./crtend-32.o";
310 }
311 #endif
312 }
313
314 if (!Sflag) {
315 if (crtbegin == NULL) {
316 (void) fprintf(stderr, "Warning: No crtbegin object found "
317 "in " INSTALLDIR "/nwcc/lib or .!\n");
318 crtbegin = "";
319 }
320 if (crtend == NULL) {
321 (void) fprintf(stderr, "Warning: No crtend object found "
322 "in " INSTALLDIR "/nwcc/lib or .!\n");
323 crtend = "";
324 }
325 if (abiflag == ABI_POWER64) {
326 sprintf(ld_pre_std_flags, "/usr/lib64/crt1.o %s",
327 crtbegin);
328 sprintf(ld_std_flags, "--eh-frame-hdr -Qy -m elf64ppc "
329 "-dynamic-linker /lib64/ld64.so.1 "
330 "-L/lib64 -L/usr/lib64 "
331 "/usr/lib64/crti.o /usr/lib64/crtn.o -lc %s",
332 crtend);
333 } else {
334 unimpl();
335 }
336 }
337 } else {
338 /* XXX */
339 (void) fprintf(stderr, "This operating system isn't supported"
340 " on PPC\n");
341 }
342 } else if (archflag == ARCH_SPARC) {
343 if (sd_host_sys == OS_LINUX) {
344 sprintf(ld_pre_std_flags, "/usr/lib64/crt1.o");
345 strcpy(ld_std_flags, "-m elf64_sparc -Y P,/usr/lib64 "
346 "-dynamic-linker /lib64/ld-linux.so.2 "
347 "-L/lib64 -L/usr/lib64 "
348 "/usr/lib64/crti.o /usr/lib64/crtn.o -lc ");
349 } else if (sd_host_sys == OS_MIRBSD) {
350 /* XXX Untested! */
351 sprintf(ld_pre_std_flags, sharedflag? "-shared /usr/lib/crtbeginS.o":
352 "/usr/lib/crt0.o /usr/lib/crtbegin.o");
353 sprintf(ld_std_flags, sharedflag ?
354 "/usr/lib/crti.o "
355 "/usr/lib/crtendS.o /usr/lib/crtn.o " :
356 "-e __start -dynamic-linker /usr/libexec/ld.so "
357 "/usr/lib/crti.o "
358 "-lc /usr/lib/crtend.o /usr/lib/crtn.o ");
359 } else if (sd_host_sys == OS_SOLARIS) {
360 /*
361 * Because Solaris/SPARC does not ship with crt1.o, we
362 * use our own
363 */
364 struct stat sbuf;
365 char *crt1 = NULL;
366
367 if (abiflag == ABI_SPARC64) {
368 if (stat(INSTALLDIR "/nwcc/lib/crt1-64.o", &sbuf)==0) {
369 crt1 = INSTALLDIR "/nwcc/lib/crt1-64.o";
370 } else if (stat("./crt1-64.o", &sbuf) == 0) {
371 crt1 = "./crt1-64.o";
372 }
373 } else {
374 /* 32bit */
375 if (stat(INSTALLDIR "/nwcc/lib/crt1-32.o", &sbuf)==0) {
376 crt1 = INSTALLDIR "/nwcc/lib/crt1-324.o";
377 } else if (stat("./crt1-32.o", &sbuf) == 0) {
378 crt1 = "./crt1-32.o";
379 }
380 }
381 if (crt1 == NULL) {
382 (void) fprintf(stderr, "Warning: No crt1 object found "
383 "in " INSTALLDIR "/nwcc/lib or .!\n");
384 crt1 = "";
385 }
386
387 if (abiflag == ABI_SPARC64) {
388 /*
389 * /usr/local/lib/gcc/sparc-sun-solaris2.10/3.4.6/crt1.o
390 /sparcv9/crt1.o*/
391 sprintf(ld_std_flags,
392 "/usr/lib/sparcv9/crti.o /usr/lib/sparcv9/crtn.o %s "
393 "-Y \"P,/usr/ccs/lib/sparcv9:/lib/sparcv9"
394 ":/usr/lib/sparcv9\" %s ",
395 sharedflag? "-G -dy -z text": crt1,
396 sharedflag? "": "-lc");
397 } else {
398 sprintf(ld_std_flags,
399 "/usr/lib/crti.o /usr/lib/crtn.o %s "
400 "-Y \"P,/usr/ccs/lib:/lib:/usr/lib\" -lc ",
401 crt1);
402 }
403 } else {
404 /* XXX */
405 (void) fprintf(stderr, "This operating system isn't supported"
406 " on SPARC\n");
407 }
408 } else {
409 unimpl();
410 }
411
412 for (i = 0; files[i] != NULL; ++i) {
413 char *p = strrchr(files[i], '.');
414 char *p2;
415 int needdel = 1;
416
417
418 /*
419 * 02/09/08: Check whether this is really a file (as
420 * opposed to a command line option parameter)
421 */
422 if (files[i][0] == '-') {
423 continue;
424 } else if (argmap[i] && !write_fcat_flag) {
425 continue;
426 }
427
428 /* Ignore files without appropriate extension */
429 if (p == NULL) {
430 continue;
431 }
432 ++p;
433
434 /*
435 * Determine file type to decide which tools (cpp, nasm, ld)
436 * have to be invoked.
437 */
438 #if 0
439 if (assembler == ASM_GAS
440 || archflag == ARCH_MIPS
441 || archflag == ) {
442 #endif
443 {
444
445
446 /*
447 * gas doesn't do foo.c -> foo.o by default. It calls
448 * the output a.out. *barf*
449 * XXX This is kludged
450 */
451 static char *out_ptr;
452 char *filep;
453
454 if ((filep = strrchr(files[i], '/')) != NULL) {
455 ++filep;
456 } else {
457 filep = files[i];
458 }
459
460 if (!cflag || !oflag) {
461 if (out_ptr == NULL) {
462 out_ptr = strchr(asm_flags, 0);
463 }
464 sprintf(out_ptr, " -o %.*s.o",
465 (int)(p - filep - 1), filep);
466 }
467 }
468 #if 0
469 }
470 #endif
471
472 if (strcmp(p, "c") == 0 || strcmp(p, "i") == 0) {
473 p2 = files[i];
474
475 #ifdef DEBUG
476 printf("Preprocessed successfully as %s\n", p2);
477 #endif
478
479 /* Compile file ``p2''. */
480 if ((pid = fork()) == -1) {
481 perror("fork");
482 exit(EXIT_FAILURE);
483 } else if (pid == 0) {
484 char *nwcc1_args[512]; /* XXX */
485 char *arch = NULL;
486 int j = 0;
487 int k = 0;
488
489 nwcc1_args[j++] = "nwcc1";
490 if (stackprotectflag) {
491 nwcc1_args[j++] = "-stackprotect";
492 }
493 if (gnuc_version) {
494 static char gnubuf[128];
495 sprintf(gnubuf, "-gnuc=%s",
496 gnuc_version);
497 nwcc1_args[j++] = gnubuf;
498 }
499 if (std_flag != NULL) {
500 static char std[16];
501 sprintf(std, "-std=%s", std_flag);
502 nwcc1_args[j++] = std;
503 }
504 if (pedanticflag) {
505 nwcc1_args[j++] = "-pedantic";
506 }
507 if (verboseflag) {
508 nwcc1_args[j++] = "-verbose";
509 }
510 if (nostdinc_flag) {
511 nwcc1_args[j++] = "-nostdinc";
512 }
513 if (picflag) {
514 nwcc1_args[j++] = "-fpic";
515 }
516 if (fulltocflag || (!mintocflag && !fulltocflag)) {
517 nwcc1_args[j++] = "-mfull-toc";
518 } else {
519 nwcc1_args[j++] = "-mminimal-toc";
520 }
521 if (stupidtraceflag) {
522 nwcc1_args[j++] = "-stupidtrace";
523 }
524
525
526 if (gflag) {
527 nwcc1_args[j++] = "-g";
528 }
529 if (Eflag) {
530 nwcc1_args[j++] = "-E";
531 }
532 if (Oflag) {
533 static char obuf[16];
534 sprintf(obuf, "-O%d", Oflag);
535 nwcc1_args[j++] = obuf;
536 }
537 if (write_fcat_flag) {
538 nwcc1_args[j++] = "-write-fcat";
539 }
540 if (save_bad_translation_unit_flag) {
541 nwcc1_args[j++] = "-save-bad-translation-unit";
542 }
543
544 /* XXX this should go into misc.c */
545 switch (archflag) {
546 case ARCH_X86:
547 arch = "-arch=x86";
548 break;
549 case ARCH_AMD64:
550 arch = "-arch=amd64";
551 break;
552 case ARCH_POWER:
553 arch = "-arch=ppc";
554 break;
555 case ARCH_MIPS:
556 if (get_target_endianness() == ENDIAN_LITTLE) {
557 arch = "-arch=mipsel";
558 } else {
559 arch = "-arch=mips";
560 }
561 break;
562 case ARCH_SPARC:
563 arch = "-arch=sparc";
564 break;
565 case ARCH_PA:
566 case ARCH_ARM:
567 case ARCH_SH:
568 unimpl();
569 }
570 nwcc1_args[j++] = arch;
571
572 if (abiflag != abiflag_default) {
573 if (abiflag != 0) {
574 nwcc1_args[j++] = /*abi*/
575 abi_to_option(abiflag);
576 }
577 }
578
579 if (sysflag != sysflag_default) {
580 if (sysflag != 0) {
581 nwcc1_args[j++] = sys_to_option(sysflag);
582 }
583 }
584
585 if (asmflag) {
586 nwcc1_args[j] =
587 n_xmalloc(strlen(asmflag)+16);
588 sprintf(nwcc1_args[j++],
589 "-asm=%s", asmflag);
590 }
591 if (cppflag) {
592 nwcc1_args[j] =
593 n_xmalloc(strlen(cppflag+16));
594 sprintf(nwcc1_args[j++],
595 "-cpp=%s", cppflag);
596 }
597 if (timeflag) {
598 nwcc1_args[j++] = n_xstrdup("-time");
599 }
600 if (funsignedchar_flag) {
601 nwcc1_args[j++] = n_xstrdup("-funsigned-char");
602 }
603 if (fsignedchar_flag) {
604 nwcc1_args[j++] = n_xstrdup("-fsigned-char");
605 }
606 if (fnocommon_flag) {
607 nwcc1_args[j++] = n_xstrdup("-fno-common");
608 }
609 if (notgnu_flag) {
610 nwcc1_args[j++] = n_xstrdup("-notgnu");
611 } else {
612 nwcc1_args[j++] = n_xstrdup("-gnu");
613 }
614 if (color_flag) {
615 nwcc1_args[j++] = n_xstrdup("-color");
616 }
617 if (dump_macros_flag) {
618 nwcc1_args[j++] = n_xstrdup("-dM");
619 }
620
621 if (custom_cpp_args) {
622 nwcc1_args[j++] = custom_cpp_args;
623 }
624
625 nwcc1_args[j++] = p2;
626 for (; cpp_flags[k] != NULL; ++j, ++k) {
627 nwcc1_args[j] = cpp_flags[k];
628 }
629 nwcc1_args[j] = NULL;
630 #define DEVEL
631 #ifdef DEVEL
632 execv("./nwcc1", nwcc1_args);
633 #endif
634
635 if ((p = getenv("NWCC_CC1")) != NULL) {
636 execv(p, nwcc1_args);
637 perror(p);
638 } else {
639 #if 0
640 execv("/usr/local/bin/nwcc1",
641 nwcc1_args);
642 perror("/usr/local/bin/nwcc1");
643 #endif
644 execv(INSTALLDIR "/bin/nwcc1",
645 nwcc1_args);
646 perror(INSTALLDIR "/bin/nwcc1");
647 }
648 exit(EXIT_FAILURE);
649 } else {
650 if (waitpid(pid, &rc, 0) == -1) {
651 perror("waitpid");
652 exit(EXIT_FAILURE);
653 }
654 if (dump_macros_flag) {
655 /*
656 * 05/19/09: -dM
657 */
658 exit(EXIT_SUCCESS);
659 }
660 if (rc != 0) {
661 /* Try other files anyway */
662 has_errors = 1;
663 continue;
664 }
665 }
666
667 /*
668 * nwcc just outputs with the same name as the input,
669 * except that the ending is .asm instead of .cpp
670 */
671 #ifdef DEBUG
672 printf("Compiled successfully as %s\n", p2);
673 #endif
674
675 if (Sflag || Eflag || write_fcat_flag) {
676 continue;
677 }
678
679 p = p2;
680 p2 = n_xmalloc(strlen(p2) + sizeof ".asm");
681 strcpy(p2, p);
682 p = strrchr(p2, '.');
683 strcpy(++p, "asm");
684
685 /* Hopefully p2 is a valid .asm file now... */
686 if (timeflag) {
687 start_timer(&tv);
688 }
689
690 if ((p = strrchr(p2, '/')) != NULL) {
691 char *saved = p+1;
692 p2 = do_asm(p+1, asm_flags, abiflag);
693 remove(saved);
694 } else {
695 char *saved_p2 = p2;
696 p2 = do_asm(p2, asm_flags, abiflag);
697 remove(saved_p2);
698 }
699 if (p2 == NULL) {
700 /* Ignore failure, try other files anyway. */
701 continue;
702 }
703
704 if (timeflag) {
705 int res = stop_timer(&tv);
706 (void) fprintf(stderr,
707 "=== Timing for assembling ===\n");
708 (void) fprintf(stderr,
709 " %f sec\n", res / 1000000.0);
710 }
711
712 #ifdef DEBUG
713 printf("Assembled successfully as %s\n", p2);
714 #endif
715 } else if (strcmp(p, "asm") == 0) {
716 p2 = do_asm(files[i], asm_flags, abiflag);
717 if (p2 == NULL) {
718 /* Ignore failure, try other files anyway. */
719 continue;
720 }
721 } else if (strcmp(p, "o") == 0
722 || strcmp(p, "a") == 0
723 || strcmp(p, "so") == 0) {
724 /*
725 * Don't do anything, the name is later just
726 * stored for ld because it is an object,
727 * library archive or shared library file
728 */
729 p2 = files[i];
730 needdel = 0;
731 } else {
732 continue;
733 }
734
735 /*
736 * File ought to be compiled and assembled fine. Store path for
737 * later ld invocation
738 */
739 if (store_file(&output_names, &output_del,
740 needdel, p2, &out_index) != 0) {
741 fprintf(stderr, "Exiting.\n");
742 return 1;
743 }
744 }
745
746 if (i == 0) {
747 fprintf(stderr, "Missing input files.\n");
748 return 1;
749 }
750
751 if (cflag || Sflag || Eflag || write_fcat_flag) return has_errors;
752
753 if (output_names == NULL) {
754 fprintf(stderr, "No valid files to link.\n");
755 return 1;
756 }
757
758 /* Count length of all files plus white spaces and ld flags */
759 ld_cmd_len = 0;
760 for (i = 0; i < out_index; ++i) {
761 ld_cmd_len += strlen(output_names[i]);
762 ++ld_cmd_len; /* white space */
763 }
764 ld_cmd_len += strlen(ld_flags);
765 ld_cmd = malloc(sizeof "ld " + ld_cmd_len + 1 + sizeof ld_std_flags
766 + (custom_ld_args != NULL? strlen(custom_ld_args) + 3: 0)
767 + (xlinker_args != NULL? strlen(xlinker_args) + 3: 0));
768 if (ld_cmd == NULL) {
769 perror("malloc");
770 return 1;
771 }
772
773 if (archflag == ARCH_SPARC) {
774 if (sd_host_sys == OS_LINUX) {
775 strcpy(ld_cmd, "ld ");
776 } else {
777 /* Solaris */
778 if (abiflag == ABI_SPARC64) {
779 strcpy(ld_cmd, "/usr/ccs/bin/sparcv9/ld ");
780 } else {
781 strcpy(ld_cmd, "/usr/ccs/bin/ld ");
782 }
783 }
784 } else {
785 strcpy(ld_cmd, "ld ");
786 }
787
788
789 /*
790 * 07/02/09: CRT modules (and possibly other things) which should be
791 * put at the beginning of the link line
792 */
793 strcat(ld_cmd, ld_pre_std_flags);
794 strcat(ld_cmd, " ");
795
796 for (i = 0; i < out_index; ++i) {
797 strcat(ld_cmd, output_names[i]);
798 strcat(ld_cmd, " ");
799 }
800
801 /*
802 * 11/23/07: Whoops, guess user-defined flags must come before
803 * standard ones (XXX are there exceptions?) because otherwise
804 * things like dummy library stubs in libc.so are given
805 * precedence over user-supplied libraries such as -lpthread or
806 * -lrt
807 */
808 strcat(ld_cmd, ld_flags);
809 strcat(ld_cmd, " ");
810 strcat(ld_cmd, ld_std_flags);
811 if (custom_ld_args != NULL) {
812 char *p;
813
814 /*
815 * Strip commas;
816 *
817 * -Wl,-foo,-bar,-baz
818 *
819 * turns into
820 *
821 * -foo -bar -baz
822 */
823 for (p = custom_ld_args; *p != 0; ++p) {
824 if (*p == ',') {
825 *p = ' ';
826 }
827 }
828 strcat(ld_cmd, " ");
829 strcat(ld_cmd, custom_ld_args);
830 }
831 if (xlinker_args != NULL) {
832 strcat(ld_cmd, " ");
833 strcat(ld_cmd, xlinker_args);
834 }
835
836
837 if (timeflag) {
838 start_timer(&tv);
839 }
840
841 if (verboseflag) {
842 printf("Running: %s\n", ld_cmd);
843 }
844 fd = popen(ld_cmd, "r");
845 if (fd == NULL) {
846 perror("popen");
847 return 1;
848 }
849 while (fgets(buf, sizeof buf, fd)) {
850 printf("%s", buf);
851 }
852
853 if (timeflag) {
854 int res = stop_timer(&tv);
855 (void) fprintf(stderr, "=== Timing of linking ===\n");
856 (void) fprintf(stderr, " %f sec\n", res / 1000000.0);
857 }
858
859 for (i = 0; i < out_index; ++i) {
860 if (output_del[i]) {
861 remove(output_names[i]);
862 }
863 }
864 rc = pclose(fd);
865 if (WIFEXITED(rc)) {
866 rc = WEXITSTATUS(rc);
867 if (rc != 0) {
868 has_errors = 1;
869 } else {
870 if (sflag) {
871 /*
872 * Strip. Note that this is only done here;
873 * i.e. when building an executable file.
874 * When doing ``nwcc -c foo.c -s'', the
875 * flag is silently ignored, just like in
876 * gcc
877 */
878 if ((fd = exec_cmd(1, "strip", " %s", out_file)) != NULL) {
879 rc = pclose(fd);
880 if (!WIFEXITED(rc)
881 || WEXITSTATUS(rc) != 0) {
882 has_errors = 1;
883 }
884 } else {
885 has_errors = 1;
886 }
887 }
888 }
889 } else {
890 has_errors = 1;
891 }
892 return has_errors /*|| ((unsigned)pclose(fd) >> 8)*/ ; /* XXX !!! */
893 }
894
895