From 93473becdaf3e1f44b175a07fa2f59b944746a3a Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Wed, 24 Feb 2016 15:58:47 -0500 Subject: [PATCH] Added a semi-functional version of the PCC compiler. Will compile and link static and dynamically linked executables but only static executables run at the moment. --- build.sh | 248 +++---- cc.c | 2054 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ccconfig.h | 98 +++ 3 files changed, 2249 insertions(+), 151 deletions(-) create mode 100644 cc.c create mode 100644 ccconfig.h diff --git a/build.sh b/build.sh index 86cd0e5..c243263 100755 --- 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 index 0000000..6518e95 --- /dev/null +++ b/cc.c @@ -0,0 +1,2054 @@ +/* $Id$ */ + +/*- + * Copyright (c) 2011 Joerg Sonnenberger . + * 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 +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#include +#include +#include +#ifdef HAVE_LIBGEN_H +#include +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +#ifdef _WIN32 +#include +#include +#include +#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 index 0000000..ff8bec9 --- /dev/null +++ b/ccconfig.h @@ -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 -- 2.52.0