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 152char *passp = PREPROCESSOR; 153char *pass0 = COMPILER; 154char *passxx0 = CXXCOMPILER; 155char *as = ASSEMBLER; 156char *ld = LINKER; 157char *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 201char *cppadd[] = CPPADD; 202char *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 237char *dynlinkarg = DYNLINKARG; 238char *dynlinklib = DYNLINKLIB; 239char *pcclibdir = PCCLIBDIR; 240char *deflibdirs[] = DEFLIBDIRS; 241char *deflibs[] = DEFLIBS; 242char *defproflibs[] = DEFPROFLIBS; 243char *defcxxlibs[] = DEFCXXLIBS; 244 245char *outfile, *MFfile, *fname; 246static char **lav; 247static int lac; 248static char *find_file(const char *file, struct strlist *path, int mode); 249static int preprocess_input(char *input, char *output, int dodep); 250static int compile_input(char *input, char *output); 251static int assemble_input(char *input, char *output); 252static int run_linker(void); 253static int strlist_exec(struct strlist *l); 254 255char *cat(const char *, const char *); 256char *setsuf(char *, char); 257int cxxsuf(char *); 258int getsuf(char *); 259char *getsufp(char *s); 260int main(int, char *[]); 261void errorx(int, char *, ...); 262int cunlink(char *); 263void exandrm(char *); 264void dexit(int); 265void idexit(int); 266char *gettmp(void); 267void oerror(char *); 268char *argnxt(char *, char *); 269char *nxtopt(char *o); 270void setup_cpp_flags(void); 271void setup_ccom_flags(void); 272void setup_as_flags(void); 273void setup_ld_flags(void); 274static void expand_sysroot(void); 275#ifdef _WIN32 276char *win32pathsubst(char *); 277char *win32commandline(struct strlist *l); 278#endif 279int sspflag; 280int freestanding; 281int Sflag; 282int cflag; 283int gflag; 284int rflag; 285int vflag; 286int noexec; /* -### */ 287int tflag; 288int Eflag; 289int Oflag; 290int kflag; /* generate PIC/pic code */ 291#define F_PIC 1 292#define F_pic 2 293int Mflag, needM, MDflag, MMDflag; /* dependencies only */ 294int pgflag; 295int Xflag; 296int nostartfiles, Bstatic, shared; 297int nostdinc, nostdlib; 298int pthreads; 299int xgnu89, xgnu99, c89defs, c99defs, c11defs; 300int ascpp; 301#ifdef CHAR_UNSIGNED 302int xuchar = 1; 303#else 304int xuchar = 0; 305#endif 306int cxxflag; 307int cppflag; 308int printprogname, printfilename; 309enum { SC11, STRAD, SC89, SGNU89, SC99, SGNU99 } cstd; 310 311#ifdef SOFTFLOAT 312int softfloat = 1; 313#else 314int softfloat = 0; 315#endif 316 317#ifdef TARGET_BIG_ENDIAN 318int bigendian = 1; 319#else 320int bigendian = 0; 321#endif 322 323#ifdef mach_amd64 324int amd64_i386; 325#endif 326 327#define match(a,b) (strcmp(a,b) == 0) 328 329/* handle gcc warning emulations */ 330struct 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 404struct strlist preprocessor_flags; 405struct strlist depflags; 406struct strlist incdirs; 407struct strlist user_sysincdirs; 408struct strlist includes; 409struct strlist sysincdirs; 410struct strlist dirafterdirs; 411struct strlist crtdirs; 412struct strlist libdirs; 413struct strlist progdirs; 414struct strlist early_linker_flags; 415struct strlist middle_linker_flags; 416struct strlist late_linker_flags; 417struct strlist inputs; 418struct strlist assembler_flags; 419struct strlist temp_outputs; 420struct strlist compiler_flags; 421 422int 423main(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 */ 1114void 1115idexit(int arg) 1116{ 1117 dexit(100); 1118} 1119 1120/* 1121 * exit and cleanup. 1122 */ 1123void 1124dexit(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 */ 1138void 1139exandrm(char *s) 1140{ 1141 if (s && *s) 1142 strlist_append(&temp_outputs, s); 1143 dexit(1); 1144} 1145 1146/* 1147 * complain and exit. 1148 */ 1149void 1150errorx(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 1162static char * 1163find_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 1187static int 1188compile_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 1218static int 1219compile_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 1236static int 1237assemble_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 1260static int 1261preprocess_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 1307static int 1308run_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 1329static char *cxxt[] = { "cc", "cp", "cxx", "cpp", "CPP", "c++", "C" }; 1330int 1331cxxsuf(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 1340char * 1341getsufp(char *s) 1342{ 1343 register char *p; 1344 1345 if ((p = strrchr(s, '.')) && p[1] != '\0') 1346 return &p[1]; 1347 return ""; 1348} 1349 1350int 1351getsuf(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 */ 1363char * 1364setsuf(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 1390static int 1391strlist_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 1433static int 1434strlist_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 */ 1480char * 1481cat(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 1492int 1493cunlink(char *f) 1494{ 1495 if (f==0 || Xflag) 1496 return(0); 1497 return (unlink(f)); 1498} 1499 1500#ifdef _WIN32 1501char * 1502gettmp(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 1521char * 1522gettmp(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 1534static void 1535expand_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 1564void 1565oerror(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 */ 1574char * 1575argnxt(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 */ 1585char * 1586nxtopt(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 1602struct 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 1623static void 1624cksetflags(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 1644static 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 1690static 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 */ 1714static 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 */ 1797void 1798setup_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 1849struct 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 1878void 1879setup_ccom_flags(void) 1880{ 1881 1882 cksetflags(ccomflgcheck, &compiler_flags, 'a'); 1883} 1884 1885static int one = 1; 1886 1887struct 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}; 1925void 1926setup_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 1935struct 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 1963static void 1964strap(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 1977void 1978setup_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 2072char * 2073win32pathsubst(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 2089char * 2090win32commandline(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