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 (at) 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 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 1115 idexit(int arg) 1116 { 1117 dexit(100); 1118 } 1119 1120 /* 1121 * exit and cleanup. 1122 */ 1123 void 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 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 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 * 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 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 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 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 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 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 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 * 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 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 * 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 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 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 * 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 1493 cunlink(char *f) 1494 { 1495 if (f==0 || Xflag) 1496 return(0); 1497 return (unlink(f)); 1498 } 1499 1500 #ifdef _WIN32 1501 char * 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 * 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 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 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 * 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 * 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 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 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 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 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 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 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 * 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 * 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