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