Quick Search:

Mode

Context

Displaying the whole file. None | Less | More | Full

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.260
 
1.261
 
MAIN:plunky:20121108112104
 
cc.c
_>11 /*      $Id$    */
 22 
 33 /*-
 44  * Copyright (c) 2011 Joerg Sonnenberger <joerg@NetBSD.org>.
 55  * All rights reserved.
 66  *
 77  * Redistribution and use in source and binary forms, with or without
 88  * modification, are permitted provided that the following conditions
 99  * are met:
 1010  *
 1111  * 1. Redistributions of source code must retain the above copyright
 1212  *    notice, this list of conditions and the following disclaimer.
 1313  * 2. Redistributions in binary form must reproduce the above copyright
 1414  *    notice, this list of conditions and the following disclaimer in
 1515  *    the documentation and/or other materials provided with the
 1616  *    distribution.
 1717  *
 1818  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 1919  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 2020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 2121  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 2222  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 2323  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
 2424  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 2525  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 2626  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 2727  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 2828  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 2929  * SUCH DAMAGE.
 3030  */
 3131 
 3232 /*
 3333  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
 3434  *
 3535  * Redistribution and use in source and binary forms, with or without
 3636  * modification, are permitted provided that the following conditions
 3737  * are met:
 3838  *
 3939  * Redistributions of source code and documentation must retain the above
 4040  * copyright notice, this list of conditions and the following disclaimer.
 4141  * Redistributions in binary form must reproduce the above copyright
 4242  * notice, this list of conditionsand the following disclaimer in the
 4343  * documentation and/or other materials provided with the distribution.
 4444  * All advertising materials mentioning features or use of this software
 4545  * must display the following acknowledgement:
 4646  *      This product includes software developed or owned by Caldera
 4747  *      International, Inc.
 4848  * Neither the name of Caldera International, Inc. nor the names of other
 4949  * contributors may be used to endorse or promote products derived from
 5050  * this software without specific prior written permission.
 5151  *
 5252  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
 5353  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
 5454  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 5555  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 5656  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
 5757  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 5858  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 5959  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 6060  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
 6161  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 6262  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 6363  * POSSIBILITY OF SUCH DAMAGE.
 6464  */
 6565 
 6666 /*
 6767  * Front-end to the C compiler.
 6868  *
 6969  * Brief description of its syntax:
 7070  * - Files that end with .c are passed via cpp->ccom->as->ld
 7171  * - Files that end with .i are passed via ccom->as->ld
 7272  * - Files that end with .S are passed via cpp->as->ld
 7373  * - Files that end with .s are passed via as->ld
 7474  * - Files that end with .o are passed directly to ld
 7575  * - Multiple files may be given on the command line.
 7676  * - Unrecognized options are all sent directly to ld.
 7777  * -c or -S cannot be combined with -o if multiple files are given.
 7878  *
 7979  * This file should be rewritten readable.
 8080  */
 8181 #include "config.h"
 8282 
 8383 #include <sys/types.h>
 8484 #ifdef HAVE_SYS_WAIT_H
 8585 #include <sys/wait.h>
 8686 #endif
 8787 
 8888 #include <ctype.h>
 8989 #include <errno.h>
 9090 #include <fcntl.h>
 9191 #ifdef HAVE_LIBGEN_H
 9292 #include <libgen.h>
 9393 #endif
 9494 #include <signal.h>
 9595 #include <stdarg.h>
 9696 #include <stdio.h>
 9797 #include <stdlib.h>
 9898 #include <string.h>
 9999 #ifdef HAVE_UNISTD_H
 100100 #include <unistd.h>
 101101 #endif
 102102 #include <assert.h>
 103103 
 104104 #ifdef os_win32
 105105 #include <windows.h>
 106106 #include <process.h>
 107107 #include <io.h>
 108108 #define F_OK    0x00
 109109 #define R_OK    0x04
 110110 #define W_OK    0x02
 111111 #define X_OK    R_OK
 112112 #endif
 113113 
 114114 #include "compat.h"
 115115 
 116116 #include "macdefs.h"
 117117 
 118118 #include "xalloc.h"
 119119 #include "strlist.h"
 120120 
 121121 #include "ccconfig.h"
 122122 /* C command */
 123123 
 124124 #define MKS(x) _MKS(x)
 125125 #define _MKS(x) #x
 126126 
 127127 /* default program names in pcc */
 128128 /* May be overridden if cross-compiler is generated */
 129129 #ifndef CPPROGNAME
 130130 #define CPPROGNAME      "cpp"   /* cc used as cpp */
 131131 #endif
 132132 #ifndef PREPROCESSOR
 133133 #define PREPROCESSOR    "cpp"   /* "real" preprocessor name */
 134134 #endif
 135135 #ifndef COMPILER
 136136 #define COMPILER        "ccom"
 137137 #endif
 138138 #ifndef CXXCOMPILER
 139139 #define CXXCOMPILER     "cxxcom"
 140140 #endif
 141141 #ifndef ASSEMBLER
 142142 #define ASSEMBLER       "as"
 143143 #endif
 144144 #ifndef LINKER
 145145 #define LINKER          "ld"
 146146 #endif
 147147 char    *passp = PREPROCESSOR;
 148148 char    *pass0 = COMPILER;
 149149 char    *passxx0 = CXXCOMPILER;
 150150 char    *as = ASSEMBLER;
 151151 char    *ld = LINKER;
 152152 char    *sysroot = "", *isysroot;
 153153 
 154154 
 155155 /* crt files using pcc default names */
 156156 #ifndef CRTBEGIN_S
 157157 #define CRTBEGIN_S      "crtbeginS.o"
 158158 #endif
 159159 #ifndef CRTEND_S
 160160 #define CRTEND_S        "crtendS.o"
 161161 #endif
 162162 #ifndef CRTBEGIN_T
 163163 #define CRTBEGIN_T      "crtbeginT.o"
 164164 #endif
 165165 #ifndef CRTEND_T
 166166 #define CRTEND_T        "crtendT.o"
 167167 #endif
 168168 #ifndef CRTBEGIN
 169169 #define CRTBEGIN        "crtbegin.o"
 170170 #endif
 171171 #ifndef CRTEND
 172172 #define CRTEND          "crtend.o"
 173173 #endif
 174174 #ifndef CRTI
 175175 #define CRTI            "crti.o"
 176176 #endif
 177177 #ifndef CRTN
 178178 #define CRTN            "crtn.o"
 179179 #endif
 180180 #ifndef CRT0
 181181 #define CRT0            "crt0.o"
 182182 #endif
 183183 #ifndef GCRT0
 184184 #define GCRT0           "gcrt0.o"
 185185 #endif
 186186 
 187187 /* preprocessor stuff */
 188188 #ifndef STDINC
 189189 #define STDINC          "/usr/include/"
 190190 #endif
 191191 
 192192 char *cppadd[] = CPPADD;
 193193 char *cppmdadd[] = CPPMDADD;
 194194 
 195195 /* Dynamic linker definitions, per-target */
 196196 #ifndef DYNLINKER
 197197 #define DYNLINKER { 0 }
 198198 #endif
 199199 
 200200 /* Default libraries and search paths */
 201201 #ifndef PCCLIBDIR       /* set by autoconf */
 202202 #define PCCLIBDIR       NULL
 203203 #endif
 204204 #ifndef DEFLIBDIRS      /* default library search paths */
 205205 #define DEFLIBDIRS      { "/usr/lib/", 0 }
 206206 #endif
 207207 #ifndef DEFLIBS         /* default libraries included */
 208208 #define DEFLIBS         { "-lpcc", "-lc", "-lpcc", 0 }
 209209 #endif
 210210 #ifndef DEFPROFLIBS     /* default profiling libraries */
 211211 #define DEFPROFLIBS     { "-lpcc", "-lc_p", "-lpcc", 0 }
 212212 #endif
 213213 #ifndef DEFCXXLIBS      /* default c++ libraries */
 214214 #define DEFCXXLIBS      { "-lp++", "-lpcc", "-lc", "-lpcc", 0 }
 215215 #endif
 216216 #ifndef STARTLABEL
 217217 #define STARTLABEL "__start"
 218218 #endif
 219219 
 220220 char *dynlinker[] = DYNLINKER;
 221221 char *pcclibdir = PCCLIBDIR;
 222222 char *deflibdirs[] = DEFLIBDIRS;
 223223 char *deflibs[] = DEFLIBS;
 224224 char *defproflibs[] = DEFPROFLIBS;
 225225 char *defcxxlibs[] = DEFCXXLIBS;
 226226 
 227227 char    *outfile, *MFfile, *fname;
 228228 static char **lav;
 229229 static int lac;
 230230 static char *find_file(const char *file, struct strlist *path, int mode);
 231231 static int preprocess_input(char *input, char *output, int dodep);
 232232 static int compile_input(char *input, char *output);
 233233 static int assemble_input(char *input, char *output);
 234234 static int run_linker(void);
 235235 static int strlist_exec(struct strlist *l);
 236236 
 237237 char *cat(const char *, const char *);
 238238 char *setsuf(char *, char);
 239239 int cxxsuf(char *);
 240240 int getsuf(char *);
 241241 char *getsufp(char *s);
 242242 int main(int, char *[]);
 243243 void error(char *, ...);
 244244 void errorx(int, char *, ...);
 245245 int cunlink(char *);
 246246 void exandrm(char *);
 247247 void dexit(int);
 248248 void idexit(int);
 249249 char *gettmp(void);
 250250 void aerror(char *);
 251251 void oerror(char *);
 252252 char *argnxt(char *, char *);
 253253 char *nxtopt(char *o);
 254254 void setup_cpp_flags(void);
 255255 void setup_ccom_flags(void);
 256256 void setup_as_flags(void);
 257257 void setup_ld_flags(void);
 258258 static void expand_sysroot(void);
 259259 #ifdef os_win32
 260260 char *win32pathsubst(char *);
 261261 char *win32commandline(struct strlist *l);
 262262 #endif
 263263 int     sspflag;
 264264 int     freestanding;
 265265 int     Sflag;
 266266 int     cflag;
 267267 int     gflag;
 268268 int     rflag;
 269269 int     vflag;
 270270 int     tflag;
 271271 int     Eflag;
 272272 int     Oflag;
 273273 int     kflag;  /* generate PIC/pic code */
 274274 #define F_PIC   1
 275275 #define F_pic   2
 276276 int     Mflag, needM, MDflag;   /* dependencies only */
 277277 int     pgflag;
 278278 int     Xflag;
 279279 int     nostartfiles, Bstatic, shared;
 280280 int     nostdinc, nostdlib;
 281281 int     pthreads;
 282282 int     xgnu89, xgnu99;
 283283 int     ascpp;
 284284 #ifdef CHAR_UNSIGNED
 285285 int     xuchar = 1;
 286286 #else
 287287 int     xuchar = 0;
 288288 #endif
 289289 int     cxxflag;
 290290 int     cppflag;
 291291 int     printprogname, printfilename;
 292292 
 293293 #ifdef mach_amd64
 294294 int amd64_i386;
 295295 #endif
 296296 
 297297 #define match(a,b)      (strcmp(a,b) == 0)
 298298 
 299299 /* handle gcc warning emulations */
 300300 struct Wflags {
 301301         char *name;
 302302         int flags;
 303303 #define INWALL          1
 304304 } Wflags[] = {
 305305         { "truncate", 0 },
 306306         { "strict-prototypes", 0 },
 307307         { "missing-prototypes", 0 },
 308308         { "implicit-int", INWALL },
 309309         { "implicit-function-declaration", INWALL },
 310310         { "shadow", 0 },
 311311         { "pointer-sign", INWALL },
 312312         { "sign-compare", 0 },
 313313         { "unknown-pragmas", INWALL },
 314314         { "unreachable-code", 0 },
 315315         { NULL, 0 },
 316316 };
 317317 
 318318 #ifndef USHORT
 319319 /* copied from mip/manifest.h */
 320320 #define USHORT          5
 321321 #define INT             6
 322322 #define UNSIGNED        7
 323323 #endif
 324324 
 325325 /*
 326326  * Wide char defines.
 327327  */
 328328 #if WCHAR_TYPE == USHORT
 329329 #define WCT "short unsigned int"
 330330 #define WCM "65535U"
 331331 #if WCHAR_SIZE != 2
 332332 #error WCHAR_TYPE vs. WCHAR_SIZE mismatch
 333333 #endif
 334334 #elif WCHAR_TYPE == INT
 335335 #define WCT "int"
 336336 #define WCM "2147483647"
 337337 #if WCHAR_SIZE != 4
 338338 #error WCHAR_TYPE vs. WCHAR_SIZE mismatch
 339339 #endif
 340340 #elif WCHAR_TYPE == UNSIGNED
 341341 #define WCT "unsigned int"
 342342 #define WCM "4294967295U"
 343343 #if WCHAR_SIZE != 4
 344344 #error WCHAR_TYPE vs. WCHAR_SIZE mismatch
 345345 #endif
 346346 #else
 347347 #error WCHAR_TYPE not defined or invalid
 348348 #endif
 349349 
 350350 #ifdef GCC_COMPAT
 351351 #ifndef REGISTER_PREFIX
 352352 #define REGISTER_PREFIX ""
 353353 #endif
 354354 #ifndef USER_LABEL_PREFIX
 355355 #define USER_LABEL_PREFIX ""
 356356 #endif
 357357 #endif
 358358 
 359359 #ifndef PCC_WINT_TYPE
 360360 #define PCC_WINT_TYPE "unsigned int"
 361361 #endif
 362362 
 363363 #ifndef PCC_SIZE_TYPE
 364364 #define PCC_SIZE_TYPE "unsigned long"
 365365 #endif
 366366 
 367367 #ifndef PCC_PTRDIFF_TYPE
 368368 #define PCC_PTRDIFF_TYPE "long int"
 369369 #endif
 370370 
 371371 
 372372 struct strlist preprocessor_flags;
 373373 struct strlist depflags;
 374374 struct strlist incdirs;
 375375 struct strlist user_sysincdirs;
 376376 struct strlist includes;
 377377 struct strlist sysincdirs;
 378378 struct strlist dirafterdirs;
 379379 struct strlist crtdirs;
 380380 struct strlist libdirs;
 381381 struct strlist progdirs;
 382382 struct strlist early_linker_flags;
 383383 struct strlist middle_linker_flags;
 384384 struct strlist late_linker_flags;
 385385 struct strlist inputs;
 386386 struct strlist assembler_flags;
 387387 struct strlist temp_outputs;
 388388 struct strlist compiler_flags;
 389389 
 390390 int
 391391 main(int argc, char *argv[])
 392392 {
 393393         struct Wflags *Wf;
 394394         struct string *s;
 395395         char *t, *u, *argp;
 396396         char *msuffix;
 397397         int ninput, j;
 398398 
 399399         lav = argv;
 400400         lac = argc;
 401401         ninput = 0;
 402402 
 403403         strlist_init(&crtdirs);
 404404         strlist_init(&libdirs);
 405405         strlist_init(&progdirs);
 406406         strlist_init(&preprocessor_flags);
 407407         strlist_init(&incdirs);
 408408         strlist_init(&user_sysincdirs);
 409409         strlist_init(&includes);
 410410         strlist_init(&sysincdirs);
 411411         strlist_init(&dirafterdirs);
 412412         strlist_init(&depflags);
 413413         strlist_init(&early_linker_flags);
 414414         strlist_init(&middle_linker_flags);
 415415         strlist_init(&late_linker_flags);
 416416         strlist_init(&inputs);
 417417         strlist_init(&assembler_flags);
 418418         strlist_init(&temp_outputs);
 419419         strlist_init(&compiler_flags);
 420420 
 421421         if ((t = strrchr(argv[0], '/')))
 422422                 t++;
 423423         else
 424424                 t = argv[0];
 425425 
 426426         if (match(t, "p++")) {
 427427                 cxxflag = 1;
 428428         } else if (match(t, "cpp") || match(t, CPPROGNAME)) {
 429429                 Eflag = cppflag = 1;
 430430         }
 431431 
 432432 #ifdef PCC_EARLY_SETUP
 433433         PCC_EARLY_SETUP
 434434 #endif
 435435 
 436436 #ifdef os_win32
 437437         /* have to prefix path early.  -B may override */
 438438         incdir = win32pathsubst(incdir);
 439439         altincdir = win32pathsubst(altincdir);
 440440         libdir = win32pathsubst(libdir);
 441441 #ifdef PCCINCDIR
 442442         pccincdir = win32pathsubst(pccincdir);
 443443         pxxincdir = win32pathsubst(pxxincdir);
 444444 #endif
 445445 #ifdef PCCLIBDIR
 446446         pcclibdir = win32pathsubst(pcclibdir);
 447447 #endif
 448448         passp = win32pathsubst(passp);
 449449         pass0 = win32pathsubst(pass0);
 450450 #ifdef STARTFILES
 451451         for (i = 0; startfiles[i] != NULL; i++)
 452452                 startfiles[i] = win32pathsubst(startfiles[i]);
 453453         for (i = 0; endfiles[i] != NULL; i++)
 454454                 endfiles[i] = win32pathsubst(endfiles[i]);
 455455 #endif
 456456 #ifdef STARTFILES_T
 457457         for (i = 0; startfiles_T[i] != NULL; i++)
 458458                 startfiles_T[i] = win32pathsubst(startfiles_T[i]);
 459459         for (i = 0; endfiles_T[i] != NULL; i++)
 460460                 endfiles_T[i] = win32pathsubst(endfiles_T[i]);
 461461 #endif
 462462 #ifdef STARTFILES_S
 463463         for (i = 0; startfiles_S[i] != NULL; i++)
 464464                 startfiles_S[i] = win32pathsubst(startfiles_S[i]);
 465465         for (i = 0; endfiles_S[i] != NULL; i++)
 466466                 endfiles_S[i] = win32pathsubst(endfiles_S[i]);
 467467 #endif
 468468 #endif
 469469 
 470470         while (--lac) {
 471471                 ++lav;
 472472                 argp = *lav;
 473473 
 474474 #ifdef PCC_EARLY_ARG_CHECK
 475475                 PCC_EARLY_ARG_CHECK
 476476 #endif
 477477 
 478478                 if (*argp != '-' || match(argp, "-")) {
 479479                         /* Check for duplicate .o files. */
 480480                         if (getsuf(argp) == 'o') {
 481481                                 j = 0;
 482482                                 STRLIST_FOREACH(s, &inputs)
 483483                                         if (match(argp, s->value))
 484484                                                 j++;
 485485                                 if (j)
 486486                                         continue; /* skip it */
 487487                         }
 488488                         strlist_append(&inputs, argp);
 489489                         ninput++;
 490490                         continue;
 491491                 }
 492492 
 493493                 switch (argp[1]) {
 494494                 default:
 495495                         oerror(argp);
 496496                         break;
 497497 
 498498                 case '-': /* double -'s */
 499499                         if (match(argp, "--version")) {
 500500                                 printf("%s\n", VERSSTR);
 501501                                 return 0;
 502502                         } else if (strncmp(argp, "--sysroot=", 10) == 0) {
 503503                                 sysroot = argp + 10;
 504504                         } else if (strcmp(argp, "--param") == 0) {
 505505                                 /* NOTHING YET */;
 506506                                 (void)nxtopt(0); /* ignore arg */
 507507                         } else
 508508                                 oerror(argp);
 509509                         break;
 510510 
 511511                 case 'B': /* other search paths for binaries */
 512512                         t = nxtopt("-B");
 513513                         strlist_append(&crtdirs, t);
 514514                         strlist_append(&libdirs, t);
 515515                         strlist_append(&progdirs, t);
 516516                         break;
 517517 
 518518                 case 'C':
 519519                         if (match(argp, "-C") || match(argp, "-CC"))
 520520                                 strlist_append(&preprocessor_flags, argp);
 521521                         else
 522522                                 oerror(argp);
 523523                         break;
 524524 
 525525                 case 'c':
 526526                         cflag++;
 527527                         break;
 528528 
 529529                 case 'd':
 530530                         oerror(argp);
 531531                         break;
 532532 
 533533                 case 'E':
 534534                         Eflag++;
 535535                         break;
 536536 
 537537                 case 'f': /* GCC compatibility flags */
 538538                         u = &argp[2];
 539539                         j = 0;
 540540                         if (strncmp(u, "no-", 3) == 0)
 541541                                 j = 1, u += 3;
 542542                         if (match(u, "PIC") || match(u, "pic")) {
 543543                                 kflag = j ? 0 : *u == 'P' ? F_PIC : F_pic;
 544544                         } else if (match(u, "freestanding")) {
 545545                                 freestanding = j ? 0 : 1;
 546546                         } else if (match(u, "signed-char")) {
 547547                                 xuchar = j ? 1 : 0;
 548548                         } else if (match(u, "unsigned-char")) {
 549549                                 xuchar = j ? 0 : 1;
 550550                         } else if (match(u, "stack-protector") ||
 551551                             match(u, "stack-protector-all")) {
 552552                                 sspflag = j ? 0 : 1;
 553553                         }
 554554                         /* silently ignore the rest */
 555555                         break;
 556556 
 557557                 case 'g': /* create debug output */
 558558                         if (argp[2] == '0')
 559559                                 gflag = 0;
 560560                         else
 561561                                 gflag++;
 562562                         break;
 563563 
 564564 
 565565                 case 'X':
 566566                         Xflag++;
 567567                         break;
 568568 
 569569                 case 'D':
 570570                 case 'U':
 571571                         strlist_append(&preprocessor_flags, argp);
 572572                         if (argp[2] != 0)
 573573                                 break;
 574574                         strlist_append(&preprocessor_flags, nxtopt(argp));
 575575                         break;
 576576 
 577577                 case 'I': /* Add include dirs */
 578578                         strlist_append(&incdirs, nxtopt("-I"));
 579579                         break;
 580580 
 581581                 case 'i':
 582582                         if (match(argp, "-isystem")) {
 583583                                 strlist_append(&user_sysincdirs, nxtopt(0));
 584584                         } else if (match(argp, "-include")) {
 585585                                 strlist_append(&includes, nxtopt(0));
 586586                         } else if (match(argp, "-isysroot")) {
 587587                                 isysroot = nxtopt(0);
 588588                         } else if (strcmp(argp, "-idirafter") == 0) {
 589589                                 strlist_append(&dirafterdirs, nxtopt(0));
 590590                         } else
 591591                                 oerror(argp);
 592592                         break;
 593593 
 594594                 case 'k': /* generate PIC code */
 595595                         kflag = argp[2] ? argp[2] - '0' : F_pic;
 596596                         break;
 597597 
 598598                 case 'l':
 599599                 case 'L':
 600600                         if (argp[2] == 0)
 601601                                 argp = cat(argp, nxtopt(0));
 602602                         strlist_append(&inputs, argp);
 603603                         break;
 604604 
 605605                 case 'm': /* target-dependent options */
 606606 #ifdef mach_amd64
 607607                         /* need to call i386 ccom for this */
 608608                         if (strcmp(argp, "-m32") == 0) {
 609609                                 pass0 = LIBEXECDIR "/ccom_i386";
 610610                                 amd64_i386 = 1;
 611611                                 break;
 612612                         }
 613613 #endif
 614614                         strlist_append(&middle_linker_flags, argp);
 615615                         if (argp[2] == 0) {
 616616                                 t = nxtopt(0);
 617617                                 strlist_append(&middle_linker_flags, t);
 618618                         }
 619619                         break;
 620620 
 621621                 case 'n': /* handle -n flags */
 622622                         if (strcmp(argp, "-nostdinc") == 0)
 623623                                 nostdinc++;
 624624                         else if (strcmp(argp, "-nostdlib") == 0) {
 625625                                 nostdlib++;
 626626                                 nostartfiles++;
 627627                         } else if (strcmp(argp, "-nostartfiles") == 0)
 628628                                 nostartfiles = 1;
 629629                         else if (strcmp(argp, "-nodefaultlibs") == 0)
 630630                                 nostdlib++;
 631631                         else
 632632                                 oerror(argp);
 633633                         break;
 634634 
 635635                 case 'p':
 636636                         if (strcmp(argp, "-pg") == 0 ||
 637637                             strcmp(argp, "-p") == 0)
 638638                                 pgflag++;
 639639                         else if (strcmp(argp, "-pthread") == 0)
 640640                                 pthreads++;
 641641                         else if (strcmp(argp, "-pipe") == 0)
 642642                                 /* NOTHING YET */;
 643643                         else if (strcmp(argp, "-pedantic") == 0)
 644644                                 /* NOTHING YET */;
 645645                         else if ((t = argnxt(argp, "-print-prog-name="))) {
 646646                                 fname = t;
 647647                                 printprogname = 1;
 648648                         } else if ((t = argnxt(argp, "-print-file-name="))) {
 649649                                 fname = t;
 650650                                 printfilename = 1;
 651651                         } else if (match(argp, "-print-libgcc-file-name")) {
 652652                                 fname = "libpcc.a";
 653653                                 printfilename = 1;
 654654                         } else
 655655                                 oerror(argp);
 656656                         break;
 657657 
 658658                 case 'r':
 659659                         rflag = 1;
 660660                         break;
 661661 
 662662                 case 'T':
 663663                         strlist_append(&inputs, argp);
 664664                         if (argp[2] == 0 ||
 665665                             strcmp(argp, "-Ttext") == 0 ||
 666666                             strcmp(argp, "-Tdata") == 0 ||
 667667                             strcmp(argp, "-Tbss") == 0)
 668668                                 strlist_append(&inputs, nxtopt(0));
 669669                         break;
 670670 
 671671                 case 's':
 672672                         if (match(argp, "-shared")) {
 673673                                 shared = 1;
 674674                         } else if (match(argp, "-static")) {
 675675                                 Bstatic = 1;
 676676                         } else if (match(argp, "-symbolic")) {
 677677                                 strlist_append(&middle_linker_flags,
 678678                                     "-Bsymbolic");
 679679                         } else if (strncmp(argp, "-std", 4) == 0) {
 680680                                 if (strcmp(&argp[5], "gnu99") == 0 ||
 681681                                     strcmp(&argp[5], "gnu9x") == 0)
 682682                                         xgnu99 = 1;
 683683                                 if (strcmp(&argp[5], "gnu89") == 0)
 684684                                         xgnu89 = 1;
 685685                         } else
 686686                                 oerror(argp);
 687687                         break;
 688688 
 689689                 case 'S':
 690690                         Sflag++;
 691691                         cflag++;
 692692                         break;
 693693 
 694694                 case 't':
 695695                         tflag++;
 696696                         break;
 697697 
 698698                 case 'o':
 699699                         if (outfile)
 700700                                 errorx(8, "too many -o");
 701701                         outfile = nxtopt("-o");
 702702                         break;
 703703 
 704704                 case 'O':
 705705                         if (argp[2] == '\0')
 706706                                 Oflag++;
 707707                         else if (argp[3] == '\0' &&
 708708                             isdigit((unsigned char)argp[2]))
 709709                                 Oflag = argp[2] - '0';
 710710                         else if (argp[3] == '\0' && argp[2] == 's')
 711711                                 Oflag = 1;      /* optimize for space only */
 712712                         else
 713713                                 oerror(argp);
 714714                         break;
 715715 
 716716                 case 'P':
 717717                         strlist_append(&preprocessor_flags, argp);
 718718                         break;
 719719 
 720720                 case 'M':
 721721                         needM = 1;
 722722                         if (match(argp, "-M")) {
 723723                                 Mflag++;
 724724                                 strlist_append(&depflags, argp);
 725725                         } else if (match(argp, "-MP")) {
 726726                                 strlist_append(&depflags, "-xMP");
 727727                         } else if (match(argp, "-MF")) {
 728728                                 MFfile = nxtopt("-MF");
 729729                         } else if (match(argp, "-MT") || match(argp, "-MQ")) {
 730730                                 t = cat("-xMT,", nxtopt("-MT"));
 731731                                 t[3] = argp[2];
 732732                                 strlist_append(&depflags, t);
 733733                         } else if (match(argp, "-MD")) {
 734734                                 MDflag++;
 735735                                 needM = 0;
 736736                                 strlist_append(&depflags, "-M");
 737737                         } else
 738738                                 oerror(argp);
 739739                         break;
 740740 
 741741                 case 'v':
 742742                         printf("%s\n", VERSSTR);
 743743                         vflag++;
 744744                         break;
 745745 
 746746                 case 'W': /* Ignore (most of) W-flags */
 747747                         if ((t = argnxt(argp, "-Wl,"))) {
 748748                                 u = strtok(t, ",");
 749749                                 do {
 750750                                         strlist_append(&inputs, u);
 751751                                 } while ((u = strtok(NULL, ",")) != NULL);
 752752                         } else if ((t = argnxt(argp, "-Wa,"))) {
 753753                                 u = strtok(t, ",");
 754754                                 do {
 755755                                         strlist_append(&assembler_flags, u);
 756756                                 } while ((u = strtok(NULL, ",")) != NULL);
 757757                         } else if ((t = argnxt(argp, "-Wc,"))) {
 758758                                 u = strtok(t, ",");
 759759                                 do {
 760760                                         strlist_append(&compiler_flags, u);
 761761                                 } while ((u = strtok(NULL, ",")) != NULL);
 762762                         } else if ((t = argnxt(argp, "-Wp,"))) {
 763763                                 u = strtok(t, ",");
 764764                                 do {
 765765                                         strlist_append(&preprocessor_flags, u);
 766766                                 } while ((u = strtok(NULL, ",")) != NULL);
 767767                         } else if (strcmp(argp, "-Werror") == 0) {
 768768                                 strlist_append(&compiler_flags, "-Werror");
<> 769+                                strlist_append(&preprocessor_flags, "-E");
<_769770                         } else if (strcmp(argp, "-Wall") == 0) {
 770771                                 for (Wf = Wflags; Wf->name; Wf++)
 771772                                         if (Wf->flags & INWALL)
 772773                                                 strlist_append(&compiler_flags,
 773774                                                     cat("-W", Wf->name));
 774775                         } else if (strcmp(argp, "-WW") == 0) {
 775776                                 for (Wf = Wflags; Wf->name; Wf++)
 776777                                         strlist_append(&compiler_flags,
 777778                                             cat("-W", Wf->name));
 778779                         } else {
 779780                                 /* pass through, if supported */
 780781                                 t = &argp[2];
 781782                                 if (strncmp(t, "no-", 3) == 0)
 782783                                         t += 3;
 783784                                 if (strncmp(t, "error=", 6) == 0)
 784785                                         t += 6;
 785786                                 for (Wf = Wflags; Wf->name; Wf++) {
 786787                                         if (strcmp(t, Wf->name) == 0)
 787788                                                 strlist_append(&compiler_flags,
 788789                                                     argp);
 789790                                 }
 790791                         }
 791792                         break;
 792793 
 793794                 case 'x':
 794795                         t = nxtopt("-x");
 795796                         if (match(t, "c"))
 796797                                 strlist_append(&inputs, ")c");
 797798                         else if (match(t, "assembler"))
 798799                                 strlist_append(&inputs, ")s");
 799800                         else if (match(t, "assembler-with-cpp"))
 800801                                 strlist_append(&inputs, ")S");
 801802                         else if (match(t, "c++"))
 802803                                 strlist_append(&inputs, ")c++");
 803804                         else {
 804805                                 strlist_append(&compiler_flags, "-x");
 805806                                 strlist_append(&compiler_flags, t);
 806807                         }
 807808                         break;
 808809 
 809810                 }
 810811                 continue;
 811812 
 812813         }
 813814 
 814815         /* Sanity checking */
 815816         if (cppflag) {
 816817                 if (ninput == 0) {
 817818                         strlist_append(&inputs, "-");
 818819                         ninput++;
 819820                 } else if (ninput > 2 || (ninput == 2 && outfile)) {
 820821                         errorx(8, "too many files");
 821822                 } else if (ninput == 2) {
 822823                         outfile = STRLIST_NEXT(STRLIST_FIRST(&inputs))->value;
 823824                         STRLIST_FIRST(&inputs)->next = NULL;
 824825                         ninput--;
 825826                 }
 826827         }
 827828         if (ninput == 0 && !(printprogname || printfilename))
 828829                 errorx(8, "no input files");
 829830         if (outfile && (cflag || Sflag || Eflag) && ninput > 1)
 830831                 errorx(8, "-o given with -c || -E || -S and more than one file");
 831832 #if 0
 832833         if (outfile && clist[0] && strcmp(outfile, clist[0]) == 0)
 833834                 errorx(8, "output file will be clobbered");
 834835 #endif
 835836 
 836837         if (needM && !Mflag && !MDflag)
 837838                 errorx(8, "to make dependencies needs -M");
 838839 
 839840 
 840841         if (signal(SIGINT, SIG_IGN) != SIG_IGN/* interrupt */
 841842                 signal(SIGINT, idexit);
 842843         if (signal(SIGTERM, SIG_IGN) != SIG_IGN)        /* terminate */
 843844                 signal(SIGTERM, idexit);
 844845 
 845846         /* after arg parsing */
 846847         strlist_append(&progdirs, LIBEXECDIR);
 847848         if (pcclibdir)
 848849                 strlist_append(&crtdirs, pcclibdir);
 849850         for (j = 0; deflibdirs[j]; j++)
 850851                 strlist_append(&crtdirs, deflibdirs[j]);
 851852 
 852853         setup_cpp_flags();
 853854         setup_ccom_flags();
 854855         setup_as_flags();
 855856 
 856857         if (isysroot == NULL)
 857858                 isysroot = sysroot;
 858859         expand_sysroot();
 859860 
 860861         if (printprogname) {
 861862                 printf("%s\n", find_file(fname, &progdirs, X_OK));
 862863                 return 0;
 863864         } else if (printfilename) {
 864865                 printf("%s\n", find_file(fname, &crtdirs, R_OK));
 865866                 return 0;
 866867         }
 867868 
 868869         msuffix = NULL;
 869870         STRLIST_FOREACH(s, &inputs) {
 870871                 char *suffix;
 871872                 char *ifile, *ofile;
 872873 
 873874                 ifile = s->value;
 874875                 if (ninput > 1 && !Eflag)
 875876                         printf("%s:\n", ifile);
 876877 
 877878                 if (ifile[0] == ')') {
 878879                         msuffix = &ifile[1]; /* -x source type given */
 879880                         ascpp = match(msuffix, "S");
 880881                         continue;
 881882                 }
 882883                 if (ifile[0] == '-' && ifile[1] == 0)
 883884                         suffix = msuffix ? msuffix : "c";
 884885                 else if (ifile[0] == '-')
 885886                         suffix = "o"; /* source files cannot begin with - */
 886887                 else if (msuffix)
 887888                         suffix = msuffix;
 888889                 else
 889890                         suffix = getsufp(ifile);
 890891                 /*
 891892                  * C preprocessor
 892893                  */
 893894                 if (match(suffix, "c") || match(suffix, "S") ||
 894895                     cxxsuf(s->value)) {
 895896                         /* find out next output file */
 896897                         if (Mflag || MDflag) {
 897898                                 char *Mofile;
 898899 
 899900                                 if (MFfile)
 900901                                         Mofile = MFfile;
 901902                                 else if (outfile)
 902903                                         Mofile = setsuf(outfile, 'd');
 903904                                 else
 904905                                         Mofile = setsuf(ifile, 'd');
 905906                                 if (preprocess_input(ifile, Mofile, 1))
 906907                                         exandrm(Mofile);
 907908                         }
 908909                         if (Mflag)
 909910                                 continue;
 910911                         if (Eflag) {
 911912                                 /* last pass */
 912913                                 ofile = outfile;
 913914                         } else {
 914915                                 /* to temp file */
 915916                                 strlist_append(&temp_outputs, ofile = gettmp());
 916917                         }
 917918                         if (preprocess_input(ifile, ofile, 0))
 918919                                 exandrm(ofile);
 919920                         if (Eflag)
 920921                                 continue;
 921922                         ifile = ofile;
 922923                         suffix = match(suffix, "S") ? "s" : "i";
 923924                 }
 924925 
 925926                 /*
 926927                  * C compiler
 927928                  */
 928929                 if (match(suffix, "i")) {
 929930                         /* find out next output file */
 930931                         if (Sflag) {
 931932                                 ofile = outfile;
 932933                                 if (outfile == NULL)
 933934                                         ofile = setsuf(s->value, 's');
 934935                         } else
 935936                                 strlist_append(&temp_outputs, ofile = gettmp());
 936937                         if (compile_input(ifile, ofile))
 937938                                 exandrm(ofile);
 938939                         if (Sflag)
 939940                                 continue;
 940941                         ifile = ofile;
 941942                         suffix = "s";
 942943                 }
 943944 
 944945                 /*
 945946                  * Assembler
 946947                  */
 947948                 if (match(suffix, "s")) {
 948949                         if (cflag) {
 949950                                 ofile = outfile;
 950951                                 if (ofile == NULL)
 951952                                         ofile = setsuf(s->value, 'o');
 952953                         } else {
 953954                                 strlist_append(&temp_outputs, ofile = gettmp());
 954955                                 /* strlist_append linker */
 955956                         }
 956957                         if (assemble_input(ifile, ofile))
 957958                                 exandrm(ofile);
 958959                         ifile = ofile;
 959960                 }
 960961                 strlist_append(&middle_linker_flags, ifile);
 961962         }
 962963 
 963964         if (cflag || Eflag || Mflag)
 964965                 dexit(0);
 965966 
 966967         /*
 967968          * Linker
 968969          */
 969970         setup_ld_flags();
 970971         if (run_linker())
 971972                 exandrm(0);
 972973 
 973974 #ifdef notdef
 974975         strlist_free(&crtdirs);
 975976         strlist_free(&libdirs);
 976977         strlist_free(&progdirs);
 977978         strlist_free(&incdirs);
 978979         strlist_free(&preprocessor_flags);
 979980         strlist_free(&user_sysincdirs);
 980981         strlist_free(&includes);
 981982         strlist_free(&sysincdirs);
 982983         strlist_free(&dirafterdirs);
 983984         strlist_free(&depflags);
 984985         strlist_free(&early_linker_flags);
 985986         strlist_free(&middle_linker_flags);
 986987         strlist_free(&late_linker_flags);
 987988         strlist_free(&inputs);
 988989         strlist_free(&assembler_flags);
 989990         strlist_free(&temp_outputs);
 990991         strlist_free(&compiler_flags);
 991992 #endif
 992993         dexit(0);
 993994         return 0;
 994995 }
 995996 
 996997 /*
 997998  * exit and cleanup after interrupt.
 998999  */
 9991000 void
 10001001 idexit(int arg)
 10011002 {
 10021003         dexit(100);
 10031004 }
 10041005 
 10051006 /*
 10061007  * exit and cleanup.
 10071008  */
 10081009 void
 10091010 dexit(int eval)
 10101011 {
 10111012         struct string *s;
 10121013 
 10131014         if (!Xflag) {
 10141015                 STRLIST_FOREACH(s, &temp_outputs)
 10151016                         cunlink(s->value);
 10161017         }
 10171018         exit(eval);
 10181019 }
 10191020 
 10201021 /*
 10211022  * Called when something failed.
 10221023  */
 10231024 void
 10241025 exandrm(char *s)
 10251026 {
 10261027         if (s && *s)
 10271028                 strlist_append(&temp_outputs, s);
 10281029         dexit(1);
 10291030 }
 10301031 
 10311032 static void
 10321033 ccerror(char *s, va_list ap)
 10331034 {
 10341035         vfprintf(Eflag ? stderr : stdout, s, ap);
 10351036         putc('\n', Eflag? stderr : stdout);
 10361037 }
 10371038 
 10381039 /*
 10391040  * complain a bit.
 10401041  */
 10411042 void
 10421043 error(char *s, ...)
 10431044 {
 10441045         va_list ap;
 10451046 
 10461047         va_start(ap, s);
 10471048         ccerror(s, ap);
 10481049         va_end(ap);
 10491050         dexit(1);
 10501051 }
 10511052 
 10521053 /*
 10531054  * complain a bit and then exit.
 10541055  */
 10551056 void
 10561057 errorx(int eval, char *s, ...)
 10571058 {
 10581059         va_list ap;
 10591060 
 10601061         va_start(ap, s);
 10611062         ccerror(s, ap);
 10621063         va_end(ap);
 10631064         dexit(eval);
 10641065 }
 10651066 
 10661067 static char *
 10671068 find_file(const char *file, struct strlist *path, int mode)
 10681069 {
 10691070         struct string *s;
 10701071         char *f;
 10711072         size_t lf, lp;
 10721073         int need_sep;
 10731074 
 10741075         lf = strlen(file);
 10751076         STRLIST_FOREACH(s, path) {
 10761077                 lp = strlen(s->value);
 10771078                 need_sep = (lp && s->value[lp - 1] != '/') ? 1 : 0;
 10781079                 f = xmalloc(lp + lf + need_sep + 1);
 10791080                 memcpy(f, s->value, lp);
 10801081                 if (need_sep)
 10811082                         f[lp] = '/';
 10821083                 memcpy(f + lp + need_sep, file, lf + 1);
 10831084                 if (access(f, mode) == 0)
 10841085                         return f;
 10851086                 free(f);
 10861087         }
 10871088         return xstrdup(file);
 10881089 }
 10891090 
 10901091 static int
 10911092 compile_input(char *input, char *output)
 10921093 {
 10931094         struct strlist args;
 10941095         int retval;
 10951096 
 10961097         strlist_init(&args);
 10971098         strlist_append_list(&args, &compiler_flags);
 10981099         strlist_append(&args, input);
 10991100         strlist_append(&args, output);
 11001101         strlist_prepend(&args,
 11011102             find_file(cxxflag ? passxx0 : pass0, &progdirs, X_OK));
 11021103         retval = strlist_exec(&args);
 11031104         strlist_free(&args);
 11041105         return retval;
 11051106 }
 11061107 
 11071108 static int
 11081109 assemble_input(char *input, char *output)
 11091110 {
 11101111         struct strlist args;
 11111112         int retval;
 11121113 
 11131114         strlist_init(&args);
 11141115 #ifdef PCC_EARLY_AS_ARGS
 11151116         PCC_EARLY_AS_ARGS
 11161117 #endif
 11171118         strlist_append_list(&args, &assembler_flags);
 11181119         strlist_append(&args, input);
 11191120         strlist_append(&args, "-o");
 11201121         strlist_append(&args, output);
 11211122         strlist_prepend(&args,
 11221123             find_file(as, &progdirs, X_OK));
 11231124 #ifdef PCC_LATE_AS_ARGS
 11241125         PCC_LATE_AS_ARGS
 11251126 #endif
 11261127         retval = strlist_exec(&args);
 11271128         strlist_free(&args);
 11281129         return retval;
 11291130 }
 11301131 
 11311132 static int
 11321133 preprocess_input(char *input, char *output, int dodep)
 11331134 {
 11341135         struct strlist args;
 11351136         struct string *s;
 11361137         int retval;
 11371138 
 11381139         strlist_init(&args);
 11391140         strlist_append_list(&args, &preprocessor_flags);
 11401141         if (ascpp)
 11411142                 strlist_append(&args, "-D__ASSEMBLER__");
 11421143         STRLIST_FOREACH(s, &includes) {
 11431144                 strlist_append(&args, "-i");
 11441145                 strlist_append(&args, s->value);
 11451146         }
 11461147         STRLIST_FOREACH(s, &incdirs) {
 11471148                 strlist_append(&args, "-I");
 11481149                 strlist_append(&args, s->value);
 11491150         }
 11501151         STRLIST_FOREACH(s, &user_sysincdirs) {
 11511152                 strlist_append(&args, "-S");
 11521153                 strlist_append(&args, s->value);
 11531154         }
 11541155         if (!nostdinc) {
 11551156                 STRLIST_FOREACH(s, &sysincdirs) {
 11561157                         strlist_append(&args, "-S");
 11571158                         strlist_append(&args, s->value);
 11581159                 }
 11591160         }
 11601161         if (dodep)
 11611162                 strlist_append_list(&args, &depflags);
 11621163         strlist_append(&args, input);
 11631164         if (output)
 11641165                 strlist_append(&args, output);
 11651166 
 11661167         strlist_prepend(&args, find_file(passp, &progdirs, X_OK));
 11671168         retval = strlist_exec(&args);
 11681169         strlist_free(&args);
 11691170         return retval;
 11701171 }
 11711172 
 11721173 static int
 11731174 run_linker(void)
 11741175 {
 11751176         struct strlist linker_flags;
 11761177         int retval;
 11771178 
 11781179         if (outfile) {
 11791180                 strlist_prepend(&early_linker_flags, outfile);
 11801181                 strlist_prepend(&early_linker_flags, "-o");
 11811182         }
 11821183         strlist_init(&linker_flags);
 11831184         strlist_append_list(&linker_flags, &early_linker_flags);
 11841185         strlist_append_list(&linker_flags, &middle_linker_flags);
 11851186         strlist_append_list(&linker_flags, &late_linker_flags);
 11861187         strlist_prepend(&linker_flags, find_file(ld, &progdirs, X_OK));
 11871188 
 11881189         retval = strlist_exec(&linker_flags);
 11891190 
 11901191         strlist_free(&linker_flags);
 11911192         return retval;
 11921193 }
 11931194 
 11941195 static char *cxxt[] = { "cc", "cp", "cxx", "cpp", "CPP", "c++", "C" };
 11951196 int
 11961197 cxxsuf(char *s)
 11971198 {
 11981199         unsigned i;
 11991200         for (i = 0; i < sizeof(cxxt)/sizeof(cxxt[0]); i++)
 12001201                 if (strcmp(s, cxxt[i]) == 0)
 12011202                         return 1;
 12021203         return 0;
 12031204 }
 12041205 
 12051206 char *
 12061207 getsufp(char *s)
 12071208 {
 12081209         register char *p;
 12091210 
 12101211         if ((p = strrchr(s, '.')) && p[1] != '\0')
 12111212                 return &p[1];
 12121213         return "";
 12131214 }
 12141215 
 12151216 int
 12161217 getsuf(char *s)
 12171218 {
 12181219         register char *p;
 12191220 
 12201221         if ((p = strrchr(s, '.')) && p[1] != '\0' && p[2] == '\0')
 12211222                 return p[1];
 12221223         return(0);
 12231224 }
 12241225 
 12251226 /*
 12261227  * Get basename of string s, copy it and change its suffix to ch.
 12271228  */
 12281229 char *
 12291230 setsuf(char *s, char ch)
 12301231 {
 12311232         char *e, *p, *rp;
 12321233 
 12331234         e = NULL;
 12341235         for (p = s; *p; p++) {
 12351236                 if (*p == '/')
 12361237                         s = p + 1;
 12371238                 if (*p == '.')
 12381239                         e = p;
 12391240         }
 12401241         if (s > e)
 12411242                 e = p;
 12421243 
 12431244         rp = p = xmalloc(e - s + 3);
 12441245         while (s < e)
 12451246                 *p++ = *s++;
 12461247 
 12471248         *p++ = '.';
 12481249         *p++ = ch;
 12491250         *p = '\0';
 12501251         return rp;
 12511252 }
 12521253 
 12531254 #ifdef os_win32
 12541255 
 12551256 static int
 12561257 strlist_exec(struct strlist *l)
 12571258 {
 12581259         char *cmd;
 12591260         STARTUPINFO si;
 12601261         PROCESS_INFORMATION pi;
 12611262         DWORD exitCode;
 12621263         BOOL ok;
 12631264 
 12641265         cmd = win32commandline(l);
 12651266         if (vflag)
 12661267                 printf("%s\n", cmd);
 12671268 
 12681269         ZeroMemory(&si, sizeof(STARTUPINFO));
 12691270         si.cb = sizeof(STARTUPINFO);
 12701271         ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
 12711272 
 12721273         ok = CreateProcess(NULL// the executable program
 12731274                 cmd,   // the command line arguments
 12741275                 NULL,       // ignored
 12751276                 NULL,       // ignored
 12761277                 TRUE,       // inherit handles
 12771278                 HIGH_PRIORITY_CLASS,
 12781279                 NULL,       // ignored
 12791280                 NULL,       // ignored
 12801281                 &si,
 12811282                 &pi);
 12821283 
 12831284         if (!ok) {
 12841285                 fprintf(stderr, "Can't find %s\n", STRLIST_FIRST(l)->value);
 12851286                 return 100;
 12861287         }
 12871288 
 12881289         WaitForSingleObject(pi.hProcess, INFINITE);
 12891290         GetExitCodeProcess(pi.hProcess, &exitCode);
 12901291         CloseHandle(pi.hProcess);
 12911292         CloseHandle(pi.hThread);
 12921293 
 12931294         return (exitCode != 0);
 12941295 }
 12951296 
 12961297 #else
 12971298 
 12981299 static int
 12991300 strlist_exec(struct strlist *l)
 13001301 {
 13011302         sig_atomic_t exit_now = 0;
 13021303         sig_atomic_t child;
 13031304         char **argv;
 13041305         size_t argc;
 13051306         int result;
 13061307 
 13071308         strlist_make_array(l, &argv, &argc);
 13081309         if (vflag) {
 13091310                 printf("Calling ");
 13101311                 strlist_print(l, stdout);
 13111312                 printf("\n");
 13121313         }
 13131314 
 13141315         switch ((child = fork())) {
 13151316         case 0:
 13161317                 execvp(argv[0], argv);
 13171318                 result = write(STDERR_FILENO, "Exec of ", 8);
 13181319                 result = write(STDERR_FILENO, argv[0], strlen(argv[0]));
 13191320                 result = write(STDERR_FILENO, "failed\n", 7);
 13201321                 (void)result;
 13211322                 _exit(127);
 13221323         case -1:
 13231324                 error("fork failed");
 13241325         default:
 13251326                 while (waitpid(child, &result, 0) == -1 && errno == EINTR)
 13261327                         /* nothing */(void)0;
 13271328                 result = WEXITSTATUS(result);
 13281329                 if (result)
 13291330                         error("%s terminated with status %d", argv[0], result);
 13301331                 while (argc-- > 0)
 13311332                         free(argv[argc]);
 13321333                 free(argv);
 13331334                 break;
 13341335         }
 13351336         return exit_now;
 13361337 }
 13371338 
 13381339 #endif
 13391340 
 13401341 /*
 13411342  * Catenate two (optional) strings together
 13421343  */
 13431344 char *
 13441345 cat(const char *a, const char *b)
 13451346 {
 13461347         size_t len;
 13471348         char *rv;
 13481349 
 13491350         len = (a ? strlen(a) : 0) + (b ? strlen(b) : 0) + 1;
 13501351         rv = xmalloc(len);
 13511352         snprintf(rv, len, "%s%s", (a ? a : ""), (b ? b : ""));
 13521353         return rv;
 13531354 }
 13541355 
 13551356 int
 13561357 cunlink(char *f)
 13571358 {
 13581359         if (f==0 || Xflag)
 13591360                 return(0);
 13601361         return (unlink(f));
 13611362 }
 13621363 
 13631364 #ifdef os_win32
 13641365 char *
 13651366 gettmp(void)
 13661367 {
 13671368         DWORD pathSize;
 13681369         char pathBuffer[MAX_PATH + 1];
 13691370         char tempFilename[MAX_PATH];
 13701371         UINT uniqueNum;
 13711372 
 13721373         pathSize = GetTempPath(sizeof(pathBuffer), pathBuffer);
 13731374         if (pathSize == 0 || pathSize > sizeof(pathBuffer))
 13741375                 pathBuffer[0] = '\0';
 13751376         uniqueNum = GetTempFileName(pathBuffer, "ctm", 0, tempFilename);
 13761377         if (uniqueNum == 0)
 13771378                 errorx(8, "GetTempFileName failed: path \"%s\"", pathBuffer);
 13781379 
 13791380         return xstrdup(tempFilename);
 13801381 }
 13811382 
 13821383 #else
 13831384 
 13841385 char *
 13851386 gettmp(void)
 13861387 {
 13871388         char *sfn = xstrdup("/tmp/ctm.XXXXXX");
 13881389         int fd = -1;
 13891390 
 13901391         if ((fd = mkstemp(sfn)) == -1) {
 13911392                 fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
 13921393                 dexit(8);
 13931394         }
 13941395         close(fd);
 13951396         return sfn;
 13961397 }
 13971398 #endif
 13981399 
 13991400 static void
 14001401 expand_sysroot(void)
 14011402 {
 14021403         struct string *s;
 14031404         struct strlist *lists[] = { &crtdirs, &sysincdirs, &incdirs,
 14041405             &user_sysincdirs, &libdirs, &progdirs, &dirafterdirs, NULL };
 14051406         const char *sysroots[] = { sysroot, isysroot, isysroot, isysroot,
 14061407             sysroot, sysroot, isysroot, NULL };
 14071408         size_t i, sysroot_len, value_len;
 14081409         char *path;
 14091410 
 14101411         assert(sizeof(lists) / sizeof(lists[0]) ==
 14111412                sizeof(sysroots) / sizeof(sysroots[0]));
 14121413 
 14131414         for (i = 0; lists[i] != NULL; ++i) {
 14141415                 STRLIST_FOREACH(s, lists[i]) {
 14151416                         if (s->value[0] != '=')
 14161417                                 continue;
 14171418                         sysroot_len = strlen(sysroots[i]);
 14181419                         /* Skipped '=' compensates additional space for '\0' */
 14191420                         value_len = strlen(s->value);
 14201421                         path = xmalloc(sysroot_len + value_len);
 14211422                         memcpy(path, sysroots[i], sysroot_len);
 14221423                         memcpy(path + sysroot_len, s->value + 1, value_len);
 14231424                         free(s->value);
 14241425                         s->value = path;
 14251426                 }
 14261427         }
 14271428 }
 14281429 
 14291430 
 14301431 void
 14311432 oerror(char *s)
 14321433 {
 14331434         fprintf(stderr, "error: unknown option '%s'\n", s);
 14341435         dexit(8);
 14351436 }
 14361437 
 14371438 void
 14381439 aerror(char *s)
 14391440 {
 14401441         fprintf(stderr, "error: missing argument to '%s'\n", s);
 14411442         dexit(8);
 14421443 }
 14431444 
 14441445 /*
 14451446  * See if m matches the beginning of string str, if it does return the
 14461447  * remaining of str, otherwise NULL.
 14471448  */
 14481449 char *
 14491450 argnxt(char *str, char *m)
 14501451 {
 14511452         if (strncmp(str, m, strlen(m)))
 14521453                 return NULL; /* No match */
 14531454         return str + strlen(m);
 14541455 }
 14551456 
 14561457 /*
 14571458  * Return next argument to option, or complain.
 14581459  */
 14591460 char *
 14601461 nxtopt(char *o)
 14611462 {
 14621463         int l;
 14631464 
 14641465         if (o != NULL) {
 14651466                 l = strlen(o);
 14661467                 if (lav[0][l] != 0)
 14671468                         return &lav[0][l];
 14681469         }
 14691470         if (lac == 0)
 14701471                 aerror(o);
 14711472         lav++;
 14721473         lac--;
 14731474         return lav[0];
 14741475 }
 14751476 
 14761477 struct flgcheck {
 14771478         int *flag;
 14781479         int set;
 14791480         char *def;
 14801481 } cppflgcheck[] = {
 14811482         { &vflag, 1, "-v" },
 14821483         { &freestanding, 1, "-D__STDC_HOSTED__=0" },
 14831484         { &freestanding, 0, "-D__STDC_HOSTED__=1" },
 14841485         { &cxxflag, 1, "-D__cplusplus" },
 14851486         { &xuchar, 1, "-D__CHAR_UNSIGNED__" },
 14861487         { &sspflag, 1, "-D__SSP__" },
 14871488         { &pthreads, 1, "-D_PTHREADS" },
 14881489         { &Oflag, 1, "-D__OPTIMIZE__" },
 14891490         { &tflag, 1, "-t" },
 14901491         { &kflag, 1, "-D__PIC__" },
 14911492         { 0 },
 14921493 };
 14931494 
 14941495 static void
 14951496 cksetflags(struct flgcheck *fs, struct strlist *sl, int which)
 14961497 {
 14971498         void (*fn)(struct strlist *, const char *);
 14981499 
 14991500         fn = which == 'p' ? strlist_prepend : strlist_append;
 15001501         for (; fs->flag; fs++) {
 15011502                 if (fs->set && *fs->flag)
 15021503                         fn(sl, fs->def);
 15031504                 if (!fs->set && !*fs->flag)
 15041505                         fn(sl, fs->def);
 15051506         }
 15061507 }
 15071508 
 15081509 static char *defflags[] = {
 15091510         "-D__PCC__=" MKS(PCC_MAJOR),
 15101511         "-D__PCC_MINOR__=" MKS(PCC_MINOR),
 15111512         "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR),
 15121513         "-D__VERSION__=" MKS(VERSSTR),
 15131514         "-D__SCHAR_MAX__=" MKS(MAX_CHAR),
 15141515         "-D__SHRT_MAX__=" MKS(MAX_SHORT),
 15151516         "-D__INT_MAX__=" MKS(MAX_INT),
 15161517         "-D__LONG_MAX__=" MKS(MAX_LONG),
 15171518         "-D__LONG_LONG_MAX__=" MKS(MAX_LONGLONG),
 15181519 
 15191520         "-D__STDC_ISO_10646__=200009L",
 15201521         "-D__WCHAR_TYPE__=" WCT,
 15211522         "-D__SIZEOF_WCHAR_T__=" MKS(WCHAR_SIZE),
 15221523         "-D__WCHAR_MAX__=" WCM,
 15231524         "-D__WINT_TYPE__=" PCC_WINT_TYPE,
 15241525         "-D__SIZE_TYPE__=" PCC_SIZE_TYPE,
 15251526         "-D__PTRDIFF_TYPE__=" PCC_PTRDIFF_TYPE,
 15261527         "-D__SIZEOF_WINT_T__=4",
 15271528 };
 15281529 
 15291530 static char *gcppflags[] = {
 15301531 #ifndef os_win32
 15311532 #ifdef GCC_COMPAT
 15321533         "-D__GNUC__=4",
 15331534         "-D__GNUC_MINOR__=3",
 15341535         "-D__GNUC_PATCHLEVEL__=1",
 15351536         "-D__REGISTER_PREFIX__=" REGISTER_PREFIX,
 15361537         "-D__USER_LABEL_PREFIX__=" USER_LABEL_PREFIX,
 15371538 #endif
 15381539 #endif
 15391540 };
 15401541 
 15411542 /* These should _not_ be defined here */
 15421543 static char *fpflags[] = {
 15431544 #if defined(os_darwin) || defined(os_netbsd)
 15441545         "-D__FLT_RADIX__=2",
 15451546         "-D__FLT_DIG__=6",
 15461547         "-D__FLT_EPSILON__=1.19209290e-07F",
 15471548         "-D__FLT_MANT_DIG__=24",
 15481549         "-D__FLT_MAX_10_EXP__=38",
 15491550         "-D__FLT_MAX_EXP__=128",
 15501551         "-D__FLT_MAX__=3.40282347e+38F",
 15511552         "-D__FLT_MIN_10_EXP__=(-37)",
 15521553         "-D__FLT_MIN_EXP__=(-125)",
 15531554         "-D__FLT_MIN__=1.17549435e-38F",
 15541555         "-D__DBL_DIG__=15",
 15551556         "-D__DBL_EPSILON__=2.2204460492503131e-16",
 15561557         "-D__DBL_MANT_DIG__=53",
 15571558         "-D__DBL_MAX_10_EXP__=308",
 15581559         "-D__DBL_MAX_EXP__=1024",
 15591560         "-D__DBL_MAX__=1.7976931348623157e+308",
 15601561         "-D__DBL_MIN_10_EXP__=(-307)",
 15611562         "-D__DBL_MIN_EXP__=(-1021)",
 15621563         "-D__DBL_MIN__=2.2250738585072014e-308",
 15631564 #if defined(mach_i386) || defined(mach_amd64)
 15641565         "-D__LDBL_DIG__=18",
 15651566         "-D__LDBL_EPSILON__=1.08420217248550443401e-19L",
 15661567         "-D__LDBL_MANT_DIG__=64",
 15671568         "-D__LDBL_MAX_10_EXP__=4932",
 15681569         "-D__LDBL_MAX_EXP__=16384",
 15691570         "-D__LDBL_MAX__=1.18973149535723176502e+4932L",
 15701571         "-D__LDBL_MIN_10_EXP__=(-4931)",
 15711572         "-D__LDBL_MIN_EXP__=(-16381)",
 15721573         "-D__LDBL_MIN__=3.36210314311209350626e-4932L",
 15731574 #else
 15741575         "-D__LDBL_DIG__=15",
 15751576         "-D__LDBL_EPSILON__=2.2204460492503131e-16",
 15761577         "-D__LDBL_MANT_DIG__=53",
 15771578         "-D__LDBL_MAX_10_EXP__=308",
 15781579         "-D__LDBL_MAX_EXP__=1024",
 15791580         "-D__LDBL_MAX__=1.7976931348623157e+308",
 15801581         "-D__LDBL_MIN_10_EXP__=(-307)",
 15811582         "-D__LDBL_MIN_EXP__=(-1021)",
 15821583         "-D__LDBL_MIN__=2.2250738585072014e-308",
 15831584 #endif
 15841585 #endif
 15851586 };
 15861587 
 15871588 
 15881589 /*
 15891590  * Configure the standard cpp flags.
 15901591  */
 15911592 void
 15921593 setup_cpp_flags(void)
 15931594 {
 15941595         int i;
 15951596 
 15961597         /* a bunch of misc defines */
 15971598         for (i = 0; i < (int)sizeof(defflags)/(int)sizeof(char *); i++)
 15981599                 strlist_prepend(&preprocessor_flags, defflags[i]);
 15991600 
 16001601         for (i = 0; i < (int)sizeof(gcppflags)/(int)sizeof(char *); i++)
 16011602                 strlist_prepend(&preprocessor_flags, gcppflags[i]);
 16021603         strlist_prepend(&preprocessor_flags, xgnu89 ?
 16031604             "-D__GNUC_GNU_INLINE__" : "-D__GNUC_STDC_INLINE__");
 16041605 
 16051606         cksetflags(cppflgcheck, &preprocessor_flags, 'p');
 16061607 
 16071608         for (i = 0; i < (int)sizeof(fpflags)/(int)sizeof(char *); i++)
 16081609                 strlist_prepend(&preprocessor_flags, fpflags[i]);
 16091610 
 16101611         for (i = 0; cppadd[i]; i++)
 16111612                 strlist_prepend(&preprocessor_flags, cppadd[i]);
 16121613         for (i = 0; cppmdadd[i]; i++)
 16131614                 strlist_prepend(&preprocessor_flags, cppmdadd[i]);
 16141615 
 16151616         /* Include dirs */
 16161617         strlist_append(&sysincdirs, "=" INCLUDEDIR "pcc/");
 16171618         strlist_append(&sysincdirs, "=" STDINC);
 16181619 #ifdef PCCINCDIR
 16191620         if (cxxflag)
 16201621                 strlist_append(&sysincdirs, "=" PCCINCDIR "/c++");
 16211622         strlist_append(&sysincdirs, "=" PCCINCDIR);
 16221623 #endif
 16231624 }
 16241625 
 16251626 struct flgcheck ccomflgcheck[] = {
 16261627         { &Oflag, 1, "-xtemps" },
 16271628         { &Oflag, 1, "-xdeljumps" },
 16281629         { &Oflag, 1, "-xinline" },
 16291630         { &Oflag, 1, "-xdce" },
 16301631 #ifdef notyet
 16311632         { &Oflag, 1, "-xssa" },
 16321633 #endif
 16331634         { &freestanding, 1, "-ffreestanding" },
 16341635         { &pgflag, 1, "-p" },
 16351636         { &gflag, 1, "-g" },
 16361637         { &xgnu89, 1, "-xgnu89" },
 16371638         { &xgnu99, 1, "-xgnu99" },
 16381639         { &xuchar, 1, "-xuchar" },
 16391640 #if !defined(os_sunos) && !defined(mach_i386)
 16401641         { &vflag, 1, "-v" },
 16411642 #endif
 16421643 #ifdef os_darwin
 16431644         { &Bstatic, 1, "-k" },
 16441645 #elif defined(os_sunos) && defined(mach_i386)
 16451646         { &kflag, 1, "-K" },
 16461647         { &kflag, 1, "pic" },
 16471648 #else
 16481649         { &kflag, 1, "-k" },
 16491650 #endif
 16501651         { &sspflag, 1, "-fstack-protector" },
 16511652         { 0 }
 16521653 };
 16531654 
 16541655 void
 16551656 setup_ccom_flags(void)
 16561657 {
 16571658 
 16581659         cksetflags(ccomflgcheck, &compiler_flags, 'a');
 16591660 }
 16601661 
 16611662 static int one = 1;
 16621663 
 16631664 struct flgcheck asflgcheck[] = {
 16641665 #if defined(USE_YASM)
 16651666         { &one, 1, "-p" },
 16661667         { &one, 1, "gnu" },
 16671668         { &one, 1, "-f" },
 16681669 #if defined(os_win32)
 16691670         { &one, 1, "win32" },
 16701671 #elif defined(os_darwin)
 16711672         { &one, 1, "macho" },
 16721673 #else
 16731674         { &one, 1, "elf" },
 16741675 #endif
 16751676 #endif
 16761677 #if defined(os_sunos) && defined(mach_sparc64)
 16771678         { &one, 1, "-m64" },
 16781679 #endif
 16791680 #if defined(os_darwin)
 16801681         { &Bstatic, 1, "-static" },
 16811682 #endif
 16821683 #if !defined(USE_YASM)
 16831684         { &vflag, 1, "-v" },
 16841685 #endif
 16851686         { &kflag, 1, "-k" },
 16861687 #ifdef os_darwin
 16871688         { &one, 1, "-arch" },
 16881689 #if mach_amd64
 16891690         { &amd64_i386, 1, "i386" },
 16901691         { &amd64_i386, 0, "x86_64" },
 16911692 #else
 16921693         { &one, 1, "i386" },
 16931694 #endif
 16941695 #else
 16951696 #ifdef mach_amd64
 16961697         { &amd64_i386, 1, "--32" },
 16971698 #endif
 16981699 #endif
 16991700         { 0 }
 17001701 };
 17011702 void
 17021703 setup_as_flags(void)
 17031704 {
 17041705         one = one;
 17051706 #ifdef PCC_SETUP_AS_ARGS
 17061707         PCC_SETUP_AS_ARGS
 17071708 #endif
 17081709         cksetflags(asflgcheck, &assembler_flags, 'a');
 17091710 }
 17101711 
 17111712 struct flgcheck ldflgcheck[] = {
 17121713 #ifndef MSLINKER
 17131714         { &vflag, 1, "-v" },
 17141715 #endif
 17151716 #ifdef os_darwin
 17161717         { &shared, 1, "-dylib" },
 17171718 #elif defined(os_win32)
 17181719         { &shared, 1, "-Bdynamic" },
 17191720 #else
 17201721         { &shared, 1, "-shared" },
 17211722 #endif
 17221723 #if !defined(os_sunos) && !defined(os_win32)
 17231724 #ifndef os_darwin
 17241725         { &shared, 0, "-d" },
 17251726 #endif
 17261727 #endif
 17271728 #ifdef os_darwin
 17281729         { &Bstatic, 1, "-static" },
 17291730 #else
 17301731         { &Bstatic, 1, "-Bstatic" },
 17311732 #endif
 17321733 #if !defined(os_darwin) && !defined(os_sunos)
 17331734         { &gflag, 1, "-g" },
 17341735 #endif
 17351736         { &pthreads, 1, "-lpthread" },
 17361737         { 0 },
 17371738 };
 17381739 
 17391740 static void
 17401741 strap(struct strlist *sh, struct strlist *cd, char *n, int where)
 17411742 {
 17421743         void (*fn)(struct strlist *, const char *);
 17431744         char *fil;
 17441745 
 17451746         if (n == 0)
 17461747                 return; /* no crtfile */
 17471748 
 17481749         fn = where == 'p' ? strlist_prepend : strlist_append;
 17491750         fil = find_file(n, cd, R_OK);
 17501751         (*fn)(sh, fil);
 17511752 }
 17521753 
 17531754 void
 17541755 setup_ld_flags(void)
 17551756 {
 17561757         char *b, *e;
 17571758         int i;
 17581759 
 17591760         cksetflags(ldflgcheck, &early_linker_flags, 'a');
 17601761         if (Bstatic == 0 && shared == 0 && rflag == 0) {
 17611762                 for (i = 0; dynlinker[i]; i++)
 17621763                         strlist_append(&early_linker_flags, dynlinker[i]);
 17631764                 strlist_append(&early_linker_flags, "-e");
 17641765                 strlist_append(&early_linker_flags, STARTLABEL);
 17651766         }
 17661767         if (shared == 0 && rflag)
 17671768                 strlist_append(&early_linker_flags, "-r");
 17681769         if (sysroot && *sysroot)
 17691770                 strlist_append(&early_linker_flags, cat("--sysroot=", sysroot));
 17701771         if (!nostdlib) {
 17711772                 /* library search paths */
 17721773                 if (pcclibdir)
 17731774                         strlist_append(&late_linker_flags,
 17741775                             cat("-L", pcclibdir));
 17751776                 for (i = 0; deflibdirs[i]; i++)
 17761777                         strlist_append(&late_linker_flags,
 17771778                             cat("-L", deflibdirs[i]));
 17781779                 /* standard libraries */
 17791780                 if (pgflag) {
 17801781                         for (i = 0; defproflibs[i]; i++)
 17811782                                 strlist_append(&late_linker_flags,
 17821783                                      defproflibs[i]);
 17831784                 } else if (cxxflag) {
 17841785                         for (i = 0; defcxxlibs[i]; i++)
 17851786                                 strlist_append(&late_linker_flags,
 17861787                                     defcxxlibs[i]);
 17871788                 } else {
 17881789                         for (i = 0; deflibs[i]; i++)
 17891790                                 strlist_append(&late_linker_flags, deflibs[i]);
 17901791                 }
 17911792         }
 17921793         if (!nostartfiles) {
 17931794                 if (Bstatic) {
 17941795                         b = CRTBEGIN_T;
 17951796                         e = CRTEND_T;
 17961797                 } else if (shared /* || pieflag */) {
 17971798                         b = CRTBEGIN_S;
 17981799                         e = CRTEND_S;
 17991800                 }  else {
 18001801                         b = CRTBEGIN;
 18011802                         e = CRTEND;
 18021803                 }
 18031804                 strap(&middle_linker_flags, &crtdirs, b, 'p');
 18041805                 strap(&late_linker_flags, &crtdirs, e, 'a');
 18051806                 strap(&middle_linker_flags, &crtdirs, CRTI, 'p');
 18061807                 strap(&late_linker_flags, &crtdirs, CRTN, 'a');
 18071808                 if (shared == 0) {
 18081809                         if (pgflag)
 18091810                                 b = GCRT0;
 18101811 #ifdef notyet
 18111812                         else if (pieflag)
 18121813                                 b = SCRT0;
 18131814 #endif
 18141815                         else
 18151816                                 b = CRT0;
 18161817                         strap(&middle_linker_flags, &crtdirs, b, 'p');
 18171818                 }
 18181819         }
 18191820 }
 18201821 
 18211822 #ifdef os_win32
 18221823 char *
 18231824 win32pathsubst(char *s)
 18241825 {
 18251826         char env[1024];
 18261827         DWORD len;
 18271828 
 18281829         len = ExpandEnvironmentStrings(s, env, sizeof(env));
 18291830         if (len == 0 || len > sizeof(env))
 18301831                 errorx(8, "ExpandEnvironmentStrings failed, len %lu", len);
 18311832 
 18321833         len--;  /* skip nil */
 18331834         while (len-- > 0 && (env[len] == '/' || env[len] == '\\'))
 18341835                 env[len] = '\0';
 18351836 
 18361837         return xstrdup(env);
 18371838 }
 18381839 
 18391840 char *
 18401841 win32commandline(struct strlist *l)
 18411842 {
 18421843         const struct string *s;
 18431844         char *cmd;
 18441845         char *p;
 18451846         int len;
 18461847         int j, k;
 18471848 
 18481849         len = 0;
 18491850         STRLIST_FOREACH(s, l) {
 18501851                 len++;
 18511852                 for (j = 0; s->value[j] != '\0'; j++) {
 18521853                         if (s->value[j] == '\"') {
 18531854                                 for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
 18541855                                         len++;
 18551856                                 len++;
 18561857                         }
 18571858                         len++;
 18581859                 }
 18591860                 for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
 18601861                         len++;
 18611862                 len++;
 18621863                 len++;
 18631864         }
 18641865 
 18651866         p = cmd = xmalloc(len);
 18661867 
 18671868         STRLIST_FOREACH(s, l) {
 18681869                 *p++ = '\"';
 18691870                 for (j = 0; s->value[j] != '\0'; j++) {
 18701871                         if (s->value[j] == '\"') {
 18711872                                 for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
 18721873                                         *p++ = '\\';
 18731874                                 *p++ = '\\';
 18741875                         }
 18751876                         *p++ = s->value[j];
 18761877                 }
 18771878                 for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
 18781879                         *p++ = '\\';
 18791880                 *p++ = '\"';
 18801881                 *p++ = ' ';
 18811882         }
 18821883         p[-1] = '\0';
 18831884 
 18841885         return cmd;
 18851886 }
 18861887 #endif
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-10-01 22:20 +0200