]> git.mdlowis.com Git - proto/aardvark-linux.git/commitdiff
Added a semi-functional version of the PCC compiler. Will compile and link static...
authorMike Lowis <mike.lowis@gentex.com>
Wed, 24 Feb 2016 20:58:47 +0000 (15:58 -0500)
committerMike Lowis <mike.lowis@gentex.com>
Wed, 24 Feb 2016 20:58:47 +0000 (15:58 -0500)
build.sh
cc.c [new file with mode: 0644]
ccconfig.h [new file with mode: 0644]

index 86cd0e5160bff46bd1365752a29551853156eca4..c243263dce73e09e458f671a09aee811a05cd55d 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -30,16 +30,24 @@ gitclone(){
     fi
 }
 
+symlink(){
+    target=$1
+    dest=$2
+    if [ ! -L "$dest" ]; then
+        ln -sfv "$target" "$dest"
+    fi
+}
+
 ###############################################################################
-# Install the Base Packages
+# Install the Toolchain
 ###############################################################################
 # Fetch the prebuilt cross compiler
 fetch crossx86-x86_64-linux-musl-1.1.12.tar.xz \
       https://e82b27f594c813a5a4ea5b07b06f16c3777c3b8c.googledrive.com/host/0BwnS5DMB0YQ6bDhPZkpOYVFhbk0/musl-1.1.12/ \
       "$AL_TOOLS"
-rm -f "$AL_TOOLS/$AL_TGT/lib/libc.so"
-[ ! -L "$AL_ROOT/sbin" ] && ln -sfv bin "$AL_ROOT/sbin"
-[ ! -L "$AL_ROOT/usr" ] && ln -sfv . "$AL_ROOT/usr"
+rm -f "$AL_TOOLS/x86_64-linux-musl/lib/libc.so"
+#symlink bin "$AL_ROOT/sbin"
+#symlink .   "$AL_ROOT/usr"
 mkdir -pv "$AL_ROOT/bin"
 mkdir -pv "$AL_ROOT/dev"
 mkdir -pv "$AL_ROOT/etc"
