1 /* Id: cc.c,v 1.304 2015/12/29 09:27:06 ragge Exp */
2 /* $NetBSD: cc.c,v 1.1.1.7 2016/02/09 20:28:41 plunky Exp $ */
3
4 /*-
5 * Copyright (c) 2011 Joerg Sonnenberger <joerg@NetBSD.org>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * Redistributions of source code and documentation must retain the above
41 * copyright notice, this list of conditions and the following disclaimer.
42 * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditionsand the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed or owned by Caldera
48 * International, Inc.
49 * Neither the name of Caldera International, Inc. nor the names of other
50 * contributors may be used to endorse or promote products derived from
51 * this software without specific prior written permission.
52 *
53 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
54 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
56 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
57 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
58 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
62 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
63 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67 /*
68 * Front-end to the C compiler.
69 *
70 * Brief description of its syntax:
71 * - Files that end with .c are passed via cpp->ccom->as->ld
72 * - Files that end with .i are passed via ccom->as->ld
73 * - Files that end with .S are passed via cpp->as->ld
74 * - Files that end with .s are passed via as->ld
75 * - Files that end with .o are passed directly to ld
76 * - Multiple files may be given on the command line.
77 * - Unrecognized options are all sent directly to ld.
78 * -c or -S cannot be combined with -o if multiple files are given.
79 *
80 * This file should be rewritten readable.
81 */
82 #include "config.h"
83
84 #include <sys/types.h>
85 #ifdef HAVE_SYS_WAIT_H
86 #include <sys/wait.h>
87 #endif
88
89 #include <ctype.h>
90 #include <errno.h>
91 #include <fcntl.h>
92 #ifdef HAVE_LIBGEN_H
93 #include <libgen.h>
94 #endif
95 #include <signal.h>
96 #include <stdarg.h>
97 #include <stdio.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #ifdef HAVE_UNISTD_H
101 #include <unistd.h>
102 #endif
103 #include <assert.h>
104 #include <time.h>
105
106 #ifdef _WIN32
107 #include <windows.h>
108 #include <process.h>
109 #include <io.h>
110 #define F_OK 0x00
111 #define R_OK 0x04
112 #define W_OK 0x02
113 #define X_OK R_OK
114 #endif
115
116 #include "compat.h"
117
118 #include "macdefs.h"
119
120 #include "xalloc.h"
121 #include "strlist.h"
122
123 #include "ccconfig.h"
124 /* C command */
125
126 #define MKS(x) _MKS(x)
127 #define _MKS(x) #x
128
129 /* default program names in pcc */
130 /* May be overridden if cross-compiler is generated */
131 #ifndef CXXPROGNAME /* name as C++ front end */
132 #define CXXPROGNAME "c++"
133 #endif
134 #ifndef CPPROGNAME
135 #define CPPROGNAME "cpp" /* name as CPP front end */
136 #endif
137 #ifndef PREPROCESSOR
138 #define PREPROCESSOR "cpp" /* "real" preprocessor name */
139 #endif
140 #ifndef COMPILER
141 #define COMPILER "ccom"
142 #endif
143 #ifndef CXXCOMPILER
144 #define CXXCOMPILER "cxxcom"
145 #endif
146 #ifndef ASSEMBLER
147 #define ASSEMBLER "as"
148 #endif
149 #ifndef LINKER
150 #define LINKER "ld"
151 #endif
152 char *passp = PREPROCESSOR;
153 char *pass0 = COMPILER;
154 char *passxx0 = CXXCOMPILER;
155 char *as = ASSEMBLER;
156 char *ld = LINKER;
157 char *sysroot = "", *isysroot;
158
159
160 /* crt files using pcc default names */
161 #ifndef CRTBEGIN_S
162 #define CRTBEGIN_S "crtbeginS.o"
163 #endif
164 #ifndef CRTEND_S
165 #define CRTEND_S "crtendS.o"
166 #endif
167 #ifndef CRTBEGIN_T
168 #define CRTBEGIN_T "crtbeginT.o"
169 #endif
170 #ifndef CRTEND_T
171 #define CRTEND_T "crtendT.o"
172 #endif
173 #ifndef CRTBEGIN
174 #define CRTBEGIN "crtbegin.o"
175 #endif
176 #ifndef CRTEND
177 #define CRTEND "crtend.o"
178 #endif
179 #ifndef CRTI
180 #define CRTI "crti.o"
181 #endif
182 #ifndef CRTN
183 #define CRTN "crtn.o"
184 #endif
185 #ifndef CRT0
186 #define CRT0 "crt0.o"
187 #endif
188 #ifndef GCRT0
189 #define GCRT0 "gcrt0.o"
190 #endif
191
192 /* preprocessor stuff */
193 #ifndef STDINC
194 #define STDINC "/usr/include/"
195 #endif
196 #ifdef MULTIARCH_PATH
197 #define STDINC_MA STDINC MULTIARCH_PATH "/"
198 #endif
199
200
201 char *cppadd[] = CPPADD;
202 char *cppmdadd[] = CPPMDADD;
203
204 /* Default libraries and search paths */
205 #ifndef PCCLIBDIR /* set by autoconf */
206 #define PCCLIBDIR NULL
207 #endif
208 #ifndef LIBDIR
209 #define LIBDIR "/usr/lib/"
210 #endif
211 #ifndef DEFLIBDIRS /* default library search paths */
212 #ifdef MULTIARCH_PATH
213 #define DEFLIBDIRS { LIBDIR, LIBDIR MULTIARCH_PATH "/", 0 }
214 #else
215 #define DEFLIBDIRS { LIBDIR, 0 }
216 #endif
217 #endif
218 #ifndef DEFLIBS /* default libraries included */
219 #define DEFLIBS { "-lpcc", "-lc", "-lpcc", 0 }
220 #endif
221 #ifndef DEFPROFLIBS /* default profiling libraries */
222 #define DEFPROFLIBS { "-lpcc", "-lc_p", "-lpcc", 0 }
223 #endif
224 #ifndef DEFCXXLIBS /* default c++ libraries */
225 #define DEFCXXLIBS { "-lp++", "-lpcc", "-lc", "-lpcc", 0 }
226 #endif
227 #ifndef STARTLABEL
228 #define STARTLABEL "__start"
229 #endif
230 #ifndef DYNLINKARG
231 #define DYNLINKARG "-dynamic-linker"
232 #endif
233 #ifndef DYNLINKLIB
234 #define DYNLINKLIB NULL
235 #endif
236
237 char *dynlinkarg = DYNLINKARG;
238 char *dynlinklib = DYNLINKLIB;
239 char *pcclibdir = PCCLIBDIR;
240 char *deflibdirs[] = DEFLIBDIRS;
241 char *deflibs[] = DEFLIBS;
242 char *defproflibs[] = DEFPROFLIBS;
243 char *defcxxlibs[] = DEFCXXLIBS;
244
245 char *outfile, *MFfile, *fname;
246 static char **lav;
247 static int lac;
248 static char *find_file(const char *file, struct strlist *path, int mode);
249 static int preprocess_input(char *input, char *output, int dodep);
250 static int compile_input(char *input, char *output);
251 static int assemble_input(char *input, char *output);
252 static int run_linker(void);
253 static int strlist_exec(struct strlist *l);
254
255 char *cat(const char *, const char *);
256 char *setsuf(char *, char);
257 int cxxsuf(char *);
258 int getsuf(char *);
259 char *getsufp(char *s);
260 int main(int, char *[]);
261 void errorx(int, char *, ...);
262 int cunlink(char *);
263 void exandrm(char *);
264 void dexit(int);
265 void idexit(int);
266 char *gettmp(void);
267 void oerror(char *);
268 char *argnxt(char *, char *);
269 char *nxtopt(char *o);
270 void setup_cpp_flags(void);
271 void setup_ccom_flags(void);
272 void setup_as_flags(void);
273 void setup_ld_flags(void);
274 static void expand_sysroot(void);
275 #ifdef _WIN32
276 char *win32pathsubst(char *);
277 char *win32commandline(struct strlist *l);
278 #endif
279 int sspflag;
280 int freestanding;
281 int Sflag;
282 int cflag;
283 int gflag;
284 int rflag;
285 int vflag;
286 int noexec; /* -### */
287 int tflag;
288 int Eflag;
289 int Oflag;
290 int kflag; /* generate PIC/pic code */
291 #define F_PIC 1
292 #define F_pic 2
293 int Mflag, needM, MDflag, MMDflag; /* dependencies only */
294 int pgflag;
295 int Xflag;
296 int nostartfiles, Bstatic, shared;
297 int nostdinc, nostdlib;
298 int pthreads;
299 int xgnu89, xgnu99, c89defs, c99defs, c11defs;
300 int ascpp;
301 #ifdef CHAR_UNSIGNED
302 int xuchar = 1;
303 #else
304 int xuchar = 0;
305 #endif
306 int cxxflag;
307 int cppflag;
308 int printprogname, printfilename;
309 enum { SC11, STRAD, SC89, SGNU89, SC99, SGNU99 } cstd;
310
311 #ifdef SOFTFLOAT
312 int softfloat = 1;
313 #else
314 int softfloat = 0;
315 #endif
316
317 #ifdef TARGET_BIG_ENDIAN
318 int bigendian = 1;
319 #else
320 int bigendian = 0;
321 #endif
322
323 #ifdef mach_amd64
324 int amd64_i386;
325 #endif
326
327 #define match(a,b) (strcmp(a,b) == 0)
328
329 /* handle gcc warning emulations */
330 struct Wflags {
331 char *name;
332 int flags;
333 #define INWALL 1
334 } Wflags[] = {
335 { "truncate", 0 },
336 { "strict-prototypes", 0 },
337 { "missing-prototypes", 0 },
338 { "implicit-int", INWALL },
339 { "implicit-function-declaration", INWALL },
340 { "shadow", 0 },
341 { "pointer-sign", INWALL },
342 { "sign-compare", 0 },
343 { "unknown-pragmas", INWALL },
344 { "unreachable-code", 0 },
345 { "deprecated-declarations", 0 },
346 { "attributes", 0 },
347 { NULL, 0 },
348 };
349
350 #ifndef USHORT
351 /* copied from mip/manifest.h */
352 #define USHORT 5
353 #define INT 6
354 #define UNSIGNED 7
355 #endif
356
357 /*
358 * Wide char defines.
359 */
360 #if WCHAR_TYPE == USHORT
361 #define WCT "short unsigned int"
362 #define WCM "65535U"
363 #if WCHAR_SIZE != 2
364 #error WCHAR_TYPE vs. WCHAR_SIZE mismatch
365 #endif
366 #elif WCHAR_TYPE == INT
367 #define WCT "int"
368 #define WCM "2147483647"
369 #if WCHAR_SIZE != 4
370 #error WCHAR_TYPE vs. WCHAR_SIZE mismatch
371 #endif
372 #elif WCHAR_TYPE == UNSIGNED
373 #define WCT "unsigned int"
374 #define WCM "4294967295U"
375 #if WCHAR_SIZE != 4
376 #error WCHAR_TYPE vs. WCHAR_SIZE mismatch
377 #endif
378 #else
379 #error WCHAR_TYPE not defined or invalid
380 #endif
381
382 #ifdef GCC_COMPAT
383 #ifndef REGISTER_PREFIX
384 #define REGISTER_PREFIX ""
385 #endif
386 #ifndef USER_LABEL_PREFIX
387 #define USER_LABEL_PREFIX ""
388 #endif
389 #endif
390
391 #ifndef PCC_WINT_TYPE
392 #define PCC_WINT_TYPE "unsigned int"
393 #endif
394
395 #ifndef PCC_SIZE_TYPE
396 #define PCC_SIZE_TYPE "unsigned long"
397 #endif
398
399 #ifndef PCC_PTRDIFF_TYPE
400 #define PCC_PTRDIFF_TYPE "long int"
401 #endif
402
403
404 struct strlist preprocessor_flags;
405 struct strlist depflags;
406 struct strlist incdirs;
407 struct strlist user_sysincdirs;
408 struct strlist includes;
409 struct strlist sysincdirs;
410 struct strlist dirafterdirs;
411 struct strlist crtdirs;
412 struct strlist libdirs;
413 struct strlist progdirs;
414 struct strlist early_linker_flags;
415 struct strlist middle_linker_flags;
416 struct strlist late_linker_flags;
417 struct strlist inputs;
418 struct strlist assembler_flags;
419 struct strlist temp_outputs;
420 struct strlist compiler_flags;
421
422 int
main(int argc,char * argv[])423 main(int argc, char *argv[])
424 {
425 struct Wflags *Wf;
426 struct string *s;
427 char *t, *u, *argp;
428 char *msuffix;
429 int ninput, j;
430
431 lav = argv;
432 lac = argc;
433 ninput = 0;
434
435 strlist_init(&crtdirs);
436 strlist_init(&libdirs);
437 strlist_init(&progdirs);
438 strlist_init(&preprocessor_flags);
439 strlist_init(&incdirs);
440 strlist_init(&user_sysincdirs);
441 strlist_init(&includes);
442 strlist_init(&sysincdirs);
443 strlist_init(&dirafterdirs);
444 strlist_init(&depflags);
445 strlist_init(&early_linker_flags);
446 strlist_init(&middle_linker_flags);
447 strlist_init(&late_linker_flags);
448 strlist_init(&inputs);
449 strlist_init(&assembler_flags);
450 strlist_init(&temp_outputs);
451 strlist_init(&compiler_flags);
452
453 if ((t = strrchr(argv[0], '/')))
454 t++;
455 else
456 t = argv[0];
457
458 if (match(t, CXXPROGNAME)) {
459 cxxflag = 1;
460 } else if (match(t, CPPROGNAME)) {
461 Eflag = cppflag = 1;
462 }
463
464 #ifdef PCC_EARLY_SETUP
465 PCC_EARLY_SETUP
466 #endif
467
468 #ifdef _WIN32
469 /* have to prefix path early. -B may override */
470 incdir = win32pathsubst(incdir);
471 altincdir = win32pathsubst(altincdir);
472 libdir = win32pathsubst(libdir);
473 #ifdef PCCINCDIR
474 pccincdir = win32pathsubst(pccincdir);
475 pxxincdir = win32pathsubst(pxxincdir);
476 #endif
477 #ifdef PCCLIBDIR
478 pcclibdir = win32pathsubst(pcclibdir);
479 #endif
480 passp = win32pathsubst(passp);
481 pass0 = win32pathsubst(pass0);
482 #ifdef STARTFILES
483 for (i = 0; startfiles[i] != NULL; i++)
484 startfiles[i] = win32pathsubst(startfiles[i]);
485 for (i = 0; endfiles[i] != NULL; i++)
486 endfiles[i] = win32pathsubst(endfiles[i]);
487 #endif
488 #ifdef STARTFILES_T
489 for (i = 0; startfiles_T[i] != NULL; i++)
490 startfiles_T[i] = win32pathsubst(startfiles_T[i]);
491 for (i = 0; endfiles_T[i] != NULL; i++)
492 endfiles_T[i] = win32pathsubst(endfiles_T[i]);
493 #endif
494 #ifdef STARTFILES_S
495 for (i = 0; startfiles_S[i] != NULL; i++)
496 startfiles_S[i] = win32pathsubst(startfiles_S[i]);
497 for (i = 0; endfiles_S[i] != NULL; i++)
498 endfiles_S[i] = win32pathsubst(endfiles_S[i]);
499 #endif
500 #endif
501
502 while (--lac) {
503 ++lav;
504 argp = *lav;
505
506 #ifdef PCC_EARLY_ARG_CHECK
507 PCC_EARLY_ARG_CHECK
508 #endif
509
510 if (*argp != '-' || match(argp, "-")) {
511 /* Check for duplicate .o files. */
512 if (getsuf(argp) == 'o') {
513 j = 0;
514 STRLIST_FOREACH(s, &inputs)
515 if (match(argp, s->value))
516 j++;
517 if (j)
518 continue; /* skip it */
519 }
520 strlist_append(&inputs, argp);
521 ninput++;
522 continue;
523 }
524
525 switch (argp[1]) {
526 default:
527 oerror(argp);
528 break;
529
530 case '#':
531 if (match(argp, "-###")) {
532 printf("%s\n", VERSSTR);
533 vflag++;
534 noexec++;
535 } else
536 oerror(argp);
537 break;
538
539 case '-': /* double -'s */
540 if (match(argp, "--version")) {
541 printf("%s\n", VERSSTR);
542 return 0;
543 } else if (strncmp(argp, "--sysroot=", 10) == 0) {
544 sysroot = argp + 10;
545 } else if (strncmp(argp, "--sysroot", 9) == 0) {
546 sysroot = nxtopt(argp);
547 } else if (strcmp(argp, "--param") == 0) {
548 /* NOTHING YET */;
549 (void)nxtopt(0); /* ignore arg */
550 } else
551 oerror(argp);
552 break;
553
554 case 'B': /* other search paths for binaries */
555 t = nxtopt("-B");
556 strlist_append(&crtdirs, t);
557 strlist_append(&libdirs, t);
558 strlist_append(&progdirs, t);
559 break;
560
561 case 'C':
562 if (match(argp, "-C") || match(argp, "-CC"))
563 strlist_append(&preprocessor_flags, argp);
564 else
565 oerror(argp);
566 break;
567
568 case 'c':
569 cflag++;
570 break;
571
572 case 'd': /* debug options */
573 for (t = &argp[2]; *t; t++) {
574 if (*t == 'M')
575 strlist_append(&preprocessor_flags, "-dM");
576
577 /* ignore others */
578 }
579 break;
580
581 case 'E':
582 Eflag++;
583 break;
584
585 case 'f': /* GCC compatibility flags */
586 u = &argp[2];
587 j = 0;
588 if (strncmp(u, "no-", 3) == 0)
589 j = 1, u += 3;
590 if (match(u, "PIC") || match(u, "pic")) {
591 kflag = j ? 0 : *u == 'P' ? F_PIC : F_pic;
592 } else if (match(u, "freestanding")) {
593 freestanding = j ? 0 : 1;
594 } else if (match(u, "signed-char")) {
595 xuchar = j ? 1 : 0;
596 } else if (match(u, "unsigned-char")) {
597 xuchar = j ? 0 : 1;
598 } else if (match(u, "stack-protector") ||
599 match(u, "stack-protector-all")) {
600 sspflag = j ? 0 : 1;
601 }
602 /* silently ignore the rest */
603 break;
604
605 case 'g': /* create debug output */
606 if (argp[2] == '0')
607 gflag = 0;
608 else
609 gflag++;
610 break;
611
612
613 case 'X':
614 Xflag++;
615 break;
616
617 case 'D':
618 case 'U':
619 strlist_append(&preprocessor_flags, argp);
620 if (argp[2] != 0)
621 break;
622 strlist_append(&preprocessor_flags, nxtopt(argp));
623 break;
624
625 case 'I': /* Add include dirs */
626 strlist_append(&incdirs, nxtopt("-I"));
627 break;
628
629 case 'i':
630 if (match(argp, "-isystem")) {
631 strlist_append(&user_sysincdirs, nxtopt(0));
632 } else if (match(argp, "-include")) {
633 strlist_append(&includes, nxtopt(0));
634 } else if (match(argp, "-isysroot")) {
635 isysroot = nxtopt(0);
636 } else if (strcmp(argp, "-idirafter") == 0) {
637 strlist_append(&dirafterdirs, nxtopt(0));
638 } else
639 oerror(argp);
640 break;
641
642 case 'k': /* generate PIC code */
643 kflag = argp[2] ? argp[2] - '0' : F_pic;
644 break;
645
646 case 'l':
647 case 'L':
648 if (argp[2] == 0)
649 argp = cat(argp, nxtopt(0));
650 strlist_append(&inputs, argp);
651 break;
652
653 case 'm': /* target-dependent options */
654 if (strncmp(argp, "-march=", 6) == 0) {
655 strlist_append(&compiler_flags, argp);
656 break;
657 }
658 #ifdef mach_amd64
659 /* need to call i386 ccom for this */
660 if (strcmp(argp, "-melf_i386") == 0) {
661 pass0 = LIBEXECDIR "/ccom_i386";
662 amd64_i386 = 1;
663 break;
664 }
665 #endif
666 #if defined(mach_arm) || defined(mach_mips)
667 if (match(argp, "-mbig-endian")) {
668 bigendian = 1;
669 strlist_append(&compiler_flags, argp);
670 break;
671 }
672 if (match(argp, "-mlittle-endian")) {
673 bigendian = 0;
674 strlist_append(&compiler_flags, argp);
675 break;
676 }
677 if (match(argp, "-msoft-float")) {
678 softfloat = 1;
679 strlist_append(&compiler_flags, argp);
680 break;
681 }
682 #endif
683 #if defined(mach_mips)
684 if (match(argp, "-mhard-float")) {
685 softfloat = 0;
686 strlist_append(&compiler_flags, argp);
687 break;
688 }
689 #endif
690 strlist_append(&middle_linker_flags, argp);
691 if (argp[2] == 0) {
692 t = nxtopt(0);
693 strlist_append(&middle_linker_flags, t);
694 }
695 break;
696
697 case 'n': /* handle -n flags */
698 if (strcmp(argp, "-nostdinc") == 0)
699 nostdinc++;
700 else if (strcmp(argp, "-nostdlib") == 0) {
701 nostdlib++;
702 nostartfiles++;
703 } else if (strcmp(argp, "-nostartfiles") == 0)
704 nostartfiles = 1;
705 else if (strcmp(argp, "-nodefaultlibs") == 0)
706 nostdlib++;
707 else
708 oerror(argp);
709 break;
710
711 case 'p':
712 if (strcmp(argp, "-pg") == 0 ||
713 strcmp(argp, "-p") == 0)
714 pgflag++;
715 else if (strcmp(argp, "-pthread") == 0)
716 pthreads++;
717 else if (strcmp(argp, "-pipe") == 0)
718 /* NOTHING YET */;
719 else if (strcmp(argp, "-pedantic") == 0)
720 /* NOTHING YET */;
721 else if ((t = argnxt(argp, "-print-prog-name="))) {
722 fname = t;
723 printprogname = 1;
724 } else if ((t = argnxt(argp, "-print-file-name="))) {
725 fname = t;
726 printfilename = 1;
727 } else if (match(argp, "-print-libgcc-file-name")) {
728 fname = "libpcc.a";
729 printfilename = 1;
730 } else
731 oerror(argp);
732 break;
733
734 case 'R':
735 if (argp[2] == 0)
736 argp = cat(argp, nxtopt(0));
737 strlist_append(&middle_linker_flags, argp);
738 break;
739
740 case 'r':
741 rflag = 1;
742 break;
743
744 case 'T':
745 strlist_append(&inputs, argp);
746 if (argp[2] == 0 ||
747 strcmp(argp, "-Ttext") == 0 ||
748 strcmp(argp, "-Tdata") == 0 ||
749 strcmp(argp, "-Tbss") == 0)
750 strlist_append(&inputs, nxtopt(0));
751 break;
752
753 case 's':
754 if (match(argp, "-shared")) {
755 shared = 1;
756 } else if (match(argp, "-static")) {
757 Bstatic = 1;
758 } else if (match(argp, "-symbolic")) {
759 strlist_append(&middle_linker_flags,
760 "-Bsymbolic");
761 } else if (strncmp(argp, "-std", 4) == 0) {
762 if (strcmp(&argp[5], "gnu99") == 0 ||
763 strcmp(&argp[5], "gnu9x") == 0)
764 cstd = SGNU99;
765 if (strcmp(&argp[5], "c89") == 0)
766 cstd = SC89;
767 if (strcmp(&argp[5], "gnu89") == 0)
768 cstd = SGNU89;
769 if (strcmp(&argp[5], "c99") == 0)
770 cstd = SC99;
771 } else
772 oerror(argp);
773 break;
774
775 case 'S':
776 Sflag++;
777 cflag++;
778 break;
779
780 case 't':
781 tflag++;
782 cstd = STRAD;
783 break;
784
785 case 'o':
786 if (outfile)
787 errorx(8, "too many -o");
788 outfile = nxtopt("-o");
789 break;
790
791 case 'O':
792 if (argp[2] == '\0')
793 Oflag++;
794 else if (argp[3] == '\0' &&
795 isdigit((unsigned char)argp[2]))
796 Oflag = argp[2] - '0';
797 else if (argp[3] == '\0' && argp[2] == 's')
798 Oflag = 1; /* optimize for space only */
799 else
800 oerror(argp);
801 break;
802
803 case 'P':
804 strlist_append(&preprocessor_flags, argp);
805 break;
806
807 case 'M':
808 needM = 1;
809 if (match(argp, "-M")) {
810 Mflag++;
811 strlist_append(&depflags, argp);
812 } else if (match(argp, "-MP")) {
813 strlist_append(&depflags, "-xMP");
814 } else if (match(argp, "-MF")) {
815 MFfile = nxtopt("-MF");
816 } else if (match(argp, "-MT") || match(argp, "-MQ")) {
817 t = cat("-xMT,", nxtopt("-MT"));
818 t[3] = argp[2];
819 strlist_append(&depflags, t);
820 } else if (match(argp, "-MD")) {
821 MDflag++;
822 needM = 0;
823 strlist_append(&depflags, "-M");
824 } else if (match(argp, "-MMD")) {
825 MMDflag++;
826 needM = 0;
827 strlist_append(&depflags, "-M");
828 strlist_append(&depflags, "-xMMD");
829 } else
830 oerror(argp);
831 break;
832
833 case 'v':
834 printf("%s\n", VERSSTR);
835 vflag++;
836 break;
837
838 case 'w': /* no warnings at all emitted */
839 strlist_append(&compiler_flags, "-w");
840 break;
841
842 case 'W': /* Ignore (most of) W-flags */
843 if ((t = argnxt(argp, "-Wl,"))) {
844 u = strtok(t, ",");
845 do {
846 strlist_append(&inputs, u);
847 } while ((u = strtok(NULL, ",")) != NULL);
848 } else if ((t = argnxt(argp, "-Wa,"))) {
849 u = strtok(t, ",");
850 do {
851 strlist_append(&assembler_flags, u);
852 } while ((u = strtok(NULL, ",")) != NULL);
853 } else if ((t = argnxt(argp, "-Wc,"))) {
854 u = strtok(t, ",");
855 do {
856 strlist_append(&compiler_flags, u);
857 } while ((u = strtok(NULL, ",")) != NULL);
858 } else if ((t = argnxt(argp, "-Wp,"))) {
859 u = strtok(t, ",");
860 do {
861 strlist_append(&preprocessor_flags, u);
862 } while ((u = strtok(NULL, ",")) != NULL);
863 } else if (strcmp(argp, "-Werror") == 0) {
864 strlist_append(&compiler_flags, "-Werror");
865 strlist_append(&preprocessor_flags, "-E");
866 } else if (strcmp(argp, "-Wall") == 0) {
867 for (Wf = Wflags; Wf->name; Wf++)
868 if (Wf->flags & INWALL)
869 strlist_append(&compiler_flags,
870 cat("-W", Wf->name));
871 } else if (strcmp(argp, "-WW") == 0) {
872 for (Wf = Wflags; Wf->name; Wf++)
873 strlist_append(&compiler_flags,
874 cat("-W", Wf->name));
875 } else {
876 /* pass through, if supported */
877 t = &argp[2];
878 if (strncmp(t, "no-", 3) == 0)
879 t += 3;
880 if (strncmp(t, "error=", 6) == 0)
881 t += 6;
882 for (Wf = Wflags; Wf->name; Wf++) {
883 if (strcmp(t, Wf->name) == 0)
884 strlist_append(&compiler_flags,
885 argp);
886 }
887 }
888 break;
889
890 case 'x':
891 t = nxtopt("-x");
892 if (match(t, "none"))
893 strlist_append(&inputs, ")");
894 else if (match(t, "c"))
895 strlist_append(&inputs, ")c");
896 else if (match(t, "assembler"))
897 strlist_append(&inputs, ")s");
898 else if (match(t, "assembler-with-cpp"))
899 strlist_append(&inputs, ")S");
900 else if (match(t, "c++"))
901 strlist_append(&inputs, ")c++");
902 else {
903 strlist_append(&compiler_flags, "-x");
904 strlist_append(&compiler_flags, t);
905 }
906 break;
907
908 }
909 continue;
910
911 }
912
913 /* Sanity checking */
914 if (cppflag) {
915 if (ninput == 0) {
916 strlist_append(&inputs, "-");
917 ninput++;
918 } else if (ninput > 2 || (ninput == 2 && outfile)) {
919 errorx(8, "too many files");
920 } else if (ninput == 2) {
921 outfile = STRLIST_NEXT(STRLIST_FIRST(&inputs))->value;
922 STRLIST_FIRST(&inputs)->next = NULL;
923 ninput--;
924 }
925 }
926 if (tflag && Eflag == 0)
927 errorx(8,"-t only allowed fi -E given");
928
929 /* Correct C standard */
930 switch (cstd) {
931 case STRAD: break;
932 case SC89: c89defs = 1; break;
933 case SGNU89: xgnu89 = c89defs = 1; break;
934 case SC99: c89defs = c99defs = 1; break;
935 case SGNU99: c89defs = c99defs = xgnu99 = 1; break;
936 case SC11: c89defs = c11defs = 1; break;
937 }
938
939 if (ninput == 0 && !(printprogname || printfilename))
940 errorx(8, "no input files");
941 if (outfile && (cflag || Sflag || Eflag) && ninput > 1)
942 errorx(8, "-o given with -c || -E || -S and more than one file");
943 #if 0
944 if (outfile && clist[0] && strcmp(outfile, clist[0]) == 0)
945 errorx(8, "output file will be clobbered");
946 #endif
947
948 if (needM && !Mflag && !MDflag && !MMDflag)
949 errorx(8, "to make dependencies needs -M");
950
951
952 if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */
953 signal(SIGINT, idexit);
954 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) /* terminate */
955 signal(SIGTERM, idexit);
956
957 /* after arg parsing */
958 strlist_append(&progdirs, LIBEXECDIR);
959 if (pcclibdir)
960 strlist_append(&crtdirs, pcclibdir);
961 for (j = 0; deflibdirs[j]; j++) {
962 if (sysroot)
963 deflibdirs[j] = cat(sysroot, deflibdirs[j]);
964 strlist_append(&crtdirs, deflibdirs[j]);
965 }
966
967 setup_cpp_flags();
968 setup_ccom_flags();
969 setup_as_flags();
970
971 if (isysroot == NULL)
972 isysroot = sysroot;
973 expand_sysroot();
974
975 if (printprogname) {
976 printf("%s\n", find_file(fname, &progdirs, X_OK));
977 return 0;
978 } else if (printfilename) {
979 printf("%s\n", find_file(fname, &crtdirs, R_OK));
980 return 0;
981 }
982
983 msuffix = NULL;
984 STRLIST_FOREACH(s, &inputs) {
985 char *suffix;
986 char *ifile, *ofile = NULL;
987
988 ifile = s->value;
989 if (ifile[0] == ')') { /* -x source type given */
990 msuffix = ifile[1] ? &ifile[1] : NULL;
991 continue;
992 }
993 if (ifile[0] == '-' && ifile[1] == 0)
994 suffix = msuffix ? msuffix : "c";
995 else if (ifile[0] == '-')
996 suffix = "o"; /* source files cannot begin with - */
997 else if (msuffix)
998 suffix = msuffix;
999 else
1000 suffix = getsufp(ifile);
1001 /*
1002 * C preprocessor
1003 */
1004 ascpp = match(suffix, "S");
1005 if (ascpp || cppflag || match(suffix, "c") || cxxsuf(suffix)) {
1006 /* find out next output file */
1007 if (Mflag || MDflag || MMDflag) {
1008 char *Mofile = NULL;
1009
1010 if (MFfile)
1011 Mofile = MFfile;
1012 else if (outfile)
1013 Mofile = setsuf(outfile, 'd');
1014 else if (MDflag || MMDflag)
1015 Mofile = setsuf(ifile, 'd');
1016 if (preprocess_input(ifile, Mofile, 1))
1017 exandrm(Mofile);
1018 }
1019 if (Mflag)
1020 continue;
1021 if (Eflag) {
1022 /* last pass */
1023 ofile = outfile;
1024 } else {
1025 /* to temp file */
1026 strlist_append(&temp_outputs, ofile = gettmp());
1027 }
1028 if (preprocess_input(ifile, ofile, 0))
1029 exandrm(ofile);
1030 if (Eflag)
1031 continue;
1032 ifile = ofile;
1033 suffix = match(suffix, "S") ? "s" : "i";
1034 }
1035
1036 /*
1037 * C compiler
1038 */
1039 if (match(suffix, "i")) {
1040 /* find out next output file */
1041 if (Sflag) {
1042 ofile = outfile;
1043 if (outfile == NULL)
1044 ofile = setsuf(s->value, 's');
1045 } else
1046 strlist_append(&temp_outputs, ofile = gettmp());
1047 if (compile_input(ifile, ofile))
1048 exandrm(ofile);
1049 if (Sflag)
1050 continue;
1051 ifile = ofile;
1052 suffix = "s";
1053 }
1054
1055 /*
1056 * Assembler
1057 */
1058 if (match(suffix, "s")) {
1059 if (cflag) {
1060 ofile = outfile;
1061 if (ofile == NULL)
1062 ofile = setsuf(s->value, 'o');
1063 } else {
1064 strlist_append(&temp_outputs, ofile = gettmp());
1065 /* strlist_append linker */
1066 }
1067 if (assemble_input(ifile, ofile))
1068 exandrm(ofile);
1069 ifile = ofile;
1070 }
1071
1072 if (ninput > 1 && !Eflag && ifile == ofile && ifile[0] != '-')
1073 printf("%s:\n", ifile);
1074
1075 strlist_append(&middle_linker_flags, ifile);
1076 }
1077
1078 if (cflag || Eflag || Mflag)
1079 dexit(0);
1080
1081 /*
1082 * Linker
1083 */
1084 setup_ld_flags();
1085 if (run_linker())
1086 exandrm(0);
1087
1088 #ifdef notdef
1089 strlist_free(&crtdirs);
1090 strlist_free(&libdirs);
1091 strlist_free(&progdirs);
1092 strlist_free(&incdirs);
1093 strlist_free(&preprocessor_flags);
1094 strlist_free(&user_sysincdirs);
1095 strlist_free(&includes);
1096 strlist_free(&sysincdirs);
1097 strlist_free(&dirafterdirs);
1098 strlist_free(&depflags);
1099 strlist_free(&early_linker_flags);
1100 strlist_free(&middle_linker_flags);
1101 strlist_free(&late_linker_flags);
1102 strlist_free(&inputs);
1103 strlist_free(&assembler_flags);
1104 strlist_free(&temp_outputs);
1105 strlist_free(&compiler_flags);
1106 #endif
1107 dexit(0);
1108 return 0;
1109 }
1110
1111 /*
1112 * exit and cleanup after interrupt.
1113 */
1114 void
idexit(int arg)1115 idexit(int arg)
1116 {
1117 dexit(100);
1118 }
1119
1120 /*
1121 * exit and cleanup.
1122 */
1123 void
dexit(int eval)1124 dexit(int eval)
1125 {
1126 struct string *s;
1127
1128 if (!Xflag) {
1129 STRLIST_FOREACH(s, &temp_outputs)
1130 cunlink(s->value);
1131 }
1132 exit(eval);
1133 }
1134
1135 /*
1136 * Called when something failed.
1137 */
1138 void
exandrm(char * s)1139 exandrm(char *s)
1140 {
1141 if (s && *s)
1142 strlist_append(&temp_outputs, s);
1143 dexit(1);
1144 }
1145
1146 /*
1147 * complain and exit.
1148 */
1149 void
errorx(int eval,char * s,...)1150 errorx(int eval, char *s, ...)
1151 {
1152 va_list ap;
1153
1154 va_start(ap, s);
1155 fputs("error: ", stderr);
1156 vfprintf(stderr, s, ap);
1157 putc('\n', stderr);
1158 va_end(ap);
1159 dexit(eval);
1160 }
1161
1162 static char *
find_file(const char * file,struct strlist * path,int mode)1163 find_file(const char *file, struct strlist *path, int mode)
1164 {
1165 struct string *s;
1166 char *f;
1167 size_t lf, lp;
1168 int need_sep;
1169
1170 lf = strlen(file);
1171 STRLIST_FOREACH(s, path) {
1172 lp = strlen(s->value);
1173 need_sep = (lp && s->value[lp - 1] != '/') ? 1 : 0;
1174 f = xmalloc(lp + lf + need_sep + 1);
1175 memcpy(f, s->value, lp);
1176 if (need_sep)
1177 f[lp] = '/';
1178 memcpy(f + lp + need_sep, file, lf + 1);
1179 if (access(f, mode) == 0)
1180 return f;
1181 free(f);
1182 }
1183 return xstrdup(file);
1184 }
1185
1186 #ifdef TWOPASS
1187 static int
compile_input(char * input,char * output)1188 compile_input(char *input, char *output)
1189 {
1190 struct strlist args;
1191 char *tfile;
1192 int retval;
1193
1194 strlist_append(&temp_outputs, tfile = gettmp());
1195
1196 strlist_init(&args);
1197 strlist_append_list(&args, &compiler_flags);
1198 strlist_append(&args, input);
1199 strlist_append(&args, tfile);
1200 strlist_prepend(&args,
1201 find_file(cxxflag ? "cxx0" : "cc0", &progdirs, X_OK));
1202 retval = strlist_exec(&args);
1203 strlist_free(&args);
1204 if (retval)
1205 return retval;
1206
1207 strlist_init(&args);
1208 strlist_append_list(&args, &compiler_flags);
1209 strlist_append(&args, tfile);
1210 strlist_append(&args, output);
1211 strlist_prepend(&args,
1212 find_file(cxxflag ? "cxx1" : "cc1", &progdirs, X_OK));
1213 retval = strlist_exec(&args);
1214 strlist_free(&args);
1215 return retval;
1216 }
1217 #else
1218 static int
compile_input(char * input,char * output)1219 compile_input(char *input, char *output)
1220 {
1221 struct strlist args;
1222 int retval;
1223
1224 strlist_init(&args);
1225 strlist_append_list(&args, &compiler_flags);
1226 strlist_append(&args, input);
1227 strlist_append(&args, output);
1228 strlist_prepend(&args,
1229 find_file(cxxflag ? passxx0 : pass0, &progdirs, X_OK));
1230 retval = strlist_exec(&args);
1231 strlist_free(&args);
1232 return retval;
1233 }
1234 #endif
1235
1236 static int
assemble_input(char * input,char * output)1237 assemble_input(char *input, char *output)
1238 {
1239 struct strlist args;
1240 int retval;
1241
1242 strlist_init(&args);
1243 #ifdef PCC_EARLY_AS_ARGS
1244 PCC_EARLY_AS_ARGS
1245 #endif
1246 strlist_append_list(&args, &assembler_flags);
1247 strlist_append(&args, input);
1248 strlist_append(&args, "-o");
1249 strlist_append(&args, output);
1250 strlist_prepend(&args,
1251 find_file(as, &progdirs, X_OK));
1252 #ifdef PCC_LATE_AS_ARGS
1253 PCC_LATE_AS_ARGS
1254 #endif
1255 retval = strlist_exec(&args);
1256 strlist_free(&args);
1257 return retval;
1258 }
1259
1260 static int
preprocess_input(char * input,char * output,int dodep)1261 preprocess_input(char *input, char *output, int dodep)
1262 {
1263 struct strlist args;
1264 struct string *s;
1265 int retval;
1266
1267 strlist_init(&args);
1268 strlist_append_list(&args, &preprocessor_flags);
1269 if (ascpp) {
1270 strlist_append(&args, "-A");
1271 strlist_append(&args, "-D__ASSEMBLER__");
1272 }
1273 STRLIST_FOREACH(s, &includes) {
1274 strlist_append(&args, "-i");
1275 strlist_append(&args, s->value);
1276 }
1277 STRLIST_FOREACH(s, &incdirs) {
1278 strlist_append(&args, "-I");
1279 strlist_append(&args, s->value);
1280 }
1281 STRLIST_FOREACH(s, &user_sysincdirs) {
1282 strlist_append(&args, "-S");
1283 strlist_append(&args, s->value);
1284 }
1285 if (!nostdinc) {
1286 STRLIST_FOREACH(s, &sysincdirs) {
1287 strlist_append(&args, "-S");
1288 strlist_append(&args, s->value);
1289 }
1290 }
1291 STRLIST_FOREACH(s, &dirafterdirs) {
1292 strlist_append(&args, "-S");
1293 strlist_append(&args, s->value);
1294 }
1295 if (dodep)
1296 strlist_append_list(&args, &depflags);
1297 strlist_append(&args, input);
1298 if (output)
1299 strlist_append(&args, output);
1300
1301 strlist_prepend(&args, find_file(passp, &progdirs, X_OK));
1302 retval = strlist_exec(&args);
1303 strlist_free(&args);
1304 return retval;
1305 }
1306
1307 static int
run_linker(void)1308 run_linker(void)
1309 {
1310 struct strlist linker_flags;
1311 int retval;
1312
1313 if (outfile) {
1314 strlist_prepend(&early_linker_flags, outfile);
1315 strlist_prepend(&early_linker_flags, "-o");
1316 }
1317 strlist_init(&linker_flags);
1318 strlist_append_list(&linker_flags, &early_linker_flags);
1319 strlist_append_list(&linker_flags, &middle_linker_flags);
1320 strlist_append_list(&linker_flags, &late_linker_flags);
1321 strlist_prepend(&linker_flags, find_file(ld, &progdirs, X_OK));
1322
1323 retval = strlist_exec(&linker_flags);
1324
1325 strlist_free(&linker_flags);
1326 return retval;
1327 }
1328
1329 static char *cxxt[] = { "cc", "cp", "cxx", "cpp", "CPP", "c++", "C" };
1330 int
cxxsuf(char * s)1331 cxxsuf(char *s)
1332 {
1333 unsigned i;
1334 for (i = 0; i < sizeof(cxxt)/sizeof(cxxt[0]); i++)
1335 if (strcmp(s, cxxt[i]) == 0)
1336 return 1;
1337 return 0;
1338 }
1339
1340 char *
getsufp(char * s)1341 getsufp(char *s)
1342 {
1343 register char *p;
1344
1345 if ((p = strrchr(s, '.')) && p[1] != '\0')
1346 return &p[1];
1347 return "";
1348 }
1349
1350 int
getsuf(char * s)1351 getsuf(char *s)
1352 {
1353 register char *p;
1354
1355 if ((p = strrchr(s, '.')) && p[1] != '\0' && p[2] == '\0')
1356 return p[1];
1357 return(0);
1358 }
1359
1360 /*
1361 * Get basename of string s, copy it and change its suffix to ch.
1362 */
1363 char *
setsuf(char * s,char ch)1364 setsuf(char *s, char ch)
1365 {
1366 char *e, *p, *rp;
1367
1368 e = NULL;
1369 for (p = s; *p; p++) {
1370 if (*p == '/')
1371 s = p + 1;
1372 if (*p == '.')
1373 e = p;
1374 }
1375 if (s > e)
1376 e = p;
1377
1378 rp = p = xmalloc(e - s + 3);
1379 while (s < e)
1380 *p++ = *s++;
1381
1382 *p++ = '.';
1383 *p++ = ch;
1384 *p = '\0';
1385 return rp;
1386 }
1387
1388 #ifdef _WIN32
1389
1390 static int
strlist_exec(struct strlist * l)1391 strlist_exec(struct strlist *l)
1392 {
1393 char *cmd;
1394 STARTUPINFO si;
1395 PROCESS_INFORMATION pi;
1396 DWORD exitCode;
1397 BOOL ok;
1398
1399 cmd = win32commandline(l);
1400 if (vflag)
1401 printf("%s\n", cmd);
1402 if (noexec)
1403 return 0;
1404
1405 ZeroMemory(&si, sizeof(STARTUPINFO));
1406 si.cb = sizeof(STARTUPINFO);
1407 ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
1408
1409 ok = CreateProcess(NULL, // the executable program
1410 cmd, // the command line arguments
1411 NULL, // ignored
1412 NULL, // ignored
1413 TRUE, // inherit handles
1414 HIGH_PRIORITY_CLASS,
1415 NULL, // ignored
1416 NULL, // ignored
1417 &si,
1418 &pi);
1419
1420 if (!ok)
1421 errorx(100, "Can't find %s\n", STRLIST_FIRST(l)->value);
1422
1423 WaitForSingleObject(pi.hProcess, INFINITE);
1424 GetExitCodeProcess(pi.hProcess, &exitCode);
1425 CloseHandle(pi.hProcess);
1426 CloseHandle(pi.hThread);
1427
1428 return (exitCode != 0);
1429 }
1430
1431 #else
1432
1433 static int
strlist_exec(struct strlist * l)1434 strlist_exec(struct strlist *l)
1435 {
1436 sig_atomic_t exit_now = 0;
1437 sig_atomic_t child;
1438 char **argv;
1439 size_t argc;
1440 int result;
1441
1442 strlist_make_array(l, &argv, &argc);
1443 if (vflag) {
1444 printf("Calling ");
1445 strlist_print(l, stdout, noexec);
1446 printf("\n");
1447 }
1448 if (noexec)
1449 return 0;
1450
1451 switch ((child = fork())) {
1452 case 0:
1453 execvp(argv[0], argv);
1454 result = write(STDERR_FILENO, "Exec of ", 8);
1455 result = write(STDERR_FILENO, argv[0], strlen(argv[0]));
1456 result = write(STDERR_FILENO, " failed\n", 8);
1457 (void)result;
1458 _exit(127);
1459 case -1:
1460 errorx(1, "fork failed");
1461 default:
1462 while (waitpid(child, &result, 0) == -1 && errno == EINTR)
1463 /* nothing */(void)0;
1464 result = WEXITSTATUS(result);
1465 if (result)
1466 errorx(1, "%s terminated with status %d", argv[0], result);
1467 while (argc-- > 0)
1468 free(argv[argc]);
1469 free(argv);
1470 break;
1471 }
1472 return exit_now;
1473 }
1474
1475 #endif
1476
1477 /*
1478 * Catenate two (optional) strings together
1479 */
1480 char *
cat(const char * a,const char * b)1481 cat(const char *a, const char *b)
1482 {
1483 size_t len;
1484 char *rv;
1485
1486 len = (a ? strlen(a) : 0) + (b ? strlen(b) : 0) + 1;
1487 rv = xmalloc(len);
1488 snprintf(rv, len, "%s%s", (a ? a : ""), (b ? b : ""));
1489 return rv;
1490 }
1491
1492 int
cunlink(char * f)1493 cunlink(char *f)
1494 {
1495 if (f==0 || Xflag)
1496 return(0);
1497 return (unlink(f));
1498 }
1499
1500 #ifdef _WIN32
1501 char *
gettmp(void)1502 gettmp(void)
1503 {
1504 DWORD pathSize;
1505 char pathBuffer[MAX_PATH + 1];
1506 char tempFilename[MAX_PATH];
1507 UINT uniqueNum;
1508
1509 pathSize = GetTempPath(sizeof(pathBuffer), pathBuffer);
1510 if (pathSize == 0 || pathSize > sizeof(pathBuffer))
1511 pathBuffer[0] = '\0';
1512 uniqueNum = GetTempFileName(pathBuffer, "ctm", 0, tempFilename);
1513 if (uniqueNum == 0)
1514 errorx(8, "GetTempFileName failed: path \"%s\"", pathBuffer);
1515
1516 return xstrdup(tempFilename);
1517 }
1518
1519 #else
1520
1521 char *
gettmp(void)1522 gettmp(void)
1523 {
1524 char *sfn = xstrdup("/tmp/ctm.XXXXXX");
1525 int fd = -1;
1526
1527 if ((fd = mkstemp(sfn)) == -1)
1528 errorx(8, "%s: %s\n", sfn, strerror(errno));
1529 close(fd);
1530 return sfn;
1531 }
1532 #endif
1533
1534 static void
expand_sysroot(void)1535 expand_sysroot(void)
1536 {
1537 struct string *s;
1538 struct strlist *lists[] = { &crtdirs, &sysincdirs, &incdirs,
1539 &user_sysincdirs, &libdirs, &progdirs, &dirafterdirs, NULL };
1540 const char *sysroots[] = { sysroot, isysroot, isysroot, isysroot,
1541 sysroot, sysroot, isysroot, NULL };
1542 size_t i, sysroot_len, value_len;
1543 char *path;
1544
1545 assert(sizeof(lists) / sizeof(lists[0]) ==
1546 sizeof(sysroots) / sizeof(sysroots[0]));
1547
1548 for (i = 0; lists[i] != NULL; ++i) {
1549 STRLIST_FOREACH(s, lists[i]) {
1550 if (s->value[0] != '=')
1551 continue;
1552 sysroot_len = strlen(sysroots[i]);
1553 /* Skipped '=' compensates additional space for '\0' */
1554 value_len = strlen(s->value);
1555 path = xmalloc(sysroot_len + value_len);
1556 memcpy(path, sysroots[i], sysroot_len);
1557 memcpy(path + sysroot_len, s->value + 1, value_len);
1558 free(s->value);
1559 s->value = path;
1560 }
1561 }
1562 }
1563
1564 void
oerror(char * s)1565 oerror(char *s)
1566 {
1567 errorx(8, "unknown option '%s'", s);
1568 }
1569
1570 /*
1571 * See if m matches the beginning of string str, if it does return the
1572 * remaining of str, otherwise NULL.
1573 */
1574 char *
argnxt(char * str,char * m)1575 argnxt(char *str, char *m)
1576 {
1577 if (strncmp(str, m, strlen(m)))
1578 return NULL; /* No match */
1579 return str + strlen(m);
1580 }
1581
1582 /*
1583 * Return next argument to option, or complain.
1584 */
1585 char *
nxtopt(char * o)1586 nxtopt(char *o)
1587 {
1588 int l;
1589
1590 if (o != NULL) {
1591 l = strlen(o);
1592 if (lav[0][l] != 0)
1593 return &lav[0][l];
1594 }
1595 if (lac == 1)
1596 errorx(8, "missing argument to '%s'", o);
1597 lav++;
1598 lac--;
1599 return lav[0];
1600 }
1601
1602 struct flgcheck {
1603 int *flag;
1604 int set;
1605 char *def;
1606 } cppflgcheck[] = {
1607 { &vflag, 1, "-v" },
1608 { &c99defs, 1, "-D__STDC_VERSION__=199901L" },
1609 { &c11defs, 1, "-D__STDC_VERSION__=201112L" },
1610 { &c89defs, 1, "-D__STDC__=1" },
1611 { &freestanding, 1, "-D__STDC_HOSTED__=0" },
1612 { &freestanding, 0, "-D__STDC_HOSTED__=1" },
1613 { &cxxflag, 1, "-D__cplusplus" },
1614 { &xuchar, 1, "-D__CHAR_UNSIGNED__" },
1615 { &sspflag, 1, "-D__SSP__" },
1616 { &pthreads, 1, "-D_PTHREADS" },
1617 { &Oflag, 1, "-D__OPTIMIZE__" },
1618 { &tflag, 1, "-t" },
1619 { &kflag, 1, "-D__PIC__" },
1620 { 0 },
1621 };
1622
1623 static void
cksetflags(struct flgcheck * fs,struct strlist * sl,int which)1624 cksetflags(struct flgcheck *fs, struct strlist *sl, int which)
1625 {
1626 void (*fn)(struct strlist *, const char *);
1627
1628 fn = which == 'p' ? strlist_prepend : strlist_append;
1629 for (; fs->flag; fs++) {
1630 if (fs->set && *fs->flag)
1631 fn(sl, fs->def);
1632 if (!fs->set && !*fs->flag)
1633 fn(sl, fs->def);
1634 }
1635 }
1636
1637 #ifndef TARGET_LE
1638 #define TARGET_LE 1
1639 #define TARGET_BE 2
1640 #define TARGET_PDP 3
1641 #define TARGET_ANY 4
1642 #endif
1643
1644 static char *defflags[] = {
1645 "-D__PCC__=" MKS(PCC_MAJOR),
1646 "-D__PCC_MINOR__=" MKS(PCC_MINOR),
1647 "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR),
1648 "-D__VERSION__=" MKS(VERSSTR),
1649 "-D__SCHAR_MAX__=" MKS(MAX_CHAR),
1650 "-D__SHRT_MAX__=" MKS(MAX_SHORT),
1651 "-D__INT_MAX__=" MKS(MAX_INT),
1652 "-D__LONG_MAX__=" MKS(MAX_LONG),
1653 "-D__LONG_LONG_MAX__=" MKS(MAX_LONGLONG),
1654
1655 "-D__STDC_ISO_10646__=200009L",
1656 "-D__WCHAR_TYPE__=" WCT,
1657 "-D__SIZEOF_WCHAR_T__=" MKS(WCHAR_SIZE),
1658 "-D__WCHAR_MAX__=" WCM,
1659 "-D__WINT_TYPE__=" PCC_WINT_TYPE,
1660 "-D__SIZE_TYPE__=" PCC_SIZE_TYPE,
1661 "-D__PTRDIFF_TYPE__=" PCC_PTRDIFF_TYPE,
1662 "-D__SIZEOF_WINT_T__=4",
1663 "-D__ORDER_LITTLE_ENDIAN__=1234",
1664 "-D__ORDER_BIG_ENDIAN__=4321",
1665 "-D__ORDER_PDP_ENDIAN__=3412",
1666 #ifndef NO_C11
1667 "-D__STDC_UTF_16__=1",
1668 "-D__STDC_UTF_32__=1",
1669 "-D__STDC_NO_ATOMICS__=1",
1670 "-D__STDC_NO_THREADS__=1",
1671 #endif
1672
1673 /*
1674 * These should probably be changeable during runtime...
1675 */
1676 #if TARGET_ENDIAN == TARGET_BE
1677 "-D__FLOAT_WORD_ORDER__=__ORDER_BIG_ENDIAN__",
1678 "-D__BYTE_ORDER__=__ORDER_BIG_ENDIAN__",
1679 #elif TARGET_ENDIAN == TARGET_PDP
1680 "-D__FLOAT_WORD_ORDER__=__ORDER_PDP_ENDIAN__",
1681 "-D__BYTE_ORDER__=__ORDER_PDP_ENDIAN__",
1682 #elif TARGET_ENDIAN == TARGET_LE
1683 "-D__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__",
1684 "-D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__",
1685 #else
1686 #error Unknown endian...
1687 #endif
1688 };
1689
1690 static char *gcppflags[] = {
1691 #ifndef os_win32
1692 #ifdef GCC_COMPAT
1693 "-D__GNUC__=4",
1694 "-D__GNUC_MINOR__=3",
1695 "-D__GNUC_PATCHLEVEL__=1",
1696 "-D__REGISTER_PREFIX__=" REGISTER_PREFIX,
1697 "-D__USER_LABEL_PREFIX__=" USER_LABEL_PREFIX,
1698 #if SZLONG == 64
1699 "-D__SIZEOF_LONG__=8",
1700 #elif SZLONG == 32
1701 "-D__SIZEOF_LONG__=4",
1702 #endif
1703 #if SZPOINT(CHAR) == 64
1704 "-D__SIZEOF_POINTER__=8",
1705 #elif SZPOINT(CHAR) == 32
1706 "-D__SIZEOF_POINTER__=4",
1707 #endif
1708 #endif
1709 #endif
1710 NULL
1711 };
1712
1713 /* These should _not_ be defined here */
1714 static char *fpflags[] = {
1715 #ifdef TARGET_FLT_EVAL_METHOD
1716 "-D__FLT_EVAL_METHOD__=" MKS(TARGET_FLT_EVAL_METHOD),
1717 #endif
1718 #if defined(os_darwin) || defined(os_netbsd) || defined(os_minix)
1719 "-D__FLT_RADIX__=2",
1720 #if defined(mach_vax)
1721 "-D__FLT_DIG__=6",
1722 "-D__FLT_EPSILON__=1.19209290e-07F",
1723 "-D__FLT_MANT_DIG__=24",
1724 "-D__FLT_MAX_10_EXP__=38",
1725 "-D__FLT_MAX_EXP__=127",
1726 "-D__FLT_MAX__=1.70141173e+38F",
1727 "-D__FLT_MIN_10_EXP__=(-38)",
1728 "-D__FLT_MIN_EXP__=(-127)",
1729 "-D__FLT_MIN__=2.93873588e-39F",
1730 "-D__DBL_DIG__=16",
1731 "-D__DBL_EPSILON__=2.77555756156289135e-17",
1732 "-D__DBL_MANT_DIG__=56",
1733 "-D__DBL_MAX_10_EXP__=38",
1734 "-D__DBL_MAX_EXP__=127",
1735 "-D__DBL_MAX__=1.701411834604692294e+38",
1736 "-D__DBL_MIN_10_EXP__=(-38)",
1737 "-D__DBL_MIN_EXP__=(-127)",
1738 "-D__DBL_MIN__=2.938735877055718770e-39",
1739 #else
1740 "-D__FLT_DIG__=6",
1741 "-D__FLT_EPSILON__=1.19209290e-07F",
1742 "-D__FLT_MANT_DIG__=24",
1743 "-D__FLT_MAX_10_EXP__=38",
1744 "-D__FLT_MAX_EXP__=128",
1745 "-D__FLT_MAX__=3.40282347e+38F",
1746 "-D__FLT_MIN_10_EXP__=(-37)",
1747 "-D__FLT_MIN_EXP__=(-125)",
1748 "-D__FLT_MIN__=1.17549435e-38F",
1749 "-D__DBL_DIG__=15",
1750 "-D__DBL_EPSILON__=2.2204460492503131e-16",
1751 "-D__DBL_MANT_DIG__=53",
1752 "-D__DBL_MAX_10_EXP__=308",
1753 "-D__DBL_MAX_EXP__=1024",
1754 "-D__DBL_MAX__=1.7976931348623157e+308",
1755 "-D__DBL_MIN_10_EXP__=(-307)",
1756 "-D__DBL_MIN_EXP__=(-1021)",
1757 "-D__DBL_MIN__=2.2250738585072014e-308",
1758 #endif
1759 #if defined(mach_i386) || defined(mach_amd64)
1760 "-D__LDBL_DIG__=18",
1761 "-D__LDBL_EPSILON__=1.08420217248550443401e-19L",
1762 "-D__LDBL_MANT_DIG__=64",
1763 "-D__LDBL_MAX_10_EXP__=4932",
1764 "-D__LDBL_MAX_EXP__=16384",
1765 "-D__LDBL_MAX__=1.18973149535723176502e+4932L",
1766 "-D__LDBL_MIN_10_EXP__=(-4931)",
1767 "-D__LDBL_MIN_EXP__=(-16381)",
1768 "-D__LDBL_MIN__=3.36210314311209350626e-4932L",
1769 #elif defined(mach_vax)
1770 "-D__LDBL_DIG__=16",
1771 "-D__LDBL_EPSILON__=2.77555756156289135e-17",
1772 "-D__LDBL_MANT_DIG__=56",
1773 "-D__LDBL_MAX_10_EXP__=38",
1774 "-D__LDBL_MAX_EXP__=127",
1775 "-D__LDBL_MAX__=1.701411834604692294e+38",
1776 "-D__LDBL_MIN_10_EXP__=(-38)",
1777 "-D__LDBL_MIN_EXP__=(-127)",
1778 "-D__LDBL_MIN__=2.938735877055718770e-39",
1779 #else
1780 "-D__LDBL_DIG__=15",
1781 "-D__LDBL_EPSILON__=2.2204460492503131e-16",
1782 "-D__LDBL_MANT_DIG__=53",
1783 "-D__LDBL_MAX_10_EXP__=308",
1784 "-D__LDBL_MAX_EXP__=1024",
1785 "-D__LDBL_MAX__=1.7976931348623157e+308",
1786 "-D__LDBL_MIN_10_EXP__=(-307)",
1787 "-D__LDBL_MIN_EXP__=(-1021)",
1788 "-D__LDBL_MIN__=2.2250738585072014e-308",
1789 #endif
1790 #endif
1791 NULL
1792 };
1793
1794 /*
1795 * Configure the standard cpp flags.
1796 */
1797 void
setup_cpp_flags(void)1798 setup_cpp_flags(void)
1799 {
1800 int i;
1801
1802 /* a bunch of misc defines */
1803 for (i = 0; i < (int)sizeof(defflags)/(int)sizeof(char *); i++)
1804 strlist_prepend(&preprocessor_flags, defflags[i]);
1805
1806 for (i = 0; gcppflags[i]; i++)
1807 strlist_prepend(&preprocessor_flags, gcppflags[i]);
1808 strlist_prepend(&preprocessor_flags, xgnu89 ?
1809 "-D__GNUC_GNU_INLINE__" : "-D__GNUC_STDC_INLINE__");
1810
1811 cksetflags(cppflgcheck, &preprocessor_flags, 'p');
1812
1813 /* Create time and date defines */
1814 if (tflag == 0) {
1815 char buf[100]; /* larger than needed */
1816 time_t t = time(NULL);
1817 char *n = ctime(&t);
1818
1819 n[19] = 0;
1820 snprintf(buf, sizeof buf, "-D__TIME__=\"%s\"", n+11);
1821 strlist_prepend(&preprocessor_flags, xstrdup(buf));
1822
1823 n[24] = n[11] = 0;
1824 snprintf(buf, sizeof buf, "-D__DATE__=\"%s%s\"", n+4, n+20);
1825 strlist_prepend(&preprocessor_flags, xstrdup(buf));
1826 }
1827
1828 for (i = 0; fpflags[i]; i++)
1829 strlist_prepend(&preprocessor_flags, fpflags[i]);
1830
1831 for (i = 0; cppadd[i]; i++)
1832 strlist_prepend(&preprocessor_flags, cppadd[i]);
1833 for (i = 0; cppmdadd[i]; i++)
1834 strlist_prepend(&preprocessor_flags, cppmdadd[i]);
1835
1836 /* Include dirs */
1837 strlist_append(&sysincdirs, "=" INCLUDEDIR "pcc/");
1838 #ifdef STDINC_MA
1839 strlist_append(&sysincdirs, "=" STDINC_MA);
1840 #endif
1841 strlist_append(&sysincdirs, "=" STDINC);
1842 #ifdef PCCINCDIR
1843 if (cxxflag)
1844 strlist_append(&sysincdirs, "=" PCCINCDIR "/c++");
1845 strlist_append(&sysincdirs, "=" PCCINCDIR);
1846 #endif
1847 }
1848
1849 struct flgcheck ccomflgcheck[] = {
1850 { &Oflag, 1, "-xtemps" },
1851 { &Oflag, 1, "-xdeljumps" },
1852 { &Oflag, 1, "-xinline" },
1853 { &Oflag, 1, "-xdce" },
1854 #ifdef notyet
1855 { &Oflag, 1, "-xssa" },
1856 #endif
1857 { &freestanding, 1, "-ffreestanding" },
1858 { &pgflag, 1, "-p" },
1859 { &gflag, 1, "-g" },
1860 { &xgnu89, 1, "-xgnu89" },
1861 { &xgnu99, 1, "-xgnu99" },
1862 { &xuchar, 1, "-xuchar" },
1863 #if !defined(os_sunos) && !defined(mach_i386)
1864 { &vflag, 1, "-v" },
1865 #endif
1866 #ifdef os_darwin
1867 { &Bstatic, 0, "-k" },
1868 #elif defined(os_sunos) && defined(mach_i386)
1869 { &kflag, 1, "-K" },
1870 { &kflag, 1, "pic" },
1871 #else
1872 { &kflag, 1, "-k" },
1873 #endif
1874 { &sspflag, 1, "-fstack-protector" },
1875 { 0 }
1876 };
1877
1878 void
setup_ccom_flags(void)1879 setup_ccom_flags(void)
1880 {
1881
1882 cksetflags(ccomflgcheck, &compiler_flags, 'a');
1883 }
1884
1885 static int one = 1;
1886
1887 struct flgcheck asflgcheck[] = {
1888 #if defined(USE_YASM)
1889 { &one, 1, "-p" },
1890 { &one, 1, "gnu" },
1891 { &one, 1, "-f" },
1892 #if defined(os_win32)
1893 { &one, 1, "win32" },
1894 #elif defined(os_darwin)
1895 { &one, 1, "macho" },
1896 #else
1897 { &one, 1, "elf" },
1898 #endif
1899 #endif
1900 #if defined(os_sunos) && defined(mach_sparc64)
1901 { &one, 1, "-m64" },
1902 #endif
1903 #if defined(os_darwin)
1904 { &Bstatic, 1, "-static" },
1905 #endif
1906 #if !defined(USE_YASM)
1907 { &vflag, 1, "-v" },
1908 #endif
1909 { &kflag, 1, "-k" },
1910 #ifdef os_darwin
1911 { &one, 1, "-arch" },
1912 #if mach_amd64
1913 { &amd64_i386, 1, "i386" },
1914 { &amd64_i386, 0, "x86_64" },
1915 #else
1916 { &one, 1, "i386" },
1917 #endif
1918 #else
1919 #ifdef mach_amd64
1920 { &amd64_i386, 1, "--32" },
1921 #endif
1922 #endif
1923 { 0 }
1924 };
1925 void
setup_as_flags(void)1926 setup_as_flags(void)
1927 {
1928 one = one;
1929 #ifdef PCC_SETUP_AS_ARGS
1930 PCC_SETUP_AS_ARGS
1931 #endif
1932 cksetflags(asflgcheck, &assembler_flags, 'a');
1933 }
1934
1935 struct flgcheck ldflgcheck[] = {
1936 #ifndef MSLINKER
1937 { &vflag, 1, "-v" },
1938 #endif
1939 #ifdef os_darwin
1940 { &shared, 1, "-dylib" },
1941 #elif defined(os_win32)
1942 { &shared, 1, "-Bdynamic" },
1943 #else
1944 { &shared, 1, "-shared" },
1945 #endif
1946 #if !defined(os_sunos) && !defined(os_win32)
1947 #ifndef os_darwin
1948 { &shared, 0, "-d" },
1949 #endif
1950 #endif
1951 #ifdef os_darwin
1952 { &Bstatic, 1, "-static" },
1953 #else
1954 { &Bstatic, 1, "-Bstatic" },
1955 #endif
1956 #if !defined(os_darwin) && !defined(os_sunos)
1957 { &gflag, 1, "-g" },
1958 #endif
1959 { &pthreads, 1, "-lpthread" },
1960 { 0 },
1961 };
1962
1963 static void
strap(struct strlist * sh,struct strlist * cd,char * n,int where)1964 strap(struct strlist *sh, struct strlist *cd, char *n, int where)
1965 {
1966 void (*fn)(struct strlist *, const char *);
1967 char *fil;
1968
1969 if (n == 0)
1970 return; /* no crtfile */
1971
1972 fn = where == 'p' ? strlist_prepend : strlist_append;
1973 fil = find_file(n, cd, R_OK);
1974 (*fn)(sh, fil);
1975 }
1976
1977 void
setup_ld_flags(void)1978 setup_ld_flags(void)
1979 {
1980 char *b, *e;
1981 int i;
1982
1983 #ifdef PCC_SETUP_LD_ARGS
1984 PCC_SETUP_LD_ARGS
1985 #endif
1986
1987 cksetflags(ldflgcheck, &early_linker_flags, 'a');
1988 if (Bstatic == 0 && shared == 0 && rflag == 0) {
1989 if (dynlinklib) {
1990 strlist_append(&early_linker_flags, dynlinkarg);
1991 strlist_append(&early_linker_flags, dynlinklib);
1992 }
1993 strlist_append(&early_linker_flags, "-e");
1994 strlist_append(&early_linker_flags, STARTLABEL);
1995 }
1996 if (shared == 0 && rflag)
1997 strlist_append(&early_linker_flags, "-r");
1998 #ifdef STARTLABEL_S
1999 if (shared == 1) {
2000 strlist_append(&early_linker_flags, "-e");
2001 strlist_append(&early_linker_flags, STARTLABEL_S);
2002 }
2003 #endif
2004 if (sysroot && *sysroot)
2005 strlist_append(&early_linker_flags, cat("--sysroot=", sysroot));
2006 if (!nostdlib) {
2007 /* library search paths */
2008 if (pcclibdir)
2009 strlist_append(&late_linker_flags,
2010 cat("-L", pcclibdir));
2011 for (i = 0; deflibdirs[i]; i++)
2012 strlist_append(&late_linker_flags,
2013 cat("-L", deflibdirs[i]));
2014 /* standard libraries */
2015 if (pgflag) {
2016 for (i = 0; defproflibs[i]; i++)
2017 strlist_append(&late_linker_flags,
2018 defproflibs[i]);
2019 } else if (cxxflag) {
2020 for (i = 0; defcxxlibs[i]; i++)
2021 strlist_append(&late_linker_flags,
2022 defcxxlibs[i]);
2023 } else {
2024 for (i = 0; deflibs[i]; i++)
2025 strlist_append(&late_linker_flags, deflibs[i]);
2026 }
2027 }
2028 if (!nostartfiles) {
2029 if (Bstatic) {
2030 b = CRTBEGIN_T;
2031 e = CRTEND_T;
2032 } else if (shared /* || pieflag */) {
2033 b = CRTBEGIN_S;
2034 e = CRTEND_S;
2035 } else {
2036 b = CRTBEGIN;
2037 e = CRTEND;
2038 }
2039 strap(&middle_linker_flags, &crtdirs, b, 'p');
2040 strap(&late_linker_flags, &crtdirs, e, 'a');
2041 strap(&middle_linker_flags, &crtdirs, CRTI, 'p');
2042 strap(&late_linker_flags, &crtdirs, CRTN, 'a');
2043 #ifdef os_win32
2044 /*
2045 * On Win32 Cygwin/MinGW runtimes, the profiling code gcrtN.o
2046 * comes in addition to crtN.o or dllcrtN.o
2047 */
2048 if (pgflag)
2049 strap(&middle_linker_flags, &crtdirs, GCRT0, 'p');
2050 if (shared == 0)
2051 b = CRT0;
2052 else
2053 b = CRT0_S; /* dllcrtN.o */
2054 strap(&middle_linker_flags, &crtdirs, b, 'p');
2055 #else
2056 if (shared == 0) {
2057 if (pgflag)
2058 b = GCRT0;
2059 #ifdef notyet
2060 else if (pieflag)
2061 b = SCRT0;
2062 #endif
2063 else
2064 b = CRT0;
2065 strap(&middle_linker_flags, &crtdirs, b, 'p');
2066 }
2067 #endif
2068 }
2069 }
2070
2071 #ifdef _WIN32
2072 char *
win32pathsubst(char * s)2073 win32pathsubst(char *s)
2074 {
2075 char env[1024];
2076 DWORD len;
2077
2078 len = ExpandEnvironmentStrings(s, env, sizeof(env));
2079 if (len == 0 || len > sizeof(env))
2080 errorx(8, "ExpandEnvironmentStrings failed, len %lu", len);
2081
2082 len--; /* skip nil */
2083 while (len-- > 0 && (env[len] == '/' || env[len] == '\\'))
2084 env[len] = '\0';
2085
2086 return xstrdup(env);
2087 }
2088
2089 char *
win32commandline(struct strlist * l)2090 win32commandline(struct strlist *l)
2091 {
2092 const struct string *s;
2093 char *cmd;
2094 char *p;
2095 int len;
2096 int j, k;
2097
2098 len = 0;
2099 STRLIST_FOREACH(s, l) {
2100 len++;
2101 for (j = 0; s->value[j] != '\0'; j++) {
2102 if (s->value[j] == '\"') {
2103 for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
2104 len++;
2105 len++;
2106 }
2107 len++;
2108 }
2109 for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
2110 len++;
2111 len++;
2112 len++;
2113 }
2114
2115 p = cmd = xmalloc(len);
2116
2117 STRLIST_FOREACH(s, l) {
2118 *p++ = '\"';
2119 for (j = 0; s->value[j] != '\0'; j++) {
2120 if (s->value[j] == '\"') {
2121 for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
2122 *p++ = '\\';
2123 *p++ = '\\';
2124 }
2125 *p++ = s->value[j];
2126 }
2127 for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
2128 *p++ = '\\';
2129 *p++ = '\"';
2130 *p++ = ' ';
2131 }
2132 p[-1] = '\0';
2133
2134 return cmd;
2135 }
2136 #endif
2137