Mercurial > projects > winelf > hg > index.cgi
changeset 0:b10489e764e3
Initial import.
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,74 @@ +TARGET=i686-win32elf + +PREFIX=/usr/local + +CC=$(TARGET)-gcc +HOSTCC=gcc +EXEEXT= +CFLAGS= +LDFLAGS= +SOFLAGS=-shared -Wl,-soname= +AR=$(TARGET)-ar +RANLIB=$(TARGET)-ranlib + +LIBC_OBJS=$(MSVCRT_OBJS) $(KERNEL32_OBJS) $(USER32_OBJS) + +all: msvcrt/libmsvcrt.so kernel32/libkernel32.so user32/libuser32.so \ + libdl.so libm.a \ + crt0.o crt1.o crti.o crtn.o \ + mingwex/libmingwex.a \ + elfimplib$(EXEEXT) + +msvcrt/libmsvcrt.so: + cd msvcrt ; \ + $(MAKE) CC=$(CC) + +kernel32/libkernel32.so: + cd kernel32 ; \ + $(MAKE) CC=$(CC) + +user32/libuser32.so: + cd user32 ; \ + $(MAKE) CC=$(CC) + +libdl.so: + $(CC) $(CFLAGS) $(LDFLAGS) $(SOFLAGS)libloader_dl.0 -nostdlib -o libdl.so dlfcn.c + +libm.a: + $(AR) rc libm.a + $(RANLIB) libm.a + +mingwex/libmingwex.a: + cd mingwex ; \ + CC=$(CC) AR=$(AR) RANLIB=$(RANLIB) ./configure --build=`./config.guess` --host=$(TARGET) ; \ + $(MAKE) + +elfimplib$(EXEEXT): elfimplib.c + $(HOSTCC) elfimplib.c -o elfimplib$(EXEEXT) + +.SUFFIXES: .c .s .o + +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ + +.s.o: + $(CC) -c $< -o $@ + +install: + mkdir -p $(PREFIX)/$(TARGET)/lib + mkdir -p $(PREFIX)/$(TARGET)/include + mkdir -p $(PREFIX)/bin + cp -f crt0.o crt1.o crti.o crtn.o libc.so msvcrt/libmsvcrt.so \ + kernel32/libkernel32.so user32/libuser32.so \ + libdl.so libm.a mingwex/libmingwex.a \ + $(PREFIX)/$(TARGET)/lib + cp -f elfimplib$(EXEEXT) $(PREFIX)/bin + cp -Rf include/* $(PREFIX)/$(TARGET)/include + $(AR) rc $(PREFIX)/$(TARGET)/lib/libg.a + $(RANLIB) $(PREFIX)/$(TARGET)/lib/libg.a + +clean: + rm -f crt0.o crt1.o crti.o crtn.o libc.a $(LIBC_OBJS) + rm -f elfimplib$(EXEEXT) + rm -f libdl.so libm.a + cd mingwex ; make distclean
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,47 @@ +This is an environment for producing valid ELF binaries for Windows. + +[This document uses /opt/crossc/i686-winelf as an example prefix] + +First you need binutils and gcc compiled for i686-win32elf, like so: + +binutils (with binutils-<version>-winelf.diff applied): +../configure --prefix=/opt/crossc/i686-winelf --target=i686-win32elf +make all install + +gcc (with gcc-<version>-winelf.diff applied): +../configure --prefix=/opt/crossc/i686-winelf --target=i686-win32elf \ + --without-headers --with-newlib --disable-threads \ + --disable-shared --enable-static --enable-languages=c \ + --disable-libssp +make all install + + +Then compile and install libc here: +make all install PREFIX=/opt/crossc/i686-winelf + +And remove a broken header from the installation: +find /opt/crossc/i686-winelf/lib/gcc -name limits.h | xargs rm -f + +At this point you can (if you'd like) compile a more complete GCC: +../configure --prefix=/opt/crossc/i686-winelf --target=i686-win32elf +make all install + + +The ELF binaries can be run with elfload.exe, provided in crosslibc. + + +For reference, the GCC configure flags: + +These allow the compiler to build without a C library: +--without-headers +--with-newlib +--disable-threads +--disable-shared +--enable-static +--enable-languages=c +--disable-libssp + +--with-stabs is to fix the broken default debugging selection. + + +This uses parts of the MingW runtime, version 3.9.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crt0.s Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,9 @@ +.globl _start +.globl _init + +_start: + call _init + call _winelf_main + push %eax + call exit + hlt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crt1.c Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2007, 2008 Gregor Richards + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +int main(int, char **, char **); + +/* _winelf_main: Arrange arguments appropriately and call main */ +int _winelf_main(int argc) +{ + char **argv, **envp; + + void *pargc = &argc; + argv = pargc + sizeof(void *); + envp = pargc + sizeof(void *) + (argc+1) * sizeof(char *); + + return main(argc, argv, envp); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crti.s Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,13 @@ +.section .rodata +.globl _data_start__ +_data_start__: + +.section .text +# This is just here to make sure frame_info gets a reference + mov $__register_frame_info, %eax + mov $__deregister_frame_info, %eax + +.section .init +.globl _init +_init: + enter $0, $0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crtn.s Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,7 @@ +.section .bss +.global _bss_end__ +_bss_end__: + +.section .init + leave + ret
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/diffs/binutils-2.17-winelf.diff Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,107 @@ +diff -ruN binutils-2.17/bfd/config.bfd binutils-2.17-winelf/bfd/config.bfd +--- binutils-2.17/bfd/config.bfd 2006-04-05 05:41:57.000000000 -0700 ++++ binutils-2.17-winelf/bfd/config.bfd 2007-03-09 10:59:13.000000000 -0800 +@@ -448,7 +448,8 @@ + ;; + i[3-7]86-*-sysv4* | i[3-7]86-*-unixware* | \ + i[3-7]86-*-elf | i[3-7]86-*-sco3.2v5* | \ +- i[3-7]86-*-dgux* | i[3-7]86-*-sysv5*) ++ i[3-7]86-*-dgux* | i[3-7]86-*-sysv5* | \ ++ i[3-7]86-*-win32elf*) + targ_defvec=bfd_elf32_i386_vec + targ_selvecs=i386coff_vec + ;; +diff -ruN binutils-2.17/config.sub binutils-2.17-winelf/config.sub +--- binutils-2.17/config.sub 2006-01-16 09:34:37.000000000 -0800 ++++ binutils-2.17-winelf/config.sub 2007-03-09 11:04:45.000000000 -0800 +@@ -1206,7 +1206,7 @@ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ +- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ ++ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* | -win32elf* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ +diff -ruN binutils-2.17/gas/configure.tgt binutils-2.17-winelf/gas/configure.tgt +--- binutils-2.17/gas/configure.tgt 2006-04-05 05:41:57.000000000 -0700 ++++ binutils-2.17-winelf/gas/configure.tgt 2007-03-09 11:00:48.000000000 -0800 +@@ -210,6 +210,7 @@ + i386-*-cygwin*) fmt=coff em=pe ;; + i386-*-interix*) fmt=coff em=interix ;; + i386-*-mingw32*) fmt=coff em=pe ;; ++ i386-*-win32elf*) fmt=elf ;; + i386-*-nto-qnx*) fmt=elf ;; + i386-*-*nt*) fmt=coff em=pe ;; + i386-*-chaos) fmt=elf ;; +diff -ruN binutils-2.17/ld/configure.tgt binutils-2.17-winelf/ld/configure.tgt +--- binutils-2.17/ld/configure.tgt 2006-04-05 05:41:57.000000000 -0700 ++++ binutils-2.17-winelf/ld/configure.tgt 2007-03-09 11:16:10.000000000 -0800 +@@ -219,6 +219,7 @@ + targ_extra_ofiles="deffilep.o pe-dll.o" ;; + i[3-7]86-*-interix*) targ_emul=i386pe_posix; + targ_extra_ofiles="deffilep.o pe-dll.o" ;; ++i[3-7]86-*-win32elf*) targ_emul=elf_i386 ;; + i[3-7]86-*-beospe*) targ_emul=i386beos ;; + i[3-7]86-*-beos*) targ_emul=elf_i386_be ;; + i[3-7]86-*-vxworks*) targ_emul=elf_i386_vxworks ;; +diff -ruN binutils-2.17/libiberty/configure binutils-2.17-winelf/libiberty/configure +--- binutils-2.17/libiberty/configure 2006-04-06 17:01:25.000000000 -0700 ++++ binutils-2.17-winelf/libiberty/configure 2007-03-09 15:13:28.000000000 -0800 +@@ -5713,7 +5713,7 @@ + + + case "${host}" in +- *-*-cygwin* | *-*-mingw*) ++ *-*-cygwin* | *-*-mingw* | *-*-win32elf*) + cat >>confdefs.h <<\_ACEOF + #define HAVE_SYS_ERRLIST 1 + _ACEOF +@@ -5877,7 +5877,7 @@ + fi + ;; + +- *-*-mingw32*) ++ *-*-mingw32* | *-*-win32elf*) + # Under mingw32, sys_nerr and sys_errlist exist, but they are + # macros, so the test below won't find them. + libiberty_cv_var_sys_nerr=yes +@@ -8198,7 +8198,7 @@ + + # Figure out which version of pexecute to use. + case "${host}" in +- *-*-mingw* | *-*-winnt*) pexecute=./pex-win32.o ;; ++ *-*-mingw* | *-*-winnt* | *-*-win32elf*) pexecute=./pex-win32.o ;; + *-*-msdosdjgpp*) pexecute=./pex-djgpp.o ;; + *-*-msdos*) pexecute=./pex-msdos.o ;; + *) pexecute=./pex-unix.o ;; +diff -ruN binutils-2.17/libiberty/configure.ac binutils-2.17-winelf/libiberty/configure.ac +--- binutils-2.17/libiberty/configure.ac 2006-04-06 17:01:25.000000000 -0700 ++++ binutils-2.17-winelf/libiberty/configure.ac 2007-03-09 15:12:44.000000000 -0800 +@@ -451,7 +451,7 @@ + AC_SUBST(target_header_dir) + + case "${host}" in +- *-*-cygwin* | *-*-mingw*) ++ *-*-cygwin* | *-*-mingw* | *-*-win32elf*) + AC_DEFINE(HAVE_SYS_ERRLIST) + AC_DEFINE(HAVE_SYS_NERR) + ;; +@@ -526,7 +526,7 @@ + fi + ;; + +- *-*-mingw32*) ++ *-*-mingw32* | *-*-win32elf*) + # Under mingw32, sys_nerr and sys_errlist exist, but they are + # macros, so the test below won't find them. + libiberty_cv_var_sys_nerr=yes +@@ -611,7 +611,7 @@ + + # Figure out which version of pexecute to use. + case "${host}" in +- *-*-mingw* | *-*-winnt*) pexecute=./pex-win32.o ;; ++ *-*-mingw* | *-*-winnt* | *-*-win32elf) pexecute=./pex-win32.o ;; + *-*-msdosdjgpp*) pexecute=./pex-djgpp.o ;; + *-*-msdos*) pexecute=./pex-msdos.o ;; + *) pexecute=./pex-unix.o ;;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/diffs/binutils-2.18-winelf.diff Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,107 @@ +diff -ruN binutils-2.18/bfd/config.bfd binutils-2.18-winelf/bfd/config.bfd +--- binutils-2.18/bfd/config.bfd 2007-08-28 10:19:33.000000000 -0700 ++++ binutils-2.18-winelf/bfd/config.bfd 2008-02-24 16:20:57.000000000 -0800 +@@ -478,7 +478,8 @@ + ;; + i[3-7]86-*-sysv4* | i[3-7]86-*-unixware* | \ + i[3-7]86-*-elf | i[3-7]86-*-sco3.2v5* | \ +- i[3-7]86-*-dgux* | i[3-7]86-*-sysv5*) ++ i[3-7]86-*-dgux* | i[3-7]86-*-sysv5* | \ ++ i[3-7]86-*-win32elf*) + targ_defvec=bfd_elf32_i386_vec + targ_selvecs=i386coff_vec + ;; +diff -ruN binutils-2.18/config.sub binutils-2.18-winelf/config.sub +--- binutils-2.18/config.sub 2007-08-06 13:00:30.000000000 -0700 ++++ binutils-2.18-winelf/config.sub 2008-02-24 16:20:57.000000000 -0800 +@@ -1217,7 +1217,7 @@ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ +- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ ++ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* | -win32elf* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ +diff -ruN binutils-2.18/gas/configure.tgt binutils-2.18-winelf/gas/configure.tgt +--- binutils-2.18/gas/configure.tgt 2007-08-28 10:19:36.000000000 -0700 ++++ binutils-2.18-winelf/gas/configure.tgt 2008-02-24 16:21:28.000000000 -0800 +@@ -221,6 +221,7 @@ + x86_64*) fmt=coff em=pep ;; + i*) fmt=coff em=pe ;; + esac ;; ++ i386-*-win32elf*) fmt=elf ;; + i386-*-nto-qnx*) fmt=elf ;; + i386-*-*nt*) fmt=coff em=pe ;; + i386-*-chaos) fmt=elf ;; +diff -ruN binutils-2.18/ld/configure.tgt binutils-2.18-winelf/ld/configure.tgt +--- binutils-2.18/ld/configure.tgt 2007-08-28 10:19:42.000000000 -0700 ++++ binutils-2.18-winelf/ld/configure.tgt 2008-02-24 16:20:57.000000000 -0800 +@@ -267,6 +267,7 @@ + targ_extra_ofiles="deffilep.o pep-dll.o" ;; + i[3-7]86-*-interix*) targ_emul=i386pe_posix; + targ_extra_ofiles="deffilep.o pe-dll.o" ;; ++i[3-7]86-*-win32elf*) targ_emul=elf_i386 ;; + i[3-7]86-*-beospe*) targ_emul=i386beos ;; + i[3-7]86-*-beos*) targ_emul=elf_i386_be ;; + i[3-7]86-*-vxworks*) targ_emul=elf_i386_vxworks ;; +diff -ruN binutils-2.18/libiberty/configure binutils-2.18-winelf/libiberty/configure +--- binutils-2.18/libiberty/configure 2007-08-06 12:59:45.000000000 -0700 ++++ binutils-2.18-winelf/libiberty/configure 2008-02-24 16:20:57.000000000 -0800 +@@ -6012,7 +6012,7 @@ + + + case "${host}" in +- *-*-cygwin* | *-*-mingw*) ++ *-*-cygwin* | *-*-mingw* | *-*-win32elf*) + cat >>confdefs.h <<\_ACEOF + #define HAVE_SYS_ERRLIST 1 + _ACEOF +@@ -6196,7 +6196,7 @@ + fi + ;; + +- *-*-mingw32*) ++ *-*-mingw32* | *-*-win32elf*) + # Under mingw32, sys_nerr and sys_errlist exist, but they are + # macros, so the test below won't find them. + libiberty_cv_var_sys_nerr=yes +@@ -8517,7 +8517,7 @@ + + # Figure out which version of pexecute to use. + case "${host}" in +- *-*-mingw* | *-*-winnt*) pexecute=./pex-win32.o ;; ++ *-*-mingw* | *-*-winnt* | *-*-win32elf*) pexecute=./pex-win32.o ;; + *-*-msdosdjgpp*) pexecute=./pex-djgpp.o ;; + *-*-msdos*) pexecute=./pex-msdos.o ;; + *) pexecute=./pex-unix.o ;; +diff -ruN binutils-2.18/libiberty/configure.ac binutils-2.18-winelf/libiberty/configure.ac +--- binutils-2.18/libiberty/configure.ac 2007-08-06 12:59:45.000000000 -0700 ++++ binutils-2.18-winelf/libiberty/configure.ac 2008-02-24 16:20:57.000000000 -0800 +@@ -502,7 +502,7 @@ + AC_SUBST(target_header_dir) + + case "${host}" in +- *-*-cygwin* | *-*-mingw*) ++ *-*-cygwin* | *-*-mingw* | *-*-win32elf*) + AC_DEFINE(HAVE_SYS_ERRLIST) + AC_DEFINE(HAVE_SYS_NERR) + ;; +@@ -594,7 +594,7 @@ + fi + ;; + +- *-*-mingw32*) ++ *-*-mingw32* | *-*-win32elf*) + # Under mingw32, sys_nerr and sys_errlist exist, but they are + # macros, so the test below won't find them. + libiberty_cv_var_sys_nerr=yes +@@ -679,7 +679,7 @@ + + # Figure out which version of pexecute to use. + case "${host}" in +- *-*-mingw* | *-*-winnt*) pexecute=./pex-win32.o ;; ++ *-*-mingw* | *-*-winnt* | *-*-win32elf) pexecute=./pex-win32.o ;; + *-*-msdosdjgpp*) pexecute=./pex-djgpp.o ;; + *-*-msdos*) pexecute=./pex-msdos.o ;; + *) pexecute=./pex-unix.o ;;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/diffs/binutils-2.19-winelf.diff Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,107 @@ +diff -r 32aece6b841a -r 2766f4462a7e bfd/config.bfd +--- a/bfd/config.bfd Thu Jul 23 13:16:34 2009 -0400 ++++ b/bfd/config.bfd Thu Jul 23 13:17:20 2009 -0400 +@@ -479,7 +479,8 @@ + ;; + i[3-7]86-*-sysv4* | i[3-7]86-*-unixware* | \ + i[3-7]86-*-elf | i[3-7]86-*-sco3.2v5* | \ +- i[3-7]86-*-dgux* | i[3-7]86-*-sysv5*) ++ i[3-7]86-*-dgux* | i[3-7]86-*-sysv5* | \ ++ i[3-7]86-*-win32elf*) + targ_defvec=bfd_elf32_i386_vec + targ_selvecs=i386coff_vec + ;; +diff -r 32aece6b841a -r 2766f4462a7e config.sub +--- a/config.sub Thu Jul 23 13:16:34 2009 -0400 ++++ b/config.sub Thu Jul 23 13:17:20 2009 -0400 +@@ -1257,7 +1257,7 @@ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ +- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ ++ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* | -win32elf* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ +diff -r 32aece6b841a -r 2766f4462a7e gas/configure.tgt +--- a/gas/configure.tgt Thu Jul 23 13:16:34 2009 -0400 ++++ b/gas/configure.tgt Thu Jul 23 13:17:20 2009 -0400 +@@ -225,6 +225,7 @@ + x86_64*) fmt=coff em=pep ;; + i*) fmt=coff em=pe ;; + esac ;; ++ i386-*-win32elf*) fmt=elf ;; + i386-*-nto-qnx*) fmt=elf ;; + i386-*-*nt*) fmt=coff em=pe ;; + i386-*-chaos) fmt=elf ;; +diff -r 32aece6b841a -r 2766f4462a7e ld/configure.tgt +--- a/ld/configure.tgt Thu Jul 23 13:16:34 2009 -0400 ++++ b/ld/configure.tgt Thu Jul 23 13:17:20 2009 -0400 +@@ -272,6 +272,7 @@ + targ_extra_ofiles="deffilep.o pep-dll.o" ;; + i[3-7]86-*-interix*) targ_emul=i386pe_posix; + targ_extra_ofiles="deffilep.o pe-dll.o" ;; ++i[3-7]86-*-win32elf*) targ_emul=elf_i386 ;; + i[3-7]86-*-beospe*) targ_emul=i386beos ;; + i[3-7]86-*-beos*) targ_emul=elf_i386_be ;; + i[3-7]86-*-vxworks*) targ_emul=elf_i386_vxworks ;; +diff -r 32aece6b841a -r 2766f4462a7e libiberty/configure +--- a/libiberty/configure Thu Jul 23 13:16:34 2009 -0400 ++++ b/libiberty/configure Thu Jul 23 13:17:20 2009 -0400 +@@ -6044,7 +6044,7 @@ + + + case "${host}" in +- *-*-cygwin* | *-*-mingw*) ++ *-*-cygwin* | *-*-mingw* | *-*-win32elf*) + cat >>confdefs.h <<\_ACEOF + #define HAVE_SYS_ERRLIST 1 + _ACEOF +@@ -6228,7 +6228,7 @@ + fi + ;; + +- *-*-mingw32*) ++ *-*-mingw32* | *-*-win32elf*) + # Under mingw32, sys_nerr and sys_errlist exist, but they are + # macros, so the test below won't find them. + libiberty_cv_var_sys_nerr=yes +@@ -8549,7 +8549,7 @@ + + # Figure out which version of pexecute to use. + case "${host}" in +- *-*-mingw* | *-*-winnt*) pexecute=./pex-win32.o ;; ++ *-*-mingw* | *-*-winnt* | *-*-win32elf*) pexecute=./pex-win32.o ;; + *-*-msdosdjgpp*) pexecute=./pex-djgpp.o ;; + *-*-msdos*) pexecute=./pex-msdos.o ;; + *) pexecute=./pex-unix.o ;; +diff -r 32aece6b841a -r 2766f4462a7e libiberty/configure.ac +--- a/libiberty/configure.ac Thu Jul 23 13:16:34 2009 -0400 ++++ b/libiberty/configure.ac Thu Jul 23 13:17:20 2009 -0400 +@@ -501,7 +501,7 @@ + AC_SUBST(target_header_dir) + + case "${host}" in +- *-*-cygwin* | *-*-mingw*) ++ *-*-cygwin* | *-*-mingw* | *-*-win32elf*) + AC_DEFINE(HAVE_SYS_ERRLIST) + AC_DEFINE(HAVE_SYS_NERR) + ;; +@@ -593,7 +593,7 @@ + fi + ;; + +- *-*-mingw32*) ++ *-*-mingw32* | *-*-win32elf*) + # Under mingw32, sys_nerr and sys_errlist exist, but they are + # macros, so the test below won't find them. + libiberty_cv_var_sys_nerr=yes +@@ -678,7 +678,7 @@ + + # Figure out which version of pexecute to use. + case "${host}" in +- *-*-mingw* | *-*-winnt*) pexecute=./pex-win32.o ;; ++ *-*-mingw* | *-*-winnt* | *-*-win32elf) pexecute=./pex-win32.o ;; + *-*-msdosdjgpp*) pexecute=./pex-djgpp.o ;; + *-*-msdos*) pexecute=./pex-msdos.o ;; + *) pexecute=./pex-unix.o ;;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/diffs/gcc-3.4.5-20060117-1-winelf.diff Fri Jul 24 21:08:19 2009 -0400 @@ -0,0 +1,131617 @@ +diff -ruN gcc-3.4.5-20060117-1/config.sub gcc-3.4.5-20060117-1-winelf/config.sub +--- gcc-3.4.5-20060117-1/config.sub 2004-02-22 06:44:23.000000000 -0800 ++++ gcc-3.4.5-20060117-1-winelf/config.sub 2008-02-26 22:19:17.000000000 -0800 +@@ -1156,7 +1156,7 @@ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ +- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ ++ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* | -win32elf* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ +diff -ruN gcc-3.4.5-20060117-1/gcc/c-format.c.orig gcc-3.4.5-20060117-1-winelf/gcc/c-format.c.orig +--- gcc-3.4.5-20060117-1/gcc/c-format.c.orig 2005-05-01 03:39:15.000000000 -0700 ++++ gcc-3.4.5-20060117-1-winelf/gcc/c-format.c.orig 1969-12-31 16:00:00.000000000 -0800 +@@ -1,2817 +0,0 @@ +-/* Check calls to formatted I/O functions (-Wformat). +- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +- 2001, 2002, 2003 Free Software Foundation, Inc. +- +-This file is part of GCC. +- +-GCC is free software; you can redistribute it and/or modify it under +-the terms of the GNU General Public License as published by the Free +-Software Foundation; either version 2, or (at your option) any later +-version. +- +-GCC is distributed in the hope that it will be useful, but WITHOUT ANY +-WARRANTY; without even the implied warranty of MERCHANTABILITY or +-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-for more details. +- +-You should have received a copy of the GNU General Public License +-along with GCC; see the file COPYING. If not, write to the Free +-Software Foundation, 59 Temple Place - Suite 330, Boston, MA +-02111-1307, USA. */ +- +-#include "config.h" +-#include "system.h" +-#include "coretypes.h" +-#include "tm.h" +-#include "tree.h" +-#include "flags.h" +-#include "toplev.h" +-#include "c-common.h" +-#include "intl.h" +-#include "diagnostic.h" +-#include "langhooks.h" +- +-/* Set format warning options according to a -Wformat=n option. */ +- +-void +-set_Wformat (int setting) +-{ +- warn_format = setting; +- warn_format_extra_args = setting; +- warn_format_zero_length = setting; +- if (setting != 1) +- { +- warn_format_nonliteral = setting; +- warn_format_security = setting; +- warn_format_y2k = setting; +- } +- /* Make sure not to disable -Wnonnull if -Wformat=0 is specified. */ +- if (setting) +- warn_nonnull = setting; +-} +- +- +-/* Handle attributes associated with format checking. */ +- +-/* This must be in the same order as format_types, with format_type_error +- last. */ +-enum format_type { printf_format_type, asm_fprintf_format_type, +- gcc_diag_format_type, gcc_cdiag_format_type, +- gcc_cxxdiag_format_type, +- scanf_format_type, strftime_format_type, +- strfmon_format_type, format_type_error }; +- +-typedef struct function_format_info +-{ +- enum format_type format_type; /* type of format (printf, scanf, etc.) */ +- unsigned HOST_WIDE_INT format_num; /* number of format argument */ +- unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */ +-} function_format_info; +- +-static bool decode_format_attr (tree, function_format_info *, int); +-static enum format_type decode_format_type (const char *); +- +-static bool check_format_string (tree argument, +- unsigned HOST_WIDE_INT format_num, +- int flags, bool *no_add_attrs); +-static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value, +- int validated_p); +- +- +-/* Handle a "format_arg" attribute; arguments as in +- struct attribute_spec.handler. */ +-tree +-handle_format_arg_attribute (tree *node, tree name ATTRIBUTE_UNUSED, +- tree args, int flags, bool *no_add_attrs) +-{ +- tree type = *node; +- tree format_num_expr = TREE_VALUE (args); +- unsigned HOST_WIDE_INT format_num; +- tree argument; +- +- if (!get_constant (format_num_expr, &format_num, 0)) +- { +- error ("format string has invalid operand number"); +- *no_add_attrs = true; +- return NULL_TREE; +- } +- +- argument = TYPE_ARG_TYPES (type); +- if (argument) +- { +- if (!check_format_string (argument, format_num, flags, no_add_attrs)) +- return NULL_TREE; +- } +- +- if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE +- || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) +- != char_type_node)) +- { +- if (!(flags & (int) ATTR_FLAG_BUILT_IN)) +- error ("function does not return string type"); +- *no_add_attrs = true; +- return NULL_TREE; +- } +- +- return NULL_TREE; +-} +- +-/* Verify that the format_num argument is actually a string, in case +- the format attribute is in error. */ +-static bool +-check_format_string (tree argument, unsigned HOST_WIDE_INT format_num, +- int flags, bool *no_add_attrs) +-{ +- unsigned HOST_WIDE_INT i; +- +- for (i = 1; i != format_num; i++) +- { +- if (argument == 0) +- break; +- argument = TREE_CHAIN (argument); +- } +- +- if (!argument +- || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE +- || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument))) +- != char_type_node)) +- { +- if (!(flags & (int) ATTR_FLAG_BUILT_IN)) +- error ("format string arg not a string type"); +- *no_add_attrs = true; +- return false; +- } +- +- return true; +-} +- +-/* Strip any conversions from the expression, verify it is a constant, +- and store its value. If validated_p is true, abort on errors. +- Returns true on success, false otherwise. */ +-static bool +-get_constant(tree expr, unsigned HOST_WIDE_INT *value, int validated_p) +-{ +- while (TREE_CODE (expr) == NOP_EXPR +- || TREE_CODE (expr) == CONVERT_EXPR +- || TREE_CODE (expr) == NON_LVALUE_EXPR) +- expr = TREE_OPERAND (expr, 0); +- +- if (TREE_CODE (expr) != INTEGER_CST || TREE_INT_CST_HIGH (expr) != 0) +- { +- if (validated_p) +- abort (); +- return false; +- } +- +- *value = TREE_INT_CST_LOW (expr); +- +- return true; +-} +- +-/* Decode the arguments to a "format" attribute into a function_format_info +- structure. It is already known that the list is of the right length. +- If VALIDATED_P is true, then these attributes have already been validated +- and this function will abort if they are erroneous; if false, it +- will give an error message. Returns true if the attributes are +- successfully decoded, false otherwise. */ +- +-static bool +-decode_format_attr (tree args, function_format_info *info, int validated_p) +-{ +- tree format_type_id = TREE_VALUE (args); +- tree format_num_expr = TREE_VALUE (TREE_CHAIN (args)); +- tree first_arg_num_expr +- = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))); +- +- if (TREE_CODE (format_type_id) != IDENTIFIER_NODE) +- { +- if (validated_p) +- abort (); +- error ("unrecognized format specifier"); +- return false; +- } +- else +- { +- const char *p = IDENTIFIER_POINTER (format_type_id); +- +- info->format_type = decode_format_type (p); +- +- if (info->format_type == format_type_error) +- { +- if (validated_p) +- abort (); +- warning ("`%s' is an unrecognized format function type", p); +- return false; +- } +- } +- +- if (!get_constant (format_num_expr, &info->format_num, validated_p)) +- { +- error ("format string has invalid operand number"); +- return false; +- } +- +- if (!get_constant (first_arg_num_expr, &info->first_arg_num, validated_p)) +- { +- error ("'...' has invalid operand number"); +- return false; +- } +- +- if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num) +- { +- if (validated_p) +- abort (); +- error ("format string arg follows the args to be formatted"); +- return false; +- } +- +- return true; +-} +- +-/* Check a call to a format function against a parameter list. */ +- +-/* The meaningfully distinct length modifiers for format checking recognized +- by GCC. */ +-enum format_lengths +-{ +- FMT_LEN_none, +- FMT_LEN_hh, +- FMT_LEN_h, +- FMT_LEN_l, +- FMT_LEN_ll, +- FMT_LEN_L, +- FMT_LEN_z, +- FMT_LEN_t, +- FMT_LEN_j, +- FMT_LEN_MAX +-}; +- +- +-/* The standard versions in which various format features appeared. */ +-enum format_std_version +-{ +- STD_C89, +- STD_C94, +- STD_C9L, /* C99, but treat as C89 if -Wno-long-long. */ +- STD_C99, +- STD_EXT +-}; +- +-/* The C standard version C++ is treated as equivalent to +- or inheriting from, for the purpose of format features supported. */ +-#define CPLUSPLUS_STD_VER STD_C94 +-/* The C standard version we are checking formats against when pedantic. */ +-#define C_STD_VER ((int)(c_dialect_cxx () \ +- ? CPLUSPLUS_STD_VER \ +- : (flag_isoc99 \ +- ? STD_C99 \ +- : (flag_isoc94 ? STD_C94 : STD_C89)))) +-/* The name to give to the standard version we are warning about when +- pedantic. FEATURE_VER is the version in which the feature warned out +- appeared, which is higher than C_STD_VER. */ +-#define C_STD_NAME(FEATURE_VER) (c_dialect_cxx () \ +- ? "ISO C++" \ +- : ((FEATURE_VER) == STD_EXT \ +- ? "ISO C" \ +- : "ISO C90")) +-/* Adjust a C standard version, which may be STD_C9L, to account for +- -Wno-long-long. Returns other standard versions unchanged. */ +-#define ADJ_STD(VER) ((int)((VER) == STD_C9L \ +- ? (warn_long_long ? STD_C99 : STD_C89) \ +- : (VER))) +- +-/* Flags that may apply to a particular kind of format checked by GCC. */ +-enum +-{ +- /* This format converts arguments of types determined by the +- format string. */ +- FMT_FLAG_ARG_CONVERT = 1, +- /* The scanf allocation 'a' kludge applies to this format kind. */ +- FMT_FLAG_SCANF_A_KLUDGE = 2, +- /* A % during parsing a specifier is allowed to be a modified % rather +- that indicating the format is broken and we are out-of-sync. */ +- FMT_FLAG_FANCY_PERCENT_OK = 4, +- /* With $ operand numbers, it is OK to reference the same argument more +- than once. */ +- FMT_FLAG_DOLLAR_MULTIPLE = 8, +- /* This format type uses $ operand numbers (strfmon doesn't). */ +- FMT_FLAG_USE_DOLLAR = 16, +- /* Zero width is bad in this type of format (scanf). */ +- FMT_FLAG_ZERO_WIDTH_BAD = 32, +- /* Empty precision specification is OK in this type of format (printf). */ +- FMT_FLAG_EMPTY_PREC_OK = 64, +- /* Gaps are allowed in the arguments with $ operand numbers if all +- arguments are pointers (scanf). */ +- FMT_FLAG_DOLLAR_GAP_POINTER_OK = 128 +- /* Not included here: details of whether width or precision may occur +- (controlled by width_char and precision_char); details of whether +- '*' can be used for these (width_type and precision_type); details +- of whether length modifiers can occur (length_char_specs). */ +-}; +- +- +-/* Structure describing a length modifier supported in format checking, and +- possibly a doubled version such as "hh". */ +-typedef struct +-{ +- /* Name of the single-character length modifier. */ +- const char *name; +- /* Index into a format_char_info.types array. */ +- enum format_lengths index; +- /* Standard version this length appears in. */ +- enum format_std_version std; +- /* Same, if the modifier can be repeated, or NULL if it can't. */ +- const char *double_name; +- enum format_lengths double_index; +- enum format_std_version double_std; +-} format_length_info; +- +- +-/* Structure describing the combination of a conversion specifier +- (or a set of specifiers which act identically) and a length modifier. */ +-typedef struct +-{ +- /* The standard version this combination of length and type appeared in. +- This is only relevant if greater than those for length and type +- individually; otherwise it is ignored. */ +- enum format_std_version std; +- /* The name to use for the type, if different from that generated internally +- (e.g., "signed size_t"). */ +- const char *name; +- /* The type itself. */ +- tree *type; +-} format_type_detail; +- +- +-/* Macros to fill out tables of these. */ +-#define NOARGUMENTS { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN } +-#define BADLEN { 0, NULL, NULL } +-#define NOLENGTHS { BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN } +- +- +-/* Structure describing a format conversion specifier (or a set of specifiers +- which act identically), and the length modifiers used with it. */ +-typedef struct +-{ +- const char *format_chars; +- int pointer_count; +- enum format_std_version std; +- /* Types accepted for each length modifier. */ +- format_type_detail types[FMT_LEN_MAX]; +- /* List of other modifier characters allowed with these specifiers. +- This lists flags, and additionally "w" for width, "p" for precision +- (right precision, for strfmon), "#" for left precision (strfmon), +- "a" for scanf "a" allocation extension (not applicable in C99 mode), +- "*" for scanf suppression, and "E" and "O" for those strftime +- modifiers. */ +- const char *flag_chars; +- /* List of additional flags describing these conversion specifiers. +- "c" for generic character pointers being allowed, "2" for strftime +- two digit year formats, "3" for strftime formats giving two digit +- years in some locales, "4" for "2" which becomes "3" with an "E" modifier, +- "o" if use of strftime "O" is a GNU extension beyond C99, +- "W" if the argument is a pointer which is dereferenced and written into, +- "R" if the argument is a pointer which is dereferenced and read from, +- "i" for printf integer formats where the '0' flag is ignored with +- precision, and "[" for the starting character of a scanf scanset. */ +- const char *flags2; +-} format_char_info; +- +- +-/* Structure describing a flag accepted by some kind of format. */ +-typedef struct +-{ +- /* The flag character in question (0 for end of array). */ +- int flag_char; +- /* Zero if this entry describes the flag character in general, or a +- nonzero character that may be found in flags2 if it describes the +- flag when used with certain formats only. If the latter, only +- the first such entry found that applies to the current conversion +- specifier is used; the values of `name' and `long_name' it supplies +- will be used, if non-NULL and the standard version is higher than +- the unpredicated one, for any pedantic warning. For example, 'o' +- for strftime formats (meaning 'O' is an extension over C99). */ +- int predicate; +- /* Nonzero if the next character after this flag in the format should +- be skipped ('=' in strfmon), zero otherwise. */ +- int skip_next_char; +- /* The name to use for this flag in diagnostic messages. For example, +- N_("`0' flag"), N_("field width"). */ +- const char *name; +- /* Long name for this flag in diagnostic messages; currently only used for +- "ISO C does not support ...". For example, N_("the `I' printf flag"). */ +- const char *long_name; +- /* The standard version in which it appeared. */ +- enum format_std_version std; +-} format_flag_spec; +- +- +-/* Structure describing a combination of flags that is bad for some kind +- of format. */ +-typedef struct +-{ +- /* The first flag character in question (0 for end of array). */ +- int flag_char1; +- /* The second flag character. */ +- int flag_char2; +- /* Nonzero if the message should say that the first flag is ignored with +- the second, zero if the combination should simply be objected to. */ +- int ignored; +- /* Zero if this entry applies whenever this flag combination occurs, +- a nonzero character from flags2 if it only applies in some +- circumstances (e.g. 'i' for printf formats ignoring 0 with precision). */ +- int predicate; +-} format_flag_pair; +- +- +-/* Structure describing a particular kind of format processed by GCC. */ +-typedef struct +-{ +- /* The name of this kind of format, for use in diagnostics. Also +- the name of the attribute (without preceding and following __). */ +- const char *name; +- /* Specifications of the length modifiers accepted; possibly NULL. */ +- const format_length_info *length_char_specs; +- /* Details of the conversion specification characters accepted. */ +- const format_char_info *conversion_specs; +- /* String listing the flag characters that are accepted. */ +- const char *flag_chars; +- /* String listing modifier characters (strftime) accepted. May be NULL. */ +- const char *modifier_chars; +- /* Details of the flag characters, including pseudo-flags. */ +- const format_flag_spec *flag_specs; +- /* Details of bad combinations of flags. */ +- const format_flag_pair *bad_flag_pairs; +- /* Flags applicable to this kind of format. */ +- int flags; +- /* Flag character to treat a width as, or 0 if width not used. */ +- int width_char; +- /* Flag character to treat a left precision (strfmon) as, +- or 0 if left precision not used. */ +- int left_precision_char; +- /* Flag character to treat a precision (for strfmon, right precision) as, +- or 0 if precision not used. */ +- int precision_char; +- /* If a flag character has the effect of suppressing the conversion of +- an argument ('*' in scanf), that flag character, otherwise 0. */ +- int suppression_char; +- /* Flag character to treat a length modifier as (ignored if length +- modifiers not used). Need not be placed in flag_chars for conversion +- specifiers, but is used to check for bad combinations such as length +- modifier with assignment suppression in scanf. */ +- int length_code_char; +- /* Pointer to type of argument expected if '*' is used for a width, +- or NULL if '*' not used for widths. */ +- tree *width_type; +- /* Pointer to type of argument expected if '*' is used for a precision, +- or NULL if '*' not used for precisions. */ +- tree *precision_type; +-} format_kind_info; +- +- +-/* Structure describing details of a type expected in format checking, +- and the type to check against it. */ +-typedef struct format_wanted_type +-{ +- /* The type wanted. */ +- tree wanted_type; +- /* The name of this type to use in diagnostics. */ +- const char *wanted_type_name; +- /* The level of indirection through pointers at which this type occurs. */ +- int pointer_count; +- /* Whether, when pointer_count is 1, to allow any character type when +- pedantic, rather than just the character or void type specified. */ +- int char_lenient_flag; +- /* Whether the argument, dereferenced once, is written into and so the +- argument must not be a pointer to a const-qualified type. */ +- int writing_in_flag; +- /* Whether the argument, dereferenced once, is read from and so +- must not be a NULL pointer. */ +- int reading_from_flag; +- /* If warnings should be of the form "field precision is not type int", +- the name to use (in this case "field precision"), otherwise NULL, +- for "%s format, %s arg" type messages. If (in an extension), this +- is a pointer type, wanted_type_name should be set to include the +- terminating '*' characters of the type name to give a correct +- message. */ +- const char *name; +- /* The actual parameter to check against the wanted type. */ +- tree param; +- /* The argument number of that parameter. */ +- int arg_num; +- /* The next type to check for this format conversion, or NULL if none. */ +- struct format_wanted_type *next; +-} format_wanted_type; +- +- +-static const format_length_info printf_length_specs[] = +-{ +- { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 }, +- { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L }, +- { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 }, +- { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 }, +- { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 }, +- { "Z", FMT_LEN_z, STD_EXT, NULL, 0, 0 }, +- { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 }, +- { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 }, +- { NULL, 0, 0, NULL, 0, 0 } +-}; +- +-/* Length specifiers valid for asm_fprintf. */ +-static const format_length_info asm_fprintf_length_specs[] = +-{ +- { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89 }, +- { "w", FMT_LEN_none, STD_C89, NULL, 0, 0 }, +- { NULL, 0, 0, NULL, 0, 0 } +-}; +- +-/* Length specifiers valid for GCC diagnostics. */ +-static const format_length_info gcc_diag_length_specs[] = +-{ +- { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89 }, +- { "w", FMT_LEN_none, STD_C89, NULL, 0, 0 }, +- { NULL, 0, 0, NULL, 0, 0 } +-}; +- +-/* The custom diagnostics all accept the same length specifiers. */ +-#define gcc_cdiag_length_specs gcc_diag_length_specs +-#define gcc_cxxdiag_length_specs gcc_diag_length_specs +- +-/* This differs from printf_length_specs only in that "Z" is not accepted. */ +-static const format_length_info scanf_length_specs[] = +-{ +- { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 }, +- { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L }, +- { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 }, +- { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 }, +- { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 }, +- { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 }, +- { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 }, +- { NULL, 0, 0, NULL, 0, 0 } +-}; +- +- +-/* All tables for strfmon use STD_C89 everywhere, since -pedantic warnings +- make no sense for a format type not part of any C standard version. */ +-static const format_length_info strfmon_length_specs[] = +-{ +- /* A GNU extension. */ +- { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 }, +- { NULL, 0, 0, NULL, 0, 0 } +-}; +- +-static const format_flag_spec printf_flag_specs[] = +-{ +- { ' ', 0, 0, N_("` ' flag"), N_("the ` ' printf flag"), STD_C89 }, +- { '+', 0, 0, N_("`+' flag"), N_("the `+' printf flag"), STD_C89 }, +- { '#', 0, 0, N_("`#' flag"), N_("the `#' printf flag"), STD_C89 }, +- { '0', 0, 0, N_("`0' flag"), N_("the `0' printf flag"), STD_C89 }, +- { '-', 0, 0, N_("`-' flag"), N_("the `-' printf flag"), STD_C89 }, +- { '\'', 0, 0, N_("`'' flag"), N_("the `'' printf flag"), STD_EXT }, +- { 'I', 0, 0, N_("`I' flag"), N_("the `I' printf flag"), STD_EXT }, +- { 'w', 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 }, +- { 'p', 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, +- { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, +- { 0, 0, 0, NULL, NULL, 0 } +-}; +- +- +-static const format_flag_pair printf_flag_pairs[] = +-{ +- { ' ', '+', 1, 0 }, +- { '0', '-', 1, 0 }, +- { '0', 'p', 1, 'i' }, +- { 0, 0, 0, 0 } +-}; +- +-static const format_flag_spec asm_fprintf_flag_specs[] = +-{ +- { ' ', 0, 0, N_("` ' flag"), N_("the ` ' printf flag"), STD_C89 }, +- { '+', 0, 0, N_("`+' flag"), N_("the `+' printf flag"), STD_C89 }, +- { '#', 0, 0, N_("`#' flag"), N_("the `#' printf flag"), STD_C89 }, +- { '0', 0, 0, N_("`0' flag"), N_("the `0' printf flag"), STD_C89 }, +- { '-', 0, 0, N_("`-' flag"), N_("the `-' printf flag"), STD_C89 }, +- { 'w', 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 }, +- { 'p', 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, +- { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, +- { 0, 0, 0, NULL, NULL, 0 } +-}; +- +-static const format_flag_pair asm_fprintf_flag_pairs[] = +-{ +- { ' ', '+', 1, 0 }, +- { '0', '-', 1, 0 }, +- { '0', 'p', 1, 'i' }, +- { 0, 0, 0, 0 } +-}; +- +-static const format_flag_pair gcc_diag_flag_pairs[] = +-{ +- { 0, 0, 0, 0 } +-}; +- +-#define gcc_cdiag_flag_pairs gcc_diag_flag_pairs +-#define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs +- +-static const format_flag_spec gcc_diag_flag_specs[] = +-{ +- { 'p', 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, +- { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, +- { 0, 0, 0, NULL, NULL, 0 } +-}; +- +-#define gcc_cdiag_flag_specs gcc_diag_flag_specs +- +-static const format_flag_spec gcc_cxxdiag_flag_specs[] = +-{ +- { '+', 0, 0, N_("`+' flag"), N_("the `+' printf flag"), STD_C89 }, +- { '#', 0, 0, N_("`#' flag"), N_("the `#' printf flag"), STD_C89 }, +- { 'p', 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, +- { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, +- { 0, 0, 0, NULL, NULL, 0 } +-}; +- +-static const format_flag_spec scanf_flag_specs[] = +-{ +- { '*', 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 }, +- { 'a', 0, 0, N_("`a' flag"), N_("the `a' scanf flag"), STD_EXT }, +- { 'w', 0, 0, N_("field width"), N_("field width in scanf format"), STD_C89 }, +- { 'L', 0, 0, N_("length modifier"), N_("length modifier in scanf format"), STD_C89 }, +- { '\'', 0, 0, N_("`'' flag"), N_("the `'' scanf flag"), STD_EXT }, +- { 'I', 0, 0, N_("`I' flag"), N_("the `I' scanf flag"), STD_EXT }, +- { 0, 0, 0, NULL, NULL, 0 } +-}; +- +- +-static const format_flag_pair scanf_flag_pairs[] = +-{ +- { '*', 'L', 0, 0 }, +- { 0, 0, 0, 0 } +-}; +- +- +-static const format_flag_spec strftime_flag_specs[] = +-{ +- { '_', 0, 0, N_("`_' flag"), N_("the `_' strftime flag"), STD_EXT }, +- { '-', 0, 0, N_("`-' flag"), N_("the `-' strftime flag"), STD_EXT }, +- { '0', 0, 0, N_("`0' flag"), N_("the `0' strftime flag"), STD_EXT }, +- { '^', 0, 0, N_("`^' flag"), N_("the `^' strftime flag"), STD_EXT }, +- { '#', 0, 0, N_("`#' flag"), N_("the `#' strftime flag"), STD_EXT }, +- { 'w', 0, 0, N_("field width"), N_("field width in strftime format"), STD_EXT }, +- { 'E', 0, 0, N_("`E' modifier"), N_("the `E' strftime modifier"), STD_C99 }, +- { 'O', 0, 0, N_("`O' modifier"), N_("the `O' strftime modifier"), STD_C99 }, +- { 'O', 'o', 0, NULL, N_("the `O' modifier"), STD_EXT }, +- { 0, 0, 0, NULL, NULL, 0 } +-}; +- +- +-static const format_flag_pair strftime_flag_pairs[] = +-{ +- { 'E', 'O', 0, 0 }, +- { '_', '-', 0, 0 }, +- { '_', '0', 0, 0 }, +- { '-', '0', 0, 0 }, +- { '^', '#', 0, 0 }, +- { 0, 0, 0, 0 } +-}; +- +- +-static const format_flag_spec strfmon_flag_specs[] = +-{ +- { '=', 0, 1, N_("fill character"), N_("fill character in strfmon format"), STD_C89 }, +- { '^', 0, 0, N_("`^' flag"), N_("the `^' strfmon flag"), STD_C89 }, +- { '+', 0, 0, N_("`+' flag"), N_("the `+' strfmon flag"), STD_C89 }, +- { '(', 0, 0, N_("`(' flag"), N_("the `(' strfmon flag"), STD_C89 }, +- { '!', 0, 0, N_("`!' flag"), N_("the `!' strfmon flag"), STD_C89 }, +- { '-', 0, 0, N_("`-' flag"), N_("the `-' strfmon flag"), STD_C89 }, +- { 'w', 0, 0, N_("field width"), N_("field width in strfmon format"), STD_C89 }, +- { '#', 0, 0, N_("left precision"), N_("left precision in strfmon format"), STD_C89 }, +- { 'p', 0, 0, N_("right precision"), N_("right precision in strfmon format"), STD_C89 }, +- { 'L', 0, 0, N_("length modifier"), N_("length modifier in strfmon format"), STD_C89 }, +- { 0, 0, 0, NULL, NULL, 0 } +-}; +- +-static const format_flag_pair strfmon_flag_pairs[] = +-{ +- { '+', '(', 0, 0 }, +- { 0, 0, 0, 0 } +-}; +- +- +-#define T_I &integer_type_node +-#define T89_I { STD_C89, NULL, T_I } +-#define T_L &long_integer_type_node +-#define T89_L { STD_C89, NULL, T_L } +-#define T_LL &long_long_integer_type_node +-#define T9L_LL { STD_C9L, NULL, T_LL } +-#define TEX_LL { STD_EXT, NULL, T_LL } +-#define T_S &short_integer_type_node +-#define T89_S { STD_C89, NULL, T_S } +-#define T_UI &unsigned_type_node +-#define T89_UI { STD_C89, NULL, T_UI } +-#define T_UL &long_unsigned_type_node +-#define T89_UL { STD_C89, NULL, T_UL } +-#define T_ULL &long_long_unsigned_type_node +-#define T9L_ULL { STD_C9L, NULL, T_ULL } +-#define TEX_ULL { STD_EXT, NULL, T_ULL } +-#define T_US &short_unsigned_type_node +-#define T89_US { STD_C89, NULL, T_US } +-#define T_F &float_type_node +-#define T89_F { STD_C89, NULL, T_F } +-#define T99_F { STD_C99, NULL, T_F } +-#define T_D &double_type_node +-#define T89_D { STD_C89, NULL, T_D } +-#define T99_D { STD_C99, NULL, T_D } +-#define T_LD &long_double_type_node +-#define T89_LD { STD_C89, NULL, T_LD } +-#define T99_LD { STD_C99, NULL, T_LD } +-#define T_C &char_type_node +-#define T89_C { STD_C89, NULL, T_C } +-#define T_SC &signed_char_type_node +-#define T99_SC { STD_C99, NULL, T_SC } +-#define T_UC &unsigned_char_type_node +-#define T99_UC { STD_C99, NULL, T_UC } +-#define T_V &void_type_node +-#define T89_V { STD_C89, NULL, T_V } +-#define T_W &wchar_type_node +-#define T94_W { STD_C94, "wchar_t", T_W } +-#define TEX_W { STD_EXT, "wchar_t", T_W } +-#define T_WI &wint_type_node +-#define T94_WI { STD_C94, "wint_t", T_WI } +-#define TEX_WI { STD_EXT, "wint_t", T_WI } +-#define T_ST &size_type_node +-#define T99_ST { STD_C99, "size_t", T_ST } +-#define T_SST &signed_size_type_node +-#define T99_SST { STD_C99, "signed size_t", T_SST } +-#define T_PD &ptrdiff_type_node +-#define T99_PD { STD_C99, "ptrdiff_t", T_PD } +-#define T_UPD &unsigned_ptrdiff_type_node +-#define T99_UPD { STD_C99, "unsigned ptrdiff_t", T_UPD } +-#define T_IM &intmax_type_node +-#define T99_IM { STD_C99, "intmax_t", T_IM } +-#define T_UIM &uintmax_type_node +-#define T99_UIM { STD_C99, "uintmax_t", T_UIM } +- +-static const format_char_info print_char_table[] = +-{ +- /* C89 conversion specifiers. */ +- { "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM }, "-wp0 +'I", "i" }, +- { "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0#", "i" }, +- { "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "-wp0'I", "i" }, +- { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#'I", "" }, +- { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#I", "" }, +- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "" }, +- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR" }, +- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c" }, +- { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM }, "", "W" }, +- /* C99 conversion specifiers. */ +- { "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#'I", "" }, +- { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "" }, +- /* X/Open conversion specifiers. */ +- { "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "" }, +- { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R" }, +- /* GNU conversion specifiers. */ +- { "m", 0, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "" }, +- { NULL, 0, 0, NOLENGTHS, NULL, NULL } +-}; +- +-static const format_char_info asm_fprintf_char_table[] = +-{ +- /* C89 conversion specifiers. */ +- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +", "i" }, +- { "oxX", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i" }, +- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0", "i" }, +- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "" }, +- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR" }, +- +- /* asm_fprintf conversion specifiers. */ +- { "O", 0, STD_C89, NOARGUMENTS, "", "" }, +- { "R", 0, STD_C89, NOARGUMENTS, "", "" }, +- { "I", 0, STD_C89, NOARGUMENTS, "", "" }, +- { "L", 0, STD_C89, NOARGUMENTS, "", "" }, +- { "U", 0, STD_C89, NOARGUMENTS, "", "" }, +- { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "@", 0, STD_C89, NOARGUMENTS, "", "" }, +- { NULL, 0, 0, NOLENGTHS, NULL, NULL } +-}; +- +-static const format_char_info gcc_diag_char_table[] = +-{ +- /* C89 conversion specifiers. */ +- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "p", "cR" }, +- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "c" }, +- +- /* Custom conversion specifiers. */ +- +- /* %H will require "location_t" at runtime. */ +- { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- +- /* These will require a "tree" at runtime. */ +- { "J", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- +- { "m", 0, STD_C89, NOARGUMENTS, "", "" }, +- { NULL, 0, 0, NOLENGTHS, NULL, NULL } +-}; +- +-static const format_char_info gcc_cdiag_char_table[] = +-{ +- /* C89 conversion specifiers. */ +- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "p", "cR" }, +- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "c" }, +- +- /* Custom conversion specifiers. */ +- +- /* %H will require "location_t" at runtime. */ +- { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- +- /* These will require a "tree" at runtime. */ +- { "DEFJT", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- +- { "m", 0, STD_C89, NOARGUMENTS, "", "" }, +- { NULL, 0, 0, NOLENGTHS, NULL, NULL } +-}; +- +-static const format_char_info gcc_cxxdiag_char_table[] = +-{ +- /* C89 conversion specifiers. */ +- { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "p", "cR" }, +- { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "c" }, +- +- /* Custom conversion specifiers. */ +- +- /* %H will require "location_t" at runtime. */ +- { "H", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- +- /* These will require a "tree" at runtime. */ +- { "ADEFJTV",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "+#", "" }, +- +- /* These accept either an `int' or an `enum tree_code' (which is handled as an `int'.) */ +- { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "" }, +- +- { "m", 0, STD_C89, NOARGUMENTS, "", "" }, +- { NULL, 0, 0, NOLENGTHS, NULL, NULL } +-}; +- +-static const format_char_info scan_char_table[] = +-{ +- /* C89 conversion specifiers. */ +- { "di", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM }, "*w'I", "W" }, +- { "u", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "*w'I", "W" }, +- { "oxX", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM }, "*w", "W" }, +- { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "*w'", "W" }, +- { "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "cW" }, +- { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW" }, +- { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "cW[" }, +- { "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W" }, +- { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM }, "", "W" }, +- /* C99 conversion specifiers. */ +- { "FaA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN }, "*w'", "W" }, +- /* X/Open conversion specifiers. */ +- { "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W" }, +- { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*aw", "W" }, +- { NULL, 0, 0, NOLENGTHS, NULL, NULL } +-}; +- +-static const format_char_info time_char_table[] = +-{ +- /* C89 conversion specifiers. */ +- { "ABZab", 0, STD_C89, NOLENGTHS, "^#", "" }, +- { "cx", 0, STD_C89, NOLENGTHS, "E", "3" }, +- { "HIMSUWdmw", 0, STD_C89, NOLENGTHS, "-_0Ow", "" }, +- { "j", 0, STD_C89, NOLENGTHS, "-_0Ow", "o" }, +- { "p", 0, STD_C89, NOLENGTHS, "#", "" }, +- { "X", 0, STD_C89, NOLENGTHS, "E", "" }, +- { "y", 0, STD_C89, NOLENGTHS, "EO-_0w", "4" }, +- { "Y", 0, STD_C89, NOLENGTHS, "-_0EOw", "o" }, +- { "%", 0, STD_C89, NOLENGTHS, "", "" }, +- /* C99 conversion specifiers. */ +- { "C", 0, STD_C99, NOLENGTHS, "-_0EOw", "o" }, +- { "D", 0, STD_C99, NOLENGTHS, "", "2" }, +- { "eVu", 0, STD_C99, NOLENGTHS, "-_0Ow", "" }, +- { "FRTnrt", 0, STD_C99, NOLENGTHS, "", "" }, +- { "g", 0, STD_C99, NOLENGTHS, "O-_0w", "2o" }, +- { "G", 0, STD_C99, NOLENGTHS, "-_0Ow", "o" }, +- { "h", 0, STD_C99, NOLENGTHS, "^#", "" }, +- { "z", 0, STD_C99, NOLENGTHS, "O", "o" }, +- /* GNU conversion specifiers. */ +- { "kls", 0, STD_EXT, NOLENGTHS, "-_0Ow", "" }, +- { "P", 0, STD_EXT, NOLENGTHS, "", "" }, +- { NULL, 0, 0, NOLENGTHS, NULL, NULL } +-}; +- +-static const format_char_info monetary_char_table[] = +-{ +- { "in", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "=^+(!-w#p", "" }, +- { NULL, 0, 0, NOLENGTHS, NULL, NULL } +-}; +- +- +-/* This must be in the same order as enum format_type. */ +-static const format_kind_info format_types_orig[] = +-{ +- { "printf", printf_length_specs, print_char_table, " +#0-'I", NULL, +- printf_flag_specs, printf_flag_pairs, +- FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK, +- 'w', 0, 'p', 0, 'L', +- &integer_type_node, &integer_type_node +- }, +- { "asm_fprintf", asm_fprintf_length_specs, asm_fprintf_char_table, " +#0-", NULL, +- asm_fprintf_flag_specs, asm_fprintf_flag_pairs, +- FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK, +- 'w', 0, 'p', 0, 'L', +- NULL, NULL +- }, +- { "gcc_diag", gcc_diag_length_specs, gcc_diag_char_table, "", NULL, +- gcc_diag_flag_specs, gcc_diag_flag_pairs, +- FMT_FLAG_ARG_CONVERT, +- 0, 0, 'p', 0, 'L', +- NULL, &integer_type_node +- }, +- { "gcc_cdiag", gcc_cdiag_length_specs, gcc_cdiag_char_table, "", NULL, +- gcc_cdiag_flag_specs, gcc_cdiag_flag_pairs, +- FMT_FLAG_ARG_CONVERT, +- 0, 0, 'p', 0, 'L', +- NULL, &integer_type_node +- }, +- { "gcc_cxxdiag", gcc_cxxdiag_length_specs, gcc_cxxdiag_char_table, "+#", NULL, +- gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs, +- FMT_FLAG_ARG_CONVERT, +- 0, 0, 'p', 0, 'L', +- NULL, &integer_type_node +- }, +- { "scanf", scanf_length_specs, scan_char_table, "*'I", NULL, +- scanf_flag_specs, scanf_flag_pairs, +- FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK, +- 'w', 0, 0, '*', 'L', +- NULL, NULL +- }, +- { "strftime", NULL, time_char_table, "_-0^#", "EO", +- strftime_flag_specs, strftime_flag_pairs, +- FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0, +- NULL, NULL +- }, +- { "strfmon", strfmon_length_specs, monetary_char_table, "=^+(!-", NULL, +- strfmon_flag_specs, strfmon_flag_pairs, +- FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L', +- NULL, NULL +- } +-}; +- +-/* This layer of indirection allows GCC to reassign format_types with +- new data if necessary, while still allowing the original data to be +- const. */ +-static const format_kind_info *format_types = format_types_orig; +-/* We can modify this one. */ +-static format_kind_info *dynamic_format_types; +- +-/* Structure detailing the results of checking a format function call +- where the format expression may be a conditional expression with +- many leaves resulting from nested conditional expressions. */ +-typedef struct +-{ +- /* Number of leaves of the format argument that could not be checked +- as they were not string literals. */ +- int number_non_literal; +- /* Number of leaves of the format argument that were null pointers or +- string literals, but had extra format arguments. */ +- int number_extra_args; +- /* Number of leaves of the format argument that were null pointers or +- string literals, but had extra format arguments and used $ operand +- numbers. */ +- int number_dollar_extra_args; +- /* Number of leaves of the format argument that were wide string +- literals. */ +- int number_wide; +- /* Number of leaves of the format argument that were empty strings. */ +- int number_empty; +- /* Number of leaves of the format argument that were unterminated +- strings. */ +- int number_unterminated; +- /* Number of leaves of the format argument that were not counted above. */ +- int number_other; +-} format_check_results; +- +-typedef struct +-{ +- format_check_results *res; +- function_format_info *info; +- tree params; +- int *status; +-} format_check_context; +- +-static void check_format_info (int *, function_format_info *, tree); +-static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT); +-static void check_format_info_main (int *, format_check_results *, +- function_format_info *, +- const char *, int, tree, +- unsigned HOST_WIDE_INT); +-static void status_warning (int *, const char *, ...) +- ATTRIBUTE_PRINTF_2; +- +-static void init_dollar_format_checking (int, tree); +-static int maybe_read_dollar_number (int *, const char **, int, +- tree, tree *, const format_kind_info *); +-static void finish_dollar_format_checking (int *, format_check_results *, int); +- +-static const format_flag_spec *get_flag_spec (const format_flag_spec *, +- int, const char *); +- +-static void check_format_types (int *, format_wanted_type *); +- +-/* Decode a format type from a string, returning the type, or +- format_type_error if not valid, in which case the caller should print an +- error message. */ +-static enum format_type +-decode_format_type (const char *s) +-{ +- int i; +- int slen; +- slen = strlen (s); +- for (i = 0; i < (int) format_type_error; i++) +- { +- int alen; +- if (!strcmp (s, format_types[i].name)) +- break; +- alen = strlen (format_types[i].name); +- if (slen == alen + 4 && s[0] == '_' && s[1] == '_' +- && s[slen - 1] == '_' && s[slen - 2] == '_' +- && !strncmp (s + 2, format_types[i].name, alen)) +- break; +- } +- return ((enum format_type) i); +-} +- +- +-/* Check the argument list of a call to printf, scanf, etc. +- ATTRS are the attributes on the function type. +- PARAMS is the list of argument values. Also, if -Wmissing-format-attribute, +- warn for calls to vprintf or vscanf in functions with no such format +- attribute themselves. */ +- +-void +-check_function_format (int *status, tree attrs, tree params) +-{ +- tree a; +- +- /* See if this function has any format attributes. */ +- for (a = attrs; a; a = TREE_CHAIN (a)) +- { +- if (is_attribute_p ("format", TREE_PURPOSE (a))) +- { +- /* Yup; check it. */ +- function_format_info info; +- decode_format_attr (TREE_VALUE (a), &info, 1); +- check_format_info (status, &info, params); +- if (warn_missing_format_attribute && info.first_arg_num == 0 +- && (format_types[info.format_type].flags +- & (int) FMT_FLAG_ARG_CONVERT)) +- { +- tree c; +- for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); +- c; +- c = TREE_CHAIN (c)) +- if (is_attribute_p ("format", TREE_PURPOSE (c)) +- && (decode_format_type (IDENTIFIER_POINTER +- (TREE_VALUE (TREE_VALUE (c)))) +- == info.format_type)) +- break; +- if (c == NULL_TREE) +- { +- /* Check if the current function has a parameter to which +- the format attribute could be attached; if not, it +- can't be a candidate for a format attribute, despite +- the vprintf-like or vscanf-like call. */ +- tree args; +- for (args = DECL_ARGUMENTS (current_function_decl); +- args != 0; +- args = TREE_CHAIN (args)) +- { +- if (TREE_CODE (TREE_TYPE (args)) == POINTER_TYPE +- && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (args))) +- == char_type_node)) +- break; +- } +- if (args != 0) +- warning ("function might be possible candidate for `%s' format attribute", +- format_types[info.format_type].name); +- } +- } +- } +- } +-} +- +-/* This function replaces `warning' inside the printf format checking +- functions. If the `status' parameter is non-NULL, then it is +- dereferenced and set to 1 whenever a warning is caught. Otherwise +- it warns as usual by replicating the innards of the warning +- function from diagnostic.c. */ +-static void +-status_warning (int *status, const char *msgid, ...) +-{ +- diagnostic_info diagnostic ; +- va_list ap; +- +- va_start (ap, msgid); +- +- if (status) +- *status = 1; +- else +- { +- /* This duplicates the warning function behavior. */ +- diagnostic_set_info (&diagnostic, _(msgid), &ap, +- input_location, DK_WARNING); +- report_diagnostic (&diagnostic); +- } +- +- va_end (ap); +-} +- +-/* Variables used by the checking of $ operand number formats. */ +-static char *dollar_arguments_used = NULL; +-static char *dollar_arguments_pointer_p = NULL; +-static int dollar_arguments_alloc = 0; +-static int dollar_arguments_count; +-static int dollar_first_arg_num; +-static int dollar_max_arg_used; +-static int dollar_format_warned; +- +-/* Initialize the checking for a format string that may contain $ +- parameter number specifications; we will need to keep track of whether +- each parameter has been used. FIRST_ARG_NUM is the number of the first +- argument that is a parameter to the format, or 0 for a vprintf-style +- function; PARAMS is the list of arguments starting at this argument. */ +- +-static void +-init_dollar_format_checking (int first_arg_num, tree params) +-{ +- tree oparams = params; +- +- dollar_first_arg_num = first_arg_num; +- dollar_arguments_count = 0; +- dollar_max_arg_used = 0; +- dollar_format_warned = 0; +- if (first_arg_num > 0) +- { +- while (params) +- { +- dollar_arguments_count++; +- params = TREE_CHAIN (params); +- } +- } +- if (dollar_arguments_alloc < dollar_arguments_count) +- { +- if (dollar_arguments_used) +- free (dollar_arguments_used); +- if (dollar_arguments_pointer_p) +- free (dollar_arguments_pointer_p); +- dollar_arguments_alloc = dollar_arguments_count; +- dollar_arguments_used = xmalloc (dollar_arguments_alloc); +- dollar_arguments_pointer_p = xmalloc (dollar_arguments_alloc); +- } +- if (dollar_arguments_alloc) +- { +- memset (dollar_arguments_used, 0, dollar_arguments_alloc); +- if (first_arg_num > 0) +- { +- int i = 0; +- params = oparams; +- while (params) +- { +- dollar_arguments_pointer_p[i] = (TREE_CODE (TREE_TYPE (TREE_VALUE (params))) +- == POINTER_TYPE); +- params = TREE_CHAIN (params); +- i++; +- } +- } +- } +-} +- +- +-/* Look for a decimal number followed by a $ in *FORMAT. If DOLLAR_NEEDED +- is set, it is an error if one is not found; otherwise, it is OK. If +- such a number is found, check whether it is within range and mark that +- numbered operand as being used for later checking. Returns the operand +- number if found and within range, zero if no such number was found and +- this is OK, or -1 on error. PARAMS points to the first operand of the +- format; PARAM_PTR is made to point to the parameter referred to. If +- a $ format is found, *FORMAT is updated to point just after it. */ +- +-static int +-maybe_read_dollar_number (int *status, const char **format, +- int dollar_needed, tree params, tree *param_ptr, +- const format_kind_info *fki) +-{ +- int argnum; +- int overflow_flag; +- const char *fcp = *format; +- if (! ISDIGIT (*fcp)) +- { +- if (dollar_needed) +- { +- status_warning (status, "missing $ operand number in format"); +- return -1; +- } +- else +- return 0; +- } +- argnum = 0; +- overflow_flag = 0; +- while (ISDIGIT (*fcp)) +- { +- int nargnum; +- nargnum = 10 * argnum + (*fcp - '0'); +- if (nargnum < 0 || nargnum / 10 != argnum) +- overflow_flag = 1; +- argnum = nargnum; +- fcp++; +- } +- if (*fcp != '$') +- { +- if (dollar_needed) +- { +- status_warning (status, "missing $ operand number in format"); +- return -1; +- } +- else +- return 0; +- } +- *format = fcp + 1; +- if (pedantic && !dollar_format_warned) +- { +- status_warning (status, +- "%s does not support %%n$ operand number formats", +- C_STD_NAME (STD_EXT)); +- dollar_format_warned = 1; +- } +- if (overflow_flag || argnum == 0 +- || (dollar_first_arg_num && argnum > dollar_arguments_count)) +- { +- status_warning (status, "operand number out of range in format"); +- return -1; +- } +- if (argnum > dollar_max_arg_used) +- dollar_max_arg_used = argnum; +- /* For vprintf-style functions we may need to allocate more memory to +- track which arguments are used. */ +- while (dollar_arguments_alloc < dollar_max_arg_used) +- { +- int nalloc; +- nalloc = 2 * dollar_arguments_alloc + 16; +- dollar_arguments_used = xrealloc (dollar_arguments_used, nalloc); +- dollar_arguments_pointer_p = xrealloc (dollar_arguments_pointer_p, +- nalloc); +- memset (dollar_arguments_used + dollar_arguments_alloc, 0, +- nalloc - dollar_arguments_alloc); +- dollar_arguments_alloc = nalloc; +- } +- if (!(fki->flags & (int) FMT_FLAG_DOLLAR_MULTIPLE) +- && dollar_arguments_used[argnum - 1] == 1) +- { +- dollar_arguments_used[argnum - 1] = 2; +- status_warning (status, +- "format argument %d used more than once in %s format", +- argnum, fki->name); +- } +- else +- dollar_arguments_used[argnum - 1] = 1; +- if (dollar_first_arg_num) +- { +- int i; +- *param_ptr = params; +- for (i = 1; i < argnum && *param_ptr != 0; i++) +- *param_ptr = TREE_CHAIN (*param_ptr); +- +- if (*param_ptr == 0) +- { +- /* This case shouldn't be caught here. */ +- abort (); +- } +- } +- else +- *param_ptr = 0; +- return argnum; +-} +- +- +-/* Finish the checking for a format string that used $ operand number formats +- instead of non-$ formats. We check for unused operands before used ones +- (a serious error, since the implementation of the format function +- can't know what types to pass to va_arg to find the later arguments). +- and for unused operands at the end of the format (if we know how many +- arguments the format had, so not for vprintf). If there were operand +- numbers out of range on a non-vprintf-style format, we won't have reached +- here. If POINTER_GAP_OK, unused arguments are OK if all arguments are +- pointers. */ +- +-static void +-finish_dollar_format_checking (int *status, format_check_results *res, int pointer_gap_ok) +-{ +- int i; +- bool found_pointer_gap = false; +- for (i = 0; i < dollar_max_arg_used; i++) +- { +- if (!dollar_arguments_used[i]) +- { +- if (pointer_gap_ok && (dollar_first_arg_num == 0 +- || dollar_arguments_pointer_p[i])) +- found_pointer_gap = true; +- else +- status_warning (status, "format argument %d unused before used argument %d in $-style format", +- i + 1, dollar_max_arg_used); +- } +- } +- if (found_pointer_gap +- || (dollar_first_arg_num +- && dollar_max_arg_used < dollar_arguments_count)) +- { +- res->number_other--; +- res->number_dollar_extra_args++; +- } +-} +- +- +-/* Retrieve the specification for a format flag. SPEC contains the +- specifications for format flags for the applicable kind of format. +- FLAG is the flag in question. If PREDICATES is NULL, the basic +- spec for that flag must be retrieved and this function aborts if +- it cannot be found. If PREDICATES is not NULL, it is a string listing +- possible predicates for the spec entry; if an entry predicated on any +- of these is found, it is returned, otherwise NULL is returned. */ +- +-static const format_flag_spec * +-get_flag_spec (const format_flag_spec *spec, int flag, const char *predicates) +-{ +- int i; +- for (i = 0; spec[i].flag_char != 0; i++) +- { +- if (spec[i].flag_char != flag) +- continue; +- if (predicates != NULL) +- { +- if (spec[i].predicate != 0 +- && strchr (predicates, spec[i].predicate) != 0) +- return &spec[i]; +- } +- else if (spec[i].predicate == 0) +- return &spec[i]; +- } +- if (predicates == NULL) +- abort (); +- else +- return NULL; +-} +- +- +-/* Check the argument list of a call to printf, scanf, etc. +- INFO points to the function_format_info structure. +- PARAMS is the list of argument values. */ +- +-static void +-check_format_info (int *status, function_format_info *info, tree params) +-{ +- format_check_context format_ctx; +- unsigned HOST_WIDE_INT arg_num; +- tree format_tree; +- format_check_results res; +- /* Skip to format argument. If the argument isn't available, there's +- no work for us to do; prototype checking will catch the problem. */ +- for (arg_num = 1; ; ++arg_num) +- { +- if (params == 0) +- return; +- if (arg_num == info->format_num) +- break; +- params = TREE_CHAIN (params); +- } +- format_tree = TREE_VALUE (params); +- params = TREE_CHAIN (params); +- if (format_tree == 0) +- return; +- +- res.number_non_literal = 0; +- res.number_extra_args = 0; +- res.number_dollar_extra_args = 0; +- res.number_wide = 0; +- res.number_empty = 0; +- res.number_unterminated = 0; +- res.number_other = 0; +- +- format_ctx.res = &res; +- format_ctx.info = info; +- format_ctx.params = params; +- format_ctx.status = status; +- +- check_function_arguments_recurse (check_format_arg, &format_ctx, +- format_tree, arg_num); +- +- if (res.number_non_literal > 0) +- { +- /* Functions taking a va_list normally pass a non-literal format +- string. These functions typically are declared with +- first_arg_num == 0, so avoid warning in those cases. */ +- if (!(format_types[info->format_type].flags & (int) FMT_FLAG_ARG_CONVERT)) +- { +- /* For strftime-like formats, warn for not checking the format +- string; but there are no arguments to check. */ +- if (warn_format_nonliteral) +- status_warning (status, "format not a string literal, format string not checked"); +- } +- else if (info->first_arg_num != 0) +- { +- /* If there are no arguments for the format at all, we may have +- printf (foo) which is likely to be a security hole. */ +- while (arg_num + 1 < info->first_arg_num) +- { +- if (params == 0) +- break; +- params = TREE_CHAIN (params); +- ++arg_num; +- } +- if (params == 0 && (warn_format_nonliteral || warn_format_security)) +- status_warning (status, "format not a string literal and no format arguments"); +- else if (warn_format_nonliteral) +- status_warning (status, "format not a string literal, argument types not checked"); +- } +- } +- +- /* If there were extra arguments to the format, normally warn. However, +- the standard does say extra arguments are ignored, so in the specific +- case where we have multiple leaves (conditional expressions or +- ngettext) allow extra arguments if at least one leaf didn't have extra +- arguments, but was otherwise OK (either non-literal or checked OK). +- If the format is an empty string, this should be counted similarly to the +- case of extra format arguments. */ +- if (res.number_extra_args > 0 && res.number_non_literal == 0 +- && res.number_other == 0 && warn_format_extra_args) +- status_warning (status, "too many arguments for format"); +- if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0 +- && res.number_other == 0 && warn_format_extra_args) +- status_warning (status, "unused arguments in $-style format"); +- if (res.number_empty > 0 && res.number_non_literal == 0 +- && res.number_other == 0 && warn_format_zero_length) +- status_warning (status, "zero-length %s format string", +- format_types[info->format_type].name); +- +- if (res.number_wide > 0) +- status_warning (status, "format is a wide character string"); +- +- if (res.number_unterminated > 0) +- status_warning (status, "unterminated format string"); +-} +- +-/* Callback from check_function_arguments_recurse to check a +- format string. FORMAT_TREE is the format parameter. ARG_NUM +- is the number of the format argument. CTX points to a +- format_check_context. */ +- +-static void +-check_format_arg (void *ctx, tree format_tree, +- unsigned HOST_WIDE_INT arg_num) +-{ +- format_check_context *format_ctx = ctx; +- format_check_results *res = format_ctx->res; +- function_format_info *info = format_ctx->info; +- tree params = format_ctx->params; +- int *status = format_ctx->status; +- +- int format_length; +- HOST_WIDE_INT offset; +- const char *format_chars; +- tree array_size = 0; +- tree array_init; +- +- if (integer_zerop (format_tree)) +- { +- /* Skip to first argument to check, so we can see if this format +- has any arguments (it shouldn't). */ +- while (arg_num + 1 < info->first_arg_num) +- { +- if (params == 0) +- return; +- params = TREE_CHAIN (params); +- ++arg_num; +- } +- +- if (params == 0) +- res->number_other++; +- else +- res->number_extra_args++; +- +- return; +- } +- +- offset = 0; +- if (TREE_CODE (format_tree) == PLUS_EXPR) +- { +- tree arg0, arg1; +- +- arg0 = TREE_OPERAND (format_tree, 0); +- arg1 = TREE_OPERAND (format_tree, 1); +- STRIP_NOPS (arg0); +- STRIP_NOPS (arg1); +- if (TREE_CODE (arg1) == INTEGER_CST) +- format_tree = arg0; +- else if (TREE_CODE (arg0) == INTEGER_CST) +- { +- format_tree = arg1; +- arg1 = arg0; +- } +- else +- { +- res->number_non_literal++; +- return; +- } +- if (!host_integerp (arg1, 0) +- || (offset = tree_low_cst (arg1, 0)) < 0) +- { +- res->number_non_literal++; +- return; +- } +- } +- if (TREE_CODE (format_tree) != ADDR_EXPR) +- { +- res->number_non_literal++; +- return; +- } +- format_tree = TREE_OPERAND (format_tree, 0); +- if (TREE_CODE (format_tree) == VAR_DECL +- && TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE +- && (array_init = decl_constant_value (format_tree)) != format_tree +- && TREE_CODE (array_init) == STRING_CST) +- { +- /* Extract the string constant initializer. Note that this may include +- a trailing NUL character that is not in the array (e.g. +- const char a[3] = "foo";). */ +- array_size = DECL_SIZE_UNIT (format_tree); +- format_tree = array_init; +- } +- if (TREE_CODE (format_tree) != STRING_CST) +- { +- res->number_non_literal++; +- return; +- } +- if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree))) != char_type_node) +- { +- res->number_wide++; +- return; +- } +- format_chars = TREE_STRING_POINTER (format_tree); +- format_length = TREE_STRING_LENGTH (format_tree); +- if (array_size != 0) +- { +- /* Variable length arrays can't be initialized. */ +- if (TREE_CODE (array_size) != INTEGER_CST) +- abort (); +- if (host_integerp (array_size, 0)) +- { +- HOST_WIDE_INT array_size_value = TREE_INT_CST_LOW (array_size); +- if (array_size_value > 0 +- && array_size_value == (int) array_size_value +- && format_length > array_size_value) +- format_length = array_size_value; +- } +- } +- if (offset) +- { +- if (offset >= format_length) +- { +- res->number_non_literal++; +- return; +- } +- format_chars += offset; +- format_length -= offset; +- } +- if (format_length < 1) +- { +- res->number_unterminated++; +- return; +- } +- if (format_length == 1) +- { +- res->number_empty++; +- return; +- } +- if (format_chars[--format_length] != 0) +- { +- res->number_unterminated++; +- return; +- } +- +- /* Skip to first argument to check. */ +- while (arg_num + 1 < info->first_arg_num) +- { +- if (params == 0) +- return; +- params = TREE_CHAIN (params); +- ++arg_num; +- } +- /* Provisionally increment res->number_other; check_format_info_main +- will decrement it if it finds there are extra arguments, but this way +- need not adjust it for every return. */ +- res->number_other++; +- check_format_info_main (status, res, info, format_chars, format_length, +- params, arg_num); +-} +- +- +-/* Do the main part of checking a call to a format function. FORMAT_CHARS +- is the NUL-terminated format string (which at this point may contain +- internal NUL characters); FORMAT_LENGTH is its length (excluding the +- terminating NUL character). ARG_NUM is one less than the number of +- the first format argument to check; PARAMS points to that format +- argument in the list of arguments. */ +- +-static void +-check_format_info_main (int *status, format_check_results *res, +- function_format_info *info, const char *format_chars, +- int format_length, tree params, +- unsigned HOST_WIDE_INT arg_num) +-{ +- const char *orig_format_chars = format_chars; +- tree first_fillin_param = params; +- +- const format_kind_info *fki = &format_types[info->format_type]; +- const format_flag_spec *flag_specs = fki->flag_specs; +- const format_flag_pair *bad_flag_pairs = fki->bad_flag_pairs; +- +- /* -1 if no conversions taking an operand have been found; 0 if one has +- and it didn't use $; 1 if $ formats are in use. */ +- int has_operand_number = -1; +- +- init_dollar_format_checking (info->first_arg_num, first_fillin_param); +- +- while (1) +- { +- int i; +- int suppressed = FALSE; +- const char *length_chars = NULL; +- enum format_lengths length_chars_val = FMT_LEN_none; +- enum format_std_version length_chars_std = STD_C89; +- int format_char; +- tree cur_param; +- tree wanted_type; +- int main_arg_num = 0; +- tree main_arg_params = 0; +- enum format_std_version wanted_type_std; +- const char *wanted_type_name; +- format_wanted_type width_wanted_type; +- format_wanted_type precision_wanted_type; +- format_wanted_type main_wanted_type; +- format_wanted_type *first_wanted_type = NULL; +- format_wanted_type *last_wanted_type = NULL; +- const format_length_info *fli = NULL; +- const format_char_info *fci = NULL; +- char flag_chars[256]; +- int aflag = 0; +- if (*format_chars == 0) +- { +- if (format_chars - orig_format_chars != format_length) +- status_warning (status, "embedded `\\0' in format"); +- if (info->first_arg_num != 0 && params != 0 +- && has_operand_number <= 0) +- { +- res->number_other--; +- res->number_extra_args++; +- } +- if (has_operand_number > 0) +- finish_dollar_format_checking (status, res, fki->flags & (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK); +- return; +- } +- if (*format_chars++ != '%') +- continue; +- if (*format_chars == 0) +- { +- status_warning (status, "spurious trailing `%%' in format"); +- continue; +- } +- if (*format_chars == '%') +- { +- ++format_chars; +- continue; +- } +- flag_chars[0] = 0; +- +- if ((fki->flags & (int) FMT_FLAG_USE_DOLLAR) && has_operand_number != 0) +- { +- /* Possibly read a $ operand number at the start of the format. +- If one was previously used, one is required here. If one +- is not used here, we can't immediately conclude this is a +- format without them, since it could be printf %m or scanf %*. */ +- int opnum; +- opnum = maybe_read_dollar_number (status, &format_chars, 0, +- first_fillin_param, +- &main_arg_params, fki); +- if (opnum == -1) +- return; +- else if (opnum > 0) +- { +- has_operand_number = 1; +- main_arg_num = opnum + info->first_arg_num - 1; +- } +- } +- +- /* Read any format flags, but do not yet validate them beyond removing +- duplicates, since in general validation depends on the rest of +- the format. */ +- while (*format_chars != 0 +- && strchr (fki->flag_chars, *format_chars) != 0) +- { +- const format_flag_spec *s = get_flag_spec (flag_specs, +- *format_chars, NULL); +- if (strchr (flag_chars, *format_chars) != 0) +- { +- status_warning (status, "repeated %s in format", _(s->name)); +- } +- else +- { +- i = strlen (flag_chars); +- flag_chars[i++] = *format_chars; +- flag_chars[i] = 0; +- } +- if (s->skip_next_char) +- { +- ++format_chars; +- if (*format_chars == 0) +- { +- status_warning (status, "missing fill character at end of strfmon format"); +- return; +- } +- } +- ++format_chars; +- } +- +- /* Read any format width, possibly * or *m$. */ +- if (fki->width_char != 0) +- { +- if (fki->width_type != NULL && *format_chars == '*') +- { +- i = strlen (flag_chars); +- flag_chars[i++] = fki->width_char; +- flag_chars[i] = 0; +- /* "...a field width...may be indicated by an asterisk. +- In this case, an int argument supplies the field width..." */ +- ++format_chars; +- if (has_operand_number != 0) +- { +- int opnum; +- opnum = maybe_read_dollar_number (status, &format_chars, +- has_operand_number == 1, +- first_fillin_param, +- ¶ms, fki); +- if (opnum == -1) +- return; +- else if (opnum > 0) +- { +- has_operand_number = 1; +- arg_num = opnum + info->first_arg_num - 1; +- } +- else +- has_operand_number = 0; +- } +- if (info->first_arg_num != 0) +- { +- if (params == 0) +- { +- status_warning (status, "too few arguments for format"); +- return; +- } +- cur_param = TREE_VALUE (params); +- if (has_operand_number <= 0) +- { +- params = TREE_CHAIN (params); +- ++arg_num; +- } +- width_wanted_type.wanted_type = *fki->width_type; +- width_wanted_type.wanted_type_name = NULL; +- width_wanted_type.pointer_count = 0; +- width_wanted_type.char_lenient_flag = 0; +- width_wanted_type.writing_in_flag = 0; +- width_wanted_type.reading_from_flag = 0; +- width_wanted_type.name = _("field width"); +- width_wanted_type.param = cur_param; +- width_wanted_type.arg_num = arg_num; +- width_wanted_type.next = NULL; +- if (last_wanted_type != 0) +- last_wanted_type->next = &width_wanted_type; +- if (first_wanted_type == 0) +- first_wanted_type = &width_wanted_type; +- last_wanted_type = &width_wanted_type; +- } +- } +- else +- { +- /* Possibly read a numeric width. If the width is zero, +- we complain if appropriate. */ +- int non_zero_width_char = FALSE; +- int found_width = FALSE; +- while (ISDIGIT (*format_chars)) +- { +- found_width = TRUE; +- if (*format_chars != '0') +- non_zero_width_char = TRUE; +- ++format_chars; +- } +- if (found_width && !non_zero_width_char && +- (fki->flags & (int) FMT_FLAG_ZERO_WIDTH_BAD)) +- status_warning (status, "zero width in %s format", +- fki->name); +- if (found_width) +- { +- i = strlen (flag_chars); +- flag_chars[i++] = fki->width_char; +- flag_chars[i] = 0; +- } +- } +- } +- +- /* Read any format left precision (must be a number, not *). */ +- if (fki->left_precision_char != 0 && *format_chars == '#') +- { +- ++format_chars; +- i = strlen (flag_chars); +- flag_chars[i++] = fki->left_precision_char; +- flag_chars[i] = 0; +- if (!ISDIGIT (*format_chars)) +- status_warning (status, "empty left precision in %s format", +- fki->name); +- while (ISDIGIT (*format_chars)) +- ++format_chars; +- } +- +- /* Read any format precision, possibly * or *m$. */ +- if (fki->precision_char != 0 && *format_chars == '.') +- { +- ++format_chars; +- i = strlen (flag_chars); +- flag_chars[i++] = fki->precision_char; +- flag_chars[i] = 0; +- if (fki->precision_type != NULL && *format_chars == '*') +- { +- /* "...a...precision...may be indicated by an asterisk. +- In this case, an int argument supplies the...precision." */ +- ++format_chars; +- if (has_operand_number != 0) +- { +- int opnum; +- opnum = maybe_read_dollar_number (status, &format_chars, +- has_operand_number == 1, +- first_fillin_param, +- ¶ms, fki); +- if (opnum == -1) +- return; +- else if (opnum > 0) +- { +- has_operand_number = 1; +- arg_num = opnum + info->first_arg_num - 1; +- } +- else +- has_operand_number = 0; +- } +- if (info->first_arg_num != 0) +- { +- if (params == 0) +- { +- status_warning (status, "too few arguments for format"); +- return; +- } +- cur_param = TREE_VALUE (params); +- if (has_operand_number <= 0) +- { +- params = TREE_CHAIN (params); +- ++arg_num; +- } +- precision_wanted_type.wanted_type = *fki->precision_type; +- precision_wanted_type.wanted_type_name = NULL; +- precision_wanted_type.pointer_count = 0; +- precision_wanted_type.char_lenient_flag = 0; +- precision_wanted_type.writing_in_flag = 0; +- precision_wanted_type.reading_from_flag = 0; +- precision_wanted_type.name = _("field precision"); +- precision_wanted_type.param = cur_param; +- precision_wanted_type.arg_num = arg_num; +- precision_wanted_type.next = NULL; +- if (last_wanted_type != 0) +- last_wanted_type->next = &precision_wanted_type; +- if (first_wanted_type == 0) +- first_wanted_type = &precision_wanted_type; +- last_wanted_type = &precision_wanted_type; +- } +- } +- else +- { +- if (!(fki->flags & (int) FMT_FLAG_EMPTY_PREC_OK) +- && !ISDIGIT (*format_chars)) +- status_warning (status, "empty precision in %s format", +- fki->name); +- while (ISDIGIT (*format_chars)) +- ++format_chars; +- } +- } +- +- /* Read any length modifier, if this kind of format has them. */ +- fli = fki->length_char_specs; +- length_chars = NULL; +- length_chars_val = FMT_LEN_none; +- length_chars_std = STD_C89; +- if (fli) +- { +- while (fli->name != 0 && fli->name[0] != *format_chars) +- fli++; +- if (fli->name != 0) +- { +- format_chars++; +- if (fli->double_name != 0 && fli->name[0] == *format_chars) +- { +- format_chars++; +- length_chars = fli->double_name; +- length_chars_val = fli->double_index; +- length_chars_std = fli->double_std; +- } +- else +- { +- length_chars = fli->name; +- length_chars_val = fli->index; +- length_chars_std = fli->std; +- } +- i = strlen (flag_chars); +- flag_chars[i++] = fki->length_code_char; +- flag_chars[i] = 0; +- } +- if (pedantic) +- { +- /* Warn if the length modifier is non-standard. */ +- if (ADJ_STD (length_chars_std) > C_STD_VER) +- status_warning (status, "%s does not support the `%s' %s length modifier", +- C_STD_NAME (length_chars_std), length_chars, +- fki->name); +- } +- } +- +- /* Read any modifier (strftime E/O). */ +- if (fki->modifier_chars != NULL) +- { +- while (*format_chars != 0 +- && strchr (fki->modifier_chars, *format_chars) != 0) +- { +- if (strchr (flag_chars, *format_chars) != 0) +- { +- const format_flag_spec *s = get_flag_spec (flag_specs, +- *format_chars, NULL); +- status_warning (status, "repeated %s in format", _(s->name)); +- } +- else +- { +- i = strlen (flag_chars); +- flag_chars[i++] = *format_chars; +- flag_chars[i] = 0; +- } +- ++format_chars; +- } +- } +- +- /* Handle the scanf allocation kludge. */ +- if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE) +- { +- if (*format_chars == 'a' && !flag_isoc99) +- { +- if (format_chars[1] == 's' || format_chars[1] == 'S' +- || format_chars[1] == '[') +- { +- /* `a' is used as a flag. */ +- i = strlen (flag_chars); +- flag_chars[i++] = 'a'; +- flag_chars[i] = 0; +- format_chars++; +- } +- } +- } +- +- format_char = *format_chars; +- if (format_char == 0 +- || (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK) +- && format_char == '%')) +- { +- status_warning (status, "conversion lacks type at end of format"); +- continue; +- } +- format_chars++; +- fci = fki->conversion_specs; +- while (fci->format_chars != 0 +- && strchr (fci->format_chars, format_char) == 0) +- ++fci; +- if (fci->format_chars == 0) +- { +- if (ISGRAPH(format_char)) +- status_warning (status, "unknown conversion type character `%c' in format", +- format_char); +- else +- status_warning (status, "unknown conversion type character 0x%x in format", +- format_char); +- continue; +- } +- if (pedantic) +- { +- if (ADJ_STD (fci->std) > C_STD_VER) +- status_warning (status, "%s does not support the `%%%c' %s format", +- C_STD_NAME (fci->std), format_char, fki->name); +- } +- +- /* Validate the individual flags used, removing any that are invalid. */ +- { +- int d = 0; +- for (i = 0; flag_chars[i] != 0; i++) +- { +- const format_flag_spec *s = get_flag_spec (flag_specs, +- flag_chars[i], NULL); +- flag_chars[i - d] = flag_chars[i]; +- if (flag_chars[i] == fki->length_code_char) +- continue; +- if (strchr (fci->flag_chars, flag_chars[i]) == 0) +- { +- status_warning (status, "%s used with `%%%c' %s format", +- _(s->name), format_char, fki->name); +- d++; +- continue; +- } +- if (pedantic) +- { +- const format_flag_spec *t; +- if (ADJ_STD (s->std) > C_STD_VER) +- status_warning (status, "%s does not support %s", +- C_STD_NAME (s->std), _(s->long_name)); +- t = get_flag_spec (flag_specs, flag_chars[i], fci->flags2); +- if (t != NULL && ADJ_STD (t->std) > ADJ_STD (s->std)) +- { +- const char *long_name = (t->long_name != NULL +- ? t->long_name +- : s->long_name); +- if (ADJ_STD (t->std) > C_STD_VER) +- status_warning (status, "%s does not support %s with the `%%%c' %s format", +- C_STD_NAME (t->std), _(long_name), +- format_char, fki->name); +- } +- } +- } +- flag_chars[i - d] = 0; +- } +- +- if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE) +- && strchr (flag_chars, 'a') != 0) +- aflag = 1; +- +- if (fki->suppression_char +- && strchr (flag_chars, fki->suppression_char) != 0) +- suppressed = 1; +- +- /* Validate the pairs of flags used. */ +- for (i = 0; bad_flag_pairs[i].flag_char1 != 0; i++) +- { +- const format_flag_spec *s, *t; +- if (strchr (flag_chars, bad_flag_pairs[i].flag_char1) == 0) +- continue; +- if (strchr (flag_chars, bad_flag_pairs[i].flag_char2) == 0) +- continue; +- if (bad_flag_pairs[i].predicate != 0 +- && strchr (fci->flags2, bad_flag_pairs[i].predicate) == 0) +- continue; +- s = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char1, NULL); +- t = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char2, NULL); +- if (bad_flag_pairs[i].ignored) +- { +- if (bad_flag_pairs[i].predicate != 0) +- status_warning (status, "%s ignored with %s and `%%%c' %s format", +- _(s->name), _(t->name), format_char, +- fki->name); +- else +- status_warning (status, "%s ignored with %s in %s format", +- _(s->name), _(t->name), fki->name); +- } +- else +- { +- if (bad_flag_pairs[i].predicate != 0) +- status_warning (status, "use of %s and %s together with `%%%c' %s format", +- _(s->name), _(t->name), format_char, +- fki->name); +- else +- status_warning (status, "use of %s and %s together in %s format", +- _(s->name), _(t->name), fki->name); +- } +- } +- +- /* Give Y2K warnings. */ +- if (warn_format_y2k) +- { +- int y2k_level = 0; +- if (strchr (fci->flags2, '4') != 0) +- if (strchr (flag_chars, 'E') != 0) +- y2k_level = 3; +- else +- y2k_level = 2; +- else if (strchr (fci->flags2, '3') != 0) +- y2k_level = 3; +- else if (strchr (fci->flags2, '2') != 0) +- y2k_level = 2; +- if (y2k_level == 3) +- status_warning (status, "`%%%c' yields only last 2 digits of year in some locales", +- format_char); +- else if (y2k_level == 2) +- status_warning (status, "`%%%c' yields only last 2 digits of year", format_char); +- } +- +- if (strchr (fci->flags2, '[') != 0) +- { +- /* Skip over scan set, in case it happens to have '%' in it. */ +- if (*format_chars == '^') +- ++format_chars; +- /* Find closing bracket; if one is hit immediately, then +- it's part of the scan set rather than a terminator. */ +- if (*format_chars == ']') +- ++format_chars; +- while (*format_chars && *format_chars != ']') +- ++format_chars; +- if (*format_chars != ']') +- /* The end of the format string was reached. */ +- status_warning (status, "no closing `]' for `%%[' format"); +- } +- +- wanted_type = 0; +- wanted_type_name = 0; +- if (fki->flags & (int) FMT_FLAG_ARG_CONVERT) +- { +- wanted_type = (fci->types[length_chars_val].type +- ? *fci->types[length_chars_val].type : 0); +- wanted_type_name = fci->types[length_chars_val].name; +- wanted_type_std = fci->types[length_chars_val].std; +- if (wanted_type == 0) +- { +- status_warning (status, "use of `%s' length modifier with `%c' type character", +- length_chars, format_char); +- /* Heuristic: skip one argument when an invalid length/type +- combination is encountered. */ +- arg_num++; +- if (params == 0) +- { +- status_warning (status, "too few arguments for format"); +- return; +- } +- params = TREE_CHAIN (params); +- continue; +- } +- else if (pedantic +- /* Warn if non-standard, provided it is more non-standard +- than the length and type characters that may already +- have been warned for. */ +- && ADJ_STD (wanted_type_std) > ADJ_STD (length_chars_std) +- && ADJ_STD (wanted_type_std) > ADJ_STD (fci->std)) +- { +- if (ADJ_STD (wanted_type_std) > C_STD_VER) +- status_warning (status, "%s does not support the `%%%s%c' %s format", +- C_STD_NAME (wanted_type_std), length_chars, +- format_char, fki->name); +- } +- } +- +- /* Finally. . .check type of argument against desired type! */ +- if (info->first_arg_num == 0) +- continue; +- if ((fci->pointer_count == 0 && wanted_type == void_type_node) +- || suppressed) +- { +- if (main_arg_num != 0) +- { +- if (suppressed) +- status_warning (status, "operand number specified with suppressed assignment"); +- else +- status_warning (status, "operand number specified for format taking no argument"); +- } +- } +- else +- { +- if (main_arg_num != 0) +- { +- arg_num = main_arg_num; +- params = main_arg_params; +- } +- else +- { +- ++arg_num; +- if (has_operand_number > 0) +- { +- status_warning (status, "missing $ operand number in format"); +- return; +- } +- else +- has_operand_number = 0; +- if (params == 0) +- { +- status_warning (status, "too few arguments for format"); +- return; +- } +- } +- cur_param = TREE_VALUE (params); +- params = TREE_CHAIN (params); +- main_wanted_type.wanted_type = wanted_type; +- main_wanted_type.wanted_type_name = wanted_type_name; +- main_wanted_type.pointer_count = fci->pointer_count + aflag; +- main_wanted_type.char_lenient_flag = 0; +- if (strchr (fci->flags2, 'c') != 0) +- main_wanted_type.char_lenient_flag = 1; +- main_wanted_type.writing_in_flag = 0; +- main_wanted_type.reading_from_flag = 0; +- if (aflag) +- main_wanted_type.writing_in_flag = 1; +- else +- { +- if (strchr (fci->flags2, 'W') != 0) +- main_wanted_type.writing_in_flag = 1; +- if (strchr (fci->flags2, 'R') != 0) +- main_wanted_type.reading_from_flag = 1; +- } +- main_wanted_type.name = NULL; +- main_wanted_type.param = cur_param; +- main_wanted_type.arg_num = arg_num; +- main_wanted_type.next = NULL; +- if (last_wanted_type != 0) +- last_wanted_type->next = &main_wanted_type; +- if (first_wanted_type == 0) +- first_wanted_type = &main_wanted_type; +- last_wanted_type = &main_wanted_type; +- } +- +- if (first_wanted_type != 0) +- check_format_types (status, first_wanted_type); +- +- } +-} +- +- +-/* Check the argument types from a single format conversion (possibly +- including width and precision arguments). */ +-static void +-check_format_types (int *status, format_wanted_type *types) +-{ +- for (; types != 0; types = types->next) +- { +- tree cur_param; +- tree cur_type; +- tree orig_cur_type; +- tree wanted_type; +- int arg_num; +- int i; +- int char_type_flag; +- cur_param = types->param; +- cur_type = TREE_TYPE (cur_param); +- if (cur_type == error_mark_node) +- continue; +- char_type_flag = 0; +- wanted_type = types->wanted_type; +- arg_num = types->arg_num; +- +- /* The following should not occur here. */ +- if (wanted_type == 0) +- abort (); +- if (wanted_type == void_type_node && types->pointer_count == 0) +- abort (); +- +- if (types->pointer_count == 0) +- wanted_type = (*lang_hooks.types.type_promotes_to) (wanted_type); +- +- STRIP_NOPS (cur_param); +- +- /* Check the types of any additional pointer arguments +- that precede the "real" argument. */ +- for (i = 0; i < types->pointer_count; ++i) +- { +- if (TREE_CODE (cur_type) == POINTER_TYPE) +- { +- cur_type = TREE_TYPE (cur_type); +- if (cur_type == error_mark_node) +- break; +- +- /* Check for writing through a NULL pointer. */ +- if (types->writing_in_flag +- && i == 0 +- && cur_param != 0 +- && integer_zerop (cur_param)) +- status_warning (status, +- "writing through null pointer (arg %d)", +- arg_num); +- +- /* Check for reading through a NULL pointer. */ +- if (types->reading_from_flag +- && i == 0 +- && cur_param != 0 +- && integer_zerop (cur_param)) +- status_warning (status, +- "reading through null pointer (arg %d)", +- arg_num); +- +- if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR) +- cur_param = TREE_OPERAND (cur_param, 0); +- else +- cur_param = 0; +- +- /* See if this is an attempt to write into a const type with +- scanf or with printf "%n". Note: the writing in happens +- at the first indirection only, if for example +- void * const * is passed to scanf %p; passing +- const void ** is simply passing an incompatible type. */ +- if (types->writing_in_flag +- && i == 0 +- && (TYPE_READONLY (cur_type) +- || (cur_param != 0 +- && (TREE_CODE_CLASS (TREE_CODE (cur_param)) == 'c' +- || (DECL_P (cur_param) +- && TREE_READONLY (cur_param)))))) +- status_warning (status, "writing into constant object (arg %d)", arg_num); +- +- /* If there are extra type qualifiers beyond the first +- indirection, then this makes the types technically +- incompatible. */ +- if (i > 0 +- && pedantic +- && (TYPE_READONLY (cur_type) +- || TYPE_VOLATILE (cur_type) +- || TYPE_RESTRICT (cur_type))) +- status_warning (status, "extra type qualifiers in format argument (arg %d)", +- arg_num); +- +- } +- else +- { +- if (types->pointer_count == 1) +- status_warning (status, "format argument is not a pointer (arg %d)", arg_num); +- else +- status_warning (status, "format argument is not a pointer to a pointer (arg %d)", arg_num); +- break; +- } +- } +- +- if (i < types->pointer_count) +- continue; +- +- orig_cur_type = cur_type; +- cur_type = TYPE_MAIN_VARIANT (cur_type); +- +- /* Check whether the argument type is a character type. This leniency +- only applies to certain formats, flagged with 'c'. +- */ +- if (types->char_lenient_flag) +- char_type_flag = (cur_type == char_type_node +- || cur_type == signed_char_type_node +- || cur_type == unsigned_char_type_node); +- +- /* Check the type of the "real" argument, if there's a type we want. */ +- if (wanted_type == cur_type) +- continue; +- /* If we want `void *', allow any pointer type. +- (Anything else would already have got a warning.) +- With -pedantic, only allow pointers to void and to character +- types. */ +- if (wanted_type == void_type_node +- && (!pedantic || (i == 1 && char_type_flag))) +- continue; +- /* Don't warn about differences merely in signedness, unless +- -pedantic. With -pedantic, warn if the type is a pointer +- target and not a character type, and for character types at +- a second level of indirection. */ +- if (TREE_CODE (wanted_type) == INTEGER_TYPE +- && TREE_CODE (cur_type) == INTEGER_TYPE +- && (! pedantic || i == 0 || (i == 1 && char_type_flag)) +- && (TREE_UNSIGNED (wanted_type) +- ? wanted_type == c_common_unsigned_type (cur_type) +- : wanted_type == c_common_signed_type (cur_type))) +- continue; +- /* Likewise, "signed char", "unsigned char" and "char" are +- equivalent but the above test won't consider them equivalent. */ +- if (wanted_type == char_type_node +- && (! pedantic || i < 2) +- && char_type_flag) +- continue; +- /* Now we have a type mismatch. */ +- { +- const char *this; +- const char *that; +- tree tmp; +- +- tmp = TYPE_NAME (wanted_type); +- if (TREE_CODE (tmp) == TYPE_DECL) +- tmp = DECL_NAME (tmp); +- this = IDENTIFIER_POINTER (tmp); +- +- that = 0; +- if (TYPE_NAME (orig_cur_type) != 0 +- && TREE_CODE (orig_cur_type) != INTEGER_TYPE +- && !(TREE_CODE (orig_cur_type) == POINTER_TYPE +- && TREE_CODE (TREE_TYPE (orig_cur_type)) == INTEGER_TYPE)) +- { +- tmp = TYPE_NAME (orig_cur_type); +- if (TREE_CODE (tmp) == TYPE_DECL) +- tmp = DECL_NAME (tmp); +- if (tmp) +- that = IDENTIFIER_POINTER (tmp); +- } +- +- /* A nameless type can't possibly match what the format wants. +- So there will be a warning for it. +- Make up a string to describe vaguely what it is. */ +- if (that == 0) +- { +- if (TREE_CODE (orig_cur_type) == POINTER_TYPE) +- that = _("pointer"); +- else +- that = _("different type"); +- } +- +- /* Make the warning better in case of mismatch of int vs long. */ +- if (TREE_CODE (orig_cur_type) == INTEGER_TYPE +- && TREE_CODE (wanted_type) == INTEGER_TYPE +- && TYPE_PRECISION (orig_cur_type) == TYPE_PRECISION (wanted_type) +- && TYPE_NAME (orig_cur_type) != 0 +- && TREE_CODE (TYPE_NAME (orig_cur_type)) == TYPE_DECL) +- that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (orig_cur_type))); +- +- if (strcmp (this, that) != 0) +- { +- /* There may be a better name for the format, e.g. size_t, +- but we should allow for programs with a perverse typedef +- making size_t something other than what the compiler +- thinks. */ +- if (types->wanted_type_name != 0 +- && strcmp (types->wanted_type_name, that) != 0) +- this = types->wanted_type_name; +- if (types->name != 0) +- status_warning (status, "%s is not type %s (arg %d)", types->name, this, +- arg_num); +- else +- status_warning (status, "%s format, %s arg (arg %d)", this, that, arg_num); +- } +- } +- } +-} +- +-/* Given a format_char_info array FCI, and a character C, this function +- returns the index into the conversion_specs where that specifier's +- data is located. If the character isn't found it aborts. */ +-static unsigned int +-find_char_info_specifier_index (const format_char_info *fci, int c) +-{ +- unsigned int i = 0; +- +- while (fci->format_chars) +- { +- if (strchr (fci->format_chars, c)) +- return i; +- i++; fci++; +- } +- +- /* We shouldn't be looking for a non-existent specifier. */ +- abort (); +-} +- +-/* Given a format_length_info array FLI, and a character C, this +- function returns the index into the conversion_specs where that +- modifier's data is located. If the character isn't found it +- aborts. */ +-static unsigned int +-find_length_info_modifier_index (const format_length_info *fli, int c) +-{ +- unsigned int i = 0; +- +- while (fli->name) +- { +- if (strchr (fli->name, c)) +- return i; +- i++; fli++; +- } +- +- /* We shouldn't be looking for a non-existent modifier. */ +- abort (); +-} +- +-/* Determine the type of HOST_WIDE_INT in the code being compiled for +- use in GCC's __asm_fprintf__ custom format attribute. You must +- have set dynamic_format_types before calling this function. */ +-static void +-init_dynamic_asm_fprintf_info (void) +-{ +- static tree hwi; +- +- if (!hwi) +- { +- format_length_info *new_asm_fprintf_length_specs; +- unsigned int i; +- +- /* Find the underlying type for HOST_WIDE_INT. For the %w +- length modifier to work, one must have issued: "typedef +- HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code +- prior to using that modifier. */ +- hwi = maybe_get_identifier ("__gcc_host_wide_int__"); +- if (!hwi) +- { +- error ("'__gcc_host_wide_int__' is not defined as a type"); +- return; +- } +- hwi = identifier_global_value (hwi); +- if (!hwi || TREE_CODE (hwi) != TYPE_DECL) +- { +- error ("'__gcc_host_wide_int__' is not defined as a type"); +- return; +- } +- hwi = DECL_ORIGINAL_TYPE (hwi); +- if (!hwi) +- abort (); +- if (hwi != long_integer_type_node && hwi != long_long_integer_type_node) +- { +- error ("'__gcc_host_wide_int__' is not defined as 'long'" +- " or 'long long'"); +- return; +- } +- +- /* Create a new (writable) copy of asm_fprintf_length_specs. */ +- new_asm_fprintf_length_specs = xmemdup (asm_fprintf_length_specs, +- sizeof (asm_fprintf_length_specs), +- sizeof (asm_fprintf_length_specs)); +- +- /* HOST_WIDE_INT must be one of 'long' or 'long long'. */ +- i = find_length_info_modifier_index (new_asm_fprintf_length_specs, 'w'); +- if (hwi == long_integer_type_node) +- new_asm_fprintf_length_specs[i].index = FMT_LEN_l; +- else if (hwi == long_long_integer_type_node) +- new_asm_fprintf_length_specs[i].index = FMT_LEN_ll; +- else +- abort (); +- +- /* Assign the new data for use. */ +- dynamic_format_types[asm_fprintf_format_type].length_char_specs = +- new_asm_fprintf_length_specs; +- } +-} +- +-/* Determine the types of "tree" and "location_t" in the code being +- compiled for use in GCC's diagnostic custom format attributes. You +- must have set dynamic_format_types before calling this function. */ +-static void +-init_dynamic_diag_info (void) +-{ +- static tree t, loc, hwi; +- +- if (!loc || !t || !hwi) +- { +- static format_char_info *diag_fci, *cdiag_fci, *cxxdiag_fci; +- static format_length_info *diag_ls; +- unsigned int i; +- +- /* For the GCC-diagnostics custom format specifiers to work, one +- must have declared `tree' and/or `location_t' prior to using +- those attributes. If we haven't seen these declarations then +- you shouldn't use the specifiers requiring these types. +- However we don't force a hard ICE because we may see only one +- or the other type. */ +- if ((loc = maybe_get_identifier ("location_t"))) +- { +- loc = identifier_global_value (loc); +- if (loc) +- { +- if (TREE_CODE (loc) != TYPE_DECL) +- { +- error ("'location_t' is not defined as a type"); +- loc = 0; +- } +- else +- loc = TREE_TYPE (loc); +- } +- } +- +- /* We need to grab the underlying `union tree_node' so peek into +- an extra type level. */ +- if ((t = maybe_get_identifier ("tree"))) +- { +- t = identifier_global_value (t); +- if (t) +- { +- if (TREE_CODE (t) != TYPE_DECL) +- { +- error ("'tree' is not defined as a type"); +- t = 0; +- } +- else if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE) +- { +- error ("'tree' is not defined as a pointer type"); +- t = 0; +- } +- else +- t = TREE_TYPE (TREE_TYPE (t)); +- } +- } +- +- /* Find the underlying type for HOST_WIDE_INT. For the %w +- length modifier to work, one must have issued: "typedef +- HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code +- prior to using that modifier. */ +- if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__"))) +- { +- hwi = identifier_global_value (hwi); +- if (hwi) +- { +- if (TREE_CODE (hwi) != TYPE_DECL) +- { +- error ("'__gcc_host_wide_int__' is not defined as a type"); +- hwi = 0; +- } +- else +- { +- hwi = DECL_ORIGINAL_TYPE (hwi); +- if (!hwi) +- abort (); +- if (hwi != long_integer_type_node +- && hwi != long_long_integer_type_node) +- { +- error ("'__gcc_host_wide_int__' is not defined" +- " as 'long' or 'long long'"); +- hwi = 0; +- } +- } +- } +- } +- +- /* Assign the new data for use. */ +- +- /* All the GCC diag formats use the same length specs. */ +- if (! diag_ls) +- dynamic_format_types[gcc_diag_format_type].length_char_specs = +- dynamic_format_types[gcc_cdiag_format_type].length_char_specs = +- dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs = +- diag_ls = xmemdup (gcc_diag_length_specs, +- sizeof (gcc_diag_length_specs), +- sizeof (gcc_diag_length_specs)); +- if (hwi) +- { +- /* HOST_WIDE_INT must be one of 'long' or 'long long'. */ +- i = find_length_info_modifier_index (diag_ls, 'w'); +- if (hwi == long_integer_type_node) +- diag_ls[i].index = FMT_LEN_l; +- else if (hwi == long_long_integer_type_node) +- diag_ls[i].index = FMT_LEN_ll; +- else +- abort (); +- } +- +- /* Handle the __gcc_diag__ format specifics. */ +- if (! diag_fci) +- dynamic_format_types[gcc_diag_format_type].conversion_specs = +- diag_fci = xmemdup (gcc_diag_char_table, +- sizeof(gcc_diag_char_table), +- sizeof(gcc_diag_char_table)); +- if (loc) +- { +- i = find_char_info_specifier_index (diag_fci, 'H'); +- diag_fci[i].types[0].type = &loc; +- diag_fci[i].pointer_count = 1; +- } +- if (t) +- { +- i = find_char_info_specifier_index (diag_fci, 'J'); +- diag_fci[i].types[0].type = &t; +- diag_fci[i].pointer_count = 1; +- } +- +- /* Handle the __gcc_cdiag__ format specifics. */ +- if (! cdiag_fci) +- dynamic_format_types[gcc_cdiag_format_type].conversion_specs = +- cdiag_fci = xmemdup (gcc_cdiag_char_table, +- sizeof(gcc_cdiag_char_table), +- sizeof(gcc_cdiag_char_table)); +- if (loc) +- { +- i = find_char_info_specifier_index (cdiag_fci, 'H'); +- cdiag_fci[i].types[0].type = &loc; +- cdiag_fci[i].pointer_count = 1; +- } +- if (t) +- { +- /* All specifiers taking a tree share the same struct. */ +- i = find_char_info_specifier_index (cdiag_fci, 'D'); +- cdiag_fci[i].types[0].type = &t; +- cdiag_fci[i].pointer_count = 1; +- i = find_char_info_specifier_index (cdiag_fci, 'J'); +- cdiag_fci[i].types[0].type = &t; +- cdiag_fci[i].pointer_count = 1; +- } +- +- /* Handle the __gcc_cxxdiag__ format specifics. */ +- if (! cxxdiag_fci) +- dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs = +- cxxdiag_fci = xmemdup (gcc_cxxdiag_char_table, +- sizeof(gcc_cxxdiag_char_table), +- sizeof(gcc_cxxdiag_char_table)); +- if (loc) +- { +- i = find_char_info_specifier_index (cxxdiag_fci, 'H'); +- cxxdiag_fci[i].types[0].type = &loc; +- cxxdiag_fci[i].pointer_count = 1; +- } +- if (t) +- { +- /* All specifiers taking a tree share the same struct. */ +- i = find_char_info_specifier_index (cxxdiag_fci, 'D'); +- cxxdiag_fci[i].types[0].type = &t; +- cxxdiag_fci[i].pointer_count = 1; +- i = find_char_info_specifier_index (cxxdiag_fci, 'J'); +- cxxdiag_fci[i].types[0].type = &t; +- cxxdiag_fci[i].pointer_count = 1; +- } +- } +-} +- +-/* Handle a "format" attribute; arguments as in +- struct attribute_spec.handler. */ +-tree +-handle_format_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, +- int flags, bool *no_add_attrs) +-{ +- tree type = *node; +- function_format_info info; +- tree argument; +- +- if (!decode_format_attr (args, &info, 0)) +- { +- *no_add_attrs = true; +- return NULL_TREE; +- } +- +- argument = TYPE_ARG_TYPES (type); +- if (argument) +- { +- if (!check_format_string (argument, info.format_num, flags, +- no_add_attrs)) +- return NULL_TREE; +- +- if (info.first_arg_num != 0) +- { +- unsigned HOST_WIDE_INT arg_num = 1; +- +- /* Verify that first_arg_num points to the last arg, +- the ... */ +- while (argument) +- arg_num++, argument = TREE_CHAIN (argument); +- +- if (arg_num != info.first_arg_num) +- { +- if (!(flags & (int) ATTR_FLAG_BUILT_IN)) +- error ("args to be formatted is not '...'"); +- *no_add_attrs = true; +- return NULL_TREE; +- } +- } +- } +- +- if (info.format_type == strftime_format_type && info.first_arg_num != 0) +- { +- error ("strftime formats cannot format arguments"); +- *no_add_attrs = true; +- return NULL_TREE; +- } +- +- /* If this is a custom GCC-internal format type, we have to +- initialize certain bits a runtime. */ +- if (info.format_type == asm_fprintf_format_type +- || info.format_type == gcc_diag_format_type +- || info.format_type == gcc_cdiag_format_type +- || info.format_type == gcc_cxxdiag_format_type) +- { +- /* Our first time through, we have to make sure that our +- format_type data is allocated dynamically and is modifiable. */ +- if (!dynamic_format_types) +- format_types = dynamic_format_types = +- xmemdup (format_types_orig, sizeof (format_types_orig), +- sizeof (format_types_orig)); +- +- /* If this is format __asm_fprintf__, we have to initialize +- GCC's notion of HOST_WIDE_INT for checking %wd. */ +- if (info.format_type == asm_fprintf_format_type) +- init_dynamic_asm_fprintf_info(); +- /* If this is one of the diagnostic attributes, then we have to +- initialize `location_t' and `tree' at runtime. */ +- else if (info.format_type == gcc_diag_format_type +- || info.format_type == gcc_cdiag_format_type +- || info.format_type == gcc_cxxdiag_format_type) +- init_dynamic_diag_info(); +- else +- abort(); +- } +- +- return NULL_TREE; +-} +diff -ruN gcc-3.4.5-20060117-1/gcc/c-incpath.c.orig gcc-3.4.5-20060117-1-winelf/gcc/c-incpath.c.orig +--- gcc-3.4.5-20060117-1/gcc/c-incpath.c.orig 2004-05-31 03:37:47.000000000 -0700 ++++ gcc-3.4.5-20060117-1-winelf/gcc/c-incpath.c.orig 1969-12-31 16:00:00.000000000 -0800 +@@ -1,364 +0,0 @@ +-/* Set up combined include path chain for the preprocessor. +- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +- +- Broken out of cppinit.c and cppfiles.c and rewritten Mar 2003. +- +-This program is free software; you can redistribute it and/or modify it +-under the terms of the GNU General Public License as published by the +-Free Software Foundation; either version 2, or (at your option) any +-later version. +- +-This program is distributed in the hope that it will be useful, +-but WITHOUT ANY WARRANTY; without even the implied warranty of +-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-GNU General Public License for more details. +- +-You should have received a copy of the GNU General Public License +-along with this program; if not, write to the Free Software +-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +- +-#include "config.h" +-#include "system.h" +-#include "coretypes.h" +-#include "tm.h" +-#include "cpplib.h" +-#include "prefix.h" +-#include "intl.h" +-#include "c-incpath.h" +-#include "cppdefault.h" +- +-/* Windows does not natively support inodes, and neither does MSDOS. +- Cygwin's emulation can generate non-unique inodes, so don't use it. +- VMS has non-numeric inodes. */ +-#ifdef VMS +-# define INO_T_EQ(A, B) (!memcmp (&(A), &(B), sizeof (A))) +-# define INO_T_COPY(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof (SRC)) +-#else +-# if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__ +-# define INO_T_EQ(A, B) 0 +-# else +-# define INO_T_EQ(A, B) ((A) == (B)) +-# endif +-# define INO_T_COPY(DEST, SRC) (DEST) = (SRC) +-#endif +- +-static void add_env_var_paths (const char *, int); +-static void add_standard_paths (const char *, const char *, int); +-static void free_path (struct cpp_dir *, int); +-static void merge_include_chains (cpp_reader *, int); +-static struct cpp_dir *remove_duplicates (cpp_reader *, struct cpp_dir *, +- struct cpp_dir *, +- struct cpp_dir *, int); +- +-/* Include chains heads and tails. */ +-static struct cpp_dir *heads[4]; +-static struct cpp_dir *tails[4]; +-static bool quote_ignores_source_dir; +-enum { REASON_QUIET = 0, REASON_NOENT, REASON_DUP, REASON_DUP_SYS }; +- +-/* Free an element of the include chain, possibly giving a reason. */ +-static void +-free_path (struct cpp_dir *path, int reason) +-{ +- switch (reason) +- { +- case REASON_DUP: +- case REASON_DUP_SYS: +- fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"), path->name); +- if (reason == REASON_DUP_SYS) +- fprintf (stderr, +- _(" as it is a non-system directory that duplicates a system directory\n")); +- break; +- +- case REASON_NOENT: +- fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"), +- path->name); +- break; +- +- case REASON_QUIET: +- default: +- break; +- } +- +- free (path->name); +- free (path); +-} +- +-/* Read ENV_VAR for a PATH_SEPARATOR-separated list of file names; and +- append all the names to the search path CHAIN. */ +-static void +-add_env_var_paths (const char *env_var, int chain) +-{ +- char *p, *q, *path; +- +- GET_ENVIRONMENT (q, env_var); +- +- if (!q) +- return; +- +- for (p = q; *q; p = q + 1) +- { +- q = p; +- while (*q != 0 && *q != PATH_SEPARATOR) +- q++; +- +- if (p == q) +- path = xstrdup ("."); +- else +- { +- path = xmalloc (q - p + 1); +- memcpy (path, p, q - p); +- path[q - p] = '\0'; +- } +- +- add_path (path, chain, chain == SYSTEM); +- } +-} +- +-/* Append the standard include chain defined in cppdefault.c. */ +-static void +-add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc) +-{ +- const struct default_include *p; +- size_t len; +- +- if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0) +- { +- /* Look for directories that start with the standard prefix. +- "Translate" them, ie. replace /usr/local/lib/gcc... with +- IPREFIX and search them first. */ +- for (p = cpp_include_defaults; p->fname; p++) +- { +- if (!p->cplusplus || cxx_stdinc) +- { +- /* Should we be translating sysrooted dirs too? Assume +- that iprefix and sysroot are mutually exclusive, for +- now. */ +- if (sysroot && p->add_sysroot) +- continue; +- if (!strncmp (p->fname, cpp_GCC_INCLUDE_DIR, len)) +- { +- char *str = concat (iprefix, p->fname + len, NULL); +- add_path (str, SYSTEM, p->cxx_aware); +- } +- } +- } +- } +- +- for (p = cpp_include_defaults; p->fname; p++) +- { +- if (!p->cplusplus || cxx_stdinc) +- { +- char *str; +- +- /* Should this directory start with the sysroot? */ +- if (sysroot && p->add_sysroot) +- str = concat (sysroot, p->fname, NULL); +- else +- str = update_path (p->fname, p->component); +- +- add_path (str, SYSTEM, p->cxx_aware); +- } +- } +-} +- +-/* For each duplicate path in chain HEAD, keep just the first one. +- Remove each path in chain HEAD that also exists in chain SYSTEM. +- Set the NEXT pointer of the last path in the resulting chain to +- JOIN, unless it duplicates JOIN in which case the last path is +- removed. Return the head of the resulting chain. Any of HEAD, +- JOIN and SYSTEM can be NULL. */ +-static struct cpp_dir * +-remove_duplicates (cpp_reader *pfile, struct cpp_dir *head, +- struct cpp_dir *system, struct cpp_dir *join, +- int verbose) +-{ +- struct cpp_dir **pcur, *tmp, *cur; +- struct stat st; +- +- for (pcur = &head; *pcur; ) +- { +- int reason = REASON_QUIET; +- +- cur = *pcur; +- +- if (stat (cur->name, &st)) +- { +- /* Dirs that don't exist are silently ignored, unless verbose. */ +- if (errno != ENOENT) +- cpp_errno (pfile, CPP_DL_ERROR, cur->name); +- else +- reason = REASON_NOENT; +- } +- else if (!S_ISDIR (st.st_mode)) +- cpp_error_with_line (pfile, CPP_DL_ERROR, 0, 0, +- "%s: not a directory", cur->name); +- else +- { +- INO_T_COPY (cur->ino, st.st_ino); +- cur->dev = st.st_dev; +- +- /* Remove this one if it is in the system chain. */ +- reason = REASON_DUP_SYS; +- for (tmp = system; tmp; tmp = tmp->next) +- if (INO_T_EQ (tmp->ino, cur->ino) && tmp->dev == cur->dev) +- break; +- +- if (!tmp) +- { +- /* Duplicate of something earlier in the same chain? */ +- reason = REASON_DUP; +- for (tmp = head; tmp != cur; tmp = tmp->next) +- if (INO_T_EQ (cur->ino, tmp->ino) && cur->dev == tmp->dev) +- break; +- +- if (tmp == cur +- /* Last in the chain and duplicate of JOIN? */ +- && !(cur->next == NULL && join +- && INO_T_EQ (cur->ino, join->ino) +- && cur->dev == join->dev)) +- { +- /* Unique, so keep this directory. */ +- pcur = &cur->next; +- continue; +- } +- } +- } +- +- /* Remove this entry from the chain. */ +- *pcur = cur->next; +- free_path (cur, verbose ? reason: REASON_QUIET); +- } +- +- *pcur = join; +- return head; +-} +- +-/* Merge the four include chains together in the order quote, bracket, +- system, after. Remove duplicate dirs (as determined by +- INO_T_EQ()). +- +- We can't just merge the lists and then uniquify them because then +- we may lose directories from the <> search path that should be +- there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however safe +- to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written -Ibar -I- -Ifoo +- -Iquux. */ +-static void +-merge_include_chains (cpp_reader *pfile, int verbose) +-{ +- /* Join the SYSTEM and AFTER chains. Remove duplicates in the +- resulting SYSTEM chain. */ +- if (heads[SYSTEM]) +- tails[SYSTEM]->next = heads[AFTER]; +- else +- heads[SYSTEM] = heads[AFTER]; +- heads[SYSTEM] = remove_duplicates (pfile, heads[SYSTEM], 0, 0, verbose); +- +- /* Remove duplicates from BRACKET that are in itself or SYSTEM, and +- join it to SYSTEM. */ +- heads[BRACKET] = remove_duplicates (pfile, heads[BRACKET], heads[SYSTEM], +- heads[SYSTEM], verbose); +- +- /* Remove duplicates from QUOTE that are in itself or SYSTEM, and +- join it to BRACKET. */ +- heads[QUOTE] = remove_duplicates (pfile, heads[QUOTE], heads[SYSTEM], +- heads[BRACKET], verbose); +- +- /* If verbose, print the list of dirs to search. */ +- if (verbose) +- { +- struct cpp_dir *p; +- +- fprintf (stderr, _("#include \"...\" search starts here:\n")); +- for (p = heads[QUOTE];; p = p->next) +- { +- if (p == heads[BRACKET]) +- fprintf (stderr, _("#include <...> search starts here:\n")); +- if (!p) +- break; +- fprintf (stderr, " %s\n", p->name); +- } +- fprintf (stderr, _("End of search list.\n")); +- } +-} +- +-/* Use given -I paths for #include "..." but not #include <...>, and +- don't search the directory of the present file for #include "...". +- (Note that -I. -I- is not the same as the default setup; -I. uses +- the compiler's working dir.) */ +-void +-split_quote_chain (void) +-{ +- heads[QUOTE] = heads[BRACKET]; +- tails[QUOTE] = tails[BRACKET]; +- heads[BRACKET] = NULL; +- tails[BRACKET] = NULL; +- /* This is NOT redundant. */ +- quote_ignores_source_dir = true; +-} +- +-/* Add PATH to the include chain CHAIN. PATH must be malloc-ed and +- NUL-terminated. */ +-void +-add_path (char *path, int chain, int cxx_aware) +-{ +- struct cpp_dir *p; +- +-#if defined (HAVE_DOS_BASED_FILE_SYSTEM) +- /* Convert all backslashes to slashes. The native CRT stat() +- function does not recognise a directory that ends in a backslash +- (unless it is a drive root dir, such "c:\"). Forward slashes, +- trailing or otherwise, cause no problems for stat(). */ +- char* c; +- for (c = path; *c; c++) +- if (*c == '\\') *c = '/'; +-#endif +- +- p = xmalloc (sizeof (struct cpp_dir)); +- p->next = NULL; +- p->name = path; +- if (chain == SYSTEM || chain == AFTER) +- p->sysp = 1 + !cxx_aware; +- else +- p->sysp = 0; +- +- if (tails[chain]) +- tails[chain]->next = p; +- else +- heads[chain] = p; +- tails[chain] = p; +-} +- +-/* Exported function to handle include chain merging, duplicate +- removal, and registration with cpplib. */ +-void +-register_include_chains (cpp_reader *pfile, const char *sysroot, +- const char *iprefix, int stdinc, int cxx_stdinc, +- int verbose) +-{ +- static const char *const lang_env_vars[] = +- { "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH", +- "OBJC_INCLUDE_PATH", "OBJCPLUS_INCLUDE_PATH" }; +- cpp_options *cpp_opts = cpp_get_options (pfile); +- size_t idx = (cpp_opts->objc ? 2: 0); +- +- if (cpp_opts->cplusplus) +- idx++; +- else +- cxx_stdinc = false; +- +- /* CPATH and language-dependent environment variables may add to the +- include chain. */ +- add_env_var_paths ("CPATH", BRACKET); +- add_env_var_paths (lang_env_vars[idx], SYSTEM); +- +- /* Finally chain on the standard directories. */ +- if (stdinc) +- add_standard_paths (sysroot, iprefix, cxx_stdinc); +- +- merge_include_chains (pfile, verbose); +- +- cpp_set_include_chains (pfile, heads[QUOTE], heads[BRACKET], +- quote_ignores_source_dir); +-} +diff -ruN gcc-3.4.5-20060117-1/gcc/collect2.c.orig gcc-3.4.5-20060117-1-winelf/gcc/collect2.c.orig +--- gcc-3.4.5-20060117-1/gcc/collect2.c.orig 2005-01-10 07:25:23.000000000 -0800 ++++ gcc-3.4.5-20060117-1-winelf/gcc/collect2.c.orig 1969-12-31 16:00:00.000000000 -0800 +@@ -1,2868 +0,0 @@ +-/* Collect static initialization info into data structures that can be +- traversed by C++ initialization and finalization routines. +- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, +- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +- Contributed by Chris Smith (csmith@convex.com). +- Heavily modified by Michael Meissner (meissner@cygnus.com), +- Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com). +- +-This file is part of GCC. +- +-GCC is free software; you can redistribute it and/or modify it under +-the terms of the GNU General Public License as published by the Free +-Software Foundation; either version 2, or (at your option) any later +-version. +- +-GCC is distributed in the hope that it will be useful, but WITHOUT ANY +-WARRANTY; without even the implied warranty of MERCHANTABILITY or +-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-for more details. +- +-You should have received a copy of the GNU General Public License +-along with GCC; see the file COPYING. If not, write to the Free +-Software Foundation, 59 Temple Place - Suite 330, Boston, MA +-02111-1307, USA. */ +- +- +-/* Build tables of static constructors and destructors and run ld. */ +- +-#include "config.h" +-#include "system.h" +-#include "coretypes.h" +-#include "tm.h" +-#include <signal.h> +-#if ! defined( SIGCHLD ) && defined( SIGCLD ) +-# define SIGCHLD SIGCLD +-#endif +- +-#ifdef vfork /* Autoconf may define this to fork for us. */ +-# define VFORK_STRING "fork" +-#else +-# define VFORK_STRING "vfork" +-#endif +-#ifdef HAVE_VFORK_H +-#include <vfork.h> +-#endif +-#ifdef VMS +-#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \ +- lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1) +-#endif /* VMS */ +- +-#ifndef LIBRARY_PATH_ENV +-#define LIBRARY_PATH_ENV "LIBRARY_PATH" +-#endif +- +-#define COLLECT +- +-#include "collect2.h" +-#include "demangle.h" +-#include "obstack.h" +-#include "intl.h" +-#include "version.h" +- +-/* On certain systems, we have code that works by scanning the object file +- directly. But this code uses system-specific header files and library +- functions, so turn it off in a cross-compiler. Likewise, the names of +- the utilities are not correct for a cross-compiler; we have to hope that +- cross-versions are in the proper directories. */ +- +-#ifdef CROSS_COMPILE +-#undef SUNOS4_SHARED_LIBRARIES +-#undef OBJECT_FORMAT_COFF +-#undef MD_EXEC_PREFIX +-#undef REAL_LD_FILE_NAME +-#undef REAL_NM_FILE_NAME +-#undef REAL_STRIP_FILE_NAME +-#endif +- +-/* If we cannot use a special method, use the ordinary one: +- run nm to find what symbols are present. +- In a cross-compiler, this means you need a cross nm, +- but that is not quite as unpleasant as special headers. */ +- +-#if !defined (OBJECT_FORMAT_COFF) +-#define OBJECT_FORMAT_NONE +-#endif +- +-#ifdef OBJECT_FORMAT_COFF +- +-#include <a.out.h> +-#include <ar.h> +- +-#ifdef UMAX +-#include <sgs.h> +-#endif +- +-/* Many versions of ldfcn.h define these. */ +-#ifdef FREAD +-#undef FREAD +-#undef FWRITE +-#endif +- +-#include <ldfcn.h> +- +-/* Some systems have an ISCOFF macro, but others do not. In some cases +- the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines +- that either do not have an ISCOFF macro in /usr/include or for those +- where it is wrong. */ +- +-#ifndef MY_ISCOFF +-#define MY_ISCOFF(X) ISCOFF (X) +-#endif +- +-#endif /* OBJECT_FORMAT_COFF */ +- +-#ifdef OBJECT_FORMAT_NONE +- +-/* Default flags to pass to nm. */ +-#ifndef NM_FLAGS +-#define NM_FLAGS "-n" +-#endif +- +-#endif /* OBJECT_FORMAT_NONE */ +- +-/* Some systems use __main in a way incompatible with its use in gcc, in these +- cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to +- give the same symbol without quotes for an alternative entry point. */ +-#ifndef NAME__MAIN +-#define NAME__MAIN "__main" +-#endif +- +-/* This must match tree.h. */ +-#define DEFAULT_INIT_PRIORITY 65535 +- +-#ifndef COLLECT_SHARED_INIT_FUNC +-#define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \ +- fprintf ((STREAM), "void _GLOBAL__DI() {\n\t%s();\n}\n", (FUNC)) +-#endif +-#ifndef COLLECT_SHARED_FINI_FUNC +-#define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \ +- fprintf ((STREAM), "void _GLOBAL__DD() {\n\t%s();\n}\n", (FUNC)) +-#endif +- +-#if defined (LDD_SUFFIX) || SUNOS4_SHARED_LIBRARIES +-#define SCAN_LIBRARIES +-#endif +- +-#ifdef USE_COLLECT2 +-int do_collecting = 1; +-#else +-int do_collecting = 0; +-#endif +- +-#ifndef COLLECT_PARSE_FLAG +-#define COLLECT_PARSE_FLAG(FLAG) +-#endif +- +-/* Nonzero if we should suppress the automatic demangling of identifiers +- in linker error messages. Set from COLLECT_NO_DEMANGLE. */ +-int no_demangle; +- +-/* Linked lists of constructor and destructor names. */ +- +-struct id +-{ +- struct id *next; +- int sequence; +- char name[1]; +-}; +- +-struct head +-{ +- struct id *first; +- struct id *last; +- int number; +-}; +- +-/* Enumeration giving which pass this is for scanning the program file. */ +- +-enum pass { +- PASS_FIRST, /* without constructors */ +- PASS_OBJ, /* individual objects */ +- PASS_LIB, /* looking for shared libraries */ +- PASS_SECOND /* with constructors linked in */ +-}; +- +-int vflag; /* true if -v */ +-static int rflag; /* true if -r */ +-static int strip_flag; /* true if -s */ +-#ifdef COLLECT_EXPORT_LIST +-static int export_flag; /* true if -bE */ +-static int aix64_flag; /* true if -b64 */ +-static int aixrtl_flag; /* true if -brtl */ +-#endif +- +-int debug; /* true if -debug */ +- +-static int shared_obj; /* true if -shared */ +- +-static const char *c_file; /* <xxx>.c for constructor/destructor list. */ +-static const char *o_file; /* <xxx>.o for constructor/destructor list. */ +-#ifdef COLLECT_EXPORT_LIST +-static const char *export_file; /* <xxx>.x for AIX export list. */ +-#endif +-const char *ldout; /* File for ld errors. */ +-static const char *output_file; /* Output file for ld. */ +-static const char *nm_file_name; /* pathname of nm */ +-#ifdef LDD_SUFFIX +-static const char *ldd_file_name; /* pathname of ldd (or equivalent) */ +-#endif +-static const char *strip_file_name; /* pathname of strip */ +-const char *c_file_name; /* pathname of gcc */ +-static char *initname, *fininame; /* names of init and fini funcs */ +- +-static struct head constructors; /* list of constructors found */ +-static struct head destructors; /* list of destructors found */ +-#ifdef COLLECT_EXPORT_LIST +-static struct head exports; /* list of exported symbols */ +-#endif +-static struct head frame_tables; /* list of frame unwind info tables */ +- +-struct obstack temporary_obstack; +-char * temporary_firstobj; +- +-/* Holds the return value of pexecute and fork. */ +-int pid; +- +-/* Structure to hold all the directories in which to search for files to +- execute. */ +- +-struct prefix_list +-{ +- const char *prefix; /* String to prepend to the path. */ +- struct prefix_list *next; /* Next in linked list. */ +-}; +- +-struct path_prefix +-{ +- struct prefix_list *plist; /* List of prefixes to try */ +- int max_len; /* Max length of a prefix in PLIST */ +- const char *name; /* Name of this list (used in config stuff) */ +-}; +- +-#ifdef COLLECT_EXPORT_LIST +-/* Lists to keep libraries to be scanned for global constructors/destructors. */ +-static struct head libs; /* list of libraries */ +-static struct path_prefix cmdline_lib_dirs; /* directories specified with -L */ +-static struct path_prefix libpath_lib_dirs; /* directories in LIBPATH */ +-static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs, +- &libpath_lib_dirs, NULL}; +-#endif +- +-static void handler (int); +-static int is_ctor_dtor (const char *); +-static char *find_a_file (struct path_prefix *, const char *); +-static void add_prefix (struct path_prefix *, const char *); +-static void prefix_from_env (const char *, struct path_prefix *); +-static void prefix_from_string (const char *, struct path_prefix *); +-static void do_wait (const char *); +-static void fork_execute (const char *, char **); +-static void maybe_unlink (const char *); +-static void add_to_list (struct head *, const char *); +-static int extract_init_priority (const char *); +-static void sort_ids (struct head *); +-static void write_list (FILE *, const char *, struct id *); +-#ifdef COLLECT_EXPORT_LIST +-static void dump_list (FILE *, const char *, struct id *); +-#endif +-#if 0 +-static void dump_prefix_list (FILE *, const char *, struct prefix_list *); +-#endif +-static void write_list_with_asm (FILE *, const char *, struct id *); +-static void write_c_file (FILE *, const char *); +-static void write_c_file_stat (FILE *, const char *); +-#ifndef LD_INIT_SWITCH +-static void write_c_file_glob (FILE *, const char *); +-#endif +-static void scan_prog_file (const char *, enum pass); +-#ifdef SCAN_LIBRARIES +-static void scan_libraries (const char *); +-#endif +-#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES +-static int is_in_args (const char *, const char **, const char **); +-#endif +-#ifdef COLLECT_EXPORT_LIST +-#if 0 +-static int is_in_list (const char *, struct id *); +-#endif +-static void write_aix_file (FILE *, struct id *); +-static char *resolve_lib_name (const char *); +-#endif +-static char *extract_string (const char **); +- +-#ifndef HAVE_DUP2 +-static int +-dup2 (int oldfd, int newfd) +-{ +- int fdtmp[256]; +- int fdx = 0; +- int fd; +- +- if (oldfd == newfd) +- return oldfd; +- close (newfd); +- while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */ +- fdtmp[fdx++] = fd; +- while (fdx > 0) +- close (fdtmp[--fdx]); +- +- return fd; +-} +-#endif /* ! HAVE_DUP2 */ +- +-/* Delete tempfiles and exit function. */ +- +-void +-collect_exit (int status) +-{ +- if (c_file != 0 && c_file[0]) +- maybe_unlink (c_file); +- +- if (o_file != 0 && o_file[0]) +- maybe_unlink (o_file); +- +-#ifdef COLLECT_EXPORT_LIST +- if (export_file != 0 && export_file[0]) +- maybe_unlink (export_file); +-#endif +- +- if (ldout != 0 && ldout[0]) +- { +- dump_file (ldout); +- maybe_unlink (ldout); +- } +- +- if (status != 0 && output_file != 0 && output_file[0]) +- maybe_unlink (output_file); +- +- exit (status); +-} +- +- +-/* Notify user of a non-error. */ +-void +-notice (const char *msgid, ...) +-{ +- va_list ap; +- +- va_start (ap, msgid); +- vfprintf (stderr, _(msgid), ap); +- va_end (ap); +-} +- +-/* Die when sys call fails. */ +- +-void +-fatal_perror (const char * msgid, ...) +-{ +- int e = errno; +- va_list ap; +- +- va_start (ap, msgid); +- fprintf (stderr, "collect2: "); +- vfprintf (stderr, _(msgid), ap); +- fprintf (stderr, ": %s\n", xstrerror (e)); +- va_end (ap); +- +- collect_exit (FATAL_EXIT_CODE); +-} +- +-/* Just die. */ +- +-void +-fatal (const char * msgid, ...) +-{ +- va_list ap; +- +- va_start (ap, msgid); +- fprintf (stderr, "collect2: "); +- vfprintf (stderr, _(msgid), ap); +- fprintf (stderr, "\n"); +- va_end (ap); +- +- collect_exit (FATAL_EXIT_CODE); +-} +- +-/* Write error message. */ +- +-void +-error (const char * msgid, ...) +-{ +- va_list ap; +- +- va_start (ap, msgid); +- fprintf (stderr, "collect2: "); +- vfprintf (stderr, _(msgid), ap); +- fprintf (stderr, "\n"); +- va_end(ap); +-} +- +-/* In case obstack is linked in, and abort is defined to fancy_abort, +- provide a default entry. */ +- +-void +-fancy_abort (void) +-{ +- fatal ("internal error"); +-} +- +-static void +-handler (int signo) +-{ +- if (c_file != 0 && c_file[0]) +- maybe_unlink (c_file); +- +- if (o_file != 0 && o_file[0]) +- maybe_unlink (o_file); +- +- if (ldout != 0 && ldout[0]) +- maybe_unlink (ldout); +- +-#ifdef COLLECT_EXPORT_LIST +- if (export_file != 0 && export_file[0]) +- maybe_unlink (export_file); +-#endif +- +- signal (signo, SIG_DFL); +- kill (getpid (), signo); +-} +- +- +-int +-file_exists (const char *name) +-{ +- return access (name, R_OK) == 0; +-} +- +-/* Parse a reasonable subset of shell quoting syntax. */ +- +-static char * +-extract_string (const char **pp) +-{ +- const char *p = *pp; +- int backquote = 0; +- int inside = 0; +- +- for (;;) +- { +- char c = *p; +- if (c == '\0') +- break; +- ++p; +- if (backquote) +- obstack_1grow (&temporary_obstack, c); +- else if (! inside && c == ' ') +- break; +- else if (! inside && c == '\\') +- backquote = 1; +- else if (c == '\'') +- inside = !inside; +- else +- obstack_1grow (&temporary_obstack, c); +- } +- +- obstack_1grow (&temporary_obstack, '\0'); +- *pp = p; +- return obstack_finish (&temporary_obstack); +-} +- +-void +-dump_file (const char *name) +-{ +- FILE *stream = fopen (name, "r"); +- +- if (stream == 0) +- return; +- while (1) +- { +- int c; +- while (c = getc (stream), +- c != EOF && (ISIDNUM (c) || c == '$' || c == '.')) +- obstack_1grow (&temporary_obstack, c); +- if (obstack_object_size (&temporary_obstack) > 0) +- { +- const char *word, *p; +- char *result; +- obstack_1grow (&temporary_obstack, '\0'); +- word = obstack_finish (&temporary_obstack); +- +- if (*word == '.') +- ++word, putc ('.', stderr); +- p = word; +- if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX))) +- p += strlen (USER_LABEL_PREFIX); +- +- if (no_demangle) +- result = 0; +- else +- result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE); +- +- if (result) +- { +- int diff; +- fputs (result, stderr); +- +- diff = strlen (word) - strlen (result); +- while (diff > 0 && c == ' ') +- --diff, putc (' ', stderr); +- while (diff < 0 && c == ' ') +- ++diff, c = getc (stream); +- +- free (result); +- } +- else +- fputs (word, stderr); +- +- fflush (stderr); +- obstack_free (&temporary_obstack, temporary_firstobj); +- } +- if (c == EOF) +- break; +- putc (c, stderr); +- } +- fclose (stream); +-} +- +-/* Decide whether the given symbol is: a constructor (1), a destructor +- (2), a routine in a shared object that calls all the constructors +- (3) or destructors (4), a DWARF exception-handling table (5), or +- nothing special (0). */ +- +-static int +-is_ctor_dtor (const char *s) +-{ +- struct names { const char *const name; const int len; const int ret; +- const int two_underscores; }; +- +- const struct names *p; +- int ch; +- const char *orig_s = s; +- +- static const struct names special[] = { +-#ifndef NO_DOLLAR_IN_LABEL +- { "GLOBAL__I$", sizeof ("GLOBAL__I$")-1, 1, 0 }, +- { "GLOBAL__D$", sizeof ("GLOBAL__D$")-1, 2, 0 }, +-#else +-#ifndef NO_DOT_IN_LABEL +- { "GLOBAL__I.", sizeof ("GLOBAL__I.")-1, 1, 0 }, +- { "GLOBAL__D.", sizeof ("GLOBAL__D.")-1, 2, 0 }, +-#endif /* NO_DOT_IN_LABEL */ +-#endif /* NO_DOLLAR_IN_LABEL */ +- { "GLOBAL__I_", sizeof ("GLOBAL__I_")-1, 1, 0 }, +- { "GLOBAL__D_", sizeof ("GLOBAL__D_")-1, 2, 0 }, +- { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, 5, 0 }, +- { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, 3, 0 }, +- { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, 4, 0 }, +- { NULL, 0, 0, 0 } +- }; +- +- while ((ch = *s) == '_') +- ++s; +- +- if (s == orig_s) +- return 0; +- +- for (p = &special[0]; p->len > 0; p++) +- { +- if (ch == p->name[0] +- && (!p->two_underscores || ((s - orig_s) >= 2)) +- && strncmp(s, p->name, p->len) == 0) +- { +- return p->ret; +- } +- } +- return 0; +-} +- +-/* We maintain two prefix lists: one from COMPILER_PATH environment variable +- and one from the PATH variable. */ +- +-static struct path_prefix cpath, path; +- +-#ifdef CROSS_COMPILE +-/* This is the name of the target machine. We use it to form the name +- of the files to execute. */ +- +-static const char *const target_machine = TARGET_MACHINE; +-#endif +- +-/* Search for NAME using prefix list PPREFIX. We only look for executable +- files. +- +- Return 0 if not found, otherwise return its name, allocated with malloc. */ +- +-static char * +-find_a_file (struct path_prefix *pprefix, const char *name) +-{ +- char *temp; +- struct prefix_list *pl; +- int len = pprefix->max_len + strlen (name) + 1; +- +- if (debug) +- fprintf (stderr, "Looking for '%s'\n", name); +- +-#ifdef HOST_EXECUTABLE_SUFFIX +- len += strlen (HOST_EXECUTABLE_SUFFIX); +-#endif +- +- temp = xmalloc (len); +- +- /* Determine the filename to execute (special case for absolute paths). */ +- +- if (*name == '/' +-#ifdef HAVE_DOS_BASED_FILE_SYSTEM +- || (*name && name[1] == ':') +-#endif +- ) +- { +- if (access (name, X_OK) == 0) +- { +- strcpy (temp, name); +- +- if (debug) +- fprintf (stderr, " - found: absolute path\n"); +- +- return temp; +- } +- +-#ifdef HOST_EXECUTABLE_SUFFIX +- /* Some systems have a suffix for executable files. +- So try appending that. */ +- strcpy (temp, name); +- strcat (temp, HOST_EXECUTABLE_SUFFIX); +- +- if (access (temp, X_OK) == 0) +- return temp; +-#endif +- +- if (debug) +- fprintf (stderr, " - failed to locate using absolute path\n"); +- } +- else +- for (pl = pprefix->plist; pl; pl = pl->next) +- { +- struct stat st; +- +- strcpy (temp, pl->prefix); +- strcat (temp, name); +- +- if (stat (temp, &st) >= 0 +- && ! S_ISDIR (st.st_mode) +- && access (temp, X_OK) == 0) +- return temp; +- +-#ifdef HOST_EXECUTABLE_SUFFIX +- /* Some systems have a suffix for executable files. +- So try appending that. */ +- strcat (temp, HOST_EXECUTABLE_SUFFIX); +- +- if (stat (temp, &st) >= 0 +- && ! S_ISDIR (st.st_mode) +- && access (temp, X_OK) == 0) +- return temp; +-#endif +- } +- +- if (debug && pprefix->plist == NULL) +- fprintf (stderr, " - failed: no entries in prefix list\n"); +- +- free (temp); +- return 0; +-} +- +-/* Add an entry for PREFIX to prefix list PPREFIX. */ +- +-static void +-add_prefix (struct path_prefix *pprefix, const char *prefix) +-{ +- struct prefix_list *pl, **prev; +- int len; +- +- if (pprefix->plist) +- { +- for (pl = pprefix->plist; pl->next; pl = pl->next) +- ; +- prev = &pl->next; +- } +- else +- prev = &pprefix->plist; +- +- /* Keep track of the longest prefix. */ +- +- len = strlen (prefix); +- if (len > pprefix->max_len) +- pprefix->max_len = len; +- +- pl = xmalloc (sizeof (struct prefix_list)); +- pl->prefix = xstrdup (prefix); +- +- if (*prev) +- pl->next = *prev; +- else +- pl->next = (struct prefix_list *) 0; +- *prev = pl; +-} +- +-/* Take the value of the environment variable ENV, break it into a path, and +- add of the entries to PPREFIX. */ +- +-static void +-prefix_from_env (const char *env, struct path_prefix *pprefix) +-{ +- const char *p; +- GET_ENVIRONMENT (p, env); +- +- if (p) +- prefix_from_string (p, pprefix); +-} +- +-static void +-prefix_from_string (const char *p, struct path_prefix *pprefix) +-{ +- const char *startp, *endp; +- char *nstore = xmalloc (strlen (p) + 3); +- +- if (debug) +- fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR); +- +- startp = endp = p; +- while (1) +- { +- if (*endp == PATH_SEPARATOR || *endp == 0) +- { +- strncpy (nstore, startp, endp-startp); +- if (endp == startp) +- { +- strcpy (nstore, "./"); +- } +- else if (! IS_DIR_SEPARATOR (endp[-1])) +- { +- nstore[endp-startp] = DIR_SEPARATOR; +- nstore[endp-startp+1] = 0; +- } +- else +- nstore[endp-startp] = 0; +- +- if (debug) +- fprintf (stderr, " - add prefix: %s\n", nstore); +- +- add_prefix (pprefix, nstore); +- if (*endp == 0) +- break; +- endp = startp = endp + 1; +- } +- else +- endp++; +- } +-} +- +-/* Main program. */ +- +-int +-main (int argc, char **argv) +-{ +- static const char *const ld_suffix = "ld"; +- static const char *const real_ld_suffix = "real-ld"; +- static const char *const collect_ld_suffix = "collect-ld"; +- static const char *const nm_suffix = "nm"; +- static const char *const gnm_suffix = "gnm"; +-#ifdef LDD_SUFFIX +- static const char *const ldd_suffix = LDD_SUFFIX; +-#endif +- static const char *const strip_suffix = "strip"; +- static const char *const gstrip_suffix = "gstrip"; +- +-#ifdef CROSS_COMPILE +- /* If we look for a program in the compiler directories, we just use +- the short name, since these directories are already system-specific. +- But it we look for a program in the system directories, we need to +- qualify the program name with the target machine. */ +- +- const char *const full_ld_suffix = +- concat(target_machine, "-", ld_suffix, NULL); +- const char *const full_nm_suffix = +- concat (target_machine, "-", nm_suffix, NULL); +- const char *const full_gnm_suffix = +- concat (target_machine, "-", gnm_suffix, NULL); +-#ifdef LDD_SUFFIX +- const char *const full_ldd_suffix = +- concat (target_machine, "-", ldd_suffix, NULL); +-#endif +- const char *const full_strip_suffix = +- concat (target_machine, "-", strip_suffix, NULL); +- const char *const full_gstrip_suffix = +- concat (target_machine, "-", gstrip_suffix, NULL); +-#else +- const char *const full_ld_suffix = ld_suffix; +- const char *const full_nm_suffix = nm_suffix; +- const char *const full_gnm_suffix = gnm_suffix; +-#ifdef LDD_SUFFIX +- const char *const full_ldd_suffix = ldd_suffix; +-#endif +- const char *const full_strip_suffix = strip_suffix; +- const char *const full_gstrip_suffix = gstrip_suffix; +-#endif /* CROSS_COMPILE */ +- +- const char *arg; +- FILE *outf; +-#ifdef COLLECT_EXPORT_LIST +- FILE *exportf; +-#endif +- const char *ld_file_name; +- const char *p; +- char **c_argv; +- const char **c_ptr; +- char **ld1_argv; +- const char **ld1; +- char **ld2_argv; +- const char **ld2; +- char **object_lst; +- const char **object; +- int first_file; +- int num_c_args = argc+9; +- +- no_demangle = !! getenv ("COLLECT_NO_DEMANGLE"); +- +- /* Suppress demangling by the real linker, which may be broken. */ +- putenv (xstrdup ("COLLECT_NO_DEMANGLE=")); +- +-#if defined (COLLECT2_HOST_INITIALIZATION) +- /* Perform system dependent initialization, if necessary. */ +- COLLECT2_HOST_INITIALIZATION; +-#endif +- +-#ifdef SIGCHLD +- /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will +- receive the signal. A different setting is inheritable */ +- signal (SIGCHLD, SIG_DFL); +-#endif +- +- gcc_init_libintl (); +- +- /* Do not invoke xcalloc before this point, since locale needs to be +- set first, in case a diagnostic is issued. */ +- +- ld1 = (const char **)(ld1_argv = xcalloc(sizeof (char *), argc+3)); +- ld2 = (const char **)(ld2_argv = xcalloc(sizeof (char *), argc+10)); +- object = (const char **)(object_lst = xcalloc(sizeof (char *), argc)); +- +-#ifdef DEBUG +- debug = 1; +-#endif +- +- /* Parse command line early for instances of -debug. This allows +- the debug flag to be set before functions like find_a_file() +- are called. */ +- { +- int i; +- +- for (i = 1; argv[i] != NULL; i ++) +- { +- if (! strcmp (argv[i], "-debug")) +- debug = 1; +- COLLECT_PARSE_FLAG (argv[i]); +- } +- vflag = debug; +- } +- +-#ifndef DEFAULT_A_OUT_NAME +- output_file = "a.out"; +-#else +- output_file = DEFAULT_A_OUT_NAME; +-#endif +- +- obstack_begin (&temporary_obstack, 0); +- temporary_firstobj = obstack_alloc (&temporary_obstack, 0); +- +- current_demangling_style = auto_demangling; +- p = getenv ("COLLECT_GCC_OPTIONS"); +- while (p && *p) +- { +- const char *q = extract_string (&p); +- if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) +- num_c_args++; +- } +- obstack_free (&temporary_obstack, temporary_firstobj); +- +- /* -fno-profile-arcs -fno-test-coverage -fno-branch-probabilities +- -fno-exceptions -w */ +- num_c_args += 5; +- +- c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args)); +- +- if (argc < 2) +- fatal ("no arguments"); +- +-#ifdef SIGQUIT +- if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) +- signal (SIGQUIT, handler); +-#endif +- if (signal (SIGINT, SIG_IGN) != SIG_IGN) +- signal (SIGINT, handler); +-#ifdef SIGALRM +- if (signal (SIGALRM, SIG_IGN) != SIG_IGN) +- signal (SIGALRM, handler); +-#endif +-#ifdef SIGHUP +- if (signal (SIGHUP, SIG_IGN) != SIG_IGN) +- signal (SIGHUP, handler); +-#endif +- if (signal (SIGSEGV, SIG_IGN) != SIG_IGN) +- signal (SIGSEGV, handler); +-#ifdef SIGBUS +- if (signal (SIGBUS, SIG_IGN) != SIG_IGN) +- signal (SIGBUS, handler); +-#endif +- +- /* Extract COMPILER_PATH and PATH into our prefix list. */ +- prefix_from_env ("COMPILER_PATH", &cpath); +- prefix_from_env ("PATH", &path); +- +- /* Try to discover a valid linker/nm/strip to use. */ +- +- /* Maybe we know the right file to use (if not cross). */ +- ld_file_name = 0; +-#ifdef DEFAULT_LINKER +- if (access (DEFAULT_LINKER, X_OK) == 0) +- ld_file_name = DEFAULT_LINKER; +- if (ld_file_name == 0) +-#endif +-#ifdef REAL_LD_FILE_NAME +- ld_file_name = find_a_file (&path, REAL_LD_FILE_NAME); +- if (ld_file_name == 0) +-#endif +- /* Search the (target-specific) compiler dirs for ld'. */ +- ld_file_name = find_a_file (&cpath, real_ld_suffix); +- /* Likewise for `collect-ld'. */ +- if (ld_file_name == 0) +- ld_file_name = find_a_file (&cpath, collect_ld_suffix); +- /* Search the compiler directories for `ld'. We have protection against +- recursive calls in find_a_file. */ +- if (ld_file_name == 0) +- ld_file_name = find_a_file (&cpath, ld_suffix); +- /* Search the ordinary system bin directories +- for `ld' (if native linking) or `TARGET-ld' (if cross). */ +- if (ld_file_name == 0) +- ld_file_name = find_a_file (&path, full_ld_suffix); +- +-#ifdef REAL_NM_FILE_NAME +- nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME); +- if (nm_file_name == 0) +-#endif +- nm_file_name = find_a_file (&cpath, gnm_suffix); +- if (nm_file_name == 0) +- nm_file_name = find_a_file (&path, full_gnm_suffix); +- if (nm_file_name == 0) +- nm_file_name = find_a_file (&cpath, nm_suffix); +- if (nm_file_name == 0) +- nm_file_name = find_a_file (&path, full_nm_suffix); +- +-#ifdef LDD_SUFFIX +- ldd_file_name = find_a_file (&cpath, ldd_suffix); +- if (ldd_file_name == 0) +- ldd_file_name = find_a_file (&path, full_ldd_suffix); +-#endif +- +-#ifdef REAL_STRIP_FILE_NAME +- strip_file_name = find_a_file (&path, REAL_STRIP_FILE_NAME); +- if (strip_file_name == 0) +-#endif +- strip_file_name = find_a_file (&cpath, gstrip_suffix); +- if (strip_file_name == 0) +- strip_file_name = find_a_file (&path, full_gstrip_suffix); +- if (strip_file_name == 0) +- strip_file_name = find_a_file (&cpath, strip_suffix); +- if (strip_file_name == 0) +- strip_file_name = find_a_file (&path, full_strip_suffix); +- +- /* Determine the full path name of the C compiler to use. */ +- c_file_name = getenv ("COLLECT_GCC"); +- if (c_file_name == 0) +- { +-#ifdef CROSS_COMPILE +- c_file_name = concat (target_machine, "-gcc", NULL); +-#else +- c_file_name = "gcc"; +-#endif +- } +- +- p = find_a_file (&cpath, c_file_name); +- +- /* Here it should be safe to use the system search path since we should have +- already qualified the name of the compiler when it is needed. */ +- if (p == 0) +- p = find_a_file (&path, c_file_name); +- +- if (p) +- c_file_name = p; +- +- *ld1++ = *ld2++ = ld_file_name; +- +- /* Make temp file names. */ +- c_file = make_temp_file (".c"); +- o_file = make_temp_file (".o"); +-#ifdef COLLECT_EXPORT_LIST +- export_file = make_temp_file (".x"); +-#endif +- ldout = make_temp_file (".ld"); +- *c_ptr++ = c_file_name; +- *c_ptr++ = "-x"; +- *c_ptr++ = "c"; +- *c_ptr++ = "-c"; +- *c_ptr++ = "-o"; +- *c_ptr++ = o_file; +- +-#ifdef COLLECT_EXPORT_LIST +- /* Generate a list of directories from LIBPATH. */ +- prefix_from_env ("LIBPATH", &libpath_lib_dirs); +- /* Add to this list also two standard directories where +- AIX loader always searches for libraries. */ +- add_prefix (&libpath_lib_dirs, "/lib"); +- add_prefix (&libpath_lib_dirs, "/usr/lib"); +-#endif +- +- /* Get any options that the upper GCC wants to pass to the sub-GCC. +- +- AIX support needs to know if -shared has been specified before +- parsing commandline arguments. */ +- +- p = getenv ("COLLECT_GCC_OPTIONS"); +- while (p && *p) +- { +- const char *q = extract_string (&p); +- if (*q == '-' && (q[1] == 'm' || q[1] == 'f')) +- *c_ptr++ = xstrdup (q); +- if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0) +- *c_ptr++ = xstrdup (q); +- if (strcmp (q, "-shared") == 0) +- shared_obj = 1; +- if (*q == '-' && q[1] == 'B') +- { +- *c_ptr++ = xstrdup (q); +- if (q[2] == 0) +- { +- q = extract_string (&p); +- *c_ptr++ = xstrdup (q); +- } +- } +- } +- obstack_free (&temporary_obstack, temporary_firstobj); +- *c_ptr++ = "-fno-profile-arcs"; +- *c_ptr++ = "-fno-test-coverage"; +- *c_ptr++ = "-fno-branch-probabilities"; +- *c_ptr++ = "-fno-exceptions"; +- *c_ptr++ = "-w"; +- +- /* !!! When GCC calls collect2, +- it does not know whether it is calling collect2 or ld. +- So collect2 cannot meaningfully understand any options +- except those ld understands. +- If you propose to make GCC pass some other option, +- just imagine what will happen if ld is really ld!!! */ +- +- /* Parse arguments. Remember output file spec, pass the rest to ld. */ +- /* After the first file, put in the c++ rt0. */ +- +- first_file = 1; +- while ((arg = *++argv) != (char *) 0) +- { +- *ld1++ = *ld2++ = arg; +- +- if (arg[0] == '-') +- { +- switch (arg[1]) +- { +-#ifdef COLLECT_EXPORT_LIST +- /* We want to disable automatic exports on AIX when user +- explicitly puts an export list in command line */ +- case 'b': +- if (arg[2] == 'E' || strncmp (&arg[2], "export", 6) == 0) +- export_flag = 1; +- else if (arg[2] == '6' && arg[3] == '4') +- aix64_flag = 1; +- else if (arg[2] == 'r' && arg[3] == 't' && arg[4] == 'l') +- aixrtl_flag = 1; +- break; +-#endif +- +- case 'd': +- if (!strcmp (arg, "-debug")) +- { +- /* Already parsed. */ +- ld1--; +- ld2--; +- } +- break; +- +- case 'l': +- if (first_file) +- { +- /* place o_file BEFORE this argument! */ +- first_file = 0; +- ld2--; +- *ld2++ = o_file; +- *ld2++ = arg; +- } +-#ifdef COLLECT_EXPORT_LIST +- { +- /* Resolving full library name. */ +- const char *s = resolve_lib_name (arg+2); +- +- /* Saving a full library name. */ +- add_to_list (&libs, s); +- } +-#endif +- break; +- +-#ifdef COLLECT_EXPORT_LIST +- /* Saving directories where to search for libraries. */ +- case 'L': +- add_prefix (&cmdline_lib_dirs, arg+2); +- break; +-#else +-#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES +- case 'L': +- if (is_in_args (arg, (const char **) ld1_argv, ld1-1)) +- --ld1; +- break; +-#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ +-#endif +- +- case 'o': +- if (arg[2] == '\0') +- output_file = *ld1++ = *ld2++ = *++argv; +- else if (1 +-#ifdef SWITCHES_NEED_SPACES +- && ! strchr (SWITCHES_NEED_SPACES, arg[1]) +-#endif +- ) +- +- output_file = &arg[2]; +- break; +- +- case 'r': +- if (arg[2] == '\0') +- rflag = 1; +- break; +- +- case 's': +- if (arg[2] == '\0' && do_collecting) +- { +- /* We must strip after the nm run, otherwise C++ linking +- will not work. Thus we strip in the second ld run, or +- else with strip if there is no second ld run. */ +- strip_flag = 1; +- ld1--; +- } +- break; +- +- case 'v': +- if (arg[2] == '\0') +- vflag = 1; +- break; +- } +- } +- else if ((p = strrchr (arg, '.')) != (char *) 0 +- && (strcmp (p, ".o") == 0 || strcmp (p, ".a") == 0 +- || strcmp (p, ".so") == 0 || strcmp (p, ".lo") == 0 +- || strcmp (p, ".obj") == 0)) +- { +- if (first_file) +- { +- first_file = 0; +- if (p[1] == 'o') +- *ld2++ = o_file; +- else +- { +- /* place o_file BEFORE this argument! */ +- ld2--; +- *ld2++ = o_file; +- *ld2++ = arg; +- } +- } +- if (p[1] == 'o' || p[1] == 'l') +- *object++ = arg; +-#ifdef COLLECT_EXPORT_LIST +- /* libraries can be specified directly, i.e. without -l flag. */ +- else +- { +- /* Saving a full library name. */ +- add_to_list (&libs, arg); +- } +-#endif +- } +- } +- +-#ifdef COLLECT_EXPORT_LIST +- /* This is added only for debugging purposes. */ +- if (debug) +- { +- fprintf (stderr, "List of libraries:\n"); +- dump_list (stderr, "\t", libs.first); +- } +- +- /* The AIX linker will discard static constructors in object files if +- nothing else in the file is referenced, so look at them first. */ +- { +- const char **export_object_lst = (const char **)object_lst; +- +- while (export_object_lst < object) +- scan_prog_file (*export_object_lst++, PASS_OBJ); +- } +- { +- struct id *list = libs.first; +- +- for (; list; list = list->next) +- scan_prog_file (list->name, PASS_FIRST); +- } +- +- if (exports.first) +- { +- char *buf = concat ("-bE:", export_file, NULL); +- +- *ld1++ = buf; +- *ld2++ = buf; +- +- exportf = fopen (export_file, "w"); +- if (exportf == (FILE *) 0) +- fatal_perror ("fopen %s", export_file); +- write_aix_file (exportf, exports.first); +- if (fclose (exportf)) +- fatal_perror ("fclose %s", export_file); +- } +-#endif +- +- *c_ptr++ = c_file; +- *c_ptr = *ld1 = *object = (char *) 0; +- +- if (vflag) +- { +- notice ("collect2 version %s", version_string); +-#ifdef TARGET_VERSION +- TARGET_VERSION; +-#endif +- fprintf (stderr, "\n"); +- } +- +- if (debug) +- { +- const char *ptr; +- fprintf (stderr, "ld_file_name = %s\n", +- (ld_file_name ? ld_file_name : "not found")); +- fprintf (stderr, "c_file_name = %s\n", +- (c_file_name ? c_file_name : "not found")); +- fprintf (stderr, "nm_file_name = %s\n", +- (nm_file_name ? nm_file_name : "not found")); +-#ifdef LDD_SUFFIX +- fprintf (stderr, "ldd_file_name = %s\n", +- (ldd_file_name ? ldd_file_name : "not found")); +-#endif +- fprintf (stderr, "strip_file_name = %s\n", +- (strip_file_name ? strip_file_name : "not found")); +- fprintf (stderr, "c_file = %s\n", +- (c_file ? c_file : "not found")); +- fprintf (stderr, "o_file = %s\n", +- (o_file ? o_file : "not found")); +- +- ptr = getenv ("COLLECT_GCC_OPTIONS"); +- if (ptr) +- fprintf (stderr, "COLLECT_GCC_OPTIONS = %s\n", ptr); +- +- ptr = getenv ("COLLECT_GCC"); +- if (ptr) +- fprintf (stderr, "COLLECT_GCC = %s\n", ptr); +- +- ptr = getenv ("COMPILER_PATH"); +- if (ptr) +- fprintf (stderr, "COMPILER_PATH = %s\n", ptr); +- +- ptr = getenv (LIBRARY_PATH_ENV); +- if (ptr) +- fprintf (stderr, "%-20s= %s\n", LIBRARY_PATH_ENV, ptr); +- +- fprintf (stderr, "\n"); +- } +- +- /* Load the program, searching all libraries and attempting to provide +- undefined symbols from repository information. */ +- +- /* On AIX we do this later. */ +-#ifndef COLLECT_EXPORT_LIST +- do_tlink (ld1_argv, object_lst); +-#endif +- +- /* If -r or they will be run via some other method, do not build the +- constructor or destructor list, just return now. */ +- if (rflag +-#ifndef COLLECT_EXPORT_LIST +- || ! do_collecting +-#endif +- ) +- { +-#ifdef COLLECT_EXPORT_LIST +- /* Do the link we avoided above if we are exiting. */ +- do_tlink (ld1_argv, object_lst); +- +- /* But make sure we delete the export file we may have created. */ +- if (export_file != 0 && export_file[0]) +- maybe_unlink (export_file); +-#endif +- maybe_unlink (c_file); +- maybe_unlink (o_file); +- return 0; +- } +- +- /* Examine the namelist with nm and search it for static constructors +- and destructors to call. +- Write the constructor and destructor tables to a .s file and reload. */ +- +- /* On AIX we already scanned for global constructors/destructors. */ +-#ifndef COLLECT_EXPORT_LIST +- scan_prog_file (output_file, PASS_FIRST); +-#endif +- +-#ifdef SCAN_LIBRARIES +- scan_libraries (output_file); +-#endif +- +- if (debug) +- { +- notice ("%d constructor(s) found\n", constructors.number); +- notice ("%d destructor(s) found\n", destructors.number); +- notice ("%d frame table(s) found\n", frame_tables.number); +- } +- +- if (constructors.number == 0 && destructors.number == 0 +- && frame_tables.number == 0 +-#if defined (SCAN_LIBRARIES) || defined (COLLECT_EXPORT_LIST) +- /* If we will be running these functions ourselves, we want to emit +- stubs into the shared library so that we do not have to relink +- dependent programs when we add static objects. */ +- && ! shared_obj +-#endif +- ) +- { +-#ifdef COLLECT_EXPORT_LIST +- /* Do tlink without additional code generation. */ +- do_tlink (ld1_argv, object_lst); +-#endif +- /* Strip now if it was requested on the command line. */ +- if (strip_flag) +- { +- char **real_strip_argv = xcalloc (sizeof (char *), 3); +- const char ** strip_argv = (const char **) real_strip_argv; +- +- strip_argv[0] = strip_file_name; +- strip_argv[1] = output_file; +- strip_argv[2] = (char *) 0; +- fork_execute ("strip", real_strip_argv); +- } +- +-#ifdef COLLECT_EXPORT_LIST +- maybe_unlink (export_file); +-#endif +- maybe_unlink (c_file); +- maybe_unlink (o_file); +- return 0; +- } +- +- /* Sort ctor and dtor lists by priority. */ +- sort_ids (&constructors); +- sort_ids (&destructors); +- +- maybe_unlink(output_file); +- outf = fopen (c_file, "w"); +- if (outf == (FILE *) 0) +- fatal_perror ("fopen %s", c_file); +- +- write_c_file (outf, c_file); +- +- if (fclose (outf)) +- fatal_perror ("fclose %s", c_file); +- +- /* Tell the linker that we have initializer and finalizer functions. */ +-#ifdef LD_INIT_SWITCH +-#ifdef COLLECT_EXPORT_LIST +- *ld2++ = concat (LD_INIT_SWITCH, ":", initname, ":", fininame, NULL); +-#else +- *ld2++ = LD_INIT_SWITCH; +- *ld2++ = initname; +- *ld2++ = LD_FINI_SWITCH; +- *ld2++ = fininame; +-#endif +-#endif +- +-#ifdef COLLECT_EXPORT_LIST +- if (shared_obj) +- { +- /* If we did not add export flag to link arguments before, add it to +- second link phase now. No new exports should have been added. */ +- if (! exports.first) +- *ld2++ = concat ("-bE:", export_file, NULL); +- +-#ifndef LD_INIT_SWITCH +- add_to_list (&exports, initname); +- add_to_list (&exports, fininame); +- add_to_list (&exports, "_GLOBAL__DI"); +- add_to_list (&exports, "_GLOBAL__DD"); +-#endif +- exportf = fopen (export_file, "w"); +- if (exportf == (FILE *) 0) +- fatal_perror ("fopen %s", export_file); +- write_aix_file (exportf, exports.first); +- if (fclose (exportf)) +- fatal_perror ("fclose %s", export_file); +- } +-#endif +- +- /* End of arguments to second link phase. */ +- *ld2 = (char*) 0; +- +- if (debug) +- { +- fprintf (stderr, "\n========== output_file = %s, c_file = %s\n", +- output_file, c_file); +- write_c_file (stderr, "stderr"); +- fprintf (stderr, "========== end of c_file\n\n"); +-#ifdef COLLECT_EXPORT_LIST +- fprintf (stderr, "\n========== export_file = %s\n", export_file); +- write_aix_file (stderr, exports.first); +- fprintf (stderr, "========== end of export_file\n\n"); +-#endif +- } +- +- /* Assemble the constructor and destructor tables. +- Link the tables in with the rest of the program. */ +- +- fork_execute ("gcc", c_argv); +-#ifdef COLLECT_EXPORT_LIST +- /* On AIX we must call tlink because of possible templates resolution. */ +- do_tlink (ld2_argv, object_lst); +-#else +- /* Otherwise, simply call ld because tlink is already done. */ +- fork_execute ("ld", ld2_argv); +- +- /* Let scan_prog_file do any final mods (OSF/rose needs this for +- constructors/destructors in shared libraries. */ +- scan_prog_file (output_file, PASS_SECOND); +-#endif +- +- maybe_unlink (c_file); +- maybe_unlink (o_file); +- +-#ifdef COLLECT_EXPORT_LIST +- maybe_unlink (export_file); +-#endif +- +- return 0; +-} +- +- +-/* Wait for a process to finish, and exit if a nonzero status is found. */ +- +-int +-collect_wait (const char *prog) +-{ +- int status; +- +- pwait (pid, &status, 0); +- if (status) +- { +- if (WIFSIGNALED (status)) +- { +- int sig = WTERMSIG (status); +- error ("%s terminated with signal %d [%s]%s", +- prog, sig, strsignal(sig), +- WCOREDUMP(status) ? ", core dumped" : ""); +- collect_exit (FATAL_EXIT_CODE); +- } +- +- if (WIFEXITED (status)) +- return WEXITSTATUS (status); +- } +- return 0; +-} +- +-static void +-do_wait (const char *prog) +-{ +- int ret = collect_wait (prog); +- if (ret != 0) +- { +- error ("%s returned %d exit status", prog, ret); +- collect_exit (ret); +- } +-} +- +- +-/* Execute a program, and wait for the reply. */ +- +-void +-collect_execute (const char *prog, char **argv, const char *redir) +-{ +- char *errmsg_fmt; +- char *errmsg_arg; +- int redir_handle = -1; +- int stdout_save = -1; +- int stderr_save = -1; +- +- if (vflag || debug) +- { +- char **p_argv; +- const char *str; +- +- if (argv[0]) +- fprintf (stderr, "%s", argv[0]); +- else +- notice ("[cannot find %s]", prog); +- +- for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) +- fprintf (stderr, " %s", str); +- +- fprintf (stderr, "\n"); +- } +- +- fflush (stdout); +- fflush (stderr); +- +- /* If we cannot find a program we need, complain error. Do this here +- since we might not end up needing something that we could not find. */ +- +- if (argv[0] == 0) +- fatal ("cannot find `%s'", prog); +- +- if (redir) +- { +- /* Open response file. */ +- redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT); +- +- /* Duplicate the stdout and stderr file handles +- so they can be restored later. */ +- stdout_save = dup (STDOUT_FILENO); +- if (stdout_save == -1) +- fatal_perror ("redirecting stdout: %s", redir); +- stderr_save = dup (STDERR_FILENO); +- if (stderr_save == -1) +- fatal_perror ("redirecting stdout: %s", redir); +- +- /* Redirect stdout & stderr to our response file. */ +- dup2 (redir_handle, STDOUT_FILENO); +- dup2 (redir_handle, STDERR_FILENO); +- } +- +- pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg, +- (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH)); +- +- if (redir) +- { +- /* Restore stdout and stderr to their previous settings. */ +- dup2 (stdout_save, STDOUT_FILENO); +- dup2 (stderr_save, STDERR_FILENO); +- +- /* Close response file. */ +- close (redir_handle); +- } +- +- if (pid == -1) +- fatal_perror (errmsg_fmt, errmsg_arg); +-} +- +-static void +-fork_execute (const char *prog, char **argv) +-{ +- collect_execute (prog, argv, NULL); +- do_wait (prog); +-} +- +-/* Unlink a file unless we are debugging. */ +- +-static void +-maybe_unlink (const char *file) +-{ +- if (!debug) +- unlink (file); +- else +- notice ("[Leaving %s]\n", file); +-} +- +- +-static long sequence_number = 0; +- +-/* Add a name to a linked list. */ +- +-static void +-add_to_list (struct head *head_ptr, const char *name) +-{ +- struct id *newid = xcalloc (sizeof (struct id) + strlen (name), 1); +- struct id *p; +- strcpy (newid->name, name); +- +- if (head_ptr->first) +- head_ptr->last->next = newid; +- else +- head_ptr->first = newid; +- +- /* Check for duplicate symbols. */ +- for (p = head_ptr->first; +- strcmp (name, p->name) != 0; +- p = p->next) +- ; +- if (p != newid) +- { +- head_ptr->last->next = 0; +- free (newid); +- return; +- } +- +- newid->sequence = ++sequence_number; +- head_ptr->last = newid; +- head_ptr->number++; +-} +- +-/* Grab the init priority number from an init function name that +- looks like "_GLOBAL_.I.12345.foo". */ +- +-static int +-extract_init_priority (const char *name) +-{ +- int pos = 0, pri; +- +- while (name[pos] == '_') +- ++pos; +- pos += 10; /* strlen ("GLOBAL__X_") */ +- +- /* Extract init_p number from ctor/dtor name. */ +- pri = atoi (name + pos); +- return pri ? pri : DEFAULT_INIT_PRIORITY; +-} +- +-/* Insertion sort the ids from ctor/dtor list HEAD_PTR in descending order. +- ctors will be run from right to left, dtors from left to right. */ +- +-static void +-sort_ids (struct head *head_ptr) +-{ +- /* id holds the current element to insert. id_next holds the next +- element to insert. id_ptr iterates through the already sorted elements +- looking for the place to insert id. */ +- struct id *id, *id_next, **id_ptr; +- +- id = head_ptr->first; +- +- /* We don't have any sorted elements yet. */ +- head_ptr->first = NULL; +- +- for (; id; id = id_next) +- { +- id_next = id->next; +- id->sequence = extract_init_priority (id->name); +- +- for (id_ptr = &(head_ptr->first); ; id_ptr = &((*id_ptr)->next)) +- if (*id_ptr == NULL +- /* If the sequence numbers are the same, we put the id from the +- file later on the command line later in the list. */ +- || id->sequence > (*id_ptr)->sequence +- /* Hack: do lexical compare, too. +- || (id->sequence == (*id_ptr)->sequence +- && strcmp (id->name, (*id_ptr)->name) > 0) */ +- ) +- { +- id->next = *id_ptr; +- *id_ptr = id; +- break; +- } +- } +- +- /* Now set the sequence numbers properly so write_c_file works. */ +- for (id = head_ptr->first; id; id = id->next) +- id->sequence = ++sequence_number; +-} +- +-/* Write: `prefix', the names on list LIST, `suffix'. */ +- +-static void +-write_list (FILE *stream, const char *prefix, struct id *list) +-{ +- while (list) +- { +- fprintf (stream, "%sx%d,\n", prefix, list->sequence); +- list = list->next; +- } +-} +- +-#if LINK_ELIMINATE_DUPLICATE_LDIRECTORIES +-/* Given a STRING, return nonzero if it occurs in the list in range +- [ARGS_BEGIN,ARGS_END). */ +- +-static int +-is_in_args (const char *string, const char **args_begin, +- const char **args_end) +-{ +- const char **args_pointer; +- for (args_pointer = args_begin; args_pointer != args_end; ++args_pointer) +- if (strcmp (string, *args_pointer) == 0) +- return 1; +- return 0; +-} +-#endif /* LINK_ELIMINATE_DUPLICATE_LDIRECTORIES */ +- +-#ifdef COLLECT_EXPORT_LIST +-/* This function is really used only on AIX, but may be useful. */ +-#if 0 +-static int +-is_in_list (const char *prefix, struct id *list) +-{ +- while (list) +- { +- if (!strcmp (prefix, list->name)) return 1; +- list = list->next; +- } +- return 0; +-} +-#endif +-#endif /* COLLECT_EXPORT_LIST */ +- +-/* Added for debugging purpose. */ +-#ifdef COLLECT_EXPORT_LIST +-static void +-dump_list (FILE *stream, const char *prefix, struct id *list) +-{ +- while (list) +- { +- fprintf (stream, "%s%s,\n", prefix, list->name); +- list = list->next; +- } +-} +-#endif +- +-#if 0 +-static void +-dump_prefix_list (FILE *stream, const char *prefix, struct prefix_list *list) +-{ +- while (list) +- { +- fprintf (stream, "%s%s,\n", prefix, list->prefix); +- list = list->next; +- } +-} +-#endif +- +-static void +-write_list_with_asm (FILE *stream, const char *prefix, struct id *list) +-{ +- while (list) +- { +- fprintf (stream, "%sx%d __asm__ (\"%s\");\n", +- prefix, list->sequence, list->name); +- list = list->next; +- } +-} +- +-/* Write out the constructor and destructor tables statically (for a shared +- object), along with the functions to execute them. */ +- +-static void +-write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED) +-{ +- const char *p, *q; +- char *prefix, *r; +- int frames = (frame_tables.number > 0); +- +- /* Figure out name of output_file, stripping off .so version. */ +- p = strrchr (output_file, '/'); +- if (p == 0) +- p = output_file; +- else +- p++; +- q = p; +- while (q) +- { +- q = strchr (q,'.'); +- if (q == 0) +- { +- q = p + strlen (p); +- break; +- } +- else +- { +- if (strncmp (q, ".so", 3) == 0) +- { +- q += 3; +- break; +- } +- else +- q++; +- } +- } +- /* q points to null at end of the string (or . of the .so version) */ +- prefix = xmalloc (q - p + 1); +- strncpy (prefix, p, q - p); +- prefix[q - p] = 0; +- for (r = prefix; *r; r++) +- if (!ISALNUM ((unsigned char)*r)) +- *r = '_'; +- if (debug) +- notice ("\nwrite_c_file - output name is %s, prefix is %s\n", +- output_file, prefix); +- +- initname = concat ("_GLOBAL__FI_", prefix, NULL); +- fininame = concat ("_GLOBAL__FD_", prefix, NULL); +- +- free (prefix); +- +- /* Write the tables as C code. */ +- +- fprintf (stream, "static int count;\n"); +- fprintf (stream, "typedef void entry_pt();\n"); +- write_list_with_asm (stream, "extern entry_pt ", constructors.first); +- +- if (frames) +- { +- write_list_with_asm (stream, "extern void *", frame_tables.first); +- +- fprintf (stream, "\tstatic void *frame_table[] = {\n"); +- write_list (stream, "\t\t&", frame_tables.first); +- fprintf (stream, "\t0\n};\n"); +- +- /* This must match what's in frame.h. */ +- fprintf (stream, "struct object {\n"); +- fprintf (stream, " void *pc_begin;\n"); +- fprintf (stream, " void *pc_end;\n"); +- fprintf (stream, " void *fde_begin;\n"); +- fprintf (stream, " void *fde_array;\n"); +- fprintf (stream, " __SIZE_TYPE__ count;\n"); +- fprintf (stream, " struct object *next;\n"); +- fprintf (stream, "};\n"); +- +- fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); +- fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); +- +- fprintf (stream, "static void reg_frame () {\n"); +- fprintf (stream, "\tstatic struct object ob;\n"); +- fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); +- fprintf (stream, "\t}\n"); +- +- fprintf (stream, "static void dereg_frame () {\n"); +- fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); +- fprintf (stream, "\t}\n"); +- } +- +- fprintf (stream, "void %s() {\n", initname); +- if (constructors.number > 0 || frames) +- { +- fprintf (stream, "\tstatic entry_pt *ctors[] = {\n"); +- write_list (stream, "\t\t", constructors.first); +- if (frames) +- fprintf (stream, "\treg_frame,\n"); +- fprintf (stream, "\t};\n"); +- fprintf (stream, "\tentry_pt **p;\n"); +- fprintf (stream, "\tif (count++ != 0) return;\n"); +- fprintf (stream, "\tp = ctors + %d;\n", constructors.number + frames); +- fprintf (stream, "\twhile (p > ctors) (*--p)();\n"); +- } +- else +- fprintf (stream, "\t++count;\n"); +- fprintf (stream, "}\n"); +- write_list_with_asm (stream, "extern entry_pt ", destructors.first); +- fprintf (stream, "void %s() {\n", fininame); +- if (destructors.number > 0 || frames) +- { +- fprintf (stream, "\tstatic entry_pt *dtors[] = {\n"); +- write_list (stream, "\t\t", destructors.first); +- if (frames) +- fprintf (stream, "\tdereg_frame,\n"); +- fprintf (stream, "\t};\n"); +- fprintf (stream, "\tentry_pt **p;\n"); +- fprintf (stream, "\tif (--count != 0) return;\n"); +- fprintf (stream, "\tp = dtors;\n"); +- fprintf (stream, "\twhile (p < dtors + %d) (*p++)();\n", +- destructors.number + frames); +- } +- fprintf (stream, "}\n"); +- +- if (shared_obj) +- { +- COLLECT_SHARED_INIT_FUNC(stream, initname); +- COLLECT_SHARED_FINI_FUNC(stream, fininame); +- } +-} +- +-/* Write the constructor/destructor tables. */ +- +-#ifndef LD_INIT_SWITCH +-static void +-write_c_file_glob (FILE *stream, const char *name ATTRIBUTE_UNUSED) +-{ +- /* Write the tables as C code. */ +- +- int frames = (frame_tables.number > 0); +- +- fprintf (stream, "typedef void entry_pt();\n\n"); +- +- write_list_with_asm (stream, "extern entry_pt ", constructors.first); +- +- if (frames) +- { +- write_list_with_asm (stream, "extern void *", frame_tables.first); +- +- fprintf (stream, "\tstatic void *frame_table[] = {\n"); +- write_list (stream, "\t\t&", frame_tables.first); +- fprintf (stream, "\t0\n};\n"); +- +- /* This must match what's in frame.h. */ +- fprintf (stream, "struct object {\n"); +- fprintf (stream, " void *pc_begin;\n"); +- fprintf (stream, " void *pc_end;\n"); +- fprintf (stream, " void *fde_begin;\n"); +- fprintf (stream, " void *fde_array;\n"); +- fprintf (stream, " __SIZE_TYPE__ count;\n"); +- fprintf (stream, " struct object *next;\n"); +- fprintf (stream, "};\n"); +- +- fprintf (stream, "extern void __register_frame_info_table (void *, struct object *);\n"); +- fprintf (stream, "extern void *__deregister_frame_info (void *);\n"); +- +- fprintf (stream, "static void reg_frame () {\n"); +- fprintf (stream, "\tstatic struct object ob;\n"); +- fprintf (stream, "\t__register_frame_info_table (frame_table, &ob);\n"); +- fprintf (stream, "\t}\n"); +- +- fprintf (stream, "static void dereg_frame () {\n"); +- fprintf (stream, "\t__deregister_frame_info (frame_table);\n"); +- fprintf (stream, "\t}\n"); +- } +- +- fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n"); +- fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number + frames); +- write_list (stream, "\t", constructors.first); +- if (frames) +- fprintf (stream, "\treg_frame,\n"); +- fprintf (stream, "\t0\n};\n\n"); +- +- write_list_with_asm (stream, "extern entry_pt ", destructors.first); +- +- fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n"); +- fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number + frames); +- write_list (stream, "\t", destructors.first); +- if (frames) +- fprintf (stream, "\tdereg_frame,\n"); +- fprintf (stream, "\t0\n};\n\n"); +- +- fprintf (stream, "extern entry_pt %s;\n", NAME__MAIN); +- fprintf (stream, "entry_pt *__main_reference = %s;\n\n", NAME__MAIN); +-} +-#endif /* ! LD_INIT_SWITCH */ +- +-static void +-write_c_file (FILE *stream, const char *name) +-{ +- fprintf (stream, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); +-#ifndef LD_INIT_SWITCH +- if (! shared_obj) +- write_c_file_glob (stream, name); +- else +-#endif +- write_c_file_stat (stream, name); +- fprintf (stream, "#ifdef __cplusplus\n}\n#endif\n"); +-} +- +-#ifdef COLLECT_EXPORT_LIST +-static void +-write_aix_file (FILE *stream, struct id *list) +-{ +- for (; list; list = list->next) +- { +- fputs (list->name, stream); +- putc ('\n', stream); +- } +-} +-#endif +- +-#ifdef OBJECT_FORMAT_NONE +- +-/* Generic version to scan the name list of the loaded program for +- the symbols g++ uses for static constructors and destructors. +- +- The constructor table begins at __CTOR_LIST__ and contains a count +- of the number of pointers (or -1 if the constructors are built in a +- separate section by the linker), followed by the pointers to the +- constructor functions, terminated with a null pointer. The +- destructor table has the same format, and begins at __DTOR_LIST__. */ +- +-static void +-scan_prog_file (const char *prog_name, enum pass which_pass) +-{ +- void (*int_handler) (int); +- void (*quit_handler) (int); +- char *real_nm_argv[4]; +- const char **nm_argv = (const char **) real_nm_argv; +- int argc = 0; +- int pipe_fd[2]; +- char *p, buf[1024]; +- FILE *inf; +- +- if (which_pass == PASS_SECOND) +- return; +- +- /* If we do not have an `nm', complain. */ +- if (nm_file_name == 0) +- fatal ("cannot find `nm'"); +- +- nm_argv[argc++] = nm_file_name; +- if (NM_FLAGS[0] != '\0') +- nm_argv[argc++] = NM_FLAGS; +- +- nm_argv[argc++] = prog_name; +- nm_argv[argc++] = (char *) 0; +- +- if (pipe (pipe_fd) < 0) +- fatal_perror ("pipe"); +- +- inf = fdopen (pipe_fd[0], "r"); +- if (inf == (FILE *) 0) +- fatal_perror ("fdopen"); +- +- /* Trace if needed. */ +- if (vflag) +- { +- const char **p_argv; +- const char *str; +- +- for (p_argv = &nm_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) +- fprintf (stderr, " %s", str); +- +- fprintf (stderr, "\n"); +- } +- +- fflush (stdout); +- fflush (stderr); +- +- /* Spawn child nm on pipe. */ +- pid = vfork (); +- if (pid == -1) +- fatal_perror (VFORK_STRING); +- +- if (pid == 0) /* child context */ +- { +- /* setup stdout */ +- if (dup2 (pipe_fd[1], 1) < 0) +- fatal_perror ("dup2 %d 1", pipe_fd[1]); +- +- if (close (pipe_fd[0]) < 0) +- fatal_perror ("close %d", pipe_fd[0]); +- +- if (close (pipe_fd[1]) < 0) +- fatal_perror ("close %d", pipe_fd[1]); +- +- execv (nm_file_name, real_nm_argv); +- fatal_perror ("execv %s", nm_file_name); +- } +- +- /* Parent context from here on. */ +- int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); +-#ifdef SIGQUIT +- quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN); +-#endif +- +- if (close (pipe_fd[1]) < 0) +- fatal_perror ("close %d", pipe_fd[1]); +- +- if (debug) +- fprintf (stderr, "\nnm output with constructors/destructors.\n"); +- +- /* Read each line of nm output. */ +- while (fgets (buf, sizeof buf, inf) != (char *) 0) +- { +- int ch, ch2; +- char *name, *end; +- +- /* If it contains a constructor or destructor name, add the name +- to the appropriate list. */ +- +- for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++) +- if (ch == ' ' && p[1] == 'U' && p[2] == ' ') +- break; +- +- if (ch != '_') +- continue; +- +- name = p; +- /* Find the end of the symbol name. +- Do not include `|', because Encore nm can tack that on the end. */ +- for (end = p; (ch2 = *end) != '\0' && !ISSPACE (ch2) && ch2 != '|'; +- end++) +- continue; +- +- +- *end = '\0'; +- switch (is_ctor_dtor (name)) +- { +- case 1: +- if (which_pass != PASS_LIB) +- add_to_list (&constructors, name); +- break; +- +- case 2: +- if (which_pass != PASS_LIB) +- add_to_list (&destructors, name); +- break; +- +- case 3: +- if (which_pass != PASS_LIB) +- fatal ("init function found in object %s", prog_name); +-#ifndef LD_INIT_SWITCH +- add_to_list (&constructors, name); +-#endif +- break; +- +- case 4: +- if (which_pass != PASS_LIB) +- fatal ("fini function found in object %s", prog_name); +-#ifndef LD_FINI_SWITCH +- add_to_list (&destructors, name); +-#endif +- break; +- +- case 5: +- if (which_pass != PASS_LIB) +- add_to_list (&frame_tables, name); +- break; +- +- default: /* not a constructor or destructor */ +- continue; +- } +- +- if (debug) +- fprintf (stderr, "\t%s\n", buf); +- } +- +- if (debug) +- fprintf (stderr, "\n"); +- +- if (fclose (inf) != 0) +- fatal_perror ("fclose"); +- +- do_wait (nm_file_name); +- +- signal (SIGINT, int_handler); +-#ifdef SIGQUIT +- signal (SIGQUIT, quit_handler); +-#endif +-} +- +-#if SUNOS4_SHARED_LIBRARIES +- +-/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries +- that the output file depends upon and their initialization/finalization +- routines, if any. */ +- +-#include <a.out.h> +-#include <fcntl.h> +-#include <link.h> +-#include <sys/mman.h> +-#include <sys/param.h> +-#include <unistd.h> +-#include <sys/dir.h> +- +-/* pointers to the object file */ +-unsigned object; /* address of memory mapped file */ +-unsigned objsize; /* size of memory mapped to file */ +-char * code; /* pointer to code segment */ +-char * data; /* pointer to data segment */ +-struct nlist *symtab; /* pointer to symbol table */ +-struct link_dynamic *ld; +-struct link_dynamic_2 *ld_2; +-struct head libraries; +- +-/* Map the file indicated by NAME into memory and store its address. */ +- +-static void +-mapfile (const char *name) +-{ +- int fp; +- struct stat s; +- if ((fp = open (name, O_RDONLY)) == -1) +- fatal ("unable to open file '%s'", name); +- if (fstat (fp, &s) == -1) +- fatal ("unable to stat file '%s'", name); +- +- objsize = s.st_size; +- object = (unsigned) mmap (0, objsize, PROT_READ|PROT_WRITE, MAP_PRIVATE, +- fp, 0); +- if (object == (unsigned)-1) +- fatal ("unable to mmap file '%s'", name); +- +- close (fp); +-} +- +-/* Helpers for locatelib. */ +- +-static const char *libname; +- +-static int +-libselect (struct direct *d) +-{ +- return (strncmp (libname, d->d_name, strlen (libname)) == 0); +-} +- +-/* If one file has an additional numeric extension past LIBNAME, then put +- that one first in the sort. If both files have additional numeric +- extensions, then put the one with the higher number first in the sort. +- +- We must verify that the extension is numeric, because Sun saves the +- original versions of patched libraries with a .FCS extension. Files with +- invalid extensions must go last in the sort, so that they will not be used. */ +- +-static int +-libcompare (struct direct **d1, struct direct **d2) +-{ +- int i1, i2 = strlen (libname); +- char *e1 = (*d1)->d_name + i2; +- char *e2 = (*d2)->d_name + i2; +- +- while (*e1 && *e2 && *e1 == '.' && *e2 == '.' +- && e1[1] && ISDIGIT (e1[1]) && e2[1] && ISDIGIT (e2[1])) +- { +- ++e1; +- ++e2; +- i1 = strtol (e1, &e1, 10); +- i2 = strtol (e2, &e2, 10); +- if (i1 != i2) +- return i1 - i2; +- } +- +- if (*e1) +- { +- /* It has a valid numeric extension, prefer this one. */ +- if (*e1 == '.' && e1[1] && ISDIGIT (e1[1])) +- return 1; +- /* It has an invalid numeric extension, must prefer the other one. */ +- else +- return -1; +- } +- else if (*e2) +- { +- /* It has a valid numeric extension, prefer this one. */ +- if (*e2 == '.' && e2[1] && ISDIGIT (e2[1])) +- return -1; +- /* It has an invalid numeric extension, must prefer the other one. */ +- else +- return 1; +- } +- else +- return 0; +-} +- +-/* Given the name NAME of a dynamic dependency, find its pathname and add +- it to the list of libraries. */ +- +-static void +-locatelib (const char *name) +-{ +- static const char **l; +- static int cnt; +- char buf[MAXPATHLEN]; +- char *p, *q; +- const char **pp; +- +- if (l == 0) +- { +- char *ld_rules; +- char *ldr = 0; +- /* counting elements in array, need 1 extra for null */ +- cnt = 1; +- ld_rules = (char *) (ld_2->ld_rules + code); +- if (ld_rules) +- { +- cnt++; +- for (; *ld_rules != 0; ld_rules++) +- if (*ld_rules == ':') +- cnt++; +- ld_rules = (char *) (ld_2->ld_rules + code); +- ldr = xstrdup (ld_rules); +- } +- p = getenv ("LD_LIBRARY_PATH"); +- q = 0; +- if (p) +- { +- cnt++; +- for (q = p ; *q != 0; q++) +- if (*q == ':') +- cnt++; +- q = xstrdup (p); +- } +- l = xmalloc ((cnt + 3) * sizeof (char *)); +- pp = l; +- if (ldr) +- { +- *pp++ = ldr; +- for (; *ldr != 0; ldr++) +- if (*ldr == ':') +- { +- *ldr++ = 0; +- *pp++ = ldr; +- } +- } +- if (q) +- { +- *pp++ = q; +- for (; *q != 0; q++) +- if (*q == ':') +- { +- *q++ = 0; +- *pp++ = q; +- } +- } +- /* built in directories are /lib, /usr/lib, and /usr/local/lib */ +- *pp++ = "/lib"; +- *pp++ = "/usr/lib"; +- *pp++ = "/usr/local/lib"; +- *pp = 0; +- } +- libname = name; +- for (pp = l; *pp != 0 ; pp++) +- { +- struct direct **namelist; +- int entries; +- if ((entries = scandir (*pp, &namelist, libselect, libcompare)) > 0) +- { +- sprintf (buf, "%s/%s", *pp, namelist[entries - 1]->d_name); +- add_to_list (&libraries, buf); +- if (debug) +- fprintf (stderr, "%s\n", buf); +- break; +- } +- } +- if (*pp == 0) +- { +- if (debug) +- notice ("not found\n"); +- else +- fatal ("dynamic dependency %s not found", name); +- } +-} +- +-/* Scan the _DYNAMIC structure of the output file to find shared libraries +- that it depends upon and any constructors or destructors they contain. */ +- +-static void +-scan_libraries (const char *prog_name) +-{ +- struct exec *header; +- char *base; +- struct link_object *lo; +- char buff[MAXPATHLEN]; +- struct id *list; +- +- mapfile (prog_name); +- header = (struct exec *)object; +- if (N_BADMAG (*header)) +- fatal ("bad magic number in file '%s'", prog_name); +- if (header->a_dynamic == 0) +- return; +- +- code = (char *) (N_TXTOFF (*header) + (long) header); +- data = (char *) (N_DATOFF (*header) + (long) header); +- symtab = (struct nlist *) (N_SYMOFF (*header) + (long) header); +- +- if (header->a_magic == ZMAGIC && header->a_entry == 0x20) +- { +- /* shared object */ +- ld = (struct link_dynamic *) (symtab->n_value + code); +- base = code; +- } +- else +- { +- /* executable */ +- ld = (struct link_dynamic *) data; +- base = code-PAGSIZ; +- } +- +- if (debug) +- notice ("dynamic dependencies.\n"); +- +- ld_2 = (struct link_dynamic_2 *) ((long) ld->ld_un.ld_2 + (long)base); +- for (lo = (struct link_object *) ld_2->ld_need; lo; +- lo = (struct link_object *) lo->lo_next) +- { +- char *name; +- lo = (struct link_object *) ((long) lo + code); +- name = (char *) (code + lo->lo_name); +- if (lo->lo_library) +- { +- if (debug) +- fprintf (stderr, "\t-l%s.%d => ", name, lo->lo_major); +- sprintf (buff, "lib%s.so.%d.%d", name, lo->lo_major, lo->lo_minor); +- locatelib (buff); +- } +- else +- { +- if (debug) +- fprintf (stderr, "\t%s\n", name); +- add_to_list (&libraries, name); +- } +- } +- +- if (debug) +- fprintf (stderr, "\n"); +- +- /* Now iterate through the library list adding their symbols to +- the list. */ +- for (list = libraries.first; list; list = list->next) +- scan_prog_file (list->name, PASS_LIB); +-} +- +-#else /* SUNOS4_SHARED_LIBRARIES */ +-#ifdef LDD_SUFFIX +- +-/* Use the List Dynamic Dependencies program to find shared libraries that +- the output file depends upon and their initialization/finalization +- routines, if any. */ +- +-static void +-scan_libraries (const char *prog_name) +-{ +- static struct head libraries; /* list of shared libraries found */ +- struct id *list; +- void (*int_handler) (int); +- void (*quit_handler) (int); +- char *real_ldd_argv[4]; +- const char **ldd_argv = (const char **) real_ldd_argv; +- int argc = 0; +- int pipe_fd[2]; +- char buf[1024]; +- FILE *inf; +- +- /* If we do not have an `ldd', complain. */ +- if (ldd_file_name == 0) +- { +- error ("cannot find `ldd'"); +- return; +- } +- +- ldd_argv[argc++] = ldd_file_name; +- ldd_argv[argc++] = prog_name; +- ldd_argv[argc++] = (char *) 0; +- +- if (pipe (pipe_fd) < 0) +- fatal_perror ("pipe"); +- +- inf = fdopen (pipe_fd[0], "r"); +- if (inf == (FILE *) 0) +- fatal_perror ("fdopen"); +- +- /* Trace if needed. */ +- if (vflag) +- { +- const char **p_argv; +- const char *str; +- +- for (p_argv = &ldd_argv[0]; (str = *p_argv) != (char *) 0; p_argv++) +- fprintf (stderr, " %s", str); +- +- fprintf (stderr, "\n"); +- } +- +- fflush (stdout); +- fflush (stderr); +- +- /* Spawn child ldd on pipe. */ +- pid = vfork (); +- if (pid == -1) +- fatal_perror (VFORK_STRING); +- +- if (pid == 0) /* child context */ +- { +- /* setup stdout */ +- if (dup2 (pipe_fd[1], 1) < 0) +- fatal_perror ("dup2 %d 1", pipe_fd[1]); +- +- if (close (pipe_fd[0]) < 0) +- fatal_perror ("close %d", pipe_fd[0]); +- +- if (close (pipe_fd[1]) < 0) +- fatal_perror ("close %d", pipe_fd[1]); +- +- execv (ldd_file_name, real_ldd_argv); +- fatal_perror ("execv %s", ldd_file_name); +- } +- +- /* Parent context from here on. */ +- int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN); +-#ifdef SIGQUIT +- quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN); +-#endif +- +- if (close (pipe_fd[1]) < 0) +- fatal_perror ("close %d", pipe_fd[1]); +- +- if (debug) +- notice ("\nldd output with constructors/destructors.\n"); +- +- /* Read each line of ldd output. */ +- while (fgets (buf, sizeof buf, inf) != (char *) 0) +- { +- int ch2; +- char *name, *end, *p = buf; +- +- /* Extract names of libraries and add to list. */ +- PARSE_LDD_OUTPUT (p); +- if (p == 0) +- continue; +- +- name = p; +- if (strncmp (name, "not found", sizeof ("not found") - 1) == 0) +- fatal ("dynamic dependency %s not found", buf); +- +- /* Find the end of the symbol name. */ +- for (end = p; +- (ch2 = *end) != '\0' && ch2 != '\n' && !ISSPACE (ch2) && ch2 != '|'; +- end++) +- continue; +- *end = '\0'; +- +- if (access (name, R_OK) == 0) +- add_to_list (&libraries, name); +- else +- fatal ("unable to open dynamic dependency '%s'", buf); +- +- if (debug) +- fprintf (stderr, "\t%s\n", buf); +- } +- if (debug) +- fprintf (stderr, "\n"); +- +- if (fclose (inf) != 0) +- fatal_perror ("fclose"); +- +- do_wait (ldd_file_name); +- +- signal (SIGINT, int_handler); +-#ifdef SIGQUIT +- signal (SIGQUIT, quit_handler); +-#endif +- +- /* Now iterate through the library list adding their symbols to +- the list. */ +- for (list = libraries.first; list; list = list->next) +- scan_prog_file (list->name, PASS_LIB); +-} +- +-#endif /* LDD_SUFFIX */ +-#endif /* SUNOS4_SHARED_LIBRARIES */ +- +-#endif /* OBJECT_FORMAT_NONE */ +- +- +-/* +- * COFF specific stuff. +- */ +- +-#ifdef OBJECT_FORMAT_COFF +- +-#if defined (EXTENDED_COFF) +- +-# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax) +-# define GCC_SYMENT SYMR +-# define GCC_OK_SYMBOL(X) ((X).st == stProc || (X).st == stGlobal) +-# define GCC_SYMINC(X) (1) +-# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax) +-# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0) +- +-#else +- +-# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms) +-# define GCC_SYMENT SYMENT +-# if defined (C_WEAKEXT) +-# define GCC_OK_SYMBOL(X) \ +- (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \ +- ((X).n_scnum > N_UNDEF) && \ +- (aix64_flag \ +- || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \ +- || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))) +-# define GCC_UNDEF_SYMBOL(X) \ +- (((X).n_sclass == C_EXT || (X).n_sclass == C_WEAKEXT) && \ +- ((X).n_scnum == N_UNDEF)) +-# else +-# define GCC_OK_SYMBOL(X) \ +- (((X).n_sclass == C_EXT) && \ +- ((X).n_scnum > N_UNDEF) && \ +- (aix64_flag \ +- || (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) \ +- || ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))) +-# define GCC_UNDEF_SYMBOL(X) \ +- (((X).n_sclass == C_EXT) && ((X).n_scnum == N_UNDEF)) +-# endif +-# define GCC_SYMINC(X) ((X).n_numaux+1) +-# define GCC_SYMZERO(X) 0 +- +-/* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */ +-#ifdef _AIX51 +-# define GCC_CHECK_HDR(X) \ +- ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ +- || (HEADER (X).f_magic == 0767 && aix64_flag)) +-#else +-# define GCC_CHECK_HDR(X) \ +- ((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \ +- || (HEADER (X).f_magic == 0757 && aix64_flag)) +-#endif +- +-#endif +- +-#ifdef COLLECT_EXPORT_LIST +-/* Array of standard AIX libraries which should not +- be scanned for ctors/dtors. */ +-static const char *const aix_std_libs[] = { +- "/unix", +- "/lib/libc.a", +- "/lib/libm.a", +- "/lib/libc_r.a", +- "/lib/libm_r.a", +- "/usr/lib/libc.a", +- "/usr/lib/libm.a", +- "/usr/lib/libc_r.a", +- "/usr/lib/libm_r.a", +- "/usr/lib/threads/libc.a", +- "/usr/ccs/lib/libc.a", +- "/usr/ccs/lib/libm.a", +- "/usr/ccs/lib/libc_r.a", +- "/usr/ccs/lib/libm_r.a", +- NULL +-}; +- +-/* This function checks the filename and returns 1 +- if this name matches the location of a standard AIX library. */ +-static int ignore_library (const char *); +-static int +-ignore_library (const char *name) +-{ +- const char *const *p = &aix_std_libs[0]; +- while (*p++ != NULL) +- if (! strcmp (name, *p)) return 1; +- return 0; +-} +-#endif /* COLLECT_EXPORT_LIST */ +- +-#if defined (HAVE_DECL_LDGETNAME) && !HAVE_DECL_LDGETNAME +-extern char *ldgetname (LDFILE *, GCC_SYMENT *); +-#endif +- +-/* COFF version to scan the name list of the loaded program for +- the symbols g++ uses for static constructors and destructors. +- +- The constructor table begins at __CTOR_LIST__ and contains a count +- of the number of pointers (or -1 if the constructors are built in a +- separate section by the linker), followed by the pointers to the +- constructor functions, terminated with a null pointer. The +- destructor table has the same format, and begins at __DTOR_LIST__. */ +- +-static void +-scan_prog_file (const char *prog_name, enum pass which_pass) +-{ +- LDFILE *ldptr = NULL; +- int sym_index, sym_count; +- int is_shared = 0; +- +- if (which_pass != PASS_FIRST && which_pass != PASS_OBJ) +- return; +- +-#ifdef COLLECT_EXPORT_LIST +- /* We do not need scanning for some standard C libraries. */ +- if (which_pass == PASS_FIRST && ignore_library (prog_name)) +- return; +- +- /* On AIX we have a loop, because there is not much difference +- between an object and an archive. This trick allows us to +- eliminate scan_libraries() function. */ +- do +- { +-#endif +- /* Some platforms (e.g. OSF4) declare ldopen as taking a +- non-const char * filename parameter, even though it will not +- modify that string. So we must cast away const-ness here, +- which will cause -Wcast-qual to burp. */ +- if ((ldptr = ldopen ((char *)prog_name, ldptr)) != NULL) +- { +- if (! MY_ISCOFF (HEADER (ldptr).f_magic)) +- fatal ("%s: not a COFF file", prog_name); +- +- if (GCC_CHECK_HDR (ldptr)) +- { +- sym_count = GCC_SYMBOLS (ldptr); +- sym_index = GCC_SYMZERO (ldptr); +- +-#ifdef COLLECT_EXPORT_LIST +- /* Is current archive member a shared object? */ +- is_shared = HEADER (ldptr).f_flags & F_SHROBJ; +-#endif +- +- while (sym_index < sym_count) +- { +- GCC_SYMENT symbol; +- +- if (ldtbread (ldptr, sym_index, &symbol) <= 0) +- break; +- sym_index += GCC_SYMINC (symbol); +- +- if (GCC_OK_SYMBOL (symbol)) +- { +- char *name; +- +- if ((name = ldgetname (ldptr, &symbol)) == NULL) +- continue; /* Should never happen. */ +- +-#ifdef XCOFF_DEBUGGING_INFO +- /* All AIX function names have a duplicate entry +- beginning with a dot. */ +- if (*name == '.') +- ++name; +-#endif +- +- switch (is_ctor_dtor (name)) +- { +- case 1: +- if (! is_shared) +- add_to_list (&constructors, name); +-#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) +- if (which_pass == PASS_OBJ) +- add_to_list (&exports, name); +-#endif +- break; +- +- case 2: +- if (! is_shared) +- add_to_list (&destructors, name); +-#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) +- if (which_pass == PASS_OBJ) +- add_to_list (&exports, name); +-#endif +- break; +- +-#ifdef COLLECT_EXPORT_LIST +- case 3: +-#ifndef LD_INIT_SWITCH +- if (is_shared) +- add_to_list (&constructors, name); +-#endif +- break; +- +- case 4: +-#ifndef LD_INIT_SWITCH +- if (is_shared) +- add_to_list (&destructors, name); +-#endif +- break; +-#endif +- +- case 5: +- if (! is_shared) +- add_to_list (&frame_tables, name); +-#if defined (COLLECT_EXPORT_LIST) && !defined (LD_INIT_SWITCH) +- if (which_pass == PASS_OBJ) +- add_to_list (&exports, name); +-#endif +- break; +- +- default: /* not a constructor or destructor */ +-#ifdef COLLECT_EXPORT_LIST +- /* Explicitly export all global symbols when +- building a shared object on AIX, but do not +- re-export symbols from another shared object +- and do not export symbols if the user +- provides an explicit export list. */ +- if (shared_obj && !is_shared +- && which_pass == PASS_OBJ && !export_flag) +- add_to_list (&exports, name); +-#endif +- continue; +- } +- +- if (debug) +-#if !defined(EXTENDED_COFF) +- fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n", +- symbol.n_scnum, symbol.n_sclass, +- (symbol.n_type ? "0" : ""), symbol.n_type, +- name); +-#else +- fprintf (stderr, +- "\tiss = %5d, value = %5ld, index = %5d, name = %s\n", +- symbol.iss, (long) symbol.value, symbol.index, name); +-#endif +- } +- } +- } +-#ifdef COLLECT_EXPORT_LIST +- else +- { +- /* If archive contains both 32-bit and 64-bit objects, +- we want to skip objects in other mode so mismatch normal. */ +- if (debug) +- fprintf (stderr, "%s : magic=%o aix64=%d mismatch\n", +- prog_name, HEADER (ldptr).f_magic, aix64_flag); +- } +-#endif +- } +- else +- { +- fatal ("%s: cannot open as COFF file", prog_name); +- } +-#ifdef COLLECT_EXPORT_LIST +- /* On AIX loop continues while there are more members in archive. */ +- } +- while (ldclose (ldptr) == FAILURE); +-#else +- /* Otherwise we simply close ldptr. */ +- (void) ldclose(ldptr); +-#endif +-} +-#endif /* OBJECT_FORMAT_COFF */ +- +-#ifdef COLLECT_EXPORT_LIST +-/* Given a library name without "lib" prefix, this function +- returns a full library name including a path. */ +-static char * +-resolve_lib_name (const char *name) +-{ +- char *lib_buf; +- int i, j, l = 0; +- /* Library extensions for AIX dynamic linking. */ +- const char * const libexts[2] = {"a", "so"}; +- +- for (i = 0; libpaths[i]; i++) +- if (libpaths[i]->max_len > l) +- l = libpaths[i]->max_len; +- +- lib_buf = xmalloc (l + strlen(name) + 10); +- +- for (i = 0; libpaths[i]; i++) +- { +- struct prefix_list *list = libpaths[i]->plist; +- for (; list; list = list->next) +- { +- /* The following lines are needed because path_prefix list +- may contain directories both with trailing '/' and +- without it. */ +- const char *p = ""; +- if (list->prefix[strlen(list->prefix)-1] != '/') +- p = "/"; +- for (j = 0; j < 2; j++) +- { +- sprintf (lib_buf, "%s%slib%s.%s", +- list->prefix, p, name, +- libexts[(j + aixrtl_flag) % 2]); +- if (debug) fprintf (stderr, "searching for: %s\n", lib_buf); +- if (file_exists (lib_buf)) +- { +- if (debug) fprintf (stderr, "found: %s\n", lib_buf); +- return (lib_buf); +- } +- } +- } +- } +- if (debug) +- fprintf (stderr, "not found\n"); +- else +- fatal ("library lib%s not found", name); +- return (NULL); +-} +-#endif /* COLLECT_EXPORT_LIST */ +diff -ruN gcc-3.4.5-20060117-1/gcc/config/i386/cygming.h.orig gcc-3.4.5-20060117-1-winelf/gcc/config/i386/cygming.h.orig +--- gcc-3.4.5-20060117-1/gcc/config/i386/cygming.h.orig 2004-06-07 23:30:32.000000000 -0700 ++++ gcc-3.4.5-20060117-1-winelf/gcc/config/i386/cygming.h.orig 1969-12-31 16:00:00.000000000 -0800 +@@ -1,391 +0,0 @@ +-/* Operating system specific defines to be used when targeting GCC for +- hosting on Windows32, using a Unix style C library and tools. +- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +- Free Software Foundation, Inc. +- +-This file is part of GCC. +- +-GCC is free software; you can redistribute it and/or modify +-it under the terms of the GNU General Public License as published by +-the Free Software Foundation; either version 2, or (at your option) +-any later version. +- +-GCC is distributed in the hope that it will be useful, +-but WITHOUT ANY WARRANTY; without even the implied warranty of +-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-GNU General Public License for more details. +- +-You should have received a copy of the GNU General Public License +-along with GCC; see the file COPYING. If not, write to +-the Free Software Foundation, 59 Temple Place - Suite 330, +-Boston, MA 02111-1307, USA. */ +- +-#define DBX_DEBUGGING_INFO 1 +-#define SDB_DEBUGGING_INFO 1 +-#undef PREFERRED_DEBUGGING_TYPE +-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +- +-#define TARGET_EXECUTABLE_SUFFIX ".exe" +- +-#define TARGET_IS_PE_COFF 1 +- +-#include <stdio.h> +- +-/* Masks for subtarget switches used by other files. */ +-#define MASK_NOP_FUN_DLLIMPORT 0x08000000 /* Ignore dllimport for functions */ +- +-/* Used in winnt.c. */ +-#define TARGET_NOP_FUN_DLLIMPORT (target_flags & MASK_NOP_FUN_DLLIMPORT) +- +-#undef SUBTARGET_SWITCHES +-#define SUBTARGET_SWITCHES \ +-{ "cygwin", 0, N_("Use the Cygwin interface") }, \ +-{ "no-cygwin", 0, N_("Use the Mingw32 interface") }, \ +-{ "windows", 0, N_("Create GUI application") }, \ +-{ "no-win32", 0, N_("Don't set Windows defines") }, \ +-{ "win32", 0, N_("Set Windows defines") }, \ +-{ "console", 0, N_("Create console application") },\ +-{ "dll", 0, N_("Generate code for a DLL") }, \ +-{ "nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, \ +- N_("Ignore dllimport for functions") }, \ +-{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" }, \ +-{ "threads", 0, N_("Use Mingw-specific thread support") }, +- +-#define MAYBE_UWIN_CPP_BUILTINS() /* Nothing. */ +- +-/* Support the __declspec keyword by turning them into attributes. +- We currently only support: dllimport and dllexport. +- Note that the current way we do this may result in a collision with +- predefined attributes later on. This can be solved by using one attribute, +- say __declspec__, and passing args to it. The problem with that approach +- is that args are not accumulated: each new appearance would clobber any +- existing args. */ +- +-#define TARGET_OS_CPP_BUILTINS() \ +- do \ +- { \ +- builtin_define ("_X86_=1"); \ +- builtin_assert ("system=winnt"); \ +- builtin_define ("__stdcall=__attribute__((__stdcall__))"); \ +- builtin_define ("__fastcall=__attribute__((__fastcall__))"); \ +- builtin_define ("__cdecl=__attribute__((__cdecl__))"); \ +- builtin_define ("__declspec(x)=__attribute__((x))"); \ +- if (!flag_iso) \ +- { \ +- builtin_define ("_stdcall=__attribute__((__stdcall__))"); \ +- builtin_define ("_fastcall=__attribute__((__fastcall__))"); \ +- builtin_define ("_cdecl=__attribute__((__cdecl__))"); \ +- } \ +- MAYBE_UWIN_CPP_BUILTINS (); \ +- EXTRA_OS_CPP_BUILTINS (); \ +- } \ +- while (0) +- +-/* Get tree.c to declare a target-specific specialization of +- merge_decl_attributes. */ +-#define TARGET_DLLIMPORT_DECL_ATTRIBUTES +- +-/* This macro defines names of additional specifications to put in the specs +- that can be used in various specifications like CC1_SPEC. Its definition +- is an initializer with a subgrouping for each command option. +- +- Each subgrouping contains a string constant, that defines the +- specification name, and a string constant that used by the GCC driver +- program. +- +- Do not define this macro if it does not need to do anything. */ +- +-#undef SUBTARGET_EXTRA_SPECS +-#define SUBTARGET_EXTRA_SPECS \ +- { "mingw_include_path", DEFAULT_TARGET_MACHINE } +- +-#undef MATH_LIBRARY +-#define MATH_LIBRARY "" +- +-#define SIZE_TYPE "unsigned int" +-#define PTRDIFF_TYPE "int" +-#define WCHAR_TYPE_SIZE 16 +-#define WCHAR_TYPE "short unsigned int" +- +- +-/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */ +-#define HANDLE_PRAGMA_PACK_PUSH_POP 1 +- +-union tree_node; +-#define TREE union tree_node * +- +-#undef EXTRA_SECTIONS +-#define EXTRA_SECTIONS in_drectve +- +-#undef EXTRA_SECTION_FUNCTIONS +-#define EXTRA_SECTION_FUNCTIONS \ +- DRECTVE_SECTION_FUNCTION \ +- SWITCH_TO_SECTION_FUNCTION +- +-#define DRECTVE_SECTION_FUNCTION \ +-void \ +-drectve_section (void) \ +-{ \ +- if (in_section != in_drectve) \ +- { \ +- fprintf (asm_out_file, "%s\n", "\t.section .drectve\n"); \ +- in_section = in_drectve; \ +- } \ +-} +-void drectve_section (void); +- +-/* Older versions of gas don't handle 'r' as data. +- Explicitly set data flag with 'd'. */ +-#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata,\"dr\"" +- +-/* Switch to SECTION (an `enum in_section'). +- +- ??? This facility should be provided by GCC proper. +- The problem is that we want to temporarily switch sections in +- ASM_DECLARE_OBJECT_NAME and then switch back to the original section +- afterwards. */ +-#define SWITCH_TO_SECTION_FUNCTION \ +-void switch_to_section (enum in_section, tree); \ +-void \ +-switch_to_section (enum in_section section, tree decl) \ +-{ \ +- switch (section) \ +- { \ +- case in_text: text_section (); break; \ +- case in_data: data_section (); break; \ +- case in_readonly_data: readonly_data_section (); break; \ +- case in_named: named_section (decl, NULL, 0); break; \ +- case in_drectve: drectve_section (); break; \ +- default: abort (); break; \ +- } \ +-} +- +-/* Don't allow flag_pic to propagate since gas may produce invalid code +- otherwise. */ +- +-#undef SUBTARGET_OVERRIDE_OPTIONS +-#define SUBTARGET_OVERRIDE_OPTIONS \ +-do { \ +- if (flag_pic) \ +- { \ +- warning ("-f%s ignored for target (all code is position independent)",\ +- (flag_pic > 1) ? "PIC" : "pic"); \ +- flag_pic = 0; \ +- } \ +-} while (0) \ +- +-/* Define this macro if references to a symbol must be treated +- differently depending on something about the variable or +- function named by the symbol (such as what section it is in). +- +- On i386 running Windows NT, modify the assembler name with a suffix +- consisting of an atsign (@) followed by string of digits that represents +- the number of bytes of arguments passed to the function, if it has the +- attribute STDCALL. +- +- In addition, we must mark dll symbols specially. Definitions of +- dllexport'd objects install some info in the .drectve section. +- References to dllimport'd objects are fetched indirectly via +- _imp__. If both are declared, dllexport overrides. This is also +- needed to implement one-only vtables: they go into their own +- section and we need to set DECL_SECTION_NAME so we do that here. +- Note that we can be called twice on the same decl. */ +- +-#undef TARGET_ENCODE_SECTION_INFO +-#define TARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info +-#undef TARGET_STRIP_NAME_ENCODING +-#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full +- +-/* Output a reference to a label. */ +-#undef ASM_OUTPUT_LABELREF +-#define ASM_OUTPUT_LABELREF i386_pe_output_labelref +- +-/* Output a common block. */ +-#undef ASM_OUTPUT_COMMON +-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ +-do { \ +- if (i386_pe_dllexport_name_p (NAME)) \ +- i386_pe_record_exported_symbol (NAME, 1); \ +- if (! i386_pe_dllimport_name_p (NAME)) \ +- { \ +- fprintf ((STREAM), "\t.comm\t"); \ +- assemble_name ((STREAM), (NAME)); \ +- fprintf ((STREAM), ", %d\t%s %d\n", \ +- (int)(ROUNDED), ASM_COMMENT_START, (int)(SIZE)); \ +- } \ +-} while (0) +- +-/* Output the label for an initialized variable. */ +-#undef ASM_DECLARE_OBJECT_NAME +-#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \ +-do { \ +- if (i386_pe_dllexport_name_p (NAME)) \ +- i386_pe_record_exported_symbol (NAME, 1); \ +- ASM_OUTPUT_LABEL ((STREAM), (NAME)); \ +-} while (0) +- +- +-/* Emit code to check the stack when allocating more that 4000 +- bytes in one go. */ +- +-#define CHECK_STACK_LIMIT 4000 +- +-/* By default, target has a 80387, uses IEEE compatible arithmetic, +- returns float values in the 387 and needs stack probes. +- We also align doubles to 64-bits for MSVC default compatibility. */ +- +-#undef TARGET_SUBTARGET_DEFAULT +-#define TARGET_SUBTARGET_DEFAULT \ +- (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE \ +- | MASK_ALIGN_DOUBLE) +- +-/* This is how to output an assembler line +- that says to advance the location counter +- to a multiple of 2**LOG bytes. */ +- +-#undef ASM_OUTPUT_ALIGN +-#define ASM_OUTPUT_ALIGN(FILE,LOG) \ +- if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG)) +- +-/* Define this macro if in some cases global symbols from one translation +- unit may not be bound to undefined symbols in another translation unit +- without user intervention. For instance, under Microsoft Windows +- symbols must be explicitly imported from shared libraries (DLLs). */ +-#define MULTIPLE_SYMBOL_SPACES +- +-extern void i386_pe_unique_section (TREE, int); +-#define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section +- +-#define SUPPORTS_ONE_ONLY 1 +- +-/* Switch into a generic section. */ +-#define TARGET_ASM_NAMED_SECTION i386_pe_asm_named_section +- +-/* Select attributes for named sections. */ +-#define TARGET_SECTION_TYPE_FLAGS i386_pe_section_type_flags +- +-/* Write the extra assembler code needed to declare a function +- properly. If we are generating SDB debugging information, this +- will happen automatically, so we only need to handle other cases. */ +-#undef ASM_DECLARE_FUNCTION_NAME +-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ +- do \ +- { \ +- if (i386_pe_dllexport_name_p (NAME)) \ +- i386_pe_record_exported_symbol (NAME, 0); \ +- if (write_symbols != SDB_DEBUG) \ +- i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \ +- ASM_OUTPUT_LABEL (FILE, NAME); \ +- } \ +- while (0) +- +-/* Add an external function to the list of functions to be declared at +- the end of the file. */ +-#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ +- do \ +- { \ +- if (TREE_CODE (DECL) == FUNCTION_DECL) \ +- i386_pe_record_external_function (NAME); \ +- } \ +- while (0) +- +-/* Declare the type properly for any external libcall. */ +-#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ +- i386_pe_declare_function_type (FILE, XSTR (FUN, 0), 1) +- +-/* This says out to put a global symbol in the BSS section. */ +-#undef ASM_OUTPUT_ALIGNED_BSS +-#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ +- asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN)) +- +-/* Output function declarations at the end of the file. */ +-#undef TARGET_ASM_FILE_END +-#define TARGET_ASM_FILE_END i386_pe_file_end +- +-#undef ASM_COMMENT_START +-#define ASM_COMMENT_START " #" +- +-/* DWARF2 Unwinding doesn't work with exception handling yet. To make +- it work, we need to build a libgcc_s.dll, and dcrt0.o should be +- changed to call __register_frame_info/__deregister_frame_info. */ +-#define DWARF2_UNWIND_INFO 0 +- +-/* Don't assume anything about the header files. */ +-#define NO_IMPLICIT_EXTERN_C +- +-#undef PROFILE_HOOK +-#define PROFILE_HOOK(LABEL) \ +- if (MAIN_NAME_P (DECL_NAME (current_function_decl))) \ +- { \ +- emit_call_insn (gen_rtx (CALL, VOIDmode, \ +- gen_rtx_MEM (FUNCTION_MODE, \ +- gen_rtx_SYMBOL_REF (Pmode, "_monstartup")), \ +- const0_rtx)); \ +- } +- +-/* Java Native Interface (JNI) methods on Win32 are invoked using the +- stdcall calling convention. */ +-#undef MODIFY_JNI_METHOD_CALL +-#define MODIFY_JNI_METHOD_CALL(MDECL) \ +- build_type_attribute_variant ((MDECL), \ +- build_tree_list (get_identifier ("stdcall"), \ +- NULL)) +- +-/* External function declarations. */ +- +-extern void i386_pe_record_external_function (const char *); +-extern void i386_pe_declare_function_type (FILE *, const char *, int); +-extern void i386_pe_record_exported_symbol (const char *, int); +-extern void i386_pe_file_end (void); +-extern int i386_pe_dllexport_name_p (const char *); +-extern int i386_pe_dllimport_name_p (const char *); +- +-/* For Win32 ABI compatibility */ +-#undef DEFAULT_PCC_STRUCT_RETURN +-#define DEFAULT_PCC_STRUCT_RETURN 0 +- +-/* MSVC returns aggregate types of up to 8 bytes via registers. +- See i386.c:ix86_return_in_memory. */ +-#undef MS_AGGREGATE_RETURN +-#define MS_AGGREGATE_RETURN 1 +- +-/* No data type wants to be aligned rounder than this. */ +-#undef BIGGEST_ALIGNMENT +-#define BIGGEST_ALIGNMENT 128 +- +-/* Native complier aligns internal doubles in structures on dword boundaries. */ +-#undef BIGGEST_FIELD_ALIGNMENT +-#define BIGGEST_FIELD_ALIGNMENT 64 +- +-/* A bit-field declared as `int' forces `int' alignment for the struct. */ +-#undef PCC_BITFIELD_TYPE_MATTERS +-#define PCC_BITFIELD_TYPE_MATTERS 1 +-#define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec) +- +-/* Enable alias attribute support. */ +-#ifndef SET_ASM_OP +-#define SET_ASM_OP "\t.set\t" +-#endif +-/* This implements the `alias' attribute, keeping any stdcall or +- fastcall decoration. */ +-#undef ASM_OUTPUT_DEF_FROM_DECLS +-#define ASM_OUTPUT_DEF_FROM_DECLS(STREAM, DECL, TARGET) \ +- do \ +- { \ +- const char *alias; \ +- rtx rtlname = XEXP (DECL_RTL (DECL), 0); \ +- if (GET_CODE (rtlname) == SYMBOL_REF) \ +- alias = XSTR (rtlname, 0); \ +- else \ +- abort (); \ +- if (TREE_CODE (DECL) == FUNCTION_DECL) \ +- i386_pe_declare_function_type (STREAM, alias, \ +- TREE_PUBLIC (DECL)); \ +- ASM_OUTPUT_DEF (STREAM, alias, IDENTIFIER_POINTER (TARGET)); \ +- } while (0) +- +-#undef TREE +- +-#ifndef BUFSIZ +-# undef FILE +-#endif +diff -ruN gcc-3.4.5-20060117-1/gcc/config/i386/i386.c.orig gcc-3.4.5-20060117-1-winelf/gcc/config/i386/i386.c.orig +--- gcc-3.4.5-20060117-1/gcc/config/i386/i386.c.orig 2005-08-03 07:15:28.000000000 -0700 ++++ gcc-3.4.5-20060117-1-winelf/gcc/config/i386/i386.c.orig 1969-12-31 16:00:00.000000000 -0800 +@@ -1,16094 +0,0 @@ +-/* Subroutines used for code generation on IA-32. +- Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +- 2002, 2003, 2004 Free Software Foundation, Inc. +- +-This file is part of GCC. +- +-GCC is free software; you can redistribute it and/or modify +-it under the terms of the GNU General Public License as published by +-the Free Software Foundation; either version 2, or (at your option) +-any later version. +- +-GCC is distributed in the hope that it will be useful, +-but WITHOUT ANY WARRANTY; without even the implied warranty of +-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-GNU General Public License for more details. +- +-You should have received a copy of the GNU General Public License +-along with GCC; see the file COPYING. If not, write to +-the Free Software Foundation, 59 Temple Place - Suite 330, +-Boston, MA 02111-1307, USA. */ +- +-#include "config.h" +-#include "system.h" +-#include "coretypes.h" +-#include "tm.h" +-#include "rtl.h" +-#include "tree.h" +-#include "tm_p.h" +-#include "regs.h" +-#include "hard-reg-set.h" +-#include "real.h" +-#include "insn-config.h" +-#include "conditions.h" +-#include "output.h" +-#include "insn-attr.h" +-#include "flags.h" +-#include "except.h" +-#include "function.h" +-#include "recog.h" +-#include "expr.h" +-#include "optabs.h" +-#include "toplev.h" +-#include "basic-block.h" +-#include "ggc.h" +-#include "target.h" +-#include "target-def.h" +-#include "langhooks.h" +-#include "cgraph.h" +- +-#ifndef CHECK_STACK_LIMIT +-#define CHECK_STACK_LIMIT (-1) +-#endif +- +-/* Return index of given mode in mult and division cost tables. */ +-#define MODE_INDEX(mode) \ +- ((mode) == QImode ? 0 \ +- : (mode) == HImode ? 1 \ +- : (mode) == SImode ? 2 \ +- : (mode) == DImode ? 3 \ +- : 4) +- +-/* Processor costs (relative to an add) */ +-static const +-struct processor_costs size_cost = { /* costs for tunning for size */ +- 2, /* cost of an add instruction */ +- 3, /* cost of a lea instruction */ +- 2, /* variable shift costs */ +- 3, /* constant shift costs */ +- {3, 3, 3, 3, 5}, /* cost of starting a multiply */ +- 0, /* cost of multiply per each bit set */ +- {3, 3, 3, 3, 5}, /* cost of a divide/mod */ +- 3, /* cost of movsx */ +- 3, /* cost of movzx */ +- 0, /* "large" insn */ +- 2, /* MOVE_RATIO */ +- 2, /* cost for loading QImode using movzbl */ +- {2, 2, 2}, /* cost of loading integer registers +- in QImode, HImode and SImode. +- Relative to reg-reg move (2). */ +- {2, 2, 2}, /* cost of storing integer registers */ +- 2, /* cost of reg,reg fld/fst */ +- {2, 2, 2}, /* cost of loading fp registers +- in SFmode, DFmode and XFmode */ +- {2, 2, 2}, /* cost of loading integer registers */ +- 3, /* cost of moving MMX register */ +- {3, 3}, /* cost of loading MMX registers +- in SImode and DImode */ +- {3, 3}, /* cost of storing MMX registers +- in SImode and DImode */ +- 3, /* cost of moving SSE register */ +- {3, 3, 3}, /* cost of loading SSE registers +- in SImode, DImode and TImode */ +- {3, 3, 3}, /* cost of storing SSE registers +- in SImode, DImode and TImode */ +- 3, /* MMX or SSE register to integer */ +- 0, /* size of prefetch block */ +- 0, /* number of parallel prefetches */ +- 1, /* Branch cost */ +- 2, /* cost of FADD and FSUB insns. */ +- 2, /* cost of FMUL instruction. */ +- 2, /* cost of FDIV instruction. */ +- 2, /* cost of FABS instruction. */ +- 2, /* cost of FCHS instruction. */ +- 2, /* cost of FSQRT instruction. */ +-}; +- +-/* Processor costs (relative to an add) */ +-static const +-struct processor_costs i386_cost = { /* 386 specific costs */ +- 1, /* cost of an add instruction */ +- 1, /* cost of a lea instruction */ +- 3, /* variable shift costs */ +- 2, /* constant shift costs */ +- {6, 6, 6, 6, 6}, /* cost of starting a multiply */ +- 1, /* cost of multiply per each bit set */ +- {23, 23, 23, 23, 23}, /* cost of a divide/mod */ +- 3, /* cost of movsx */ +- 2, /* cost of movzx */ +- 15, /* "large" insn */ +- 3, /* MOVE_RATIO */ +- 4, /* cost for loading QImode using movzbl */ +- {2, 4, 2}, /* cost of loading integer registers +- in QImode, HImode and SImode. +- Relative to reg-reg move (2). */ +- {2, 4, 2}, /* cost of storing integer registers */ +- 2, /* cost of reg,reg fld/fst */ +- {8, 8, 8}, /* cost of loading fp registers +- in SFmode, DFmode and XFmode */ +- {8, 8, 8}, /* cost of loading integer registers */ +- 2, /* cost of moving MMX register */ +- {4, 8}, /* cost of loading MMX registers +- in SImode and DImode */ +- {4, 8}, /* cost of storing MMX registers +- in SImode and DImode */ +- 2, /* cost of moving SSE register */ +- {4, 8, 16}, /* cost of loading SSE registers +- in SImode, DImode and TImode */ +- {4, 8, 16}, /* cost of storing SSE registers +- in SImode, DImode and TImode */ +- 3, /* MMX or SSE register to integer */ +- 0, /* size of prefetch block */ +- 0, /* number of parallel prefetches */ +- 1, /* Branch cost */ +- 23, /* cost of FADD and FSUB insns. */ +- 27, /* cost of FMUL instruction. */ +- 88, /* cost of FDIV instruction. */ +- 22, /* cost of FABS instruction. */ +- 24, /* cost of FCHS instruction. */ +- 122, /* cost of FSQRT instruction. */ +-}; +- +-static const +-struct processor_costs i486_cost = { /* 486 specific costs */ +- 1, /* cost of an add instruction */ +- 1, /* cost of a lea instruction */ +- 3, /* variable shift costs */ +- 2, /* constant shift costs */ +- {12, 12, 12, 12, 12}, /* cost of starting a multiply */ +- 1, /* cost of multiply per each bit set */ +- {40, 40, 40, 40, 40}, /* cost of a divide/mod */ +- 3, /* cost of movsx */ +- 2, /* cost of movzx */ +- 15, /* "large" insn */ +- 3, /* MOVE_RATIO */ +- 4, /* cost for loading QImode using movzbl */ +- {2, 4, 2}, /* cost of loading integer registers +- in QImode, HImode and SImode. +- Relative to reg-reg move (2). */ +- {2, 4, 2}, /* cost of storing integer registers */ +- 2, /* cost of reg,reg fld/fst */ +- {8, 8, 8}, /* cost of loading fp registers +- in SFmode, DFmode and XFmode */ +- {8, 8, 8}, /* cost of loading integer registers */ +- 2, /* cost of moving MMX register */ +- {4, 8}, /* cost of loading MMX registers +- in SImode and DImode */ +- {4, 8}, /* cost of storing MMX registers +- in SImode and DImode */ +- 2, /* cost of moving SSE register */ +- {4, 8, 16}, /* cost of loading SSE registers +- in SImode, DImode and TImode */ +- {4, 8, 16}, /* cost of storing SSE registers +- in SImode, DImode and TImode */ +- 3, /* MMX or SSE register to integer */ +- 0, /* size of prefetch block */ +- 0, /* number of parallel prefetches */ +- 1, /* Branch cost */ +- 8, /* cost of FADD and FSUB insns. */ +- 16, /* cost of FMUL instruction. */ +- 73, /* cost of FDIV instruction. */ +- 3, /* cost of FABS instruction. */ +- 3, /* cost of FCHS instruction. */ +- 83, /* cost of FSQRT instruction. */ +-}; +- +-static const +-struct processor_costs pentium_cost = { +- 1, /* cost of an add instruction */ +- 1, /* cost of a lea instruction */ +- 4, /* variable shift costs */ +- 1, /* constant shift costs */ +- {11, 11, 11, 11, 11}, /* cost of starting a multiply */ +- 0, /* cost of multiply per each bit set */ +- {25, 25, 25, 25, 25}, /* cost of a divide/mod */ +- 3, /* cost of movsx */ +- 2, /* cost of movzx */ +- 8, /* "large" insn */ +- 6, /* MOVE_RATIO */ +- 6, /* cost for loading QImode using movzbl */ +- {2, 4, 2}, /* cost of loading integer registers +- in QImode, HImode and SImode. +- Relative to reg-reg move (2). */ +- {2, 4, 2}, /* cost of storing integer registers */ +- 2, /* cost of reg,reg fld/fst */ +- {2, 2, 6}, /* cost of loading fp registers +- in SFmode, DFmode and XFmode */ +- {4, 4, 6}, /* cost of loading integer registers */ +- 8, /* cost of moving MMX register */ +- {8, 8}, /* cost of loading MMX registers +- in SImode and DImode */ +- {8, 8}, /* cost of storing MMX registers +- in SImode and DImode */ +- 2, /* cost of moving SSE register */ +- {4, 8, 16}, /* cost of loading SSE registers +- in SImode, DImode and TImode */ +- {4, 8, 16}, /* cost of storing SSE registers +- in SImode, DImode and TImode */ +- 3, /* MMX or SSE register to integer */ +- 0, /* size of prefetch block */ +- 0, /* number of parallel prefetches */ +- 2, /* Branch cost */ +- 3, /* cost of FADD and FSUB insns. */ +- 3, /* cost of FMUL instruction. */ +- 39, /* cost of FDIV instruction. */ +- 1, /* cost of FABS instruction. */ +- 1, /* cost of FCHS instruction. */ +- 70, /* cost of FSQRT instruction. */ +-}; +- +-static const +-struct processor_costs pentiumpro_cost = { +- 1, /* cost of an add instruction */ +- 1, /* cost of a lea instruction */ +- 1, /* variable shift costs */ +- 1, /* constant shift costs */ +- {4, 4, 4, 4, 4}, /* cost of starting a multiply */ +- 0, /* cost of multiply per each bit set */ +- {17, 17, 17, 17, 17}, /* cost of a divide/mod */ +- 1, /* cost of movsx */ +- 1, /* cost of movzx */ +- 8, /* "large" insn */ +- 6, /* MOVE_RATIO */ +- 2, /* cost for loading QImode using movzbl */ +- {4, 4, 4}, /* cost of loading integer registers +- in QImode, HImode and SImode. +- Relative to reg-reg move (2). */ +- {2, 2, 2}, /* cost of storing integer registers */ +- 2, /* cost of reg,reg fld/fst */ +- {2, 2, 6}, /* cost of loading fp registers +- in SFmode, DFmode and XFmode */ +- {4, 4, 6}, /* cost of loading integer registers */ +- 2, /* cost of moving MMX register */ +- {2, 2}, /* cost of loading MMX registers +- in SImode and DImode */ +- {2, 2}, /* cost of storing MMX registers +- in SImode and DImode */ +- 2, /* cost of moving SSE register */ +- {2, 2, 8}, /* cost of loading SSE registers +- in SImode, DImode and TImode */ +- {2, 2, 8}, /* cost of storing SSE registers +- in SImode, DImode and TImode */ +- 3, /* MMX or SSE register to integer */ +- 32, /* size of prefetch block */ +- 6, /* number of parallel prefetches */ +- 2, /* Branch cost */ +- 3, /* cost of FADD and FSUB insns. */ +- 5, /* cost of FMUL instruction. */ +- 56, /* cost of FDIV instruction. */ +- 2, /* cost of FABS instruction. */ +- 2, /* cost of FCHS instruction. */ +- 56, /* cost of FSQRT instruction. */ +-}; +- +-static const +-struct processor_costs k6_cost = { +- 1, /* cost of an add instruction */ +- 2, /* cost of a lea instruction */ +- 1, /* variable shift costs */ +- 1, /* constant shift costs */ +- {3, 3, 3, 3, 3}, /* cost of starting a multiply */ +- 0, /* cost of multiply per each bit set */ +- {18, 18, 18, 18, 18}, /* cost of a divide/mod */ +- 2, /* cost of movsx */ +- 2, /* cost of movzx */ +- 8, /* "large" ins