@@ -51,6 +59,52 @@ mkdir -pv "$AL_ROOT/var"
 cp etc/* "$AL_ROOT/etc/"
 cp bin/* "$AL_ROOT/bin/"
 
+# Install musl
+fetch musl-1.1.12.tar.gz http://www.musl-libc.org/releases/ "$AL_ROOT/src/musl"
+if [ ! -f "$AL_ROOT/lib/libc.a" ]; then
+    cd "$AL_ROOT/src/musl"
+    ./configure --prefix="$AL_ROOT"
+    make $MAKEFLAGS install
+    make clean
+    cd $AL
+fi
+
+# Install pcc
+gitclone https://github.com/antoineL/pcc.git "$AL_ROOT/src/pcc"
+if [ ! -f "$AL_ROOT/bin/cc" ]; then
+    cd "$AL_ROOT/src/pcc/"
+    cp "$AL/cc.c" "$AL_ROOT/src/pcc/cc/cc/"
+    cp "$AL/ccconfig.h" "$AL_ROOT/src/pcc/os/linux/"
+    ./configure                      \
+        --prefix="$AL_ROOT"          \
+        --exec-prefix="$AL_ROOT"     \
+        --sbindir="$AL_ROOT/bin"     \
+        --libexecdir="$AL_ROOT/bin"  \
+        --with-libdir="/lib"         \
+        --enable-native
+    make $MAKEFLAGS
+    make install
+    cp cc/cc/cc "$AL_ROOT/bin"
+    chmod 755 "$AL_ROOT/bin/cc"
+    cd $AL
+fi
+
+# Install binutils
+fetch binutils-2.25.tar.bz2 http://ftp.gnu.org/gnu/binutils/ "$AL_ROOT/src/binutils"
+if [ ! -f "$AL_ROOT/bin/as" ]; then
+    cd "$AL_ROOT/src/binutils/"
+    ./configure \
+        --prefix="$AL_ROOT"       \
+        --exec-prefix="$AL_ROOT"  \
+        --disable-shared
+    make $MAKEFLAGS
+    make install
+    cd $AL
+fi
+
+###############################################################################
+# Install the Base Packages
+###############################################################################
 # Install sbase
 gitclone http://git.suckless.org/sbase "$AL_SOURCES/sbase"
 if [ ! -f "$AL_ROOT/bin/ls" ]; then
@@ -59,7 +113,6 @@ if [ ! -f "$AL_ROOT/bin/ls" ]; then
     git apply ../../patches/sbase.diff
     make $MAKEFLAGS CC="$CC" LD="$LD" LDFLAGS="$LDFLAGS"
     make $MAKEFLAGS PREFIX=$AL_ROOT install
-    #rm -f "$AL_ROOT/bin/grep"
     cd $AL
 fi
 
@@ -94,6 +147,7 @@ if [ ! -f "$AL_ROOT/bin/groups" ]; then
         LDFLAGS="--static"  \
         --prefix="$AL_ROOT" \
         --exec-prefix="$AL_ROOT" \
+        --sbindir="$AL_ROOT/bin" \
         --sysconfdir="$AL_ROOT/etc"   \
         --with-group-name-max-length=32
     make $MAKEFLAGS install
@@ -141,153 +195,45 @@ if [ ! -f "$AL_ROOT/bin/diff" ]; then
     cd $AL
 fi
 
-## Install GNU grep
-#fetch grep-2.9.tar.xz http://ftp.gnu.org/gnu/grep/ "$AL_SOURCES/grep"
-#if [ ! -f "$AL_ROOT/bin/grep" ]; then
-#    cd "$AL_SOURCES/grep"
-#    ./configure             \
-#        LDFLAGS="--static"  \
-#        --prefix="$AL_ROOT" \
-#        --disable-threads   \
-#        --disable-rpath     \
-#        --disable-nls
-#    make $MAKEFLAGS install
-#    cd $AL
-#fi
-
-# Install GNU tar
-#fetch tar-1.28.tar.xz http://ftp.gnu.org/gnu/tar/ "$AL_SOURCES/tar"
-#if [ ! -f "$AL_ROOT/bin/tar" ]; then
-#    cd "$AL_SOURCES/tar"
-#    ./configure \
-#        --prefix="$AL_ROOT"
-#    make $MAKEFLAGS install
-#    cd $AL
-#fi
-
-## Install GNU make
-#fetch make-4.1.tar.gz http://ftp.gnu.org/gnu/make/ "$AL_SOURCES/make"
-#if [ ! -f "$AL_ROOT/bin/make" ]; then
-#    cd "$AL_SOURCES/make"
-#    ./configure              \
-#        LDFLAGS="--static"   \
-#        --prefix="$AL_ROOT"  \
-#        --without-guile
-#    make $MAKEFLAGS install
-#    cd $AL
-#fi
-
-
-# Install GNU inetutils
-#fetch inetutils-1.9.4.tar.xz http://ftp.gnu.org/gnu/inetutils/ "$AL_SOURCES/inetutils"
-#if [ ! -f "$AL_ROOT/bin/ping" ]; then
-#    cd "$AL_SOURCES/inetutils"
-#    ./configure              \
-#        --prefix="$AL_ROOT"  \
-#        --localstatedir=/var \
-#        --disable-logger     \
-#        --disable-rcp        \
-#        --disable-rexec      \
-#        --disable-rlogin     \
-#        --disable-rsh        \
-#        --disable-servers
-#    make $MAKEFLAGS install
-#    cd $AL
-#fi
-
-## Install GNU bc
-#fetch bc-1.06.tar.gz http://ftp.gnu.org/gnu/bc/ "$AL_SOURCES/bc"
-#if [ ! -f "$AL_ROOT/bin/bc" ]; then
-#    cd "$AL_SOURCES/bc"
-#    ./configure              \
-#        LDFLAGS="--static"   \
-#        --prefix="$AL_ROOT"
-#    make $MAKEFLAGS install
-#    cd $AL
-#fi
-#
-## Install GNU gzip
-#fetch gzip-1.6.tar.xz http://ftp.gnu.org/gnu/gzip/ "$AL_SOURCES/gzip"
-#if [ ! -f "$AL_ROOT/bin/gzip" ]; then
-#    cd "$AL_SOURCES/gzip"
-#    ./configure              \
-#        LDFLAGS="--static"   \
-#        --prefix="$AL_ROOT"
-#    make $MAKEFLAGS install
-#    cd $AL
-#fi
-#
-## Install GNU ncurses
-#fetch ncurses-6.0.tar.gz http://ftp.gnu.org/gnu/ncurses/ "$AL_SOURCES/ncurses"
-#if [ ! -f "$AL_ROOT/lib/ncurses" ]; then
-#    cd "$AL_SOURCES/ncurses"
-#    ./configure              \
-#        LDFLAGS="--static"   \
-#        --prefix="$AL_TOOLS/lib/gcc/$AL_TGT/5.3.0"  \
-#        --without-shared     \
-#        --without-debug      \
-#        --without-ada        \
-#        --enable-widec       \
-#        --enable-overwrite
-#    make $MAKEFLAGS install
-#    cd $AL
-#fi
-#/tools/bin/../lib/gcc/x86_64-linux-musl/5.3.0/include
-#
-## Install Perl
-#fetch perl-5.22.0.tar.bz2 http://www.cpan.org/src/5.0/ "$AL_SOURCES/perl"
-#if [ ! -f "$AL_ROOT/bin/perl" ]; then
-#    cd "$AL_SOURCES/perl"
-#    ./Configure -des -Dprefix="$AL_ROOT"
-#    make $MAKEFLAGS
-#    cd $AL
-#fi
-
-###############################################################################
-# Install Sources
-###############################################################################
-fetch    pkgsrc.tar.bz2      http://ftp.netbsd.org/pub/pkgsrc/stable/      "$AL_ROOT/pkgsrc/"
-
-#fetch    musl-1.1.12.tar.gz  http://www.musl-libc.org/releases/            "$AL_ROOT/src/musl"
-#gitclone                     http://git.suckless.org/sbase                 "$AL_ROOT/src/sbase"
-#gitclone                     http://git.suckless.org/ubase                 "$AL_ROOT/src/ubase"
-#fetch    mksh-R52b.tgz       https://www.mirbsd.org/MirOS/dist/mir/mksh/   "$AL_ROOT/src/mksh"
-#fetch    make-4.1.tar.gz     http://ftp.gnu.org/gnu/make/                  "$AL_ROOT/src/make"
-#fetch    grep-2.9.tar.xz     http://ftp.gnu.org/gnu/grep/                  "$AL_ROOT/src/grep"
-#fetch    gawk-4.1.3.tar.xz   http://ftp.gnu.org/gnu/gawk/                  "$AL_ROOT/src/gawk"
-#fetch    bc-1.06.tar.gz      http://ftp.gnu.org/gnu/bc/                    "$AL_ROOT/src/bc"
-#fetch    gzip-1.6.tar.xz     http://ftp.gnu.org/gnu/gzip/                  "$AL_ROOT/src/gzip"
-#fetch    ncurses-6.0.tar.gz  http://ftp.gnu.org/gnu/ncurses/               "$AL_ROOT/src/ncurses"
-#fetch    perl-5.22.0.tar.bz2 http://www.cpan.org/src/5.0/                  "$AL_ROOT/src/perl"
-#fetch    linux-4.4.tar.xz    https://cdn.kernel.org/pub/linux/kernel/v4.x/ "$AL_ROOT/src/linux"
+# Install GNU make
+fetch make-4.1.tar.gz http://ftp.gnu.org/gnu/make/ "$AL_SOURCES/make"
+if [ ! -f "$AL_ROOT/bin/make" ]; then
+    cd "$AL_SOURCES/make"
+    ./configure              \
+        LDFLAGS="--static"   \
+        --prefix="$AL_ROOT"  \
+        --without-guile
+    make $MAKEFLAGS install
+    cd $AL
+fi
 
 ###############################################################################
 # Finalize the Chroot
 ###############################################################################
-ln -sfv "$AL_TGT-addr2line"  "$AL_TOOLS/bin/addr2line"
-ln -sfv "$AL_TGT-ar"         "$AL_TOOLS/bin/ar"
-ln -sfv "$AL_TGT-as"         "$AL_TOOLS/bin/as"
-ln -sfv "$AL_TGT-c++"        "$AL_TOOLS/bin/c++"
-ln -sfv "$AL_TGT-c++filt"    "$AL_TOOLS/bin/c++filt"
-ln -sfv "$AL_TGT-cpp"        "$AL_TOOLS/bin/cpp"
-ln -sfv "$AL_TGT-elfedit"    "$AL_TOOLS/bin/elfedit"
-ln -sfv "$AL_TGT-g++"        "$AL_TOOLS/bin/g++"
-ln -sfv "$AL_TGT-gcc"        "$AL_TOOLS/bin/gcc"
-ln -sfv "$AL_TGT-gcc-5.3.0"  "$AL_TOOLS/bin/gcc-5.3.0"
-ln -sfv "$AL_TGT-gcc-ar"     "$AL_TOOLS/bin/gcc-ar"
-ln -sfv "$AL_TGT-gcc-nm"     "$AL_TOOLS/bin/gcc-nm"
-ln -sfv "$AL_TGT-gcc-ranlib" "$AL_TOOLS/bin/gcc-ranlib"
-ln -sfv "$AL_TGT-gcov"       "$AL_TOOLS/bin/gcov"
-ln -sfv "$AL_TGT-gcov-tool"  "$AL_TOOLS/bin/gcov-tool"
-ln -sfv "$AL_TGT-gprof"      "$AL_TOOLS/bin/gprof"
-ln -sfv "$AL_TGT-ld"         "$AL_TOOLS/bin/ld"
-ln -sfv "$AL_TGT-ld.bfd"     "$AL_TOOLS/bin/ld.bfd"
-ln -sfv "$AL_TGT-nm"         "$AL_TOOLS/bin/nm"
-ln -sfv "$AL_TGT-objcopy"    "$AL_TOOLS/bin/objcopy"
-ln -sfv "$AL_TGT-objdump"    "$AL_TOOLS/bin/objdump"
-ln -sfv "$AL_TGT-ranlib"     "$AL_TOOLS/bin/ranlib"
-ln -sfv "$AL_TGT-readelf"    "$AL_TOOLS/bin/readelf"
-ln -sfv "$AL_TGT-size"       "$AL_TOOLS/bin/size"
-ln -sfv "$AL_TGT-strings"    "$AL_TOOLS/bin/strings"
-ln -sfv "$AL_TGT-strip"      "$AL_TOOLS/bin/strip"
-#strip $AL_ROOT/bin/*
+#rm -r "$AL_TOOLS"
+#symlink "$AL_TGT-addr2line"  "$AL_TOOLS/bin/addr2line"
+#symlink "$AL_TGT-ar"         "$AL_TOOLS/bin/ar"
+#symlink "$AL_TGT-as"         "$AL_TOOLS/bin/as"
+#symlink "$AL_TGT-c++"        "$AL_TOOLS/bin/c++"
+#symlink "$AL_TGT-c++filt"    "$AL_TOOLS/bin/c++filt"
+#symlink "$AL_TGT-cpp"        "$AL_TOOLS/bin/cpp"
+#symlink "$AL_TGT-elfedit"    "$AL_TOOLS/bin/elfedit"
+#symlink "$AL_TGT-g++"        "$AL_TOOLS/bin/g++"
+#symlink "$AL_TGT-gcc"        "$AL_TOOLS/bin/gcc"
+#symlink "$AL_TGT-gcc-5.3.0"  "$AL_TOOLS/bin/gcc-5.3.0"
+#symlink "$AL_TGT-gcc-ar"     "$AL_TOOLS/bin/gcc-ar"
+#symlink "$AL_TGT-gcc-nm"     "$AL_TOOLS/bin/gcc-nm"
+#symlink "$AL_TGT-gcc-ranlib" "$AL_TOOLS/bin/gcc-ranlib"
+#symlink "$AL_TGT-gcov"       "$AL_TOOLS/bin/gcov"
+#symlink "$AL_TGT-gcov-tool"  "$AL_TOOLS/bin/gcov-tool"
+#symlink "$AL_TGT-gprof"      "$AL_TOOLS/bin/gprof"
+#symlink "$AL_TGT-ld"         "$AL_TOOLS/bin/ld"
+#symlink "$AL_TGT-ld.bfd"     "$AL_TOOLS/bin/ld.bfd"
+#symlink "$AL_TGT-nm"         "$AL_TOOLS/bin/nm"
+#symlink "$AL_TGT-objcopy"    "$AL_TOOLS/bin/objcopy"
+#symlink "$AL_TGT-objdump"    "$AL_TOOLS/bin/objdump"
+#symlink "$AL_TGT-ranlib"     "$AL_TOOLS/bin/ranlib"
+#symlink "$AL_TGT-readelf"    "$AL_TOOLS/bin/readelf"
+#symlink "$AL_TGT-size"       "$AL_TOOLS/bin/size"
+#symlink "$AL_TGT-strings"    "$AL_TOOLS/bin/strings"
+#symlink "$AL_TGT-strip"      "$AL_TOOLS/bin/strip"
diff --git a/cc.c b/cc.c
new file mode 100644 (file)
index 0000000..6518e95
--- /dev/null
+++ b/cc.c
@@ -0,0 +1,2054 @@
+/*  $Id$    */
+
+/*-
+ * Copyright (c) 2011 Joerg Sonnenberger <joerg@NetBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code and documentation must retain the above
+ * copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditionsand the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *  This product includes software developed or owned by Caldera
+ *  International, Inc.
+ * Neither the name of Caldera International, Inc. nor the names of other
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Front-end to the C compiler.
+ *
+ * Brief description of its syntax:
+ * - Files that end with .c are passed via cpp->ccom->as->ld
+ * - Files that end with .i are passed via ccom->as->ld
+ * - Files that end with .S are passed via cpp->as->ld
+ * - Files that end with .s are passed via as->ld
+ * - Files that end with .o are passed directly to ld
+ * - Multiple files may be given on the command line.
+ * - Unrecognized options are all sent directly to ld.
+ * -c or -S cannot be combined with -o if multiple files are given.
+ *
+ * This file should be rewritten readable.
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <assert.h>
+
+#ifdef  _WIN32
+#include <windows.h>
+#include <process.h>
+#include <io.h>
+#define F_OK    0x00
+#define R_OK    0x04
+#define W_OK    0x02
+#define X_OK    R_OK
+#endif
+
+#include "compat.h"
+
+#include "macdefs.h"
+
+#include "xalloc.h"
+#include "strlist.h"
+
+#include "ccconfig.h"
+/* C command */
+
+#define MKS(x) _MKS(x)
+#define _MKS(x) #x
+
+/* default program names in pcc */
+/* May be overridden if cross-compiler is generated */
+#ifndef CPPROGNAME
+#define CPPROGNAME  "cpp"   /* cc used as cpp */
+#endif
+#ifndef PREPROCESSOR
+#define PREPROCESSOR    "cpp"   /* "real" preprocessor name */
+#endif
+#ifndef COMPILER
+#define COMPILER    "ccom"
+#endif
+#ifndef CXXCOMPILER
+#define CXXCOMPILER "cxxcom"
+#endif
+#ifndef ASSEMBLER
+#define ASSEMBLER   "as"
+#endif
+#ifndef LINKER
+#define LINKER      "ld"
+#endif
+char    *passp = PREPROCESSOR;
+char    *pass0 = COMPILER;
+char    *passxx0 = CXXCOMPILER;
+char    *as = ASSEMBLER;
+char    *ld = LINKER;
+char    *sysroot = "", *isysroot;
+
+
+/* crt files using pcc default names */
+#ifndef CRTBEGIN_S
+#define CRTBEGIN_S  "crtbeginS.o"
+#endif
+#ifndef CRTEND_S
+#define CRTEND_S    "crtendS.o"
+#endif
+#ifndef CRTBEGIN_T
+#define CRTBEGIN_T  "crtbeginT.o"
+#endif
+#ifndef CRTEND_T
+#define CRTEND_T    "crtendT.o"
+#endif
+#ifndef CRTBEGIN
+#define CRTBEGIN    "crtbegin.o"
+#endif
+#ifndef CRTEND
+#define CRTEND      "crtend.o"
+#endif
+#ifndef CRTI
+#define CRTI        "crti.o"
+#endif
+#ifndef CRTN
+#define CRTN        "crtn.o"
+#endif
+#ifndef CRT0
+#define CRT0        "crt0.o"
+#endif
+#ifndef GCRT0
+#define GCRT0       "gcrt0.o"
+#endif
+
+/* preprocessor stuff */
+#ifndef STDINC
+#define STDINC      "/include/"
+#endif
+#ifdef MULTIARCH_PATH
+#define STDINC_MA   STDINC MULTIARCH_PATH "/"
+#endif
+
+
+char *cppadd[] = CPPADD;
+char *cppmdadd[] = CPPMDADD;
+
+/* Default libraries and search paths */
+#ifndef PCCLIBDIR   /* set by autoconf */
+#define PCCLIBDIR   NULL
+#endif
+#ifndef LIBDIR
+#define LIBDIR      "/lib/"
+#endif
+#ifndef DEFLIBDIRS  /* default library search paths */
+#ifdef MULTIARCH_PATH
+#define DEFLIBDIRS  { LIBDIR, LIBDIR MULTIARCH_PATH "/", 0 }
+#else
+#define DEFLIBDIRS  { LIBDIR, 0 }
+#endif
+#endif
+#ifndef DEFLIBS     /* default libraries included */
+#define DEFLIBS     { "-lc", 0 }
+#endif
+#ifndef DEFPROFLIBS /* default profiling libraries */
+#define DEFPROFLIBS { "-lc", 0 }
+#endif
+#ifndef DEFCXXLIBS  /* default c++ libraries */
+#define DEFCXXLIBS  { 0 }
+#endif
+#ifndef STARTLABEL
+#define STARTLABEL "__start"
+#endif
+#ifndef DYNLINKARG
+#define DYNLINKARG  "-dynamic-linker"
+#endif
+#ifndef DYNLINKLIB
+#define DYNLINKLIB  NULL
+#endif
+
+char *dynlinkarg = DYNLINKARG;
+char *dynlinklib = DYNLINKLIB;
+char *pcclibdir = PCCLIBDIR;
+char *deflibdirs[] = DEFLIBDIRS;
+char *deflibs[] = DEFLIBS;
+char *defproflibs[] = DEFPROFLIBS;
+char *defcxxlibs[] = DEFCXXLIBS;
+
+char    *outfile, *MFfile, *fname;
+static char **lav;
+static int lac;
+static char *find_file(const char *file, struct strlist *path, int mode);
+static int preprocess_input(char *input, char *output, int dodep);
+static int compile_input(char *input, char *output);
+static int assemble_input(char *input, char *output);
+static int run_linker(void);
+static int strlist_exec(struct strlist *l);
+
+char *cat(const char *, const char *);
+char *setsuf(char *, char);
+int cxxsuf(char *);
+int getsuf(char *);
+char *getsufp(char *s);
+int main(int, char *[]);
+void errorx(int, char *, ...);
+int cunlink(char *);
+void exandrm(char *);
+void dexit(int);
+void idexit(int);
+char *gettmp(void);
+void oerror(char *);
+char *argnxt(char *, char *);
+char *nxtopt(char *o);
+void setup_cpp_flags(void);
+void setup_ccom_flags(void);
+void setup_as_flags(void);
+void setup_ld_flags(void);
+static void expand_sysroot(void);
+#ifdef  _WIN32
+char *win32pathsubst(char *);
+char *win32commandline(struct strlist *l);
+#endif
+int sspflag;
+int freestanding;
+int Sflag;
+int cflag;
+int gflag;
+int rflag;
+int vflag;
+int noexec; /* -### */
+int tflag;
+int Eflag;
+int Oflag;
+int kflag;  /* generate PIC/pic code */
+#define F_PIC   1
+#define F_pic   2
+int Mflag, needM, MDflag, MMDflag;  /* dependencies only */
+int pgflag;
+int Xflag;
+int nostartfiles, Bstatic, shared;
+int nostdinc, nostdlib;
+int pthreads;
+int xgnu89, xgnu99;
+int     ascpp;
+#ifdef CHAR_UNSIGNED
+int xuchar = 1;
+#else
+int xuchar = 0;
+#endif
+int cxxflag;
+int cppflag;
+int printprogname, printfilename;
+
+#ifdef SOFTFLOAT
+int softfloat = 1;
+#else
+int softfloat = 0;
+#endif
+
+#ifdef TARGET_BIG_ENDIAN
+int bigendian = 1;
+#else
+int bigendian = 0;
+#endif
+
+#ifdef mach_amd64
+int amd64_i386;
+#endif
+
+#define match(a,b)  (strcmp(a,b) == 0)
+
+/* handle gcc warning emulations */
+struct Wflags {
+    char *name;
+    int flags;
+#define INWALL      1
+} Wflags[] = {
+    { "truncate", 0 },
+    { "strict-prototypes", 0 },
+    { "missing-prototypes", 0 },
+    { "implicit-int", INWALL },
+    { "implicit-function-declaration", INWALL },
+    { "shadow", 0 },
+    { "pointer-sign", INWALL },
+    { "sign-compare", 0 },
+    { "unknown-pragmas", INWALL },
+    { "unreachable-code", 0 },
+    { "deprecated-declarations", 0 },
+    { "attributes", 0 },
+    { NULL, 0 },
+};
+
+#ifndef USHORT
+/* copied from mip/manifest.h */
+#define USHORT      5
+#define INT     6
+#define UNSIGNED    7
+#endif
+
+/*
+ * Wide char defines.
+ */
+#if WCHAR_TYPE == USHORT
+#define WCT "short unsigned int"
+#define WCM "65535U"
+#if WCHAR_SIZE != 2
+#error WCHAR_TYPE vs. WCHAR_SIZE mismatch
+#endif
+#elif WCHAR_TYPE == INT
+#define WCT "int"
+#define WCM "2147483647"
+#if WCHAR_SIZE != 4
+#error WCHAR_TYPE vs. WCHAR_SIZE mismatch
+#endif
+#elif WCHAR_TYPE == UNSIGNED
+#define WCT "unsigned int"
+#define WCM "4294967295U"
+#if WCHAR_SIZE != 4
+#error WCHAR_TYPE vs. WCHAR_SIZE mismatch
+#endif
+#else
+#error WCHAR_TYPE not defined or invalid
+#endif
+
+#ifdef GCC_COMPAT
+#ifndef REGISTER_PREFIX
+#define REGISTER_PREFIX ""
+#endif
+#ifndef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+#endif
+#endif
+
+#ifndef PCC_WINT_TYPE
+#define PCC_WINT_TYPE "unsigned int"
+#endif
+
+#ifndef PCC_SIZE_TYPE
+#define PCC_SIZE_TYPE "unsigned long"
+#endif
+
+#ifndef PCC_PTRDIFF_TYPE
+#define PCC_PTRDIFF_TYPE "long int"
+#endif
+
+
+struct strlist preprocessor_flags;
+struct strlist depflags;
+struct strlist incdirs;
+struct strlist user_sysincdirs;
+struct strlist includes;
+struct strlist sysincdirs;
+struct strlist dirafterdirs;
+struct strlist crtdirs;
+struct strlist libdirs;
+struct strlist progdirs;
+struct strlist early_linker_flags;
+struct strlist middle_linker_flags;
+struct strlist late_linker_flags;
+struct strlist inputs;
+struct strlist assembler_flags;
+struct strlist temp_outputs;
+struct strlist compiler_flags;
+
+int
+main(int argc, char *argv[])
+{
+    struct Wflags *Wf;
+    struct string *s;
+    char *t, *u, *argp;
+    char *msuffix;
+    int ninput, j;
+
+    lav = argv;
+    lac = argc;
+    ninput = 0;
+
+    strlist_init(&crtdirs);
+    strlist_init(&libdirs);
+    strlist_init(&progdirs);
+    strlist_init(&preprocessor_flags);
+    strlist_init(&incdirs);
+    strlist_init(&user_sysincdirs);
+    strlist_init(&includes);
+    strlist_init(&sysincdirs);
+    strlist_init(&dirafterdirs);
+    strlist_init(&depflags);
+    strlist_init(&early_linker_flags);
+    strlist_init(&middle_linker_flags);
+    strlist_init(&late_linker_flags);
+    strlist_init(&inputs);
+    strlist_init(&assembler_flags);
+    strlist_init(&temp_outputs);
+    strlist_init(&compiler_flags);
+
+    if ((t = strrchr(argv[0], '/')))
+        t++;
+    else
+        t = argv[0];
+
+    if (match(t, "p++")) {
+        cxxflag = 1;
+    } else if (match(t, "cpp") || match(t, CPPROGNAME)) {
+        Eflag = cppflag = 1;
+    }
+
+#ifdef PCC_EARLY_SETUP
+    PCC_EARLY_SETUP
+#endif
+
+#ifdef _WIN32
+    /* have to prefix path early.  -B may override */
+    incdir = win32pathsubst(incdir);
+    altincdir = win32pathsubst(altincdir);
+    libdir = win32pathsubst(libdir);
+#ifdef PCCINCDIR
+    pccincdir = win32pathsubst(pccincdir);
+    pxxincdir = win32pathsubst(pxxincdir);
+#endif
+#ifdef PCCLIBDIR
+    pcclibdir = win32pathsubst(pcclibdir);
+#endif
+    passp = win32pathsubst(passp);
+    pass0 = win32pathsubst(pass0);
+#ifdef STARTFILES
+    for (i = 0; startfiles[i] != NULL; i++)
+        startfiles[i] = win32pathsubst(startfiles[i]);
+    for (i = 0; endfiles[i] != NULL; i++)
+        endfiles[i] = win32pathsubst(endfiles[i]);
+#endif
+#ifdef STARTFILES_T
+    for (i = 0; startfiles_T[i] != NULL; i++)
+        startfiles_T[i] = win32pathsubst(startfiles_T[i]);
+    for (i = 0; endfiles_T[i] != NULL; i++)
+        endfiles_T[i] = win32pathsubst(endfiles_T[i]);
+#endif
+#ifdef STARTFILES_S
+    for (i = 0; startfiles_S[i] != NULL; i++)
+        startfiles_S[i] = win32pathsubst(startfiles_S[i]);
+    for (i = 0; endfiles_S[i] != NULL; i++)
+        endfiles_S[i] = win32pathsubst(endfiles_S[i]);
+#endif
+#endif
+
+    while (--lac) {
+        ++lav;
+        argp = *lav;
+
+#ifdef PCC_EARLY_ARG_CHECK
+        PCC_EARLY_ARG_CHECK
+#endif
+
+        if (*argp != '-' || match(argp, "-")) {
+            /* Check for duplicate .o files. */
+            if (getsuf(argp) == 'o') {
+                j = 0;
+                STRLIST_FOREACH(s, &inputs)
+                    if (match(argp, s->value))
+                        j++;
+                if (j)
+                    continue; /* skip it */
+            }
+            strlist_append(&inputs, argp);
+            ninput++;
+            continue;
+        }
+
+        switch (argp[1]) {
+        default:
+            oerror(argp);
+            break;
+
+        case '#':
+            if (match(argp, "-###")) {
+                printf("%s\n", VERSSTR);
+                vflag++;
+                noexec++;
+            } else
+                oerror(argp);
+            break;
+
+        case '-': /* double -'s */
+            if (match(argp, "--version")) {
+                printf("%s\n", VERSSTR);
+                return 0;
+            } else if (strncmp(argp, "--sysroot=", 10) == 0) {
+                sysroot = argp + 10;
+            } else if (strncmp(argp, "--sysroot", 9) == 0) {
+                sysroot = nxtopt(argp);
+            } else if (strcmp(argp, "--param") == 0) {
+                /* NOTHING YET */;
+                (void)nxtopt(0); /* ignore arg */
+            } else
+                oerror(argp);
+            break;
+
+        case 'B': /* other search paths for binaries */
+            t = nxtopt("-B");
+            strlist_append(&crtdirs, t);
+            strlist_append(&libdirs, t);
+            strlist_append(&progdirs, t);
+            break;
+
+        case 'C':
+            if (match(argp, "-C") || match(argp, "-CC"))
+                strlist_append(&preprocessor_flags, argp);
+            else
+                oerror(argp);
+            break;
+
+        case 'c':
+            cflag++;
+            break;
+
+        case 'd': /* debug options */
+            for (t = &argp[2]; *t; t++) {
+                if (*t == 'M')
+                    strlist_append(&preprocessor_flags, "-dM");
+
+                /* ignore others */
+            }
+            break;
+
+        case 'E':
+            Eflag++;
+            break;
+
+        case 'f': /* GCC compatibility flags */
+            u = &argp[2];
+            j = 0;
+            if (strncmp(u, "no-", 3) == 0)
+                j = 1, u += 3;
+            if (match(u, "PIC") || match(u, "pic")) {
+                kflag = j ? 0 : *u == 'P' ? F_PIC : F_pic;
+            } else if (match(u, "freestanding")) {
+                freestanding = j ? 0 : 1;
+            } else if (match(u, "signed-char")) {
+                xuchar = j ? 1 : 0;
+            } else if (match(u, "unsigned-char")) {
+                xuchar = j ? 0 : 1;
+            } else if (match(u, "stack-protector") ||
+                match(u, "stack-protector-all")) {
+                sspflag = j ? 0 : 1;
+            }
+            /* silently ignore the rest */
+            break;
+
+        case 'g': /* create debug output */
+            if (argp[2] == '0')
+                gflag = 0;
+            else
+                gflag++;
+            break;
+
+
+        case 'X':
+            Xflag++;
+            break;
+
+        case 'D':
+        case 'U':
+            strlist_append(&preprocessor_flags, argp);
+            if (argp[2] != 0)
+                break;
+            strlist_append(&preprocessor_flags, nxtopt(argp));
+            break;
+
+        case 'I': /* Add include dirs */
+            strlist_append(&incdirs, nxtopt("-I"));
+            break;
+
+        case 'i':
+            if (match(argp, "-isystem")) {
+                strlist_append(&user_sysincdirs, nxtopt(0));
+            } else if (match(argp, "-include")) {
+                strlist_append(&includes, nxtopt(0));
+            } else if (match(argp, "-isysroot")) {
+                isysroot = nxtopt(0);
+            } else if (strcmp(argp, "-idirafter") == 0) {
+                strlist_append(&dirafterdirs, nxtopt(0));
+            } else
+                oerror(argp);
+            break;
+
+        case 'k': /* generate PIC code */
+            kflag = argp[2] ? argp[2] - '0' : F_pic;
+            break;
+
+        case 'l':
+        case 'L':
+            if (argp[2] == 0)
+                argp = cat(argp, nxtopt(0));
+            strlist_append(&inputs, argp);
+            break;
+
+        case 'm': /* target-dependent options */
+            if (strncmp(argp, "-march=", 6) == 0) {
+                strlist_append(&compiler_flags, argp);
+                break;
+            }
+#ifdef mach_amd64
+            /* need to call i386 ccom for this */
+            if (strcmp(argp, "-melf_i386") == 0) {
+                pass0 = LIBEXECDIR "/ccom_i386";
+                amd64_i386 = 1;
+                break;
+            }
+#endif
+#if defined(mach_arm) || defined(mach_mips)
+            if (match(argp, "-mbig-endian")) {
+                bigendian = 1;
+                strlist_append(&compiler_flags, argp);
+                break;
+            }
+            if (match(argp, "-mlittle-endian")) {
+                bigendian = 0;
+                strlist_append(&compiler_flags, argp);
+                break;
+            }
+            if (match(argp, "-msoft-float")) {
+                softfloat = 1;
+                strlist_append(&compiler_flags, argp);
+                break;
+            }
+#endif
+#if defined(mach_mips)
+            if (match(argp, "-mhard-float")) {
+                softfloat = 0;
+                strlist_append(&compiler_flags, argp);
+                break;
+            }
+#endif
+            strlist_append(&middle_linker_flags, argp);
+            if (argp[2] == 0) {
+                t = nxtopt(0);
+                strlist_append(&middle_linker_flags, t);
+            }
+            break;
+
+        case 'n': /* handle -n flags */
+            if (strcmp(argp, "-nostdinc") == 0)
+                nostdinc++;
+            else if (strcmp(argp, "-nostdlib") == 0) {
+                nostdlib++;
+                nostartfiles++;
+            } else if (strcmp(argp, "-nostartfiles") == 0)
+                nostartfiles = 1;
+            else if (strcmp(argp, "-nodefaultlibs") == 0)
+                nostdlib++;
+            else
+                oerror(argp);
+            break;
+
+        case 'p':
+            if (strcmp(argp, "-pg") == 0 ||
+                strcmp(argp, "-p") == 0)
+                pgflag++;
+            else if (strcmp(argp, "-pthread") == 0)
+                pthreads++;
+            else if (strcmp(argp, "-pipe") == 0)
+                /* NOTHING YET */;
+            else if (strcmp(argp, "-pedantic") == 0)
+                /* NOTHING YET */;
+            else if ((t = argnxt(argp, "-print-prog-name="))) {
+                fname = t;
+                printprogname = 1;
+            } else if ((t = argnxt(argp, "-print-file-name="))) {
+                fname = t;
+                printfilename = 1;
+            } else if (match(argp, "-print-libgcc-file-name")) {
+                fname = "libpcc.a";
+                printfilename = 1;
+            } else
+                oerror(argp);
+            break;
+
+        case 'R':
+            if (argp[2] == 0)
+                argp = cat(argp, nxtopt(0));
+            strlist_append(&middle_linker_flags, argp);
+            break;
+
+        case 'r':
+            rflag = 1;
+            break;
+
+        case 'T':
+            strlist_append(&inputs, argp);
+            if (argp[2] == 0 ||
+                strcmp(argp, "-Ttext") == 0 ||
+                strcmp(argp, "-Tdata") == 0 ||
+                strcmp(argp, "-Tbss") == 0)
+                strlist_append(&inputs, nxtopt(0));
+            break;
+
+        case 's':
+            if (match(argp, "-shared")) {
+                shared = 1;
+            } else if (match(argp, "-static")) {
+                Bstatic = 1;
+            } else if (match(argp, "-symbolic")) {
+                strlist_append(&middle_linker_flags,
+                    "-Bsymbolic");
+            } else if (strncmp(argp, "-std", 4) == 0) {
+                if (strcmp(&argp[5], "gnu99") == 0 ||
+                    strcmp(&argp[5], "gnu9x") == 0)
+                    xgnu99 = 1;
+                if (strcmp(&argp[5], "gnu89") == 0)
+                    xgnu89 = 1;
+            } else
+                oerror(argp);
+            break;
+
+        case 'S':
+            Sflag++;
+            cflag++;
+            break;
+
+        case 't':
+            tflag++;
+            break;
+
+        case 'o':
+            if (outfile)
+                errorx(8, "too many -o");
+            outfile = nxtopt("-o");
+            break;
+
+        case 'O':
+            if (argp[2] == '\0')
+                Oflag++;
+            else if (argp[3] == '\0' &&
+                isdigit((unsigned char)argp[2]))
+                Oflag = argp[2] - '0';
+            else if (argp[3] == '\0' && argp[2] == 's')
+                Oflag = 1;  /* optimize for space only */
+            else
+                oerror(argp);
+            break;
+
+        case 'P':
+            strlist_append(&preprocessor_flags, argp);
+            break;
+
+        case 'M':
+            needM = 1;
+            if (match(argp, "-M")) {
+                Mflag++;
+                strlist_append(&depflags, argp);
+            } else if (match(argp, "-MP")) {
+                strlist_append(&depflags, "-xMP");
+            } else if (match(argp, "-MF")) {
+                MFfile = nxtopt("-MF");
+            } else if (match(argp, "-MT") || match(argp, "-MQ")) {
+                t = cat("-xMT,", nxtopt("-MT"));
+                t[3] = argp[2];
+                strlist_append(&depflags, t);
+            } else if (match(argp, "-MD")) {
+                MDflag++;
+                needM = 0;
+                strlist_append(&depflags, "-M");
+            } else if (match(argp, "-MMD")) {
+                MMDflag++;
+                needM = 0;
+                strlist_append(&depflags, "-M");
+                strlist_append(&depflags, "-xMMD");
+            } else
+                oerror(argp);
+            break;
+
+        case 'v':
+            printf("%s\n", VERSSTR);
+            vflag++;
+            break;
+
+        case 'w': /* no warnings at all emitted */
+            strlist_append(&compiler_flags, "-w");
+            break;
+
+        case 'W': /* Ignore (most of) W-flags */
+            if ((t = argnxt(argp, "-Wl,"))) {
+                u = strtok(t, ",");
+                do {
+                    strlist_append(&inputs, u);
+                } while ((u = strtok(NULL, ",")) != NULL);
+            } else if ((t = argnxt(argp, "-Wa,"))) {
+                u = strtok(t, ",");
+                do {
+                    strlist_append(&assembler_flags, u);
+                } while ((u = strtok(NULL, ",")) != NULL);
+            } else if ((t = argnxt(argp, "-Wc,"))) {
+                u = strtok(t, ",");
+                do {
+                    strlist_append(&compiler_flags, u);
+                } while ((u = strtok(NULL, ",")) != NULL);
+            } else if ((t = argnxt(argp, "-Wp,"))) {
+                u = strtok(t, ",");
+                do {
+                    strlist_append(&preprocessor_flags, u);
+                } while ((u = strtok(NULL, ",")) != NULL);
+            } else if (strcmp(argp, "-Werror") == 0) {
+                strlist_append(&compiler_flags, "-Werror");
+                strlist_append(&preprocessor_flags, "-E");
+            } else if (strcmp(argp, "-Wall") == 0) {
+                for (Wf = Wflags; Wf->name; Wf++)
+                    if (Wf->flags & INWALL)
+                        strlist_append(&compiler_flags,
+                            cat("-W", Wf->name));
+            } else if (strcmp(argp, "-WW") == 0) {
+                for (Wf = Wflags; Wf->name; Wf++)
+                    strlist_append(&compiler_flags,
+                        cat("-W", Wf->name));
+            } else {
+                /* pass through, if supported */
+                t = &argp[2];
+                if (strncmp(t, "no-", 3) == 0)
+                    t += 3;
+                if (strncmp(t, "error=", 6) == 0)
+                    t += 6;
+                for (Wf = Wflags; Wf->name; Wf++) {
+                    if (strcmp(t, Wf->name) == 0)
+                        strlist_append(&compiler_flags,
+                            argp);
+                }
+            }
+            break;
+
+        case 'x':
+            t = nxtopt("-x");
+            if (match(t, "none"))
+                strlist_append(&inputs, ")");
+            else if (match(t, "c"))
+                strlist_append(&inputs, ")c");
+            else if (match(t, "assembler"))
+                strlist_append(&inputs, ")s");
+            else if (match(t, "assembler-with-cpp"))
+                strlist_append(&inputs, ")S");
+            else if (match(t, "c++"))
+                strlist_append(&inputs, ")c++");
+            else {
+                strlist_append(&compiler_flags, "-x");
+                strlist_append(&compiler_flags, t);
+            }
+            break;
+
+        }
+        continue;
+
+    }
+
+    /* Sanity checking */
+    if (cppflag) {
+        if (ninput == 0) {
+            strlist_append(&inputs, "-");
+            ninput++;
+        } else if (ninput > 2 || (ninput == 2 && outfile)) {
+            errorx(8, "too many files");
+        } else if (ninput == 2) {
+            outfile = STRLIST_NEXT(STRLIST_FIRST(&inputs))->value;
+            STRLIST_FIRST(&inputs)->next = NULL;
+            ninput--;
+        }
+    }
+    if (ninput == 0 && !(printprogname || printfilename))
+        errorx(8, "no input files");
+    if (outfile && (cflag || Sflag || Eflag) && ninput > 1)
+        errorx(8, "-o given with -c || -E || -S and more than one file");
+#if 0
+    if (outfile && clist[0] && strcmp(outfile, clist[0]) == 0)
+        errorx(8, "output file will be clobbered");
+#endif
+
+    if (needM && !Mflag && !MDflag && !MMDflag)
+        errorx(8, "to make dependencies needs -M");
+
+
+    if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */
+        signal(SIGINT, idexit);
+    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)    /* terminate */
+        signal(SIGTERM, idexit);
+
+    /* after arg parsing */
+    strlist_append(&progdirs, LIBEXECDIR);
+    if (pcclibdir)
+        strlist_append(&crtdirs, pcclibdir);
+    for (j = 0; deflibdirs[j]; j++) {
+        if (sysroot)
+            deflibdirs[j] = cat(sysroot, deflibdirs[j]);
+        strlist_append(&crtdirs, deflibdirs[j]);
+    }
+
+    setup_cpp_flags();
+    setup_ccom_flags();
+    setup_as_flags();
+
+    if (isysroot == NULL)
+        isysroot = sysroot;
+    expand_sysroot();
+
+    if (printprogname) {
+        printf("%s\n", find_file(fname, &progdirs, X_OK));
+        return 0;
+    } else if (printfilename) {
+        printf("%s\n", find_file(fname, &crtdirs, R_OK));
+        return 0;
+    }
+
+    msuffix = NULL;
+    STRLIST_FOREACH(s, &inputs) {
+        char *suffix;
+        char *ifile, *ofile = NULL;
+
+        ifile = s->value;
+        if (ifile[0] == ')') { /* -x source type given */
+            msuffix = ifile[1] ? &ifile[1] : NULL;
+            continue;
+        }
+        if (ifile[0] == '-' && ifile[1] == 0)
+            suffix = msuffix ? msuffix : "c";
+        else if (ifile[0] == '-')
+            suffix = "o"; /* source files cannot begin with - */
+        else if (msuffix)
+            suffix = msuffix;
+        else
+            suffix = getsufp(ifile);
+        /*
+         * C preprocessor
+         */
+        ascpp = match(suffix, "S");
+        if (ascpp || match(suffix, "c") || cxxsuf(suffix)) {
+            /* find out next output file */
+            if (Mflag || MDflag || MMDflag) {
+                char *Mofile = NULL;
+
+                if (MFfile)
+                    Mofile = MFfile;
+                else if (outfile)
+                    Mofile = setsuf(outfile, 'd');
+                else if (MDflag || MMDflag)
+                    Mofile = setsuf(ifile, 'd');
+                if (preprocess_input(ifile, Mofile, 1))
+                    exandrm(Mofile);
+            }
+            if (Mflag)
+                continue;
+            if (Eflag) {
+                /* last pass */
+                ofile = outfile;
+            } else {
+                /* to temp file */
+                strlist_append(&temp_outputs, ofile = gettmp());
+            }
+            if (preprocess_input(ifile, ofile, 0))
+                exandrm(ofile);
+            if (Eflag)
+                continue;
+            ifile = ofile;
+            suffix = match(suffix, "S") ? "s" : "i";
+        }
+
+        /*
+         * C compiler
+         */
+        if (match(suffix, "i")) {
+            /* find out next output file */
+            if (Sflag) {
+                ofile = outfile;
+                if (outfile == NULL)
+                    ofile = setsuf(s->value, 's');
+            } else
+                strlist_append(&temp_outputs, ofile = gettmp());
+            if (compile_input(ifile, ofile))
+                exandrm(ofile);
+            if (Sflag)
+                continue;
+            ifile = ofile;
+            suffix = "s";
+        }
+
+        /*
+         * Assembler
+         */
+        if (match(suffix, "s")) {
+            if (cflag) {
+                ofile = outfile;
+                if (ofile == NULL)
+                    ofile = setsuf(s->value, 'o');
+            } else {
+                strlist_append(&temp_outputs, ofile = gettmp());
+                /* strlist_append linker */
+            }
+            if (assemble_input(ifile, ofile))
+                exandrm(ofile);
+            ifile = ofile;
+        }
+
+        if (ninput > 1 && !Eflag && ifile == ofile && ifile[0] != '-')
+            printf("%s:\n", ifile);
+
+        strlist_append(&middle_linker_flags, ifile);
+    }
+
+    if (cflag || Eflag || Mflag)
+        dexit(0);
+
+    /*
+     * Linker
+     */
+    setup_ld_flags();
+    if (run_linker())
+        exandrm(0);
+
+#ifdef notdef
+    strlist_free(&crtdirs);
+    strlist_free(&libdirs);
+    strlist_free(&progdirs);
+    strlist_free(&incdirs);
+    strlist_free(&preprocessor_flags);
+    strlist_free(&user_sysincdirs);
+    strlist_free(&includes);
+    strlist_free(&sysincdirs);
+    strlist_free(&dirafterdirs);
+    strlist_free(&depflags);
+    strlist_free(&early_linker_flags);
+    strlist_free(&middle_linker_flags);
+    strlist_free(&late_linker_flags);
+    strlist_free(&inputs);
+    strlist_free(&assembler_flags);
+    strlist_free(&temp_outputs);
+    strlist_free(&compiler_flags);
+#endif
+    dexit(0);
+    return 0;
+}
+
+/*
+ * exit and cleanup after interrupt.
+ */
+void
+idexit(int arg)
+{
+    dexit(100);
+}
+
+/*
+ * exit and cleanup.
+ */
+void
+dexit(int eval)
+{
+    struct string *s;
+
+    if (!Xflag) {
+        STRLIST_FOREACH(s, &temp_outputs)
+            cunlink(s->value);
+    }
+    exit(eval);
+}
+
+/*
+ * Called when something failed.
+ */
+void
+exandrm(char *s)
+{
+    if (s && *s)
+        strlist_append(&temp_outputs, s);
+    dexit(1);
+}
+
+/*
+ * complain and exit.
+ */
+void
+errorx(int eval, char *s, ...)
+{
+    va_list ap;
+
+    va_start(ap, s);
+    fputs("error: ", stderr);
+    vfprintf(stderr, s, ap);
+    putc('\n', stderr);
+    va_end(ap);
+    dexit(eval);
+}
+
+static char *
+find_file(const char *file, struct strlist *path, int mode)
+{
+    struct string *s;
+    char *f;
+    size_t lf, lp;
+    int need_sep;
+
+    lf = strlen(file);
+    STRLIST_FOREACH(s, path) {
+        lp = strlen(s->value);
+        need_sep = (lp && s->value[lp - 1] != '/') ? 1 : 0;
+        f = xmalloc(lp + lf + need_sep + 1);
+        memcpy(f, s->value, lp);
+        if (need_sep)
+            f[lp] = '/';
+        memcpy(f + lp + need_sep, file, lf + 1);
+        if (access(f, mode) == 0)
+            return f;
+        free(f);
+    }
+    return xstrdup(file);
+}
+
+static int
+compile_input(char *input, char *output)
+{
+    struct strlist args;
+    int retval;
+
+    strlist_init(&args);
+    strlist_append_list(&args, &compiler_flags);
+    strlist_append(&args, input);
+    strlist_append(&args, output);
+    strlist_prepend(&args,
+        find_file(cxxflag ? passxx0 : pass0, &progdirs, X_OK));
+    retval = strlist_exec(&args);
+    strlist_free(&args);
+    return retval;
+}
+
+static int
+assemble_input(char *input, char *output)
+{
+    struct strlist args;
+    int retval;
+
+    strlist_init(&args);
+#ifdef PCC_EARLY_AS_ARGS
+    PCC_EARLY_AS_ARGS
+#endif
+    strlist_append_list(&args, &assembler_flags);
+    strlist_append(&args, input);
+    strlist_append(&args, "-o");
+    strlist_append(&args, output);
+    strlist_prepend(&args,
+        find_file(as, &progdirs, X_OK));
+#ifdef PCC_LATE_AS_ARGS
+    PCC_LATE_AS_ARGS
+#endif
+    retval = strlist_exec(&args);
+    strlist_free(&args);
+    return retval;
+}
+
+static int
+preprocess_input(char *input, char *output, int dodep)
+{
+    struct strlist args;
+    struct string *s;
+    int retval;
+
+    strlist_init(&args);
+    strlist_append_list(&args, &preprocessor_flags);
+    if (ascpp) {
+        strlist_append(&args, "-A");
+        strlist_append(&args, "-D__ASSEMBLER__");
+    }
+    STRLIST_FOREACH(s, &includes) {
+        strlist_append(&args, "-i");
+        strlist_append(&args, s->value);
+    }
+    STRLIST_FOREACH(s, &incdirs) {
+        strlist_append(&args, "-I");
+        strlist_append(&args, s->value);
+    }
+    STRLIST_FOREACH(s, &user_sysincdirs) {
+        strlist_append(&args, "-S");
+        strlist_append(&args, s->value);
+    }
+    if (!nostdinc) {
+        STRLIST_FOREACH(s, &sysincdirs) {
+            strlist_append(&args, "-S");
+            strlist_append(&args, s->value);
+        }
+    }
+    STRLIST_FOREACH(s, &dirafterdirs) {
+        strlist_append(&args, "-S");
+        strlist_append(&args, s->value);
+    }
+    if (dodep)
+        strlist_append_list(&args, &depflags);
+    strlist_append(&args, input);
+    if (output)
+        strlist_append(&args, output);
+
+    strlist_prepend(&args, find_file(passp, &progdirs, X_OK));
+    retval = strlist_exec(&args);
+    strlist_free(&args);
+    return retval;
+}
+
+static int
+run_linker(void)
+{
+    struct strlist linker_flags;
+    int retval;
+
+    if (outfile) {
+        strlist_prepend(&early_linker_flags, outfile);
+        strlist_prepend(&early_linker_flags, "-o");
+    }
+    strlist_init(&linker_flags);
+    strlist_append_list(&linker_flags, &early_linker_flags);
+    strlist_append_list(&linker_flags, &middle_linker_flags);
+    strlist_append_list(&linker_flags, &late_linker_flags);
+    strlist_prepend(&linker_flags, find_file(ld, &progdirs, X_OK));
+
+    retval = strlist_exec(&linker_flags);
+
+    strlist_free(&linker_flags);
+    return retval;
+}
+
+static char *cxxt[] = { "cc", "cp", "cxx", "cpp", "CPP", "c++", "C" };
+int
+cxxsuf(char *s)
+{
+    unsigned i;
+    for (i = 0; i < sizeof(cxxt)/sizeof(cxxt[0]); i++)
+        if (strcmp(s, cxxt[i]) == 0)
+            return 1;
+    return 0;
+}
+
+char *
+getsufp(char *s)
+{
+    register char *p;
+
+    if ((p = strrchr(s, '.')) && p[1] != '\0')
+        return &p[1];
+    return "";
+}
+
+int
+getsuf(char *s)
+{
+    register char *p;
+
+    if ((p = strrchr(s, '.')) && p[1] != '\0' && p[2] == '\0')
+        return p[1];
+    return(0);
+}
+
+/*
+ * Get basename of string s, copy it and change its suffix to ch.
+ */
+char *
+setsuf(char *s, char ch)
+{
+    char *e, *p, *rp;
+
+    e = NULL;
+    for (p = s; *p; p++) {
+        if (*p == '/')
+            s = p + 1;
+        if (*p == '.')
+            e = p;
+    }
+    if (s > e)
+        e = p;
+
+    rp = p = xmalloc(e - s + 3);
+    while (s < e)
+        *p++ = *s++;
+
+    *p++ = '.';
+    *p++ = ch;
+    *p = '\0';
+    return rp;
+}
+
+#ifdef _WIN32
+
+static int
+strlist_exec(struct strlist *l)
+{
+    char *cmd;
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    DWORD exitCode;
+    BOOL ok;
+
+    cmd = win32commandline(l);
+    if (vflag)
+        printf("%s\n", cmd);
+    if (noexec)
+        return 0;
+
+    ZeroMemory(&si, sizeof(STARTUPINFO));
+    si.cb = sizeof(STARTUPINFO);
+    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+
+    ok = CreateProcess(NULL,  // the executable program
+        cmd,   // the command line arguments
+        NULL,       // ignored
+        NULL,       // ignored
+        TRUE,       // inherit handles
+        HIGH_PRIORITY_CLASS,
+        NULL,       // ignored
+        NULL,       // ignored
+        &si,
+        &pi);
+
+    if (!ok)
+        errorx(100, "Can't find %s\n", STRLIST_FIRST(l)->value);
+
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    GetExitCodeProcess(pi.hProcess, &exitCode);
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
+
+    return (exitCode != 0);
+}
+
+#else
+
+static int
+strlist_exec(struct strlist *l)
+{
+    sig_atomic_t exit_now = 0;
+    sig_atomic_t child;
+    char **argv;
+    size_t argc;
+    int result;
+
+    strlist_make_array(l, &argv, &argc);
+    if (vflag) {
+        printf("Calling ");
+        strlist_print(l, stdout, noexec);
+        printf("\n");
+    }
+    if (noexec)
+        return 0;
+
+    switch ((child = fork())) {
+    case 0:
+        execvp(argv[0], argv);
+        result = write(STDERR_FILENO, "Exec of ", 8);
+        result = write(STDERR_FILENO, argv[0], strlen(argv[0]));
+        result = write(STDERR_FILENO, " failed\n", 8);
+        (void)result;
+        _exit(127);
+    case -1:
+        errorx(1, "fork failed");
+    default:
+        while (waitpid(child, &result, 0) == -1 && errno == EINTR)
+            /* nothing */(void)0;
+        result = WEXITSTATUS(result);
+        if (result)
+            errorx(1, "%s terminated with status %d", argv[0], result);
+        while (argc-- > 0)
+            free(argv[argc]);
+        free(argv);
+        break;
+    }
+    return exit_now;
+}
+
+#endif
+
+/*
+ * Catenate two (optional) strings together
+ */
+char *
+cat(const char *a, const char *b)
+{
+    size_t len;
+    char *rv;
+
+    len = (a ? strlen(a) : 0) + (b ? strlen(b) : 0) + 1;
+    rv = xmalloc(len);
+    snprintf(rv, len, "%s%s", (a ? a : ""), (b ? b : ""));
+    return rv;
+}
+
+int
+cunlink(char *f)
+{
+    if (f==0 || Xflag)
+        return(0);
+    return (unlink(f));
+}
+
+#ifdef _WIN32
+char *
+gettmp(void)
+{
+    DWORD pathSize;
+    char pathBuffer[MAX_PATH + 1];
+    char tempFilename[MAX_PATH];
+    UINT uniqueNum;
+
+    pathSize = GetTempPath(sizeof(pathBuffer), pathBuffer);
+    if (pathSize == 0 || pathSize > sizeof(pathBuffer))
+        pathBuffer[0] = '\0';
+    uniqueNum = GetTempFileName(pathBuffer, "ctm", 0, tempFilename);
+    if (uniqueNum == 0)
+        errorx(8, "GetTempFileName failed: path \"%s\"", pathBuffer);
+
+    return xstrdup(tempFilename);
+}
+
+#else
+
+char *
+gettmp(void)
+{
+    char *sfn = xstrdup("/tmp/ctm.XXXXXX");
+    int fd = -1;
+
+    if ((fd = mkstemp(sfn)) == -1)
+        errorx(8, "%s: %s\n", sfn, strerror(errno));
+    close(fd);
+    return sfn;
+}
+#endif
+
+static void
+expand_sysroot(void)
+{
+    struct string *s;
+    struct strlist *lists[] = { &crtdirs, &sysincdirs, &incdirs,
+        &user_sysincdirs, &libdirs, &progdirs, &dirafterdirs, NULL };
+    const char *sysroots[] = { sysroot, isysroot, isysroot, isysroot,
+        sysroot, sysroot, isysroot, NULL };
+    size_t i, sysroot_len, value_len;
+    char *path;
+
+    assert(sizeof(lists) / sizeof(lists[0]) ==
+           sizeof(sysroots) / sizeof(sysroots[0]));
+
+    for (i = 0; lists[i] != NULL; ++i) {
+        STRLIST_FOREACH(s, lists[i]) {
+            if (s->value[0] != '=')
+                continue;
+            sysroot_len = strlen(sysroots[i]);
+            /* Skipped '=' compensates additional space for '\0' */
+            value_len = strlen(s->value);
+            path = xmalloc(sysroot_len + value_len);
+            memcpy(path, sysroots[i], sysroot_len);
+            memcpy(path + sysroot_len, s->value + 1, value_len);
+            free(s->value);
+            s->value = path;
+        }
+    }
+}
+
+void
+oerror(char *s)
+{
+    errorx(8, "unknown option '%s'", s);
+}
+
+/*
+ * See if m matches the beginning of string str, if it does return the
+ * remaining of str, otherwise NULL.
+ */
+char *
+argnxt(char *str, char *m)
+{
+    if (strncmp(str, m, strlen(m)))
+        return NULL; /* No match */
+    return str + strlen(m);
+}
+
+/*
+ * Return next argument to option, or complain.
+ */
+char *
+nxtopt(char *o)
+{
+    int l;
+
+    if (o != NULL) {
+        l = strlen(o);
+        if (lav[0][l] != 0)
+            return &lav[0][l];
+    }
+    if (lac == 1)
+        errorx(8, "missing argument to '%s'", o);
+    lav++;
+    lac--;
+    return lav[0];
+}
+
+struct flgcheck {
+    int *flag;
+    int set;
+    char *def;
+} cppflgcheck[] = {
+    { &vflag, 1, "-v" },
+    { &freestanding, 1, "-D__STDC_HOSTED__=0" },
+    { &freestanding, 0, "-D__STDC_HOSTED__=1" },
+    { &cxxflag, 1, "-D__cplusplus" },
+    { &xuchar, 1, "-D__CHAR_UNSIGNED__" },
+    { &sspflag, 1, "-D__SSP__" },
+    { &pthreads, 1, "-D_PTHREADS" },
+    { &Oflag, 1, "-D__OPTIMIZE__" },
+    { &tflag, 1, "-t" },
+    { &kflag, 1, "-D__PIC__" },
+    { 0 },
+};
+
+static void
+cksetflags(struct flgcheck *fs, struct strlist *sl, int which)
+{
+    void (*fn)(struct strlist *, const char *);
+
+    fn = which == 'p' ? strlist_prepend : strlist_append;
+    for (; fs->flag; fs++) {
+        if (fs->set && *fs->flag)
+            fn(sl, fs->def);
+        if (!fs->set && !*fs->flag)
+            fn(sl, fs->def);
+    }
+}
+
+#ifndef TARGET_LE
+#define TARGET_LE       1
+#define TARGET_BE       2
+#define TARGET_PDP      3
+#define TARGET_ANY      4
+#endif
+
+static char *defflags[] = {
+    "-D__PCC__=" MKS(PCC_MAJOR),
+    "-D__PCC_MINOR__=" MKS(PCC_MINOR),
+    "-D__PCC_MINORMINOR__=" MKS(PCC_MINORMINOR),
+    "-D__VERSION__=" MKS(VERSSTR),
+    "-D__SCHAR_MAX__=" MKS(MAX_CHAR),
+    "-D__SHRT_MAX__=" MKS(MAX_SHORT),
+    "-D__INT_MAX__=" MKS(MAX_INT),
+    "-D__LONG_MAX__=" MKS(MAX_LONG),
+    "-D__LONG_LONG_MAX__=" MKS(MAX_LONGLONG),
+
+    "-D__STDC_ISO_10646__=200009L",
+    "-D__WCHAR_TYPE__=" WCT,
+    "-D__SIZEOF_WCHAR_T__=" MKS(WCHAR_SIZE),
+    "-D__WCHAR_MAX__=" WCM,
+    "-D__WINT_TYPE__=" PCC_WINT_TYPE,
+    "-D__SIZE_TYPE__=" PCC_SIZE_TYPE,
+    "-D__PTRDIFF_TYPE__=" PCC_PTRDIFF_TYPE,
+    "-D__SIZEOF_WINT_T__=4",
+    "-D__ORDER_LITTLE_ENDIAN__=1234",
+    "-D__ORDER_BIG_ENDIAN__=4321",
+    "-D__ORDER_PDP_ENDIAN__=3412",
+/*
+ * These should probably be changeable during runtime...
+ */
+#if TARGET_ENDIAN == TARGET_BE
+    "-D__FLOAT_WORD_ORDER__=__ORDER_BIG_ENDIAN__",
+    "-D__BYTE_ORDER__=__ORDER_BIG_ENDIAN__",
+#elif TARGET_ENDIAN == TARGET_PDP
+    "-D__FLOAT_WORD_ORDER__=__ORDER_PDP_ENDIAN__",
+    "-D__BYTE_ORDER__=__ORDER_PDP_ENDIAN__",
+#elif TARGET_ENDIAN == TARGET_LE
+    "-D__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__",
+    "-D__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__",
+#else
+#error Unknown endian...
+#endif
+};
+
+static char *gcppflags[] = {
+#ifndef os_win32
+#ifdef GCC_COMPAT
+    "-D__GNUC__=4",
+    "-D__GNUC_MINOR__=3",
+    "-D__GNUC_PATCHLEVEL__=1",
+    "-D__REGISTER_PREFIX__=" REGISTER_PREFIX,
+    "-D__USER_LABEL_PREFIX__=" USER_LABEL_PREFIX,
+#if SZLONG == 64
+    "-D__SIZEOF_LONG__=8",
+#elif SZLONG == 32
+    "-D__SIZEOF_LONG__=4",
+#endif
+#if SZPOINT(CHAR) == 64
+    "-D__SIZEOF_POINTER__=8",
+#elif SZPOINT(CHAR) == 32
+    "-D__SIZEOF_POINTER__=4",
+#endif
+#endif
+#endif
+    NULL
+};
+
+/* These should _not_ be defined here */
+static char *fpflags[] = {
+#ifdef TARGET_FLT_EVAL_METHOD
+    "-D__FLT_EVAL_METHOD__=" MKS(TARGET_FLT_EVAL_METHOD),
+#endif
+#if defined(os_darwin) || defined(os_netbsd) || defined(os_minix)
+    "-D__FLT_RADIX__=2",
+#if defined(mach_vax)
+    "-D__FLT_DIG__=6",
+    "-D__FLT_EPSILON__=1.19209290e-07F",
+    "-D__FLT_MANT_DIG__=24",
+    "-D__FLT_MAX_10_EXP__=38",
+    "-D__FLT_MAX_EXP__=127",
+    "-D__FLT_MAX__=1.70141173e+38F",
+    "-D__FLT_MIN_10_EXP__=(-38)",
+    "-D__FLT_MIN_EXP__=(-127)",
+    "-D__FLT_MIN__=2.93873588e-39F",
+    "-D__DBL_DIG__=16",
+    "-D__DBL_EPSILON__=2.77555756156289135e-17",
+    "-D__DBL_MANT_DIG__=56",
+    "-D__DBL_MAX_10_EXP__=38",
+    "-D__DBL_MAX_EXP__=127",
+    "-D__DBL_MAX__=1.701411834604692294e+38",
+    "-D__DBL_MIN_10_EXP__=(-38)",
+    "-D__DBL_MIN_EXP__=(-127)",
+    "-D__DBL_MIN__=2.938735877055718770e-39",
+#else
+    "-D__FLT_DIG__=6",
+    "-D__FLT_EPSILON__=1.19209290e-07F",
+    "-D__FLT_MANT_DIG__=24",
+    "-D__FLT_MAX_10_EXP__=38",
+    "-D__FLT_MAX_EXP__=128",
+    "-D__FLT_MAX__=3.40282347e+38F",
+    "-D__FLT_MIN_10_EXP__=(-37)",
+    "-D__FLT_MIN_EXP__=(-125)",
+    "-D__FLT_MIN__=1.17549435e-38F",
+    "-D__DBL_DIG__=15",
+    "-D__DBL_EPSILON__=2.2204460492503131e-16",
+    "-D__DBL_MANT_DIG__=53",
+    "-D__DBL_MAX_10_EXP__=308",
+    "-D__DBL_MAX_EXP__=1024",
+    "-D__DBL_MAX__=1.7976931348623157e+308",
+    "-D__DBL_MIN_10_EXP__=(-307)",
+    "-D__DBL_MIN_EXP__=(-1021)",
+    "-D__DBL_MIN__=2.2250738585072014e-308",
+#endif
+#if defined(mach_i386) || defined(mach_amd64)
+    "-D__LDBL_DIG__=18",
+    "-D__LDBL_EPSILON__=1.08420217248550443401e-19L",
+    "-D__LDBL_MANT_DIG__=64",
+    "-D__LDBL_MAX_10_EXP__=4932",
+    "-D__LDBL_MAX_EXP__=16384",
+    "-D__LDBL_MAX__=1.18973149535723176502e+4932L",
+    "-D__LDBL_MIN_10_EXP__=(-4931)",
+    "-D__LDBL_MIN_EXP__=(-16381)",
+    "-D__LDBL_MIN__=3.36210314311209350626e-4932L",
+#elif defined(mach_vax)
+    "-D__LDBL_DIG__=16",
+    "-D__LDBL_EPSILON__=2.77555756156289135e-17",
+    "-D__LDBL_MANT_DIG__=56",
+    "-D__LDBL_MAX_10_EXP__=38",
+    "-D__LDBL_MAX_EXP__=127",
+    "-D__LDBL_MAX__=1.701411834604692294e+38",
+    "-D__LDBL_MIN_10_EXP__=(-38)",
+    "-D__LDBL_MIN_EXP__=(-127)",
+    "-D__LDBL_MIN__=2.938735877055718770e-39",
+#else
+    "-D__LDBL_DIG__=15",
+    "-D__LDBL_EPSILON__=2.2204460492503131e-16",
+    "-D__LDBL_MANT_DIG__=53",
+    "-D__LDBL_MAX_10_EXP__=308",
+    "-D__LDBL_MAX_EXP__=1024",
+    "-D__LDBL_MAX__=1.7976931348623157e+308",
+    "-D__LDBL_MIN_10_EXP__=(-307)",
+    "-D__LDBL_MIN_EXP__=(-1021)",
+    "-D__LDBL_MIN__=2.2250738585072014e-308",
+#endif
+#endif
+    NULL
+};
+
+/*
+ * Configure the standard cpp flags.
+ */
+void
+setup_cpp_flags(void)
+{
+    int i;
+
+    /* a bunch of misc defines */
+    for (i = 0; i < (int)sizeof(defflags)/(int)sizeof(char *); i++)
+        strlist_prepend(&preprocessor_flags, defflags[i]);
+
+    for (i = 0; gcppflags[i]; i++)
+        strlist_prepend(&preprocessor_flags, gcppflags[i]);
+    strlist_prepend(&preprocessor_flags, xgnu89 ?
+        "-D__GNUC_GNU_INLINE__" : "-D__GNUC_STDC_INLINE__");
+
+    cksetflags(cppflgcheck, &preprocessor_flags, 'p');
+
+    for (i = 0; fpflags[i]; i++)
+        strlist_prepend(&preprocessor_flags, fpflags[i]);
+
+    for (i = 0; cppadd[i]; i++)
+        strlist_prepend(&preprocessor_flags, cppadd[i]);
+    for (i = 0; cppmdadd[i]; i++)
+        strlist_prepend(&preprocessor_flags, cppmdadd[i]);
+
+    /* Include dirs */
+    strlist_append(&sysincdirs, "=" INCLUDEDIR "pcc/");
+#ifdef STDINC_MA
+    strlist_append(&sysincdirs, "=" STDINC_MA);
+#endif
+    strlist_append(&sysincdirs, "=" STDINC);
+#ifdef PCCINCDIR
+    if (cxxflag)
+        strlist_append(&sysincdirs, "=" PCCINCDIR "/c++");
+    strlist_append(&sysincdirs, "=" PCCINCDIR);
+#endif
+}
+
+struct flgcheck ccomflgcheck[] = {
+    { &Oflag, 1, "-xtemps" },
+    { &Oflag, 1, "-xdeljumps" },
+    { &Oflag, 1, "-xinline" },
+    { &Oflag, 1, "-xdce" },
+#ifdef notyet
+    { &Oflag, 1, "-xssa" },
+#endif
+    { &freestanding, 1, "-ffreestanding" },
+    { &pgflag, 1, "-p" },
+    { &gflag, 1, "-g" },
+    { &xgnu89, 1, "-xgnu89" },
+    { &xgnu99, 1, "-xgnu99" },
+    { &xuchar, 1, "-xuchar" },
+#if !defined(os_sunos) && !defined(mach_i386)
+    { &vflag, 1, "-v" },
+#endif
+#ifdef os_darwin
+    { &Bstatic, 0, "-k" },
+#elif defined(os_sunos) && defined(mach_i386)
+    { &kflag, 1, "-K" },
+    { &kflag, 1, "pic" },
+#else
+    { &kflag, 1, "-k" },
+#endif
+    { &sspflag, 1, "-fstack-protector" },
+    { 0 }
+};
+
+void
+setup_ccom_flags(void)
+{
+
+    cksetflags(ccomflgcheck, &compiler_flags, 'a');
+}
+
+static int one = 1;
+
+struct flgcheck asflgcheck[] = {
+#if defined(USE_YASM)
+    { &one, 1, "-p" },
+    { &one, 1, "gnu" },
+    { &one, 1, "-f" },
+#if defined(os_win32)
+    { &one, 1, "win32" },
+#elif defined(os_darwin)
+    { &one, 1, "macho" },
+#else
+    { &one, 1, "elf" },
+#endif
+#endif
+#if defined(os_sunos) && defined(mach_sparc64)
+    { &one, 1, "-m64" },
+#endif
+#if defined(os_darwin)
+    { &Bstatic, 1, "-static" },
+#endif
+#if !defined(USE_YASM)
+    { &vflag, 1, "-v" },
+#endif
+    { &kflag, 1, "-k" },
+#ifdef os_darwin
+    { &one, 1, "-arch" },
+#if mach_amd64
+    { &amd64_i386, 1, "i386" },
+    { &amd64_i386, 0, "x86_64" },
+#else
+    { &one, 1, "i386" },
+#endif
+#else
+#ifdef mach_amd64
+    { &amd64_i386, 1, "--32" },
+#endif
+#endif
+    { 0 }
+};
+void
+setup_as_flags(void)
+{
+    one = one;
+#ifdef PCC_SETUP_AS_ARGS
+    PCC_SETUP_AS_ARGS
+#endif
+    cksetflags(asflgcheck, &assembler_flags, 'a');
+}
+
+struct flgcheck ldflgcheck[] = {
+#ifndef MSLINKER
+    { &vflag, 1, "-v" },
+#endif
+#ifdef os_darwin
+    { &shared, 1, "-dylib" },
+#elif defined(os_win32)
+    { &shared, 1, "-Bdynamic" },
+#else
+    { &shared, 1, "-shared" },
+#endif
+#if !defined(os_sunos) && !defined(os_win32)
+#ifndef os_darwin
+    { &shared, 0, "-d" },
+#endif
+#endif
+#ifdef os_darwin
+    { &Bstatic, 1, "-static" },
+#else
+    { &Bstatic, 1, "-Bstatic" },
+#endif
+#if !defined(os_darwin) && !defined(os_sunos)
+    { &gflag, 1, "-g" },
+#endif
+    { &pthreads, 1, "-lpthread" },
+    { 0 },
+};
+
+static void
+strap(struct strlist *sh, struct strlist *cd, char *n, int where)
+{
+    void (*fn)(struct strlist *, const char *);
+    char *fil;
+
+    if (n == 0)
+        return; /* no crtfile */
+
+    fn = where == 'p' ? strlist_prepend : strlist_append;
+    fil = find_file(n, cd, R_OK);
+    (*fn)(sh, fil);
+}
+
+void
+setup_ld_flags(void)
+{
+    char *b, *e;
+    int i;
+
+#ifdef PCC_SETUP_LD_ARGS
+    PCC_SETUP_LD_ARGS
+#endif
+
+    cksetflags(ldflgcheck, &early_linker_flags, 'a');
+    if (Bstatic == 0 && shared == 0 && rflag == 0) {
+        if (dynlinklib) {
+            strlist_append(&early_linker_flags, dynlinkarg);
+            strlist_append(&early_linker_flags, dynlinklib);
+        }
+        strlist_append(&early_linker_flags, "-e");
+        strlist_append(&early_linker_flags, STARTLABEL);
+    }
+    if (shared == 0 && rflag)
+        strlist_append(&early_linker_flags, "-r");
+#ifdef STARTLABEL_S
+    if (shared == 1) {
+        strlist_append(&early_linker_flags, "-e");
+        strlist_append(&early_linker_flags, STARTLABEL_S);
+    }
+#endif
+    if (sysroot && *sysroot)
+        strlist_append(&early_linker_flags, cat("--sysroot=", sysroot));
+    if (!nostdlib) {
+        /* library search paths */
+        if (pcclibdir)
+            strlist_append(&late_linker_flags,
+                cat("-L", pcclibdir));
+        for (i = 0; deflibdirs[i]; i++)
+            strlist_append(&late_linker_flags,
+                cat("-L", deflibdirs[i]));
+        /* standard libraries */
+        if (pgflag) {
+            for (i = 0; defproflibs[i]; i++)
+                strlist_append(&late_linker_flags,
+                     defproflibs[i]);
+        } else if (cxxflag) {
+            for (i = 0; defcxxlibs[i]; i++)
+                strlist_append(&late_linker_flags,
+                    defcxxlibs[i]);
+        } else {
+            for (i = 0; deflibs[i]; i++)
+                strlist_append(&late_linker_flags, deflibs[i]);
+        }
+    }
+    if (!nostartfiles) {
+        if (Bstatic) {
+            b = CRTBEGIN_T;
+            e = CRTEND_T;
+        } else if (shared /* || pieflag */) {
+            b = CRTBEGIN_S;
+            e = CRTEND_S;
+        }  else {
+            b = CRTBEGIN;
+            e = CRTEND;
+        }
+        //strap(&middle_linker_flags, &crtdirs, b, 'p');
+        //strap(&late_linker_flags, &crtdirs, e, 'a');
+        strap(&middle_linker_flags, &crtdirs, CRTI, 'p');
+        strap(&late_linker_flags, &crtdirs, CRTN, 'a');
+#ifdef os_win32
+        /*
+         * On Win32 Cygwin/MinGW runtimes, the profiling code gcrtN.o
+         * comes in addition to crtN.o or dllcrtN.o
+         */
+        if (pgflag)
+            strap(&middle_linker_flags, &crtdirs, GCRT0, 'p');
+        if (shared == 0)
+            b = CRT0;
+        else
+            b = CRT0_S;     /* dllcrtN.o */
+        strap(&middle_linker_flags, &crtdirs, b, 'p');
+#else
+        if (shared == 0) {
+            if (pgflag)
+                b = GCRT0;
+#ifdef notyet
+            else if (pieflag)
+                b = SCRT0;
+#endif
+            else
+                b = CRT0;
+            strap(&middle_linker_flags, &crtdirs, b, 'p');
+        }
+#endif
+    }
+}
+
+#ifdef _WIN32
+char *
+win32pathsubst(char *s)
+{
+    char env[1024];
+    DWORD len;
+
+    len = ExpandEnvironmentStrings(s, env, sizeof(env));
+    if (len == 0 || len > sizeof(env))
+        errorx(8, "ExpandEnvironmentStrings failed, len %lu", len);
+
+    len--;  /* skip nil */
+    while (len-- > 0 && (env[len] == '/' || env[len] == '\\'))
+        env[len] = '\0';
+
+    return xstrdup(env);
+}
+
+char *
+win32commandline(struct strlist *l)
+{
+    const struct string *s;
+    char *cmd;
+    char *p;
+    int len;
+    int j, k;
+
+    len = 0;
+    STRLIST_FOREACH(s, l) {
+        len++;
+        for (j = 0; s->value[j] != '\0'; j++) {
+            if (s->value[j] == '\"') {
+                for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
+                    len++;
+                len++;
+            }
+            len++;
+        }
+        for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
+            len++;
+        len++;
+        len++;
+    }
+
+    p = cmd = xmalloc(len);
+
+    STRLIST_FOREACH(s, l) {
+        *p++ = '\"';
+        for (j = 0; s->value[j] != '\0'; j++) {
+            if (s->value[j] == '\"') {
+                for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
+                    *p++ = '\\';
+                *p++ = '\\';
+            }
+            *p++ = s->value[j];
+        }
+        for (k = j-1; k >= 0 && s->value[k] == '\\'; k--)
+            *p++ = '\\';
+        *p++ = '\"';
+        *p++ = ' ';
+    }
+    p[-1] = '\0';
+
+    return cmd;
+}
+#endif
diff --git a/ccconfig.h b/ccconfig.h
new file mode 100644 (file)
index 0000000..ff8bec9
--- /dev/null
@@ -0,0 +1,98 @@
+/*  $Id$    */
+
+/*
+ * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Various settings that controls how the C compiler works.
+ */
+
+/* common cpp predefines */
+#define CPPADD  { "-D__linux__", "-D__ELF__", NULL, }
+
+#define CRT0        "crt1.o"
+#define GCRT0       "gcrt1.o"
+
+#define STARTLABEL "_start"
+
+#if defined(mach_i386)
+#define CPPMDADD    { "-D__i386__", NULL, }
+#define DYNLINKLIB  "/lib/ld-linux.so.2"
+#define MUSL_DYLIB  "/lib/ld-musl-i386.so.1"
+#elif defined(mach_powerpc)
+#define CPPMDADD    { "-D__ppc__", NULL, }
+#define DYNLINKLIB  "/lib/ld-linux.so.2"
+#define MUSL_DYLIB  "/lib/ld-musl-powerpc.so.1"
+#elif defined(mach_amd64)
+#include "../inc/amd64.h"
+#define DYNLINKLIB  "/lib/ld-linux-x86-64.so.2"
+#define MUSL_DYLIB  "/lib/ld-musl-x86_64.so.1"
+#ifndef MULTIARCH_PATH
+#define DEFLIBDIRS  { "/lib/", 0 }
+#else
+#define DEFLIBDIRS  { "/lib/", "/lib/" MULTIARCH_PATH "/", 0 }
+#endif
+#elif defined(mach_mips)
+#define CPPMDADD    { "-D__mips__", NULL, }
+#define DYNLINKLIB  "/lib/ld.so.1"
+#define MUSL_ROOT   "/lib/ld-musl-mips"
+#define MUSL_EL     "el"
+#define MUSL_SF     "-sf"
+#else
+#error defines for arch missing
+#endif
+
+/*
+ * When USE_MUSL is defined, we either provide MUSL_DYLIB, or
+ * code to construct the dynamic linker name at runtime
+ */
+#ifdef USE_MUSL
+#ifdef MUSL_DYLIB
+#define DYNLINKLIB MUSL_DYLIB
+#else
+#ifndef MUSL_EB
+#define MUSL_EB NULL
+#endif
+#ifndef MUSL_EL
+#define MUSL_EL NULL
+#endif
+#ifndef MUSL_SF
+#define MUSL_SF NULL
+#endif
+#ifndef MUSL_HF
+#define MUSL_HF NULL
+#endif
+#ifndef MUSL_EXT
+#define MUSL_EXT ".so.1"
+#endif
+
+#define PCC_SETUP_LD_ARGS   {               \
+        char *t = MUSL_ROOT;                \
+        t = cat(t, bigendian ? MUSL_EB : MUSL_EL);  \
+        t = cat(t, softfloat ? MUSL_SF : MUSL_HF);  \
+        dynlinklib = cat(t, MUSL_EXT);          \
+    }
+#endif
+#endif